CompoundCollisionShape* CollisionShapeManager::PerformConvexDecomposition(const String& Name, Graphics::Mesh* ObjectMesh, Whole Depth, Real CPercent, Real PPercent, Boole UseAllSubmeshes) { //new submesh friendly code Ogre::MeshPtr myMesh = ObjectMesh->_GetInternalMesh(); Ogre::SubMesh* subMesh = NULL; Ogre::IndexData* indexData = NULL; Ogre::VertexData* vertexData = NULL; Boole use32bitindexes = false; unsigned int currtriCount = 0; unsigned int triCount = 0; unsigned int vCount = 0; unsigned int iCount = 0; Whole VertPrevSize = 0; Whole IndiPrevSize = 0; Boole SharedVerts = myMesh->getSubMesh(0)->useSharedVertices; Whole* VertPerSubMesh = NULL; if(UseAllSubmeshes) { VertPerSubMesh = new Whole[myMesh->getNumSubMeshes()]; for( Whole X = 0 ; X < myMesh->getNumSubMeshes() ; X++ ) { vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount; iCount += myMesh->getSubMesh(X)->indexData->indexCount; VertPerSubMesh[X] = SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount; } }else{ vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(0)->vertexData->vertexCount; iCount += myMesh->getSubMesh(0)->indexData->indexCount; } Ogre::Vector3* vertices = new Ogre::Vector3[vCount]; unsigned int* indices = new unsigned int[iCount]; for( unsigned short int SubMeshIndex = 0 ; SubMeshIndex < myMesh->getNumSubMeshes() ; SubMeshIndex++ ) { if( !UseAllSubmeshes && (SubMeshIndex > 0) ) break; if( SharedVerts && (SubMeshIndex > 0) ) break; subMesh = myMesh->getSubMesh(SubMeshIndex); indexData = subMesh->indexData; vertexData = SharedVerts ? myMesh->sharedVertexData : myMesh->getSubMesh(SubMeshIndex)->vertexData; const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vBuffer = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); Ogre::HardwareIndexBufferSharedPtr iBuffer = indexData->indexBuffer; currtriCount=indexData->indexCount/3; triCount+=(indexData->indexCount/3); unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float* pReal = NULL; for( size_t j = 0 ; j < vertexData->vertexCount ; j++, vertex += vBuffer->getVertexSize() ) { posElem->baseVertexPointerToElement(vertex, &pReal); vertices[j + VertPrevSize].x = *pReal++; vertices[j + VertPrevSize].y = *pReal++; vertices[j + VertPrevSize].z = *pReal++; } vBuffer->unlock(); size_t index_offset = 0; use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); if( use32bitindexes ) { for (size_t k = 0; k < currtriCount*3; ++k) { if(SubMeshIndex > 0 && VertPerSubMesh) { indices[index_offset+IndiPrevSize] = pLong[k] + VertPerSubMesh[SubMeshIndex]; }else{ indices[index_offset+IndiPrevSize] = pLong[k]; } index_offset++; } }else{ for( size_t k = 0 ; k < currtriCount * 3 ; ++k ) { if(SubMeshIndex > 0 && VertPerSubMesh) { indices[index_offset+IndiPrevSize] = (static_cast<unsigned long>(pShort[k])) + VertPerSubMesh[SubMeshIndex]; }else{ indices[index_offset+IndiPrevSize] = static_cast<unsigned long>(pShort[k]); } index_offset++; } } iBuffer->unlock(); VertPrevSize += vertexData->vertexCount; IndiPrevSize += indexData->indexCount; } ConvexDecomposition::DecompDesc desc; desc.mVcount = vertexData->vertexCount; desc.mTcount = triCount; desc.mVertices = &vertices[0].x; desc.mIndices = &indices[0]; unsigned int maxv = 16; float skinWidth = 0.0; desc.mDepth = Depth; desc.mCpercent = CPercent; desc.mPpercent = PPercent; desc.mMaxVertices = maxv; desc.mSkinWidth = skinWidth; Internal::MezzConvexDecomposition decomp; desc.mCallback = &decomp; ConvexBuilder cb(desc.mCallback); cb.process(desc); CompoundCollisionShape* compound = new CompoundCollisionShape(Name); btTransform trans; trans.setIdentity(); for (int i=0;i<decomp.m_convexShapes.size();i++) { std::stringstream namestream; namestream << Name << "Child" << i; Vector3 centroid(decomp.m_convexCentroids[i]); ConvexHullCollisionShape* convexShape = new ConvexHullCollisionShape(namestream.str(),decomp.m_convexShapes[i]); compound->AddChildShape(convexShape,centroid); } delete[] vertices; delete[] indices; delete[] VertPerSubMesh; return compound; }
// ------------------------------------------------------------------------- void Vehicle::init(Environment* env) { this->env = env; mSceneMgr = env->getSceneMgr(); mWorld = env->getmWorld(); mWheelsEngineCount = 2; mWheelsEngine[0] = 0; mWheelsEngine[1] = 1; mWheelsEngine[2] = 2; mWheelsEngine[3] = 3; mWheelsSteerableCount = 2; mWheelsSteerable[0] = 0; mWheelsSteerable[1] = 1; mWheelEngineStyle = 0; mWheelSteeringStyle = 0; mSteeringLeft = false; mSteeringRight = false; mEngineForce = 0; mSteering = 0; /// create vehicle { const Ogre::Vector3 chassisShift(0, 1.0, 0); float connectionHeight = 0.7f; mChassis = mSceneMgr->createEntity( "chassis" + StringConverter::toString(mNumEntitiesInstanced++), "chassis.mesh"); SceneNode *node = mSceneMgr->getRootSceneNode ()->createChildSceneNode (); SceneNode *chassisnode = node->createChildSceneNode (); chassisnode->attachObject (mChassis); chassisnode->setPosition (chassisShift); // mChassis->setQueryFlags (GEOMETRY_QUERY_MASK); #if (OGRE_VERSION < ((1 << 16) | (5 << 8) | 0)) // only applicable before shoggoth (1.5.0) mChassis->setNormaliseNormals(true); #endif mChassis->setCastShadows(true); BoxCollisionShape* chassisShape = new BoxCollisionShape(Ogre::Vector3(1.f,0.75f,2.1f)); CompoundCollisionShape* compound = new CompoundCollisionShape(); compound->addChildShape(chassisShape, chassisShift); mCarChassis = new WheeledRigidBody("carChassis", mWorld); //valor de 800 faz referencia a massa do chassis (OgrebulletDynamicsRigidBody.h) 03/09/2011 mCarChassis->setShape (node, compound, 0.6, 0.6, 800, CarPosition, Quaternion::IDENTITY); mCarChassis->setDamping(0.2, 0.2); mCarChassis->disableDeactivation (); mTuning = new VehicleTuning( gSuspensionStiffness, gSuspensionCompression, gSuspensionDamping, gMaxSuspensionTravelCm, gFrictionSlip); mVehicleRayCaster = new VehicleRayCaster(mWorld); mVehicle = new RaycastVehicle(mCarChassis, mTuning, mVehicleRayCaster); { int rightIndex = 0; int upIndex = 1; int forwardIndex = 2; mVehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex); Ogre::Vector3 wheelDirectionCS0(0,-1,0); Ogre::Vector3 wheelAxleCS(-1,0,0); for (size_t i = 0; i < 4; i++) { mWheels[i] = mSceneMgr->createEntity( "wheel" + StringConverter::toString(mNumEntitiesInstanced++), "wheel.mesh"); // mWheels[i]->setQueryFlags (GEOMETRY_QUERY_MASK); #if (OGRE_VERSION < ((1 << 16) | (5 << 8) | 0)) // only applicable before shoggoth (1.5.0) mWheels[i]->setNormaliseNormals(true); #endif mWheels[i]->setCastShadows(true); mWheelNodes[i] = mSceneMgr->getRootSceneNode ()->createChildSceneNode (); mWheelNodes[i]->attachObject (mWheels[i]); } { bool isFrontWheel = true; Ogre::Vector3 connectionPointCS0 ( CUBE_HALF_EXTENTS-(0.3*gWheelWidth), connectionHeight, 2*CUBE_HALF_EXTENTS-gWheelRadius); mVehicle->addWheel( mWheelNodes[0], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); connectionPointCS0 = Ogre::Vector3( -CUBE_HALF_EXTENTS+(0.3*gWheelWidth), connectionHeight, 2*CUBE_HALF_EXTENTS-gWheelRadius); mVehicle->addWheel( mWheelNodes[1], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); connectionPointCS0 = Ogre::Vector3( -CUBE_HALF_EXTENTS+(0.3*gWheelWidth), connectionHeight, -2*CUBE_HALF_EXTENTS+gWheelRadius); isFrontWheel = false; mVehicle->addWheel( mWheelNodes[2], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); connectionPointCS0 = Ogre::Vector3( CUBE_HALF_EXTENTS-(0.3*gWheelWidth), connectionHeight, -2*CUBE_HALF_EXTENTS+gWheelRadius); mVehicle->addWheel( mWheelNodes[3], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); } } } }
// ------------------------------------------------------------------------- void Terrain_Demo::init(Ogre::Root *root, Ogre::RenderWindow *win, OgreBulletApplication *application) { mCameraMove = 1; mHelpKeys.clear(); mHelpKeys.push_back(BASIC_HELP_INFO0); mHelpKeys.push_back(BASIC_HELP_INFO1); mHelpKeys.push_back(BASIC_HELP_INFO2); mHelpKeys.push_back(BASIC_HELP_INFO3); mHelpKeys.push_back(BASIC_HELP_INFO4); mHelpKeys.push_back(BASIC_HELP_INFO5); mHelpKeys.push_back(BASIC_HELP_INFO6); mHelpKeys.push_back("Use Arrow Key to move Car."); // reset for (int i = 0; i < 4; i++) { mWheelsEngine[i] = 0; mWheelsSteerable[i] = 0; } mWheelsEngineCount = 2; mWheelsEngine[0] = 0; mWheelsEngine[1] = 1; mWheelsEngine[2] = 2; mWheelsEngine[3] = 3; mWheelsSteerableCount = 2; mWheelsSteerable[0] = 0; mWheelsSteerable[1] = 1; //mWheelsSteerable[2] = 2; //mWheelsSteerable[3] = 3; mWheelEngineStyle = 0; mWheelSteeringStyle = 0; mSteeringLeft = false; mSteeringRight = false; mEngineForce = 0; mSteering = 0; // ------------------------ // Start OgreScene mSceneMgr = root->createSceneManager("TerrainSceneManager", "BulletTerrain"); mCamera = mSceneMgr->createCamera("Cam"); //mCamera->setFOVy(Degree(90)); mCamera->setNearClipDistance(0.1); mCamera->setFarClipDistance(1000); Viewport *vp = win->addViewport(mCamera); vp->setBackgroundColour(ColourValue(0,0,0)); // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio( Real(vp->getActualWidth()) / Real(vp->getActualHeight())); mCamera->setPosition(CameraStart + terrain_Shift); mCamera->lookAt(CarPosition + terrain_Shift); // Create a terrain std::string terrain_cfg("terrain.cfg"); mSceneMgr->setWorldGeometry(terrain_cfg); OgreBulletListener::init(root, win, application); // ------------------------ // add lights setBasicLight(); // ------------------------ // Add the Gui setPhysicGUI(); // ------------------------ // Start Bullet initWorld(); // ------------------------ // Add the ground // 0.1, 0.8 //addStaticPlane(0.3, 0.8); { Ogre::ConfigFile config; config.loadFromResourceSystem(terrain_cfg, ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, "=", true); unsigned page_size = Ogre::StringConverter::parseUnsignedInt(config.getSetting("PageSize")); Ogre::Vector3 terrainScale(Ogre::StringConverter::parseReal(config.getSetting("PageWorldX")) / (page_size - 1), Ogre::StringConverter::parseReal(config.getSetting("MaxHeight")), Ogre::StringConverter::parseReal(config.getSetting("PageWorldZ")) / (page_size - 1)); Ogre::String terrainfileName = config.getSetting("Heightmap.image"); float *heights = new float[page_size*page_size]; Ogre::Image terrainHeightMap; terrainHeightMap.load(terrainfileName, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); for (unsigned y = 0; y < page_size; ++y) { for (unsigned x = 0; x < page_size; ++x) { Ogre::ColourValue color = terrainHeightMap.getColourAt(x, y, 0); heights[x + y * page_size] = color.r; } } mTerrainShape = new HeightmapCollisionShape(page_size, page_size, terrainScale, heights, true); RigidBody *defaultTerrainBody = new RigidBody("Terrain", mWorld); const float terrainBodyRestitution = 0.1f; const float terrainBodyFriction = 0.8f; Ogre::Vector3 terrainShiftPos( (terrainScale.x * (page_size - 1) / 2), \ 0, (terrainScale.z * (page_size - 1) / 2)); terrainShiftPos.y = terrainScale.y / 2 * terrainScale.y; Ogre::SceneNode* pTerrainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); defaultTerrainBody->setStaticShape (pTerrainNode, mTerrainShape, terrainBodyRestitution, terrainBodyFriction, terrainShiftPos); mBodies.push_back(defaultTerrainBody); mShapes.push_back(mTerrainShape); } // create obstacle in front of car addCube("obstacle", Ogre::Vector3(13, -5.25, -5) + terrain_Shift , Quaternion(Radian(Degree(22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(15, -5.25, -5) + terrain_Shift , Quaternion(Radian(Degree(22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(17, -5.25, -5) + terrain_Shift , Quaternion(Radian(Degree(22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(13, -5.25, -10) + terrain_Shift , Quaternion(Radian(Degree(-22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(15, -5.25, -10) + terrain_Shift , Quaternion(Radian(Degree(-22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(17, -5.25, -10) + terrain_Shift , Quaternion(Radian(Degree(-22.5)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); // create obstacle a bit aside addCube("obstacle", Ogre::Vector3(-2, 0, -5) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(0, 0, -5) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(2, 0, -5) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(-2, 0, -10) + terrain_Shift , Quaternion(Radian(Degree(-45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(0, 0, -10) + terrain_Shift , Quaternion(Radian(Degree(-45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(2, 0, -10) + terrain_Shift , Quaternion(Radian(Degree(-45.0)), Ogre::Vector3::UNIT_X), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); // create obstacle just for fun addCube("obstacle", Ogre::Vector3(25, -10, -25) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_Z), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(25, -10, -27) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_Z), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); addCube("obstacle", Ogre::Vector3(25, -10, -29) + terrain_Shift , Quaternion(Radian(Degree(45.0)), Ogre::Vector3::UNIT_Z), Ogre::Vector3(1, 1, 1), 0.3, 0.8, 0); /// create vehicle { const Ogre::Vector3 chassisShift(0, 1.0, 0); float connectionHeight = 0.7f; mChassis = mSceneMgr->createEntity( "chassis" + StringConverter::toString(mNumEntitiesInstanced++), "chassis.mesh"); SceneNode *node = mSceneMgr->getRootSceneNode ()->createChildSceneNode (); SceneNode *chassisnode = node->createChildSceneNode (); chassisnode->attachObject (mChassis); chassisnode->setPosition (chassisShift); mChassis->setQueryFlags (GEOMETRY_QUERY_MASK); #if (OGRE_VERSION < ((1 << 16) | (5 << 8) | 0)) // only applicable before shoggoth (1.5.0) mChassis->setNormaliseNormals(true); #endif mChassis->setCastShadows(true); CompoundCollisionShape* compound = new CompoundCollisionShape(); BoxCollisionShape* chassisShape = new BoxCollisionShape(Ogre::Vector3(1.f,0.75f,2.1f)); compound->addChildShape(chassisShape, chassisShift); mCarChassis = new WheeledRigidBody("carChassis", mWorld); mCarChassis->setShape(node, compound, 0.6, //restitution 0.6, //friction 800, //bodyMass CarPosition + terrain_Shift, Quaternion::IDENTITY); mCarChassis->setDamping(0.2, 0.2); mCarChassis->disableDeactivation(); mTuning = new VehicleTuning(gSuspensionStiffness, gSuspensionCompression, gSuspensionDamping, gMaxSuspensionTravelCm, gMaxSuspensionForce, gFrictionSlip); mVehicleRayCaster = new VehicleRayCaster(mWorld); mVehicle = new RaycastVehicle(mCarChassis, mTuning, mVehicleRayCaster); { int rightIndex = 0; int upIndex = 1; int forwardIndex = 2; mVehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex); Ogre::Vector3 wheelDirectionCS0(0,-1,0); Ogre::Vector3 wheelAxleCS(-1,0,0); for (size_t i = 0; i < 4; i++) { mWheels[i] = mSceneMgr->createEntity( "wheel" + StringConverter::toString(mNumEntitiesInstanced++), "wheel.mesh"); mWheels[i]->setQueryFlags (GEOMETRY_QUERY_MASK); #if (OGRE_VERSION < ((1 << 16) | (5 << 8) | 0)) // only applicable before shoggoth (1.5.0) mWheels[i]->setNormaliseNormals(true); #endif mWheels[i]->setCastShadows(true); mWheelNodes[i] = mSceneMgr->getRootSceneNode ()->createChildSceneNode (); mWheelNodes[i]->attachObject (mWheels[i]); } { bool isFrontWheel = true; Ogre::Vector3 connectionPointCS0 ( CUBE_HALF_EXTENTS-(0.3*gWheelWidth), connectionHeight, 2*CUBE_HALF_EXTENTS-gWheelRadius); mVehicle->addWheel( mWheelNodes[0], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); connectionPointCS0 = Ogre::Vector3( -CUBE_HALF_EXTENTS+(0.3*gWheelWidth), connectionHeight, 2*CUBE_HALF_EXTENTS-gWheelRadius); mVehicle->addWheel( mWheelNodes[1], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); connectionPointCS0 = Ogre::Vector3( -CUBE_HALF_EXTENTS+(0.3*gWheelWidth), connectionHeight, -2*CUBE_HALF_EXTENTS+gWheelRadius); isFrontWheel = false; mVehicle->addWheel( mWheelNodes[2], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); connectionPointCS0 = Ogre::Vector3( CUBE_HALF_EXTENTS-(0.3*gWheelWidth), connectionHeight, -2*CUBE_HALF_EXTENTS+gWheelRadius); mVehicle->addWheel( mWheelNodes[3], connectionPointCS0, wheelDirectionCS0, wheelAxleCS, gSuspensionRestLength, gWheelRadius, isFrontWheel, gWheelFriction, gRollInfluence); //mVehicle->setWheelsAttached(); } } } }