Terrain integration into newton physics
Posted: Mon Jan 17, 2005 6:22 pm
Hi!
I'm trying to implement my terrain into the newton world. I'm using the same code as for my BSP Level. You can see the result at:
http://aoh.arturh.com/terrain.JPG
Another problem i have with my existing code is, that i cannot set the position of my bsp level, because this results in an endless loop at NewtonTreeCollisionEndBuild(newtonmap, 1);
First, my function for creating the NewtonCollison* from the scene node and the mesh:
The code for creating my bsp level:
And here is my code to implement the terrain:
Does anyone implemented a code for newton that works better? i rewrote some parts of the mercior tutorial for my code.
I'm trying to implement my terrain into the newton world. I'm using the same code as for my BSP Level. You can see the result at:
http://aoh.arturh.com/terrain.JPG
Another problem i have with my existing code is, that i cannot set the position of my bsp level, because this results in an endless loop at NewtonTreeCollisionEndBuild(newtonmap, 1);
First, my function for creating the NewtonCollison* from the scene node and the mesh:
Code: Select all
NewtonCollision* GetNewtonCollision(scene::ISceneNode* node, scene::IAnimatedMesh* mesh)
{
NewtonCollision* newtonmap;
newtonmap = NewtonCreateTreeCollision(nWorld, NULL);
NewtonTreeCollisionBeginBuild(newtonmap);
int cMeshBuffer, j;
int v1i, v2i, v3i;
scene::IMeshBuffer *mb;
core::vector3df vArray[3]; // vertex array (3*3 floats)
int tmpCount = 0;
core::vector3df scale = node->getScale();
core::vector3df translation = node->getPosition();
for (cMeshBuffer=0; cMeshBuffer<mesh->getMesh(0)->getMeshBufferCount(); cMeshBuffer++)
{
mb = mesh->getMesh(0)->getMeshBuffer(cMeshBuffer);
video::S3DVertex2TCoords* mb_vertices = (irr::video::S3DVertex2TCoords*)mb->getVertices();
u16* mb_indices = mb->getIndices();
// add each triangle from the mesh
int IndexCount = mb->getIndexCount();
for (j=0; j<IndexCount; j+=3)
{
v1i = mb_indices[j];
v2i = mb_indices[j+1];
v3i = mb_indices[j+2];
// to make thing easier, her we can use engine data type
vArray[0] = ((mb_vertices[v1i].Pos +translation) * scale) * IrrToNewton;
vArray[1] = ((mb_vertices[v2i].Pos +translation) * scale) * IrrToNewton;
vArray[2] = ((mb_vertices[v3i].Pos +translation) * scale) * IrrToNewton;
// make sure we do not add degenerated polygons to the tree
core::vector3df e0 (vArray[1] - vArray[0]);
core::vector3df e1 (vArray[2] - vArray[0]);
// the area of the face is the cross product
core::vector3df area (e0.crossProduct (e1));
// skip faces with very small area
float mag = area.dotProduct (area);
if (mag > 1.0e-9f) {
NewtonTreeCollisionAddFace(newtonmap, 3, &vArray[0].X, sizeof (core::vector3df), 1);
}
}
}
// we definilte wan to optimize the mesh (improve performace and vehaviuor a lot)
NewtonTreeCollisionEndBuild(newtonmap, 1);
return newtonmap;
}
Code: Select all
for(u32 b=0; b<App->Map->BSPLevels.size(); b++)
{
wcstombs(cBuffer, App->Map->BSPLevels[b].BspFilename.c_str(),256);
scene::IAnimatedMesh* quakeLevelMesh = resmanager->getMesh(cBuffer);
quakeLevelMeshes.push_back(quakeLevelMesh);
if (quakeLevelMesh)
{
scene::ISceneNode* quakeLevelNode = smgr->addOctTreeSceneNode(quakeLevelMesh->getMesh(0));
quakeLevelNodes.push_back(quakeLevelNode);
if (quakeLevelNode)
{
quakeLevelNode->setVisible(true);
quakeLevelNode->setScale(App->Map->BSPLevels[b].scale);
quakeLevelNode->setPosition(App->Map->BSPLevels[b].position);
quakeLevelNode->setMaterialType(video::EMT_SOLID );
quakeLevelNode->setMaterialFlag(video::EMF_LIGHTING,true);
quakeLevelNode->setMaterialFlag(video::EMF_TRILINEAR_FILTER,true);
quakeLevelNode->setMaterialFlag(video::EMF_BACK_FACE_CULLING,true);
// create map triangle selector
mapSelector = smgr->createOctTreeTriangleSelector(quakeLevelMesh->getMesh(0), quakeLevelNode, 128);
metaSelector->addTriangleSelector(mapSelector);
// ------------------------------------------------------------------
// Add Level to Newton Physic Engine
NewtonCollision* newtonmap = GetNewtonCollision(quakeLevelNode, quakeLevelMesh);
// create a ridid body to represent the world
NewtonBody* newtonmapbody;
newtonmapbody = NewtonCreateBody(nWorld, newtonmap);
DebugBodies.push_back(newtonmapbody);
// release the collsion tree (this way the application does not have to do book keeping of Newton objects
NewtonReleaseCollision (nWorld, newtonmap);
// set the newton world size based on the bsp size
core::vector3df boxP0;
core::vector3df boxP1;
core::matrix4 matrix;
NewtonBodyGetMatrix (newtonmapbody, &matrix.M[0]);
NewtonCollisionCalculateAABB (newtonmap, &matrix.M[0], &boxP0.X, &boxP1.X);
NewtonSetWorldSize (nWorld, &boxP0.X, &boxP1.X);
// the world uses the ground material
NewtonBodySetMaterialGroupID (newtonmapbody, Physics->m_groundMaterial);
// ------------------------------------------------------------------
}
}
}
Code: Select all
for(u32 t=0; t<App->Map->Terrains.size(); t++)
{
video::IImage* texture = resmanager->createImageFromFile(util->Convert(cBuffer, App->Map->Terrains[t].texture.c_str(), 255));
if (texture == NULL )
Log("Could not load terrain texture: %s", cBuffer);
video::IImage* heightmap = resmanager->createImageFromFile(util->Convert(cBuffer, App->Map->Terrains[t].heightmap.c_str(), 255));
if (heightmap == NULL )
Log("Could not load heightmap texture: %s", cBuffer);
video::ITexture* detail = resmanager->getTexture(util->Convert(cBuffer, App->Map->Terrains[t].detail.c_str(), 255)) ;
if (detail == NULL )
Log("Could not load detail texture: %s", cBuffer);
if ( texture && heightmap && detail )
{
scene::IAnimatedMesh* terrainMesh =
resmanager->addTerrainMesh("terrain", texture, heightmap, App->Map->Terrains[t].stretch,App->Map->Terrains[t].maxheight, App->Map->Terrains[t].blocksize);
scene::ISceneNode* terrain = smgr->addOctTreeSceneNode ( terrainMesh );
scene::ITriangleSelector* selector = smgr->createOctTreeTriangleSelector ( terrainMesh->getMesh ( 0 ),terrain, 128 );
metaSelector->addTriangleSelector(selector);
terrain->setTriangleSelector(selector);
terrains.push_back(terrain);
terrain->setScale(App->Map->Terrains[t].scale);
terrain->setPosition(App->Map->Terrains[t].position);
NewtonCollision* newtonmap = GetNewtonCollision(terrain, terrainMesh);
// create a ridid body to represent the world
NewtonBody* newtonmapbody;
newtonmapbody = NewtonCreateBody(nWorld, newtonmap);
DebugBodies.push_back(newtonmapbody);
NewtonReleaseCollision (nWorld, newtonmap);
NewtonBodySetMaterialGroupID (newtonmapbody, Physics->m_groundMaterial);
}
}