Bullet Collision Detection & Physics Library

btParallelConstraintSolver.cpp

Go to the documentation of this file.
00001 /*
00002    Copyright (C) 2010 Sony Computer Entertainment Inc.
00003    All rights reserved.
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 
00015 */
00016 
00017 
00018 #include "btParallelConstraintSolver.h"
00019 #include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
00020 #include "BulletCollision/BroadphaseCollision/btDispatcher.h"
00021 #include "LinearMath/btPoolAllocator.h"
00022 
00023 #include "BulletMultiThreaded/vectormath2bullet.h"
00024 
00025 #include "LinearMath/btQuickprof.h"
00026 #include "BulletMultiThreaded/btThreadSupportInterface.h"
00027 #ifdef PFX_USE_FREE_VECTORMATH
00028 #include "vecmath/vmInclude.h"
00029 #else
00030 #include "vectormath/vmInclude.h"
00031 #endif //PFX_USE_FREE_VECTORMATH
00032 
00033 #include "HeapManager.h"
00034 
00035 #include "PlatformDefinitions.h"
00036 
00037 //#include "PfxSimdUtils.h"
00038 #include "LinearMath/btScalar.h"
00039 
00040 #include "TrbStateVec.h"
00041 
00042 
00043 
00045 
00046 
00047 #define TMP_BUFF_BYTES (15*1024*1024)
00048 unsigned char ATTRIBUTE_ALIGNED128(tmp_buff[TMP_BUFF_BYTES]);
00049 
00050 
00051 
00052 // Project Gauss Seidel or the equivalent Sequential Impulse
00053  inline void resolveSingleConstraintRowGeneric(PfxSolverBody& body1,PfxSolverBody& body2,const btSolverConstraint& c)
00054 {
00055 
00056         btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
00057         const btScalar deltaVel1Dotn    =       c.m_contactNormal.dot(getBtVector3(body1.mDeltaLinearVelocity))         + c.m_relpos1CrossNormal.dot(getBtVector3(body1.mDeltaAngularVelocity));
00058         const btScalar deltaVel2Dotn    =       -c.m_contactNormal.dot(getBtVector3(body2.mDeltaLinearVelocity)) + c.m_relpos2CrossNormal.dot(getBtVector3(body2.mDeltaAngularVelocity));
00059 
00060 //      const btScalar delta_rel_vel    =       deltaVel1Dotn-deltaVel2Dotn;
00061         deltaImpulse    -=      deltaVel1Dotn*c.m_jacDiagABInv;
00062         deltaImpulse    -=      deltaVel2Dotn*c.m_jacDiagABInv;
00063 
00064         const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
00065         if (sum < c.m_lowerLimit)
00066         {
00067                 deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
00068                 c.m_appliedImpulse = c.m_lowerLimit;
00069         }
00070         else if (sum > c.m_upperLimit) 
00071         {
00072                 deltaImpulse = c.m_upperLimit-c.m_appliedImpulse;
00073                 c.m_appliedImpulse = c.m_upperLimit;
00074         }
00075         else
00076         {
00077                 c.m_appliedImpulse = sum;
00078         }
00079         
00080 
00081         if (body1.mMassInv)
00082         {
00083                 btVector3 linearComponent = c.m_contactNormal*body1.mMassInv;
00084                 body1.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse);
00085                 btVector3 tmp=c.m_angularComponentA*(btVector3(deltaImpulse,deltaImpulse,deltaImpulse));
00086                 body1.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ());
00087         }
00088 
00089         if (body2.mMassInv)
00090         {
00091                 btVector3 linearComponent = -c.m_contactNormal*body2.mMassInv;
00092                 body2.mDeltaLinearVelocity += vmVector3(linearComponent.getX()*deltaImpulse,linearComponent.getY()*deltaImpulse,linearComponent.getZ()*deltaImpulse);
00093                 btVector3 tmp = c.m_angularComponentB*((btVector3(deltaImpulse,deltaImpulse,deltaImpulse)));//*m_angularFactor);
00094                 body2.mDeltaAngularVelocity += vmVector3(tmp.getX(),tmp.getY(),tmp.getZ());
00095         }
00096 
00097         //body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
00098         //body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
00099 
00100 }
00101 
00102  
00103 static SIMD_FORCE_INLINE
00104 void pfxSolveLinearConstraintRow(btConstraintRow &constraint,
00105         vmVector3 &deltaLinearVelocityA,vmVector3 &deltaAngularVelocityA,
00106         float massInvA,const vmMatrix3 &inertiaInvA,const vmVector3 &rA,
00107         vmVector3 &deltaLinearVelocityB,vmVector3 &deltaAngularVelocityB,
00108         float massInvB,const vmMatrix3 &inertiaInvB,const vmVector3 &rB)
00109 {
00110         const vmVector3 normal(btReadVector3(constraint.m_normal));
00111         btScalar deltaImpulse = constraint.m_rhs;
00112         vmVector3 dVA = deltaLinearVelocityA + cross(deltaAngularVelocityA,rA);
00113         vmVector3 dVB = deltaLinearVelocityB + cross(deltaAngularVelocityB,rB);
00114         deltaImpulse -= constraint.m_jacDiagInv * dot(normal,dVA-dVB);
00115         btScalar oldImpulse = constraint.m_accumImpulse;
00116         constraint.m_accumImpulse = btClamped(oldImpulse + deltaImpulse,constraint.m_lowerLimit,constraint.m_upperLimit);
00117         deltaImpulse = constraint.m_accumImpulse - oldImpulse;
00118         deltaLinearVelocityA += deltaImpulse * massInvA * normal;
00119         deltaAngularVelocityA += deltaImpulse * inertiaInvA * cross(rA,normal);
00120         deltaLinearVelocityB -= deltaImpulse * massInvB * normal;
00121         deltaAngularVelocityB -= deltaImpulse * inertiaInvB * cross(rB,normal);
00122 
00123 }
00124  
00125 void btSolveContactConstraint(
00126         btConstraintRow &constraintResponse,
00127         btConstraintRow &constraintFriction1,
00128         btConstraintRow &constraintFriction2,
00129         const vmVector3 &contactPointA,
00130         const vmVector3 &contactPointB,
00131         PfxSolverBody &solverBodyA,
00132         PfxSolverBody &solverBodyB,
00133         float friction
00134         )
00135 {
00136         vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA);
00137         vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB);
00138 
00139         pfxSolveLinearConstraintRow(constraintResponse,
00140                 solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA,
00141                 solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB);
00142 
00143         float mf = friction*fabsf(constraintResponse.m_accumImpulse);
00144         constraintFriction1.m_lowerLimit = -mf;
00145         constraintFriction1.m_upperLimit =  mf;
00146         constraintFriction2.m_lowerLimit = -mf;
00147         constraintFriction2.m_upperLimit =  mf;
00148 
00149         pfxSolveLinearConstraintRow(constraintFriction1,
00150                 solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA,
00151                 solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB);
00152 
00153         pfxSolveLinearConstraintRow(constraintFriction2,
00154                 solverBodyA.mDeltaLinearVelocity,solverBodyA.mDeltaAngularVelocity,solverBodyA.mMassInv,solverBodyA.mInertiaInv,rA,
00155                 solverBodyB.mDeltaLinearVelocity,solverBodyB.mDeltaAngularVelocity,solverBodyB.mMassInv,solverBodyB.mInertiaInv,rB);
00156 }
00157 
00158 
00159 void CustomSolveConstraintsTaskParallel(
00160         const PfxParallelGroup *contactParallelGroup,const PfxParallelBatch *contactParallelBatches,
00161         PfxConstraintPair *contactPairs,uint32_t numContactPairs,
00162         btPersistentManifold* offsetContactManifolds,
00163         const PfxParallelGroup *jointParallelGroup,const PfxParallelBatch *jointParallelBatches,
00164         PfxConstraintPair *jointPairs,uint32_t numJointPairs,
00165         btSolverConstraint* offsetSolverConstraints,
00166         TrbState *offsetRigStates,
00167         PfxSolverBody *offsetSolverBodies,
00168         uint32_t numRigidBodies,
00169         int iteration,unsigned int taskId,unsigned int numTasks,btBarrier *barrier)
00170 {
00171 
00172         PfxSolverBody staticBody;
00173         staticBody.mMassInv = 0.f;
00174         staticBody.mDeltaAngularVelocity=vmVector3(0,0,0);
00175         staticBody.mDeltaLinearVelocity =vmVector3(0,0,0);
00176 
00177 
00178         for(int k=0;k<iteration+1;k++) {
00179                 // Joint
00180                 for(uint32_t phaseId=0;phaseId<jointParallelGroup->numPhases;phaseId++) {
00181                         for(uint32_t batchId=0;batchId<jointParallelGroup->numBatches[phaseId];batchId++) {
00182                                 uint32_t numPairs = jointParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId];
00183                                 if(batchId%numTasks == taskId && numPairs > 0) {
00184                                         const PfxParallelBatch &batch = jointParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId];
00185                                         for(uint32_t i=0;i<numPairs;i++) {
00186                                                 PfxConstraintPair &pair = jointPairs[batch.pairIndices[i]];
00187                                                 uint16_t iA = pfxGetRigidBodyIdA(pair);
00188                                                 uint16_t iB = pfxGetRigidBodyIdB(pair);
00189 
00190                                                 
00191                                                 PfxSolverBody &solverBodyA = iA != 65535 ? offsetSolverBodies[iA] : staticBody;
00192                                                 PfxSolverBody &solverBodyB = iB != 65535 ? offsetSolverBodies[iB] : staticBody;
00193 
00194                                                 if(k==0) {
00195                                                         
00196                                                 }
00197                                                 else {
00198                                                         btSolverConstraint* constraintRow = &offsetSolverConstraints[pfxGetContactId1(pair)];
00199                                                         int numRows = pfxGetNumConstraints(pair);
00200                                                         int i;
00201                                                         for (i=0;i<numRows;i++)
00202                                                         {
00203                                                                 resolveSingleConstraintRowGeneric(solverBodyA,solverBodyB,constraintRow[i]);
00204                                                         }
00205                                                         
00206                                                 }
00207                                         }
00208                                 }
00209                         }
00210 
00211                         barrier->sync();
00212                 }
00213 
00214                 // Contact
00215                 for(uint32_t phaseId=0;phaseId<contactParallelGroup->numPhases;phaseId++) {
00216                         for(uint32_t batchId=0;batchId<contactParallelGroup->numBatches[phaseId];batchId++) {
00217                                 uint32_t numPairs = contactParallelGroup->numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId];
00218                                 if(batchId%numTasks == taskId && numPairs > 0) {
00219                                         const PfxParallelBatch &batch = contactParallelBatches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId];
00220                                         for(uint32_t i=0;i<numPairs;i++) {
00221                                                 PfxConstraintPair &pair = contactPairs[batch.pairIndices[i]];
00222                                                 uint16_t iA = pfxGetRigidBodyIdA(pair);
00223                                                 uint16_t iB = pfxGetRigidBodyIdB(pair);
00224 
00225                                                 btPersistentManifold& contact = offsetContactManifolds[pfxGetConstraintId1(pair)];
00226 
00227 
00228                                                 PfxSolverBody &solverBodyA = offsetSolverBodies[iA];
00229                                                 PfxSolverBody &solverBodyB = offsetSolverBodies[iB];
00230                                                 
00231                                                 for(int j=0;j<contact.getNumContacts();j++) {
00232                                                         btManifoldPoint& cp = contact.getContactPoint(j);
00233                                                         
00234                                                         if(k==0) {
00235                                                                 vmVector3 rA = rotate(solverBodyA.mOrientation,btReadVector3(cp.m_localPointA));
00236                                                                 vmVector3 rB = rotate(solverBodyB.mOrientation,btReadVector3(cp.m_localPointB));
00237                                                                 
00238                                                                 for(int k=0;k<3;k++) {
00239                                                                         vmVector3 normal = btReadVector3(cp.mConstraintRow[k].m_normal);
00240                                                                         float deltaImpulse = cp.mConstraintRow[k].m_accumImpulse;
00241                                                                         solverBodyA.mDeltaLinearVelocity += deltaImpulse * solverBodyA.mMassInv * normal;
00242                                                                         solverBodyA.mDeltaAngularVelocity += deltaImpulse * solverBodyA.mInertiaInv * cross(rA,normal);
00243                                                                         solverBodyB.mDeltaLinearVelocity -= deltaImpulse * solverBodyB.mMassInv * normal;
00244                                                                         solverBodyB.mDeltaAngularVelocity -= deltaImpulse * solverBodyB.mInertiaInv * cross(rB,normal);
00245                                                                 }
00246                                                         }
00247                                                         else {
00248                                                                 btSolveContactConstraint(
00249                                                                         cp.mConstraintRow[0],
00250                                                                         cp.mConstraintRow[1],
00251                                                                         cp.mConstraintRow[2],
00252                                                                         btReadVector3(cp.m_localPointA),
00253                                                                         btReadVector3(cp.m_localPointB),
00254                                                                         solverBodyA,
00255                                                                         solverBodyB,
00256                                                                         cp.m_combinedFriction
00257                                                                         );
00258                                                         }
00259                                                 }
00260                                         }
00261                                 }
00262                         }
00263 
00264                         if (barrier)
00265                                 barrier->sync();
00266                 }
00267         }
00268 }
00269 
00270 void CustomPostSolverTask(
00271         TrbState *states,
00272         PfxSolverBody *solverBodies,
00273         uint32_t numRigidBodies)
00274 {
00275         for(uint32_t i=0;i<numRigidBodies;i++) {
00276                 TrbState &state = states[i];
00277                 PfxSolverBody &solverBody = solverBodies[i];
00278                 state.setLinearVelocity(state.getLinearVelocity()+solverBody.mDeltaLinearVelocity);
00279                 state.setAngularVelocity(state.getAngularVelocity()+solverBody.mDeltaAngularVelocity);
00280         }
00281 }
00282 
00283 void*   SolverlsMemoryFunc()
00284 {
00285         //don't create local store memory, just return 0
00286         return 0;
00287 }
00288 
00289 
00290 static SIMD_FORCE_INLINE
00291 void pfxGetPlaneSpace(const vmVector3& n, vmVector3& p, vmVector3& q)
00292 {
00293         if(fabsf(n[2]) > 0.707f) {
00294                 // choose p in y-z plane
00295                 float a = n[1]*n[1] + n[2]*n[2];
00296                 float k = 1.0f/sqrtf(a);
00297                 p[0] = 0;
00298                 p[1] = -n[2]*k;
00299                 p[2] = n[1]*k;
00300                 // set q = n x p
00301                 q[0] = a*k;
00302                 q[1] = -n[0]*p[2];
00303                 q[2] = n[0]*p[1];
00304         }
00305         else {
00306                 // choose p in x-y plane
00307                 float a = n[0]*n[0] + n[1]*n[1];
00308                 float k = 1.0f/sqrtf(a);
00309                 p[0] = -n[1]*k;
00310                 p[1] = n[0]*k;
00311                 p[2] = 0;
00312                 // set q = n x p
00313                 q[0] = -n[2]*p[1];
00314                 q[1] = n[2]*p[0];
00315                 q[2] = a*k;
00316         }
00317 }
00318 
00319 
00320 
00321 #define PFX_CONTACT_SLOP 0.001f
00322 
00323 void btSetupContactConstraint(
00324         btConstraintRow &constraintResponse,
00325         btConstraintRow &constraintFriction1,
00326         btConstraintRow &constraintFriction2,
00327         float penetrationDepth,
00328         float restitution,
00329         float friction,
00330         const vmVector3 &contactNormal,
00331         const vmVector3 &contactPointA,
00332         const vmVector3 &contactPointB,
00333         const TrbState &stateA,
00334         const TrbState &stateB,
00335         PfxSolverBody &solverBodyA,
00336         PfxSolverBody &solverBodyB,
00337         float separateBias,
00338         float timeStep
00339         )
00340 {
00341         vmVector3 rA = rotate(solverBodyA.mOrientation,contactPointA);
00342         vmVector3 rB = rotate(solverBodyB.mOrientation,contactPointB);
00343 
00344         vmMatrix3 K = vmMatrix3::scale(vmVector3(solverBodyA.mMassInv + solverBodyB.mMassInv)) - 
00345                         crossMatrix(rA) * solverBodyA.mInertiaInv * crossMatrix(rA) - 
00346                         crossMatrix(rB) * solverBodyB.mInertiaInv * crossMatrix(rB);
00347 
00348         vmVector3 vA = stateA.getLinearVelocity() + cross(stateA.getAngularVelocity(),rA);
00349         vmVector3 vB = stateB.getLinearVelocity() + cross(stateB.getAngularVelocity(),rB);
00350         vmVector3 vAB = vA-vB;
00351 
00352         vmVector3 tangent1,tangent2;
00353         btPlaneSpace1(contactNormal,tangent1,tangent2);
00354 
00355 //      constraintResponse.m_accumImpulse = 0.f;
00356 //      constraintFriction1.m_accumImpulse = 0.f;
00357 //      constraintFriction2.m_accumImpulse = 0.f;
00358 
00359         // Contact Constraint
00360         {
00361                 vmVector3 normal = contactNormal;
00362 
00363                 float denom = dot(K*normal,normal);
00364 
00365                 constraintResponse.m_rhs = -(1.0f+restitution)*dot(vAB,normal); // velocity error
00366                 constraintResponse.m_rhs -= (separateBias * btMin(0.0f,penetrationDepth+PFX_CONTACT_SLOP)) / timeStep; // position error
00367                 constraintResponse.m_rhs /= denom;
00368                 constraintResponse.m_jacDiagInv = 1.0f/denom;
00369                 constraintResponse.m_lowerLimit = 0.0f;
00370                 constraintResponse.m_upperLimit = SIMD_INFINITY;
00371                 btStoreVector3(normal,constraintResponse.m_normal);
00372         }
00373 
00374         // Friction Constraint 1
00375         {
00376                 vmVector3 normal = tangent1;
00377 
00378                 float denom = dot(K*normal,normal);
00379 
00380                 constraintFriction1.m_jacDiagInv = 1.0f/denom;
00381                 constraintFriction1.m_rhs = -dot(vAB,normal);
00382                 constraintFriction1.m_rhs *= constraintFriction1.m_jacDiagInv;
00383                 constraintFriction1.m_lowerLimit = 0.0f;
00384                 constraintFriction1.m_upperLimit = SIMD_INFINITY;
00385                 btStoreVector3(normal,constraintFriction1.m_normal);
00386         }
00387         
00388         // Friction Constraint 2
00389         {
00390                 vmVector3 normal = tangent2;
00391 
00392                 float denom = dot(K*normal,normal);
00393 
00394                 constraintFriction2.m_jacDiagInv = 1.0f/denom;
00395                 constraintFriction2.m_rhs = -dot(vAB,normal);
00396                 constraintFriction2.m_rhs *= constraintFriction2.m_jacDiagInv;
00397                 constraintFriction2.m_lowerLimit = 0.0f;
00398                 constraintFriction2.m_upperLimit = SIMD_INFINITY;
00399                 btStoreVector3(normal,constraintFriction2.m_normal);
00400         }
00401 }
00402 
00403 
00404 void CustomSetupContactConstraintsTask(
00405         PfxConstraintPair *contactPairs,uint32_t numContactPairs,
00406         btPersistentManifold*   offsetContactManifolds,
00407         TrbState *offsetRigStates,
00408         PfxSolverBody *offsetSolverBodies,
00409         uint32_t numRigidBodies,
00410         float separateBias,
00411         float timeStep)
00412 {
00413         for(uint32_t i=0;i<numContactPairs;i++) {
00414                 PfxConstraintPair &pair = contactPairs[i];
00415                 if(!pfxGetActive(pair) || pfxGetNumConstraints(pair) == 0 ||
00416                         ((pfxGetMotionMaskA(pair)&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pair)&PFX_MOTION_MASK_STATIC)) ) {
00417                         continue;
00418                 }
00419 
00420                 uint16_t iA = pfxGetRigidBodyIdA(pair);
00421                 uint16_t iB = pfxGetRigidBodyIdB(pair);
00422 
00423                 int id = pfxGetConstraintId1(pair);
00424                 btPersistentManifold& contact = offsetContactManifolds[id];
00425 
00426 
00427                 TrbState &stateA = offsetRigStates[iA];
00428 //              PfxRigBody &bodyA = offsetRigBodies[iA];
00429                 PfxSolverBody &solverBodyA = offsetSolverBodies[iA];
00430 
00431                 TrbState &stateB = offsetRigStates[iB];
00432 //              PfxRigBody &bodyB = offsetRigBodies[iB];
00433                 PfxSolverBody &solverBodyB = offsetSolverBodies[iB];
00434                 
00435                 float restitution = 0.5f * (solverBodyA.restitution + solverBodyB.restitution);
00436                 //if(contact.getDuration() > 1) restitution = 0.0f;
00437                 
00438                 float friction = sqrtf(solverBodyA.friction * solverBodyB.friction);
00439 
00440                 for(int j=0;j<contact.getNumContacts();j++) {
00441                         btManifoldPoint& cp = contact.getContactPoint(j);
00442                         
00443                         btSetupContactConstraint(
00444                                 cp.mConstraintRow[0],
00445                                 cp.mConstraintRow[1],
00446                                 cp.mConstraintRow[2],
00447                                 cp.getDistance(),
00448                                 restitution,
00449                                 friction,
00450                                 btReadVector3(cp.m_normalWorldOnB),//.mConstraintRow[0].m_normal),
00451                                 btReadVector3(cp.m_localPointA),
00452                                 btReadVector3(cp.m_localPointB),
00453                                 stateA,
00454                                 stateB,
00455                                 solverBodyA,
00456                                 solverBodyB,
00457                                 separateBias,
00458                                 timeStep
00459                                 );
00460                 }
00461 
00462                 //contact.setCompositeFriction(friction);
00463         }
00464 }
00465 
00466 void    SolverThreadFunc(void* userPtr,void* lsMemory)
00467 {
00468         btConstraintSolverIO* io = (btConstraintSolverIO*)(userPtr);//arg->io);
00469         btCriticalSection* criticalsection = io->setupContactConstraints.criticalSection;
00470         
00471 
00472         //CustomCriticalSection *criticalsection = &io->m_cs;
00473         switch(io->cmd) {
00474 
00475                 case PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS:
00476                 CustomSolveConstraintsTaskParallel(
00477                         io->solveConstraints.contactParallelGroup,
00478                         io->solveConstraints.contactParallelBatches,
00479                         io->solveConstraints.contactPairs,
00480                         io->solveConstraints.numContactPairs,
00481                         io->solveConstraints.offsetContactManifolds,
00482 
00483                         io->solveConstraints.jointParallelGroup,
00484                         io->solveConstraints.jointParallelBatches,
00485                         io->solveConstraints.jointPairs,
00486                         io->solveConstraints.numJointPairs,
00487                         io->solveConstraints.offsetSolverConstraints,
00488                         io->solveConstraints.offsetRigStates1,
00489                         io->solveConstraints.offsetSolverBodies,
00490                         io->solveConstraints.numRigidBodies,
00491                         io->solveConstraints.iteration,
00492 
00493                         io->solveConstraints.taskId,
00494                         io->maxTasks1,
00495                         io->solveConstraints.barrier
00496                         );
00497                 break;
00498 
00499                 case PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER:
00500                         CustomPostSolverTask(   io->postSolver.states,io->postSolver.solverBodies,      io->postSolver.numRigidBodies);
00501                         break;
00502 
00503 
00504                 case PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS:
00505                 {
00506                         bool empty = false;
00507                         while(!empty) {
00508                                 int start,batch;
00509                                 
00510                                 criticalsection->lock();
00511 
00512                                 start = (int)criticalsection->getSharedParam(0);
00513                                 batch = (int)criticalsection->getSharedParam(1);
00514 
00515                                 //PFX_PRINTF("taskId %d start %d num %d\n",arg->taskId,start,batch);
00516 
00517                                 // ŽŸ‚̃oƒbƒtƒ@‚ðƒZƒbƒg
00518                                 int nextStart = start + batch;
00519                                 int rest = btMax((int)io->setupContactConstraints.numContactPairs1 - nextStart,0);
00520                                 int nextBatch = (rest > batch)?batch:rest;
00521 
00522                                 criticalsection->setSharedParam(0,nextStart);
00523                 criticalsection->setSharedParam(1,nextBatch);
00524 
00525                                 criticalsection->unlock();
00526                                 
00527                                 if(batch > 0) {
00528                                         CustomSetupContactConstraintsTask(
00529                                                 io->setupContactConstraints.offsetContactPairs+start,batch,
00530                                                 io->setupContactConstraints.offsetContactManifolds,
00531                                                 io->setupContactConstraints.offsetRigStates,
00532 //                                              io->setupContactConstraints.offsetRigBodies,
00533                                                 io->setupContactConstraints.offsetSolverBodies,
00534                                                 io->setupContactConstraints.numRigidBodies,
00535                                                 io->setupContactConstraints.separateBias,
00536                                                 io->setupContactConstraints.timeStep);
00537                                 }
00538                                 else {
00539                                         empty = true;
00540                                 }
00541                         }
00542                 }
00543                 break;
00544 
00545                 default:
00546                         {
00547                                 btAssert(0);
00548                         }
00549         }
00550 
00551 }
00552 
00553 
00554 void CustomSetupContactConstraintsNew(
00555         PfxConstraintPair *contactPairs1,uint32_t numContactPairs,
00556         btPersistentManifold *offsetContactManifolds,
00557         TrbState *offsetRigStates,
00558         PfxSolverBody *offsetSolverBodies,
00559         uint32_t numRigidBodies,
00560         float separationBias,
00561         float timeStep,
00562         class btThreadSupportInterface* threadSupport,
00563         btCriticalSection* criticalSection,
00564         btConstraintSolverIO *io 
00565         )
00566 {
00567         int maxTasks = threadSupport->getNumTasks();
00568 
00569         int div = (int)maxTasks * 4;
00570         int batch = ((int)numContactPairs + div - 1) / div;
00571 #ifdef __PPU__
00572                 BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport;
00573 #endif
00574         if (criticalSection)
00575         {
00576                 criticalSection->setSharedParam(0,0);
00577                 criticalSection->setSharedParam(1,btMin(batch,64)); // batched number
00578         } else
00579         {
00580 #ifdef __PPU__
00581                 spursThread->setSharedParam(0,0);
00582                 spursThread->setSharedParam(1,btMin(batch,64)); // batched number
00583 #endif //__PPU__
00584         }
00585 
00586         for(int t=0;t<maxTasks;t++) {
00587                 io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_SETUP_CONTACT_CONSTRAINTS;
00588                 io[t].setupContactConstraints.offsetContactPairs = contactPairs1;
00589                 io[t].setupContactConstraints.numContactPairs1 = numContactPairs;
00590                 io[t].setupContactConstraints.offsetRigStates = offsetRigStates;
00591                 io[t].setupContactConstraints.offsetContactManifolds = offsetContactManifolds;          
00592                 io[t].setupContactConstraints.offsetSolverBodies = offsetSolverBodies;
00593                 io[t].setupContactConstraints.numRigidBodies = numRigidBodies;
00594                 io[t].setupContactConstraints.separateBias = separationBias;
00595                 io[t].setupContactConstraints.timeStep = timeStep;
00596                 io[t].setupContactConstraints.criticalSection = criticalSection;
00597                 io[t].maxTasks1 = maxTasks;
00598 #ifdef __PPU__
00599                 io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress();
00600                 io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress();
00601 #endif
00602         
00603 
00604 //#define SEQUENTIAL_SETUP
00605 #ifdef SEQUENTIAL_SETUP
00606                 CustomSetupContactConstraintsTask(contactPairs1,numContactPairs,offsetContactManifolds,offsetRigStates,offsetSolverBodies,numRigidBodies,separationBias,timeStep);
00607 #else
00608                 threadSupport->sendRequest(1,(ppu_address_t)&io[t],t);
00609 #endif
00610 
00611         }
00612 #ifndef SEQUENTIAL_SETUP
00613         unsigned int arg0,arg1;
00614         for(int t=0;t<maxTasks;t++) {
00615                 arg0 = t;
00616                 threadSupport->waitForResponse(&arg0,&arg1);
00617         }
00618 #endif //SEQUENTIAL_SETUP
00619 
00620 }
00621 
00622 
00623 void CustomSplitConstraints(
00624         PfxConstraintPair *pairs,uint32_t numPairs,
00625         PfxParallelGroup &group,PfxParallelBatch *batches,
00626         uint32_t numTasks,
00627         uint32_t numRigidBodies,
00628         void *poolBuff,
00629         uint32_t poolBytes
00630         )
00631 {
00632         HeapManager pool((unsigned char*)poolBuff,poolBytes);
00633 
00634         // ƒXƒe[ƒgƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹
00635         int bufSize = sizeof(uint8_t)*numRigidBodies;
00636         bufSize = ((bufSize+127)>>7)<<7; // 128 bytes alignment
00637         uint8_t *bodyTable = (uint8_t*)pool.allocate(bufSize,HeapManager::ALIGN128);
00638 
00639         // ƒyƒAƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹
00640         uint32_t *pairTable;
00641         size_t allocSize = sizeof(uint32_t)*((numPairs+31)/32);
00642         pairTable = (uint32_t*)pool.allocate(allocSize);
00643         memset(pairTable,0,allocSize);
00644 
00645         // –Ú•W‚Æ‚·‚é•ªŠ„”
00646         uint32_t targetCount = btMax(uint32_t(PFX_MIN_SOLVER_PAIRS),btMin(numPairs / (numTasks*2),uint32_t(PFX_MAX_SOLVER_PAIRS)));
00647         uint32_t startIndex = 0;
00648         
00649         uint32_t phaseId;
00650         uint32_t batchId;
00651         uint32_t totalCount=0;
00652         
00653         uint32_t maxBatches = btMin(numTasks,uint32_t(PFX_MAX_SOLVER_BATCHES));
00654         
00655         for(phaseId=0;phaseId<PFX_MAX_SOLVER_PHASES&&totalCount<numPairs;phaseId++) {
00656                 bool startIndexCheck = true;
00657                 
00658                 group.numBatches[phaseId] = 0;
00659                 
00660                 uint32_t i = startIndex;
00661                 
00662         // ƒ`ƒFƒbƒN—pƒrƒbƒgƒtƒ‰ƒOƒe[ƒuƒ‹‚ðƒNƒŠƒA
00663                 memset(bodyTable,0xff,bufSize);
00664                 
00665                 for(batchId=0;i<numPairs&&totalCount<numPairs&&batchId<maxBatches;batchId++) {
00666                         uint32_t pairCount=0;
00667                         
00668                         PfxParallelBatch &batch = batches[phaseId*PFX_MAX_SOLVER_BATCHES+batchId];
00669                         uint32_t pairId = 0;
00670                         
00671                         for(;i<numPairs&&pairCount<targetCount;i++) {
00672                                 uint32_t idxP = i>>5;
00673                                 uint32_t maskP = 1L << (i & 31);
00674                                 
00675                                 //pair is already assigned to a phase/batch
00676                                 if(pairTable[idxP] & maskP) {
00677                                         continue;
00678                                 }
00679                                 
00680                                 uint32_t idxA = pfxGetRigidBodyIdA(pairs[i]);
00681                                 uint32_t idxB = pfxGetRigidBodyIdB(pairs[i]);
00682 
00683                                 // —¼•û‚Æ‚àƒAƒNƒeƒBƒu‚łȂ¢A‚Ü‚½‚ÍÕ“Ë“_‚ª‚O‚̃yƒA‚Í“o˜^‘ÎÛ‚©‚ç‚Í‚¸‚·
00684                                 if(!pfxGetActive(pairs[i]) || pfxGetNumConstraints(pairs[i]) == 0 ||
00685                                         ((pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_STATIC) && (pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_STATIC)) ) {
00686                                         if(startIndexCheck) 
00687                                                 startIndex++;
00688                                         //assign pair -> skip it because it has no constraints
00689                                         pairTable[idxP] |= maskP;
00690                                         totalCount++;
00691                                         continue;
00692                                 }
00693                                 
00694                                 // ˆË‘¶«‚̃`ƒFƒbƒN
00695                                 if( (bodyTable[idxA] != batchId && bodyTable[idxA] != 0xff) || 
00696                                         (bodyTable[idxB] != batchId && bodyTable[idxB] != 0xff) ) {
00697                                         startIndexCheck = false;
00698                                         //bodies of the pair are already assigned to another batch within this phase
00699                                         continue;
00700                                 }
00701                                 
00702                                 // ˆË‘¶«”»’èƒe[ƒuƒ‹‚É“o˜^
00703                                 if(pfxGetMotionMaskA(pairs[i])&PFX_MOTION_MASK_DYNAMIC) 
00704                                                 bodyTable[idxA] = batchId;
00705                                 if(pfxGetMotionMaskB(pairs[i])&PFX_MOTION_MASK_DYNAMIC) 
00706                                                 bodyTable[idxB] = batchId;
00707                                 
00708                                 if(startIndexCheck) 
00709                                         startIndex++;
00710                                 
00711                                 pairTable[idxP] |= maskP;
00712                                 //add the pair 'i' to the current batch
00713                                 batch.pairIndices[pairId++] = i;
00714                                 pairCount++;
00715                         }
00716 
00717                         group.numPairs[phaseId*PFX_MAX_SOLVER_BATCHES+batchId] = (uint16_t)pairId;
00718                         totalCount += pairCount;
00719                 }
00720 
00721                 group.numBatches[phaseId] = batchId;
00722         }
00723 
00724         group.numPhases = phaseId;
00725 
00726         pool.clear();
00727 }
00728 
00729 
00730 
00731 void CustomSolveConstraintsParallel(
00732         PfxConstraintPair *contactPairs,uint32_t numContactPairs,
00733         
00734         PfxConstraintPair *jointPairs,uint32_t numJointPairs,
00735         btPersistentManifold* offsetContactManifolds,
00736         btSolverConstraint* offsetSolverConstraints,
00737         TrbState *offsetRigStates,
00738         PfxSolverBody *offsetSolverBodies,
00739         uint32_t numRigidBodies,
00740         struct btConstraintSolverIO* io,
00741         class btThreadSupportInterface* threadSupport,
00742         int iteration,
00743         void* poolBuf,
00744         int poolBytes,
00745         class btBarrier* barrier)
00746         {
00747 
00748         int maxTasks = threadSupport->getNumTasks();
00749 //      config.taskManager->setTaskEntry(PFX_SOLVER_ENTRY);
00750 
00751         HeapManager pool((unsigned char*)poolBuf,poolBytes);
00752 
00753         {
00754                 PfxParallelGroup *cgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup));
00755                 PfxParallelBatch *cbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128);
00756                 PfxParallelGroup *jgroup = (PfxParallelGroup*)pool.allocate(sizeof(PfxParallelGroup));
00757                 PfxParallelBatch *jbatches = (PfxParallelBatch*)pool.allocate(sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES),128);
00758                 
00759                 uint32_t tmpBytes = poolBytes - 2 * (sizeof(PfxParallelGroup) + sizeof(PfxParallelBatch)*(PFX_MAX_SOLVER_PHASES*PFX_MAX_SOLVER_BATCHES) + 128);
00760                 void *tmpBuff = pool.allocate(tmpBytes);
00761                 
00762                 {
00763                         BT_PROFILE("CustomSplitConstraints");
00764                         CustomSplitConstraints(contactPairs,numContactPairs,*cgroup,cbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes);
00765                         CustomSplitConstraints(jointPairs,numJointPairs,*jgroup,jbatches,maxTasks,numRigidBodies,tmpBuff,tmpBytes);
00766                 }
00767 
00768                 {
00769                         BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS");
00770 //#define SOLVE_SEQUENTIAL
00771 #ifdef SOLVE_SEQUENTIAL
00772                 CustomSolveConstraintsTask(
00773                         io->solveConstraints.contactParallelGroup,
00774                         io->solveConstraints.contactParallelBatches,
00775                         io->solveConstraints.contactPairs,
00776                         io->solveConstraints.numContactPairs,
00777                         io->solveConstraints.offsetContactManifolds,
00778 
00779                         io->solveConstraints.jointParallelGroup,
00780                         io->solveConstraints.jointParallelBatches,
00781                         io->solveConstraints.jointPairs,
00782                         io->solveConstraints.numJointPairs,
00783                         io->solveConstraints.offsetJoints,
00784 
00785                         io->solveConstraints.offsetRigStates,
00786                         io->solveConstraints.offsetSolverBodies,
00787                         io->solveConstraints.numRigidBodies,
00788                         io->solveConstraints.iteration,0,1,0);//arg->taskId,1,0);//,arg->maxTasks,arg->barrier);
00789 #else
00790                 for(int t=0;t<maxTasks;t++) {
00791                         io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_SOLVE_CONSTRAINTS;
00792                         io[t].solveConstraints.contactParallelGroup = cgroup;
00793                         io[t].solveConstraints.contactParallelBatches = cbatches;
00794                         io[t].solveConstraints.contactPairs = contactPairs;
00795                         io[t].solveConstraints.numContactPairs = numContactPairs;
00796                         io[t].solveConstraints.offsetContactManifolds = offsetContactManifolds;
00797                         io[t].solveConstraints.jointParallelGroup = jgroup;
00798                         io[t].solveConstraints.jointParallelBatches = jbatches;
00799                         io[t].solveConstraints.jointPairs = jointPairs;
00800                         io[t].solveConstraints.numJointPairs = numJointPairs;
00801                         io[t].solveConstraints.offsetSolverConstraints = offsetSolverConstraints;
00802                         io[t].solveConstraints.offsetRigStates1 = offsetRigStates;
00803                         io[t].solveConstraints.offsetSolverBodies = offsetSolverBodies;
00804                         io[t].solveConstraints.numRigidBodies = numRigidBodies;
00805                         io[t].solveConstraints.iteration = iteration;
00806                         io[t].solveConstraints.taskId = t;
00807                         io[t].solveConstraints.barrier = barrier;
00808 
00809                 io[t].maxTasks1 = maxTasks;
00810 #ifdef __PPU__
00811                 BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport;
00812                 io[t].barrierAddr2 = (unsigned int) spursThread->getBarrierAddress();
00813                 io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress();
00814 #endif
00815 
00816                         threadSupport->sendRequest(1,(ppu_address_t)&io[t],t);
00817                 }
00818 
00819                 unsigned int arg0,arg1;
00820                 for(int t=0;t<maxTasks;t++) {
00821                         arg0 = t;
00822                         threadSupport->waitForResponse(&arg0,&arg1);
00823                 }
00824 #endif
00825                 }
00826                 pool.clear();
00827         }
00828 
00829         {
00830                         BT_PROFILE("PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER");
00831                 int batch = ((int)numRigidBodies + maxTasks - 1) / maxTasks;
00832                 int rest = (int)numRigidBodies;
00833                 int start = 0;
00834 
00835                 for(int t=0;t<maxTasks;t++) {
00836                         int num = (rest - batch ) > 0 ? batch : rest;
00837                         io[t].cmd = PFX_CONSTRAINT_SOLVER_CMD_POST_SOLVER;
00838                         io[t].postSolver.states = offsetRigStates + start;
00839                         io[t].postSolver.solverBodies = offsetSolverBodies + start;
00840                         io[t].postSolver.numRigidBodies = (uint32_t)num;
00841                 io[t].maxTasks1 = maxTasks;
00842 #ifdef __PPU__
00843                 BulletPE2ConstraintSolverSpursSupport* spursThread = (BulletPE2ConstraintSolverSpursSupport*) threadSupport;
00844                 io[t].barrierAddr2 = (unsigned int)spursThread->getBarrierAddress();
00845                 io[t].criticalsectionAddr2 = (unsigned int)spursThread->getCriticalSectionAddress();
00846 #endif
00847 
00848 #ifdef SOLVE_SEQUENTIAL
00849                         CustomPostSolverTask(   io[t].postSolver.states,io[t].postSolver.solverBodies,  io[t].postSolver.numRigidBodies);
00850 #else
00851                         threadSupport->sendRequest(1,(ppu_address_t)&io[t],t);
00852 #endif
00853                         rest -= num;
00854                         start += num;
00855                 }
00856 
00857                 unsigned int arg0,arg1;
00858                 for(int t=0;t<maxTasks;t++) {
00859 #ifndef SOLVE_SEQUENTIAL
00860                         arg0 = t;
00861                         threadSupport->waitForResponse(&arg0,&arg1);
00862 #endif
00863                 }
00864         }
00865 
00866 }
00867 
00868 
00869 
00870 void BPE_customConstraintSolverSequentialNew(unsigned int new_num, PfxBroadphasePair *new_pairs1 ,
00871                                                                         btPersistentManifold* offsetContactManifolds,
00872                                                                           TrbState* states,int numRigidBodies, 
00873                                                                           struct PfxSolverBody* solverBodies, 
00874                                                                           PfxConstraintPair* jointPairs, unsigned int numJoints,
00875                                                                           btSolverConstraint* offsetSolverConstraints,
00876                                                                           float separateBias,
00877                                                                           float timeStep,
00878                                                                           int iteration,
00879                                                                           btThreadSupportInterface* solverThreadSupport,
00880                                                                           btCriticalSection* criticalSection,
00881                                                                           struct btConstraintSolverIO* solverIO,
00882                                                                           btBarrier* barrier
00883                                                                           )
00884 {
00885 
00886         {
00887                 BT_PROFILE("pfxSetupConstraints");
00888 
00889                 for(uint32_t i=0;i<numJoints;i++) {
00890                         // î•ñ‚ÌXV
00891                         PfxConstraintPair &pair = jointPairs[i];
00892                         int idA = pfxGetRigidBodyIdA(pair);
00893 
00894                         if (idA != 65535)
00895                         {
00896                                 pfxSetMotionMaskA(pair,states[pfxGetRigidBodyIdA(pair)].getMotionMask());
00897                         }
00898                         else
00899                         {
00900                                 pfxSetMotionMaskA(pair,PFX_MOTION_MASK_STATIC);
00901                         }
00902                         int idB = pfxGetRigidBodyIdB(pair);
00903                         if (idB!= 65535)
00904                         {
00905                                 pfxSetMotionMaskB(pair,states[pfxGetRigidBodyIdB(pair)].getMotionMask());
00906                         } else
00907                         {
00908                                 pfxSetMotionMaskB(pair,PFX_MOTION_MASK_STATIC);
00909                         }
00910                 }
00911 
00912 //              CustomSetupJointConstraintsSeq(                 jointPairs,numJoints,joints,                    states,                 solverBodies,                   numRigidBodies,                 timeStep);
00913 
00914 #ifdef SEQUENTIAL_SETUP
00915                 CustomSetupContactConstraintsSeqNew(
00916                         (PfxConstraintPair*)new_pairs1,new_num,contacts,
00917                         states,
00918                         solverBodies,
00919                         numRigidBodies,
00920                         separateBias,
00921                         timeStep);
00922 #else
00923                 CustomSetupContactConstraintsNew(
00924                         (PfxConstraintPair*)new_pairs1,new_num,
00925                         offsetContactManifolds,
00926                         states,
00927                         solverBodies,
00928                         numRigidBodies,
00929                         separateBias,
00930                         timeStep,
00931                         solverThreadSupport,
00932                         criticalSection,solverIO
00933                         );
00934 
00935 #endif //SEQUENTIAL_SETUP
00936 
00937         }
00938         {
00939                 BT_PROFILE("pfxSolveConstraints");
00940 
00941 //#define SEQUENTIAL
00942 #ifdef SEQUENTIAL
00943                 CustomSolveConstraintsSeq(
00944                         (PfxConstraintPair*)new_pairs1,new_num,contacts,
00945                         jointPairs,numJoints,
00946                         states,
00947                         solverBodies,
00948                         numRigidBodies,
00949                         separateBias,
00950                         timeStep,
00951                         iteration);
00952 #else //SEQUENTIAL
00953                 CustomSolveConstraintsParallel(
00954                         (PfxConstraintPair*)new_pairs1,new_num,
00955                         jointPairs,numJoints,
00956                         offsetContactManifolds,
00957                         offsetSolverConstraints,
00958                         states,
00959                         solverBodies,
00960                         numRigidBodies,
00961                         solverIO, solverThreadSupport,
00962                         iteration,
00963                         tmp_buff,
00964                         TMP_BUFF_BYTES,
00965                         barrier
00966                         );
00967 
00968 #endif //SEQUENTIAL
00969         }
00970 
00971 }
00972 
00973 
00974 struct  btParallelSolverMemoryCache
00975 {
00976         btAlignedObjectArray<TrbState>  m_mystates;
00977         btAlignedObjectArray<PfxSolverBody>  m_mysolverbodies;
00978         btAlignedObjectArray<PfxBroadphasePair> m_mypairs;
00979         btAlignedObjectArray<PfxConstraintPair> m_jointPairs;
00980         
00981 };
00982 
00983 
00984 btConstraintSolverIO* createSolverIO(int numThreads)
00985 {
00986         return new btConstraintSolverIO[numThreads];
00987 }
00988 
00989 btParallelConstraintSolver::btParallelConstraintSolver(btThreadSupportInterface* solverThreadSupport)
00990 {
00991         
00992         m_solverThreadSupport = solverThreadSupport;//createSolverThreadSupport(maxNumThreads);
00993         m_solverIO = createSolverIO(m_solverThreadSupport->getNumTasks());
00994 
00995         m_barrier = m_solverThreadSupport->createBarrier();
00996         m_criticalSection = m_solverThreadSupport->createCriticalSection();
00997 
00998         m_memoryCache = new btParallelSolverMemoryCache();
00999 }
01000         
01001 btParallelConstraintSolver::~btParallelConstraintSolver()
01002 {
01003         delete m_memoryCache;
01004         delete m_solverIO;
01005 }
01006 
01007 
01008 
01009 btScalar btParallelConstraintSolver::solveGroup(btCollisionObject** bodies1,int numRigidBodies,btPersistentManifold** manifoldPtr,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher)
01010 {
01011         
01012 /*      int sz = sizeof(PfxSolverBody);
01013         int sz2 = sizeof(vmVector3);
01014         int sz3 = sizeof(vmMatrix3);
01015         int sz4 = sizeof(vmQuat);
01016         int sz5 = sizeof(btConstraintRow);
01017         int sz6 = sizeof(btSolverConstraint);
01018         int sz7 = sizeof(TrbState);
01019 */
01020 
01021         btPersistentManifold* offsetContactManifolds= (btPersistentManifold*) dispatcher->getInternalManifoldPool()->getPoolAddress();
01022 
01023                 
01024         m_memoryCache->m_mysolverbodies.resize(numRigidBodies);
01025         m_memoryCache->m_mystates.resize(numRigidBodies);
01026 
01027         {
01028                         BT_PROFILE("create states and solver bodies");
01029         for (int i=0;i<numRigidBodies;i++)
01030         {
01031                 btCollisionObject* obj = bodies1[i];
01032                 obj->setCompanionId(i);
01033 
01034                 PfxSolverBody& solverBody = m_memoryCache->m_mysolverbodies[i];
01035                 btRigidBody* rb = btRigidBody::upcast(obj);
01036                 TrbState& state = m_memoryCache->m_mystates[i];
01037         
01038                 state.reset();
01039                 const btQuaternion& orgOri = obj->getWorldTransform().getRotation();
01040                 vmQuat orn(orgOri.getX(),orgOri.getY(),orgOri.getZ(),orgOri.getW());
01041                 state.setPosition(getVmVector3(obj->getWorldTransform().getOrigin()));
01042                 state.setOrientation(orn);
01043                 state.setPosition(state.getPosition());
01044                 state.setRigidBodyId(i);
01045                 state.setAngularDamping(0);
01046                 state.setLinearDamping(0);
01047                 
01048                 
01049                 solverBody.mOrientation = state.getOrientation();
01050                 solverBody.mDeltaLinearVelocity = vmVector3(0.0f);
01051                 solverBody.mDeltaAngularVelocity = vmVector3(0.0f);
01052                 solverBody.friction = obj->getFriction();
01053                 solverBody.restitution = obj->getRestitution();
01054                 
01055                 state.resetSleepCount();
01056                 
01057                 //if(state.getMotionMask()&PFX_MOTION_MASK_DYNAMIC) {
01058                 if (rb && (rb->getInvMass()>0.f))
01059                 {
01060                         state.setAngularVelocity(vmVector3(rb->getAngularVelocity().getX(),rb->getAngularVelocity().getY(),rb->getAngularVelocity().getZ()));
01061                         state.setLinearVelocity(vmVector3(rb->getLinearVelocity().getX(),rb->getLinearVelocity().getY(),rb->getLinearVelocity().getZ()));
01062         
01063                         state.setMotionType(PfxMotionTypeActive);
01064                         vmMatrix3 ori(solverBody.mOrientation);
01065                         vmMatrix3 localInvInertia = vmMatrix3::identity();
01066                         localInvInertia.setCol(0,vmVector3(rb->getInvInertiaDiagLocal().getX(),0,0));
01067                         localInvInertia.setCol(1,vmVector3(0, rb->getInvInertiaDiagLocal().getY(),0));
01068                         localInvInertia.setCol(2,vmVector3(0,0, rb->getInvInertiaDiagLocal().getZ()));
01069 
01070                         solverBody.mMassInv = rb->getInvMass();
01071                         solverBody.mInertiaInv = ori * localInvInertia * transpose(ori);
01072                 } else
01073                 {
01074                         state.setAngularVelocity(vmVector3(0));
01075                         state.setLinearVelocity(vmVector3(0));
01076                 
01077                         state.setMotionType(PfxMotionTypeFixed);
01078                         m_memoryCache->m_mysolverbodies[i].mMassInv = 0.f;
01079                         m_memoryCache->m_mysolverbodies[i].mInertiaInv = vmMatrix3(0.0f);
01080                 }
01081 
01082         }
01083         }
01084 
01085 
01086 
01087         int totalPoints = 0;
01088 #ifndef USE_C_ARRAYS
01089         m_memoryCache->m_mypairs.resize(numManifolds);
01090         m_memoryCache->m_jointPairs.resize(numConstraints);
01091 #endif//USE_C_ARRAYS
01092 
01093         int actualNumManifolds= 0;
01094         {
01095                 BT_PROFILE("convert manifolds");
01096                 for (int i1=0;i1<numManifolds;i1++)
01097                 {
01098                         if (manifoldPtr[i1]->getNumContacts()>0)
01099                         {
01100                                 btPersistentManifold* m = manifoldPtr[i1];
01101                                 btCollisionObject* obA = (btCollisionObject*)m->getBody0();
01102                                 btCollisionObject* obB = (btCollisionObject*)m->getBody1();
01103                                 bool obAisActive = !obA->isStaticOrKinematicObject() && obA->isActive();
01104                                 bool obBisActive = !obB->isStaticOrKinematicObject() && obB->isActive();
01105 
01106                                 if (!obAisActive && !obBisActive)
01107                                         continue;
01108 
01109 
01110                                 //int contactId = i1;//actualNumManifolds;
01111                                 
01112                                 PfxBroadphasePair& pair = m_memoryCache->m_mypairs[actualNumManifolds];
01113                                 //init those
01114                                 float compFric = obA->getFriction()*obB->getFriction();//@todo
01115                                 int idA = obA->getCompanionId();
01116                                 int idB = obB->getCompanionId();
01117                                 
01118                                 m->m_companionIdA = idA;
01119                                 m->m_companionIdB = idB;
01120                                 
01121                                 
01122                         //      if ((mysolverbodies[idA].mMassInv!=0)&&(mysolverbodies[idB].mMassInv!=0))
01123                         //              continue;
01124                                 int numPosPoints=0;
01125                                 for (int p=0;p<m->getNumContacts();p++)
01126                                 {
01127                                         //btManifoldPoint& pt = m->getContactPoint(p);
01128                                         //float dist = pt.getDistance();
01129                                         //if (dist<0.001)
01130                                                 numPosPoints++;
01131                                 }
01132 
01133                                 
01134                                 numPosPoints = numPosPoints;
01135                                 totalPoints+=numPosPoints;
01136                                 pfxSetRigidBodyIdA(pair,idA);
01137                                 pfxSetRigidBodyIdB(pair,idB);
01138                                 pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask());
01139                                 pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask());
01140                                 pfxSetActive(pair,numPosPoints>0);
01141                                 
01142                                 pfxSetBroadphaseFlag(pair,0);
01143                                 int contactId = m-offsetContactManifolds;
01144                                 //likely the contact pool is not contiguous, make sure to allocate large enough contact pool
01145                                 btAssert(contactId>=0);
01146                                 btAssert(contactId<dispatcher->getInternalManifoldPool()->getMaxCount());
01147                                 
01148                                 pfxSetContactId(pair,contactId);
01149                                 pfxSetNumConstraints(pair,numPosPoints);//manifoldPtr[i]->getNumContacts());
01150                                 actualNumManifolds++;
01151                         }
01152 
01153                 }
01154         }
01155 
01156         PfxConstraintPair* jointPairs=0;
01157         jointPairs = numConstraints? &m_memoryCache->m_jointPairs[0]:0;
01158         int actualNumJoints=0;
01159 
01160 
01161         btSolverConstraint* offsetSolverConstraints = 0;
01162 
01163         //if (1)
01164         {
01165                 
01166                 {
01167                         BT_PROFILE("convert constraints");
01168 
01169                         int totalNumRows = 0;
01170                         int i;
01171                         
01172                         m_tmpConstraintSizesPool.resize(numConstraints);
01173                         //calculate the total number of contraint rows
01174                         for (i=0;i<numConstraints;i++)
01175                         {
01176                                 btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
01177                                 constraints[i]->getInfo1(&info1);
01178                                 totalNumRows += info1.m_numConstraintRows;
01179                         }
01180                         m_tmpSolverNonContactConstraintPool.resize(totalNumRows);
01181                         offsetSolverConstraints =totalNumRows? &m_tmpSolverNonContactConstraintPool[0]:0;
01182 
01183                         
01185                         int currentRow = 0;
01186 
01187                         for (i=0;i<numConstraints;i++)
01188                         {
01189                                 const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
01190                                 
01191                                 if (info1.m_numConstraintRows)
01192                                 {
01193                                         btAssert(currentRow<totalNumRows);
01194                                         btTypedConstraint* constraint = constraints[i];
01195                                         btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
01196 
01197                                         btRigidBody& rbA = constraint->getRigidBodyA();
01198                                         btRigidBody& rbB = constraint->getRigidBodyB();
01199 
01200                                         
01201                                         int j;
01202                                         for ( j=0;j<info1.m_numConstraintRows;j++)
01203                                         {
01204                                                 memset(&currentConstraintRow[j],0,sizeof(btSolverConstraint));
01205                                                 currentConstraintRow[j].m_lowerLimit = -FLT_MAX;
01206                                                 currentConstraintRow[j].m_upperLimit = FLT_MAX;
01207                                                 currentConstraintRow[j].m_appliedImpulse = 0.f;
01208                                                 currentConstraintRow[j].m_appliedPushImpulse = 0.f;
01209                                                 currentConstraintRow[j].m_solverBodyA = &rbA;
01210                                                 currentConstraintRow[j].m_solverBodyB = &rbB;
01211                                         }
01212 
01213                                         rbA.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
01214                                         rbA.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
01215                                         rbB.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
01216                                         rbB.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
01217 
01218 
01219 
01220                                         btTypedConstraint::btConstraintInfo2 info2;
01221                                         info2.fps = 1.f/infoGlobal.m_timeStep;
01222                                         info2.erp = infoGlobal.m_erp;
01223                                         info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
01224                                         info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
01225                                         info2.m_J2linearAxis = 0;
01226                                         info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
01227                                         info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
01229                                         btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
01230                                         info2.m_constraintError = &currentConstraintRow->m_rhs;
01231                                         currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
01232                                         info2.cfm = &currentConstraintRow->m_cfm;
01233                                         info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
01234                                         info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
01235                                         info2.m_numIterations = infoGlobal.m_numIterations;
01236                                         constraints[i]->getInfo2(&info2);
01237 
01238                                         
01239                                         int idA = constraint->getRigidBodyA().getCompanionId();
01240                                         int idB = constraint->getRigidBodyB().getCompanionId();
01241                                 
01242 
01244                                         for ( j=0;j<info1.m_numConstraintRows;j++)
01245                                         {
01246                                                 btSolverConstraint& solverConstraint = currentConstraintRow[j];
01247                                                 solverConstraint.m_originalContactPoint = constraint;
01248 
01249                                                 solverConstraint.m_companionIdA = idA;
01250                                                 solverConstraint.m_companionIdB = idB;
01251 
01252                                                 {
01253                                                         const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
01254                                                         solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
01255                                                 }
01256                                                 {
01257                                                         const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
01258                                                         solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
01259                                                 }
01260 
01261                                                 {
01262                                                         btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass();
01263                                                         btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
01264                                                         btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal?
01265                                                         btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
01266 
01267                                                         btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
01268                                                         sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
01269                                                         sum += iMJlB.dot(solverConstraint.m_contactNormal);
01270                                                         sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
01271 
01272                                                         solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
01273                                                 }
01274 
01275 
01278                                                 {
01279                                                         btScalar rel_vel;
01280                                                         btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity());
01281                                                         btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity());
01282 
01283                                                         rel_vel = vel1Dotn+vel2Dotn;
01284 
01285                                                         btScalar restitution = 0.f;
01286                                                         btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
01287                                                         btScalar        velocityError = restitution - rel_vel;// * damping;
01288                                                         btScalar        penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
01289                                                         btScalar        velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
01290                                                         solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
01291                                                         solverConstraint.m_appliedImpulse = 0.f;
01292 
01293                                                 }
01294                                         }
01295 
01296                                         PfxConstraintPair& pair = jointPairs[actualNumJoints];
01297                                         
01298                                         int numConstraintRows= info1.m_numConstraintRows;
01299                                         pfxSetNumConstraints(pair,numConstraintRows);
01300                                         
01301 
01302 
01303                                         pfxSetRigidBodyIdA(pair,idA);
01304                                         pfxSetRigidBodyIdB(pair,idB);
01305                                         //is this needed?
01306                                         if (idA>=0)
01307                                                 pfxSetMotionMaskA(pair,m_memoryCache->m_mystates[idA].getMotionMask());
01308                                         if (idB>=0)
01309                                                 pfxSetMotionMaskB(pair,m_memoryCache->m_mystates[idB].getMotionMask());
01310 
01311                                         pfxSetActive(pair,true);
01312                                         int id = currentConstraintRow-offsetSolverConstraints;
01313                                         pfxSetContactId(pair,id);
01314                                         actualNumJoints++;
01315 
01316 
01317                                 }
01318                                 currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
01319                         }
01320                 }
01321         }
01322 
01323 
01324         
01325         float separateBias=0.1;//info.m_erp;//or m_erp2?
01326         float timeStep=infoGlobal.m_timeStep;
01327         int iteration=infoGlobal.m_numIterations;
01328 
01329         //create a pair for each constraints, copy over info etc
01330         
01331         
01332 
01333 
01334         
01335         {
01336                 BT_PROFILE("compute num contacts");
01337                 int totalContacts =0;
01338 
01339                 for (int i=0;i<actualNumManifolds;i++)
01340                 {
01341                         PfxConstraintPair* pair = &m_memoryCache->m_mypairs[i];
01342                         totalContacts += pfxGetNumConstraints(*pair);
01343                 }
01344                 //printf("numManifolds = %d\n",numManifolds);
01345                 //printf("totalContacts=%d\n",totalContacts);
01346         }
01347         
01348 
01349 
01350 //      printf("actualNumManifolds=%d\n",actualNumManifolds);
01351         {
01352                 BT_PROFILE("BPE_customConstraintSolverSequentialNew");
01353                 if (numRigidBodies>0 && (actualNumManifolds+actualNumJoints)>0)
01354                 {
01355 //                      PFX_PRINTF("num points = %d\n",totalPoints);
01356 //                      PFX_PRINTF("num points PFX = %d\n",total);
01357                         
01358                         
01359                          
01360                         BPE_customConstraintSolverSequentialNew(
01361                                 actualNumManifolds,
01362                                 &m_memoryCache->m_mypairs[0],
01363                                 offsetContactManifolds,
01364                                 &m_memoryCache->m_mystates[0],numRigidBodies,
01365                                 &m_memoryCache->m_mysolverbodies[0],
01366                                 jointPairs,actualNumJoints,
01367                                 offsetSolverConstraints,
01368                                 separateBias,timeStep,iteration,
01369                                 m_solverThreadSupport,m_criticalSection,m_solverIO,m_barrier);
01370                 }
01371         }
01372 
01373         //copy results back to bodies
01374         {
01375                 BT_PROFILE("copy back");
01376                 for (int i=0;i<numRigidBodies;i++)
01377                 {
01378                         btCollisionObject* obj = bodies1[i];
01379                         btRigidBody* rb = btRigidBody::upcast(obj);
01380                         TrbState& state = m_memoryCache->m_mystates[i];
01381                         if (rb && (rb->getInvMass()>0.f))
01382                         {
01383                                 rb->setLinearVelocity(btVector3(state.getLinearVelocity().getX(),state.getLinearVelocity().getY(),state.getLinearVelocity().getZ()));
01384                                 rb->setAngularVelocity(btVector3(state.getAngularVelocity().getX(),state.getAngularVelocity().getY(),state.getAngularVelocity().getZ()));
01385                         }
01386                 }
01387         }
01388 
01389 
01390         return 0.f;
01391 }