I've finished the new batching scheme I described in my previous entry, so see that for more details. Here's the new rendering and geometry code. It's still in an early state, so it's not very clean, and documentation is still pretty obsolete. Take a look and leave any questions/comments.
Thanks!
Renderer.h
#ifndef RENDERER_H#define RENDERER_H#define D3D_DEBUG_INFO#include #include #include #include #include "../Header Files/GeometryBuffer.h"#include "../Header Files/Texture.h"#include "../../Main/Header Files/Entity.h"#include "../../Main/Header Files/Types.h"#include "Camera.h"namespace ISO{ namespace Base { class Event; } namespace Graphics { namespace detail { class TextureFinder { std::string name; public: TextureFinder(std::string str) : name(str) {} bool operator()(ISO::Graphics::Texture *tex) { return tex->GetFileName() == name; } }; } class Renderer : public ISO::Base::BaseEntity { public: Renderer(HWND hWnd); ~Renderer(); void Render(); void InitProjection(float windowWidth, float windowHeight, float zNear, float zFar); void AddTile( const ISO::Base::Event *evt ); void RemoveTile( const ISO::Base::Event *evt ); void EditTile( const ISO::Base::Event *evt ); int AddButton(int texIndex, float bX, float bY, float tX, float tY); void AddTexture(const ISO::Base::Event *evt); virtual bool IsA(ISO::Base::TYPE t) { return t == ISO::Base::RENDERER; } void DrawFrame( const ISO::Base::Event *evt ); void RebuildGeometry( const ISO::Base::Event *evt ); void UpdateButtonTexture(const ISO::Base::Event *evt); LPDIRECT3DDEVICE9 GetDevice() const; private: void BuildMasterGeometry(); Camera m_Cam; LPDIRECT3D9 m_D3D; LPDIRECT3DDEVICE9 m_D3DDevice; D3DXMATRIX m_MatProj; struct DrawInfo { int TextureIndex; //DIP parameters D3DPRIMITIVETYPE Type; int BaseVertexIndex; unsigned MinIndex; unsigned NumVertices; unsigned StartIndex; unsigned PrimitiveCount; DrawInfo(int tex=0, D3DPRIMITIVETYPE type=D3DPT_TRIANGLELIST, int base=0, int min=0, int num=0, int starti=0, int primcnt=0) : TextureIndex(tex), Type(type), BaseVertexIndex(base), MinIndex(min), NumVertices(num), StartIndex(starti), PrimitiveCount(primcnt) {} }; struct TileGeometry { GeometryBuffer *Geometry; int TexIndex; TileGeometry(GeometryBuffer *geom, int tex) : Geometry(geom), TexIndex(tex) {} bool operator<(const TileGeometry& rhs) { return TexIndex < rhs.TexIndex; } }; typedef std::vector< std::pair*, int > >ButtonBuffer; typedef std::vector TileContainer; std::vector m_DrawInfos; TileContainer m_Tiles; GeometryBuffer* m_MasterGeometry; ButtonBuffer m_UIBuffers; std::vector m_TextureBuffer; bool m_NeedToDraw; bool m_RebuildGeometry; }; }}#endif
Renderer.cpp
#define D3D_DEBUG_INFO#include #include #include #include #include "../Header Files/Renderer.h"#include "../Header Files/GeometryBuffer.h"#include "../../Main/Header Files/Event.h"#include "../../UI/Header Files/Button.h"#include "../../Math/Header Files/Vector.h"extern ISO::Base::EventManager *g_Events;#pragma comment(lib, "d3d9.lib")#pragma comment(lib, "d3dx9.lib")LPDIRECT3DTEXTURE9 tex;ISO::Graphics::Renderer::Renderer(HWND hWnd): m_D3D(NULL),m_D3DDevice(NULL),m_NeedToDraw(false),m_MasterGeometry(NULL){ m_D3D = ::Direct3DCreate9(D3D_SDK_VERSION); if (!m_D3D) { return; } D3DPRESENT_PARAMETERS params = {0}; params.Windowed = TRUE; params.SwapEffect = D3DSWAPEFFECT_DISCARD; params.BackBufferFormat = D3DFMT_UNKNOWN; params.EnableAutoDepthStencil = TRUE; params.AutoDepthStencilFormat = D3DFMT_D16; m_D3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶ms, &m_D3DDevice ); if (!m_D3DDevice) { m_D3D->Release(); } D3DXCreateTextureFromFile(m_D3DDevice, "tex1.png", &tex); m_D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); m_D3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); //m_D3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); //m_D3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); g_Events->RegisterEventHandler("draw", this, &Renderer::DrawFrame); g_Events->RegisterEventHandler("rebuildgeometry", this, &Renderer::RebuildGeometry); g_Events->RegisterEventHandler("updatebuttontexture", this, &Renderer::UpdateButtonTexture); g_Events->RegisterEventHandler("addtile", this, &Renderer::AddTile); g_Events->RegisterEventHandler("addtexture", this, &Renderer::AddTexture); g_Events->RegisterEventHandler("rendererremovetile", this, &Renderer::RemoveTile); g_Events->RegisterEventHandler("rendereredittile", this, &Renderer::EditTile);}ISO::Graphics::Renderer::~Renderer(){ for (unsigned i = 0; i < m_Tiles.size(); ++i) { delete m_Tiles.Geometry; } for (unsigned i = 0; i < m_UIBuffers.size(); ++i) { delete m_UIBuffers.first; } for (unsigned i = 0; i < m_TextureBuffer.size(); ++i) { delete m_TextureBuffer; } if (m_D3DDevice) { m_D3DDevice->Release(); m_D3DDevice = NULL; } if (m_D3D) { m_D3D->Release(); m_D3D = NULL; }}void ISO::Graphics::Renderer::Render(){ if( NULL == m_D3DDevice ) { return; } if (!m_MasterGeometry || m_RebuildGeometry) { BuildMasterGeometry(); m_RebuildGeometry = false; } if (m_NeedToDraw) { // Clear the backbuffer to a blue color m_D3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); // Begin the scene if( SUCCEEDED( m_D3DDevice->BeginScene() ) ) { m_D3DDevice->SetTransform(D3DTS_PROJECTION, &m_MatProj); D3DXMATRIX view; D3DXVECTOR3 eye = m_Cam.GetEyeVec(); D3DXVECTOR3 at = m_Cam.GetAtVec(); D3DXVECTOR3 up = m_Cam.GetUpVec(); D3DXMatrixLookAtLH(&view, &eye, &at, &up ); m_D3DDevice->SetTransform(D3DTS_VIEW, &view); m_D3DDevice->SetStreamSource(0, m_MasterGeometry->GetVertexBufferPointer(), 0, sizeof(MapVertex)); m_D3DDevice->SetIndices(m_MasterGeometry->GetIndexBufferPointer()); m_D3DDevice->SetFVF(m_MasterGeometry->GetFVF()); for (std::vector::iterator it = m_DrawInfos.begin(); it != m_DrawInfos.end(); ++it) { m_D3DDevice->SetTexture(0, m_TextureBuffer[it->TextureIndex]->GetTexturePointer()); HRESULT hr = m_D3DDevice->DrawIndexedPrimitive( it->Type, it->BaseVertexIndex, it->MinIndex, it->NumVertices, it->StartIndex, it->PrimitiveCount ); if (FAILED(hr)) { assert(0); } } for (ButtonBuffer::iterator it = m_UIBuffers.begin(); it != m_UIBuffers.end(); ++it) { if (it->second == -1) { continue; } m_D3DDevice->SetTexture(0, m_TextureBuffer[(*it).second]->GetTexturePointer()); m_D3DDevice->SetFVF((*it).first->GetFVF()); m_D3DDevice->SetStreamSource(0, (*it).first->GetVertexBufferPointer(), 0, sizeof(UIVertex)); m_D3DDevice->SetIndices((*it).first->GetIndexBufferPointer()); HRESULT hr = m_D3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, (*it).first->GetNumVertices(), 0, (*it).first->GetNumPrimitives() ); if (FAILED(hr)) { assert(0); } } // End the scene m_D3DDevice->EndScene(); } // Present the backbuffer contents to the display m_D3DDevice->Present( NULL, NULL, NULL, NULL ); m_NeedToDraw = false; }}void ISO::Graphics::Renderer::BuildMasterGeometry(){ TileContainer tiles(m_Tiles.begin(), m_Tiles.end()); std::sort(tiles.begin(), tiles.end()); delete m_MasterGeometry; m_MasterGeometry = new GeometryBuffer(m_D3DDevice, (int)tiles.size() * 8, (int)tiles.size() * 36); m_DrawInfos.clear(); int currTex = tiles[0].TexIndex; DrawInfo info(currTex); for(unsigned i = 0; i < tiles.size(); ++i) { if (tiles.TexIndex == currTex) { info.NumVertices += tiles.Geometry->GetNumVertices(); info.PrimitiveCount += tiles.Geometry->GetNumPrimitives(); } else { currTex = tiles.TexIndex; m_DrawInfos.push_back(info); info = DrawInfo(currTex, D3DPT_TRIANGLELIST, 0, m_MasterGeometry->GetNumVertices(), 0, m_MasterGeometry->GetNumPrimitives() * 3, 0); } m_MasterGeometry->AddGeometryBuffers(tiles.Geometry->GetVertexBufferPointer(), tiles.Geometry->GetNumVertices(), tiles.Geometry->GetIndexBufferPointer(), tiles.Geometry->GetNumPrimitives() * 3); } m_DrawInfos.push_back(info);}void ISO::Graphics::Renderer::InitProjection(float windowWidth, float windowHeight, float zNear, float zFar){ D3DXMatrixOrthoLH( &m_MatProj, windowWidth, windowHeight, zNear, zFar );}void ISO::Graphics::Renderer::AddTile(const ISO::Base::Event *evt){ assert( evt->IsA(ISO::Base::EVT_4) ); ISO::Base::Event4int, int*> *evt4 = (ISO::Base::Event4int, int*> *)evt; ISO::Math::CVector3 b = evt4->param1; ISO::Math::CVector3 t = evt4->param2; MapVertex verts[] = { {b.x, b.y, b.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 0.f, 1.f}, {b.x, t.y, b.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .33f, .66f}, {b.x, t.y, t.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .33f, .33f}, {b.x, b.y, t.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 0.f, 0.f}, {t.x, b.y, t.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 1.f, 0.f}, {t.x, b.y, b.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 1.f, 1.f}, {t.x, t.y, b.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .66f, .66f}, {t.x, t.y, t.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .66f, .33f} }; short indices[] = { 0, 1, 2, 0, 2, 3, 3, 2, 7, 3, 7, 4, 4, 7, 6, 4, 6, 5, 5, 6, 1, 5, 1, 0, 6, 7, 2, 6, 2, 1, 4, 5, 0, 4, 0, 3 }; GeometryBuffer *buffer = new GeometryBuffer(m_D3DDevice, 8, 36); buffer->AddGeometry(verts, 8, indices, 36); m_Tiles.push_back(TileGeometry(buffer, evt4->param3)); *evt4->param4 = (int)m_Tiles.size() - 1;}void ISO::Graphics::Renderer::RemoveTile( const ISO::Base::Event *evt ){ assert( evt->IsA(ISO::Base::EVT_1) ); ISO::Base::Event1<int> *evt1 = (ISO::Base::Event1<int> *)evt; delete m_Tiles[evt1->param1].Geometry; m_Tiles.erase(m_Tiles.begin() + evt1->param1); //update positions of remaining tiles g_Events->MakeEventNow("updatetilebufferposition", new ISO::Base::Event1<int>(evt1->param1));}void ISO::Graphics::Renderer::EditTile( const ISO::Base::Event *evt ){ assert( evt->IsA(ISO::Base::EVT_4) ); ISO::Base::Event4int, int> *evt4 = (ISO::Base::Event4int, int> *)evt; ISO::Math::CVector3 b = evt4->param1; ISO::Math::CVector3 t = evt4->param2; MapVertex verts[] = { {b.x, b.y, b.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 0.f, 1.f}, {b.x, t.y, b.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .33f, .66f}, {b.x, t.y, t.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .33f, .33f}, {b.x, b.y, t.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 0.f, 0.f}, {t.x, b.y, t.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 1.f, 0.f}, {t.x, b.y, b.z, 0.f, 0.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), 1.f, 1.f}, {t.x, t.y, b.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .66f, .66f}, {t.x, t.y, t.z, 0.f, 1.f, 0.f, D3DCOLOR_XRGB(255, 255, 255), .66f, .33f} }; m_Tiles[evt4->param3].Geometry->EditGeometry(0, verts, 8); m_Tiles[evt4->param3].TexIndex = evt4->param4;}int ISO::Graphics::Renderer::AddButton(int texIndex, float bX, float bY, float tX, float tY){ UIVertex verts[] = { {bX, bY, 0.5f, 1.f, D3DCOLOR_XRGB(255, 255, 255), 0.f, 0.f}, {bX, tY, 0.5f, 1.f, D3DCOLOR_XRGB(255, 255, 255), 0.f, 1.f}, {tX, tY, 0.5f, 1.f, D3DCOLOR_XRGB(255, 255, 255), 1.f, 1.f}, {tX, bY, 0.5f, 1.f, D3DCOLOR_XRGB(255, 255, 255), 1.f, 0.f} }; short indices[] = { 0, 1, 2, 0, 2, 3 }; GeometryBuffer *buffer = new GeometryBuffer(m_D3DDevice, 4, 6); buffer->AddGeometry(verts, 4, indices, 6); m_UIBuffers.push_back(ButtonBuffer::value_type(buffer, texIndex)); return (int)m_UIBuffers.size() - 1;}void ISO::Graphics::Renderer::AddTexture(const ISO::Base::Event *evt){ assert(evt->IsA(ISO::Base::EVT_2)); ISO::Base::Event2int*> *evt2 = (ISO::Base::Event2int*> *)evt; std::vector::iterator it = std::find_if(m_TextureBuffer.begin(), m_TextureBuffer.end(), detail::TextureFinder(evt2->param1)); if (it != m_TextureBuffer.end()) { //ugly hack to get index of current iterator std::vector::iterator first = m_TextureBuffer.begin(); int ret = static_cast<int>(it._Myptr - first._Myptr); *evt2->param2 = ret; return; } m_TextureBuffer.push_back(new Texture(m_D3DDevice, evt2->param1)); int ret = static_cast<int>(m_TextureBuffer.size() - 1); *evt2->param2 = ret;}void ISO::Graphics::Renderer::DrawFrame(const ISO::Base::Event* /*evt*/){ m_NeedToDraw = true;}void ISO::Graphics::Renderer::RebuildGeometry( const ISO::Base::Event* /*evt*/ ){ m_RebuildGeometry = true;}void ISO::Graphics::Renderer::UpdateButtonTexture(const ISO::Base::Event *evt){ assert( evt->IsA(ISO::Base::EVT_2) ); ISO::Base::Event2<int, int> *evt2 = (ISO::Base::Event2<int, int> *)evt; m_UIBuffers[evt2->param1].second = evt2->param2;}LPDIRECT3DDEVICE9 ISO::Graphics::Renderer::GetDevice() const{ return m_D3DDevice;}
GeometryBuffer.h
#ifndef GEOMETRYBUFFER_H#define GEOMETRYBUFFER_H#include "VertexBuffer.h"#include "IndexBuffer.h"namespace ISO{ namespace Graphics { template <class T> class GeometryBuffer { public: GeometryBuffer(LPDIRECT3DDEVICE9 device, int numVerts, int numIndices) : m_VertexBuffer(device, numVerts), m_IndexBuffer(device, numIndices), m_NumPrimitives(0), m_FVF(T::FVF) { } ~GeometryBuffer() { } int AddGeometry(T *verts, int numVerts, short *indices, int numIndices) { short i = static_cast<short>(m_VertexBuffer.AddVertices(verts, numVerts)); for (int index = 0; index < numIndices; ++index) { indices[index] = i + indices[index]; } m_IndexBuffer.AddIndices(indices, numIndices); m_NumPrimitives += numIndices / 3; return i; } int AddGeometryBuffers(LPDIRECT3DVERTEXBUFFER9 verts, int numVerts, LPDIRECT3DINDEXBUFFER9 indices, int numIndices) { short i = static_cast<short>(m_VertexBuffer.AddVertices(verts, numVerts)); short *buffer; indices->Lock(0, numIndices * sizeof(short), (void**)&buffer, D3DLOCK_NOOVERWRITE); for (int index = 0; index < numIndices; ++index) { buffer[index] = i + buffer[index]; } indices->Unlock(); m_IndexBuffer.AddIndices(indices, numIndices); m_NumPrimitives += numIndices / 3; return i; } int RemoveGeometry(int vertIndex, int numVerts, int indiceIndex, int numIndices) { m_VertexBuffer.RemoveVertices(vertIndex, numVerts); m_IndexBuffer.RemoveIndices(indiceIndex, numIndices); m_NumPrimitives -= numIndices / 3; return 0; } int EditGeometry(int vertIndex, T *verts, int numVerts) { return m_VertexBuffer.EditVertices(vertIndex, verts, numVerts); } LPDIRECT3DVERTEXBUFFER9 GetVertexBufferPointer() { return m_VertexBuffer.GetVertexBufferPointer(); } LPDIRECT3DINDEXBUFFER9 GetIndexBufferPointer() { return m_IndexBuffer.GetIndexBufferPointer(); } int GetNumPrimitives() const { return m_NumPrimitives; } int GetNumVertices() { return m_VertexBuffer.GetCurrentIndex(); } DWORD GetFVF() const { return m_FVF; } private: VertexBuffer m_VertexBuffer; IndexBuffer m_IndexBuffer; DWORD m_FVF; int m_NumPrimitives; }; }}#endif
VertexBuffer.h
#ifndef VERTEXBUFFER_H#define VERTEXBUFFER_H#include <cassert>#include <algorithm>#include <d3d9.h>namespace ISO{ namespace Graphics { struct MapVertex { float x, y, z; //position float Nx, Ny, Nz; //normal D3DCOLOR color; //diffuse color float u, v; //tex coords static const DWORD FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1; }; struct UIVertex { float x, y, z, w; D3DCOLOR color; //diffuse color float u, v; static const DWORD FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1; }; template <class T> class VertexBuffer { public: VertexBuffer(LPDIRECT3DDEVICE9 device, int size) : m_VertexBuffer(NULL), m_Index(0) { assert(size > 0); HRESULT hr = device->CreateVertexBuffer( size * sizeof(T), D3DUSAGE_WRITEONLY, T::FVF, D3DPOOL_DEFAULT, &m_VertexBuffer, NULL ); if (FAILED(hr)) { return; } } ~VertexBuffer() { if (m_VertexBuffer) { m_VertexBuffer->Release(); } } int AddVertices(T *verts, int numVerts) { assert(m_VertexBuffer); T *buffer; HRESULT hr = m_VertexBuffer->Lock(m_Index * sizeof(T), numVerts * sizeof(T), (void**)&buffer, 0); if (FAILED(hr)) { return -1; } std::copy(verts, verts + numVerts, buffer); hr = m_VertexBuffer->Unlock(); if (FAILED(hr)) { return -1; } int retVal = m_Index; m_Index += numVerts; return retVal; } int AddVertices(LPDIRECT3DVERTEXBUFFER9 verts, int numVerts) { assert(m_VertexBuffer); T *buffer; HRESULT hr = m_VertexBuffer->Lock(m_Index * sizeof(T), numVerts * sizeof(T), (void**)&buffer, 0); if (FAILED(hr)) { return -1; } T *newVerts; hr = verts->Lock(0, numVerts * sizeof(T), (void**)&newVerts, 0); if (FAILED(hr)) { return -1; } std::copy(newVerts, newVerts + numVerts, buffer); hr = verts->Unlock(); if (FAILED(hr)) { return -1; } hr = m_VertexBuffer->Unlock(); if (FAILED(hr)) { return -1; } int retVal = m_Index; m_Index += numVerts; return retVal; } int RemoveVertices(int index, int numVerts) { assert (m_VertexBuffer); T* buffer; HRESULT hr = m_VertexBuffer->Lock(index * sizeof(T), (m_Index - index) * sizeof(T), (void**)&buffer, 0); std::copy(buffer + numVerts, buffer + (m_Index - index), buffer); hr = m_VertexBuffer->Unlock(); m_Index -= numVerts; return m_Index; } int EditVertices(int index, T* verts, int numVerts) { assert (m_VertexBuffer); T* buffer; HRESULT hr = m_VertexBuffer->Lock(index * sizeof(T), numVerts * sizeof(T), (void**)&buffer, 0); std::copy(verts, verts + numVerts, buffer); hr = m_VertexBuffer->Unlock(); return index; } LPDIRECT3DVERTEXBUFFER9 GetVertexBufferPointer() { assert(m_VertexBuffer); return m_VertexBuffer; } const int GetCurrentIndex() { return m_Index; } private: LPDIRECT3DVERTEXBUFFER9 m_VertexBuffer; int m_Index; }; }}#endif
IndexBuffer.h
#ifndef INDEXBUFFER_H#define INDEXBUFFER_H#include namespace ISO{ namespace Graphics { class IndexBuffer { public: IndexBuffer(LPDIRECT3DDEVICE9 device, int size); ~IndexBuffer(); int AddIndices(short *indices, int numIndices); int AddIndices(LPDIRECT3DINDEXBUFFER9 indices, int numIndices); int RemoveIndices(int index, int numIndices); LPDIRECT3DINDEXBUFFER9 GetIndexBufferPointer() const; private: LPDIRECT3DINDEXBUFFER9 m_IndexBuffer; int m_CurrentIndex; }; }}#endif
IndexBuffer.cpp
#include #include #include "../Header Files/IndexBuffer.h"ISO::Graphics::IndexBuffer::IndexBuffer(LPDIRECT3DDEVICE9 device, int size): m_IndexBuffer(NULL),m_CurrentIndex(0){ assert(size > 0); HRESULT hr = device->CreateIndexBuffer( size * sizeof(short), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_IndexBuffer, NULL ); if (FAILED(hr)) { return; }}ISO::Graphics::IndexBuffer::~IndexBuffer(){ if (m_IndexBuffer) { m_IndexBuffer->Release(); }}int ISO::Graphics::IndexBuffer::AddIndices(short *indices, int numIndices){ assert(m_IndexBuffer); short *Indices; HRESULT hr = m_IndexBuffer->Lock(m_CurrentIndex * sizeof(short), numIndices * sizeof(short), (void**)&Indices, D3DLOCK_NOOVERWRITE); if (FAILED(hr)) { return -1; } std::copy(indices, indices + numIndices, Indices); hr = m_IndexBuffer->Unlock(); if (FAILED(hr)) { return -1; } m_CurrentIndex += numIndices; return 0;}int ISO::Graphics::IndexBuffer::AddIndices(LPDIRECT3DINDEXBUFFER9 indices, int numIndices){ assert(m_IndexBuffer); short *Indices; HRESULT hr = m_IndexBuffer->Lock(m_CurrentIndex * sizeof(short), numIndices * sizeof(short), (void**)&Indices, D3DLOCK_NOOVERWRITE); if (FAILED(hr)) { return -1; } short *newIndices; hr = indices->Lock(0, numIndices * sizeof(short), (void**)&newIndices, D3DLOCK_NOOVERWRITE); if (FAILED(hr)) { return -1; } std::copy(newIndices, newIndices + numIndices, Indices); hr = indices->Unlock(); if (FAILED(hr)) { return -1; } hr = m_IndexBuffer->Unlock(); if (FAILED(hr)) { return -1; } m_CurrentIndex += numIndices; return 0;}int ISO::Graphics::IndexBuffer::RemoveIndices(int /*index*/, int numIndices){ assert (m_IndexBuffer); m_CurrentIndex -= numIndices; return m_CurrentIndex;}LPDIRECT3DINDEXBUFFER9 ISO::Graphics::IndexBuffer::GetIndexBufferPointer() const{ assert(m_IndexBuffer); return m_IndexBuffer;}