//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
HeightfieldCollisionShape::HeightfieldCollisionShape(dSpaceID _spaceId, pTerrainChunk_type _pTerrainChunk)
:   m_pTerrainChunk(_pTerrainChunk)
,   CollisionShape(NULL)
{
    m_heightfieldDataId = dGeomHeightfieldDataCreate();

    dGeomHeightfieldDataBuildCallback(
        m_heightfieldDataId,
        this,
        getHeightCallback,
        m_pTerrainChunk->getWorldWidth(),
        m_pTerrainChunk->getWorldWidth(),
        m_pTerrainChunk->getWidth(),
        m_pTerrainChunk->getWidth(),
        1.0f,
        m_pTerrainChunk->getOffset(),
        m_pTerrainChunk->getSkirtSize(),
        0
    );

    dGeomHeightfieldDataSetBounds(
        m_heightfieldDataId,
        m_pTerrainChunk->getMinHeight(),
        m_pTerrainChunk->getMaxHeight()
    );

    dGeomID geometryId = dCreateHeightfield(
        _spaceId,
        m_heightfieldDataId,
        1
    );

    Zen::Math::Vector3& position(m_pTerrainChunk->getPosition());
    dGeomSetPosition(
        geometryId,
        position.m_x,
        position.m_y,
        position.m_z
    );

    /// TODO Set rotation of terrain for cases where it is not
    /// planar with the X and Z axes.

    setGeometryId(geometryId);
}
WorldPhysics::WorldPhysics() {

  enable_complex=0;
  bulldozer_state=1;
  tmp_scalar=0;
  tmp_wait=0;

  qsrand(QTime::currentTime().msec());

  dInitODE();
  world = dWorldCreate();
  space = dHashSpaceCreate (0);
  contactgroup = dJointGroupCreate (0);
  dWorldSetGravity (world,0,0,-9.81);
  //ground_cheat = dCreatePlane (space,0,0,1,0);
  wall1=dCreatePlane (space,-1,0,0,-100);
  wall2=dCreatePlane (space,1,0,0,0);
  wall3=dCreatePlane (space,0,-1,0,-100);
  wall4=dCreatePlane (space,0,1,0,0);
  
  
  
  // our heightfield floor

  dHeightfieldDataID heightid = dGeomHeightfieldDataCreate();

	// Create an finite heightfield.
  dGeomHeightfieldDataBuildCallback( heightid, NULL, near_heightfield_callback,
                                     HFIELD_WIDTH, HFIELD_DEPTH, HFIELD_WSTEP, HFIELD_DSTEP,
                                     REAL( 1.0 ), REAL( 0.0 ), REAL( 0.0 ), 0 );

	// Give some very bounds which, while conservative,
	// makes AABB computation more accurate than +/-INF.
  //dGeomHeightfieldDataSetBounds( heightid, REAL( -4.0 ), REAL( +6.0 ) );

  gheight = dCreateHeightfield( space, heightid, 1 );
  
  
  
  // Rotate so Z is up, not Y (which is the default orientation)
  dMatrix3 R;
  dRSetIdentity( R );
  dRFromAxisAndAngle( R, 1, 0, 0, DEGTORAD * 90 );
  dGeomSetRotation( gheight, R );
  dGeomSetPosition( gheight, 50,50,0 );

//  for (int  i=0;i<MAX_ITEMS;i++) {
  //  items.push_back(generateItem());
  //}
  generateItems();

  bulldozer_space = dSimpleSpaceCreate(space);
  dSpaceSetCleanup (bulldozer_space,0);
  
  bulldozer=new BoxItem(world,bulldozer_space,LENGTH,WIDTH,HEIGHT,CMASS);
  bulldozer->setPosition(STARTX,STARTY,STARTZ);

  bulldozer_cabin=new BoxItem(world,bulldozer_space,LENGTH/2,WIDTH/2,2*HEIGHT,CMASS/3);
  bulldozer_cabin->setPosition(-LENGTH/4+STARTX,STARTY,3.0/2.0*HEIGHT+STARTZ);

  bulldozer_bucket_c=new BoxItem(world,bulldozer_space,BUCKET_LENGTH,BUCKET_WIDTH,BUCKET_HEIGHT,CMASS/10);
  bulldozer_bucket_c->setPosition(LENGTH/2+BUCKET_LENGTH/2+RADIUS+STARTX,STARTY,STARTZ);
  
  bulldozer_bucket_l=new BoxItem(world,bulldozer_space,BUCKET_WIDTH/5,BUCKET_LENGTH,BUCKET_HEIGHT,CMASS/20);
  bulldozer_bucket_l->setPosition(LENGTH/2+BUCKET_LENGTH+RADIUS+BUCKET_WIDTH/10+STARTX,-BUCKET_WIDTH/2+BUCKET_LENGTH/2+STARTY,STARTZ);
  
  
  bulldozer_bucket_r=new BoxItem(world,bulldozer_space,BUCKET_WIDTH/5,BUCKET_LENGTH,BUCKET_HEIGHT,CMASS/20);
  bulldozer_bucket_r->setPosition(LENGTH/2+BUCKET_LENGTH+RADIUS+BUCKET_WIDTH/10+STARTX,BUCKET_WIDTH/2-BUCKET_LENGTH/2+STARTY,STARTZ);
  
  
  for (int i=0; i<4; i++) {
    dQuaternion q;
    dQFromAxisAndAngle(q,1,0,0,M_PI*0.5);
    wheels[i] = new WheelItem(world,bulldozer_space,q,RADIUS,WMASS);
  }
  dBodySetPosition (wheels[0]->body,0.5*LENGTH+STARTX,WIDTH*0.5+STARTY,STARTZ-HEIGHT*0.5);
  dBodySetPosition (wheels[1]->body,0.5*LENGTH+STARTX,-WIDTH*0.5+STARTY,STARTZ-HEIGHT*0.5);
  dBodySetPosition (wheels[2]->body,-0.5*LENGTH+STARTX, WIDTH*0.5+STARTY,STARTZ-HEIGHT*0.5);
  dBodySetPosition (wheels[3]->body,-0.5*LENGTH+STARTX,-WIDTH*0.5+STARTY,STARTZ-HEIGHT*0.5);

  cabin_joint=dJointCreateSlider(world,0);
  dJointAttach(cabin_joint,bulldozer->body,bulldozer_cabin->body);
  dJointSetSliderAxis(cabin_joint,0,0,1);
  dJointSetSliderParam(cabin_joint,dParamLoStop,0);
  dJointSetSliderParam(cabin_joint,dParamHiStop,0);

  bucket_joint_c=dJointCreateSlider(world,0);
  dJointAttach(bucket_joint_c,bulldozer->body,bulldozer_bucket_c->body);
  dJointSetSliderAxis(bucket_joint_c,0,0,1);
  dJointSetSliderParam(bucket_joint_c,dParamLoStop,0);
  dJointSetSliderParam(bucket_joint_c,dParamHiStop,0);
  
  bucket_joint_l=dJointCreateSlider(world,0);
  dJointAttach(bucket_joint_l,bulldozer->body,bulldozer_bucket_l->body);
  dJointSetSliderAxis(bucket_joint_l,0,0,1);
  dJointSetSliderParam(bucket_joint_l,dParamLoStop,0);
  dJointSetSliderParam(bucket_joint_l,dParamHiStop,0);
  
  bucket_joint_r=dJointCreateSlider(world,0);
  dJointAttach(bucket_joint_r,bulldozer->body,bulldozer_bucket_r->body);
  dJointSetSliderAxis(bucket_joint_r,0,0,1);
  dJointSetSliderParam(bucket_joint_r,dParamLoStop,0);
  dJointSetSliderParam(bucket_joint_r,dParamHiStop,0);

  // front and back wheel hinges
  for (int i=0; i<4; i++) {
    wheelJoints[i] = dJointCreateHinge2 (world,0);
    dJointAttach (wheelJoints[i],bulldozer->body,wheels[i]->body);
    const dReal *a = dBodyGetPosition (wheels[i]->body);
    dJointSetHinge2Anchor (wheelJoints[i],a[0],a[1],a[2]);
    dJointSetHinge2Axis1 (wheelJoints[i],0,0,1);
    dJointSetHinge2Axis2 (wheelJoints[i],0,1,0);
  }
  // seeting ERP & CRM
  for (int i=0; i<4; i++) {
    dJointSetHinge2Param (wheelJoints[i],dParamSuspensionERP,0.5);
    dJointSetHinge2Param (wheelJoints[i],dParamSuspensionCFM,0.8);
  }
  // block back axis !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  for (int i=0; i<2; i++) {
    dJointSetHinge2Param (wheelJoints[i],dParamLoStop,0);
    dJointSetHinge2Param (wheelJoints[i],dParamHiStop,0);
  }

}
int main (int argc, char **argv)
{
        printf("ODE configuration: %s\n", dGetConfiguration());
        
	// Is trimesh support built into this ODE?
	g_allow_trimesh = dCheckConfiguration( "ODE_EXT_trimesh" );

	// setup pointers to drawstuff callback functions
	dsFunctions fn;
	fn.version = DS_VERSION;
	fn.start = &start;
	fn.step = &simLoop;
	fn.command = &command;
	fn.stop = 0;
	fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;

	// create world
	dInitODE2(0);
	world = dWorldCreate();
	space = dHashSpaceCreate (0);
	contactgroup = dJointGroupCreate (0);
	dWorldSetGravity (world,0,0,-0.05);
	dWorldSetCFM (world,1e-5);
	dWorldSetAutoDisableFlag (world,1);
	dWorldSetContactMaxCorrectingVel (world,0.1);
	dWorldSetContactSurfaceLayer (world,0.001);
	memset (obj,0,sizeof(obj));

#if 1

  dWorldSetAutoDisableAverageSamplesCount( world, 1 );

#endif

	// base plane to catch overspill
	dCreatePlane( space, 0, 0, 1, 0 );


	// our heightfield floor

	dHeightfieldDataID heightid = dGeomHeightfieldDataCreate();

	// Create an finite heightfield.
	dGeomHeightfieldDataBuildCallback( heightid, NULL, heightfield_callback,
		HFIELD_WIDTH, HFIELD_DEPTH, HFIELD_WSTEP, HFIELD_DSTEP,
		REAL( 1.0 ), REAL( 0.0 ), REAL( 0.0 ), 0 );

	// Give some very bounds which, while conservative,
	// makes AABB computation more accurate than +/-INF.
	dGeomHeightfieldDataSetBounds( heightid, REAL( -4.0 ), REAL( +6.0 ) );

	gheight = dCreateHeightfield( space, heightid, 1 );

	dVector3 pos;
	pos[ 0 ] = 0;
	pos[ 1 ] = 0;
	pos[ 2 ] = 0;

	// Rotate so Z is up, not Y (which is the default orientation)
	dMatrix3 R;
	dRSetIdentity( R );
	dRFromAxisAndAngle( R, 1, 0, 0, DEGTORAD * 90 );

	// Place it.
	dGeomSetRotation( gheight, R );
	dGeomSetPosition( gheight, pos[0], pos[1], pos[2] );

	// run simulation
	dsSimulationLoop (argc,argv,352,288,&fn);

	dJointGroupDestroy (contactgroup);
	dSpaceDestroy (space);
	dWorldDestroy (world);

	// destroy heightfield data, because _we_ own it not ODE
	dGeomHeightfieldDataDestroy( heightid );

	dCloseODE();
	return 0;
}
Exemple #4
0
    void cPhysicsObject::CreateHeightmap(cWorld* pWorld, const game::cTerrainHeightMap& loader, size_t width, size_t length, const physvec_t& scale, const physvec_t& pos, const physvec_t& rot)
    {
      // NOTE: Actual heightmap doesn't seem to be working at the moment so we use a trimesh instead

#if 1
      // TODO: Shared indices
      const float fScale = scale.x;

      std::vector<spitfire::math::cVec3> tempVertices;
      std::vector<uint32_t> tempIndices;
      tempVertices.reserve(length * width * 4);
      tempIndices.reserve(length * width * 6);

      size_t index = 0;
      for (size_t y = 0; y < length; y++) {
        for (size_t x = 0; x < width; x++) {
          const float fX = float(x) * fScale;
          const float fY = float(y) * fScale;

          tempVertices.push_back(spitfire::math::cVec3(fX, fY, loader.GetHeight(fX, fY)));

          tempVertices.push_back(spitfire::math::cVec3(fX + fScale, fY, loader.GetHeight(fX + fScale, fY)));

          tempVertices.push_back(spitfire::math::cVec3(fX + fScale, fY + fScale, loader.GetHeight(fX + fScale, fY + fScale)));

          tempVertices.push_back(spitfire::math::cVec3(fX, fY + fScale, loader.GetHeight(fX, fY + fScale)));


          tempIndices.push_back(index + 0);
          tempIndices.push_back(index + 1);
          tempIndices.push_back(index + 2);

          tempIndices.push_back(index + 2);
          tempIndices.push_back(index + 3);
          tempIndices.push_back(index + 0);

          index += 4;
        }
      }

      CreateTrimesh(pWorld, tempVertices, tempIndices, pos, rot);

#else
      DestroyHeightfield();

      bBody = false;
      bDynamic = false;

      // Heightfields are always static
      v[0] = 0.0f;
      v[1] = 0.0f;
      v[2] = 0.0f;


      fWidth = float(width) * scale.x;
      fLength = float(length) * scale.y;
      fHeight = 1.0f * scale.z;

      const size_t height = length;

      pHeightfieldData = new float[width * height];
      for (size_t y = 0; y < height; y++) {
        for (size_t x = 0; x < width; x++) {
          pHeightfieldData[(width * y) + x] = 200.0f * (sinf(float(x)) + cosf(float(y)));// 10.0f * loader.GetHeight(x, y);
        }
      }

      heightfield = dGeomHeightfieldDataCreate();

      // TODO: Last parameter, tile indefinitely
      int copyHeightData = 1; // 0 = we are keeping our own copy (Dynamic), 1 = copy the data to ODE (static)
      int wrap = 1; // 0 = don't wrap, 1 = wrap indefinitely
      float fThickness = 10.0f; // The thickness of the "shell" of the heightmap
      dGeomHeightfieldDataBuildSingle(
        heightfield, pHeightfieldData, copyHeightData,
        fWidth, fLength,
        width, height,
        scale.z, pos.z, fThickness, wrap
      );

      // Set finite AABB
      dGeomHeightfieldDataSetBounds(heightfield, 0.0f, 1000.0f);

      int movable = 1; // 1 = true, 0 = false
      geom = dCreateHeightfield(pWorld->GetSpaceStatic(), heightfield, movable);
      ASSERT(geom != 0);

      InitCommon(pWorld, pos, rot);
#endif
    }