Blender V2.61 - r43446

CcdPhysicsEnvironment.cpp

Go to the documentation of this file.
00001 
00004 /*
00005 Bullet Continuous Collision Detection and Physics Library
00006 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00007 
00008 This software is provided 'as-is', without any express or implied warranty.
00009 In no event will the authors be held liable for any damages arising from the use of this software.
00010 Permission is granted to anyone to use this software for any purpose, 
00011 including commercial applications, and to alter it and redistribute it freely, 
00012 subject to the following restrictions:
00013 
00014 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00015 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00016 3. This notice may not be removed or altered from any source distribution.
00017 */
00018 
00019 
00020 
00021 
00022 #include "CcdPhysicsEnvironment.h"
00023 #include "CcdPhysicsController.h"
00024 #include "CcdGraphicController.h"
00025 
00026 #include <algorithm>
00027 #include "btBulletDynamicsCommon.h"
00028 #include "LinearMath/btIDebugDraw.h"
00029 #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
00030 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
00031 #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
00032 #include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
00033 
00034 //profiling/timings
00035 #include "LinearMath/btQuickprof.h"
00036 
00037 
00038 #include "PHY_IMotionState.h"
00039 #include "KX_GameObject.h"
00040 #include "RAS_MeshObject.h"
00041 #include "RAS_Polygon.h"
00042 #include "RAS_TexVert.h"
00043 
00044 #define CCD_CONSTRAINT_DISABLE_LINKED_COLLISION 0x80
00045 
00046 bool useIslands = true;
00047 
00048 #ifdef NEW_BULLET_VEHICLE_SUPPORT
00049 #include "BulletDynamics/Vehicle/btRaycastVehicle.h"
00050 #include "BulletDynamics/Vehicle/btVehicleRaycaster.h"
00051 #include "BulletDynamics/Vehicle/btWheelInfo.h"
00052 #include "PHY_IVehicle.h"
00053 btRaycastVehicle::btVehicleTuning   gTuning;
00054 
00055 #endif //NEW_BULLET_VEHICLE_SUPPORT
00056 #include "LinearMath/btAabbUtil2.h"
00057 #include "MT_Matrix4x4.h"
00058 #include "MT_Vector3.h"
00059 #include "GL/glew.h"
00060 
00061 #ifdef WIN32
00062 void DrawRasterizerLine(const float* from,const float* to,int color);
00063 #endif
00064 
00065 
00066 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
00067 
00068 
00069 #include <stdio.h>
00070 #include <string.h>     // for memset
00071 
00072 #ifdef NEW_BULLET_VEHICLE_SUPPORT
00073 class WrapperVehicle : public PHY_IVehicle
00074 {
00075 
00076     btRaycastVehicle*   m_vehicle;
00077     PHY_IPhysicsController* m_chassis;
00078 
00079 public:
00080 
00081     WrapperVehicle(btRaycastVehicle* vehicle,PHY_IPhysicsController* chassis)
00082         :m_vehicle(vehicle),
00083         m_chassis(chassis)
00084     {
00085     }
00086 
00087     btRaycastVehicle*   GetVehicle()
00088     {
00089         return m_vehicle;
00090     }
00091 
00092     PHY_IPhysicsController* GetChassis()
00093     {
00094         return m_chassis;
00095     }
00096 
00097     virtual void    AddWheel(
00098         PHY_IMotionState*   motionState,
00099         PHY__Vector3    connectionPoint,
00100         PHY__Vector3    downDirection,
00101         PHY__Vector3    axleDirection,
00102         float   suspensionRestLength,
00103         float wheelRadius,
00104         bool hasSteering
00105         )
00106     {
00107         btVector3 connectionPointCS0(connectionPoint[0],connectionPoint[1],connectionPoint[2]);
00108         btVector3 wheelDirectionCS0(downDirection[0],downDirection[1],downDirection[2]);
00109         btVector3 wheelAxle(axleDirection[0],axleDirection[1],axleDirection[2]);
00110 
00111 
00112         btWheelInfo& info = m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxle,
00113             suspensionRestLength,wheelRadius,gTuning,hasSteering);
00114         info.m_clientInfo = motionState;
00115 
00116     }
00117 
00118     void    SyncWheels()
00119     {
00120         int numWheels = GetNumWheels();
00121         int i;
00122         for (i=0;i<numWheels;i++)
00123         {
00124             btWheelInfo& info = m_vehicle->getWheelInfo(i);
00125             PHY_IMotionState* motionState = (PHY_IMotionState*)info.m_clientInfo ;
00126     //      m_vehicle->updateWheelTransformsWS(info,false);
00127             m_vehicle->updateWheelTransform(i,false);
00128             btTransform trans = m_vehicle->getWheelInfo(i).m_worldTransform;
00129             btQuaternion orn = trans.getRotation();
00130             const btVector3& pos = trans.getOrigin();
00131             motionState->setWorldOrientation(orn.x(),orn.y(),orn.z(),orn[3]);
00132             motionState->setWorldPosition(pos.x(),pos.y(),pos.z());
00133 
00134         }
00135     }
00136 
00137     virtual int     GetNumWheels() const
00138     {
00139         return m_vehicle->getNumWheels();
00140     }
00141 
00142     virtual void    GetWheelPosition(int wheelIndex,float& posX,float& posY,float& posZ) const
00143     {
00144         btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
00145         posX = trans.getOrigin().x();
00146         posY = trans.getOrigin().y();
00147         posZ = trans.getOrigin().z();
00148     }
00149     virtual void    GetWheelOrientationQuaternion(int wheelIndex,float& quatX,float& quatY,float& quatZ,float& quatW) const
00150     {
00151         btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
00152         btQuaternion quat = trans.getRotation();
00153         btMatrix3x3 orn2(quat);
00154 
00155         quatX = trans.getRotation().x();
00156         quatY = trans.getRotation().y();
00157         quatZ = trans.getRotation().z();
00158         quatW = trans.getRotation()[3];
00159 
00160 
00161         //printf("test");
00162 
00163 
00164     }
00165 
00166     virtual float   GetWheelRotation(int wheelIndex) const
00167     {
00168         float rotation = 0.f;
00169 
00170         if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
00171         {
00172             btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
00173             rotation = info.m_rotation;
00174         }
00175         return rotation;
00176 
00177     }
00178 
00179 
00180 
00181     virtual int GetUserConstraintId() const
00182     {
00183         return m_vehicle->getUserConstraintId();
00184     }
00185 
00186     virtual int GetUserConstraintType() const
00187     {
00188         return m_vehicle->getUserConstraintType();
00189     }
00190 
00191     virtual void    SetSteeringValue(float steering,int wheelIndex)
00192     {
00193         m_vehicle->setSteeringValue(steering,wheelIndex);
00194     }
00195 
00196     virtual void    ApplyEngineForce(float force,int wheelIndex)
00197     {
00198         m_vehicle->applyEngineForce(force,wheelIndex);
00199     }
00200 
00201     virtual void    ApplyBraking(float braking,int wheelIndex)
00202     {
00203         if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
00204         {
00205             btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
00206             info.m_brake = braking;
00207         }
00208     }
00209 
00210     virtual void    SetWheelFriction(float friction,int wheelIndex)
00211     {
00212         if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
00213         {
00214             btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
00215             info.m_frictionSlip = friction;
00216         }
00217 
00218     }
00219 
00220     virtual void    SetSuspensionStiffness(float suspensionStiffness,int wheelIndex)
00221     {
00222         if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
00223         {
00224             btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
00225             info.m_suspensionStiffness = suspensionStiffness;
00226 
00227         }
00228     }
00229 
00230     virtual void    SetSuspensionDamping(float suspensionDamping,int wheelIndex)
00231     {
00232         if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
00233         {
00234             btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
00235             info.m_wheelsDampingRelaxation = suspensionDamping;
00236         }
00237     }
00238 
00239     virtual void    SetSuspensionCompression(float suspensionCompression,int wheelIndex)
00240     {
00241         if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
00242         {
00243             btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
00244             info.m_wheelsDampingCompression = suspensionCompression;
00245         }
00246     }
00247 
00248 
00249 
00250     virtual void    SetRollInfluence(float rollInfluence,int wheelIndex)
00251     {
00252         if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
00253         {
00254             btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
00255             info.m_rollInfluence = rollInfluence;
00256         }
00257     }
00258 
00259     virtual void    SetCoordinateSystem(int rightIndex,int upIndex,int forwardIndex)
00260     {
00261         m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex);
00262     }
00263 
00264 
00265 
00266 };
00267 #endif //NEW_BULLET_VEHICLE_SUPPORT
00268 
00269 class CcdOverlapFilterCallBack : public btOverlapFilterCallback
00270 {
00271 private:
00272     class CcdPhysicsEnvironment* m_physEnv;
00273 public:
00274     CcdOverlapFilterCallBack(CcdPhysicsEnvironment* env) : 
00275         m_physEnv(env)
00276     {
00277     }
00278     virtual ~CcdOverlapFilterCallBack()
00279     {
00280     }
00281     // return true when pairs need collision
00282     virtual bool    needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const;
00283 };
00284 
00285 
00286 void CcdPhysicsEnvironment::setDebugDrawer(btIDebugDraw* debugDrawer)
00287 {
00288     if (debugDrawer && m_dynamicsWorld)
00289         m_dynamicsWorld->setDebugDrawer(debugDrawer);
00290     m_debugDrawer = debugDrawer;
00291 }
00292 
00293 #if 0
00294 static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVector3& to,const btVector3& color)
00295 {
00296     btVector3 halfExtents = (to-from)* 0.5f;
00297     btVector3 center = (to+from) *0.5f;
00298     int i,j;
00299 
00300     btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
00301     for (i=0;i<4;i++)
00302     {
00303         for (j=0;j<3;j++)
00304         {
00305             pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],        
00306                 edgecoord[2]*halfExtents[2]);
00307             pa+=center;
00308 
00309             int othercoord = j%3;
00310             edgecoord[othercoord]*=-1.f;
00311             pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],    
00312                 edgecoord[2]*halfExtents[2]);
00313             pb+=center;
00314 
00315             debugDrawer->drawLine(pa,pb,color);
00316         }
00317         edgecoord = btVector3(-1.f,-1.f,-1.f);
00318         if (i<3)
00319             edgecoord[i]*=-1.f;
00320     }
00321 }
00322 #endif
00323 
00324 
00325 
00326 
00327 
00328 CcdPhysicsEnvironment::CcdPhysicsEnvironment(bool useDbvtCulling,btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
00329 :m_cullingCache(NULL),
00330 m_cullingTree(NULL),
00331 m_numIterations(10),
00332 m_numTimeSubSteps(1),
00333 m_ccdMode(0),
00334 m_solverType(-1),
00335 m_profileTimings(0),
00336 m_enableSatCollisionDetection(false),
00337 m_solver(NULL),
00338 m_ownPairCache(NULL),
00339 m_filterCallback(NULL),
00340 m_ownDispatcher(NULL),
00341 m_scalingPropagated(false)
00342 {
00343 
00344     for (int i=0;i<PHY_NUM_RESPONSE;i++)
00345     {
00346         m_triggerCallbacks[i] = 0;
00347     }
00348 
00349 //  m_collisionConfiguration = new btDefaultCollisionConfiguration();
00350     m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
00351     //m_collisionConfiguration->setConvexConvexMultipointIterations();
00352 
00353     if (!dispatcher)
00354     {
00355         btCollisionDispatcher* disp = new btCollisionDispatcher(m_collisionConfiguration);
00356         dispatcher = disp;
00357         btGImpactCollisionAlgorithm::registerAlgorithm(disp);
00358         m_ownDispatcher = dispatcher;
00359     }
00360 
00361     //m_broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000),btVector3(1000,1000,1000));
00362     //m_broadphase = new btSimpleBroadphase();
00363     m_broadphase = new btDbvtBroadphase();
00364     // avoid any collision in the culling tree
00365     if (useDbvtCulling) {
00366         m_cullingCache = new btNullPairCache();
00367         m_cullingTree = new btDbvtBroadphase(m_cullingCache);
00368     }
00369 
00370     m_filterCallback = new CcdOverlapFilterCallBack(this);
00371     m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
00372 
00373     setSolverType(1);//issues with quickstep and memory allocations
00374 //  m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
00375     m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
00376     //m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f;
00377     //m_dynamicsWorld->getSolverInfo().m_solverMode=    SOLVER_USE_WARMSTARTING +   SOLVER_USE_2_FRICTION_DIRECTIONS +  SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING;
00378 
00379     m_debugDrawer = 0;
00380     setGravity(0.f,0.f,-9.81f);
00381 }
00382 
00383 void    CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
00384 {
00385     btRigidBody* body = ctrl->GetRigidBody();
00386     btCollisionObject* obj = ctrl->GetCollisionObject();
00387 
00388     //this m_userPointer is just used for triggers, see CallbackTriggers
00389     obj->setUserPointer(ctrl);
00390     if (body)
00391         body->setGravity( m_gravity );
00392 
00393     m_controllers.insert(ctrl);
00394 
00395     if (body)
00396     {
00397         //use explicit group/filter for finer control over collision in bullet => near/radar sensor
00398         m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
00399     } else
00400     {
00401         if (ctrl->GetSoftBody())
00402         {
00403             btSoftBody* softBody = ctrl->GetSoftBody();
00404             m_dynamicsWorld->addSoftBody(softBody);
00405         } else
00406         {
00407             if (obj->getCollisionShape())
00408             {
00409                 m_dynamicsWorld->addCollisionObject(obj,ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
00410             }
00411         }
00412     }
00413     if (obj->isStaticOrKinematicObject())
00414     {
00415         obj->setActivationState(ISLAND_SLEEPING);
00416     }
00417 
00418     assert(obj->getBroadphaseHandle());
00419 }
00420 
00421         
00422 
00423 bool    CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl)
00424 {
00425     //also remove constraint
00426     btRigidBody* body = ctrl->GetRigidBody();
00427     if (body)
00428     {
00429         for (int i=body->getNumConstraintRefs()-1;i>=0;i--)
00430         {
00431             btTypedConstraint* con = body->getConstraintRef(i);
00432             m_dynamicsWorld->removeConstraint(con);
00433             body->removeConstraintRef(con);
00434             //delete con; //might be kept by python KX_ConstraintWrapper
00435         }
00436         m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
00437     } else
00438     {
00439         //if a softbody
00440         if (ctrl->GetSoftBody())
00441         {
00442             m_dynamicsWorld->removeSoftBody(ctrl->GetSoftBody());
00443         } else
00444         {
00445             m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
00446         }
00447     }
00448     if (ctrl->m_registerCount != 0)
00449         printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount);
00450 
00451     //remove it from the triggers
00452     m_triggerControllers.erase(ctrl);
00453 
00454     return (m_controllers.erase(ctrl) != 0);
00455 }
00456 
00457 void    CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask)
00458 {
00459     // this function is used when the collisionning group of a controller is changed
00460     // remove and add the collistioning object
00461     btRigidBody* body = ctrl->GetRigidBody();
00462     btCollisionObject* obj = ctrl->GetCollisionObject();
00463     if (obj)
00464     {
00465         btVector3 inertia(0.0,0.0,0.0);
00466         m_dynamicsWorld->removeCollisionObject(obj);
00467         obj->setCollisionFlags(newCollisionFlags);
00468         if (body)
00469         {
00470             if (newMass)
00471                 body->getCollisionShape()->calculateLocalInertia(newMass, inertia);
00472             body->setMassProps(newMass, inertia);
00473             m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask);
00474         }   
00475         else
00476         {
00477             m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
00478         }
00479     }
00480     // to avoid nasty interaction, we must update the property of the controller as well
00481     ctrl->m_cci.m_mass = newMass;
00482     ctrl->m_cci.m_collisionFilterGroup = newCollisionGroup;
00483     ctrl->m_cci.m_collisionFilterMask = newCollisionMask;
00484     ctrl->m_cci.m_collisionFlags = newCollisionFlags;
00485 }
00486 
00487 void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctrl)
00488 {
00489     if (m_controllers.insert(ctrl).second)
00490     {
00491         btCollisionObject* obj = ctrl->GetCollisionObject();
00492         obj->setUserPointer(ctrl);
00493         // update the position of the object from the user
00494         if (ctrl->GetMotionState()) 
00495         {
00496             btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState());
00497             ctrl->SetCenterOfMassTransform(xform);
00498         }
00499         m_dynamicsWorld->addCollisionObject(obj, 
00500             ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
00501     }
00502 }
00503 
00504 void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ctrl)
00505 {
00506     if (m_controllers.erase(ctrl))
00507     {
00508         btRigidBody* body = ctrl->GetRigidBody();
00509         if (body)
00510         {
00511             m_dynamicsWorld->removeRigidBody(body);
00512         } else
00513         {
00514             if (ctrl->GetSoftBody())
00515             {
00516             } else
00517             {
00518                 m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
00519             }
00520         }
00521     }
00522 }
00523 
00524 void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ctrl)
00525 {
00526     btCollisionObject* obj = ctrl->GetCollisionObject();
00527     if (obj)
00528     {
00529         btBroadphaseProxy* proxy = obj->getBroadphaseHandle();
00530         if (proxy)
00531         {
00532             m_dynamicsWorld->getPairCache()->cleanProxyFromPairs(proxy,m_dynamicsWorld->getDispatcher());
00533         }
00534     }
00535 }
00536 
00537 void CcdPhysicsEnvironment::addCcdGraphicController(CcdGraphicController* ctrl)
00538 {
00539     if (m_cullingTree && !ctrl->getBroadphaseHandle())
00540     {
00541         btVector3   minAabb;
00542         btVector3   maxAabb;
00543         ctrl->getAabb(minAabb, maxAabb);
00544 
00545         ctrl->setBroadphaseHandle(m_cullingTree->createProxy(
00546                 minAabb,
00547                 maxAabb,
00548                 INVALID_SHAPE_PROXYTYPE,    // this parameter is not used
00549                 ctrl,
00550                 0,                          // this object does not collision with anything
00551                 0,
00552                 NULL,                       // dispatcher => this parameter is not used
00553                 0));
00554 
00555         assert(ctrl->getBroadphaseHandle());
00556     }
00557 }
00558 
00559 void CcdPhysicsEnvironment::removeCcdGraphicController(CcdGraphicController* ctrl)
00560 {
00561     if (m_cullingTree)
00562     {
00563         btBroadphaseProxy* bp = ctrl->getBroadphaseHandle();
00564         if (bp)
00565         {
00566             m_cullingTree->destroyProxy(bp,NULL);
00567             ctrl->setBroadphaseHandle(0);
00568         }
00569     }
00570 }
00571 
00572 void    CcdPhysicsEnvironment::beginFrame()
00573 {
00574 
00575 }
00576 
00577 void CcdPhysicsEnvironment::debugDrawWorld()
00578 {
00579     if (m_dynamicsWorld->getDebugDrawer() &&  m_dynamicsWorld->getDebugDrawer()->getDebugMode() >0)
00580             m_dynamicsWorld->debugDrawWorld();
00581 }
00582 
00583 bool    CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval)
00584 {
00585     std::set<CcdPhysicsController*>::iterator it;
00586     int i;
00587 
00588     for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
00589     {
00590         (*it)->SynchronizeMotionStates(timeStep);
00591     }
00592 
00593     float subStep = timeStep / float(m_numTimeSubSteps);
00594     i = m_dynamicsWorld->stepSimulation(interval,25,subStep);//perform always a full simulation step
00595 //uncomment next line to see where Bullet spend its time (printf in console)    
00596 //CProfileManager::dumpAll();
00597 
00598     processFhSprings(curTime,i*subStep);
00599 
00600     for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
00601     {
00602         (*it)->SynchronizeMotionStates(timeStep);
00603     }
00604 
00605     //for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
00606     //{
00607     //  (*it)->SynchronizeMotionStates(timeStep);
00608     //}
00609 
00610     for (i=0;i<m_wrapperVehicles.size();i++)
00611     {
00612         WrapperVehicle* veh = m_wrapperVehicles[i];
00613         veh->SyncWheels();
00614     }
00615 
00616 
00617     CallbackTriggers();
00618 
00619     return true;
00620 }
00621 
00622 class ClosestRayResultCallbackNotMe : public btCollisionWorld::ClosestRayResultCallback
00623 {
00624     btCollisionObject* m_owner;
00625     btCollisionObject* m_parent;
00626 
00627 public:
00628     ClosestRayResultCallbackNotMe(const btVector3& rayFromWorld,const btVector3& rayToWorld,btCollisionObject* owner,btCollisionObject* parent)
00629         :btCollisionWorld::ClosestRayResultCallback(rayFromWorld,rayToWorld),
00630         m_owner(owner),
00631         m_parent(parent)
00632     {
00633         
00634     }
00635 
00636     virtual bool needsCollision(btBroadphaseProxy* proxy0) const
00637     {
00638         //don't collide with self
00639         if (proxy0->m_clientObject == m_owner)
00640             return false;
00641 
00642         if (proxy0->m_clientObject == m_parent)
00643             return false;
00644 
00645         return btCollisionWorld::ClosestRayResultCallback::needsCollision(proxy0);
00646     }
00647 
00648 };
00649 
00650 void    CcdPhysicsEnvironment::processFhSprings(double curTime,float interval)
00651 {
00652     std::set<CcdPhysicsController*>::iterator it;
00653     // dynamic of Fh spring is based on a timestep of 1/60
00654     int numIter = (int)(interval*60.0001f);
00655     
00656     for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
00657     {
00658         CcdPhysicsController* ctrl = (*it);
00659         btRigidBody* body = ctrl->GetRigidBody();
00660 
00661         if (body && (ctrl->getConstructionInfo().m_do_fh || ctrl->getConstructionInfo().m_do_rot_fh))
00662         {
00663             //printf("has Fh or RotFh\n");
00664             //re-implement SM_FhObject.cpp using btCollisionWorld::rayTest and info from ctrl->getConstructionInfo()
00665             //send a ray from {0.0, 0.0, 0.0} towards {0.0, 0.0, -10.0}, in local coordinates
00666             CcdPhysicsController* parentCtrl = ctrl->getParentCtrl();
00667             btRigidBody* parentBody = parentCtrl?parentCtrl->GetRigidBody() : 0;
00668             btRigidBody* cl_object = parentBody ? parentBody : body;
00669 
00670             if (body->isStaticOrKinematicObject())
00671                 continue;
00672 
00673             btVector3 rayDirLocal(0,0,-10);
00674 
00675             //m_dynamicsWorld
00676             //ctrl->GetRigidBody();
00677             btVector3 rayFromWorld = body->getCenterOfMassPosition();
00678             //btVector3 rayToWorld = rayFromWorld + body->getCenterOfMassTransform().getBasis() * rayDirLocal;
00679             //ray always points down the z axis in world space...
00680             btVector3   rayToWorld = rayFromWorld + rayDirLocal;
00681             
00682             ClosestRayResultCallbackNotMe   resultCallback(rayFromWorld,rayToWorld,body,parentBody);
00683 
00684             m_dynamicsWorld->rayTest(rayFromWorld,rayToWorld,resultCallback);
00685             if (resultCallback.hasHit())
00686             {
00687                 //we hit this one: resultCallback.m_collisionObject;
00688                 CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(resultCallback.m_collisionObject->getUserPointer());
00689 
00690                 if (controller)
00691                 {
00692                     if (controller->getConstructionInfo().m_fh_distance < SIMD_EPSILON)
00693                         continue;
00694 
00695                     btRigidBody* hit_object = controller->GetRigidBody();
00696                     if (!hit_object)
00697                         continue;
00698 
00699                     CcdConstructionInfo& hitObjShapeProps = controller->getConstructionInfo();
00700 
00701                     float distance = resultCallback.m_closestHitFraction*rayDirLocal.length()-ctrl->getConstructionInfo().m_radius;
00702                     if (distance >= hitObjShapeProps.m_fh_distance)
00703                         continue;
00704                     
00705                     
00706 
00707                     //btVector3 ray_dir = cl_object->getCenterOfMassTransform().getBasis()* rayDirLocal.normalized();
00708                     btVector3 ray_dir = rayDirLocal.normalized();
00709                     btVector3 normal = resultCallback.m_hitNormalWorld;
00710                     normal.normalize();
00711 
00712                     for (int i=0; i<numIter; i++)
00713                     {
00714                         if (ctrl->getConstructionInfo().m_do_fh) 
00715                         {
00716                             btVector3 lspot = cl_object->getCenterOfMassPosition()
00717                                 + rayDirLocal * resultCallback.m_closestHitFraction;
00718 
00719 
00720                                 
00721 
00722                             lspot -= hit_object->getCenterOfMassPosition();
00723                             btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot);
00724                             btScalar rel_vel_ray = ray_dir.dot(rel_vel);
00725                             btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance; 
00726                             
00727                             btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring;
00728                             btScalar i_damp =   rel_vel_ray * hitObjShapeProps.m_fh_damping;
00729                             
00730                             cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir)); 
00731                             if (hitObjShapeProps.m_fh_normal) 
00732                             {
00733                                 cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir));
00734                             }
00735                             
00736                             btVector3 lateral = rel_vel - rel_vel_ray * ray_dir;
00737                             
00738                             
00739                             if (ctrl->getConstructionInfo().m_do_anisotropic) {
00740                                 //Bullet basis contains no scaling/shear etc.
00741                                 const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis();
00742                                 btVector3 loc_lateral = lateral * lcs;
00743                                 const btVector3& friction_scaling = cl_object->getAnisotropicFriction();
00744                                 loc_lateral *= friction_scaling;
00745                                 lateral = lcs * loc_lateral;
00746                             }
00747 
00748                             btScalar rel_vel_lateral = lateral.length();
00749                             
00750                             if (rel_vel_lateral > SIMD_EPSILON) {
00751                                 btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction();
00752 
00753                                 btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring);
00754                                 
00755                                 btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass();
00756                                 
00757                                 btVector3 friction = (rel_mom_lateral > max_friction) ?
00758                                     -lateral * (max_friction / rel_vel_lateral) :
00759                                     -lateral;
00760                                 
00761                                     cl_object->applyCentralImpulse(friction);
00762                             }
00763                         }
00764 
00765                         
00766                         if (ctrl->getConstructionInfo().m_do_rot_fh) {
00767                             btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2);
00768 
00769                             btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring;
00770                             btVector3 ang_vel = cl_object->getAngularVelocity();
00771                             
00772                             // only rotations that tilt relative to the normal are damped
00773                             ang_vel -= ang_vel.dot(normal) * normal;
00774                             
00775                             btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping;  
00776                             
00777                             cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp));
00778                         }
00779                     }
00780                 }
00781             }
00782         }
00783     }
00784 }
00785 
00786 void        CcdPhysicsEnvironment::setDebugMode(int debugMode)
00787 {
00788     if (m_debugDrawer){
00789         m_debugDrawer->setDebugMode(debugMode);
00790     }
00791 }
00792 
00793 void        CcdPhysicsEnvironment::setNumIterations(int numIter)
00794 {
00795     m_numIterations = numIter;
00796 }
00797 void        CcdPhysicsEnvironment::setDeactivationTime(float dTime)
00798 {
00799     gDeactivationTime = dTime;
00800 }
00801 void        CcdPhysicsEnvironment::setDeactivationLinearTreshold(float linTresh)
00802 {
00803     gLinearSleepingTreshold = linTresh;
00804 }
00805 void        CcdPhysicsEnvironment::setDeactivationAngularTreshold(float angTresh) 
00806 {
00807     gAngularSleepingTreshold = angTresh;
00808 }
00809 
00810 void        CcdPhysicsEnvironment::setContactBreakingTreshold(float contactBreakingTreshold)
00811 {
00812     gContactBreakingThreshold = contactBreakingTreshold;
00813 
00814 }
00815 
00816 
00817 void        CcdPhysicsEnvironment::setCcdMode(int ccdMode)
00818 {
00819     m_ccdMode = ccdMode;
00820 }
00821 
00822 
00823 void        CcdPhysicsEnvironment::setSolverSorConstant(float sor)
00824 {
00825     m_solverInfo.m_sor = sor;
00826 }
00827 
00828 void        CcdPhysicsEnvironment::setSolverTau(float tau)
00829 {
00830     m_solverInfo.m_tau = tau;
00831 }
00832 void        CcdPhysicsEnvironment::setSolverDamping(float damping)
00833 {
00834     m_solverInfo.m_damping = damping;
00835 }
00836 
00837 
00838 void        CcdPhysicsEnvironment::setLinearAirDamping(float damping)
00839 {
00840     //gLinearAirDamping = damping;
00841 }
00842 
00843 void        CcdPhysicsEnvironment::setUseEpa(bool epa)
00844 {
00845     //gUseEpa = epa;
00846 }
00847 
00848 void        CcdPhysicsEnvironment::setSolverType(int solverType)
00849 {
00850 
00851     switch (solverType)
00852     {
00853     case 1:
00854         {
00855             if (m_solverType != solverType)
00856             {
00857 
00858                 m_solver = new btSequentialImpulseConstraintSolver();
00859                 
00860                 
00861                 break;
00862             }
00863         }
00864 
00865     case 0:
00866     default:
00867         if (m_solverType != solverType)
00868         {
00869 //          m_solver = new OdeConstraintSolver();
00870 
00871             break;
00872         }
00873 
00874     };
00875 
00876     m_solverType = solverType ;
00877 }
00878 
00879 
00880 
00881 void        CcdPhysicsEnvironment::getGravity(PHY__Vector3& grav)
00882 {
00883         const btVector3& gravity = m_dynamicsWorld->getGravity();
00884         grav[0] = gravity.getX();
00885         grav[1] = gravity.getY();
00886         grav[2] = gravity.getZ();
00887 }
00888 
00889 
00890 void        CcdPhysicsEnvironment::setGravity(float x,float y,float z)
00891 {
00892     m_gravity = btVector3(x,y,z);
00893     m_dynamicsWorld->setGravity(m_gravity);
00894     m_dynamicsWorld->getWorldInfo().m_gravity.setValue(x,y,z);
00895 }
00896 
00897 
00898 
00899 
00900 static int gConstraintUid = 1;
00901 
00902 //Following the COLLADA physics specification for constraints
00903 int         CcdPhysicsEnvironment::createUniversalD6Constraint(
00904                         class PHY_IPhysicsController* ctrlRef,class PHY_IPhysicsController* ctrlOther,
00905                         btTransform& frameInA,
00906                         btTransform& frameInB,
00907                         const btVector3& linearMinLimits,
00908                         const btVector3& linearMaxLimits,
00909                         const btVector3& angularMinLimits,
00910                         const btVector3& angularMaxLimits,int flags
00911 )
00912 {
00913 
00914     bool disableCollisionBetweenLinkedBodies = (0!=(flags & CCD_CONSTRAINT_DISABLE_LINKED_COLLISION));
00915 
00916     //we could either add some logic to recognize ball-socket and hinge, or let that up to the user
00917     //perhaps some warning or hint that hinge/ball-socket is more efficient?
00918     
00919     
00920     btGeneric6DofConstraint* genericConstraint = 0;
00921     CcdPhysicsController* ctrl0 = (CcdPhysicsController*) ctrlRef;
00922     CcdPhysicsController* ctrl1 = (CcdPhysicsController*) ctrlOther;
00923     
00924     btRigidBody* rb0 = ctrl0->GetRigidBody();
00925     btRigidBody* rb1 = ctrl1->GetRigidBody();
00926 
00927     if (rb1)
00928     {
00929         
00930 
00931         bool useReferenceFrameA = true;
00932         genericConstraint = new btGeneric6DofSpringConstraint(
00933             *rb0,*rb1,
00934             frameInA,frameInB,useReferenceFrameA);
00935         genericConstraint->setLinearLowerLimit(linearMinLimits);
00936         genericConstraint->setLinearUpperLimit(linearMaxLimits);
00937         genericConstraint->setAngularLowerLimit(angularMinLimits);
00938         genericConstraint->setAngularUpperLimit(angularMaxLimits);
00939     } else
00940     {
00941         // TODO: Implement single body case...
00942         //No, we can use a fixed rigidbody in above code, rather than unnecessary duplation of code
00943 
00944     }
00945     
00946     if (genericConstraint)
00947     {
00948     //  m_constraints.push_back(genericConstraint);
00949         m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
00950 
00951         genericConstraint->setUserConstraintId(gConstraintUid++);
00952         genericConstraint->setUserConstraintType(PHY_GENERIC_6DOF_CONSTRAINT);
00953         //64 bit systems can't cast pointer to int. could use size_t instead.
00954         return genericConstraint->getUserConstraintId();
00955     }
00956     return 0;
00957 }
00958 
00959 
00960 
00961 void        CcdPhysicsEnvironment::removeConstraint(int constraintId)
00962 {
00963     
00964     int i;
00965     int numConstraints = m_dynamicsWorld->getNumConstraints();
00966     for (i=0;i<numConstraints;i++)
00967     {
00968         btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
00969         if (constraint->getUserConstraintId() == constraintId)
00970         {
00971             constraint->getRigidBodyA().activate();
00972             constraint->getRigidBodyB().activate();
00973             m_dynamicsWorld->removeConstraint(constraint);
00974             break;
00975         }
00976     }
00977 }
00978 
00979 
00980 struct  FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
00981 {
00982     PHY_IRayCastFilterCallback& m_phyRayFilter;
00983     const btCollisionShape*     m_hitTriangleShape;
00984     int                         m_hitTriangleIndex;
00985 
00986 
00987     FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo)
00988         : btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo),
00989         m_phyRayFilter(phyRayFilter),
00990         m_hitTriangleShape(NULL),
00991         m_hitTriangleIndex(0)
00992     {
00993     }
00994 
00995     virtual ~FilterClosestRayResultCallback()
00996     {
00997     }
00998 
00999     virtual bool needsCollision(btBroadphaseProxy* proxy0) const
01000     {
01001         if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask))
01002             return false;
01003         if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask))
01004             return false;
01005         btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject;
01006         CcdPhysicsController* phyCtrl = static_cast<CcdPhysicsController*>(object->getUserPointer());
01007         if (phyCtrl == m_phyRayFilter.m_ignoreController)
01008             return false;
01009         return m_phyRayFilter.needBroadphaseRayCast(phyCtrl);
01010     }
01011 
01012     virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
01013     {
01014         //CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer());
01015         // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it
01016         if (rayResult.m_localShapeInfo)
01017         {
01018             m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape();
01019             m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex;
01020         } else 
01021         {
01022             m_hitTriangleShape = NULL;
01023             m_hitTriangleIndex = 0;
01024         }
01025         return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace);
01026     }
01027 
01028 };
01029 
01030 static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* shapeInfo, int hitTriangleIndex, btVector3 triangle[])
01031 {
01032     // this code is copied from Bullet 
01033     const unsigned char *vertexbase;
01034     int numverts;
01035     PHY_ScalarType type;
01036     int stride;
01037     const unsigned char *indexbase;
01038     int indexstride;
01039     int numfaces;
01040     PHY_ScalarType indicestype;
01041     btStridingMeshInterface* meshInterface = NULL;
01042     btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape();
01043 
01044     if (triangleShape)
01045         meshInterface = triangleShape->getMeshInterface();
01046     else
01047     {
01048         // other possibility is gImpact
01049         if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
01050             meshInterface = (static_cast<btGImpactMeshShape*>(shape))->getMeshInterface();
01051     }
01052     if (!meshInterface)
01053         return false;
01054 
01055     meshInterface->getLockedReadOnlyVertexIndexBase(
01056         &vertexbase,
01057         numverts,
01058         type,
01059         stride,
01060         &indexbase,
01061         indexstride,
01062         numfaces,
01063         indicestype,
01064         0);
01065 
01066     unsigned int* gfxbase = (unsigned int*)(indexbase+hitTriangleIndex*indexstride);
01067     const btVector3& meshScaling = shape->getLocalScaling();
01068     for (int j=2;j>=0;j--)
01069     {
01070         int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
01071 
01072         btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
01073 
01074         triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());      
01075     }
01076     meshInterface->unLockReadOnlyVertexBase(0);
01077     return true;
01078 }
01079 
01080 PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
01081 {
01082     btVector3 rayFrom(fromX,fromY,fromZ);
01083     btVector3 rayTo(toX,toY,toZ);
01084 
01085     btVector3   hitPointWorld,normalWorld;
01086 
01087     //Either Ray Cast with or without filtering
01088 
01089     //btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo);
01090     FilterClosestRayResultCallback   rayCallback(filterCallback,rayFrom,rayTo);
01091 
01092 
01093     PHY_RayCastResult result;
01094     memset(&result, 0, sizeof(result));
01095 
01096     // don't collision with sensor object
01097     rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
01098     //, ,filterCallback.m_faceNormal);
01099 
01100     m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback);
01101     if (rayCallback.hasHit())
01102     {
01103         CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(rayCallback.m_collisionObject->getUserPointer());
01104         result.m_controller = controller;
01105         result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX();
01106         result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY();
01107         result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ();
01108 
01109         if (rayCallback.m_hitTriangleShape != NULL)
01110         {
01111             // identify the mesh polygon
01112             CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo;
01113             if (shapeInfo)
01114             {
01115                 btCollisionShape* shape = controller->GetCollisionObject()->getCollisionShape();
01116                 if (shape->isCompound())
01117                 {
01118                     btCompoundShape* compoundShape = (btCompoundShape*)shape;
01119                     CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo;
01120                     // need to search which sub-shape has been hit
01121                     for (int i=0; i<compoundShape->getNumChildShapes(); i++)
01122                     {
01123                         shapeInfo = compoundShapeInfo->GetChildShape(i);
01124                         shape=compoundShape->getChildShape(i);
01125                         if (shape == rayCallback.m_hitTriangleShape)
01126                             break;
01127                     }
01128                 }
01129                 if (shape == rayCallback.m_hitTriangleShape && 
01130                     rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size())
01131                 {
01132                     // save original collision shape triangle for soft body
01133                     int hitTriangleIndex = rayCallback.m_hitTriangleIndex;
01134 
01135                     result.m_meshObject = shapeInfo->GetMesh();
01136                     if (shape->isSoftBody())
01137                     {
01138                         // soft body using different face numbering because of randomization
01139                         // hopefully we have stored the original face number in m_tag
01140                         btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject);
01141                         if (softBody->m_faces[hitTriangleIndex].m_tag != 0)
01142                         {
01143                             rayCallback.m_hitTriangleIndex = (int)((uintptr_t)(softBody->m_faces[hitTriangleIndex].m_tag)-1);
01144                         }
01145                     }
01146                     // retrieve the original mesh polygon (in case of quad->tri conversion)
01147                     result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex);
01148                     // hit triangle in world coordinate, for face normal and UV coordinate
01149                     btVector3 triangle[3];
01150                     bool triangleOK = false;
01151                     if (filterCallback.m_faceUV && (3*rayCallback.m_hitTriangleIndex) < shapeInfo->m_triFaceUVcoArray.size())
01152                     {
01153                         // interpolate the UV coordinate of the hit point
01154                         CcdShapeConstructionInfo::UVco* uvCo = &shapeInfo->m_triFaceUVcoArray[3*rayCallback.m_hitTriangleIndex];
01155                         // 1. get the 3 coordinate of the triangle in world space
01156                         btVector3 v1, v2, v3;
01157                         if (shape->isSoftBody())
01158                         {
01159                             // soft body give points directly in world coordinate
01160                             btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject);
01161                             v1 = softBody->m_faces[hitTriangleIndex].m_n[0]->m_x;
01162                             v2 = softBody->m_faces[hitTriangleIndex].m_n[1]->m_x;
01163                             v3 = softBody->m_faces[hitTriangleIndex].m_n[2]->m_x;
01164                         } else 
01165                         {
01166                             // for rigid body we must apply the world transform
01167                             triangleOK = GetHitTriangle(shape, shapeInfo, hitTriangleIndex, triangle);
01168                             if (!triangleOK)
01169                                 // if we cannot get the triangle, no use to continue
01170                                 goto SKIP_UV_NORMAL;
01171                             v1 = rayCallback.m_collisionObject->getWorldTransform()(triangle[0]);
01172                             v2 = rayCallback.m_collisionObject->getWorldTransform()(triangle[1]);
01173                             v3 = rayCallback.m_collisionObject->getWorldTransform()(triangle[2]);
01174                         }
01175                         // 2. compute barycentric coordinate of the hit point
01176                         btVector3 v = v2-v1;
01177                         btVector3 w = v3-v1;
01178                         btVector3 u = v.cross(w);
01179                         btScalar A = u.length();
01180 
01181                         v = v2-rayCallback.m_hitPointWorld;
01182                         w = v3-rayCallback.m_hitPointWorld;
01183                         u = v.cross(w);
01184                         btScalar A1 = u.length();
01185 
01186                         v = rayCallback.m_hitPointWorld-v1;
01187                         w = v3-v1;
01188                         u = v.cross(w);
01189                         btScalar A2 = u.length();
01190 
01191                         btVector3 baryCo;
01192                         baryCo.setX(A1/A);
01193                         baryCo.setY(A2/A);
01194                         baryCo.setZ(1.0f-baryCo.getX()-baryCo.getY());
01195                         // 3. compute UV coordinate
01196                         result.m_hitUV[0] = baryCo.getX()*uvCo[0].uv[0] + baryCo.getY()*uvCo[1].uv[0] + baryCo.getZ()*uvCo[2].uv[0];
01197                         result.m_hitUV[1] = baryCo.getX()*uvCo[0].uv[1] + baryCo.getY()*uvCo[1].uv[1] + baryCo.getZ()*uvCo[2].uv[1];
01198                         result.m_hitUVOK = 1;
01199                     }
01200                         
01201                     // Bullet returns the normal from "outside".
01202                     // If the user requests the real normal, compute it now
01203                     if (filterCallback.m_faceNormal)
01204                     {
01205                         if (shape->isSoftBody()) 
01206                         {
01207                             // we can get the real normal directly from the body
01208                             btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject);
01209                             rayCallback.m_hitNormalWorld = softBody->m_faces[hitTriangleIndex].m_normal;
01210                         } else
01211                         {
01212                             if (!triangleOK)
01213                                 triangleOK = GetHitTriangle(shape, shapeInfo, hitTriangleIndex, triangle);
01214                             if (triangleOK)
01215                             {
01216                                 btVector3 triangleNormal; 
01217                                 triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
01218                                 rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal;
01219                             }
01220                         }
01221                     }
01222                 SKIP_UV_NORMAL:
01223                     ;
01224                 }
01225             }
01226         }
01227         if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON))
01228         {
01229             rayCallback.m_hitNormalWorld.normalize();
01230         } else
01231         {
01232             rayCallback.m_hitNormalWorld.setValue(1,0,0);
01233         }
01234         result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX();
01235         result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY();
01236         result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ();
01237         filterCallback.reportHit(&result);
01238     }   
01239 
01240 
01241     return result.m_controller;
01242 }
01243 
01244 // Handles occlusion culling. 
01245 // The implementation is based on the CDTestFramework
01246 struct OcclusionBuffer
01247 {
01248     struct WriteOCL
01249     {
01250         static inline bool Process(btScalar& q,btScalar v) { if(q<v) q=v;return(false); }
01251         static inline void Occlusion(bool& flag) { flag = true; }
01252     };
01253     struct QueryOCL
01254     {
01255         static inline bool Process(btScalar& q,btScalar v) { return(q<=v); }
01256         static inline void Occlusion(bool& flag) { }
01257     };
01258     btScalar*                       m_buffer;
01259     size_t                          m_bufferSize;
01260     bool                            m_initialized;
01261     bool                            m_occlusion;
01262     int                             m_sizes[2];
01263     btScalar                        m_scales[2];
01264     btScalar                        m_offsets[2];
01265     btScalar                        m_wtc[16];      // world to clip transform
01266     btScalar                        m_mtc[16];      // model to clip transform
01267     // constructor: size=largest dimension of the buffer. 
01268     // Buffer size depends on aspect ratio
01269     OcclusionBuffer()
01270     {
01271         m_initialized=false;
01272         m_occlusion = false;
01273         m_buffer = NULL;
01274         m_bufferSize = 0;
01275     }
01276     // multiplication of column major matrices: m=m1*m2
01277     template<typename T1, typename T2>
01278     void        CMmat4mul(btScalar* m, const T1* m1, const T2* m2)
01279     {
01280         m[ 0] = btScalar(m1[ 0]*m2[ 0]+m1[ 4]*m2[ 1]+m1[ 8]*m2[ 2]+m1[12]*m2[ 3]);
01281         m[ 1] = btScalar(m1[ 1]*m2[ 0]+m1[ 5]*m2[ 1]+m1[ 9]*m2[ 2]+m1[13]*m2[ 3]);
01282         m[ 2] = btScalar(m1[ 2]*m2[ 0]+m1[ 6]*m2[ 1]+m1[10]*m2[ 2]+m1[14]*m2[ 3]);
01283         m[ 3] = btScalar(m1[ 3]*m2[ 0]+m1[ 7]*m2[ 1]+m1[11]*m2[ 2]+m1[15]*m2[ 3]);
01284 
01285         m[ 4] = btScalar(m1[ 0]*m2[ 4]+m1[ 4]*m2[ 5]+m1[ 8]*m2[ 6]+m1[12]*m2[ 7]);
01286         m[ 5] = btScalar(m1[ 1]*m2[ 4]+m1[ 5]*m2[ 5]+m1[ 9]*m2[ 6]+m1[13]*m2[ 7]);
01287         m[ 6] = btScalar(m1[ 2]*m2[ 4]+m1[ 6]*m2[ 5]+m1[10]*m2[ 6]+m1[14]*m2[ 7]);
01288         m[ 7] = btScalar(m1[ 3]*m2[ 4]+m1[ 7]*m2[ 5]+m1[11]*m2[ 6]+m1[15]*m2[ 7]);
01289 
01290         m[ 8] = btScalar(m1[ 0]*m2[ 8]+m1[ 4]*m2[ 9]+m1[ 8]*m2[10]+m1[12]*m2[11]);
01291         m[ 9] = btScalar(m1[ 1]*m2[ 8]+m1[ 5]*m2[ 9]+m1[ 9]*m2[10]+m1[13]*m2[11]);
01292         m[10] = btScalar(m1[ 2]*m2[ 8]+m1[ 6]*m2[ 9]+m1[10]*m2[10]+m1[14]*m2[11]);
01293         m[11] = btScalar(m1[ 3]*m2[ 8]+m1[ 7]*m2[ 9]+m1[11]*m2[10]+m1[15]*m2[11]);
01294 
01295         m[12] = btScalar(m1[ 0]*m2[12]+m1[ 4]*m2[13]+m1[ 8]*m2[14]+m1[12]*m2[15]);
01296         m[13] = btScalar(m1[ 1]*m2[12]+m1[ 5]*m2[13]+m1[ 9]*m2[14]+m1[13]*m2[15]);
01297         m[14] = btScalar(m1[ 2]*m2[12]+m1[ 6]*m2[13]+m1[10]*m2[14]+m1[14]*m2[15]);
01298         m[15] = btScalar(m1[ 3]*m2[12]+m1[ 7]*m2[13]+m1[11]*m2[14]+m1[15]*m2[15]);
01299     }
01300     void        setup(int size)
01301     {
01302         m_initialized=false;
01303         m_occlusion=false;
01304         // compute the size of the buffer
01305         GLint       v[4];
01306         GLdouble    m[16],p[16];
01307         int         maxsize;
01308         double      ratio;
01309         glGetIntegerv(GL_VIEWPORT,v);
01310         maxsize = (v[2] > v[3]) ? v[2] : v[3];
01311         assert(maxsize > 0);
01312         ratio = 1.0/(2*maxsize);
01313         // ensure even number
01314         m_sizes[0] = 2*((int)(size*v[2]*ratio+0.5));
01315         m_sizes[1] = 2*((int)(size*v[3]*ratio+0.5));
01316         m_scales[0]=btScalar(m_sizes[0]/2);
01317         m_scales[1]=btScalar(m_sizes[1]/2);
01318         m_offsets[0]=m_scales[0]+0.5f;
01319         m_offsets[1]=m_scales[1]+0.5f;
01320         // prepare matrix
01321         // at this time of the rendering, the modelview matrix is the 
01322         // world to camera transformation and the projection matrix is
01323         // camera to clip transformation. combine both so that 
01324         glGetDoublev(GL_MODELVIEW_MATRIX,m);
01325         glGetDoublev(GL_PROJECTION_MATRIX,p);
01326         CMmat4mul(m_wtc,p,m);
01327     }
01328     void        initialize()
01329     {
01330         size_t newsize = (m_sizes[0]*m_sizes[1])*sizeof(btScalar);
01331         if (m_buffer)
01332         {
01333             // see if we can reuse
01334             if (newsize > m_bufferSize)
01335             {
01336                 free(m_buffer);
01337                 m_buffer = NULL;
01338                 m_bufferSize = 0;
01339             }
01340         }
01341         if (!m_buffer)
01342         {
01343             m_buffer = (btScalar*)calloc(1, newsize);
01344             m_bufferSize = newsize;
01345         } else
01346         {
01347             // buffer exists already, just clears it
01348             memset(m_buffer, 0, newsize);
01349         }
01350         // memory allocate must succeed
01351         assert(m_buffer != NULL);
01352         m_initialized = true;
01353         m_occlusion = false;
01354     }
01355     void        SetModelMatrix(double *fl)
01356     {
01357         CMmat4mul(m_mtc,m_wtc,fl);
01358         if (!m_initialized)
01359             initialize();
01360     }
01361 
01362     // transform a segment in world coordinate to clip coordinate
01363     void        transformW(const btVector3& x, btVector4& t)
01364     {
01365         t[0]    =   x[0]*m_wtc[0]+x[1]*m_wtc[4]+x[2]*m_wtc[8]+m_wtc[12];
01366         t[1]    =   x[0]*m_wtc[1]+x[1]*m_wtc[5]+x[2]*m_wtc[9]+m_wtc[13];
01367         t[2]    =   x[0]*m_wtc[2]+x[1]*m_wtc[6]+x[2]*m_wtc[10]+m_wtc[14];
01368         t[3]    =   x[0]*m_wtc[3]+x[1]*m_wtc[7]+x[2]*m_wtc[11]+m_wtc[15];
01369     }
01370     void        transformM(const float* x, btVector4& t)
01371     {
01372         t[0]    =   x[0]*m_mtc[0]+x[1]*m_mtc[4]+x[2]*m_mtc[8]+m_mtc[12];
01373         t[1]    =   x[0]*m_mtc[1]+x[1]*m_mtc[5]+x[2]*m_mtc[9]+m_mtc[13];
01374         t[2]    =   x[0]*m_mtc[2]+x[1]*m_mtc[6]+x[2]*m_mtc[10]+m_mtc[14];
01375         t[3]    =   x[0]*m_mtc[3]+x[1]*m_mtc[7]+x[2]*m_mtc[11]+m_mtc[15];
01376     }
01377     // convert polygon to device coordinates
01378     static bool project(btVector4* p,int n)
01379     {
01380         for(int i=0;i<n;++i)
01381         {           
01382             p[i][2]=1/p[i][3];
01383             p[i][0]*=p[i][2];
01384             p[i][1]*=p[i][2];
01385         }
01386         return(true);
01387     }
01388     // pi: closed polygon in clip coordinate, NP = number of segments
01389     // po: same polygon with clipped segments removed
01390     template <const int NP>
01391     static int  clip(const btVector4* pi,btVector4* po)
01392     {
01393         btScalar    s[2*NP];
01394         btVector4   pn[2*NP];
01395         int         i, j, m, n, ni;
01396         // deal with near clipping
01397         for(i=0, m=0;i<NP;++i)
01398         {
01399             s[i]=pi[i][2]+pi[i][3];
01400             if(s[i]<0) m+=1<<i;
01401         }
01402         if(m==((1<<NP)-1)) 
01403             return(0);
01404         if(m!=0)
01405         {
01406             for(i=NP-1,j=0,n=0;j<NP;i=j++)
01407             {
01408                 const btVector4&    a=pi[i];
01409                 const btVector4&    b=pi[j];
01410                 const btScalar      t=s[i]/(a[3]+a[2]-b[3]-b[2]);
01411                 if((t>0)&&(t<1))
01412                 {
01413                     pn[n][0]    =   a[0]+(b[0]-a[0])*t;
01414                     pn[n][1]    =   a[1]+(b[1]-a[1])*t;
01415                     pn[n][2]    =   a[2]+(b[2]-a[2])*t;
01416                     pn[n][3]    =   a[3]+(b[3]-a[3])*t;
01417                     ++n;
01418                 }
01419                 if(s[j]>0) pn[n++]=b;
01420             }
01421             // ready to test far clipping, start from the modified polygon
01422             pi = pn;
01423             ni = n;
01424         } else
01425         {
01426             // no clipping on the near plane, keep same vector
01427             ni = NP;
01428         }
01429         // now deal with far clipping
01430         for(i=0, m=0;i<ni;++i)
01431         {
01432             s[i]=pi[i][2]-pi[i][3];
01433             if(s[i]>0) m+=1<<i;
01434         }
01435         if(m==((1<<ni)-1)) 
01436             return(0);
01437         if(m!=0)
01438         {
01439             for(i=ni-1,j=0,n=0;j<ni;i=j++)
01440             {
01441                 const btVector4&    a=pi[i];
01442                 const btVector4&    b=pi[j];
01443                 const btScalar      t=s[i]/(a[2]-a[3]-b[2]+b[3]);
01444                 if((t>0)&&(t<1))
01445                 {
01446                     po[n][0]    =   a[0]+(b[0]-a[0])*t;
01447                     po[n][1]    =   a[1]+(b[1]-a[1])*t;
01448                     po[n][2]    =   a[2]+(b[2]-a[2])*t;
01449                     po[n][3]    =   a[3]+(b[3]-a[3])*t;
01450                     ++n;
01451                 }
01452                 if(s[j]<0) po[n++]=b;
01453             }
01454             return(n);
01455         }
01456         for(int i=0;i<ni;++i) po[i]=pi[i];
01457         return(ni);
01458     }
01459     // write or check a triangle to buffer. a,b,c in device coordinates (-1,+1)
01460     template <typename POLICY>
01461     inline bool draw(   const btVector4& a,
01462                         const btVector4& b,
01463                         const btVector4& c,
01464                         const float face,
01465                         const btScalar minarea)
01466     {
01467         const btScalar      a2=btCross(b-a,c-a)[2];
01468         if((face*a2)<0.f || btFabs(a2)<minarea)
01469             return false;
01470         // further down we are normally going to write to the Zbuffer, mark it so
01471         POLICY::Occlusion(m_occlusion);
01472 
01473         int x[3], y[3], ib=1, ic=2;
01474         btScalar z[3];
01475         x[0]=(int)(a.x()*m_scales[0]+m_offsets[0]);
01476         y[0]=(int)(a.y()*m_scales[1]+m_offsets[1]);
01477         z[0]=a.z();
01478         if (a2 < 0.f)
01479         {
01480             // negative aire is possible with double face => must
01481             // change the order of b and c otherwise the algorithm doesn't work
01482             ib=2;
01483             ic=1;
01484         }
01485         x[ib]=(int)(b.x()*m_scales[0]+m_offsets[0]);
01486         x[ic]=(int)(c.x()*m_scales[0]+m_offsets[0]);
01487         y[ib]=(int)(b.y()*m_scales[1]+m_offsets[1]);
01488         y[ic]=(int)(c.y()*m_scales[1]+m_offsets[1]);
01489         z[ib]=b.z();
01490         z[ic]=c.z();
01491         const int       mix=btMax(0,btMin(x[0],btMin(x[1],x[2])));
01492         const int       mxx=btMin(m_sizes[0],1+btMax(x[0],btMax(x[1],x[2])));
01493         const int       miy=btMax(0,btMin(y[0],btMin(y[1],y[2])));
01494         const int       mxy=btMin(m_sizes[1],1+btMax(y[0],btMax(y[1],y[2])));
01495         const int       width=mxx-mix;
01496         const int       height=mxy-miy;
01497         if ((width*height) <= 1)
01498         {
01499             // degenerated in at most one single pixel
01500             btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
01501             // use for loop to detect the case where width or height == 0
01502             for(int iy=miy;iy<mxy;++iy)
01503             {
01504                 for(int ix=mix;ix<mxx;++ix)
01505                 {
01506                     if(POLICY::Process(*scan,z[0])) 
01507                         return(true);
01508                     if(POLICY::Process(*scan,z[1])) 
01509                         return(true);
01510                     if(POLICY::Process(*scan,z[2])) 
01511                         return(true);
01512                 }
01513             }
01514         } else if (width == 1) 
01515         {
01516             // Degenerated in at least 2 vertical lines
01517             // The algorithm below doesn't work when face has a single pixel width
01518             // We cannot use general formulas because the plane is degenerated. 
01519             // We have to interpolate along the 3 edges that overlaps and process each pixel.
01520             // sort the y coord to make formula simpler
01521             int ytmp;
01522             btScalar ztmp;
01523             if (y[0] > y[1]) { ytmp=y[1];y[1]=y[0];y[0]=ytmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; }
01524             if (y[0] > y[2]) { ytmp=y[2];y[2]=y[0];y[0]=ytmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; }
01525             if (y[1] > y[2]) { ytmp=y[2];y[2]=y[1];y[1]=ytmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; }
01526             int dy[]={  y[0]-y[1],
01527                         y[1]-y[2],
01528                         y[2]-y[0]};
01529             btScalar dzy[3];
01530             dzy[0] = (dy[0]) ? (z[0]-z[1])/dy[0] : btScalar(0.f);
01531             dzy[1] = (dy[1]) ? (z[1]-z[2])/dy[1] : btScalar(0.f);
01532             dzy[2] = (dy[2]) ? (z[2]-z[0])/dy[2] : btScalar(0.f);
01533             btScalar v[3] = {   dzy[0]*(miy-y[0])+z[0],
01534                                 dzy[1]*(miy-y[1])+z[1],
01535                                 dzy[2]*(miy-y[2])+z[2] };
01536             dy[0] = y[1]-y[0];
01537             dy[1] = y[0]-y[1];
01538             dy[2] = y[2]-y[0];
01539             btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
01540             for(int iy=miy;iy<mxy;++iy)
01541             {
01542                 if(dy[0] >= 0 && POLICY::Process(*scan,v[0])) 
01543                     return(true);
01544                 if(dy[1] >= 0 && POLICY::Process(*scan,v[1])) 
01545                     return(true);
01546                 if(dy[2] >= 0 && POLICY::Process(*scan,v[2])) 
01547                     return(true);
01548                 scan+=m_sizes[0];
01549                 v[0] += dzy[0]; v[1] += dzy[1]; v[2] += dzy[2];
01550                 dy[0]--; dy[1]++, dy[2]--;
01551             }
01552         } else if (height == 1)
01553         {
01554             // Degenerated in at least 2 horizontal lines
01555             // The algorithm below doesn't work when face has a single pixel width
01556             // We cannot use general formulas because the plane is degenerated. 
01557             // We have to interpolate along the 3 edges that overlaps and process each pixel.
01558             int xtmp;
01559             btScalar ztmp;
01560             if (x[0] > x[1]) { xtmp=x[1];x[1]=x[0];x[0]=xtmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; }
01561             if (x[0] > x[2]) { xtmp=x[2];x[2]=x[0];x[0]=xtmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; }
01562             if (x[1] > x[2]) { xtmp=x[2];x[2]=x[1];x[1]=xtmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; }
01563             int dx[]={  x[0]-x[1],
01564                         x[1]-x[2],
01565                         x[2]-x[0]};
01566             btScalar dzx[3];
01567             dzx[0] = (dx[0]) ? (z[0]-z[1])/dx[0] : btScalar(0.f);
01568             dzx[1] = (dx[1]) ? (z[1]-z[2])/dx[1] : btScalar(0.f);
01569             dzx[2] = (dx[2]) ? (z[2]-z[0])/dx[2] : btScalar(0.f);
01570             btScalar v[3] = { dzx[0]*(mix-x[0])+z[0],
01571                               dzx[1]*(mix-x[1])+z[1],
01572                               dzx[2]*(mix-x[2])+z[2] };
01573             dx[0] = x[1]-x[0];
01574             dx[1] = x[0]-x[1];
01575             dx[2] = x[2]-x[0];
01576             btScalar* scan=&m_buffer[miy*m_sizes[0]+mix];
01577             for(int ix=mix;ix<mxx;++ix)
01578             {
01579                 if(dx[0] >= 0 && POLICY::Process(*scan,v[0])) 
01580                     return(true);
01581                 if(dx[1] >= 0 && POLICY::Process(*scan,v[1])) 
01582                     return(true);
01583                 if(dx[2] >= 0 && POLICY::Process(*scan,v[2])) 
01584                     return(true);
01585                 scan++;
01586                 v[0] += dzx[0]; v[1] += dzx[1]; v[2] += dzx[2];
01587                 dx[0]--; dx[1]++, dx[2]--;
01588             }
01589         } else
01590         {
01591             // general case
01592             const int       dx[]={  y[0]-y[1],
01593                                     y[1]-y[2],
01594                                     y[2]-y[0]};
01595             const int       dy[]={  x[1]-x[0]-dx[0]*width,
01596                                     x[2]-x[1]-dx[1]*width,
01597                                     x[0]-x[2]-dx[2]*width};
01598             const int       a=x[2]*y[0]+x[0]*y[1]-x[2]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0];
01599             const btScalar  ia=1/(btScalar)a;
01600             const btScalar  dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1]));
01601             const btScalar  dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width);        
01602             int             c[]={   miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0],
01603                                     miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1],
01604                                     miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]};
01605             btScalar        v=ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2]));
01606             btScalar*       scan=&m_buffer[miy*m_sizes[0]];
01607             for(int iy=miy;iy<mxy;++iy)
01608             {
01609                 for(int ix=mix;ix<mxx;++ix)
01610                 {
01611                     if((c[0]>=0)&&(c[1]>=0)&&(c[2]>=0))
01612                     {
01613                         if(POLICY::Process(scan[ix],v)) 
01614                             return(true);
01615                     }
01616                     c[0]+=dx[0];c[1]+=dx[1];c[2]+=dx[2];v+=dzx;
01617                 }
01618                 c[0]+=dy[0];c[1]+=dy[1];c[2]+=dy[2];v+=dzy;
01619                 scan+=m_sizes[0];
01620             }
01621         }
01622         return(false);
01623     }
01624     // clip than write or check a polygon 
01625     template <const int NP,typename POLICY>
01626     inline bool clipDraw(   const btVector4* p,
01627                             const float face,
01628                             btScalar minarea)
01629     {
01630         btVector4   o[NP*2];
01631         int         n=clip<NP>(p,o);
01632         bool        earlyexit=false;
01633         if (n)
01634         {
01635             project(o,n);
01636             for(int i=2;i<n && !earlyexit;++i)
01637             {
01638                 earlyexit|=draw<POLICY>(o[0],o[i-1],o[i],face,minarea);
01639             }
01640         }
01641         return(earlyexit);
01642     }
01643     // add a triangle (in model coordinate)
01644     // face =  0.f if face is double side, 
01645     //      =  1.f if face is single sided and scale is positive
01646     //      = -1.f if face is single sided and scale is negative
01647     void        appendOccluderM(const float* a,
01648                                 const float* b,
01649                                 const float* c,
01650                                 const float face)
01651     {
01652         btVector4   p[3];
01653         transformM(a,p[0]);
01654         transformM(b,p[1]);
01655         transformM(c,p[2]);
01656         clipDraw<3,WriteOCL>(p,face,btScalar(0.f));
01657     }
01658     // add a quad (in model coordinate)
01659     void        appendOccluderM(const float* a,
01660                                 const float* b,
01661                                 const float* c,
01662                                 const float* d,
01663                                 const float face)
01664     {   
01665         btVector4   p[4];
01666         transformM(a,p[0]);
01667         transformM(b,p[1]);
01668         transformM(c,p[2]);
01669         transformM(d,p[3]);
01670         clipDraw<4,WriteOCL>(p,face,btScalar(0.f));
01671     }
01672     // query occluder for a box (c=center, e=extend) in world coordinate
01673     inline bool queryOccluderW( const btVector3& c,
01674                                 const btVector3& e)
01675     {
01676         if (!m_occlusion)
01677             // no occlusion yet, no need to check
01678             return true;
01679         btVector4   x[8];
01680         transformW(btVector3(c[0]-e[0],c[1]-e[1],c[2]-e[2]),x[0]);
01681         transformW(btVector3(c[0]+e[0],c[1]-e[1],c[2]-e[2]),x[1]);
01682         transformW(btVector3(c[0]+e[0],c[1]+e[1],c[2]-e[2]),x[2]);
01683         transformW(btVector3(c[0]-e[0],c[1]+e[1],c[2]-e[2]),x[3]);
01684         transformW(btVector3(c[0]-e[0],c[1]-e[1],c[2]+e[2]),x[4]);
01685         transformW(btVector3(c[0]+e[0],c[1]-e[1],c[2]+e[2]),x[5]);
01686         transformW(btVector3(c[0]+e[0],c[1]+e[1],c[2]+e[2]),x[6]);
01687         transformW(btVector3(c[0]-e[0],c[1]+e[1],c[2]+e[2]),x[7]);
01688         for(int i=0;i<8;++i)
01689         {
01690             // the box is clipped, it's probably a large box, don't waste our time to check
01691             if((x[i][2]+x[i][3])<=0) return(true);
01692         }
01693         static const int    d[]={   1,0,3,2,
01694                                     4,5,6,7,
01695                                     4,7,3,0,
01696                                     6,5,1,2,
01697                                     7,6,2,3,
01698                                     5,4,0,1};
01699         for(unsigned int i=0;i<(sizeof(d)/sizeof(d[0]));)
01700         {
01701             const btVector4 p[]={   x[d[i++]],
01702                                     x[d[i++]],
01703                                     x[d[i++]],
01704                                     x[d[i++]]};
01705             if(clipDraw<4,QueryOCL>(p,1.f,0.f)) 
01706                 return(true);
01707         }
01708         return(false);
01709     }
01710 };
01711 
01712 
01713 struct  DbvtCullingCallback : btDbvt::ICollide
01714 {
01715     PHY_CullingCallback m_clientCallback;
01716     void* m_userData;
01717     OcclusionBuffer *m_ocb;
01718 
01719     DbvtCullingCallback(PHY_CullingCallback clientCallback, void* userData)
01720     {
01721         m_clientCallback = clientCallback;
01722         m_userData = userData;
01723         m_ocb = NULL;
01724     }
01725     bool Descent(const btDbvtNode* node)
01726     {
01727         return(m_ocb->queryOccluderW(node->volume.Center(),node->volume.Extents()));
01728     }
01729     void Process(const btDbvtNode* node,btScalar depth)
01730     {
01731         Process(node);
01732     }
01733     void Process(const btDbvtNode* leaf)
01734     {   
01735         btBroadphaseProxy*  proxy=(btBroadphaseProxy*)leaf->data;
01736         // the client object is a graphic controller
01737         CcdGraphicController* ctrl = static_cast<CcdGraphicController*>(proxy->m_clientObject);
01738         KX_ClientObjectInfo* info = (KX_ClientObjectInfo*)ctrl->getNewClientInfo();
01739         if (m_ocb)
01740         {
01741             // means we are doing occlusion culling. Check if this object is an occluders
01742             KX_GameObject* gameobj = KX_GameObject::GetClientObject(info);
01743             if (gameobj && gameobj->GetOccluder())
01744             {
01745                 double* fl = gameobj->GetOpenGLMatrixPtr()->getPointer();
01746                 // this will create the occlusion buffer if not already done
01747                 // and compute the transformation from model local space to clip space
01748                 m_ocb->SetModelMatrix(fl);
01749                 float face = (gameobj->IsNegativeScaling()) ? -1.0f : 1.0f;
01750                 // walk through the meshes and for each add to buffer
01751                 for (int i=0; i<gameobj->GetMeshCount(); i++)
01752                 {
01753                     RAS_MeshObject* meshobj = gameobj->GetMesh(i);
01754                     const float *v1, *v2, *v3, *v4;
01755 
01756                     int polycount = meshobj->NumPolygons();
01757                     for (int j=0; j<polycount; j++)
01758                     {
01759                         RAS_Polygon* poly = meshobj->GetPolygon(j);
01760                         switch (poly->VertexCount())
01761                         {
01762                         case 3:
01763                             v1 = poly->GetVertex(0)->getXYZ();
01764                             v2 = poly->GetVertex(1)->getXYZ();
01765                             v3 = poly->GetVertex(2)->getXYZ();
01766                             m_ocb->appendOccluderM(v1,v2,v3,((poly->IsTwoside())?0.f:face));
01767                             break;
01768                         case 4:
01769                             v1 = poly->GetVertex(0)->getXYZ();
01770                             v2 = poly->GetVertex(1)->getXYZ();
01771                             v3 = poly->GetVertex(2)->getXYZ();
01772                             v4 = poly->GetVertex(3)->getXYZ();
01773                             m_ocb->appendOccluderM(v1,v2,v3,v4,((poly->IsTwoside())?0.f:face));
01774                             break;
01775                         }
01776                     }
01777                 }
01778             }
01779         }
01780         if (info)
01781             (*m_clientCallback)(info, m_userData);
01782     }
01783 };
01784 
01785 static OcclusionBuffer gOcb;
01786 bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes)
01787 {
01788     if (!m_cullingTree)
01789         return false;
01790     DbvtCullingCallback dispatcher(callback, userData);
01791     btVector3 planes_n[6];
01792     btScalar planes_o[6];
01793     if (nplanes > 6)
01794         nplanes = 6;
01795     for (int i=0; i<nplanes; i++)
01796     {
01797         planes_n[i].setValue(planes[i][0], planes[i][1], planes[i][2]);
01798         planes_o[i] = planes[i][3];
01799     }
01800     // if occlusionRes != 0 => occlusion culling
01801     if (occlusionRes)
01802     {
01803         gOcb.setup(occlusionRes);
01804         dispatcher.m_ocb = &gOcb;
01805         // occlusion culling, the direction of the view is taken from the first plan which MUST be the near plane
01806         btDbvt::collideOCL(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);
01807         btDbvt::collideOCL(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher);       
01808     }else 
01809     {
01810         btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher);
01811         btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);      
01812     }
01813     return true;
01814 }
01815 
01816 int CcdPhysicsEnvironment::getNumContactPoints()
01817 {
01818     return 0;
01819 }
01820 
01821 void CcdPhysicsEnvironment::getContactPoint(int i,float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
01822 {
01823 
01824 }
01825 
01826 
01827 
01828 
01829 btBroadphaseInterface*  CcdPhysicsEnvironment::getBroadphase()
01830 { 
01831     return m_dynamicsWorld->getBroadphase(); 
01832 }
01833 
01834 btDispatcher*   CcdPhysicsEnvironment::getDispatcher()
01835 { 
01836     return m_dynamicsWorld->getDispatcher();
01837 }
01838 
01839 void CcdPhysicsEnvironment::MergeEnvironment(CcdPhysicsEnvironment *other)
01840 {
01841     std::set<CcdPhysicsController*>::iterator it;
01842 
01843     while (other->m_controllers.begin() != other->m_controllers.end())
01844     {
01845         it= other->m_controllers.begin();
01846         CcdPhysicsController* ctrl= (*it);
01847 
01848         other->removeCcdPhysicsController(ctrl);
01849         this->addCcdPhysicsController(ctrl);
01850     }
01851 }
01852 
01853 CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
01854 {
01855 
01856 #ifdef NEW_BULLET_VEHICLE_SUPPORT
01857     m_wrapperVehicles.clear();
01858 #endif //NEW_BULLET_VEHICLE_SUPPORT
01859 
01860     //m_broadphase->DestroyScene();
01861     //delete broadphase ? release reference on broadphase ?
01862 
01863     //first delete scene, then dispatcher, because pairs have to release manifolds on the dispatcher
01864     //delete m_dispatcher;
01865     delete m_dynamicsWorld;
01866     
01867 
01868     if (NULL != m_ownPairCache)
01869         delete m_ownPairCache;
01870 
01871     if (NULL != m_ownDispatcher)
01872         delete m_ownDispatcher;
01873 
01874     if (NULL != m_solver)
01875         delete m_solver;
01876 
01877     if (NULL != m_debugDrawer)
01878         delete m_debugDrawer;
01879 
01880     if (NULL != m_filterCallback)
01881         delete m_filterCallback;
01882 
01883     if (NULL != m_collisionConfiguration)
01884         delete m_collisionConfiguration;
01885 
01886     if (NULL != m_broadphase)
01887         delete m_broadphase;
01888 
01889     if (NULL != m_cullingTree)
01890         delete m_cullingTree;
01891 
01892     if (NULL != m_cullingCache)
01893         delete m_cullingCache;
01894 
01895 }
01896 
01897 
01898 float   CcdPhysicsEnvironment::getConstraintParam(int constraintId,int param)
01899 {
01900     btTypedConstraint* typedConstraint = getConstraintById(constraintId);
01901     switch (typedConstraint->getUserConstraintType())
01902     {
01903     case PHY_GENERIC_6DOF_CONSTRAINT:
01904         {
01905             
01906             switch (param)
01907             {
01908             case 0: case 1: case 2: 
01909                 {
01910                     //param = 0..2 are linear constraint values
01911                     btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
01912                     genCons->calculateTransforms();
01913                     return genCons->getRelativePivotPosition(param);
01914                     break;
01915                 }
01916                 case 3: case 4: case 5:
01917                 {
01918                     //param = 3..5 are relative constraint (Euler) angles
01919                     btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
01920                     genCons->calculateTransforms();
01921                     return genCons->getAngle(param-3);
01922                     break;
01923                 }
01924             default:
01925                 {
01926                 }
01927             }
01928             break;
01929         };
01930     default:
01931         {
01932         };
01933     };
01934     return 0.f;
01935 }
01936 
01937 void    CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float value0,float value1)
01938 {
01939     btTypedConstraint* typedConstraint = getConstraintById(constraintId);
01940     switch (typedConstraint->getUserConstraintType())
01941     {
01942     case PHY_GENERIC_6DOF_CONSTRAINT:
01943         {
01944             
01945             switch (param)
01946             {
01947             case 0: case 1: case 2: case 3: case 4: case 5:
01948                 {
01949                     //param = 0..5 are constraint limits, with low/high limit value
01950                     btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
01951                     genCons->setLimit(param,value0,value1);
01952                     break;
01953                 }
01954             case 6: case 7: case 8:
01955                 {
01956                     //param = 6,7,8 are translational motors, with value0=target velocity, value1 = max motor force
01957                     btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
01958                     int transMotorIndex = param-6;
01959                     btTranslationalLimitMotor* transMotor = genCons->getTranslationalLimitMotor();
01960                     transMotor->m_targetVelocity[transMotorIndex]= value0;
01961                     transMotor->m_maxMotorForce[transMotorIndex]=value1;
01962                     transMotor->m_enableMotor[transMotorIndex] = (value1>0.f);
01963                     break;
01964                 }
01965             case 9: case 10: case 11:
01966                 {
01967                     //param = 9,10,11 are rotational motors, with value0=target velocity, value1 = max motor force
01968                     btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
01969                     int angMotorIndex = param-9;
01970                     btRotationalLimitMotor* rotMotor = genCons->getRotationalLimitMotor(angMotorIndex);
01971                     rotMotor->m_enableMotor = (value1 > 0.f);
01972                     rotMotor->m_targetVelocity = value0;
01973                     rotMotor->m_maxMotorForce = value1;
01974                     break;
01975                 }
01976 
01977             case 12: case 13: case 14: case 15: case 16: case 17:
01978             {
01979                 //param 13-17 are for motorized springs on each of the degrees of freedom
01980                     btGeneric6DofSpringConstraint* genCons = (btGeneric6DofSpringConstraint*)typedConstraint;
01981                     int springIndex = param-12;
01982                     if (value0!=0.f)
01983                     {
01984                         bool springEnabled = true;
01985                         genCons->setStiffness(springIndex,value0);
01986                         genCons->setDamping(springIndex,value1);
01987                         genCons->enableSpring(springIndex,springEnabled);
01988                         genCons->setEquilibriumPoint(springIndex);
01989                     } else
01990                     {
01991                         bool springEnabled = false;
01992                         genCons->enableSpring(springIndex,springEnabled);
01993                     }
01994                     break;
01995             }
01996 
01997             default:
01998                 {
01999                 }
02000             };
02001             break;
02002         };
02003     case PHY_CONE_TWIST_CONSTRAINT:
02004         {
02005             switch (param)
02006             {
02007             case 3: case 4: case 5:
02008                 {
02009                     //param = 3,4,5 are constraint limits, high limit values
02010                     btConeTwistConstraint* coneTwist = (btConeTwistConstraint*)typedConstraint;
02011                     if(value1<0.0f)
02012                         coneTwist->setLimit(param,btScalar(BT_LARGE_FLOAT));
02013                     else
02014                         coneTwist->setLimit(param,value1);
02015                     break;
02016                 }
02017             default:
02018                 {
02019                 }
02020             };
02021             break;
02022         };
02023     case PHY_ANGULAR_CONSTRAINT:
02024     case PHY_LINEHINGE_CONSTRAINT:
02025         {
02026             switch (param)
02027             {
02028             case 3:
02029                 {
02030                     //param = 3 is a constraint limit, with low/high limit value
02031                     btHingeConstraint* hingeCons = (btHingeConstraint*)typedConstraint;
02032                     hingeCons->setLimit(value0,value1);
02033                     break;
02034                 }
02035             default:
02036                 {
02037                 }
02038             }
02039             break;
02040         };
02041     default:
02042         {
02043         };
02044     };
02045 }
02046 
02047 btTypedConstraint*  CcdPhysicsEnvironment::getConstraintById(int constraintId)
02048 {
02049 
02050     int numConstraints = m_dynamicsWorld->getNumConstraints();
02051     int i;
02052     for (i=0;i<numConstraints;i++)
02053     {
02054         btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
02055         if (constraint->getUserConstraintId()==constraintId)
02056         {
02057             return constraint;
02058         }
02059     }
02060     return 0;
02061 }
02062 
02063 
02064 void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
02065 {
02066 
02067     CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl;
02068     // addSensor() is a "light" function for bullet because it is used
02069     // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead 
02070     //if (m_controllers.insert(ctrl1).second)
02071     //{
02072     //  addCcdPhysicsController(ctrl1);
02073     //}
02074     enableCcdPhysicsController(ctrl1);
02075 }
02076 
02077 bool CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl)
02078 {
02079     CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl;
02080     if (!ccdCtrl->Unregister())
02081         return false;
02082     m_triggerControllers.erase(ccdCtrl);
02083     return true;
02084 }
02085 
02086 
02087 void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl)
02088 {
02089     disableCcdPhysicsController((CcdPhysicsController*)ctrl);
02090 }
02091 
02092 void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
02093 {
02094     /*  printf("addTouchCallback\n(response class = %i)\n",response_class);
02095 
02096     //map PHY_ convention into SM_ convention
02097     switch (response_class)
02098     {
02099     case    PHY_FH_RESPONSE:
02100     printf("PHY_FH_RESPONSE\n");
02101     break;
02102     case PHY_SENSOR_RESPONSE:
02103     printf("PHY_SENSOR_RESPONSE\n");
02104     break;
02105     case PHY_CAMERA_RESPONSE:
02106     printf("PHY_CAMERA_RESPONSE\n");
02107     break;
02108     case PHY_OBJECT_RESPONSE:
02109     printf("PHY_OBJECT_RESPONSE\n");
02110     break;
02111     case PHY_STATIC_RESPONSE:
02112     printf("PHY_STATIC_RESPONSE\n");
02113     break;
02114     default:
02115     assert(0);
02116     return;
02117     }
02118     */
02119 
02120     m_triggerCallbacks[response_class] = callback;
02121     m_triggerCallbacksUserPtrs[response_class] = user;
02122 
02123 }
02124 bool CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl)
02125 {
02126     CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl);
02127 
02128     if (!ccdCtrl->Register())
02129         return false;
02130     m_triggerControllers.insert(ccdCtrl);
02131     return true;
02132 }
02133 
02134 void    CcdPhysicsEnvironment::CallbackTriggers()
02135 {
02136     if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)))
02137     {
02138         //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
02139         btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
02140         int numManifolds = dispatcher->getNumManifolds();
02141         for (int i=0;i<numManifolds;i++)
02142         {
02143             btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
02144             int numContacts = manifold->getNumContacts();
02145             if (numContacts)
02146             {
02147                 btRigidBody* rb0 = static_cast<btRigidBody*>(manifold->getBody0());
02148                 btRigidBody* rb1 = static_cast<btRigidBody*>(manifold->getBody1());
02149                 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))
02150                 {
02151                     for (int j=0;j<numContacts;j++)
02152                     {
02153                         btVector3 color(1,0,0);
02154                         const btManifoldPoint& cp = manifold->getContactPoint(j);
02155                         if (m_debugDrawer)
02156                             m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
02157                     }
02158                 }
02159                 btRigidBody* obj0 = rb0;
02160                 btRigidBody* obj1 = rb1;
02161 
02162                 //m_internalOwner is set in 'addPhysicsController'
02163                 CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer());
02164                 CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer());
02165 
02166                 std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0);
02167                 if (i == m_triggerControllers.end())
02168                 {
02169                     i = m_triggerControllers.find(ctrl1);
02170                 }
02171 
02172                 if (!(i == m_triggerControllers.end()))
02173                 {
02174                     m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
02175                         ctrl0,ctrl1,0);
02176                 }
02177                 // Bullet does not refresh the manifold contact point for object without contact response
02178                 // may need to remove this when a newer Bullet version is integrated
02179                 if (!dispatcher->needsResponse(rb0, rb1))
02180                 {
02181                     // Refresh algorithm fails sometimes when there is penetration 
02182                     // (usuall the case with ghost and sensor objects)
02183                     // Let's just clear the manifold, in any case, it is recomputed on each frame.
02184                     manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
02185                 }
02186             }
02187         }
02188 
02189 
02190 
02191     }
02192 
02193 
02194 }
02195 
02196 // This call back is called before a pair is added in the cache
02197 // Handy to remove objects that must be ignored by sensors
02198 bool CcdOverlapFilterCallBack::needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
02199 {
02200     btCollisionObject *colObj0, *colObj1;
02201     CcdPhysicsController *sensorCtrl, *objCtrl;
02202     bool collides;
02203     // first check the filters
02204     collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
02205     collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
02206     if (!collides)
02207         return false;
02208 
02209     // additional check for sensor object
02210     if (proxy0->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
02211     {
02212         // this is a sensor object, the other one can't be a sensor object because 
02213         // they exclude each other in the above test
02214         assert(!(proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger));
02215         colObj0 = (btCollisionObject*)proxy0->m_clientObject;
02216         colObj1 = (btCollisionObject*)proxy1->m_clientObject;
02217     }
02218     else if (proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
02219     {
02220         colObj0 = (btCollisionObject*)proxy1->m_clientObject;
02221         colObj1 = (btCollisionObject*)proxy0->m_clientObject;
02222     }
02223     else
02224     {
02225         return true;
02226     }
02227     if (!colObj0 || !colObj1)
02228         return false;
02229     sensorCtrl = static_cast<CcdPhysicsController*>(colObj0->getUserPointer());
02230     objCtrl = static_cast<CcdPhysicsController*>(colObj1->getUserPointer());
02231     if (m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE])
02232     {
02233         return m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE](m_physEnv->m_triggerCallbacksUserPtrs[PHY_BROADPH_RESPONSE], sensorCtrl, objCtrl, 0);
02234     }
02235     return true;
02236 }
02237 
02238 
02239 #ifdef NEW_BULLET_VEHICLE_SUPPORT
02240 
02241 //complex constraint for vehicles
02242 PHY_IVehicle*   CcdPhysicsEnvironment::getVehicleConstraint(int constraintId)
02243 {
02244     int i;
02245 
02246     int numVehicles = m_wrapperVehicles.size();
02247     for (i=0;i<numVehicles;i++)
02248     {
02249         WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i];
02250         if (wrapperVehicle->GetVehicle()->getUserConstraintId() == constraintId)
02251             return wrapperVehicle;
02252     }
02253 
02254     return 0;
02255 }
02256 
02257 #endif //NEW_BULLET_VEHICLE_SUPPORT
02258 
02259 
02260 int currentController = 0;
02261 int numController = 0;
02262 
02263 
02264 
02265 
02266 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position)
02267 {
02268     
02269     CcdConstructionInfo cinfo;
02270     memset(&cinfo, 0, sizeof(cinfo)); /* avoid uninitialized values */
02271     cinfo.m_collisionShape = new btSphereShape(radius); // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
02272     cinfo.m_MotionState = 0;
02273     cinfo.m_physicsEnv = this;
02274     // declare this object as Dyamic rather than static!!
02275     // The reason as it is designed to detect all type of object, including static object
02276     // It would cause static-static message to be printed on the console otherwise
02277     cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE | btCollisionObject::CF_STATIC_OBJECT;
02278     DefaultMotionState* motionState = new DefaultMotionState();
02279     cinfo.m_MotionState = motionState;
02280     // we will add later the possibility to select the filter from option
02281     cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
02282     cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
02283     cinfo.m_bSensor = true;
02284     motionState->m_worldTransform.setIdentity();
02285     motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
02286 
02287     CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
02288     
02289     return sphereController;
02290 }
02291 
02292 int findClosestNode(btSoftBody* sb,const btVector3& worldPoint);
02293 int findClosestNode(btSoftBody* sb,const btVector3& worldPoint)
02294 {
02295     int node = -1;
02296 
02297     btSoftBody::tNodeArray&   nodes(sb->m_nodes);
02298     float maxDistSqr = 1e30f;
02299 
02300     for (int n=0;n<nodes.size();n++)
02301     {
02302         btScalar distSqr = (nodes[n].m_x - worldPoint).length2();
02303         if (distSqr<maxDistSqr)
02304         {
02305             maxDistSqr = distSqr;
02306             node = n;
02307         }
02308     }
02309     return node;
02310 }
02311 
02312 int         CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl0,class PHY_IPhysicsController* ctrl1,PHY_ConstraintType type,
02313                                                     float pivotX,float pivotY,float pivotZ,
02314                                                     float axisX,float axisY,float axisZ,
02315                                                     float axis1X,float axis1Y,float axis1Z,
02316                                                     float axis2X,float axis2Y,float axis2Z,int flags
02317                                                     )
02318 {
02319 
02320     bool disableCollisionBetweenLinkedBodies = (0!=(flags & CCD_CONSTRAINT_DISABLE_LINKED_COLLISION));
02321 
02322 
02323 
02324     CcdPhysicsController* c0 = (CcdPhysicsController*)ctrl0;
02325     CcdPhysicsController* c1 = (CcdPhysicsController*)ctrl1;
02326 
02327     btRigidBody* rb0 = c0 ? c0->GetRigidBody() : 0;
02328     btRigidBody* rb1 = c1 ? c1->GetRigidBody() : 0;
02329 
02330     
02331 
02332 
02333     bool rb0static = rb0 ? rb0->isStaticOrKinematicObject() : true;
02334     bool rb1static = rb1 ? rb1->isStaticOrKinematicObject() : true;
02335 
02336     btCollisionObject* colObj0 = c0->GetCollisionObject();
02337     if (!colObj0)
02338     {
02339         return 0;
02340     }
02341 
02342     btVector3 pivotInA(pivotX,pivotY,pivotZ);
02343 
02344     
02345 
02346     //it might be a soft body, let's try
02347     btSoftBody* sb0 = c0 ? c0->GetSoftBody() : 0;
02348     btSoftBody* sb1 = c1 ? c1->GetSoftBody() : 0;
02349     if (sb0 && sb1)
02350     {
02351         //not between two soft bodies?
02352         return 0;
02353     }
02354 
02355     if (sb0)
02356     {
02357         //either cluster or node attach, let's find closest node first
02358         //the soft body doesn't have a 'real' world transform, so get its initial world transform for now
02359         btVector3 pivotPointSoftWorld = sb0->m_initialWorldTransform(pivotInA);
02360         int node=findClosestNode(sb0,pivotPointSoftWorld);
02361         if (node >=0)
02362         {
02363             bool clusterconstaint = false;
02364 /*
02365             switch (type)
02366             {
02367             case PHY_LINEHINGE_CONSTRAINT:
02368                 {
02369                     if (sb0->clusterCount() && rb1)
02370                     {
02371                         btSoftBody::LJoint::Specs   ls;
02372                         ls.erp=0.5f;
02373                         ls.position=sb0->clusterCom(0);
02374                         sb0->appendLinearJoint(ls,rb1);
02375                         clusterconstaint = true;
02376                         break;
02377                     }
02378                 }
02379             case PHY_GENERIC_6DOF_CONSTRAINT:
02380                 {
02381                     if (sb0->clusterCount() && rb1)
02382                     {
02383                         btSoftBody::AJoint::Specs as;
02384                         as.erp = 1;
02385                         as.cfm = 1;
02386                         as.axis.setValue(axisX,axisY,axisZ);
02387                         sb0->appendAngularJoint(as,rb1);
02388                         clusterconstaint = true;
02389                         break;
02390                     }
02391 
02392                     break;
02393                 }
02394             default:
02395                 {
02396                 
02397                 }
02398             };
02399             */
02400 
02401             if (!clusterconstaint)
02402             {
02403                 if (rb1)
02404                 {
02405                     sb0->appendAnchor(node,rb1,disableCollisionBetweenLinkedBodies);
02406                 } else
02407                 {
02408                     sb0->setMass(node,0.f);
02409                 }
02410             }
02411 
02412             
02413         }
02414         return 0;//can't remove soft body anchors yet
02415     }
02416 
02417     if (sb1)
02418     {
02419         btVector3 pivotPointAWorld = colObj0->getWorldTransform()(pivotInA);
02420         int node=findClosestNode(sb1,pivotPointAWorld);
02421         if (node >=0)
02422         {
02423             bool clusterconstaint = false;
02424 
02425             /*
02426             switch (type)
02427             {
02428             case PHY_LINEHINGE_CONSTRAINT:
02429                 {
02430                     if (sb1->clusterCount() && rb0)
02431                     {
02432                         btSoftBody::LJoint::Specs   ls;
02433                         ls.erp=0.5f;
02434                         ls.position=sb1->clusterCom(0);
02435                         sb1->appendLinearJoint(ls,rb0);
02436                         clusterconstaint = true;
02437                         break;
02438                     }
02439                 }
02440             case PHY_GENERIC_6DOF_CONSTRAINT:
02441                 {
02442                     if (sb1->clusterCount() && rb0)
02443                     {
02444                         btSoftBody::AJoint::Specs as;
02445                         as.erp = 1;
02446                         as.cfm = 1;
02447                         as.axis.setValue(axisX,axisY,axisZ);
02448                         sb1->appendAngularJoint(as,rb0);
02449                         clusterconstaint = true;
02450                         break;
02451                     }
02452 
02453                     break;
02454                 }
02455             default:
02456                 {
02457                     
02458 
02459                 }
02460             };*/
02461 
02462 
02463             if (!clusterconstaint)
02464             {
02465                 if (rb0)
02466                 {
02467                     sb1->appendAnchor(node,rb0,disableCollisionBetweenLinkedBodies);
02468                 } else
02469                 {
02470                     sb1->setMass(node,0.f);
02471                 }
02472             }
02473             
02474 
02475         }
02476         return 0;//can't remove soft body anchors yet
02477     }
02478 
02479     if (rb0static && rb1static)
02480     {
02481         
02482         return 0;
02483     }
02484     
02485 
02486     if (!rb0)
02487         return 0;
02488 
02489     
02490     btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) : 
02491         rb0->getCenterOfMassTransform() * pivotInA;
02492     btVector3 axisInA(axisX,axisY,axisZ);
02493 
02494 
02495     bool angularOnly = false;
02496 
02497     switch (type)
02498     {
02499     case PHY_POINT2POINT_CONSTRAINT:
02500         {
02501 
02502             btPoint2PointConstraint* p2p = 0;
02503 
02504             if (rb1)
02505             {
02506                 p2p = new btPoint2PointConstraint(*rb0,
02507                     *rb1,pivotInA,pivotInB);
02508             } else
02509             {
02510                 p2p = new btPoint2PointConstraint(*rb0,
02511                     pivotInA);
02512             }
02513 
02514             m_dynamicsWorld->addConstraint(p2p,disableCollisionBetweenLinkedBodies);
02515 //          m_constraints.push_back(p2p);
02516 
02517             p2p->setUserConstraintId(gConstraintUid++);
02518             p2p->setUserConstraintType(type);
02519             //64 bit systems can't cast pointer to int. could use size_t instead.
02520             return p2p->getUserConstraintId();
02521 
02522             break;
02523         }
02524 
02525     case PHY_GENERIC_6DOF_CONSTRAINT:
02526         {
02527             btGeneric6DofConstraint* genericConstraint = 0;
02528 
02529             if (rb1)
02530             {
02531                 btTransform frameInA;
02532                 btTransform frameInB;
02533                 
02534                 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
02535                 if (axis1.length() == 0.0)
02536                 {
02537                     btPlaneSpace1( axisInA, axis1, axis2 );
02538                 }
02539                 
02540                 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
02541                                               axisInA.y(), axis1.y(), axis2.y(),
02542                                               axisInA.z(), axis1.z(), axis2.z() );
02543                 frameInA.setOrigin( pivotInA );
02544 
02545                 btTransform inv = rb1->getCenterOfMassTransform().inverse();
02546 
02547                 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
02548                 
02549                 frameInB = inv  * globalFrameA;
02550                 bool useReferenceFrameA = true;
02551 
02552                 genericConstraint = new btGeneric6DofSpringConstraint(
02553                     *rb0,*rb1,
02554                     frameInA,frameInB,useReferenceFrameA);
02555 
02556 
02557             } else
02558             {
02559                 static btRigidBody s_fixedObject2( 0,0,0);
02560                 btTransform frameInA;
02561                 btTransform frameInB;
02562                 
02563                 btVector3 axis1, axis2;
02564                 btPlaneSpace1( axisInA, axis1, axis2 );
02565 
02566                 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
02567                                               axisInA.y(), axis1.y(), axis2.y(),
02568                                               axisInA.z(), axis1.z(), axis2.z() );
02569 
02570                 frameInA.setOrigin( pivotInA );
02571 
02573                 frameInB = rb0->getCenterOfMassTransform() * frameInA;
02574 
02575                 bool useReferenceFrameA = true;
02576                 genericConstraint = new btGeneric6DofSpringConstraint(
02577                     *rb0,s_fixedObject2,
02578                     frameInA,frameInB,useReferenceFrameA);
02579             }
02580             
02581             if (genericConstraint)
02582             {
02583                 //m_constraints.push_back(genericConstraint);
02584                 m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
02585                 genericConstraint->setUserConstraintId(gConstraintUid++);
02586                 genericConstraint->setUserConstraintType(type);
02587                 //64 bit systems can't cast pointer to int. could use size_t instead.
02588                 return genericConstraint->getUserConstraintId();
02589             } 
02590 
02591             break;
02592         }
02593     case PHY_CONE_TWIST_CONSTRAINT:
02594         {
02595             btConeTwistConstraint* coneTwistContraint = 0;
02596 
02597             
02598             if (rb1)
02599             {
02600                 btTransform frameInA;
02601                 btTransform frameInB;
02602                 
02603                 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
02604                 if (axis1.length() == 0.0)
02605                 {
02606                     btPlaneSpace1( axisInA, axis1, axis2 );
02607                 }
02608                 
02609                 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
02610                                               axisInA.y(), axis1.y(), axis2.y(),
02611                                               axisInA.z(), axis1.z(), axis2.z() );
02612                 frameInA.setOrigin( pivotInA );
02613 
02614                 btTransform inv = rb1->getCenterOfMassTransform().inverse();
02615 
02616                 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
02617                 
02618                 frameInB = inv  * globalFrameA;
02619                 
02620                 coneTwistContraint = new btConeTwistConstraint( *rb0,*rb1,
02621                     frameInA,frameInB);
02622 
02623 
02624             } else
02625             {
02626                 static btRigidBody s_fixedObject2( 0,0,0);
02627                 btTransform frameInA;
02628                 btTransform frameInB;
02629                 
02630                 btVector3 axis1, axis2;
02631                 btPlaneSpace1( axisInA, axis1, axis2 );
02632 
02633                 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
02634                                               axisInA.y(), axis1.y(), axis2.y(),
02635                                               axisInA.z(), axis1.z(), axis2.z() );
02636 
02637                 frameInA.setOrigin( pivotInA );
02638 
02640                 frameInB = rb0->getCenterOfMassTransform() * frameInA;
02641 
02642                 coneTwistContraint = new btConeTwistConstraint(
02643                     *rb0,s_fixedObject2,
02644                     frameInA,frameInB);
02645             }
02646             
02647             if (coneTwistContraint)
02648             {
02649                 //m_constraints.push_back(genericConstraint);
02650                 m_dynamicsWorld->addConstraint(coneTwistContraint,disableCollisionBetweenLinkedBodies);
02651                 coneTwistContraint->setUserConstraintId(gConstraintUid++);
02652                 coneTwistContraint->setUserConstraintType(type);
02653                 //64 bit systems can't cast pointer to int. could use size_t instead.
02654                 return coneTwistContraint->getUserConstraintId();
02655             } 
02656 
02657 
02658 
02659             break;
02660         }
02661     case PHY_ANGULAR_CONSTRAINT:
02662         angularOnly = true;
02663 
02664 
02665     case PHY_LINEHINGE_CONSTRAINT:
02666         {
02667             btHingeConstraint* hinge = 0;
02668 
02669             if (rb1)
02670             {
02671                 // We know the orientations so we should use them instead of
02672                 // having btHingeConstraint fill in the blanks any way it wants to.
02673                 btTransform frameInA;
02674                 btTransform frameInB;
02675                 
02676                 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
02677                 if (axis1.length() == 0.0)
02678                 {
02679                     btPlaneSpace1( axisInA, axis1, axis2 );
02680                 }
02681                 
02682                 // Internally btHingeConstraint's hinge-axis is z
02683                 frameInA.getBasis().setValue( axis1.x(), axis2.x(), axisInA.x(),
02684                                             axis1.y(), axis2.y(), axisInA.y(),
02685                                             axis1.z(), axis2.z(), axisInA.z() );
02686                                             
02687                 frameInA.setOrigin( pivotInA );
02688 
02689                 btTransform inv = rb1->getCenterOfMassTransform().inverse();
02690 
02691                 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
02692                 
02693                 frameInB = inv  * globalFrameA;
02694                 
02695                 hinge = new btHingeConstraint(*rb0,*rb1,frameInA,frameInB);
02696 
02697 
02698             } else
02699             {
02700                 static btRigidBody s_fixedObject2( 0,0,0);
02701 
02702                 btTransform frameInA;
02703                 btTransform frameInB;
02704                 
02705                 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
02706                 if (axis1.length() == 0.0)
02707                 {
02708                     btPlaneSpace1( axisInA, axis1, axis2 );
02709                 }
02710 
02711                 // Internally btHingeConstraint's hinge-axis is z
02712                 frameInA.getBasis().setValue( axis1.x(), axis2.x(), axisInA.x(),
02713                                             axis1.y(), axis2.y(), axisInA.y(),
02714                                             axis1.z(), axis2.z(), axisInA.z() );
02715                 frameInA.setOrigin( pivotInA );
02716                 frameInB = rb0->getCenterOfMassTransform() * frameInA;
02717 
02718                 hinge = new btHingeConstraint(*rb0, s_fixedObject2, frameInA, frameInB);
02719             }
02720             hinge->setAngularOnly(angularOnly);
02721 
02722             //m_constraints.push_back(hinge);
02723             m_dynamicsWorld->addConstraint(hinge,disableCollisionBetweenLinkedBodies);
02724             hinge->setUserConstraintId(gConstraintUid++);
02725             hinge->setUserConstraintType(type);
02726             //64 bit systems can't cast pointer to int. could use size_t instead.
02727             return hinge->getUserConstraintId();
02728             break;
02729         }
02730 #ifdef NEW_BULLET_VEHICLE_SUPPORT
02731 
02732     case PHY_VEHICLE_CONSTRAINT:
02733         {
02734             btRaycastVehicle::btVehicleTuning* tuning = new btRaycastVehicle::btVehicleTuning();
02735             btRigidBody* chassis = rb0;
02736             btDefaultVehicleRaycaster* raycaster = new btDefaultVehicleRaycaster(m_dynamicsWorld);
02737             btRaycastVehicle* vehicle = new btRaycastVehicle(*tuning,chassis,raycaster);
02738             WrapperVehicle* wrapperVehicle = new WrapperVehicle(vehicle,ctrl0);
02739             m_wrapperVehicles.push_back(wrapperVehicle);
02740             m_dynamicsWorld->addVehicle(vehicle);
02741             vehicle->setUserConstraintId(gConstraintUid++);
02742             vehicle->setUserConstraintType(type);
02743             return vehicle->getUserConstraintId();
02744 
02745             break;
02746         };
02747 #endif //NEW_BULLET_VEHICLE_SUPPORT
02748 
02749     default:
02750         {
02751         }
02752     };
02753 
02754     //btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB
02755 
02756     return 0;
02757 
02758 }
02759 
02760 
02761 
02762 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
02763 {
02764     CcdConstructionInfo cinfo;
02765 //don't memset cinfo: this is C++ and values should be set in the constructor!
02766 
02767     // we don't need a CcdShapeConstructionInfo for this shape:
02768     // it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
02769     cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
02770     cinfo.m_MotionState = 0;
02771     cinfo.m_physicsEnv = this;
02772     cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE | btCollisionObject::CF_STATIC_OBJECT;
02773     DefaultMotionState* motionState = new DefaultMotionState();
02774     cinfo.m_MotionState = motionState;
02775     
02776     // we will add later the possibility to select the filter from option
02777     cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
02778     cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
02779     cinfo.m_bSensor = true;
02780     motionState->m_worldTransform.setIdentity();
02781 //  motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
02782 
02783     CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
02784 
02785 
02786     return sphereController;
02787 }
02788     
02789 float       CcdPhysicsEnvironment::getAppliedImpulse(int    constraintid)
02790 {
02791     int i;
02792     int numConstraints = m_dynamicsWorld->getNumConstraints();
02793     for (i=0;i<numConstraints;i++)
02794     {
02795         btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
02796         if (constraint->getUserConstraintId() == constraintid)
02797         {
02798             return constraint->getAppliedImpulse();
02799         }
02800     }
02801 
02802     return 0.f;
02803 }
02804 
02805 void    CcdPhysicsEnvironment::exportFile(const char* filename)
02806 {
02807     btDefaultSerializer*    serializer = new btDefaultSerializer();
02808     
02809         
02810     for (int i=0;i<m_dynamicsWorld->getNumCollisionObjects();i++)
02811     {
02812 
02813         btCollisionObject* colObj = m_dynamicsWorld->getCollisionObjectArray()[i];
02814 
02815         CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(colObj->getUserPointer());
02816         if (controller)
02817         {
02818             const char* name = controller->getName();
02819             if (name)
02820             {
02821                 serializer->registerNameForPointer(colObj,name);
02822             }
02823         }
02824     }
02825 
02826     m_dynamicsWorld->serialize(serializer);
02827 
02828     FILE* file = fopen(filename,"wb");
02829     if (file)
02830     {
02831         fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file);
02832         fclose(file);
02833     }
02834 }
02835