Example #1
0
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;
}
Example #2
0
bool Physics::buildStaticGeometry( osg::Group* p_root, const std::string& levelFile )
{
    NewtonCollision* p_collision = NULL;

    // check if a serialization file exists, if so then load it. otherwise build the static geometry on the fly.
    assert( levelFile.length() && "internal error: missing levelFile name!" );
    std::string file = cleanPath( levelFile );
    std::vector< std::string > path;
    explode( file, "/", &path );
    file = yaf3d::Application::get()->getMediaPath() + YAF3DPHYSICS_MEDIA_FOLDER + path[ path.size() - 1 ] + YAF3DPHYSICS_SERIALIZE_POSTFIX;
    std::ifstream serializationfile;
    serializationfile.open( file.c_str(), std::ios_base::binary | std::ios_base::in );
    if ( !serializationfile )
    {
        log_warning << "Physics: no serialization file for physics static geometry exists, building on-the-fly ..." << std::endl;

        p_collision = NewtonCreateTreeCollision( _p_world, levelCollisionCallback );
        NewtonTreeCollisionBeginBuild( p_collision );

        // build the collision faces
        //--------------------------
        // 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 );
        p_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 with optimization off ( because the meshes are already optimized by
        //  osg _and_ Newton has currently problems with optimization )
        NewtonTreeCollisionEndBuild( p_collision, 0 /* 1 */);
    }
    else
    {
        log_debug << "Physics: loading serialization file for physics static geometry: '" << file << "' ..." << std::endl;

        // start timer
        osg::Timer_t start_tick = osg::Timer::instance()->tick();

        p_collision = NewtonCreateTreeCollisionFromSerialization( _p_world, NULL, deserializationCallback, &serializationfile );
        assert( p_collision && "internal error, something went wrong during physics deserialization!" );

        // stop timer and give out the time messure
        osg::Timer_t end_tick = osg::Timer::instance()->tick();
        log_debug << "Physics: elapsed time for deserializing physics collision faces = "<< osg::Timer::instance()->delta_s( start_tick, end_tick ) << std::endl;

        serializationfile.close();
    }

    _p_body = NewtonCreateBody( _p_world, p_collision );

    // release collision object
    NewtonReleaseCollision( _p_world, p_collision );

    // set Material Id for this object
    NewtonBodySetMaterialGroupID( _p_body, getMaterialId( "level" ) );

    osg::Matrixf mat;
    mat.identity();
    NewtonBodySetMatrix( _p_body, mat.ptr() );

    // calculate the world bbox and world size
    float  bmin[ 4 ], bmax[ 4 ];
    NewtonCollisionCalculateAABB( p_collision, mat.ptr(), bmin, bmax );
    bmin[ 0 ] -= 10.0f;
    bmin[ 1 ] -= 10.0f;
    bmin[ 2 ] -= 10.0f;
    bmin[ 3 ] = 1.0f;
    bmax[ 0 ] += 10.0f;
    bmax[ 1 ] += 10.0f;
    bmax[ 2 ] += 10.0f;
    bmax[ 3 ] = 1.0f;
    NewtonSetWorldSize( _p_world, bmin, bmax );

    return true;
}
 void TreeCollisionSerializer::importTreeCollision(Ogre::DataStreamPtr& stream, CollisionPrimitives::TreeCollision* pDest)
 {
   NewtonCollision* col=NewtonCreateTreeCollisionFromSerialization(pDest->getWorld()->getNewtonWorld(), NULL, &TreeCollisionSerializer::_newtonDeserializeCallback, &stream);
   pDest->m_col=col;
 }