I'm trying to convert my heightmap generated terrain into a D3DXMesh. This is the currenct code which I use to read the heightmap & load the terrain:
int i, j, k;
m_lpDevice = lpDevice;
LPDIRECT3DSURFACE9 lpSurface = NULL;
D3DXIMAGE_INFO ImgInfo;
D3DXGetImageInfoFromFile(lpHeightmap, &ImgInfo);
m_Width = ImgInfo.Width;
m_Length = ImgInfo.Height;
m_lpDevice->CreateOffscreenPlainSurface(m_Width,
m_Length,
D3DFMT_L8,
D3DPOOL_SCRATCH,
&lpSurface, 0);
D3DXLoadSurfaceFromFile(lpSurface, 0, 0, lpHeightmap, 0, D3DX_DEFAULT, 0, 0);
int SizeVertices = m_Width * m_Length;
int SizeIndices = (m_Width-1)*(m_Length-1)*2*3;
D3DLOCKED_RECT LockedRect;
lpSurface->LockRect(&LockedRect, 0, 0);
BYTE* lpHeights = (BYTE*) LockedRect.pBits;
int nPitch = LockedRect.Pitch;
TERRAIN_VERTEX* Vertices = new TERRAIN_VERTEX[SizeVertices];
// und mit Werten belegen
for(i=0;i<m_Length;i++)
{
// der Farbwert des Pixels bestimmt die Hoehe
for(j=0;j<m_Width;j++)
{
Vertices[i*m_Width+j].x = static_cast<float>(j);
Vertices[i*m_Width+j].y = static_cast<float>(lpHeights[i*nPitch+j])/2;
Vertices[i*m_Width+j].z = static_cast<float>(m_Length - i);
// je hoeher der Vertex, umso heller die Farbe
Vertices[i*m_Width+j].Color = D3DCOLOR_XRGB(lpHeights[i*nPitch+j],
lpHeights[i*nPitch+j],
lpHeights[i*nPitch+j]);
//Vertices[i*m_Width+j].tu1 = static_cast<float>(j) / m_Width;
//Vertices[i*m_Width+j].tv1 = static_cast<float>(i) / m_Length;
Vertices[i*m_Width+j].tu2 = static_cast<float>(j) / m_Width * 32;
Vertices[i*m_Width+j].tv2 = static_cast<float>(i) / m_Length * 32;
}
}
unsigned int* Indices = new unsigned int[SizeIndices];
k = 0;
for(i=0;i<m_Length-1;i++)
{
for(j=0;j<m_Width-1;j++)
{
Indices[k++] = m_Width * (i + 1) + j;
Indices[k++] = m_Width * i + j;
Indices[k++] = m_Width * (i + 1) + j + 1;
Indices[k++] = m_Width * i + j;
Indices[k++] = m_Width * i + j + 1;
Indices[k++] = m_Width * (i + 1) + j + 1;
}
}
DWORD* pVertices;
LPD3DXMESH Mesh;
HRESULT hr = D3DXCreateMeshFVF(SizeIndices/3, SizeVertices, D3DXMESH_32BIT, D3DFVF_TERRAINVERTEX, m_lpDevice, &Mesh);
int nNumFaces = Mesh->GetNumFaces();
DWORD* att = NULL;
Mesh->LockAttributeBuffer(0,&att);
memset((void*)att, 0, sizeof(int)*nNumFaces);
Mesh->UnlockAttributeBuffer();
int l = Mesh->GetNumVertices();
Mesh->LockVertexBuffer(0,(LPVOID*)&pVertices);
memcpy(pVertices, Vertices, sizeof(Vertices)*sizeof(TERRAIN_VERTEX));
Mesh->UnlockVertexBuffer();
DWORD* pIndices;
hr = Mesh->LockIndexBuffer(0, (void**)&pIndices);
//m_IBuffer->Lock(0, SizeIndices * sizeof(unsigned int), &pIndices, 0);
memcpy(pIndices, Indices, sizeof(Indices)*sizeof(unsigned int));
Mesh->UnlockIndexBuffer();
// Speicher freigeben
delete[] Vertices;
delete[] Indices;
LPD3DXBUFFER pBuffer = NULL;
LPD3DXMESH pMeshTemp = NULL;
DWORD *pAdjacency1 = new DWORD[nNumFaces * 3];
DWORD *pAdjacency2 = new DWORD[nNumFaces * 3];
DWORD *pAdjacency3 = new DWORD[nNumFaces * 3];
Mesh->GenerateAdjacency(0.0f, pAdjacency1);
// Zusammenfassen von Vertices. Diese Funktion muss aufgerufen werden
hr = D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION, Mesh, pAdjacency1, &pMeshTemp, pAdjacency2, &pBuffer);
D3DXValidMesh(pMeshTemp, pAdjacency2, &pBuffer);
Mesh->Release();
Mesh = pMeshTemp;
D3DXComputeNormals(Mesh, NULL);
D3DXComputeTangent(Mesh, 0, 0, 0, 0, NULL);
D3DXGeneratePMesh(Mesh, pAdjacency2, NULL, NULL, 300, D3DXMESHSIMP_FACE, &m_lpMesh);
lpSurface->Release();
delete[] pAdjacency1;
delete[] pAdjacency2;
delete[] pAdjacency3;
After a lot of errors with the filling of the vertex and index buffer I managed to at least make it work, but on my call of D3DXCleanMesh() the HR says that the mesh is invalid, so it wont create the PMesh, and I get an error on rendering (because m_lpMesh points to 0xccccccccc).
If I don't use the cleaned pmesh, just the one I created, I get messed up graphics. I can barely see anything because there are so many triangles on the screen with random coordinates, all pointing to the center of the camera, whereever I move it.
Does anyone know whats wrong here? The code worked as long as I filled a seperate vertex/index-buffer. I tried many different ways like a for() loop instead of memcpy but everything failed. Does someone know what I'm doing wrong?
Second question, I want to calculate the normals, tangents and binormals of my mesh. I know this functions:
D3DXComputeNormals(Mesh, NULL);
D3DXComputeTangent(Mesh, 0, 0, 0, 0, NULL);
Does D3DXComputeTangent also calculate binormals or do I need another function (didn't found one so far)? Is my call of D3DXComputeTangent even valid? I looked up msdn but the explanations of what for example parameter 2 and 3 does make no sense to me. What should I do?