Bugfix #2875
[blender.git] / extern / bullet / BulletDynamics / ConstraintSolver / OdeConstraintSolver2.cpp
1 /*
2  * Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
3  *
4  * Permission to use, copy, modify, distribute and sell this software
5  * and its documentation for any purpose is hereby granted without fee,
6  * provided that the above copyright notice appear in all copies.
7  * Erwin Coumans makes no representations about the suitability 
8  * of this software for any purpose.  
9  * It is provided "as is" without express or implied warranty.
10 */
11
12 #include "OdeConstraintSolver.h"
13
14 #include "NarrowPhaseCollision/PersistentManifold.h"
15 #include "Dynamics/RigidBody.h"
16 #include "ContactConstraint.h"
17 #include "Solve2LinearConstraint.h"
18 #include "ContactSolverInfo.h"
19 #include "Dynamics/BU_Joint.h"
20 #include "Dynamics/ContactJoint.h"
21
22 #define USE_SOR_SOLVER
23
24 #include "SorLcp.h"
25
26 #include <math.h>
27 #include <float.h>//FLT_MAX
28 #ifdef WIN32
29 #include <memory.h>
30 #endif
31 #include <string.h>
32 #include <stdio.h>
33
34 #ifdef WIN32
35 #include <malloc.h>
36 #else
37 #include <alloca.h>
38 #endif
39
40 class BU_Joint;
41
42 //see below
43
44 int gCurBody = 0;
45 int gCurJoint= 0;
46
47 int ConvertBody(RigidBody* body,RigidBody** bodies,int& numBodies);
48 void ConvertConstraint(PersistentManifold* manifold,BU_Joint** joints,int& numJoints,
49                                            RigidBody** bodies,int bodyId0,int bodyId1);
50
51
52
53
54
55 //iterative lcp and penalty method
56 float OdeConstraintSolver::SolveGroup(PersistentManifold** manifoldPtr, int numManifolds,const ContactSolverInfo& infoGlobal)
57 {
58         gCurBody = 0;
59         gCurJoint = 0;
60
61         float cfm = 1e-5f;
62         float erp = 0.2f;
63
64         RigidBody* bodies [128];
65
66         int numBodies = 0;
67         BU_Joint* joints [128*5];
68         int numJoints = 0;
69
70         for (int j=0;j<numManifolds;j++)
71         {
72
73                 int body0=-1,body1=-1;
74
75                 PersistentManifold* manifold = manifoldPtr[j];
76                 if (manifold->GetNumContacts() > 0)
77                 {
78                         body0 = ConvertBody((RigidBody*)manifold->GetBody0(),bodies,numBodies);
79                         body1 = ConvertBody((RigidBody*)manifold->GetBody1(),bodies,numBodies);
80                         ConvertConstraint(manifold,joints,numJoints,bodies,body0,body1);
81                 }
82         }
83
84         SolveInternal1(cfm,erp,bodies,numBodies,joints,numJoints,infoGlobal);
85
86         return 0.f;
87
88 }
89
90 /////////////////////////////////////////////////////////////////////////////////
91
92
93 typedef SimdScalar dQuaternion[4];
94 #define _R(i,j) R[(i)*4+(j)]
95
96 void dRfromQ1 (dMatrix3 R, const dQuaternion q)
97 {
98   // q = (s,vx,vy,vz)
99   SimdScalar qq1 = 2*q[1]*q[1];
100   SimdScalar qq2 = 2*q[2]*q[2];
101   SimdScalar qq3 = 2*q[3]*q[3];
102   _R(0,0) = 1 - qq2 - qq3;
103   _R(0,1) = 2*(q[1]*q[2] - q[0]*q[3]);
104   _R(0,2) = 2*(q[1]*q[3] + q[0]*q[2]);
105   _R(1,0) = 2*(q[1]*q[2] + q[0]*q[3]);
106   _R(1,1) = 1 - qq1 - qq3;
107   _R(1,2) = 2*(q[2]*q[3] - q[0]*q[1]);
108   _R(2,0) = 2*(q[1]*q[3] - q[0]*q[2]);
109   _R(2,1) = 2*(q[2]*q[3] + q[0]*q[1]);
110   _R(2,2) = 1 - qq1 - qq2;
111 }
112
113
114
115 int ConvertBody(RigidBody* body,RigidBody** bodies,int& numBodies)
116 {
117         if (!body || (body->getInvMass() == 0.f) )
118         {
119                 return -1;
120         }
121         //first try to find
122         int i,j;
123         for (i=0;i<numBodies;i++)
124         {
125                 if (bodies[i] == body)
126                         return i;
127         }
128         //if not found, create a new body
129         bodies[numBodies++] = body;
130         //convert data
131
132
133         body->m_facc.setValue(0,0,0);
134         body->m_tacc.setValue(0,0,0);
135         
136         //are the indices the same ?
137         for (i=0;i<4;i++)
138         {
139                 for ( j=0;j<3;j++)
140                 {
141                         body->m_invI[i+4*j] = 0.f;
142                 }
143         }
144         body->m_invI[0+4*0] =   body->getInvInertiaDiagLocal()[0];
145         body->m_invI[1+4*1] =   body->getInvInertiaDiagLocal()[1];
146         body->m_invI[2+4*2] =   body->getInvInertiaDiagLocal()[2];
147         
148         
149         SimdMatrix3x3 invI;
150         invI.setIdentity();
151         invI[0][0] = body->getInvInertiaDiagLocal()[0];
152         invI[1][1] = body->getInvInertiaDiagLocal()[1];
153         invI[2][2] = body->getInvInertiaDiagLocal()[2];
154         SimdMatrix3x3 inertia = invI.inverse();
155
156         for (i=0;i<3;i++)
157         {
158                 for (j=0;j<3;j++)
159                 {
160                         body->m_I[i+4*j] = inertia[i][j];
161                 }
162         }
163         body->m_I[3+0*4] = 0.f;
164         body->m_I[3+1*4] = 0.f;
165         body->m_I[3+2*4] = 0.f;
166         body->m_I[3+3*4] = 0.f;
167         
168         
169         dQuaternion q;
170
171         q[1] = body->getOrientation()[0];
172         q[2] = body->getOrientation()[1];
173         q[3] = body->getOrientation()[2];
174         q[0] = body->getOrientation()[3];
175         
176         dRfromQ1(body->m_R,q);
177         
178         return numBodies-1;
179 }
180
181
182
183
184         
185 #define MAX_JOINTS_1 8192
186
187 static ContactJoint gJointArray[MAX_JOINTS_1];
188
189
190 void ConvertConstraint(PersistentManifold* manifold,BU_Joint** joints,int& numJoints,
191                                            RigidBody** bodies,int _bodyId0,int _bodyId1)
192 {
193
194
195         manifold->RefreshContactPoints(((RigidBody*)manifold->GetBody0())->getCenterOfMassTransform(),
196                 ((RigidBody*)manifold->GetBody1())->getCenterOfMassTransform());
197
198         int bodyId0 = _bodyId0,bodyId1 = _bodyId1;
199
200         int i,numContacts = manifold->GetNumContacts();
201         
202         bool swapBodies = (bodyId0 < 0);
203
204         
205         RigidBody* body0,*body1;
206
207         if (swapBodies)
208         {
209                 bodyId0 = _bodyId1;
210                 bodyId1 = _bodyId0;
211
212                 body0 = (RigidBody*)manifold->GetBody1();
213                 body1 = (RigidBody*)manifold->GetBody0();
214
215         } else
216         {
217                 body0 = (RigidBody*)manifold->GetBody0();
218                 body1 = (RigidBody*)manifold->GetBody1();
219         }
220
221         assert(bodyId0 >= 0);
222
223         for (i=0;i<numContacts;i++)
224         {
225                 
226                 assert (gCurJoint < MAX_JOINTS_1);
227
228                 ContactJoint* cont = new (&gJointArray[gCurJoint++]) ContactJoint( manifold ,i, swapBodies,body0,body1);
229
230                 cont->node[0].joint = cont;
231                 cont->node[0].body = bodyId0 >= 0 ? bodies[bodyId0] : 0;
232                 
233                 cont->node[1].joint = cont;
234                 cont->node[1].body = bodyId1 >= 0 ? bodies[bodyId1] : 0;
235                 
236                 joints[numJoints++] = cont;
237                 for (int i=0;i<6;i++)
238                         cont->lambda[i] = 0.f;
239
240                 cont->flags = 0;
241         
242         }
243
244         //create a new contact constraint
245 };
246