2 Physics Effects Copyright(C) 2011 Sony Computer Entertainment Inc.
\r
5 Physics Effects is open software; you can redistribute it and/or
\r
6 modify it under the terms of the BSD License.
\r
8 Physics Effects is distributed in the hope that it will be useful,
\r
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
\r
11 See the BSD License for more details.
\r
13 A copy of the BSD License is distributed with
\r
14 Physics Effects under the filename: physics_effects_license.txt
\r
17 #include "btBulletPhysicsEffectsWorld.h"
\r
18 #include "BulletDynamics/Dynamics/btRigidBody.h"
\r
19 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
\r
20 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
\r
21 #include "LinearMath/btAabbUtil2.h"
\r
22 #include "BulletMultiThreaded/SequentialThreadSupport.h"
\r
23 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
\r
24 #include "LinearMath/btIDebugDraw.h"
\r
25 #include "LinearMath/btQuickprof.h"
\r
27 #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
\r
29 #include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
\r
32 #include "BulletPhysicsEffects/btLowLevelData.h"
\r
33 #include <physics_effects/low_level/pfx_low_level_include.h>
\r
34 #include <physics_effects/util/pfx_util_include.h>
\r
35 #include "btLowLevelBroadphase.h"
\r
38 #include "BulletCollision/CollisionShapes/btCompoundShape.h"//required for shape conversion
\r
39 #include "BulletCollision/CollisionShapes/btConvexHullShape.h"//required for shape conversion
\r
40 #include "BulletCollision/CollisionShapes/btCylinderShape.h"//required for shape conversion
\r
41 #include "BulletCollision/CollisionShapes/btSphereShape.h"//required for shape conversion
\r
42 #include "BulletCollision/CollisionShapes/btCapsuleShape.h"//required for shape conversion
\r
43 #include "BulletCollision/CollisionShapes/btBoxShape.h"//required for shape conversion
\r
44 #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
\r
45 #include "BulletMultiThreaded/vectormath2bullet.h"
\r
48 #include "BulletMultiThreaded/Win32ThreadSupport.h"
\r
52 #ifdef USE_PE_GATHER_SCATTER_SPURS_TASK
\r
53 #include "SpuDispatch/BulletPEGatherScatterSpursSupport.h"
\r
54 #include "SpuDispatch/SpuPEGatherScatterTaskProcess.h"
\r
58 btBulletPhysicsEffectsWorld::btBulletPhysicsEffectsWorld(btLowLevelData* lowLevelData, btDispatcher* dispatcher,btLowLevelBroadphase* broadphase,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration, btThreadSupportInterface* threadSupport)
\r
59 :btDiscreteDynamicsWorld(dispatcher,broadphase,constraintSolver,collisionConfiguration),
\r
60 m_lowLevelData(lowLevelData)
\r
63 #ifdef USE_PE_GATHER_SCATTER_SPURS_TASK
\r
64 int numGatherScatterSpus = threadSupport->getNumTasks();
\r
65 m_PEGatherScatterProcess = new SpuPEGatherScatterTaskProcess(threadSupport,numGatherScatterSpus);
\r
66 #endif //USE_PE_GATHER_SCATTER_SPURS_TASK
\r
68 m_lowLevelStates.resize(broadphase->m_maxHandles);//or use expandNonInitializing?
\r
69 m_lowLevelBodies.resize(broadphase->m_maxHandles);
\r
70 m_lowLevelSolverBodies.resize(broadphase->m_maxHandles);
\r
71 m_lowLevelCollidables.resize(broadphase->m_maxHandles);
\r
73 m_lowLevelData->m_states = &m_lowLevelStates[0];
\r
74 m_lowLevelData->m_collidables = &m_lowLevelCollidables[0];
\r
75 m_lowLevelData->m_bodies = &m_lowLevelBodies[0];
\r
76 m_lowLevelData->m_solverBodies = &m_lowLevelSolverBodies[0];
\r
77 m_lowLevelData->m_numRigidBodies = broadphase->m_maxHandles;
\r
81 btBulletPhysicsEffectsWorld::~btBulletPhysicsEffectsWorld()
\r
83 #ifdef USE_PE_GATHER_SCATTER_SPURS_TASK
\r
84 delete m_PEGatherScatterProcess;
\r
91 void btBulletPhysicsEffectsWorld::integrateTransforms(btScalar timeStep)
\r
93 ///integrate transforms
\r
94 #ifdef USE_PE_GATHER_SCATTER_SPURS_TASK
\r
95 if (getDispatchInfo().m_enableSPU)
\r
97 BT_PROFILE("integrateTransformsSPU");
\r
98 int numRemainingObjects = m_nonStaticRigidBodies.size();
\r
100 int batchSize = PARALLEL_BATCH_SIZE;
\r
101 int startIndex = 0;
\r
102 while (numRemainingObjects>0)
\r
104 int currentBatchSize = numRemainingObjects > batchSize? batchSize : numRemainingObjects;
\r
106 //issue and flush is likely to be called every frame, move the construction and deletion out of the inner loop (at construction/init etc)
\r
107 m_PEGatherScatterProcess->issueTask(
\r
108 CMD_SAMPLE_INTEGRATE_BODIES,
\r
109 &m_nonStaticRigidBodies[0],
\r
114 numRemainingObjects -= currentBatchSize;
\r
115 startIndex += currentBatchSize;
\r
118 m_PEGatherScatterProcess->flush();
\r
120 #endif //USE_PE_GATHER_SCATTER_SPURS_TASK
\r
122 // BT_PROFILE("integrateTransforms");
\r
123 btDiscreteDynamicsWorld::integrateTransforms(timeStep);
\r
128 void btBulletPhysicsEffectsWorld::predictUnconstraintMotion(btScalar timeStep)
\r
130 #ifdef USE_PE_GATHER_SCATTER_SPURS_TASK
\r
131 if (getDispatchInfo().m_enableSPU)
\r
133 BT_PROFILE("predictUnconstraintMotionSPU");
\r
134 int numRemainingObjects = m_nonStaticRigidBodies.size();
\r
136 int batchSize = PARALLEL_BATCH_SIZE;
\r
138 while (numRemainingObjects>0)
\r
140 int currentBatchSize = numRemainingObjects > batchSize? batchSize : numRemainingObjects;
\r
142 //issue and flush is likely to be called every frame, move the construction and deletion out of the inner loop (at construction/init etc)
\r
143 m_PEGatherScatterProcess->issueTask(
\r
144 CMD_SAMPLE_PREDICT_MOTION_BODIES,
\r
145 &m_nonStaticRigidBodies[0],
\r
150 numRemainingObjects -= currentBatchSize;
\r
151 startIndex += currentBatchSize;
\r
154 m_PEGatherScatterProcess->flush();
\r
157 #endif //USE_PE_GATHER_SCATTER_SPURS_TASK
\r
159 btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep);
\r
162 for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
\r
164 btRigidBody* body = m_nonStaticRigidBodies[i];
\r
165 body->setHitFraction(1.f);
\r
167 if (body->isActive() && (!body->isStaticOrKinematicObject()))
\r
169 syncRigidBodyState(body);
\r
176 void btBulletPhysicsEffectsWorld::solveConstraints(btContactSolverInfo& solverInfo)
\r
178 BT_PROFILE("solveConstraints");
\r
180 btCollisionDispatcher* disp = (btCollisionDispatcher*) getDispatcher();
\r
181 int numBodies = getNumCollisionObjects();
\r
183 btPersistentManifold** manifolds = disp->getInternalManifoldPointer();
\r
185 int numManifolds = disp->getNumManifolds();
\r
188 if ((getNumCollisionObjects()>0) && (numManifolds + m_constraints.size()>0))
\r
191 btCollisionObject** bodies = numBodies ? &getCollisionObjectArray()[0] : 0;
\r
192 btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
\r
194 getConstraintSolver()->solveGroup( bodies,numBodies, disp->getInternalManifoldPointer(),numManifolds, constraints, m_constraints.size() ,m_solverInfo,m_debugDrawer,m_stackAlloc,disp);
\r
199 void btBulletPhysicsEffectsWorld::calculateSimulationIslands()
\r
204 static void convertShape(btCollisionShape* bulletShape, btAlignedObjectArray<sce::PhysicsEffects::PfxShape>& shapes)
\r
206 switch (bulletShape->getShapeType())
\r
208 case BOX_SHAPE_PROXYTYPE:
\r
210 btBoxShape* boxshape = (btBoxShape*)bulletShape;
\r
211 sce::PhysicsEffects::PfxBox box(boxshape->getHalfExtentsWithMargin().getX(),boxshape->getHalfExtentsWithMargin().getY(),boxshape->getHalfExtentsWithMargin().getZ());
\r
212 sce::PhysicsEffects::PfxShape& shape = shapes.expand();
\r
218 case TRIANGLE_MESH_SHAPE_PROXYTYPE:
\r
220 btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*) bulletShape;
\r
222 int numSubParts = trimesh->getMeshInterface()->getNumSubParts();
\r
223 btAssert(numSubParts>0);
\r
225 for (int i=0;i<numSubParts;i++)
\r
227 unsigned char* vertexBase=0;
\r
229 PHY_ScalarType vertexType;
\r
230 int vertexStride=0;
\r
231 unsigned char* indexBase=0;
\r
234 PHY_ScalarType indexType;
\r
236 trimesh->getMeshInterface()->getLockedVertexIndexBase(&vertexBase,numVerts,vertexType,vertexStride,&indexBase,indexStride,numFaces,indexType,i);
\r
238 sce::PhysicsEffects::PfxCreateLargeTriMeshParam param;
\r
239 btAssert(param.flag&SCE_PFX_MESH_FLAG_16BIT_INDEX);
\r
240 unsigned short int* copyIndices = new unsigned short int[numFaces*3];
\r
245 for (int p=0;p<numFaces;p++)
\r
247 copyIndices[p*3]=indexBase[p*indexStride];
\r
248 copyIndices[p*3+1]=indexBase[p*indexStride+1];
\r
249 copyIndices[p*3+2]=indexBase[p*indexStride+2];
\r
261 param.verts = (float*)vertexBase;
\r
262 param.numVerts = numVerts;
\r
263 param.vertexStrideBytes = vertexStride;
\r
265 param.triangles = copyIndices;
\r
266 param.numTriangles = numFaces;
\r
267 param.triangleStrideBytes = sizeof(unsigned short int)*3;
\r
269 sce::PhysicsEffects::PfxLargeTriMesh* largeMesh = new sce::PhysicsEffects::PfxLargeTriMesh();
\r
271 sce::PhysicsEffects::PfxInt32 ret = pfxCreateLargeTriMesh(*largeMesh,param);
\r
272 if(ret != SCE_PFX_OK) {
\r
273 SCE_PFX_PRINTF("Can't create large mesh.\n");
\r
276 sce::PhysicsEffects::PfxShape& shape = shapes.expand();
\r
278 shape.setLargeTriMesh(largeMesh);
\r
283 case SPHERE_SHAPE_PROXYTYPE:
\r
285 btSphereShape* sphereshape = (btSphereShape*)bulletShape;
\r
286 sce::PhysicsEffects::PfxSphere sphere(sphereshape->getRadius());
\r
287 sce::PhysicsEffects::PfxShape& shape = shapes.expand();
\r
289 shape.setSphere(sphere);
\r
292 case CAPSULE_SHAPE_PROXYTYPE:
\r
294 btCapsuleShape* capsuleshape= (btCapsuleShape*)bulletShape;//assume btCapsuleShapeX for now
\r
295 sce::PhysicsEffects::PfxCapsule capsule(capsuleshape->getHalfHeight(),capsuleshape->getRadius());
\r
296 sce::PhysicsEffects::PfxShape& shape = shapes.expand();
\r
298 shape.setCapsule(capsule);
\r
301 case CYLINDER_SHAPE_PROXYTYPE:
\r
303 btCylinderShape* cylindershape= (btCylinderShape*)bulletShape;//assume btCylinderShapeX for now
\r
304 sce::PhysicsEffects::PfxCylinder cylinder(cylindershape->getHalfExtentsWithMargin()[0],cylindershape->getRadius());
\r
305 sce::PhysicsEffects::PfxShape& shape = shapes.expand();
\r
307 shape.setCylinder(cylinder);
\r
310 case CONVEX_HULL_SHAPE_PROXYTYPE:
\r
312 btConvexHullShape* convexHullShape = (btConvexHullShape*)bulletShape;
\r
314 sce::PhysicsEffects::PfxConvexMesh* convex = new sce::PhysicsEffects::PfxConvexMesh();
\r
315 convex->m_numVerts = convexHullShape->getNumPoints();
\r
316 convex->m_numIndices = 0;//todo for ray intersection test support
\r
318 for (int i=0;i<convex->m_numVerts;i++)
\r
320 convex->m_verts[i].setX(convexHullShape->getPoints()[i].getX());
\r
321 convex->m_verts[i].setY(convexHullShape->getPoints()[i].getY());
\r
322 convex->m_verts[i].setZ(convexHullShape->getPoints()[i].getZ());
\r
325 convex->updateAABB();
\r
326 sce::PhysicsEffects::PfxShape& shape = shapes.expand();
\r
328 shape.setConvexMesh(convex);
\r
331 case COMPOUND_SHAPE_PROXYTYPE:
\r
333 btCompoundShape* compound = (btCompoundShape*) bulletShape;
\r
335 for (int s=0;s<compound->getNumChildShapes();s++)
\r
337 convertShape(compound->getChildShape(s),shapes);
\r
339 sce::PhysicsEffects::PfxMatrix3 rotMat = getVmMatrix3(compound->getChildTransform(s).getBasis());
\r
340 sce::PhysicsEffects::PfxVector3 translate = getVmVector3(compound->getChildTransform(s).getOrigin());
\r
341 sce::PhysicsEffects::PfxTransform3 childtransform(rotMat,translate);
\r
342 shapes[shapes.size()-1].setOffsetTransform(childtransform);
\r
357 void btBulletPhysicsEffectsWorld::createStateAndCollidable(btRigidBody* body)
\r
360 int objectIndex = body->getBroadphaseProxy()->m_uniqueId;
\r
361 btAssert(objectIndex>=0);
\r
362 //btAssert(objectIndex<m_maxHandles);
\r
365 sce::PhysicsEffects::PfxRigidBody* pfxbody = &m_lowLevelBodies[objectIndex];
\r
366 sce::PhysicsEffects::PfxRigidState* pfxstate = &m_lowLevelStates[objectIndex];
\r
367 sce::PhysicsEffects::PfxCollidable* pfxcollidable = &m_lowLevelCollidables[objectIndex];
\r
369 ///convert/initialize body, shape, state and collidable
\r
372 pfxcollidable->reset();
\r
376 pfxbody->setFriction(body->getFriction());
\r
377 pfxbody->setRestitution(body->getRestitution());
\r
379 if (body->getInvMass())
\r
381 btScalar mass = 1.f/body->getInvMass();
\r
382 pfxbody->setMass(mass);
\r
383 Vectormath::Aos::Matrix3 inertiaInv = inertiaInv.identity();
\r
384 inertiaInv.setElem(0,0,body->getInvInertiaDiagLocal().getX());
\r
385 inertiaInv.setElem(1,1,body->getInvInertiaDiagLocal().getY());
\r
386 inertiaInv.setElem(2,2,body->getInvInertiaDiagLocal().getZ());
\r
387 pfxbody->setInertiaInv(inertiaInv);
\r
388 pfxstate->setMotionType(sce::PhysicsEffects::kPfxMotionTypeActive);
\r
391 pfxstate->setMotionType(sce::PhysicsEffects::kPfxMotionTypeFixed);
\r
394 btAlignedObjectArray<sce::PhysicsEffects::PfxShape> shapes;
\r
396 convertShape(body->getCollisionShape(), shapes);
\r
398 btAssert(shapes.size()>0);
\r
400 if (shapes.size()==1)
\r
402 pfxcollidable->addShape(shapes[0]);
\r
403 pfxcollidable->finish();
\r
406 if (shapes.size()>1)
\r
408 sce::PhysicsEffects::PfxUInt16* ints=new sce::PhysicsEffects::PfxUInt16[shapes.size()];
\r
409 sce::PhysicsEffects::PfxShape* pfxshapes = new sce::PhysicsEffects::PfxShape[shapes.size()];
\r
411 for (p=0;p<shapes.size();p++)
\r
414 pfxshapes[p] = shapes[p];
\r
416 pfxcollidable->reset(pfxshapes,ints,shapes.size());
\r
418 for (p=0;p<shapes.size();p++)
\r
420 pfxcollidable->addShape(pfxshapes[p]);
\r
423 pfxcollidable->finish();
\r
426 pfxstate->setRigidBodyId(objectIndex);
\r
428 syncRigidBodyState(body);
\r
435 void btBulletPhysicsEffectsWorld::syncRigidBodyState(btRigidBody* body)
\r
437 int objectIndex = body->getBroadphaseProxy()->m_uniqueId;
\r
438 sce::PhysicsEffects::PfxRigidState* pfxstate = &m_lowLevelStates[objectIndex];
\r
440 pfxstate->setPosition(sce::PhysicsEffects::PfxVector3(body->getWorldTransform().getOrigin()[0],body->getWorldTransform().getOrigin()[1],body->getWorldTransform().getOrigin()[2]));
\r
441 sce::PhysicsEffects::PfxQuat rot(body->getOrientation().getX(),body->getOrientation().getY(),body->getOrientation().getZ(),body->getOrientation().getW());
\r
442 pfxstate->setOrientation(rot);
\r
448 void btBulletPhysicsEffectsWorld::addRigidBody(btRigidBody* body)
\r
451 btDiscreteDynamicsWorld::addRigidBody(body);
\r
453 //create a state and collidable
\r
455 createStateAndCollidable(body);
\r
461 // m_lowLevelData->m_numRigidBodies++;
\r
462 // btAssert(m_lowLevelData->m_numRigidBodies<m_lowLevelData->m_maxNumRigidBodies);
\r
466 void btBulletPhysicsEffectsWorld::addRigidBody(btRigidBody* body, short group, short mask)
\r
468 btDiscreteDynamicsWorld::addRigidBody(body,group,mask);
\r
472 void btBulletPhysicsEffectsWorld::removeRigidBody(btRigidBody* body)
\r
474 btDiscreteDynamicsWorld::removeRigidBody(body);
\r
476 // m_lowLevelData->m_numRigidBodies--;
\r
477 // btAssert(m_lowLevelData->m_numRigidBodies>=0);
\r