2 Copyright (C) 2010 Sony Computer Entertainment Inc.
\r
5 This software is provided 'as-is', without any express or implied warranty.
\r
6 In no event will the authors be held liable for any damages arising from the use of this software.
\r
7 Permission is granted to anyone to use this software for any purpose,
\r
8 including commercial applications, and to alter it and redistribute it freely,
\r
9 subject to the following restrictions:
\r
11 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.
\r
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
\r
13 3. This notice may not be removed or altered from any source distribution.
\r
18 #include "btLowLevelConstraintSolver.h"
\r
19 #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
\r
21 #include "LinearMath/btQuickprof.h"
\r
22 #include "BulletMultiThreaded/btThreadSupportInterface.h"
\r
24 #include "vecmath/vmInclude.h"
\r
26 #include "BulletMultiThreaded/HeapManager.h"
\r
28 #include "BulletMultiThreaded/PlatformDefinitions.h"
\r
30 //#include "PfxSimdUtils.h"
\r
31 #include "LinearMath/btScalar.h"
\r
33 #include "BulletMultiThreaded/TrbStateVec.h"
\r
40 #define TMP_BUFF_BYTES (15*1024*1024)
\r
41 unsigned char ATTRIBUTE_ALIGNED128(tmp_buff[TMP_BUFF_BYTES]);
\r
44 static SIMD_FORCE_INLINE vmVector3 btReadVector3(const double* p)
\r
46 float tmp[3] = {float(p[0]),float(p[1]),float(p[2])};
\r
52 static SIMD_FORCE_INLINE vmQuat btReadQuat(const double* p)
\r
54 float tmp[4] = {float(p[0]),float(p[1]),float(p[2]),float(p[4])};
\r
60 static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, double* p)
\r
71 static SIMD_FORCE_INLINE vmVector3 btReadVector3(const float* p)
\r
78 static SIMD_FORCE_INLINE vmQuat btReadQuat(const float* p)
\r
85 static SIMD_FORCE_INLINE void btStoreVector3(const vmVector3 &src, float* p)
\r
95 // Project Gauss Seidel or the equivalent Sequential Impulse
\r
96 inline void resolveSingleConstraintRowGeneric(PfxSolverBody& body1,PfxSolverBody& body2,const btSolverConstraint& c)
\r
99 btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
\r
100 const btScalar deltaVel1Dotn = c.m_contactNormal.dot((btVector3&)body1.m_deltaLinearVelocity) + c.m_relpos1CrossNormal.dot((btVector3&)body1.m_deltaAngularVelocity);
\r
101 const btScalar deltaVel2Dotn = -c.m_contactNormal.dot((btVector3&)body2.m_deltaLinearVelocity) + c.m_relpos2CrossNormal.dot((btVector3&)body2.m_deltaAngularVelocity);
\r
103 // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
\r
104 deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
\r
105 deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
\r
107 const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
\r
108 if (sum < c.m_lowerLimit)
\r
110 deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
\r
111 c.m_appliedImpulse = c.m_lowerLimit;
\r
113 else if (sum > c.m_upperLimit)
\r
115 deltaImpulse = c.m_upperLimit-c.m_appliedImpulse;
\r
116 c.m_appliedImpulse = c.m_upperLimit;
\r
120 c.m_appliedImpulse = sum;
\r
124 if (body1.m_massInv)
\r
126 btVector3 linearComponent = c.m_contactNormal*body1.m_massInv;
\r
127 ((btVector3&)body1.m_deltaLinearVelocity) += linearComponent*deltaImpulse;
\r
128 ((btVector3&)body1.m_deltaAngularVelocity) += c.m_angularComponentA*(btVector3(deltaImpulse,deltaImpulse,deltaImpulse));//*m_angularFactor);
\r
131 if (body2.m_massInv)
\r
133 btVector3 linearComponent = -c.m_contactNormal*body2.m_massInv;
\r
134 ((btVector3&)body2.m_deltaLinearVelocity) += linearComponent*deltaImpulse;
\r
135 ((btVector3&)body2.m_deltaAngularVelocity) += c.m_angularComponentB*((btVector3(deltaImpulse,deltaImpulse,deltaImpulse)));//*m_angularFactor);
\r
138 //body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
\r
139 //body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
\r
144 static SIMD_FORCE_INLINE
\r
145 void pfxSolveLinearConstraintRow(btConstraintRow &constraint,
\r
146 vmVector3 &deltaLinearVelocityA,vmVector3 &deltaAngularVelocityA,
\r
147 float massInvA,const vmMatrix3 &inertiaInvA,const vmVector3 &rA,
\r
148 vmVector3 &deltaLinearVelocityB,vmVector3 &deltaAngularVelocityB,
\r
149 float massInvB,const vmMatrix3 &inertiaInvB,const vmVector3 &rB)
\r
151 const vmVector3 normal(btReadVector3(constraint.m_normal));
\r
152 btScalar deltaImpulse = constraint.m_rhs;
\r
153 vmVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA);
\r
154 vmVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB);
\r
155 deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB);
\r
156 btScalar oldImpulse = constraint.m_accumImpulse;
\r
157 constraint.m_accumImpulse = btClamped(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit);
\r
158 deltaImpulse = constraint.m_accumImpulse - oldImpulse;
\r
159 deltaLinearVelocityA += deltaImpulse * massInvA * normal;
\r
160 deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal);
\r
161 deltaLinearVelocityB -= deltaImpulse * massInvB * normal;
\r
162 deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal);
\r
166 void btSolveContactConstraint(
\r
167 btConstraintRow &constraintResponse,
\r
168 btConstraintRow &constraintFriction1,
\r
169 btConstraintRow &constraintFriction2,
\r
170 const vmVector3 &contactPointA,
\r
171 const vmVector3 &contactPointB,
\r
172 PfxSolverBody &solverBodyA,
\r
173 PfxSolverBody &solverBodyB,
\r
177 vmVector3 rA = rotate(solverBodyA.m_orientation,contactPointA);
\r
178 vmVector3 rB = rotate(solverBodyB.m_orientation,contactPointB);
\r
180 pfxSolveLinearConstraintRow(constraintResponse,
\r
181 solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA,
\r
182 solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB);
\r
184 float mf = friction*fabsf(constraintResponse.m_accumImpulse);
\r
185 constraintFriction1.m_lowerLimit = -mf;
\r
186 constraintFriction1.m_upperLimit = mf;
\r
187 constraintFriction2.m_lowerLimit = -mf;
\r
188 constraintFriction2.m_upperLimit = mf;
\r
190 pfxSolveLinearConstraintRow(constraintFriction1,
\r
191 solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA,
\r
192 solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB);
\r
194 pfxSolveLinearConstraintRow(constraintFriction2,
\r
195 solverBodyA.m_deltaLinearVelocity,solverBodyA.m_deltaAngularVelocity,solverBodyA.m_massInv,solverBodyA.m_inertiaInv,rA,
\r
196 solverBodyB.m_deltaLinearVelocity,solverBodyB.m_deltaAngularVelocity,solverBodyB.m_massInv,solverBodyB.m_inertiaInv,rB);
\r
200 void CustomSolveConstraintsTaskParallel(
\r
201 const PfxParallelGroup *contactParallelGroup,const PfxParallelBatch *contactParallelBatches,
\r
202 PfxConstraintPair *contactPairs,uint32_t numContactPairs,
\r
203 btPersistentManifold* offsetContactManifolds__,
\r
204 const PfxParallelGroup *jointParallelGroup,const PfxParallelBatch *jointParallelBatches,
\r
205 PfxConstraintPair *jointPairs,uint32_t numJointPairs,
\r
206 TrbState *offsetRigStates,
\r
207 PfxSolverBody *offsetSolverBodies,
\r
208 uint32_t numRigidBodies,
\r
209 int iteration,unsigned int taskId,unsigned int numTasks,btBarrier *barrier)
\r
212 PfxSolverBody staticBody;
\r
213 staticBody.m_massInv = 0.f;
\r
214 staticBody.m_deltaAngularVelocity=vmVector3(0,0,0);
\r
215 staticBody.m_deltaLinearVelocity =vmVector3(0,0,0);
\r
218 for(int k=0;k<iteration+1;k++) {
\r
220 for(uint32_t phaseId=0;phaseId<jointParallelGroup->numPhases;phaseId++) {
\r
221 for(uint32_t batchId=0;batchId<jointParallelGroup->numBatches[phaseId];batchId++) {
\r
222 uint32_t numPairs = jointParallelGroup->numPairs[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId];
\r
223 if(batchId%numTasks == taskId && numPairs > 0) {
\r
224 const PfxParallelBatch &batch = jointParallelBatches[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId];
\r
225 for(uint32_t i=0;i<numPairs;i++) {
\r
226 PfxConstraintPair &pair = jointPairs[batch.pairIndices[i]];
\r
227 uint16_t iA = pfxGetObjectIdA(pair);
\r
228 uint16_t iB = pfxGetObjectIdB(pair);
\r
231 PfxSolverBody &solverBodyA = iA != 65535 ? offsetSolverBodies[iA] : staticBody;
\r
232 PfxSolverBody &solverBodyB = iB != 65535 ? offsetSolverBodies[iB] : staticBody;
\r
238 btSolverConstraint* constraintRow = (btSolverConstraint*) pfxGetContactId(pair);
\r
239 int numRows = pfxGetNumConstraints(pair);
\r
241 for (i=0;i<numRows;i++)
\r
243 resolveSingleConstraintRowGeneric(solverBodyA,solverBodyB,constraintRow[i]);
\r
255 for(uint32_t phaseId=0;phaseId<contactParallelGroup->numPhases;phaseId++) {
\r
256 for(uint32_t batchId=0;batchId<contactParallelGroup->numBatches[phaseId];batchId++) {
\r
257 uint32_t numPairs = contactParallelGroup->numPairs[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId];
\r
258 if(batchId%numTasks == taskId && numPairs > 0) {
\r
259 const PfxParallelBatch &batch = contactParallelBatches[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId];
\r
260 for(uint32_t i=0;i<numPairs;i++) {
\r
261 PfxConstraintPair &pair = contactPairs[batch.pairIndices[i]];
\r
262 uint16_t iA = pfxGetObjectIdA(pair);
\r
263 uint16_t iB = pfxGetObjectIdB(pair);
\r
265 btPersistentManifold& contact = *(btPersistentManifold*)pfxGetConstraintId(pair);
\r
268 PfxSolverBody &solverBodyA = offsetSolverBodies[iA];
\r
269 PfxSolverBody &solverBodyB = offsetSolverBodies[iB];
\r
271 for(int j=0;j<contact.getNumContacts();j++) {
\r
272 btManifoldPoint& cp = contact.getContactPoint(j);
\r
275 vmVector3 rA = rotate(solverBodyA.m_orientation,btReadVector3(cp.m_localPointA));
\r
276 vmVector3 rB = rotate(solverBodyB.m_orientation,btReadVector3(cp.m_localPointB));
\r
278 for(int k=0;k<3;k++) {
\r
279 vmVector3 normal = btReadVector3(cp.mConstraintRow[k].m_normal);
\r
280 float deltaImpulse = cp.mConstraintRow[k].m_accumImpulse;
\r
281 solverBodyA.m_deltaLinearVelocity += deltaImpulse * solverBodyA.m_massInv * normal;
\r
282 solverBodyA.m_deltaAngularVelocity += deltaImpulse * solverBodyA.m_inertiaInv * cross(rA,normal);
\r
283 solverBodyB.m_deltaLinearVelocity -= deltaImpulse * solverBodyB.m_massInv * normal;
\r
284 solverBodyB.m_deltaAngularVelocity -= deltaImpulse * solverBodyB.m_inertiaInv * cross(rB,normal);
\r
288 btSolveContactConstraint(
\r
289 cp.mConstraintRow[0],
\r
290 cp.mConstraintRow[1],
\r
291 cp.mConstraintRow[2],
\r
292 btReadVector3(cp.m_localPointA),
\r
293 btReadVector3(cp.m_localPointB),
\r
296 cp.m_combinedFriction
\r
310 void CustomPostSolverTask(
\r
312 PfxSolverBody *solverBodies,
\r
313 uint32_t numRigidBodies)
\r
315 for(uint32_t i=0;i<numRigidBodies;i++) {
\r
316 TrbState &state = states[i];
\r
317 PfxSolverBody &solverBody = solverBodies[i];
\r
318 state.setLinearVelocity(state.getLinearVelocity()+solverBody.m_deltaLinearVelocity);
\r
319 state.setAngularVelocity(state.getAngularVelocity()+solverBody.m_deltaAngularVelocity);
\r
323 void* SolverlsMemoryFunc()
\r
325 //don't create local store memory, just return 0
\r
330 static SIMD_FORCE_INLINE
\r
331 void pfxGetPlaneSpace(const vmVector3& n, vmVector3& p, vmVector3& q)
\r
333 if(fabsf(n[2]) > 0.707f) {
\r
334 // choose p in y-z plane
\r
335 float a = n[1]*n[1] + n[2]*n[2];
\r
336 float k = 1.0f/sqrtf(a);
\r
346 // choose p in x-y plane
\r
347 float a = n[0]*n[0] + n[1]*n[1];
\r
348 float k = 1.0f/sqrtf(a);
\r
361 #define PFX_CONTACT_SLOP 0.001f
\r
363 void btSetupContactConstraint(
\r
364 btConstraintRow &constraintResponse,
\r
365 btConstraintRow &constraintFriction1,
\r
366 btConstraintRow &constraintFriction2,
\r
367 float penetrationDepth,
\r
370 const vmVector3 &contactNormal,
\r
371 const vmVector3 &contactPointA,
\r
372 const vmVector3 &contactPointB,
\r
373 const TrbState &stateA,
\r
374 const TrbState &stateB,
\r
375 PfxSolverBody &solverBodyA,
\r
376 PfxSolverBody &solverBodyB,
\r
377 float separateBias,
\r
381 vmVector3 rA = rotate(solverBodyA.m_orientation,contactPointA);
\r
382 vmVector3 rB = rotate(solverBodyB.m_orientation,contactPointB);
\r
384 vmMatrix3 K = vmMatrix3::scale(vmVector3(solverBodyA.m_massInv + solverBodyB.m_massInv)) -
\r
385 crossMatrix(rA) * solverBodyA.m_inertiaInv * crossMatrix(rA) -
\r
386 crossMatrix(rB) * solverBodyB.m_inertiaInv * crossMatrix(rB);
\r
388 vmVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA);
\r
389 vmVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB);
\r
390 vmVector3 vAB = vA-vB;
\r
392 vmVector3 tangent1,tangent2;
\r
393 btPlaneSpace1(contactNormal,tangent1,tangent2);
\r
395 // constraintResponse.m_accumImpulse = 0.f;
\r
396 // constraintFriction1.m_accumImpulse = 0.f;
\r
397 // constraintFriction2.m_accumImpulse = 0.f;
\r
399 // Contact Constraint
\r
401 vmVector3 normal = contactNormal;
\r
403 float denom = dot(K*normal,normal);
\r
405 constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error
\r
406 constraintResponse.m_rhs -= (separateBias * btMin(0.0f,penetrationDepth+PFX_CONTACT_SLOP)) / timeStep; // position error
\r
407 constraintResponse.m_rhs /= denom;
\r
408 constraintResponse.m_jacDiagInv = 1.0f/denom;
\r
409 constraintResponse.m_lowerLimit = 0.0f;
\r
410 constraintResponse.m_upperLimit = SIMD_INFINITY;
\r
411 btStoreVector3(normal,constraintResponse.m_normal);
\r
414 // Friction Constraint 1
\r
416 vmVector3 normal = tangent1;
\r
418 float denom = dot(K*normal,normal);
\r
420 constraintFriction1.m_jacDiagInv = 1.0f/denom;
\r
421 constraintFriction1.m_rhs = -dot(vAB,normal);
\r
422 constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv;
\r
423 constraintFriction1.m_lowerLimit = 0.0f;
\r
424 constraintFriction1.m_upperLimit = SIMD_INFINITY;
\r
425 btStoreVector3(normal,constraintFriction1.m_normal);
\r
428 // Friction Constraint 2
\r
430 vmVector3 normal = tangent2;
\r
432 float denom = dot(K*normal,normal);
\r
434 constraintFriction2.m_jacDiagInv = 1.0f/denom;
\r
435 constraintFriction2.m_rhs = -dot(vAB,normal);
\r
436 constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv;
\r
437 constraintFriction2.m_lowerLimit = 0.0f;
\r
438 constraintFriction2.m_upperLimit = SIMD_INFINITY;
\r
439 btStoreVector3(normal,constraintFriction2.m_normal);
\r
444 void CustomSetupContactConstraintsTask(
\r
445 PfxConstraintPair *contactPairs,uint32_t numContactPairs,
\r
446 TrbState *offsetRigStates,
\r
447 PfxSolverBody *offsetSolverBodies,
\r
448 uint32_t numRigidBodies,
\r
449 float separateBias,
\r
452 for(uint32_t i=0;i<numContactPairs;i++) {
\r
453 PfxConstraintPair &pair = contactPairs[i];
\r
454 if(!pfxGetActive(pair) || pfxGetNumConstraints(pair) == 0 ||
\r
455 ((pfxGetMotionMaskA(pair)&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pair)&PFX_MOTION_MASK_STATIC)) ) {
\r
459 uint16_t iA = pfxGetObjectIdA(pair);
\r
460 uint16_t iB = pfxGetObjectIdB(pair);
\r
462 btPersistentManifold &contact = *(btPersistentManifold*)pfxGetConstraintId(pair);
\r
465 TrbState &stateA = offsetRigStates[iA];
\r
466 // PfxRigBody &bodyA = offsetRigBodies[iA];
\r
467 PfxSolverBody &solverBodyA = offsetSolverBodies[iA];
\r
469 TrbState &stateB = offsetRigStates[iB];
\r
470 // PfxRigBody &bodyB = offsetRigBodies[iB];
\r
471 PfxSolverBody &solverBodyB = offsetSolverBodies[iB];
\r
472 #ifdef SOLVERBODY_FRICTION
\r
473 float restitution = 0.5f * (solverBodyA.restitution + solverBodyB.restitution);
\r
474 float friction = sqrtf(solverBodyA.friction * solverBodyB.friction);
\r
476 float restitution = 0.f;
\r
477 float friction = 0.5;
\r
479 #endif //SOLVERBODY_FRICTION
\r
481 for(int j=0;j<contact.getNumContacts();j++) {
\r
482 btManifoldPoint& cp = contact.getContactPoint(j);
\r
484 btSetupContactConstraint(
\r
485 cp.mConstraintRow[0],
\r
486 cp.mConstraintRow[1],
\r
487 cp.mConstraintRow[2],
\r
491 btReadVector3(cp.m_normalWorldOnB),//.mConstraintRow[0].m_normal),
\r
492 btReadVector3(cp.m_localPointA),
\r
493 btReadVector3(cp.m_localPointB),
\r
503 //contact.setCompositeFriction(friction);
\r
507 void SolverThreadFunc(void* userPtr,void* lsMemory)
\r
509 btConstraintSolverIO* io = (btConstraintSolverIO*)(userPtr);//arg->io);
\r
510 btCriticalSection* criticalsection = io->setupContactConstraints.criticalSection;
\r
513 //CustomCriticalSection *criticalsection = &io->m_cs;
\r
516 case PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS:
\r
517 CustomSolveConstraintsTaskParallel(
\r
518 io->solveConstraints.contactParallelGroup,
\r
519 io->solveConstraints.contactParallelBatches,
\r
520 io->solveConstraints.contactPairs,
\r
521 io->solveConstraints.numContactPairs,
\r
522 io->solveConstraints.offsetContactManifolds,
\r
524 io->solveConstraints.jointParallelGroup,
\r
525 io->solveConstraints.jointParallelBatches,
\r
526 io->solveConstraints.jointPairs,
\r
527 io->solveConstraints.numJointPairs,
\r
529 io->solveConstraints.offsetRigStates,
\r
530 io->solveConstraints.offsetSolverBodies,
\r
531 io->solveConstraints.numRigidBodies,
\r
532 io->solveConstraints.iteration,
\r
534 io->solveConstraints.taskId,
\r
536 io->solveConstraints.barrier
\r
540 case PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER:
\r
541 CustomPostSolverTask( io->postSolver.states,io->postSolver.solverBodies, io->postSolver.numRigidBodies);
\r
545 case PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS:
\r
547 bool empty = false;
\r
551 criticalsection->lock();
\r
553 start = (int)criticalsection->getSharedParam(0);
\r
554 batch = (int)criticalsection->getSharedParam(1);
\r
556 //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch);
\r
558 //
\8e\9f\82Ì
\83o
\83b
\83t
\83@
\82ð
\83Z
\83b
\83g
\r
559 int nextStart = start + batch;
\r
560 int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0);
\r
561 int nextBatch = (rest > batch)?batch:rest;
\r
563 criticalsection->setSharedParam(0,nextStart);
\r
564 criticalsection->setSharedParam(1,nextBatch);
\r
566 criticalsection->unlock();
\r
569 CustomSetupContactConstraintsTask(
\r
570 io->setupContactConstraints.offsetContactPairs+start,batch,
\r
571 // io->setupContactConstraints.offsetContactManifolds,
\r
572 io->setupContactConstraints.offsetRigStates,
\r
573 // io->setupContactConstraints.offsetRigBodies,
\r
574 io->setupContactConstraints.offsetSolverBodies,
\r
575 io->setupContactConstraints.numRigidBodies,
\r
576 io->setupContactConstraints.separateBias,
\r
577 io->setupContactConstraints.timeStep);
\r
595 void CustomSetupContactConstraintsNew(
\r
596 PfxConstraintPair *contactPairs1,uint32_t numContactPairs,
\r
597 btPersistentManifold *offsetContactManifolds,
\r
598 TrbState *offsetRigStates,
\r
599 PfxSolverBody *offsetSolverBodies,
\r
600 uint32_t numRigidBodies,
\r
601 float separationBias,
\r
603 class btThreadSupportInterface* threadSupport,
\r
604 btCriticalSection* criticalSection,
\r
605 btConstraintSolverIO *io
\r
608 int maxTasks = threadSupport->getNumTasks();
\r
610 int div = (int)maxTasks * 4;
\r
611 int batch = ((int)numContactPairs + div - 1) / div;
\r
613 BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport;
\r
615 if (criticalSection)
\r
617 criticalSection->setSharedParam(0,0);
\r
618 criticalSection->setSharedParam(1,btMin(batch,64)); // batched number
\r
622 spursThread->setSharedParam(0,0);
\r
623 spursThread->setSharedParam(1,btMin(batch,64)); // batched number
\r
627 for(int t=0;t<maxTasks;t++) {
\r
628 io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS;
\r
629 io[t].setupContactConstraints.offsetContactPairs = contactPairs1;
\r
630 io[t].setupContactConstraints.numContactPairs1 = numContactPairs;
\r
631 io[t].setupContactConstraints.offsetRigStates = offsetRigStates;
\r
632 io[t].setupContactConstraints.offsetSolverBodies = offsetSolverBodies;
\r
633 io[t].setupContactConstraints.numRigidBodies = numRigidBodies;
\r
634 io[t].setupContactConstraints.separateBias = separationBias;
\r
635 io[t].setupContactConstraints.timeStep = timeStep;
\r
636 io[t].setupContactConstraints.criticalSection = criticalSection;
\r
637 io[t].maxTasks1 = maxTasks;
\r
639 io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress();
\r
640 io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress();
\r
644 //#define SEQUENTIAL_SETUP
\r
645 #ifdef SEQUENTIAL_SETUP
\r
646 CustomSetupContactConstraintsTask(contactPairs1,numContactPairs,offsetRigStates,offsetSolverBodies,numRigidBodies,separationBias,timeStep);
\r
648 threadSupport->sendRequest(1,(ppu_address_t)&io[t],t);
\r
652 #ifndef SEQUENTIAL_SETUP
\r
653 unsigned int arg0,arg1;
\r
654 for(int t=0;t<maxTasks;t++) {
\r
656 threadSupport->waitForResponse(&arg0,&arg1);
\r
658 #endif //SEQUENTIAL_SETUP
\r
663 void CustomSplitConstraints(
\r
664 PfxConstraintPair *pairs,uint32_t numPairs,
\r
665 PfxParallelGroup &group,PfxParallelBatch *batches,
\r
667 uint32_t numRigidBodies,
\r
672 HeapManager pool((unsigned char*)poolBuff,poolBytes);
\r
674 //
\83X
\83e
\81[
\83g
\83`
\83F
\83b
\83N
\97p
\83r
\83b
\83g
\83t
\83\89\83O
\83e
\81[
\83u
\83\8b\r
675 int bufSize = sizeof(uint8_t)*numRigidBodies;
\r
676 bufSize = ((bufSize+127)>>7)<<7; // 128 bytes alignment
\r
677 uint8_t *bodyTable = (uint8_t*)pool.allocate(bufSize,HeapManager::ALIGN128);
\r
679 //
\83y
\83A
\83`
\83F
\83b
\83N
\97p
\83r
\83b
\83g
\83t
\83\89\83O
\83e
\81[
\83u
\83\8b\r
680 uint32_t *pairTable;
\r
681 size_t allocSize = sizeof(uint32_t)*((numPairs+31)/32);
\r
682 pairTable = (uint32_t*)pool.allocate(allocSize);
\r
683 memset(pairTable,0,allocSize);
\r
685 //
\96Ú
\95W
\82Æ
\82·
\82é
\95ª
\8a\84\90\94\r
686 uint32_t targetCount = btMax(uint32_t(SCE_PFX_MIN_SOLVER_PAIRS),btMin(numPairs / (numTasks*2),uint32_t(SCE_PFX_MAX_SOLVER_PAIRS)));
\r
687 uint32_t startIndex = 0;
\r
691 uint32_t totalCount=0;
\r
693 uint32_t maxBatches = btMin(numTasks,uint32_t(SCE_PFX_MAX_SOLVER_BATCHES));
\r
695 for(phaseId=0;phaseId<SCE_PFX_MAX_SOLVER_PHASES&&totalCount<numPairs;phaseId++) {
\r
696 bool startIndexCheck = true;
\r
698 group.numBatches[phaseId] = 0;
\r
700 uint32_t i = startIndex;
\r
702 //
\83`
\83F
\83b
\83N
\97p
\83r
\83b
\83g
\83t
\83\89\83O
\83e
\81[
\83u
\83\8b\82ð
\83N
\83\8a\83A
\r
703 memset(bodyTable,0xff,bufSize);
\r
705 for(batchId=0;i<numPairs&&totalCount<numPairs&&batchId<maxBatches;batchId++) {
\r
706 uint32_t pairCount=0;
\r
708 PfxParallelBatch &batch = batches[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId];
\r
709 uint32_t pairId = 0;
\r
711 for(;i<numPairs&&pairCount<targetCount;i++) {
\r
712 uint32_t idxP = i>>5;
\r
713 uint32_t maskP = 1L << (i & 31);
\r
715 //pair is already assigned to a phase/batch
\r
716 if(pairTable[idxP] & maskP) {
\r
720 uint32_t idxA = pfxGetObjectIdA(pairs[i]);
\r
721 uint32_t idxB = pfxGetObjectIdB(pairs[i]);
\r
723 //
\97¼
\95û
\82Æ
\82à
\83A
\83N
\83e
\83B
\83u
\82Å
\82È
\82¢
\81A
\82Ü
\82½
\82Í
\8fÕ
\93Ë
\93_
\82ª
\82O
\82Ì
\83y
\83A
\82Í
\93o
\98^
\91Î
\8fÛ
\82©
\82ç
\82Í
\82¸
\82·
\r
724 if(!pfxGetActive(pairs[i]) || pfxGetNumConstraints(pairs[i]) == 0 ||
\r
725 ((pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_STATIC)) ) {
\r
726 if(startIndexCheck)
\r
728 //assign pair -> skip it because it has no constraints
\r
729 pairTable[idxP] |= maskP;
\r
734 //
\88Ë
\91¶
\90«
\82Ì
\83`
\83F
\83b
\83N
\r
735 if( (bodyTable[idxA] != batchId && bodyTable[idxA] != 0xff) ||
\r
736 (bodyTable[idxB] != batchId && bodyTable[idxB] != 0xff) ) {
\r
737 startIndexCheck = false;
\r
738 //bodies of the pair are already assigned to another batch within this phase
\r
742 //
\88Ë
\91¶
\90«
\94»
\92è
\83e
\81[
\83u
\83\8b\82É
\93o
\98^
\r
743 if(pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_DYNAMIC)
\r
744 bodyTable[idxA] = batchId;
\r
745 if(pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_DYNAMIC)
\r
746 bodyTable[idxB] = batchId;
\r
748 if(startIndexCheck)
\r
751 pairTable[idxP] |= maskP;
\r
752 //add the pair 'i' to the current batch
\r
753 batch.pairIndices[pairId++] = i;
\r
757 group.numPairs[phaseId*SCE_PFX_MAX_SOLVER_BATCHES+batchId] = (uint16_t)pairId;
\r
758 totalCount += pairCount;
\r
761 group.numBatches[phaseId] = batchId;
\r
764 group.numPhases = phaseId;
\r
771 void CustomSolveConstraintsParallel(
\r
772 PfxConstraintPair *contactPairs,uint32_t numContactPairs,
\r
774 PfxConstraintPair *jointPairs,uint32_t numJointPairs,
\r
776 TrbState *offsetRigStates,
\r
777 PfxSolverBody *offsetSolverBodies,
\r
778 uint32_t numRigidBodies,
\r
779 struct btConstraintSolverIO* io,
\r
780 class btThreadSupportInterface* threadSupport,
\r
784 class btBarrier* barrier)
\r
787 int maxTasks = threadSupport->getNumTasks();
\r
788 // config.taskManager->setTaskEntry(PFX_SOLVER_ENTRY);
\r
790 HeapManager pool((unsigned char*)poolBuf,poolBytes);
\r
793 PfxParallelGroup *cgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup));
\r
794 PfxParallelBatch *cbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES),128);
\r
795 PfxParallelGroup *jgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup));
\r
796 PfxParallelBatch *jbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES),128);
\r
798 uint32_t tmpBytes = poolBytes - 2 * (sizeof(PfxParallelGroup) + sizeof(PfxParallelBatch)*(SCE_PFX_MAX_SOLVER_PHASES*SCE_PFX_MAX_SOLVER_BATCHES) + 128);
\r
799 void *tmpBuff = pool.allocate(tmpBytes);
\r
802 BT_PROFILE("CustomSplitConstraints");
\r
803 CustomSplitConstraints(contactPairs,numContactPairs,*cgroup,cbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes);
\r
804 CustomSplitConstraints(jointPairs,numJointPairs,*jgroup,jbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes);
\r
808 BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS");
\r
809 //#define SOLVE_SEQUENTIAL
\r
810 #ifdef SOLVE_SEQUENTIAL
\r
811 CustomSolveConstraintsTask(
\r
812 io->solveConstraints.contactParallelGroup,
\r
813 io->solveConstraints.contactParallelBatches,
\r
814 io->solveConstraints.contactPairs,
\r
815 io->solveConstraints.numContactPairs,
\r
816 io->solveConstraints.offsetContactManifolds,
\r
818 io->solveConstraints.jointParallelGroup,
\r
819 io->solveConstraints.jointParallelBatches,
\r
820 io->solveConstraints.jointPairs,
\r
821 io->solveConstraints.numJointPairs,
\r
822 io->solveConstraints.offsetJoints,
\r
824 io->solveConstraints.offsetRigStates,
\r
825 io->solveConstraints.offsetSolverBodies,
\r
826 io->solveConstraints.numRigidBodies,
\r
827 io->solveConstraints.iteration,0,1,0);//arg->taskId,1,0);//,arg->maxTasks,arg->barrier);
\r
829 for(int t=0;t<maxTasks;t++) {
\r
830 io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS;
\r
831 io[t].solveConstraints.contactParallelGroup = cgroup;
\r
832 io[t].solveConstraints.contactParallelBatches = cbatches;
\r
833 io[t].solveConstraints.contactPairs = contactPairs;
\r
834 io[t].solveConstraints.numContactPairs = numContactPairs;
\r
835 // io[t].solveConstraints.offsetContactManifolds = offsetContactManifolds;
\r
836 io[t].solveConstraints.jointParallelGroup = jgroup;
\r
837 io[t].solveConstraints.jointParallelBatches = jbatches;
\r
838 io[t].solveConstraints.jointPairs = jointPairs;
\r
839 io[t].solveConstraints.numJointPairs = numJointPairs;
\r
840 io[t].solveConstraints.offsetRigStates = offsetRigStates;
\r
841 io[t].solveConstraints.offsetSolverBodies = offsetSolverBodies;
\r
842 io[t].solveConstraints.numRigidBodies = numRigidBodies;
\r
843 io[t].solveConstraints.iteration = iteration;
\r
844 io[t].solveConstraints.taskId = t;
\r
845 io[t].solveConstraints.barrier = barrier;
\r
847 io[t].maxTasks1 = maxTasks;
\r
849 BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport;
\r
850 io[t].barrierAddr2 = (unsigned int) spursThread->getBarrierAddress();
\r
851 io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress();
\r
854 threadSupport->sendRequest(1,(ppu_address_t)&io[t],t);
\r
857 unsigned int arg0,arg1;
\r
858 for(int t=0;t<maxTasks;t++) {
\r
860 threadSupport->waitForResponse(&arg0,&arg1);
\r
868 BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER");
\r
869 int batch = ((int)numRigidBodies + maxTasks - 1) / maxTasks;
\r
870 int rest = (int)numRigidBodies;
\r
873 for(int t=0;t<maxTasks;t++) {
\r
874 int num = (rest - batch ) > 0 ? batch : rest;
\r
875 io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER;
\r
876 io[t].postSolver.states = offsetRigStates + start;
\r
877 io[t].postSolver.solverBodies = offsetSolverBodies + start;
\r
878 io[t].postSolver.numRigidBodies = (uint32_t)num;
\r
879 io[t].maxTasks1 = maxTasks;
\r
881 BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport;
\r
882 io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress();
\r
883 io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress();
\r
886 #ifdef SOLVE_SEQUENTIAL
\r
887 CustomPostSolverTask( io[t].postSolver.states,io[t].postSolver.solverBodies, io[t].postSolver.numRigidBodies);
\r
889 threadSupport->sendRequest(1,(ppu_address_t)&io[t],t);
\r
895 unsigned int arg0,arg1;
\r
896 for(int t=0;t<maxTasks;t++) {
\r
897 #ifndef SOLVE_SEQUENTIAL
\r
899 threadSupport->waitForResponse(&arg0,&arg1);
\r
908 void BPE_customConstraintSolverSequentialNew(unsigned int new_num, PfxBroadphasePair *new_pairs1 ,
\r
909 TrbState* states,int numRigidBodies,
\r
910 struct PfxSolverBody* solverBodies,
\r
911 btPersistentManifold* contacts,
\r
912 PfxConstraintPair* jointPairs, unsigned int numJoints,
\r
913 float separateBias,
\r
916 btThreadSupportInterface* solverThreadSupport,
\r
917 btCriticalSection* criticalSection,
\r
918 struct btConstraintSolverIO* solverIO,
\r
924 BT_PROFILE("pfxSetupConstraints");
\r
926 for(uint32_t i=0;i<numJoints;i++) {
\r
927 //
\8fî
\95ñ
\82Ì
\8dX
\90V
\r
928 PfxConstraintPair &pair = jointPairs[i];
\r
929 int idA = pfxGetObjectIdA(pair);
\r
933 pfxSetMotionMaskA(pair,states[pfxGetObjectIdA(pair)].getMotionMask());
\r
937 pfxSetMotionMaskA(pair,PFX_MOTION_MASK_STATIC);
\r
939 int idB = pfxGetObjectIdB(pair);
\r
942 pfxSetMotionMaskB(pair,states[pfxGetObjectIdB(pair)].getMotionMask());
\r
945 pfxSetMotionMaskB(pair,PFX_MOTION_MASK_STATIC);
\r
949 // CustomSetupJointConstraintsSeq( jointPairs,numJoints,joints, states, solverBodies, numRigidBodies, timeStep);
\r
951 #ifdef SEQUENTIAL_SETUP
\r
952 CustomSetupContactConstraintsSeqNew(
\r
953 (PfxConstraintPair*)new_pairs1,new_num,contacts,
\r
960 CustomSetupContactConstraintsNew(
\r
961 (PfxConstraintPair*)new_pairs1,new_num,contacts,
\r
967 solverThreadSupport,
\r
968 criticalSection,solverIO
\r
971 #endif //SEQUENTIAL_SETUP
\r
975 BT_PROFILE("pfxSolveConstraints");
\r
977 //#define SEQUENTIAL
\r
979 CustomSolveConstraintsSeq(
\r
980 (PfxConstraintPair*)new_pairs1,new_num,contacts,
\r
981 jointPairs,numJoints,
\r
989 CustomSolveConstraintsParallel(
\r
990 (PfxConstraintPair*)new_pairs1,new_num,
\r
991 jointPairs,numJoints,
\r
995 solverIO, solverThreadSupport,
\r
1002 #endif //SEQUENTIAL
\r
1008 struct btParallelSolverMemoryCache
\r
1010 btAlignedObjectArray<TrbState> m_mystates;
\r
1011 btAlignedObjectArray<PfxSolverBody> m_mysolverbodies;
\r
1012 btAlignedObjectArray<PfxBroadphasePair> m_mypairs;
\r
1013 btAlignedObjectArray<PfxConstraintPair> m_jointPairs;
\r
1018 btConstraintSolverIO* createSolverIO(int numThreads)
\r
1020 return new btConstraintSolverIO[numThreads];
\r
1023 btLowLevelConstraintSolver::btLowLevelConstraintSolver(btThreadSupportInterface* solverThreadSupport)
\r
1026 m_solverThreadSupport = solverThreadSupport;//createSolverThreadSupport(maxNumThreads);
\r
1027 m_solverIO = createSolverIO(m_solverThreadSupport->getNumTasks());
\r
1029 m_barrier = m_solverThreadSupport->createBarrier();
\r
1030 m_criticalSection = m_solverThreadSupport->createCriticalSection();
\r
1032 m_memoryCache = new btParallelSolverMemoryCache();
\r
1035 btLowLevelConstraintSolver::~btLowLevelConstraintSolver()
\r
1037 delete m_memoryCache;
\r
1038 delete m_solverIO;
\r
1043 btScalar btLowLevelConstraintSolver::solveGroup(btCollisionObject** bodies1,int numRigidBodies,btPersistentManifold** manifoldPtr,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher)
\r
1046 /* int sz = sizeof(PfxSolverBody);
\r
1047 int sz2 = sizeof(vmVector3);
\r
1048 int sz3 = sizeof(vmMatrix3);
\r
1049 int sz4 = sizeof(vmQuat);
\r
1050 int sz5 = sizeof(btConstraintRow);
\r
1051 int sz6 = sizeof(btSolverConstraint);
\r
1052 int sz7 = sizeof(TrbState);
\r
1056 m_memoryCache->m_mysolverbodies.resize(numRigidBodies);
\r
1057 m_memoryCache->m_mystates.resize(numRigidBodies);
\r
1060 BT_PROFILE("create states and solver bodies");
\r
1061 for (int i=0;i<numRigidBodies;i++)
\r
1063 btCollisionObject* obj = bodies1[i];
\r
1064 obj->setCompanionId(i);
\r
1066 PfxSolverBody& solverBody = m_memoryCache->m_mysolverbodies[i];
\r
1067 btRigidBody* rb = btRigidBody::upcast(obj);
\r
1068 TrbState& state = m_memoryCache->m_mystates[i];
\r
1071 const btQuaternion& orgOri = obj->getWorldTransform().getRotation();
\r
1072 vmQuat orn(orgOri.getX(),orgOri.getY(),orgOri.getZ(),orgOri.getW());
\r
1073 state.setPosition((vmVector3&) obj->getWorldTransform().getOrigin());
\r
1074 state.setOrientation(orn);
\r
1075 state.setPosition(state.getPosition());
\r
1076 state.setRigidBodyId(i);
\r
1077 state.setAngularDamping(0);
\r
1078 state.setLinearDamping(0);
\r
1081 solverBody.m_orientation = state.getOrientation();
\r
1082 solverBody.m_deltaLinearVelocity = vmVector3(0.0f);
\r
1083 solverBody.m_deltaAngularVelocity = vmVector3(0.0f);
\r
1084 #ifdef SOLVERBODY_FRICTION
\r
1085 solverBody.friction = obj->getFriction();
\r
1086 solverBody.restitution = obj->getRestitution();
\r
1087 #endif //SOLVERBODY_FRICTION
\r
1088 state.resetSleepCount();
\r
1090 //if(state.getMotionMask()&PFX_MOTION_MASK_DYNAMIC) {
\r
1091 if (rb && (rb->getInvMass()>0.f))
\r
1093 state.setAngularVelocity(vmVector3(rb->getAngularVelocity().getX(),rb->getAngularVelocity().getY(),rb->getAngularVelocity().getZ()));
\r
1094 state.setLinearVelocity(vmVector3(rb->getLinearVelocity().getX(),rb->getLinearVelocity().getY(),rb->getLinearVelocity().getZ()));
\r
1096 state.setMotionType(PfxMotionTypeActive);
\r
1097 vmMatrix3 ori(solverBody.m_orientation);
\r
1098 vmMatrix3 localInvInertia = vmMatrix3::identity();
\r
1099 localInvInertia.setCol(0,vmVector3(rb->getInvInertiaDiagLocal().getX(),0,0));
\r
1100 localInvInertia.setCol(1,vmVector3(0, rb->getInvInertiaDiagLocal().getY(),0));
\r
1101 localInvInertia.setCol(2,vmVector3(0,0, rb->getInvInertiaDiagLocal().getZ()));
\r
1103 solverBody.m_massInv = rb->getInvMass();
\r
1104 solverBody.m_inertiaInv = ori * localInvInertia * transpose(ori);
\r
1107 state.setAngularVelocity(vmVector3(0));
\r
1108 state.setLinearVelocity(vmVector3(0));
\r
1110 state.setMotionType(PfxMotionTypeFixed);
\r
1111 m_memoryCache->m_mysolverbodies[i].m_massInv = 0.f;
\r
1112 m_memoryCache->m_mysolverbodies[i].m_inertiaInv = vmMatrix3(0.0f);
\r
1120 int totalPoints = 0;
\r
1121 #ifndef USE_C_ARRAYS
\r
1122 m_memoryCache->m_mypairs.resize(numManifolds);
\r
1123 m_memoryCache->m_jointPairs.resize(numConstraints);
\r
1124 #endif//USE_C_ARRAYS
\r
1126 int actualNumManifolds= 0;
\r
1128 BT_PROFILE("convert manifolds");
\r
1129 for (int i1=0;i1<numManifolds;i1++)
\r
1131 if (manifoldPtr[i1]->getNumContacts()>0)
\r
1133 btPersistentManifold* m = manifoldPtr[i1];
\r
1134 btCollisionObject* obA = (btCollisionObject*)m->getBody0();
\r
1135 btCollisionObject* obB = (btCollisionObject*)m->getBody1();
\r
1136 bool obAisActive = !obA->isStaticOrKinematicObject() && obA->isActive();
\r
1137 bool obBisActive = !obB->isStaticOrKinematicObject() && obB->isActive();
\r
1139 if (!obAisActive && !obBisActive)
\r
1143 //int contactId = i1;//actualNumManifolds;
\r
1145 PfxBroadphasePair& pair = m_memoryCache->m_mypairs[actualNumManifolds];
\r
1147 float compFric = obA->getFriction()*obB->getFriction();//@todo
\r
1148 int idA = obA->getCompanionId();
\r
1149 int idB = obB->getCompanionId();
\r
1151 m->m_companionIdA = idA;
\r
1152 m->m_companionIdB = idB;
\r
1155 // if ((mysolverbodies[idA].m_massInv!=0)&&(mysolverbodies[idB].m_massInv!=0))
\r
1157 int numPosPoints=0;
\r
1158 for (int p=0;p<m->getNumContacts();p++)
\r
1160 //btManifoldPoint& pt = m->getContactPoint(p);
\r
1161 //float dist = pt.getDistance();
\r
1167 numPosPoints = numPosPoints;
\r
1168 totalPoints+=numPosPoints;
\r
1169 pfxSetObjectIdA(pair,idA);
\r
1170 pfxSetObjectIdB(pair,idB);
\r
1171 pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask());
\r
1172 pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask());
\r
1173 pfxSetActive(pair,numPosPoints>0);
\r
1175 pfxSetBroadphaseFlag(pair,0);
\r
1176 pfxSetContactId(pair,(uint32_t)m);//contactId);
\r
1177 pfxSetNumConstraints(pair,numPosPoints);//manifoldPtr[i]->getNumContacts());
\r
1178 actualNumManifolds++;
\r
1184 PfxConstraintPair* jointPairs=0;
\r
1185 jointPairs = numConstraints? &m_memoryCache->m_jointPairs[0]:0;
\r
1186 int actualNumJoints=0;
\r
1191 BT_PROFILE("convert constraints");
\r
1194 int totalNumRows = 0;
\r
1197 m_tmpConstraintSizesPool.resize(numConstraints);
\r
1198 //calculate the total number of contraint rows
\r
1199 for (i=0;i<numConstraints;i++)
\r
1201 btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
\r
1202 constraints[i]->getInfo1(&info1);
\r
1203 totalNumRows += info1.m_numConstraintRows;
\r
1205 m_tmpSolverNonContactConstraintPool.resize(totalNumRows);
\r
1208 ///setup the btSolverConstraints
\r
1209 int currentRow = 0;
\r
1211 for (i=0;i<numConstraints;i++)
\r
1213 const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
\r
1215 if (info1.m_numConstraintRows)
\r
1217 btAssert(currentRow<totalNumRows);
\r
1219 btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
\r
1220 btTypedConstraint* constraint = constraints[i];
\r
1224 btRigidBody& rbA = constraint->getRigidBodyA();
\r
1225 btRigidBody& rbB = constraint->getRigidBodyB();
\r
1229 for ( j=0;j<info1.m_numConstraintRows;j++)
\r
1231 memset(¤tConstraintRow[j],0,sizeof(btSolverConstraint));
\r
1232 currentConstraintRow[j].m_lowerLimit = -FLT_MAX;
\r
1233 currentConstraintRow[j].m_upperLimit = FLT_MAX;
\r
1234 currentConstraintRow[j].m_appliedImpulse = 0.f;
\r
1235 currentConstraintRow[j].m_appliedPushImpulse = 0.f;
\r
1236 currentConstraintRow[j].m_solverBodyA = &rbA;
\r
1237 currentConstraintRow[j].m_solverBodyB = &rbB;
\r
1240 rbA.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
\r
1241 rbA.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
\r
1242 rbB.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
\r
1243 rbB.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
\r
1247 btTypedConstraint::btConstraintInfo2 info2;
\r
1248 info2.fps = 1.f/infoGlobal.m_timeStep;
\r
1249 info2.erp = infoGlobal.m_erp;
\r
1250 info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
\r
1251 info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
\r
1252 info2.m_J2linearAxis = 0;
\r
1253 info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
\r
1254 info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
\r
1255 ///the size of btSolverConstraint needs be a multiple of btScalar
\r
1256 btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
\r
1257 info2.m_constraintError = ¤tConstraintRow->m_rhs;
\r
1258 currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
\r
1259 info2.cfm = ¤tConstraintRow->m_cfm;
\r
1260 info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit;
\r
1261 info2.m_upperLimit = ¤tConstraintRow->m_upperLimit;
\r
1262 info2.m_numIterations = infoGlobal.m_numIterations;
\r
1263 constraints[i]->getInfo2(&info2);
\r
1265 int idA = constraint->getRigidBodyA().getCompanionId();
\r
1266 int idB = constraint->getRigidBodyB().getCompanionId();
\r
1269 ///finalize the constraint setup
\r
1270 for ( j=0;j<info1.m_numConstraintRows;j++)
\r
1272 btSolverConstraint& solverConstraint = currentConstraintRow[j];
\r
1273 solverConstraint.m_originalContactPoint = constraint;
\r
1275 solverConstraint.m_companionIdA = idA;
\r
1276 solverConstraint.m_companionIdB = idB;
\r
1279 const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
\r
1280 solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
\r
1283 const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
\r
1284 solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
\r
1288 btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass();
\r
1289 btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
\r
1290 btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal?
\r
1291 btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
\r
1293 btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
\r
1294 sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
\r
1295 sum += iMJlB.dot(solverConstraint.m_contactNormal);
\r
1296 sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
\r
1298 solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
\r
1303 ///todo: add force/torque accelerators
\r
1306 btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity());
\r
1307 btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity());
\r
1309 rel_vel = vel1Dotn+vel2Dotn;
\r
1311 btScalar restitution = 0.f;
\r
1312 btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
\r
1313 btScalar velocityError = restitution - rel_vel;// * damping;
\r
1314 btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
\r
1315 btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
\r
1316 solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
\r
1317 solverConstraint.m_appliedImpulse = 0.f;
\r
1322 PfxConstraintPair& pair = jointPairs[actualNumJoints];
\r
1324 int numConstraintRows= info1.m_numConstraintRows;
\r
1325 pfxSetNumConstraints(pair,numConstraintRows);
\r
1329 pfxSetObjectIdA(pair,idA);
\r
1330 pfxSetObjectIdB(pair,idB);
\r
1332 pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask());
\r
1333 pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask());
\r
1335 pfxSetActive(pair,true);
\r
1336 pfxSetContactId(pair,(uint32_t)currentConstraintRow);//contactId);
\r
1337 actualNumJoints++;
\r
1341 currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
\r
1348 float separateBias=0.1;//info.m_erp;//or m_erp2?
\r
1349 float timeStep=infoGlobal.m_timeStep;
\r
1350 int iteration=infoGlobal.m_numIterations;
\r
1352 //create a pair for each constraints, copy over info etc
\r
1359 BT_PROFILE("compute num contacts");
\r
1360 int totalContacts =0;
\r
1362 for (int i=0;i<actualNumManifolds;i++)
\r
1364 PfxConstraintPair* pair = &m_memoryCache->m_mypairs[i];
\r
1365 totalContacts += pfxGetNumConstraints(*pair);
\r
1367 //printf("numManifolds = %d\n",numManifolds);
\r
1368 //printf("totalContacts=%d\n",totalContacts);
\r
1373 // printf("actualNumManifolds=%d\n",actualNumManifolds);
\r
1375 BT_PROFILE("BPE_customConstraintSolverSequentialNew");
\r
1376 if (numRigidBodies>0 && (actualNumManifolds+actualNumJoints)>0)
\r
1378 // PFX_PRINTF("num points = %d\n",totalPoints);
\r
1379 // PFX_PRINTF("num points PFX = %d\n",total);
\r
1381 BPE_customConstraintSolverSequentialNew(
\r
1382 actualNumManifolds,
\r
1383 &m_memoryCache->m_mypairs[0],
\r
1384 &m_memoryCache->m_mystates[0],numRigidBodies,
\r
1385 &m_memoryCache->m_mysolverbodies[0],
\r
1386 0,//manifoldArray,
\r
1387 jointPairs,actualNumJoints,separateBias,timeStep,iteration,
\r
1388 m_solverThreadSupport,m_criticalSection,m_solverIO,m_barrier);
\r
1392 //copy results back to bodies
\r
1394 BT_PROFILE("copy back");
\r
1395 for (int i=0;i<numRigidBodies;i++)
\r
1397 btCollisionObject* obj = bodies1[i];
\r
1398 btRigidBody* rb = btRigidBody::upcast(obj);
\r
1399 TrbState& state = m_memoryCache->m_mystates[i];
\r
1400 if (rb && (rb->getInvMass()>0.f))
\r
1402 rb->setLinearVelocity(btVector3(state.getLinearVelocity().getX(),state.getLinearVelocity().getY(),state.getLinearVelocity().getZ()));
\r
1403 rb->setAngularVelocity(btVector3(state.getAngularVelocity().getX(),state.getAngularVelocity().getY(),state.getAngularVelocity().getZ()));
\r