C
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.com
Seit gestern versuche ich ein Terrain zu rendern, wobei mir diese Seite sehr geholfen hat:
http://www.toymaker.info/Games/html/terrain.html
Auf 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.png
Dieser *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
}