PLSM2 Treecollision: lots of small or few large bodies?

pra

21-06-2007 13:31:34

I want to use ogrenewt with plsm2. i decided to load/destroy terrain bodies when a page is loaded/unloaded.
should i create a body for each tile, or one for each page?
a page is about 513*513, a tile 65*65.
i thought, lots of bodies would use more ram, but with small bodies, newton has to check a smaller part of the geometry when AABBs are overlapping

edit: do I have to attach a body to a scenenode? i don't need it in this case

walaber

21-06-2007 17:38:27

either will probably work fine, although for very large objects, breaking it up into smaller chunks might be more efficient.

no, you don't need to attach a Body to a SceneNode.

Eldarion

21-06-2007 20:38:01

i have a little question similar to the topic.

if you use smaller chunks you could include frustum culling. or can you also include that with ogre if you have larger chunks?

pra

23-06-2007 13:14:43

frustum culling? for collision? does this make sense?

@topic: i tried 1tile=1body now. serialization is fast, but it takes half an eternity to load it... I'll try serializing the entire page now.
I also found that the collision meshes for plsm2 are created with wrong face winding, so i guess i have to update from cvs and apply my changes to the treecollisionsceneparser again^^
(i would submit a patch, if i would know how)

walaber

24-06-2007 03:46:18

ogrenewt has been updated now, so that you can switch the facewinding without altering the source.

pra

24-06-2007 14:56:43

yeah, seen that, alerady changed the code. i also found out how to submit a patch, so I submitted one^^

edit: i'm a little confused right now, i'm not sure if i've done it the right way:
with my fix, the sceneparser doesn't care where the startnode is, this means you have to position the body afterwards. without, the body has to be at 0,0,0 and Quaternion::IDENTITY. I thought, my approach would be better, because someone might want to move/rotate the whole thing afterwards.

@topic: is there a way to add collisions?
I do the following in my export function:
//recover data at the end of the vector and send it to our physics class for the next step
int* numVtx=((int*)params[5]);
Vector3* vertices=((Vector3*)params[6]);
IndexData* indexData=((IndexData*)params[7]);

//hier col erstellen und exportieren
Collision* collision=new CollisionPrimitives::TreeCollision(mWorld,*numVtx,vertices,indexData,false,OgreNewt::CollisionPrimitives::FW_REVERSE);

this code is inside a loop which loops through all pages. what I want now is to combine all of this collisions into one singe. can I do something like
collision += another_collision?
or, if not, i guess i have to add numVtx, verticles and indexData. unfortunately, i have no idea how :oops:

walaber

24-06-2007 17:16:42

for a tree collision, you can create them manually... so you can do something like this:


TreeCollision* col = new TreeCollision(mWorld);

col->begin();

// for each page, add a poly 1 by 1
col->addPoly( blah, blah, blah );

// at the very end,
col->finish( optimize );


in other words, you need to modify the page code to just add polygons to an existing TreeCollision, and at the very end finish it up.

let me know if you need more explanation.

pra

24-06-2007 17:53:18

that's what I was looking for, thanks
i'll look in the ogrenewt code for more info^^

pra

27-06-2007 13:53:54

ok, it is done.
it seems what with one collision file per page the scene is loading faster.

here's the code i use to export collision:
PagingLandScapeSceneManager *plsmMgr = static_cast<PagingLandScapeSceneManager*>(mSceneMgr);
PagingLandScapeOptions *opt = plsmMgr->getOptions();
unsigned int height = opt->world_height;
unsigned int width = opt->world_width;
unsigned int NumTiles = opt->NumTiles;
unsigned int NumPages = opt->NumPages;

TreeCollisionSerializer* serializer=new TreeCollisionSerializer();
//loop through all pages
for(unsigned int page_z = 0;page_z<height;page_z++)
for(unsigned int page_x = 0;page_x<width;page_x++)
{
//create collision
OgreNewt::CollisionPrimitives::TreeCollision *pageCol = new CollisionPrimitives::TreeCollision(mWorld);
pageCol->start();
//loop through all tiles
for(unsigned int tile_z = 0;tile_z<NumTiles;tile_z++)
for(unsigned int tile_x = 0;tile_x<NumTiles;tile_x++)
{
//ask reference to geometry to PLSM2
std::vector<void*> params;
int renderLevel=0;
params.push_back(&page_x);
params.push_back(&page_z);
params.push_back(&tile_x);
params.push_back(&tile_z);
params.push_back(&renderLevel);
mSceneMgr->getOption("PageGetTileVertexData_2",&params);

//recover data at the end of the vector and send it to our physics class for the next step
int* numVtx=((int*)params[5]);
Vector3* vertices=((Vector3*)params[6]);
IndexData* indexData=((IndexData*)params[7]);
//now add the polys
//C&P from ogrenewt BEGIN
unsigned int numPolys = indexData->indexCount / 3;
Ogre::HardwareIndexBufferSharedPtr hwIndexBuffer=indexData->indexBuffer;
size_t indexSize=hwIndexBuffer->getIndexSize();
void* indices=hwIndexBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY);

assert((indexSize==2) || (indexSize==4));

if (indexSize==2)
{
unsigned short* curIndex=(unsigned short*)indices;
for ( unsigned int poly = 0; poly < numPolys; poly++ )
{
Ogre::Vector3 poly_verts[3];

//invert vertex winding (otherwise, raycasting won't work???)

poly_verts[0] = vertices[*curIndex]; curIndex++;
poly_verts[1] = vertices[*curIndex]; curIndex++;
poly_verts[2] = vertices[*curIndex]; curIndex++;

pageCol->addPoly( poly_verts, 0 );
}
}
else
{
unsigned int* curIndex=(unsigned int*)indices;
for ( unsigned int poly = 0; poly < numPolys; poly++ )
{
Ogre::Vector3 poly_verts[3];

poly_verts[0] = vertices[*curIndex]; curIndex++;
poly_verts[1] = vertices[*curIndex]; curIndex++;
poly_verts[2] = vertices[*curIndex]; curIndex++;
pageCol->addPoly( poly_verts, 0 );
}
}

hwIndexBuffer->unlock();
//C&P from ogrenewt END

//cleanup
delete[] vertices;
delete numVtx;



}
pageCol->finish(false);
//export the collision
serializer->exportTreeCollision(static_cast<OgreNewt::CollisionPrimitives::TreeCollision*>(pageCol),"yourFileName");
//I use "plsm2_"+terrain_configname+"_"+page_x+"_"+page_z+".collision" for filename


}

delete serializer;

for importing, i do this on PageLoaded:

unsigned int page_x = e->mPagex;
unsigned int page_z = e->mPagez;



ResourceGroupManager *rgm = ResourceGroupManager::getSingletonPtr();
TreeCollisionSerializer* serializer=new TreeCollisionSerializer();

String filename = "yourFileName";
if(rgm->resourceExists("yourResourceGroup",filename))
{
//ok, it is there and can be loaded
DataStreamPtr ptr = rgm->openResource(filename,"yourResourceGroup");
CollisionPrimitives::TreeCollision *collision=new CollisionPrimitives::TreeCollision(mWorld);
serializer->importTreeCollision(ptr,collision);
OgreNewt::Body *bod = new OgreNewt::Body(mWorld,collision);
bod->attachToNode(NULL);
}
else
{
//no collision file. display error or stuff
}
delete serializer;

the part for destroying the bodies afterwards (on page unload?) is still missing, though

walaber

27-06-2007 19:07:00

nice! note that the body->attachToNode(NULL) is unnecessary.