Cannot render the navigation mesh
Hello belfegor, It was a success to render the navmesh nicely.
But one final question,
is how do you add adjacency info into it?
That is to add lines and colors to differentiate between tiles?
Thanks Jack
Update:
I am following LaMothe's book source code that I own.
here is the modification. You should notice that the end point of the first line is connected to the head of the next line
which is quite messy..... Any ideas why?
#ifndef NavDebugMesh_HEADER_DEFINED
#define NavDebugMesh_HEADER_DEFINED
#include <d3dx9.h>
#include "Recast/Recast.h"
#include "../Camera/CCamera.h"
extern LPDIRECT3DDEVICE9 g_pDevice;
extern LPD3DXEFFECT g_pEffect;
extern CCamera g_CurrCam;
struct Line {
D3DXVECTOR3 start;
D3DXVECTOR3 end;
D3DCOLOR color;
};
class NavDebugMesh
{
private:
struct Vertex
{
D3DXVECTOR3 p;
D3DXVECTOR3 c;
};
LPDIRECT3DDEVICE9 m_device;
LPDIRECT3DVERTEXDECLARATION9 m_VDecl;
LPDIRECT3DVERTEXBUFFER9 m_VB;
LPDIRECT3DINDEXBUFFER9 m_IB;
CZenLineList ZenLineList;
//CZenLine ZenLine;
LPD3DXMESH m_dxDebugMesh;
public:
NavDebugMesh(LPDIRECT3DDEVICE9 device, rcPolyMeshDetail* dmesh)
: m_device(device), m_VDecl(nullptr), m_VB(nullptr), m_IB(nullptr)
{
m_device->AddRef();
HRESULT hr = 0;
D3DVERTEXELEMENT9 vertexElements[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
D3DDECL_END()
};
hr = m_device->CreateVertexDeclaration(vertexElements, &m_VDecl);
if (FAILED(hr))
{
MessageBox(0, "CreateVertexDeclaration failed!", 0, 0);
}
hr = m_device->CreateVertexBuffer(sizeof(Vertex) * dmesh->nverts, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_VB, nullptr);
if (FAILED(hr))
{
MessageBox(0, "CreateVertexBuffer failed!", 0, 0);
}
hr = m_device->CreateIndexBuffer(sizeof(DWORD) * dmesh->ntris * 3, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_MANAGED, &m_IB, nullptr);
if (FAILED(hr))
{
MessageBox(0, "CreateIndexBuffer failed!", 0, 0);
}
Vertex* pVert;
m_VB->Lock(0, 0, (void**)&pVert, 0);
const D3DXVECTOR3* verts = (const D3DXVECTOR3*)dmesh->verts;
for (int i = 0; i < dmesh->nverts; ++i)
{
pVert[i].p = verts[i];
pVert[i].c = D3DXVECTOR3(0.78f, 1.0f, 1.0f);
}
m_VB->Unlock();
DWORD* pInd;
m_IB->Lock(0, 0, (void**)&pInd, 0);
int cnt = 0;
int tri_offset = 0;
int old_nverts = 0;
for (int p = 0; p < dmesh->nmeshes; ++p)
{
unsigned int* m = &(dmesh->meshes[p * 4]);
const unsigned short bverts = m[0]; // `b' means "beginning of"!!
const unsigned short nverts = m[1];
const unsigned short btris = m[2];
const unsigned short ntris = m[3];
const unsigned char* tris = &(dmesh->tris[btris * 4]);
tri_offset += old_nverts;
for (int n = 0; n < ntris; ++n)
{
for (int k = 0; k < 3; ++k)
{
int tri = tris[n * 4 + k] + tri_offset;
pInd[cnt] = tri;
cnt++;
}
}
old_nverts = nverts;
}
m_IB->Unlock();
if(FAILED(D3DXCreateMesh(dmesh->ntris, dmesh->nverts, D3DXMESH_MANAGED, vertexElements, g_pDevice, &m_dxDebugMesh)))
{
MessageBox(0, "Failed to create dx mesh!", 0, 0);
return;
}
DWORD numFaces = m_dxDebugMesh->GetNumFaces();
DWORD* meshAdj = new DWORD[numFaces * 3];
hr = m_dxDebugMesh->GenerateAdjacency(0.001f, meshAdj);
if (FAILED(hr))
{
MessageBox(NULL, "Failed to generate adjacency info", "Failed", NULL);
}
// add line lists
//const D3DXVECTOR3 outlineColor(0.0f, 0.0f, 0.0f);
//const D3DXVECTOR3 innerColor(0.85f, 0.85f, 0.85f);
const D3DCOLOR outlineColor = 0xFFFFFF;
const D3DCOLOR innerColor = 0xFFFFFF;
for (DWORD i = 0; i < numFaces; ++i)
{
if (0xFFFFFFFF == meshAdj[i * 3 + 0])
{
Line line;
line.start = pVert[pInd[i * 3 + 0]].p;
line.end = pVert[pInd[i * 3 + 1]].p;
line.color = outlineColor;
ZenLineList.AddPoint(line.start.x,
line.start.y, line.start.z, line.color);
ZenLineList.AddPoint(line.end.x,
line.end.y, line.end.z, line.color);
/* ZenLine.SetProps(line.start.x, line.start.y, line.start.z,
line.color, line.end.x, line.end.y, line.end.z, line.color);*/
}
else
{
Line line;
line.start = pVert[pInd[i * 3 + 0]].p;
line.end = pVert[pInd[i * 3 + 1]].p;
line.color = innerColor;
//lRenderer->addLine(line);
ZenLineList.AddPoint(line.start.x,
line.start.y, line.start.z, line.color);
ZenLineList.AddPoint(line.end.x,
line.end.y, line.end.z, line.color);
/*ZenLine.SetProps(line.start.x, line.start.y, line.start.z,
line.color, line.end.x, line.end.y, line.end.z, line.color);*/
}
if (0xFFFFFFFF == meshAdj[i * 3 + 1])
{
Line line;
line.start = pVert[pInd[i * 3 + 1]].p;
line.end = pVert[pInd[i * 3 + 2]].p;
line.color = outlineColor;
//lRenderer->addLine(line);
ZenLineList.AddPoint(line.start.x,
line.start.y, line.start.z, line.color);
ZenLineList.AddPoint(line.end.x,
line.end.y, line.end.z, line.color);
/*ZenLine.SetProps(line.start.x, line.start.y, line.start.z,
line.color, line.end.x, line.end.y, line.end.z, line.color);*/
}
else
{
Line line;
line.start = pVert[pInd[i * 3 + 1]].p;
line.end = pVert[pInd[i * 3 + 2]].p;
line.color = innerColor;
//lRenderer->addLine(line);
ZenLineList.AddPoint(line.start.x,
line.start.y, line.start.z, line.color);
ZenLineList.AddPoint(line.end.x,
line.end.y, line.end.z, line.color);
/*ZenLine.SetProps(line.start.x, line.start.y, line.start.z,
line.color, line.end.x, line.end.y, line.end.z, line.color);*/
}
if (0xFFFFFFFF == meshAdj[i * 3 + 2])
{
Line line;
line.start = pVert[pInd[i * 3 + 2]].p;
line.end = pVert[pInd[i * 3 + 0]].p;
line.color = outlineColor;
//lRenderer->addLine(line);
ZenLineList.AddPoint(line.start.x,
line.start.y, line.start.z, line.color);
ZenLineList.AddPoint(line.end.x,
line.end.y, line.end.z, line.color);
/*ZenLine.SetProps(line.start.x, line.start.y, line.start.z,
line.color, line.end.x, line.end.y, line.end.z, line.color);*/
}
else
{
Line line;
line.start = pVert[pInd[i * 3 + 2]].p;
line.end = pVert[pInd[i * 3 + 0]].p;
line.color = innerColor;
//lRenderer->addLine(line);
ZenLineList.AddPoint(line.start.x,
line.start.y, line.start.z, line.color);
ZenLineList.AddPoint(line.end.x,
line.end.y, line.end.z, line.color);
/*ZenLine.SetProps(line.start.x, line.start.y, line.start.z,
line.color, line.end.x, line.end.y, line.end.z, line.color);*/
}
}
ZenLineList.m_bConnected = FALSE;
}
~NavDebugMesh()
{
Release();
}
void Release()
{
m_device->Release();
m_VDecl->Release();
m_VB->Release();
m_IB->Release();
}
void Draw()
{
D3DVERTEXBUFFER_DESC vbDesc;
m_VB->GetDesc(&vbDesc);
UINT numVerts = vbDesc.Size / sizeof(Vertex);
D3DINDEXBUFFER_DESC ibDesc;
m_IB->GetDesc(&ibDesc);
UINT numTris = ibDesc.Size / sizeof(DWORD) / 3;
m_device->SetVertexDeclaration(m_VDecl);
m_device->SetStreamSource(0, m_VB, 0, sizeof(Vertex));
m_device->SetIndices(m_IB);
D3DXHANDLE hTech = g_pEffect->GetTechniqueByName("NavMeshDraw");
g_pEffect->SetTechnique(hTech);
// get adjacency info and push it onto the Line List and render away
//ZenLineList.AddPoint(
g_pEffect->Begin(NULL, NULL);
g_pEffect->BeginPass(0);
D3DXMATRIX iden;
D3DXMatrixIdentity(&iden);
g_pEffect->SetMatrix("WorldViewProjection", &(iden * (*g_CurrCam.GetViewMatrix()) * (*g_CurrCam.GetProjMatrix())));
m_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numVerts, 0, numTris);
g_pEffect->EndPass();
g_pEffect->End();
ZenLineList.Render();
}
};
#endif
CZenLineList::CZenLineList()
{
m_pSegmentList = 0;
m_NumPoints = 0;
m_bConnected = TRUE;
}
CZenLineList::~CZenLineList()
{
CPointSegment* pSegment = m_pSegmentList;
CPointSegment* pTempSeg = 0;
while( pSegment )
{
pTempSeg = pSegment->m_pNext;
delete pSegment;
pSegment = pTempSeg;
}
}
// Empties the list of segments
void CZenLineList::ClearPoints()
{
CPointSegment* pSegment = m_pSegmentList;
CPointSegment* pTempSeg = 0;
// While there are segments left, delete them
while( pSegment )
{
pTempSeg = pSegment->m_pNext;
delete pSegment;
pSegment = pTempSeg;
}
// Reset the segment counters
m_pSegmentList = 0;
m_NumPoints = 0;
}
// Adds a point to the segment list
HRESULT CZenLineList::AddPoint( float x, float y, float z, D3DCOLOR PointColor )
{
HRESULT r = 0;
// If the segment list has not been created yet...
if( !m_pSegmentList )
{
//...Create the list and set this point as the
// first entry
m_pSegmentList = new CPointSegment;
m_pSegmentList->m_Vertex.m_Position.x = x;
m_pSegmentList->m_Vertex.m_Position.y = y;
m_pSegmentList->m_Vertex.m_Position.z = z;
m_pSegmentList->m_Vertex.m_DiffuseColor = PointColor;
}
else
{
//...or else just add the point to the end of
// the list
CPointSegment* pSegment = m_pSegmentList;
// Find the last entry in the list
while( pSegment->m_pNext != NULL )
pSegment = pSegment->m_pNext;
// Add this new point to the end of the list
pSegment->m_pNext = new CPointSegment;
pSegment = pSegment->m_pNext;
pSegment->m_Vertex.m_Position.x = x;
pSegment->m_Vertex.m_Position.y = y;
pSegment->m_Vertex.m_Position.z = z;
pSegment->m_Vertex.m_DiffuseColor = PointColor;
}
// Increment the segment counter
m_NumPoints++;
return S_OK;
}
// Renders the line list
HRESULT CZenLineList::Render()
{
HRESULT r = 0;
// Exit if no points are in the list
if( !m_pSegmentList )
return E_FAIL;
// Pointer for the vertex buffer
LPDIRECT3DVERTEXBUFFER9 pVB = 0;
// Create the vertex buffer
r = g_pDevice->CreateVertexBuffer( sizeof( CZenVertex ) * m_NumPoints,
D3DUSAGE_WRITEONLY, ZENVERTEX_TYPE, D3DPOOL_DEFAULT, &pVB, NULL );
if( FAILED( r ) )
return E_FAIL;
// Pointer to the vertex buffer data
BYTE* pData = 0;
// Lock the vertex buffer
r = pVB->Lock( 0, 0, (void**)&pData, 0 );
if( FAILED( r ) )
{
pVB->Release();
return E_FAIL;
}
// Get a pointer to the first segment
CPointSegment* pSegment = m_pSegmentList;
int Offset = 0;
// Loop though the segments and copy them into the vertex buffer
while( pSegment )
{
CopyMemory( pData + Offset, &(pSegment->m_Vertex), sizeof( CZenVertex ) );
pSegment = pSegment->m_pNext;
Offset += sizeof( CZenVertex );
}
// Unlock the vertex buffer
pVB->Unlock();
// Connect the vertex buffer to a rendering source
g_pDevice->SetStreamSource( 1, pVB, 0, sizeof( CZenVertex ) );
// Render the points as a strip or list
if( m_bConnected )
g_pDevice->DrawPrimitive( D3DPT_LINESTRIP, 0, m_NumPoints-1 );
else
g_pDevice->DrawPrimitive( D3DPT_LINELIST, 0, m_NumPoints/2 );
// Release the vertex buffer
pVB->Release();
return S_OK;
}
I come to know that I can implement the DebugDraw interface to draw the outlines of the Navigation Mesh. But How do I convert this code to Direct3D? Sorry, I've been using the high level stuff (D3DX) and didn't understand the low level stuff very well yet.... I am still learning..
Are the any good books to learn about porting between these 2 competing APIs?
#include <math.h>
#include <string.h>
#include <d3dx9.h>
#include "..\include\DebugNavMesh.h"
extern LPDIRECT3DDEVICE9 g_pDevice;
void DebugDrawDX::depthMask(bool state)
{
//glDepthMask(state ? GL_TRUE : GL_FALSE);
}
void DebugDrawDX::texture(bool state)
{
/*if (state)
{
glEnable(GL_TEXTURE_2D);
g_tex.bind();
}
else
{
glDisable(GL_TEXTURE_2D);
}*/
}
void DebugDrawDX::begin(duDebugDrawPrimitives prim, float size)
{
/*
switch (prim)
{
case DU_DRAW_POINTS:
glPointSize(size);
glBegin(GL_POINTS);
break;
case DU_DRAW_LINES:
glLineWidth(size);
glBegin(GL_LINES);
break;
case DU_DRAW_TRIS:
glBegin(GL_TRIANGLES);
break;
case DU_DRAW_QUADS:
glBegin(GL_QUADS);
break;
};*/
}
void DebugDrawDX::vertex(const float* pos, unsigned int color)
{
/*
glColor4ubv((GLubyte*)&color);
glVertex3fv(pos);
*/
}
void DebugDrawDX::vertex(const float x, const float y, const float z, unsigned int color)
{
/*
glColor4ubv((GLubyte*)&color);
glVertex3f(x,y,z);
*/
}
void DebugDrawDX::vertex(const float* pos, unsigned int color, const float* uv)
{
/*
glColor4ubv((GLubyte*)&color);
glTexCoord2fv(uv);
glVertex3fv(pos);
*/
}
void DebugDrawDX::vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v)
{
/*
glColor4ubv((GLubyte*)&color);
glTexCoord2f(u,v);
glVertex3f(x,y,z);
*/
}
void DebugDrawDX::end()
{
/*
glEnd();
glLineWidth(1.0f);
glPointSize(1.0f);
*/
}