void TreeCollisionSerializer::exportTreeCollision(const CollisionPrimitives::TreeCollision* collision, const Ogre::String& filename) { mpfFile=fopen(filename.c_str(),"wb"); if (!mpfFile) { OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Unable to open file " + filename + " for writing","TreeCollisionSerializer::exportTreeCollision"); } NewtonTreeCollisionSerialize(collision->m_col,&TreeCollisionSerializer::_newtonSerializeCallback,this); }
bool Physics::serialize( const std::string& meshFile, const std::string& outputFile ) { log_debug << "Physics: serializing physics static geometry '" << meshFile << "'" << std::endl; log_debug << "Physics: unloading existing level" << std::endl; // first unload existing level LevelManager::get()->unloadLevel( true, true ); osg::ref_ptr< osg::Node > meshnode = LevelManager::get()->loadMesh( meshFile, false ); if ( !meshnode.valid() ) return false; osg::ref_ptr< osg::Group > root = new osg::Group; root->addChild( meshnode.get() ); // begin build the collision faces //-------------------------- NewtonCollision* p_collision = NewtonCreateTreeCollision( _p_world, levelCollisionCallback ); NewtonTreeCollisionBeginBuild( p_collision ); // start timer osg::Timer_t start_tick = osg::Timer::instance()->tick(); //! iterate through all geometries and create their collision faces PhysicsVisitor physVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN, p_collision ); root->accept( physVisitor ); // stop timer and give out the time messure osg::Timer_t end_tick = osg::Timer::instance()->tick(); log_debug << "Physics: elapsed time for building physics collision faces = "<< osg::Timer::instance()->delta_s( start_tick, end_tick ) << std::endl; log_debug << "Physics: total num of evaluated primitives: " << physVisitor.getNumPrimitives() << std::endl; log_debug << "Physics: total num of vertices: " << physVisitor.getNumVertices() << std::endl; //-------------------------- // finalize tree building NewtonTreeCollisionEndBuild( p_collision, 0 ); // write out the serialization data std::string file( yaf3d::Application::get()->getMediaPath() + outputFile + YAF3DPHYSICS_SERIALIZE_POSTFIX ); log_debug << "Physics: write to serialization file '" << file << "'" << std::endl; std::ofstream serializationoutput; serializationoutput.open( file.c_str(), std::ios_base::binary | std::ios_base::out ); if ( !serializationoutput ) { log_error << "Physics: cannot write to serialization file '" << file << "'" << std::endl; serializationoutput.close(); NewtonReleaseCollision( _p_world, p_collision ); return false; } NewtonTreeCollisionSerialize( p_collision, serializationCallback, &serializationoutput ); serializationoutput.close(); NewtonReleaseCollision( _p_world, p_collision ); return true; }
Terrain::Terrain(const ion::base::String& identifier,NewtonWorld *pNewtonworld,ion::scene::Renderer& rRenderer, ion::base::Streamable& heightmap,const ion_uint32 width,const ion_uint32 depth,const ion_uint32 patchwidth, const ion_uint32 patchdepth,const ion::math::Vector3f& offset,const ion::math::Vector3f& size): m_pNewtonworld(pNewtonworld),Node(identifier) { ion_uint32 numpatchesX=(width-1)/(patchwidth-1),numpatchesZ=(depth-1)/(patchdepth-1); ion_uint16 *pHeightbuffer=new ion_uint16[(width+1)*(depth+1)]; { ion_uint16 *pHLine=pHeightbuffer; for (ion_uint32 z=0;z<depth;++z) { heightmap.read(pHLine,width*sizeof(ion_uint16)); // Copy the first height to the one extra height for correct normal vector calculations pHLine[width]=pHLine[0]; pHLine+=(width+1); } // Copy the first line to the one extra line for correct normal vector calculations memcpy(pHeightbuffer+(width+1)*depth,pHeightbuffer,(width+1)*sizeof(ion_uint16)); } const ion::math::Vector3f psize( size.x()/((float)numpatchesX), size.y(), size.z()/((float)numpatchesZ) ); ion::math::Vector3f poffset( offset.x()/*-psize.x()*0.5f*/, offset.y(), offset.z()/*-psize.z()*0.5f*/ ); ion::base::Localfile serializefile; bool fileok=serializefile.open(serializefilename,"rb"); if (fileok) { ion::base::log("Terrain::Terrain()",ion::base::Message) << "Using previously serialized terrain data\n"; serializefile.open(serializefilename,"rb"); m_pTreeCollision=NewtonCreateTreeCollisionFromSerialization(pNewtonworld,0,TerrainDeserialize,&serializefile); serializefile.close(); } else { ion::base::log("Terrain::Terrain()",ion::base::Message) << "Calculating terrain data\n"; m_pTreeCollision=NewtonCreateTreeCollision(pNewtonworld,0); NewtonTreeCollisionBeginBuild(m_pTreeCollision); { for (ion_uint32 z=0;z<(depth-1);++z) { /*float zz1=offset.z()+((float)z)/((float)(depth-1))*zsize; float zz2=offset.z()+((float)(z+1))/((float)(depth-1))*zsize;*/ float zz1=offset.z()+( ((float)z)/((float)(patchdepth-1)) )*psize.z(); float zz2=offset.z()+( ((float)(z+1))/((float)(patchdepth-1)) )*psize.z(); unsigned int zT=(z/patchdepth)&1; for (ion_uint32 x=0;x<(width-1);++x) { float xx1=offset.x()+( ((float)x)/((float)(patchwidth-1)) )*psize.x(); float xx2=offset.x()+( ((float)(x+1))/((float)(patchwidth-1)) )*psize.x(); /*float xx1=offset.x()+((float)x)/((float)(width-1))*xsize; float xx2=offset.x()+((float)(x+1))/((float)(width-1))*xsize;*/ float yy11=offset.y()+((float)(pHeightbuffer[x+z*(width+1)]))/65535.0f*size.y(); float yy21=offset.y()+((float)(pHeightbuffer[x+1+z*(width+1)]))/65535.0f*size.y(); float yy12=offset.y()+((float)(pHeightbuffer[x+(z+1)*(width+1)]))/65535.0f*size.y(); float yy22=offset.y()+((float)(pHeightbuffer[x+1+(z+1)*(width+1)]))/65535.0f*size.y(); float tri1[]={ xx1,yy11,zz1, xx1,yy12,zz2, xx2,yy21,zz1 }; float tri2[]={ xx2,yy21,zz1, xx1,yy12,zz2, xx2,yy22,zz2 }; unsigned int xT=(x/patchwidth)&1; unsigned int matID=((xT&zT)==1) ? 0 : (xT|zT); NewtonTreeCollisionAddFace(m_pTreeCollision,3,tri1,12,0); NewtonTreeCollisionAddFace(m_pTreeCollision,3,tri2,12,0); } } } NewtonTreeCollisionEndBuild(m_pTreeCollision,0); serializefile.open(serializefilename,"wb"); NewtonTreeCollisionSerialize(m_pTreeCollision,TerrainSerialize,&serializefile); serializefile.close(); } NewtonBody *pTerrainBody=NewtonCreateBody(m_pNewtonworld,m_pTreeCollision); NewtonReleaseCollision(m_pNewtonworld,m_pTreeCollision); NewtonBodySetMatrix(pTerrainBody,ion::math::Matrix4f::identitymatrix()); for (ion_uint32 z=0;z<numpatchesZ;++z) { /*if (z==0) { heightmap.read(pHeightbuffer,sizeof(ion_uint16)*width*patchdepth); } else { memcpy(pHeightbuffer,pHeightbuffer+width*(patchdepth-1),width*sizeof(ion_uint16)); heightmap.read(pHeightbuffer+width,sizeof(ion_uint16)*width*(patchdepth-1)); }*/ poffset.x()=offset.x()/*-psize.x()*0.5f*/; for (ion_uint32 x=0;x<numpatchesX;++x) { ion_uint16 *pH=pHeightbuffer+x*(patchwidth-1)+z*(width+1)*(patchdepth-1); TerrainPatch *pPatch=new TerrainPatch("tpatch",rRenderer,pH,patchwidth,width+1,patchdepth, (z==(numpatchesZ-1)),poffset,psize); poffset.x()+=psize.x(); m_Patches.push_back(pPatch); addChild(*pPatch); } poffset.z()+=psize.z(); } delete [] pHeightbuffer; }