Ok, so here is my progress so far
OgreRecastDebugDraw.h
Code: Select all
#include <DebugDraw.h>
#include <OgreSceneNode.h>
#include <OgreManualObject2.h>
struct oduVertex
{
Ogre::Vector3 pos;
Ogre::ColourValue color;
Ogre::Vector2 uv;
};
class OgreRecastDebugDraw :public duDebugDraw
{
private:
Ogre::SceneManager* m_pScnMgr;
Ogre::SceneNode* m_pNode;
Ogre::ManualObject* m_pManualObject;
duDebugDrawPrimitives m_crtShape;
std::vector<oduVertex> m_lstCrtVertex;
public:
OgreRecastDebugDraw(Ogre::SceneManager* scnMgr);
virtual void depthMask(bool state);
virtual void texture(bool state);
virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f);
virtual void vertex(const float* pos, unsigned int color);
virtual void vertex(const float x, const float y, const float z, unsigned int color);
virtual void vertex(const float* pos, unsigned int color, const float* uv);
virtual void vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v);
virtual void end();
};
OgreRecastDebugDraw.cpp
Code: Select all
#include "OgreRecastDebugDraw.h"
#include <OgreSceneManager.h>
OgreRecastDebugDraw::OgreRecastDebugDraw(Ogre::SceneManager* scnMgr)
{
m_pScnMgr = scnMgr;
m_pNode = m_pScnMgr->getRootSceneNode()->createChildSceneNode();
m_pManualObject = m_pScnMgr->createManualObject();
m_pNode->attachObject(m_pManualObject);
}
void OgreRecastDebugDraw::depthMask(bool state)
{
}
void OgreRecastDebugDraw::texture(bool state)
{
}
void OgreRecastDebugDraw::begin(duDebugDrawPrimitives prim, float size)
{
m_crtShape = prim;
m_lstCrtVertex.clear();
}
void OgreRecastDebugDraw::vertex(const float * pos, unsigned int color)
{
oduVertex crtVertex;
crtVertex.pos.x = pos[0];
crtVertex.pos.y = pos[1];
crtVertex.pos.z = pos[2];
m_lstCrtVertex.push_back(crtVertex);
}
void OgreRecastDebugDraw::vertex(const float x, const float y, const float z, unsigned int color)
{
oduVertex crtVertex;
crtVertex.pos.x = x;
crtVertex.pos.y = y;
crtVertex.pos.z = z;
m_lstCrtVertex.push_back(crtVertex);
}
void OgreRecastDebugDraw::vertex(const float * pos, unsigned int color, const float * uv)
{
vertex(pos, color);
}
void OgreRecastDebugDraw::vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v)
{
vertex(x, y, z, color);
}
void OgreRecastDebugDraw::end()
{
int idx = 0;
int connectIdx = 0;
bool bSuccessSet = false;
switch (m_crtShape)
{
case DU_DRAW_POINTS:
m_pManualObject->begin("Rocks", Ogre::OT_POINT_LIST);
for (int i = 0, n = m_lstCrtVertex.size(); i < n; ++i)
{
idx = i;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
m_pManualObject->index(idx);
bSuccessSet = true;
}
break;
case DU_DRAW_LINES:
m_pManualObject->begin("Rocks", Ogre::OT_LINE_LIST);
if (m_lstCrtVertex.size() % 2 == 0)
{
for (int i = 0, n = m_lstCrtVertex.size(); i < n; i += 2)
{
idx = i;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
++idx;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
connectIdx = i;
m_pManualObject->line(connectIdx++, connectIdx++);
bSuccessSet = true;
}
}
break;
case DU_DRAW_TRIS:
m_pManualObject->begin("Rocks", Ogre::OT_TRIANGLE_LIST);
if (m_lstCrtVertex.size() % 3 == 0)
{
for (int i = 0, n = m_lstCrtVertex.size(); i < n; i += 3)
{
idx = i;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
++idx;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
++idx;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
connectIdx = i;
m_pManualObject->triangle(connectIdx++, connectIdx++, connectIdx++);
bSuccessSet = true;
}
}
break;
case DU_DRAW_QUADS:
m_pManualObject->begin("Rocks", Ogre::OT_TRIANGLE_LIST);
if (m_lstCrtVertex.size() % 4 == 0)
{
for (int i = 0, n = m_lstCrtVertex.size(); i < n; i += 4)
{
idx = i;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
++idx;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
++idx;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
++idx;
m_pManualObject->position(m_lstCrtVertex[idx].pos);
m_pManualObject->colour(m_lstCrtVertex[idx].color);
connectIdx = i;
m_pManualObject->quad(connectIdx++, connectIdx++, connectIdx++, connectIdx++);
bSuccessSet = true;
}
}
break;
default:
break;
}
if (!bSuccessSet)
{
assert(!"Wrong debug shape");
}
m_pManualObject->end();
}
But I didn't see any manual object, maybe I did something wrong
Maybe it's about "DataBlockName"
Edit: Since the Post_Process sample has
"Rocks" datablock
So, Replace "DataBlockName" with "Rocks" should work.
Another thing is the color, I don't understand why it has data type unsigned int while it's an array, so to prevent messed up, just hard-code the color inside the class - ignore the input value, just to be sure.
Edit 2: After taking a close look at Manual Object, I edit the code above to make it work better.
Also I took a test drive
Code: Select all
void EmptyProjectGameState::createScene01(void)
{
mCameraController = new CameraController( mGraphicsSystem, false );
m_pScnMgr = mGraphicsSystem->getSceneManager();
/*Create light*/
m_pLight = m_pScnMgr->createLight();
m_pLightNode = m_pScnMgr->getRootSceneNode()->createChildSceneNode();
m_pLightNode->attachObject(m_pLight);
m_pLight->setPowerScale(Ogre::Math::PI); //Since we don't do HDR, counter the PBS' division by PI
m_pLight->setType(Ogre::Light::LT_DIRECTIONAL);
m_pLight->setDirection(Ogre::Vector3(-1, -1, -1).normalisedCopy());
m_pCam = mGraphicsSystem->getCamera();
/*Create plane*/
float nPlaneCx;
float nPlaneCy;
float nPlaneX;
float nPlaneY;
nPlaneCx = nPlaneCy = 300;
nPlaneX = 0;
nPlaneY = 0;
Ogre::v1::MeshManager::getSingleton().createPlane("MyPlane",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::Plane(Ogre::Vector3::UNIT_Y, 1.0f), nPlaneCx, nPlaneCy,
1, 1, true, 1, 8.1f, 8.12f, Ogre::Vector3::UNIT_Z,
Ogre::v1::HardwareBuffer::HBU_STATIC,
Ogre::v1::HardwareBuffer::HBU_STATIC);
Ogre::v1::MeshPtr v1Mesh;
Ogre::MeshPtr v2Mesh;
v1Mesh = Ogre::v1::MeshManager::getSingleton().load(
"MyPlane", Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME,
Ogre::v1::HardwareBuffer::HBU_STATIC, Ogre::v1::HardwareBuffer::HBU_STATIC);
//Create a v2 mesh to import to, with a different name (arbitrary).
v2Mesh = Ogre::MeshManager::getSingleton().createManual(
"Plane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
v2Mesh->importV1(v1Mesh.get(), true, true, true);
//Free memory
v1Mesh->unload();
Ogre::v1::MeshManager::getSingleton().remove("MyPlane");
m_pItemPlane = m_pScnMgr->createItem(
"Plane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::SCENE_STATIC);
m_pItemPlane->setDatablock("Rocks");
Ogre::HlmsManager *hlmsManager = mGraphicsSystem->getRoot()->getHlmsManager();
Ogre::Hlms *hlms = hlmsManager->getHlms(Ogre::HLMS_PBS);
Ogre::HlmsPbsDatablock *datablock = static_cast<Ogre::HlmsPbsDatablock*>(
hlms->getDatablock("Rocks"));
for (size_t i = Ogre::PBSM_DIFFUSE; i <= Ogre::PBSM_ROUGHNESS; ++i)
{
Ogre::HlmsSamplerblock samplerblock;
samplerblock.mU = Ogre::TAM_WRAP;
samplerblock.mV = Ogre::TAM_WRAP;
datablock->setSamplerblock(static_cast<Ogre::PbsTextureTypes>(i), samplerblock);
}
m_pNodePlane = m_pScnMgr->getRootSceneNode(Ogre::SCENE_STATIC)->
createChildSceneNode(Ogre::SCENE_STATIC);
m_pNodePlane->setPosition(nPlaneX, -3.6, nPlaneY);
m_pNodePlane->attachObject(m_pItemPlane);
//CreateParticle("Examples/ClickFx", Ogre::Vector3::ZERO);
//--------------Recast & Detour
Ogre::Aabb box = m_pItemPlane->getWorldAabbUpdated();
Ogre::Vector3 vMinBound = box.mCenter - box.mHalfSize;
Ogre::Vector3 vMaxBound = box.mHalfSize + box.mCenter;
Ogre::Vector3 vVertex[4];
int vIdx = 0;
vVertex[vIdx].x = -150;
vVertex[vIdx].z = -150;
++vIdx;
vVertex[vIdx].x = 150;
vVertex[vIdx].z = -150;
++vIdx;
vVertex[vIdx].x = 150;
vVertex[vIdx].z = 150;
++vIdx;
vVertex[vIdx].x = -150;
vVertex[vIdx].z = 150;
for (Ogre::Vector3 &v : vVertex)
{
v.y = vMaxBound.y;
}
const int TREE_DIMENSION = 3;
const int TREE_VERTICLE = 3;
const int NUM_VERTEX = 4;
const int NUM_TRI = 2;
float bmin[TREE_DIMENSION];
float bmax[TREE_DIMENSION];
float verts[NUM_VERTEX * TREE_DIMENSION];
OgreVect3ToFloatA(vMinBound, bmin);
OgreVect3ToFloatA(vMaxBound, bmax);
vIdx = 0;
for (int i = 0; i < NUM_VERTEX; ++i)
{
OgreVect3ToFloatA(vVertex[vIdx], &verts[i*TREE_DIMENSION]);
++vIdx;
}
int tris[TREE_VERTICLE * NUM_TRI];
vIdx = 0;
(&tris[TREE_VERTICLE*vIdx])[0] = 0;
(&tris[TREE_VERTICLE*vIdx])[1] = 1;
(&tris[TREE_VERTICLE*vIdx])[2] = 3;
++vIdx;
(&tris[TREE_VERTICLE*vIdx])[0] = 1;
(&tris[TREE_VERTICLE*vIdx])[1] = 2;
(&tris[TREE_VERTICLE*vIdx])[2] = 3;
rcHeightfield m_solid;
rcCompactHeightfield* m_chf;
rcContourSet m_cset;
rcPolyMesh m_pmesh;
rcPolyMeshDetail m_dmesh;
rcContext m_ctx;
int nWidth;
int nHeight;
float cellSize = 1.0f;
float cellHeight = 1.0f;
rcCalcGridSize(bmin, bmax, cellSize, &nWidth, &nHeight);
if (!rcCreateHeightfield(&m_ctx, m_solid, nWidth, nHeight,bmin,bmax,cellSize, cellHeight))
{
assert(!"buildNavigation: Could not create solid heightfield.");
}
unsigned char arrTriArea[NUM_TRI];
float walkableSlopeAngle = 45.0f;
int walkableClimb = 4;
int walkableHeight = 10;
int walkableRadius = 2;
const float REGION_MIN_SIZE = 8.0f;
const float REGION_MERGE_SIZE = 20.0f;
const float EDGE_MAX_LEN = 12.0f;
int minRegionArea = (int)rcSqr(REGION_MIN_SIZE); // Note: area = size*size
int mergeRegionArea = (int)rcSqr(REGION_MERGE_SIZE); // Note: area = size*size
float maxSimplificationError = 1.295f;
float maxEdgeLen = (int)(EDGE_MAX_LEN / cellSize);
int maxVertsPerPoly = 6;
float m_detailSampleDist = 6.0f;
float detailSampleDist = m_detailSampleDist < 0.9f ? 0 : cellSize * m_detailSampleDist;
float m_detailSampleMaxError = 1.0f;
float detailSampleMaxError = cellHeight * m_detailSampleMaxError;
rcMarkWalkableTriangles(&m_ctx, walkableSlopeAngle, verts, NUM_VERTEX, tris, NUM_TRI, arrTriArea);
if (!rcRasterizeTriangles(&m_ctx, verts, NUM_VERTEX, tris, arrTriArea, NUM_TRI, m_solid, walkableClimb))
{
assert(!"buildNavigation: Could not rasterize triangles.");
}
//
// Step 3. Filter walkables surfaces.
//
// Once all geoemtry is rasterized, we do initial pass of filtering to
// remove unwanted overhangs caused by the conservative rasterization
// as well as filter spans where the character cannot possibly stand.
rcFilterLowHangingWalkableObstacles(&m_ctx, walkableClimb, m_solid);
rcFilterLedgeSpans(&m_ctx, walkableHeight, walkableClimb, m_solid);
rcFilterWalkableLowHeightSpans(&m_ctx, walkableHeight, m_solid);
//
// Step 4. Partition walkable surface to simple regions.
//
// Compact the heightfield so that it is faster to handle from now on.
// This will result more cache coherent data as well as the neighbours
// between walkable cells will be calculated.
m_chf = rcAllocCompactHeightfield();
if (!m_chf)
{
assert(!"buildNavigation: Out of memory 'chf'.");
}
if (!rcBuildCompactHeightfield(&m_ctx, walkableHeight, walkableClimb, m_solid, *m_chf))
{
assert(!"buildNavigation: Could not build compact data.");
}
//No need m_solid anymore
// Erode the walkable area by agent radius.
if (!rcErodeWalkableArea(&m_ctx, walkableRadius, *m_chf))
{
assert(!"buildNavigation: Could not erode.");
}
//Watershed partitioning
// Prepare for region partitioning, by calculating distance field along the walkable surface.
if (!rcBuildDistanceField(&m_ctx, *m_chf))
{
assert(!"buildNavigation: Could not build distance field.");
}
// Partition the walkable surface into simple regions without holes.
if (!rcBuildRegions(&m_ctx, *m_chf, 0, minRegionArea, mergeRegionArea))
{
assert(!"buildNavigation: Could not build watershed regions.");
}
//
// Step 5. Trace and simplify region contours.
//
// Create contours.
if (!rcBuildContours(&m_ctx, *m_chf,maxSimplificationError, maxEdgeLen, m_cset))
{
assert(!"buildNavigation: Could not create contours.");
}
//
// Step 6. Build polygons mesh from contours.
//
// Build polygon navmesh from the contours.
if (!rcBuildPolyMesh(&m_ctx, m_cset, maxVertsPerPoly, m_pmesh))
{
assert(!"buildNavigation: Could not triangulate contours.");
}
//
// Step 7. Create detail mesh which allows to access approximate height on each polygon.
//
if (!rcBuildPolyMeshDetail(&m_ctx, m_pmesh, *m_chf, detailSampleDist, detailSampleMaxError, m_dmesh))
{
assert(!"buildNavigation: Could not build detail mesh.");
}
//===============Now let test our Debug drawer===============
OgreRecastDebugDraw oduDebug(m_pScnMgr);
duDebugDrawPolyMesh(&oduDebug, m_pmesh);
TutorialGameState::createScene01();
}