OgreCrowd: a crowd component for Ogre using Recast/Detour
-
- Minaton
- Posts: 921
- Joined: Sat Jul 31, 2010 6:29 pm
- Location: Belgium
- x 80
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Good catch!
That code has indeed a tendency to go out of scope. Strange how gcc seems to be very forgiving for these types of mistakes. Maybe it notices stack allocation is not wishful for such a large object and heap allocates it instead.
I committed your fix.
That code has indeed a tendency to go out of scope. Strange how gcc seems to be very forgiving for these types of mistakes. Maybe it notices stack allocation is not wishful for such a large object and heap allocates it instead.
I committed your fix.
Developer @ MakeHuman.org
-
- Kobold
- Posts: 31
- Joined: Wed Feb 08, 2012 1:00 pm
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Hi.First i want to say thnx for sharing your works Mikko Mononen and duststorm.
I've just implement save and load Tilecache functions to my game and i want to share with you.NavMesh save load functions are just copy paste from recast Sample_TileMesh demo.
OgreDetourTileCache.h
OgreDetourTileCache.cpp
usage for save;
for load;
I've just implement save and load Tilecache functions to my game and i want to share with you.NavMesh save load functions are just copy paste from recast Sample_TileMesh demo.
OgreDetourTileCache.h
Code: Select all
void buildTilesLive(InputGeom *inputGeom,const Ogre::AxisAlignedBox *areaToUpdate = NULL);
void saveAllCache(const char* path, const dtTileCache* mesh);
dtTileCache* loadAllCache(const char* path);
dtTileCache *getTileCache(){return m_tileCache;};
Code: Select all
struct TileCacheSetHeader
{
int magic;
int version;
int numTiles;
dtTileCacheParams params;
};
Code: Select all
struct TileCacheHeader
{
dtTileRef tileRef;
int dataSize;
};
Code: Select all
void OgreDetourTileCache::buildTilesLive(InputGeom *inputGeom, const Ogre::AxisAlignedBox *areaToUpdate)
{
// Use bounding box from inputgeom if no area was explicitly specified
Ogre::AxisAlignedBox updateArea;
if(!areaToUpdate)
updateArea = inputGeom->getBoundingBox();
else
updateArea = *areaToUpdate;
// Reduce bounding area a little with one cell in size, to be sure that if it was already tile-aligned, we don't select an extra tile
updateArea.setMinimum( updateArea.getMinimum() + Ogre::Vector3(m_cellSize, 0, m_cellSize) );
updateArea.setMaximum( updateArea.getMaximum() - Ogre::Vector3(m_cellSize, 0, m_cellSize) );
// Select tiles to build or rebuild (builds a tile-aligned BB)
TileSelection selection = getTileSelection(updateArea);
// Debug drawing of bounding area that is updated
// Remove previous debug drawn bounding box of rebuilt area
if(mDebugRebuiltBB) {
mDebugRebuiltBB->detachFromParent();
m_recast->mSceneMgrz->destroyManualObject(mDebugRebuiltBB);
mDebugRebuiltBB = NULL;
}
if(DEBUG_DRAW_REBUILT_BB)
mDebugRebuiltBB = InputGeom::drawBoundingBox(selection.bounds,mSceneMgr);
// Build tiles
for (int ty = selection.minTy; ty <= selection.maxTy; ty++) {
for (int tx = selection.minTx; tx <= selection.maxTx; tx++) {
m_tileCache->buildNavMeshTilesAt(tx,ty,m_navMesh);
}
}
}
Code: Select all
void OgreDetourTileCache::saveAllCache(const char* path, const dtTileCache* mesh)
{
if (!mesh) return;
FILE* fp = fopen(path, "wb");
if (!fp)
return;
// Store header.
TileCacheSetHeader header;
header.magic = NAVMESHSET_MAGIC;
header.version = NAVMESHSET_VERSION;
header.numTiles = 0;
for (int i = 0; i < mesh->getTileCount(); ++i)
{
const dtCompressedTile* tile = mesh->getTile(i);
if (!tile || !tile->header || !tile->dataSize) continue;
header.numTiles++;
}
memcpy(&header.params, mesh->getParams(), sizeof(dtTileCacheParams));
fwrite(&header, sizeof(TileCacheSetHeader), 1, fp);
// Store tiles.
for (int i = 0; i < mesh->getTileCount(); ++i)
{
const dtCompressedTile* tile = mesh->getTile(i);
if (!tile || !tile->header || !tile->dataSize) continue;
TileCacheHeader tileHeader;
tileHeader.tileRef = mesh->getTileRef(tile);
tileHeader.dataSize = tile->dataSize;
fwrite(&tileHeader, sizeof(tileHeader), 1, fp);
fwrite(tile->data, tile->dataSize, 1, fp);
}
fclose(fp);
}
Code: Select all
dtTileCache* OgreDetourTileCache::loadAllCache(const char* path)
{
FILE* fp = fopen(path, "rb");
if (!fp) return 0;
// Read header.
TileCacheSetHeader header;
fread(&header, sizeof(TileCacheSetHeader), 1, fp);
if (header.magic != NAVMESHSET_MAGIC)
{
fclose(fp);
return 0;
}
if (header.version != NAVMESHSET_VERSION)
{
fclose(fp);
return 0;
}
m_tileCache = dtAllocTileCache();
if (!m_tileCache)
{
fclose(fp);
return 0;
}
dtStatus status = m_tileCache->init(&header.params, m_talloc, m_tcomp, m_tmproc);
if (dtStatusFailed(status))
{
fclose(fp);
return 0;
}
// Read tiles.
for (int i = 0; i < header.numTiles; ++i)
{
TileCacheHeader tileHeader;
fread(&tileHeader, sizeof(tileHeader), 1, fp);
if (!tileHeader.tileRef || !tileHeader.dataSize)
break;
unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM);
if (!data) break;
memset(data, 0, tileHeader.dataSize);
fread(data, tileHeader.dataSize, 1, fp);
m_tileCache->addTile(data, tileHeader.dataSize, DT_COMPRESSEDTILE_FREE_DATA, 0);
}
fclose(fp);
return m_tileCache;
}
Code: Select all
/InputGeom */mGeom = new InputGeom(mTerrainGroup,entities);
mDetourTileCache->TileCacheBuild(mGeom);
mDetourTileCache->saveAll("./NavMeshCache/NavmeshTile.bin",m_navMesh);
mDetourTileCache->saveAllCache("./NavMeshCache/NavmeshTileCache.bin",mDetourTileCache->getTileCache());
Code: Select all
/InputGeom */mGeom = new InputGeom(mTerrainGroup,entities);
mDetourTileCache->configure(mGeom);
m_navMesh = mDetourTileCache->loadAll("./NavMeshCache/NavmeshTile.bin");
m_navQuery->init(m_navMesh, 2048);
mDetourTileCache->loadAllCache("./NavMeshCache/NavmeshTileCache.bin");
//and every frame.
areaToLoad.setMinimum(Ogre::Vector3(CameraPos.x-25,bmin[1],CameraPos.z-25));
areaToLoad.setMaximum(Ogre::Vector3(CameraPos.x+25,bmax[1],CameraPos.z+25));
mDetourTileCache->buildTilesLive(mGeom, &areaToLoad);
Last edited by cbibejs on Wed Oct 03, 2012 3:27 pm, edited 1 time in total.
-
- Minaton
- Posts: 921
- Joined: Sat Jul 31, 2010 6:29 pm
- Location: Belgium
- x 80
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Thanks for sharing your solution.
I actually added functions for loading and saving all tiles a few days ago, check the bitbucket repo, the github one is a bit out of date (changed dev machine, git is not setup yet).
Bitbucket repo is the main one and will be most up to date.
Loading and unloading individual tiles is still todo, though.
Edit: I made an effort and github repo is back in sync
I actually added functions for loading and saving all tiles a few days ago, check the bitbucket repo, the github one is a bit out of date (changed dev machine, git is not setup yet).
Bitbucket repo is the main one and will be most up to date.
Loading and unloading individual tiles is still todo, though.
Edit: I made an effort and github repo is back in sync
Last edited by duststorm on Wed Oct 03, 2012 3:31 pm, edited 1 time in total.
Developer @ MakeHuman.org
-
- Kobold
- Posts: 31
- Joined: Wed Feb 08, 2012 1:00 pm
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Oh i was looking the github all the time.I was a bit slow:(.Anyway thnx for your time.
-
- Troll
- Posts: 1394
- Joined: Wed Aug 02, 2006 9:41 am
- Location: Bucharest
- x 94
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
I integrated OgreRecast into my project and I though that RecastInputGeometry needed some performance/readability improvements. What I did is to store vertices/indices/normals in std::vector and pass the underlying array further to recast. This also eliminates nverts and ntris, they are now relative to array sizes, and also a lot of dynamic allocation of arrays and some loops that where used to transform vertices to world (recast?) space and to move the vertices from some buffer to another. I think it is also possible to reuse InputGeometry object, to take advantage of the already allocated vectors and get rid of future allocation/reallocations.
This is not usable directly as I only update one constructor, the others can be updated in a similar fashion. Also some code reuse could be nice, as they are mostly copy pasted. It also uses my own GameEntity class, but can be easily modified (pass Ogre entities instead of GameEntities, for example). Also I only use one terrain, as I expect each navmesh to be included in a single terrain. Anyway, I though I'd share it with the interested parties.
RecastInputGeometry.cpp changes:
RecastInputGeometry.h changes:
This is not usable directly as I only update one constructor, the others can be updated in a similar fashion. Also some code reuse could be nice, as they are mostly copy pasted. It also uses my own GameEntity class, but can be easily modified (pass Ogre entities instead of GameEntities, for example). Also I only use one terrain, as I expect each navmesh to be included in a single terrain. Anyway, I though I'd share it with the interested parties.
RecastInputGeometry.cpp changes:
Code: Select all
void InputGeom::addMeshToVertexIndexArray(const Ogre::MeshPtr mesh, Ogre::Matrix4 transform)
{
// this is the offset for all indexes of this mesh
size_t mesh_offset = getVertCount();
bool added_shared = false;
size_t current_offset = mesh_offset;
size_t shared_offset = mesh_offset;
size_t next_offset = mesh_offset;
added_shared = false;
// Run through the submeshes again, adding the data into the arrays
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
Ogre::SubMesh* submesh = mesh->getSubMesh(i);
Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared))
{
if(submesh->useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}
const Ogre::VertexElement* posElem =
vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
Ogre::HardwareVertexBufferSharedPtr vbuf =
vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
unsigned char* vertex =
static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
// as second argument. So make it float, to avoid trouble when Ogre::Real will
// be comiled/typedefed as double:
//Ogre::Real* pReal;
float* pReal;
for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
{
posElem->baseVertexPointerToElement(vertex, &pReal);
Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
pt = transform * pt;
mVertices.push_back(pt.x);
mVertices.push_back(pt.y);
mVertices.push_back(pt.z);
}
vbuf->unlock();
}
Ogre::IndexData* index_data = submesh->indexData;
size_t numTris = index_data->indexCount / 3;
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
if ( use32bitindexes )
{
for ( size_t k = 0; k < numTris*3; ++k)
{
mIndices.push_back(pLong[k] + static_cast<unsigned long>(offset));
}
}
else
{
for ( size_t k = 0; k < numTris*3; ++k)
{
mIndices.push_back(static_cast<unsigned long>(pShort[k]) +
static_cast<unsigned long>(offset));
}
}
ibuf->unlock();
current_offset = next_offset;
}
};
InputGeom::InputGeom(const Ogre::AxisAlignedBox &tileBounds, Ogre::Terrain *trn, std::vector<GameEntity*> &entities)
: bmin(0),
bmax(0),
m_offMeshConCount(0),
m_volumeCount(0),
m_chunkyMesh(0)
{
// PARTS OF THE FOLLOWING CODE WERE TAKEN AND MODIFIED FROM AN OGRE3D FORUM POST
// Set the area where the navigation mesh will be build to the tileBounds parameter.
bmin = new float[3];
bmax = new float[3];
OgreRecast::OgreVect3ToFloatA(tileBounds.getMinimum(), bmin);
OgreRecast::OgreVect3ToFloatA(tileBounds.getMaximum(), bmax);
//---------------------------------------------------------------------------------
// TERRAIN DATA BUILDING
size_t trnCount = 0;
// get height data, world size, map size
float *mapptr = trn->getHeightData();
float WorldSize = trn->getWorldSize();
int MapSize = trn->getSize();
// calculate where we need to move/place our vertices
float DeltaPos = (WorldSize / 2.0f);
// Determine world offset position for this terrain tile
Ogre::AxisAlignedBox tileBox = trn->getWorldAABB();
float DeltaX = tileBox.getMinimum().x;
float DeltaZ = tileBox.getMaximum().z;
float Scale = WorldSize / (float)(MapSize - 1);
// build vertices
mVertices.reserve(MapSize*MapSize*3);
int max = MapSize; // i think i needed this for something before but now it's obviously redundant
int z = 0;
for(int x = 0;; ++x)
{
// if we've reached the right edge, start over on the next line
if(x == max)
{
x = 0;
++z;
}
// if we reached the bottom/end, we're done
if(z == max)
break;
// add the vertex to the buffer
mVertices.push_back((Scale * x) + DeltaX);
mVertices.push_back(mapptr[(MapSize * z) + x]);
mVertices.push_back((Scale * -z) + DeltaZ);
}
// build indices
size_t size = ((MapSize*MapSize)-(MapSize*2)) * 6;
mIndices.reserve(size);
for(int x = 0;;++x)
{
// skip rightmost vertices
if((x+1)%MapSize == 0)
{
++x;
}
// make a square of 2 triangles
mIndices.push_back(x);
mIndices.push_back(x + 1);
mIndices.push_back(x + MapSize);
mIndices.push_back(x + 1);
mIndices.push_back(x + 1 + MapSize);
mIndices.push_back(x + MapSize);
// if we just did the final square, we're done
if(x+1+MapSize == (MapSize*MapSize)-1)
break;
}
//-----------------------------------------------------------------------------------------
// ENTITY DATA BUILDING
for(int i = 0; i < entities.size(); i++)
{
Ogre::Matrix4 transform;
transform.makeTransform(entities[i]->getPosition(),Ogre::Vector3::UNIT_SCALE,entities[i]->getOrientation());
Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().getByName (entities[i]->getClass()->getMeshName()+".mesh",ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
addMeshToVertexIndexArray(mesh,transform);
}
//---------------------------------------------------------------------------------------------
// RECAST **ONLY** NORMAL CALCS ( These are not used anywhere other than internally by recast)
mNormals.resize(mIndices.size());
for (int i = 0; i < mIndices.size(); i += 3)
{
const float* v0 = &mVertices[mIndices[i]];
const float* v1 = &mVertices[mIndices[i+1]];
const float* v2 = &mVertices[mIndices[i+2]];
float e0[3], e1[3];
for (int j = 0; j < 3; ++j)
{
e0[j] = (v1[j] - v0[j]);
e1[j] = (v2[j] - v0[j]);
}
float* n = &mNormals[i];
n[0] = ((e0[1]*e1[2]) - (e0[2]*e1[1]));
n[1] = ((e0[2]*e1[0]) - (e0[0]*e1[2]));
n[2] = ((e0[0]*e1[1]) - (e0[1]*e1[0]));
float d = sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
if (d > 0)
{
d = 1.0f/d;
n[0] *= d;
n[1] *= d;
n[2] *= d;
}
}
// Build chunky tri mesh from triangles, used for tiled navmesh construction
buildChunkyTriMesh();
}
int InputGeom::getVertCount()
{
return mVertices.size()/3;
}
int InputGeom::getTriCount()
{
return mIndices.size()/3;
}
int* InputGeom::getTris()
{
return &mIndices[0];
}
float* InputGeom::getVerts()
{
return &mVertices[0];
}
bool InputGeom::isEmpty()
{
return getTriCount() <= 0 || getVertCount() <= 0;
}
Code: Select all
/**
* Recast input vertices
**/
std::vector<float> mVertices;
/**
* Recast input tris
* Tris are index references to verts array
**/
std::vector<int> mIndices;
/**
* Normals calculated for verts
* Normals are not entirely accurate but good enough for recast use.
* Size of the normals array is 3*nverts
**/
std::vector<float> mNormals;
-
- Gremlin
- Posts: 156
- Joined: Tue Sep 18, 2012 3:43 am
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
It just can't get the source code to compile
src/OgrerecastApplication.h has a question mark on the project pane showing that the .h file is not found
I have put the source code in the OGRE folder where the system environment variable is pointing to.
Any help please?
Thanks
Jack
src/OgrerecastApplication.h has a question mark on the project pane showing that the .h file is not found
I have put the source code in the OGRE folder where the system environment variable is pointing to.
Any help please?
Thanks
Jack
-
- OGRE Retired Team Member
- Posts: 972
- Joined: Mon Jun 02, 2008 6:52 pm
- Location: Berlin
- x 65
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Uhm... IDE? Compiler line? Anything that would help us help you?
-
- Gremlin
- Posts: 156
- Joined: Tue Sep 18, 2012 3:43 am
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Sorry, I am using VS2010. Let me know if you need further info.TheSHEEEP wrote:Uhm... IDE? Compiler line? Anything that would help us help you?
Thanks
Jack
-
- Orc Shaman
- Posts: 788
- Joined: Mon Jan 18, 2010 6:06 pm
- Location: Costa Mesa, California
- x 24
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Click the file with the ? and press ALT + ENTER, then change it's path to the appropriate path for the file. That should get rid of the ?
-
- Minaton
- Posts: 921
- Joined: Sat Jul 31, 2010 6:29 pm
- Location: Belgium
- x 80
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Thanks for sharing this!tod wrote:I integrated OgreRecast into my project and I though that RecastInputGeometry needed some performance/readability improvements.
I agree that there is a serious performance penalty in the inputGeometry class, and that it can be optimized a lot. It also needs an aesthetic reworking.
I will try to incorporate your improvements into it in a future version.
Developer @ MakeHuman.org
-
- Troll
- Posts: 1394
- Joined: Wed Aug 02, 2006 9:41 am
- Location: Bucharest
- x 94
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Glad you found it useful. PM me if you have questions. I also managed to only feed recast the terrain triangles that are in the bounding box (I use only one terrain, and I always suppose any navigation mesh is included in it, but I think it may work with more terrains, if my calculations are correct, but I wouldn't bet on it ). By the way, I am trying to regenerate navigation tiles at runtime, from Ogre geometry when some entities are destroyed, do you think this could work? Regarding performance I mean.duststorm wrote: Thanks for sharing this!
I agree that there is a serious performance penalty in the inputGeometry class, and that it can be optimized a lot. It also needs an aesthetic reworking.
I will try to incorporate your improvements into it in a future version.
Code: Select all
//---------------------------------------------------------------------------------
// TERRAIN DATA BUILDING
size_t trnCount = 0;
// get height data, world size, map size
float *mapptr = trn->getHeightData();
float WorldSize = trn->getWorldSize();
int MapSize = trn->getSize();
// calculate where we need to move/place our vertices
float DeltaPos = (WorldSize / 2.0f);
// Determine world offset position for this terrain tile
Ogre::AxisAlignedBox trnBox = trn->getWorldAABB();
float DeltaX = trnBox.getMinimum().x;
float DeltaZ = trnBox.getMaximum().z;
float Scale = WorldSize / (float)(MapSize - 1);
// build vertices
int maxX = (tileBounds.getMaximum().x + Scale < trnBox.getMaximum().x)? MapSize - (trnBox.getMaximum().x - tileBounds.getMaximum().x)/ Scale:MapSize - 1;
int maxZ = (tileBounds.getMaximum().z + Scale < trnBox.getMaximum().z)? MapSize - (trnBox.getMaximum().z - tileBounds.getMaximum().z)/ Scale:MapSize - 1;
int minX = (tileBounds.getMinimum().x > trnBox.getMinimum().x)?((tileBounds.getMinimum().x - trnBox.getMinimum().x) / Scale):0;
int minZ = (tileBounds.getMinimum().z > trnBox.getMinimum().z)?((tileBounds.getMinimum().z - trnBox.getMinimum().z) / Scale):0;
mVertices.reserve((maxX-minX +1)*(maxZ-minZ + 1)*3);
//Ogre::ManualObject *rahat = GameManager::getSingleton().getSceneMgr()->createManualObject("onerahat");
//rahat->begin("recastdebug", Ogre::RenderOperation::OT_TRIANGLE_LIST) ;
for(int z = MapSize - maxZ; z <= MapSize - minZ; z++)
{
for(int x = minX; x <= maxX ; x++)
{
mVertices.push_back((Scale * x) + DeltaX);
mVertices.push_back(mapptr[(MapSize * z) + x]);
mVertices.push_back((Scale * -z) + DeltaZ);
//rahat->position((Scale * x) + DeltaX, mapptr[(MapSize * z) + x] + 3.0,(Scale * -z) + DeltaZ);
//rahat->colour(Ogre::ColourValue::Red);
}
}
// build indices
size_t size = ((maxX-minX)*(maxZ-minZ)) * 6;
mIndices.reserve(size);
for(int x = 0 ; x < (maxX-minX + 1)*(maxZ-minZ);++x)
{
if(x && (x + 2)%(maxX-minX + 1) == 0)
{
x++;
continue;
}
// make a square of 2 triangles
mIndices.push_back(x);
mIndices.push_back(x + 1);
mIndices.push_back(x + maxX - minX + 1);
mIndices.push_back(x + 1);
mIndices.push_back(x + 1 + maxX - minX + 1);
mIndices.push_back(x + maxX - minX + 1);
//rahat->triangle(x,x + 1, x + maxX - minX + 1);
//rahat->triangle(x + 1,x + 1 + maxX - minX + 1, x + maxX - minX + 1);
}
//rahat->end();
//GameManager::getSingleton().getSceneMgr()->getRootSceneNode()->createChildSceneNode()->attachObject(rahat);
-
- Gnoll
- Posts: 675
- Joined: Mon Jul 05, 2010 6:16 pm
- Location: Pavia Italy
- x 4
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
a simple question: if i use heightmaps how i can decide where are walking place?
thanks
Nevarim
thanks
Nevarim
i'm a noob until proven otherwise
used in my project and thanks to everyone
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
used in my project and thanks to everyone
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
-
- Troll
- Posts: 1394
- Joined: Wed Aug 02, 2006 9:41 am
- Location: Bucharest
- x 94
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
I don't think Recast can handle heightmaps directly, you will have to feed it the terrain geometry you created from the heightmap.
-
- Gnoll
- Posts: 675
- Joined: Mon Jul 05, 2010 6:16 pm
- Location: Pavia Italy
- x 4
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
so first i have to create geometry from heightmap and then give it to crowd?
i'm a noob until proven otherwise
used in my project and thanks to everyone
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
used in my project and thanks to everyone
Ogre 3d
Mygui
Skyx
Hydrax
MOC
CCS
-
- Minaton
- Posts: 921
- Joined: Sat Jul 31, 2010 6:29 pm
- Location: Belgium
- x 80
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
I you mean feeding heightmap data to recast, you need to generate triangles form the heightmap data in some way.nevarim wrote:a simple question: if i use heightmaps how i can decide where are walking place?
Since there is already an adaptation for Ogre::Terrain you could load the heightmaps with that and feed the terrain tiles to recast.
It might also be possible to create voxel data from the heightmap, and feed that directly to recast, but that would take a lot more work to get right.
Developer @ MakeHuman.org
-
- Gnoblar
- Posts: 8
- Joined: Sun Jun 10, 2012 7:36 pm
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Hey there.
This component is fantastic, should be included in future releases of Ogre! However, I got a (hopefully) simple question:
Is there any way to add new input geometry to the already generated mesh? The reason I'm asking is because I got a paged terrain and I'd like the navmesh to be rebuilt for each page individually.
Thank you in advance!
This component is fantastic, should be included in future releases of Ogre! However, I got a (hopefully) simple question:
Is there any way to add new input geometry to the already generated mesh? The reason I'm asking is because I got a paged terrain and I'd like the navmesh to be rebuilt for each page individually.
Thank you in advance!
-
- Gremlin
- Posts: 171
- Joined: Tue Jan 03, 2012 1:38 am
- Location: Brazil
- x 3
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Hello guys,
I've been Reading the Recast and Detour lib for a while, and i decided to take a step ahead before i finish Reading and then create a sample out of the rc and dt source, so i just edited the ogrerecastterrainapplication.cpp and then added my own terrain built with artifex terra 3d a while ago,and also edited the characteranimatable.cpp file and added my own character ,also a few more things,well it worked when i left the terrain size to 1025 and the terrain world size to 12000.0f however if i leave that size of my artifex imported terrain ,it will look strechy in terms of height map, the mountains and some other stuff will be streched out since the standard arfifex terrain world size is 5000.0f,which is the size i use to load it, so the thing is if i set the terrain world size to 5000.0f the navmesh wont cover all the terrain areas and will look a little buggy like in the Picture below :
Uploaded with ImageShack.us
and im pretty sure my code is correct as you all can see :
i know i could use the other way of building it but both ways wont work.....any clue of why this is happening? i want to have the navmesh for the entire terrain,just like when i leave the terrain world size in 12000.0f...
any help here is greatly appreciated and i look forward for repies!
Kind regards,
Romulo Romero
PS: Thanks cbibejs and Tod for sharing your implementations!!
i will add the save and load feature later as soon as i get my problem sorted :d
I've been Reading the Recast and Detour lib for a while, and i decided to take a step ahead before i finish Reading and then create a sample out of the rc and dt source, so i just edited the ogrerecastterrainapplication.cpp and then added my own terrain built with artifex terra 3d a while ago,and also edited the characteranimatable.cpp file and added my own character ,also a few more things,well it worked when i left the terrain size to 1025 and the terrain world size to 12000.0f however if i leave that size of my artifex imported terrain ,it will look strechy in terms of height map, the mountains and some other stuff will be streched out since the standard arfifex terrain world size is 5000.0f,which is the size i use to load it, so the thing is if i set the terrain world size to 5000.0f the navmesh wont cover all the terrain areas and will look a little buggy like in the Picture below :
Uploaded with ImageShack.us
and im pretty sure my code is correct as you all can see :
Code: Select all
mDetourTileCache = new OgreDetourTileCache(mRecast, 72);
mDetourTileCache->configure(mGeom);
Ogre::AxisAlignedBox areaToLoad;
areaToLoad.setMinimum(mGeom->getBoundingBox().getMinimum());
areaToLoad.setMaximum(mGeom->getBoundingBox().getMaximum());
mDetourTileCache->buildTiles(mGeom, &areaToLoad);
any help here is greatly appreciated and i look forward for repies!
Kind regards,
Romulo Romero
PS: Thanks cbibejs and Tod for sharing your implementations!!
i will add the save and load feature later as soon as i get my problem sorted :d
-
- OGRE Retired Team Member
- Posts: 972
- Joined: Mon Jun 02, 2008 6:52 pm
- Location: Berlin
- x 65
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
So it does work with a terrain of size 12k but not 5k?
Have you tried numbers in between to see if there is a "breaking point"?
I guess you'll have to debug the recast/detour itself to see when things break in there.
There is also a google group for recast (the "official" forum), did you ask there? I'd imagine they may know more about it than people here.
Have you tried numbers in between to see if there is a "breaking point"?
I guess you'll have to debug the recast/detour itself to see when things break in there.
There is also a google group for recast (the "official" forum), did you ask there? I'd imagine they may know more about it than people here.
-
- Gremlin
- Posts: 171
- Joined: Tue Jan 03, 2012 1:38 am
- Location: Brazil
- x 3
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
TheSHEEEP wrote:So it does work with a terrain of size 12k but not 5k?
Have you tried numbers in between to see if there is a "breaking point"?
I guess you'll have to debug the recast/detour itself to see when things break in there.
There is also a google group for recast (the "official" forum), did you ask there? I'd imagine they may know more about it than people here.
Hi TheSHEEEP first of all i appreciate your reply, and about the numbers attempts , yeah i have already tried several range of number but they all seem to result in the same navesh mesh drawn area, pretty weird actually..i sent DustStorm a pm lets see if he knows how to fix it but meanwhile i will take a look at the oficial forums and see if i can get any help from there!
thanks The SHEEEP and i look forward for more replies here in this thread
Kind regards,
Romulo Romero
-
- Gremlin
- Posts: 171
- Joined: Tue Jan 03, 2012 1:38 am
- Location: Brazil
- x 3
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Hi folks,
im sorry bout bothering you but i found where the problem was, i had to fix it in the inputgeometry.cpp file these lines(i tried the ogre recast forums but Mikko also didnt detect where the issue was located at..then based on the navmesh geom i thought the problem could be related to the geom so..) :
they were set to -6000 and 6000 which explains why it was workin on a terrain size of 12000.0f hehe
i hope this can help someone else who may face the same problem!!
Thanks alot!
Kind regards,
Romulo Romero
im sorry bout bothering you but i found where the problem was, i had to fix it in the inputgeometry.cpp file these lines(i tried the ogre recast forums but Mikko also didnt detect where the issue was located at..then based on the navmesh geom i thought the problem could be related to the geom so..) :
Code: Select all
// TODO this hardcoded behaviour has to go! Supports only up to 4 terrain pages
switch(trnCount)
{
case 0:
DeltaX = -2500;
DeltaZ = 2500;
break;
case 1:
DeltaX = -2500;
DeltaZ = -2500;
break;
case 2:
DeltaX = 2500;
DeltaZ = 2500;
break;
case 3:
DeltaX = 2500;
DeltaZ = -2500;
break;
DeltaX = 0;
DeltaZ = 0;
}
they were set to -6000 and 6000 which explains why it was workin on a terrain size of 12000.0f hehe
i hope this can help someone else who may face the same problem!!
Thanks alot!
Kind regards,
Romulo Romero
-
- Orc Shaman
- Posts: 788
- Joined: Mon Jan 18, 2010 6:06 pm
- Location: Costa Mesa, California
- x 24
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
I'm sure there's a function to get the terrain size to pass that instead of the hardcoded 12000f. Just a thought...
-
- Gremlin
- Posts: 171
- Joined: Tue Jan 03, 2012 1:38 am
- Location: Brazil
- x 3
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Hi drwbns ,drwbns wrote:I'm sure there's a function to get the terrain size to pass that instead of the hardcoded 12000f. Just a thought...
Yeah it might have it but as i still consider myself a newbie and i havent studied all the recast and detour files, theres still a lot to learn from it ,but i have a general idea of how it Works already thats why i decided to build a sample out of it ...actually edited some files and the crwd sample file ^^
but if you find any function(before i finish Reading all the files) which gets the terrain size let us know please
All the best,
Romulo Romero
-
- Gremlin
- Posts: 171
- Joined: Tue Jan 03, 2012 1:38 am
- Location: Brazil
- x 3
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Ok here i go again,
another error but this time it seems to be a little more complicated, ok i have a scene saved in a scene.scene file so what im trying to do is to generate first the navmesh geometry for the terrain and then right after its done,load the scene so when it starts creating the entities(scene objects like rocks ,trees etc..)right after the creation of every entity i want to get my geometry updated and recreate the recast input geometry data with terrain and all extra entities, however im having a little problem while doing that, it updates most of it but it crashes almost at the end of the scene objects..so what i noticed is that it usually crashes at the objects which their bounding boxes are inside another bb,usually for example a small plant bb inside a rock bb, the plants are very close to the rock almost touching it...i think this is the reason why its crashing...
the file that throws the exption is the throw.cpp and in this line :
so i tried a work around such as merging bounding boxes which intersects with each other like this :
but to no avail, so the reason why i came to this conclusion is that when i added these lines :
(i might be completely wrong but so far thats what i have in mind), so after doing something like the above i cant remember cause i already removed the code so this is what i can recall, then it rendered the scene "without a problem" however the entities which were intersecting with each other were not created since the node creation comes after the scope above..so it returns to the next entity before creating the node for the previous entity ,so thats why i think the issue kind of got to do with the entities bounding boxes and its geometries at the bottom!!
i hope any of you guys can help me out with this cause i spent a whole day yesterday up to 4AM trying to solve that problem and im stuck!!
any help is greatly appreciated !!!!!!!
All the best,
Romulo Romero
another error but this time it seems to be a little more complicated, ok i have a scene saved in a scene.scene file so what im trying to do is to generate first the navmesh geometry for the terrain and then right after its done,load the scene so when it starts creating the entities(scene objects like rocks ,trees etc..)right after the creation of every entity i want to get my geometry updated and recreate the recast input geometry data with terrain and all extra entities, however im having a little problem while doing that, it updates most of it but it crashes almost at the end of the scene objects..so what i noticed is that it usually crashes at the objects which their bounding boxes are inside another bb,usually for example a small plant bb inside a rock bb, the plants are very close to the rock almost touching it...i think this is the reason why its crashing...
the file that throws the exption is the throw.cpp and in this line :
Code: Select all
// Hand it off to the OS:
//
EHTRACE_EXIT;
#if defined(_M_X64) && defined(_NTSUBSET_)
RtlRaiseException( (PEXCEPTION_RECORD) &ThisException );
#else
RaiseException( ThisException.ExceptionCode,
ThisException.ExceptionFlags,
ThisException.NumberParameters,
(PULONG_PTR)&ThisException.params );
#endif
}
Code: Select all
Ogre::AxisAlignedBox bb = InputGeom::getWorldSpaceBoundingBox(ent);
if(bb.intersects(ent->getBoundingBox()))
bb.merge(ent->getBoundingBox());
Code: Select all
Ogre::AxisAlignedBox bb = InputGeom::getWorldSpaceBoundingBox(ent);
if(mGeom)
delete mGeom;
// Recreate recast input geometry data with terrain and all extra entities
mGeom = new InputGeom(mTerrainGroup, mNavmeshEnts);
if(bb.intersects(ent->getBoundingBox()))
return;
// Rebuild tiles that touch bounding box
mDetourTileCache->updateFromGeometry(mGeom, &bb);
i hope any of you guys can help me out with this cause i spent a whole day yesterday up to 4AM trying to solve that problem and im stuck!!
any help is greatly appreciated !!!!!!!
All the best,
Romulo Romero
-
- Gremlin
- Posts: 171
- Joined: Tue Jan 03, 2012 1:38 am
- Location: Brazil
- x 3
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
ok so I was debugging it and set a couple of break points then checked to see where exactly it was crashing then this is the line :
it seems to be something with memory allocation...maybe a memset issue..not sure..=(
HELP please ;(
thanks in advance for any reply!
Romulo Romero
Code: Select all
mGeom = new InputGeom(mTerrainGroup, mNavmeshEnts);
HELP please ;(
thanks in advance for any reply!
Romulo Romero
-
- Gremlin
- Posts: 171
- Joined: Tue Jan 03, 2012 1:38 am
- Location: Brazil
- x 3
Re: OgreCrowd: a crowd component for Ogre using Recast/Detou
Hi guys i want to provide more details this time...
so i have the call stack sequence before the error occurrs and till it happens..
so here are the pictures sequence :
http://i1179.photobucket.com/albums/x40 ... uence1.jpg
http://i1179.photobucket.com/albums/x40 ... uence2.jpg
http://i1179.photobucket.com/albums/x40 ... uence3.jpg
http://i1179.photobucket.com/albums/x40 ... uence4.jpg
http://i1179.photobucket.com/albums/x40 ... uence5.jpg
http://i1179.photobucket.com/albums/x40 ... uence6.jpg
its in order, so it starts trying to build a chuncky tri mesh but then...it seems to be a bad memory allocation or maybe it runs out of memory...so i hope this time i can get some help with all those details!
Thanks in advance,
Romulo Romero
so i have the call stack sequence before the error occurrs and till it happens..
so here are the pictures sequence :
http://i1179.photobucket.com/albums/x40 ... uence1.jpg
http://i1179.photobucket.com/albums/x40 ... uence2.jpg
http://i1179.photobucket.com/albums/x40 ... uence3.jpg
http://i1179.photobucket.com/albums/x40 ... uence4.jpg
http://i1179.photobucket.com/albums/x40 ... uence5.jpg
http://i1179.photobucket.com/albums/x40 ... uence6.jpg
its in order, so it starts trying to build a chuncky tri mesh but then...it seems to be a bad memory allocation or maybe it runs out of memory...so i hope this time i can get some help with all those details!
Thanks in advance,
Romulo Romero