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);
}
}