00001
00008 #include "../ScolPack/SO3Scol.h"
00009 #include "../SO3SceneGraph/SO3Physics.h"
00010 #include "../SO3SceneGraph/SO3Scene.h"
00011 #include "../SO3PhysicGraph/SO3Body.h"
00012 #include "../SO3PhysicGraph/SO3MaterialPair.h"
00013 #include "../SO3PhysicGraph/SO3MaterialID.h"
00014 #include "../SO3Renderer/SO3Root.h"
00015
00016 extern WindowHandle hwndScol;
00017 extern int SO3_BODY_LEAVE_WORLD_MSG;
00018 extern int getMaterialOverlapStartedCallback(mmachine m, int id, MCOLL * result);
00019 extern int getMaterialContactCallback(mmachine m, int id, MCOLL * result);
00020 extern int getMaterialOverlapEndedCallback(mmachine m, int id, MCOLL * result);
00021 extern SMaterialPair* getMaterialPairByWorld(SPhysicWorld* world, int ID1, int ID2);
00022
00023 namespace SO3
00024 {
00025
00026
00027 SPhysicWorld::SPhysicWorld()
00028 {
00029 }
00030
00031 SPhysicWorld::SPhysicWorld(SScene* scene): mscene(scene)
00032 {
00033 initNewtonWorld();
00034 }
00035
00036 SPhysicWorld::~SPhysicWorld()
00037 {
00038 if(worldDebugger)
00039 {
00040 if(worldDebuggerIsInit)
00041 {
00042 worldDebugger->hideDebugInformation();
00043 worldDebugger->deInit();
00044 worldDebuggerIsInit = false;
00045 }
00046 worldDebugger = 0;
00047 }
00048
00049 listOfMaterialID.clear();
00050 listOfPhysicsMaterialPair.clear();
00051
00052 SAFE_DELETE(world);
00053 SAFE_DELETE(worldDebugger);
00054 }
00055
00056 void SPhysicWorld::initNewtonWorld()
00057 {
00058 world = NULL;
00059 showPhysicsLine = false;
00060 mResetPhysicWorld = false;
00061 mGravity = Ogre::Vector3(0.0f, -9.81f, 0.0f);
00062 minWorldSize.x = -500;
00063 minWorldSize.y = -500;
00064 minWorldSize.z = -500;
00065 maxWorldSize.x = 500;
00066 maxWorldSize.y = 500;
00067 maxWorldSize.z = 500;
00068 worldIsEnabled = false;
00069 worldDebugger = 0;
00070 solverModel = 0;
00071 frictionModel = 0;
00072
00073 world = new OgreNewt::World();
00074
00075
00076 world->setWorldSize(minWorldSize,maxWorldSize);
00077
00078 SetPhysicFPS(60);
00079
00080 worldDebugger = &world->getDebugger();
00081 worldDebuggerIsInit = false;
00082
00083
00084 world->setLeaveWorldCallback(boost::bind(&SPhysicWorld::LeaveWorldCallBack, this, _1, _2));
00085 }
00086
00087 OgreNewt::World* SPhysicWorld::GetPhysicWorld(){
00088 return world;
00089 }
00090
00091 bool SPhysicWorld::GetPhysicWorldEnable()
00092 {
00093 return worldIsEnabled;
00094 }
00095
00096 void SPhysicWorld::SetPhysicWorldEnable(bool enable)
00097 {
00098 worldIsEnabled = enable;
00099
00100 if (world && worldDebugger)
00101 {
00102 if (!worldIsEnabled && showPhysicsLine && worldDebuggerIsInit)
00103 {
00104 worldDebugger->hideDebugInformation();
00105
00106 worldDebugger->deInit();
00107 worldDebuggerIsInit = false;
00108 }
00109 else if (worldIsEnabled && showPhysicsLine)
00110 {
00111 SetPhysicDebugEnable(true);
00112 }
00113 }
00114 }
00115
00116 bool SPhysicWorld::GetPhysicDebugEnable()
00117 {
00118 return showPhysicsLine;
00119 }
00120
00121 void SPhysicWorld::SetPhysicDebugEnable(bool enable)
00122 {
00123
00124
00125
00126 if (worldDebugger)
00127 {
00128 if (worldDebuggerIsInit)
00129 {
00130 worldDebugger->hideDebugInformation();
00131
00132
00133 worldDebugger->deInit();
00134 worldDebuggerIsInit = false;
00135 }
00136
00137 showPhysicsLine = enable;
00138
00139
00140 if (showPhysicsLine)
00141 {
00142 worldDebugger->init(const_cast<SScene*>(mscene)->GetOgreScenePointer());
00143 worldDebuggerIsInit = true;
00144 }
00145 }
00146 }
00147
00148 OgreNewt::Debugger* SPhysicWorld::GetPhysicDebugger()
00149 {
00150 return worldDebugger;
00151 }
00152
00153 void SPhysicWorld::ResetPhysicWorld()
00154 {
00155 bool bLastState = GetPhysicWorldEnable();
00156 if (bLastState)
00157 SetPhysicWorldEnable(false);
00158
00159
00160 const BodyPairMap bodyListCopy = bodyPairMap;
00161 BodyPairMap::const_iterator iBodyMap = bodyListCopy.begin();
00162 while (iBodyMap != bodyListCopy.end())
00163 {
00164 free(iBodyMap->second);
00165 bodyPairMap.erase(iBodyMap->first);
00166
00167 iBodyMap++;
00168 }
00169
00170
00171 physicContactMap.clear();
00172 physicContactOverlapStartMap.clear();
00173
00174
00175 SetResetPhysicWorld(true);
00176
00177 SNodeMap::const_iterator iNodeList = mscene->GetNodeList().begin();
00178 while(iNodeList != mscene->GetNodeList().end())
00179 {
00180 SNode* curNode = iNodeList->second;
00181 SBody* curBody = curNode->getSceneNodeBody();
00182
00183 if(curBody!=NULL)
00184 {
00185 curNode->ResetToInitialPRS();
00186 curBody->SetVelocity(Ogre::Vector3::ZERO);
00187 curBody->SetOmega(Ogre::Vector3::ZERO);
00188 curBody->SetTorque(Ogre::Vector3::ZERO);
00189 curBody->SetForce(Ogre::Vector3::ZERO);
00190 curBody->SetConstantForce(Ogre::Vector3::ZERO);
00191 curBody->SetConstantTorque(Ogre::Vector3::ZERO);
00192 curBody->SetGlobalForce(Ogre::Vector3::ZERO);
00193 curNode->UpdateNodeBody(false);
00194 }
00195 iNodeList++;
00196 }
00197
00198 if (bLastState)
00199 SetPhysicWorldEnable(true);
00200 }
00201
00202 void SPhysicWorld::SetPhysicBodiesInitialState()
00203 {
00204 SNodeMap::const_iterator iNodeList = mscene->GetNodeList().begin();
00205 while(iNodeList != mscene->GetNodeList().end())
00206 {
00207 SNode* curNode = iNodeList->second;
00208 SBody* curBody = curNode->getSceneNodeBody();
00209
00210 if(curBody!=NULL)
00211 {
00212 curNode->StoreInitialPRS();
00213 }
00214 iNodeList++;
00215 }
00216 }
00217
00218 void SPhysicWorld::SetPhysicSolverModel(int mod)
00219 {
00220 world->setSolverModel(mod);
00221 solverModel = mod;
00222 }
00223
00224 int SPhysicWorld::GetPhysicSolverModel()
00225 {
00226 return solverModel;
00227 }
00228
00229 void SPhysicWorld::SetPhysicFrictionModel(int mod)
00230 {
00231 world->setFrictionModel(mod);
00232 frictionModel = mod;
00233 }
00234
00235 int SPhysicWorld::GetPhysicFrictionModel()
00236 {
00237 return frictionModel;
00238 }
00239
00240 void SPhysicWorld::SetPhysicPlatformArchitecture(int mod)
00241 {
00242 world->setPlatformArchitecture(mod);
00243 }
00244
00245 int SPhysicWorld::GetPhysicPlatformArchitecture()
00246 {
00247 Ogre::String aname;
00248 return world->getPlatformArchitecture(aname);
00249 }
00250
00251 void SPhysicWorld::SetPhysicGravity(Ogre::Vector3 gravity)
00252 {
00253 mGravity = gravity;
00254 }
00255
00256 Ogre::Vector3 SPhysicWorld::GetPhysicGravity()
00257 {
00258 return mGravity;
00259 }
00260
00261 void SPhysicWorld::SetPhysicFPS(int fps)
00262 {
00263 worldFPS = fps;
00264 if (world != 0)
00265 world->setUpdateFPS(Ogre::Real(fps), 5);
00266 }
00267
00268 int SPhysicWorld::GetPhysicFPS()
00269 {
00270 return worldFPS;
00271 }
00272
00273 bool SPhysicWorld::GetResetPhysicWorld()
00274 {
00275 return mResetPhysicWorld;
00276 }
00277
00278 void SPhysicWorld::SetResetPhysicWorld(bool state)
00279 {
00280 mResetPhysicWorld = state;
00281 }
00282
00283 SBody* SPhysicWorld::PhysicsRayCast(Ogre::Vector3 src, Ogre::Vector3 dir, Ogre::Real maxdist, Ogre::Real &hitdistance, Ogre::Vector3 &hitnormal)
00284 {
00285 OgreNewt::BasicRaycast* ray = new OgreNewt::BasicRaycast(world, src, (src + (dir * maxdist)), true);
00286 OgreNewt::BasicRaycast::BasicRaycastInfo info = ray->getFirstHit();
00287 OgreNewt::Body * body = info.getBody();
00288
00289 SBody* sbody = 0;
00290 if (info.getBody())
00291 {
00292 SNode* node = Ogre::any_cast<SNode*>(body->getUserData());
00293 sbody = node->getSceneNodeBody();
00294
00295 hitdistance = maxdist * info.getDistance();
00296 hitnormal = info.getNormal();
00297 }
00298 delete ray;
00299
00300 return sbody;
00301 }
00302
00303 void SPhysicWorld::SetPhysicWorldSize(Ogre::Vector3 minsize, Ogre::Vector3 maxsize)
00304 {
00305 world->setWorldSize(minsize, maxsize);
00306 }
00307
00308 void SPhysicWorld::GetPhysicWorldSize(Ogre::Vector3 &minsize, Ogre::Vector3 &maxsize)
00309 {
00310 Ogre::AxisAlignedBox box = world->getWorldSize();
00311 minsize = box.getMinimum();
00312 maxsize = box.getMaximum();
00313 }
00314
00315 SMaterialID* SPhysicWorld::CreatePhysicMaterialID(std::string materialIdName)
00316 {
00317 SMaterialID* matid = new SMaterialID(const_cast<SScene*>(mscene), materialIdName);
00318 listOfMaterialID.insert(SMaterialIDMap::value_type(materialIdName, matid));
00319
00320 return matid;
00321 }
00322
00323 void SPhysicWorld::DeletePhysicMaterialID(SMaterialID* matID)
00324 {
00325
00326 SMaterialIDMap::iterator iMaterialIDList = listOfMaterialID.begin();
00327 while (iMaterialIDList != listOfMaterialID.end())
00328 {
00329
00330 SMaterialPair* matPair;
00331 matPair = NULL;
00332 matPair = getMaterialPairByWorld(this, matID->getID(), iMaterialIDList->second->getID());
00333 OBJdelTH(mm, SO3PHYSICSMATERIALPAIR, (int)matPair);
00334
00335 iMaterialIDList++;
00336 }
00337
00338
00339 OgreNewt::Body* curBody = world->getFirstBody();
00340 while(curBody!=NULL)
00341 {
00342 if(curBody->getMaterialGroupID()->getID() == matID->getID())
00343 curBody->setMaterialGroupID(world->getDefaultMaterialID());
00344
00345 curBody = curBody->getNext();
00346 }
00347
00348
00349 SMaterialIDMap::iterator iMaterialIDSearched = listOfMaterialID.find(matID->GetName());
00350 if(iMaterialIDSearched != listOfMaterialID.end())
00351 listOfMaterialID.erase(iMaterialIDSearched);
00352
00353 delete matID;
00354 }
00355
00356 SMaterialPair* SPhysicWorld::CreatePhysicMaterialPair(SMaterialID* mat1, SMaterialID* mat2)
00357 {
00358 SMaterialPair* matpair = new SMaterialPair(const_cast<SScene*>(mscene), mat1, mat2);
00359 listOfPhysicsMaterialPair.insert(matpair);
00360
00361 return matpair;
00362 }
00363
00364 void SPhysicWorld::DeletePhysicMaterialPair(SMaterialPair* matpair)
00365 {
00366 listOfPhysicsMaterialPair.erase(matpair);
00367 delete matpair;
00368 }
00369
00370 void SPhysicWorld::LeaveWorldCallBack(OgreNewt::Body* body, int threadIndex)
00371 {
00372 SNode* nodeScol = Ogre::any_cast<SNode*>(body->getUserData());
00373
00374 if(nodeScol != NULL)
00375 {
00376 SBody* b0 = nodeScol->getSceneNodeBody();
00377 if (b0 != 0)
00378 SendMessage(const_cast<SScene*>(mscene)->GetParent()->GetRootWindowHandle(), SO3_BODY_LEAVE_WORLD_MSG, (int)b0, 0);
00379 }
00380 }
00381
00382 }