D3D9 C++ Terrain wird nicht korrekt gezeichnet
-
EDIT: Problem gelöst, lag am Verwechseln von CUSTOMVERTEX und CUSTOMFVF
Moin,
vor zwei Tagen habe ich angefangen mich in Direct3D einzuarbeiten.
Als Grundlage habe ich diese Tutorials verwendet:
http://directxtutorial.comSeit gestern versuche ich ein Terrain zu rendern, wobei mir diese Seite sehr geholfen hat:
http://www.toymaker.info/Games/html/terrain.htmlAuf dieser Basis habe ich den gleich folgenden Code geschrieben.
Das Problem: Es wird zwar etwas gezeichnet, aber das scheint komplett wirres Zeug zu sein. Ich habe meinen Vertexbuffer und Indexbuffer überprüft und eine Zeichnung angelegt wie alles sein sollte:
http://img3.imagebanana.com/view/i8jc8tf/TerrainMesh.pngDieser *Müll* kommt bei mir heraus beim Ausführen des Programms:
http://img3.imagebanana.com/view/j4hmvqw/crapTerrain.png
(wobei allein schon die Positionierung der Kamera mit den gegebenen Daten keinen Sinn ergibt, siehe Code)Ich teste mit einem kleinem 2 * 2 Terrain für den Anfang ohne Höhenwerte. Also y ist immer 0.0f. Ich habe den Vertex- und Indexbuffer vor dem Kopieren in den VideoRAM überprüft und alles ist korrekt. Ich Vermute das ich beim Kopieren oder Zeichnen etwas falsch mache.
eigenes flexible vertex format und die struct:
#define CUSTOMFVF (D3DFVF_XYZ|D3DFVF_DIFFUSE) struct CUSTOMVERTEX { FLOAT x, y, z; DWORD color; };
Funktionen zum Erstellen des Terrainmesh und Renderfunktion:
bool Cterrain::CreateTerrainMesh(unsigned short numCellsX, unsigned short numCellsZ, float CellSize) { this->cellsx = numCellsX; this->cellsz = numCellsZ; this->cells = cellsx * cellsz; this->verticesx = cellsx + 1; this->verticesz = cellsz + 1; this->vertices = verticesx * verticesz; this->triangles = cellsx * cellsz * 2; this->cellsize = CellSize; this->minboundx = 0.0f; this->maxboundx = cellsx * cellsize; this->minboundz = 0.0f; this->maxboundz = cellsz * cellsize; CUSTOMVERTEX *vertex = new CUSTOMVERTEX[this->vertices]; unsigned short *indices = new unsigned short[this->triangles*3]; // fill temporary vertexbuffer unsigned long count=0; float posx = this->minboundx; float posz = this->minboundz; for (unsigned long z=0; z<this->verticesz; z++) { posx = this->minboundx; for (unsigned long x=0; x<this->verticesx; x++) { vertex[count].x = posx; vertex[count].y = 0.0f; vertex[count].z = posz; vertex[count].color = 0xFFFFFFFF; posx += this->cellsize; count++; } posz += this->cellsize; } // fill temporary indexbuffer count=0; unsigned short vIndex=0; for (unsigned long z=0; z<this->cellsz; z++) { for (unsigned long x=0; x<this->cellsz; x++) { // first triangle indices[count++]=vIndex; indices[count++]=vIndex+this->verticesx; indices[count++]=vIndex+this->verticesx+1; // second triangle indices[count++]=vIndex; indices[count++]=vIndex+this->verticesx+1; indices[count++]=vIndex+1; vIndex++; } vIndex++; } d3ddev->CreateVertexBuffer( this->vertices*sizeof(CUSTOMFVF), D3DUSAGE_WRITEONLY, CUSTOMFVF, D3DPOOL_MANAGED, &vertexbuffer, NULL ); d3ddev->CreateIndexBuffer( this->triangles*3*2,// *3=three vertices per triangle; *2=each index 2 bytes D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexbuffer, NULL); // copy buffers VOID* pVoid=0; vertexbuffer->Lock(0, this->vertices*sizeof(CUSTOMFVF), (void**)&pVoid, 0); // lock the vertex buffer memcpy(pVoid, vertex, sizeof(CUSTOMVERTEX)*this->vertices); // copy the vertices to the locked buffer vertexbuffer->Unlock(); // unlock the vertex buffer pVoid=0; indexbuffer->Lock(0, sizeof(unsigned short)*this->triangles*3, (void**)&pVoid, 0); // lock the indexbuffer memcpy(pVoid, indices, sizeof(unsigned short)*this->triangles*3); // copy indexbuffer indexbuffer->Unlock(); // unlock the indexbuffer delete []vertex; delete []indices; return true; } void Cterrain::RenderTerrain() { d3ddev->SetStreamSource(0,this->vertexbuffer,0,sizeof(CUSTOMFVF)); d3ddev->SetFVF(CUSTOMFVF); d3ddev->SetIndices(this->indexbuffer); if (d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,this->vertices,0,this->triangles) != D3D_OK) { int SETBPHERE=0; // something is wrong, damn... } }
Funktion zum Rendern eines Frames, hier wird RenderTerrain() gecallt:
void render_frame() { d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0); d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3ddev->BeginScene(); // SET UP THE PIPELINE D3DXMATRIX matTranslate; D3DXMatrixTranslation(&matTranslate, 0.0f, 0.0f, 0.0f); d3ddev->SetTransform(D3DTS_WORLD, &matTranslate); D3DXMATRIX matView; D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3 (0.0f, 50.0f,-200.0f), // the camera position &D3DXVECTOR3 (-50.0f, 0.0f,-50.0f), // the look-at position &D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction d3ddev->SetTransform(D3DTS_VIEW, &matView); D3DXMATRIX matProjection; D3DXMatrixPerspectiveFovLH(&matProjection, D3DXToRadian(45), // the horizontal field of view (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio 1.0f, // the near view-plane 1000.0f); // the far view-plane d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection terrain.RenderTerrain(); d3ddev->EndScene(); d3ddev->Present(NULL, NULL, NULL, NULL); // displays the created frame on the screen }