Bullet Collision Detection & Physics Library: btSoftBodyHelpers.cpp Source File

Bullet Collision Detection & Physics Library

btSoftBodyHelpers.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10
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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
16
17 #include "btSoftBodyInternals.h"
18 #include <stdio.h>
19 #include <string.h>
20 #include "btSoftBodyHelpers.h"
21 #include "LinearMath/btConvexHull.h"
22 #include "LinearMath/btConvexHullComputer.h"
23
24
25 //
26 static void drawVertex( btIDebugDraw* idraw,
27 const btVector3& x,btScalar s,const btVector3& c)
28 {
29 idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
30 idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c);
31 idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
32 }
33
34 //
35 static void drawBox( btIDebugDraw* idraw,
36 const btVector3& mins,
37 const btVector3& maxs,
38 const btVector3& color)
39 {
40 const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()),
41 btVector3(maxs.x(),mins.y(),mins.z()),
42 btVector3(maxs.x(),maxs.y(),mins.z()),
43 btVector3(mins.x(),maxs.y(),mins.z()),
44 btVector3(mins.x(),mins.y(),maxs.z()),
45 btVector3(maxs.x(),mins.y(),maxs.z()),
46 btVector3(maxs.x(),maxs.y(),maxs.z()),
47 btVector3(mins.x(),maxs.y(),maxs.z())};
48 idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color);
49 idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color);
50 idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color);
51 idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color);
52 idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color);
53 idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color);
54 }
55
56 //
57 static void drawTree( btIDebugDraw* idraw,
58 const btDbvtNode* node,
59 int depth,
60 const btVector3& ncolor,
61 const btVector3& lcolor,
62 int mindepth,
63 int maxdepth)
64 {
65 if(node)
66 {
67 if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
68 {
69 drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth);
70 drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth);
71 }
72 if(depth>=mindepth)
73 {
74 const btScalar scl=(btScalar)(node->isinternal()?1:1);
75 const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl;
76 const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl;
77 drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
78 }
79 }
80 }
81
82 //
83 template <typename T>
84 static inline T sum(const btAlignedObjectArray<T>& items)
85 {
86 T v;
87 if(items.size())
88 {
89 v=items[0];
90 for(int i=1,ni=items.size();i<ni;++i)
91 {
92 v+=items[i];
93 }
94 }
95 return(v);
96 }
97
98 //
99 template <typename T,typename Q>
100 static inline void add(btAlignedObjectArray<T>& items,const Q& value)
101 {
102 for(int i=0,ni=items.size();i<ni;++i)
103 {
104 items[i]+=value;
105 }
106 }
107
108 //
109 template <typename T,typename Q>
110 static inline void mul(btAlignedObjectArray<T>& items,const Q& value)
111 {
112 for(int i=0,ni=items.size();i<ni;++i)
113 {
114 items[i]*=value;
115 }
116 }
117
118 //
119 template <typename T>
120 static inline T average(const btAlignedObjectArray<T>& items)
121 {
122 const btScalar n=(btScalar)(items.size()>0?items.size():1);
123 return(sum(items)/n);
124 }
125
126 #if 0
127 //
128 inline static btScalar tetravolume(const btVector3& x0,
129 const btVector3& x1,
130 const btVector3& x2,
131 const btVector3& x3)
132 {
133 const btVector3 a=x1-x0;
134 const btVector3 b=x2-x0;
135 const btVector3 c=x3-x0;
136 return(btDot(a,btCross(b,c)));
137 }
138 #endif
139
140 //
141 #if 0
142 static btVector3 stresscolor(btScalar stress)
143 {
144 static const btVector3 spectrum[]= { btVector3(1,0,1),
145 btVector3(0,0,1),
146 btVector3(0,1,1),
147 btVector3(0,1,0),
148 btVector3(1,1,0),
149 btVector3(1,0,0),
150 btVector3(1,0,0)};
151 static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
152 static const btScalar one=1;
153 stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
154 const int sel=(int)stress;
155 const btScalar frc=stress-sel;
156 return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
157 }
158 #endif
159
160 //
161 void btSoftBodyHelpers::Draw( btSoftBody* psb,
162 btIDebugDraw* idraw,
163 int drawflags)
164 {
165 const btScalar scl=(btScalar)0.1;
166 const btScalar nscl=scl*5;
167 const btVector3 lcolor=btVector3(0,0,0);
168 const btVector3 ncolor=btVector3(1,1,1);
169 const btVector3 ccolor=btVector3(1,0,0);
170 int i,j,nj;
171
172 /* Clusters */
173 if(0!=(drawflags&fDrawFlags::Clusters))
174 {
175 srand(1806);
176 for(i=0;i<psb->m_clusters.size();++i)
177 {
178 if(psb->m_clusters[i]->m_collide)
179 {
180 btVector3 color( rand()/(btScalar)RAND_MAX,
181 rand()/(btScalar)RAND_MAX,
182 rand()/(btScalar)RAND_MAX);
183 color=color.normalized()*0.75;
184 btAlignedObjectArray<btVector3> vertices;
185 vertices.resize(psb->m_clusters[i]->m_nodes.size());
186 for(j=0,nj=vertices.size();j<nj;++j)
187 {
188 vertices[j]=psb->m_clusters[i]->m_nodes[j]->m_x;
189 }
190 #define USE_NEW_CONVEX_HULL_COMPUTER
191 #ifdef USE_NEW_CONVEX_HULL_COMPUTER
192 btConvexHullComputer computer;
193 int stride = sizeof(btVector3);
194 int count = vertices.size();
195 btScalar shrink=0.f;
196 btScalar shrinkClamp=0.f;
197 computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp);
198 for (int i=0;i<computer.faces.size();i++)
199 {
200
201 int face = computer.faces[i];
202 //printf("face=%d\n",face);
203 const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
204 const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
205
206 int v0 = firstEdge->getSourceVertex();
207 int v1 = firstEdge->getTargetVertex();
208 while (edge!=firstEdge)
209 {
210 int v2 = edge->getTargetVertex();
211 idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1);
212 edge = edge->getNextEdgeOfFace();
213 v0=v1;
214 v1=v2;
215 };
216 }
217 #else
218
219 HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]);
220 HullResult hres;
221 HullLibrary hlib;
222 hdsc.mMaxVertices=vertices.size();
223 hlib.CreateConvexHull(hdsc,hres);
224 const btVector3 center=average(hres.m_OutputVertices);
225 add(hres.m_OutputVertices,-center);
226 mul(hres.m_OutputVertices,(btScalar)1);
227 add(hres.m_OutputVertices,center);
228 for(j=0;j<(int)hres.mNumFaces;++j)
229 {
230 const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]};
231 idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
232 hres.m_OutputVertices[idx[1]],
233 hres.m_OutputVertices[idx[2]],
234 color,1);
235 }
236 hlib.ReleaseResult(hres);
237 #endif
238
239 }
240 /* Velocities */
241 #if 0
242 for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
243 {
244 const btSoftBody::Cluster& c=psb->m_clusters[i];
245 const btVector3 r=c.m_nodes[j]->m_x-c.m_com;
246 const btVector3 v=c.m_lv+btCross(c.m_av,r);
247 idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
248 }
249 #endif
250 /* Frame */
251 // btSoftBody::Cluster& c=*psb->m_clusters[i];
252 // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
253 // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
254 // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
255 }
256 }
257 else
258 {
259 /* Nodes */
260 if(0!=(drawflags&fDrawFlags::Nodes))
261 {
262 for(i=0;i<psb->m_nodes.size();++i)
263 {
264 const btSoftBody::Node& n=psb->m_nodes[i];
265 if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
266 idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
267 idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
268 idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
269 }
270 }
271 /* Links */
272 if(0!=(drawflags&fDrawFlags::Links))
273 {
274 for(i=0;i<psb->m_links.size();++i)
275 {
276 const btSoftBody::Link& l=psb->m_links[i];
277 if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
278 idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor);
279 }
280 }
281 /* Normals */
282 if(0!=(drawflags&fDrawFlags::Normals))
283 {
284 for(i=0;i<psb->m_nodes.size();++i)
285 {
286 const btSoftBody::Node& n=psb->m_nodes[i];
287 if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
288 const btVector3 d=n.m_n*nscl;
289 idraw->drawLine(n.m_x,n.m_x+d,ncolor);
290 idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
291 }
292 }
293 /* Contacts */
294 if(0!=(drawflags&fDrawFlags::Contacts))
295 {
296 static const btVector3 axis[]={btVector3(1,0,0),
297 btVector3(0,1,0),
298 btVector3(0,0,1)};
299 for(i=0;i<psb->m_rcontacts.size();++i)
300 {
301 const btSoftBody::RContact& c=psb->m_rcontacts[i];
302 const btVector3 o= c.m_node->m_x-c.m_cti.m_normal*
303 (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset);
304 const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
305 const btVector3 y=btCross(x,c.m_cti.m_normal).normalized();
306 idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
307 idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
308 idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
309 }
310 }
311 /* Faces */
312 if(0!=(drawflags&fDrawFlags::Faces))
313 {
314 const btScalar scl=(btScalar)0.8;
315 const btScalar alp=(btScalar)1;
316 const btVector3 col(0,(btScalar)0.7,0);
317 for(i=0;i<psb->m_faces.size();++i)
318 {
319 const btSoftBody::Face& f=psb->m_faces[i];
320 if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
321 const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
322 const btVector3 c=(x[0]+x[1]+x[2])/3;
323 idraw->drawTriangle((x[0]-c)*scl+c,
324 (x[1]-c)*scl+c,
325 (x[2]-c)*scl+c,
326 col,alp);
327 }
328 }
329 /* Tetras */
330 if(0!=(drawflags&fDrawFlags::Tetras))
331 {
332 const btScalar scl=(btScalar)0.8;
333 const btScalar alp=(btScalar)1;
334 const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7);
335 for(int i=0;i<psb->m_tetras.size();++i)
336 {
337 const btSoftBody::Tetra& t=psb->m_tetras[i];
338 if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
339 const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
340 const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
341 idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
342 idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
343 idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
344 idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
345 }
346 }
347 }
348 /* Anchors */
349 if(0!=(drawflags&fDrawFlags::Anchors))
350 {
351 for(i=0;i<psb->m_anchors.size();++i)
352 {
353 const btSoftBody::Anchor& a=psb->m_anchors[i];
354 const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
355 drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
356 drawVertex(idraw,q,0.25,btVector3(0,1,0));
357 idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
358 }
359 for(i=0;i<psb->m_nodes.size();++i)
360 {
361 const btSoftBody::Node& n=psb->m_nodes[i];
362 if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
363 if(n.m_im<=0)
364 {
365 drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
366 }
367 }
368 }
369
370
371 /* Notes */
372 if(0!=(drawflags&fDrawFlags::Notes))
373 {
374 for(i=0;i<psb->m_notes.size();++i)
375 {
376 const btSoftBody::Note& n=psb->m_notes[i];
377 btVector3 p=n.m_offset;
378 for(int j=0;j<n.m_rank;++j)
379 {
380 p+=n.m_nodes[j]->m_x*n.m_coords[j];
381 }
382 idraw->draw3dText(p,n.m_text);
383 }
384 }
385 /* Node tree */
386 if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw);
387 /* Face tree */
388 if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw);
389 /* Cluster tree */
390 if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw);
391 /* Joints */
392 if(0!=(drawflags&fDrawFlags::Joints))
393 {
394 for(i=0;i<psb->m_joints.size();++i)
395 {
396 const btSoftBody::Joint* pj=psb->m_joints[i];
397 switch(pj->Type())
398 {
399 case btSoftBody::Joint::eType::Linear:
400 {
401 const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj;
402 const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0];
403 const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1];
404 idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0));
405 idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1));
406 drawVertex(idraw,a0,0.25,btVector3(1,1,0));
407 drawVertex(idraw,a1,0.25,btVector3(0,1,1));
408 }
409 break;
410 case btSoftBody::Joint::eType::Angular:
411 {
412 //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj;
413 const btVector3 o0=pj->m_bodies[0].xform().getOrigin();
414 const btVector3 o1=pj->m_bodies[1].xform().getOrigin();
415 const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0];
416 const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1];
417 idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0));
418 idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0));
419 idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1));
420 idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1));
421 break;
422 }
423 default:
424 {
425 }
426
427 }
428 }
429 }
430 }
431
432 //
433 void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
434 btIDebugDraw* idraw,
435 bool masses,
436 bool areas,
437 bool /*stress*/)
438 {
439 for(int i=0;i<psb->m_nodes.size();++i)
440 {
441 const btSoftBody::Node& n=psb->m_nodes[i];
442 char text[2048]={0};
443 char buff[1024];
444 if(masses)
445 {
446 sprintf(buff," M(%.2f)",1/n.m_im);
447 strcat(text,buff);
448 }
449 if(areas)
450 {
451 sprintf(buff," A(%.2f)",n.m_area);
452 strcat(text,buff);
453 }
454 if(text[0]) idraw->draw3dText(n.m_x,text);
455 }
456 }
457
458 //
459 void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb,
460 btIDebugDraw* idraw,
461 int mindepth,
462 int maxdepth)
463 {
464 drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth);
465 }
466
467 //
468 void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb,
469 btIDebugDraw* idraw,
470 int mindepth,
471 int maxdepth)
472 {
473 drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth);
474 }
475
476 //
477 void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb,
478 btIDebugDraw* idraw,
479 int mindepth,
480 int maxdepth)
481 {
482 drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth);
483 }
484
485
486 //The btSoftBody object from the BulletSDK includes an array of Nodes and Links. These links appear
487 // to be first set up to connect a node to between 5 and 6 of its neighbors [480 links],
488 //and then to the rest of the nodes after the execution of the Floyd-Warshall graph algorithm
489 //[another 930 links].
490 //The way the links are stored by default, we have a number of cases where adjacent links share a node in common
491 // - this leads to the creation of a data dependency through memory.
492 //The PSolve_Links() function reads and writes nodes as it iterates over each link.
493 //So, we now have the possibility of a data dependency between iteration X
494 //that processes link L with iteration X+1 that processes link L+1
495 //because L and L+1 have one node in common, and iteration X updates the positions of that node,
496 //and iteration X+1 reads in the position of that shared node.
497 //
498 //Such a memory dependency limits the ability of a modern CPU to speculate beyond
499 //a certain point because it has to respect a possible dependency
500 //- this prevents the CPU from making full use of its out-of-order resources.
501 //If we re-order the links such that we minimize the cases where a link L and L+1 share a common node,
502 //we create a temporal gap between when the node position is written,
503 //and when it is subsequently read. This in turn allows the CPU to continue execution without
504 //risking a dependency violation. Such a reordering would result in significant speedups on
505 //modern CPUs with lots of execution resources.
506 //In our testing, we see it have a tremendous impact not only on the A7,
507 //but also on all x86 cores that ship with modern Macs.
508 //The attached source file includes a single function (ReoptimizeLinkOrder) which can be called on a
509 //btSoftBody object in the solveConstraints() function before the actual solver is invoked,
510 //or right after generateBendingConstraints() once we have all 1410 links.
511
512
513 //===================================================================
514 //
515 //
516 // This function takes in a list of interdependent Links and tries
517 // to maximize the distance between calculation
518 // of dependent links. This increases the amount of parallelism that can
519 // be exploited by out-of-order instruction processors with large but
520 // (inevitably) finite instruction windows.
521 //
522 //===================================================================
523
524 // A small structure to track lists of dependent link calculations
525 class LinkDeps_t {
526 public:
527 int value; // A link calculation that is dependent on this one
528 // Positive values = "input A" while negative values = "input B"
529 LinkDeps_t *next; // Next dependence in the list
530 };
531 typedef LinkDeps_t *LinkDepsPtr_t;
532
533 // Dependency list constants
534 #define REOP_NOT_DEPENDENT -1
535 #define REOP_NODE_COMPLETE -2 // Must be less than REOP_NOT_DEPENDENT
536
537
538 void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody *psb /* This can be replaced by a btSoftBody pointer */)
539 {
540 int i, nLinks=psb->m_links.size(), nNodes=psb->m_nodes.size();
541 btSoftBody::Link *lr;
542 int ar, br;
543 btSoftBody::Node *node0 = &(psb->m_nodes[0]);
544 btSoftBody::Node *node1 = &(psb->m_nodes[1]);
545 LinkDepsPtr_t linkDep;
546 int readyListHead, readyListTail, linkNum, linkDepFrees, depLink;
547
548 // Allocate temporary buffers
549 int *nodeWrittenAt = new int[nNodes+1]; // What link calculation produced this node's current values?
550 int *linkDepA = new int[nLinks]; // Link calculation input is dependent upon prior calculation #N
551 int *linkDepB = new int[nLinks];
552 int *readyList = new int[nLinks]; // List of ready-to-process link calculations (# of links, maximum)
553 LinkDeps_t *linkDepFreeList = new LinkDeps_t[2*nLinks]; // Dependent-on-me list elements (2x# of links, maximum)
554 LinkDepsPtr_t *linkDepListStarts = new LinkDepsPtr_t[nLinks]; // Start nodes of dependent-on-me lists, one for each link
555
556 // Copy the original, unsorted links to a side buffer
557 btSoftBody::Link *linkBuffer = new btSoftBody::Link[nLinks];
558 memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link)*nLinks);
559
560 // Clear out the node setup and ready list
561 for (i=0; i < nNodes+1; i++) {
562 nodeWrittenAt[i] = REOP_NOT_DEPENDENT;
563 }
564 for (i=0; i < nLinks; i++) {
565 linkDepListStarts[i] = NULL;
566 }
567 readyListHead = readyListTail = linkDepFrees = 0;
568
569 // Initial link analysis to set up data structures
570 for (i=0; i < nLinks; i++) {
571
572 // Note which prior link calculations we are dependent upon & build up dependence lists
573 lr = &(psb->m_links[i]);
574 ar = (lr->m_n[0] - node0)/(node1 - node0);
575 br = (lr->m_n[1] - node0)/(node1 - node0);
576 if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT) {
577 linkDepA[i] = nodeWrittenAt[ar];
578 linkDep = &linkDepFreeList[linkDepFrees++];
579 linkDep->value = i;
580 linkDep->next = linkDepListStarts[nodeWrittenAt[ar]];
581 linkDepListStarts[nodeWrittenAt[ar]] = linkDep;
582 } else {
583 linkDepA[i] = REOP_NOT_DEPENDENT;
584 }
585 if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT) {
586 linkDepB[i] = nodeWrittenAt[br];
587 linkDep = &linkDepFreeList[linkDepFrees++];
588 linkDep->value = -(i+1);
589 linkDep->next = linkDepListStarts[nodeWrittenAt[br]];
590 linkDepListStarts[nodeWrittenAt[br]] = linkDep;
591 } else {
592 linkDepB[i] = REOP_NOT_DEPENDENT;
593 }
594
595 // Add this link to the initial ready list, if it is not dependent on any other links
596 if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT)) {
597 readyList[readyListTail++] = i;
598 linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE; // Probably not needed now
599 }
600
601 // Update the nodes to mark which ones are calculated by this link
602 nodeWrittenAt[ar] = nodeWrittenAt[br] = i;
603 }
604
605 // Process the ready list and create the sorted list of links
606 // -- By treating the ready list as a queue, we maximize the distance between any
607 // inter-dependent node calculations
608 // -- All other (non-related) nodes in the ready list will automatically be inserted
609 // in between each set of inter-dependent link calculations by this loop
610 i = 0;
611 while (readyListHead != readyListTail) {
612 // Use ready list to select the next link to process
613 linkNum = readyList[readyListHead++];
614 // Copy the next-to-calculate link back into the original link array
615 psb->m_links[i++] = linkBuffer[linkNum];
616
617 // Free up any link inputs that are dependent on this one
618 linkDep = linkDepListStarts[linkNum];
619 while (linkDep) {
620 depLink = linkDep->value;
621 if (depLink >= 0) {
622 linkDepA[depLink] = REOP_NOT_DEPENDENT;
623 } else {
624 depLink = -depLink - 1;
625 linkDepB[depLink] = REOP_NOT_DEPENDENT;
626 }
627 // Add this dependent link calculation to the ready list if *both* inputs are clear
628 if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT)) {
629 readyList[readyListTail++] = depLink;
630 linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE; // Probably not needed now
631 }
632 linkDep = linkDep->next;
633 }
634 }
635
636 // Delete the temporary buffers
637 delete [] nodeWrittenAt;
638 delete [] linkDepA;
639 delete [] linkDepB;
640 delete [] readyList;
641 delete [] linkDepFreeList;
642 delete [] linkDepListStarts;
643 delete [] linkBuffer;
644 }
645
646
647 //
648 void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
649 btIDebugDraw* idraw)
650 {
651 if(psb->m_pose.m_bframe)
652 {
653 static const btScalar ascl=10;
654 static const btScalar nscl=(btScalar)0.1;
655 const btVector3 com=psb->m_pose.m_com;
656 const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl;
657 const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized();
658 const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized();
659 const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized();
660 idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
661 idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
662 idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
663 for(int i=0;i<psb->m_pose.m_pos.size();++i)
664 {
665 const btVector3 x=com+trs*psb->m_pose.m_pos[i];
666 drawVertex(idraw,x,nscl,btVector3(1,0,1));
667 }
668 }
669 }
670
671 //
672 btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from,
673 const btVector3& to,
674 int res,
675 int fixeds)
676 {
677 /* Create nodes */
678 const int r=res+2;
679 btVector3* x=new btVector3[r];
680 btScalar* m=new btScalar[r];
681 int i;
682
683 for(i=0;i<r;++i)
684 {
685 const btScalar t=i/(btScalar)(r-1);
686 x[i]=lerp(from,to,t);
687 m[i]=1;
688 }
689 btSoftBody* psb= new btSoftBody(&worldInfo,r,x,m);
690 if(fixeds&1) psb->setMass(0,0);
691 if(fixeds&2) psb->setMass(r-1,0);
692 delete[] x;
693 delete[] m;
694 /* Create links */
695 for(i=1;i<r;++i)
696 {
697 psb->appendLink(i-1,i);
698 }
699 /* Finished */
700 return(psb);
701 }
702
703 //
704 btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
705 const btVector3& corner10,
706 const btVector3& corner01,
707 const btVector3& corner11,
708 int resx,
709 int resy,
710 int fixeds,
711 bool gendiags)
712 {
713 #define IDX(_x_,_y_) ((_y_)*rx+(_x_))
714 /* Create nodes */
715 if((resx<2)||(resy<2)) return(0);
716 const int rx=resx;
717 const int ry=resy;
718 const int tot=rx*ry;
719 btVector3* x=new btVector3[tot];
720 btScalar* m=new btScalar[tot];
721 int iy;
722
723 for(iy=0;iy<ry;++iy)
724 {
725 const btScalar ty=iy/(btScalar)(ry-1);
726 const btVector3 py0=lerp(corner00,corner01,ty);
727 const btVector3 py1=lerp(corner10,corner11,ty);
728 for(int ix=0;ix<rx;++ix)
729 {
730 const btScalar tx=ix/(btScalar)(rx-1);
731 x[IDX(ix,iy)]=lerp(py0,py1,tx);
732 m[IDX(ix,iy)]=1;
733 }
734 }
735 btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
736 if(fixeds&1) psb->setMass(IDX(0,0),0);
737 if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
738 if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
739 if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
740 delete[] x;
741 delete[] m;
742 /* Create links and faces */
743 for(iy=0;iy<ry;++iy)
744 {
745 for(int ix=0;ix<rx;++ix)
746 {
747 const int idx=IDX(ix,iy);
748 const bool mdx=(ix+1)<rx;
749 const bool mdy=(iy+1)<ry;
750 if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
751 if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
752 if(mdx&&mdy)
753 {
754 if((ix+iy)&1)
755 {
756 psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
757 psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
758 if(gendiags)
759 {
760 psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
761 }
762 }
763 else
764 {
765 psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
766 psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
767 if(gendiags)
768 {
769 psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
770 }
771 }
772 }
773 }
774 }
775 /* Finished */
776 #undef IDX
777 return(psb);
778 }
779
780 //
781 btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
782 const btVector3& corner00,
783 const btVector3& corner10,
784 const btVector3& corner01,
785 const btVector3& corner11,
786 int resx,
787 int resy,
788 int fixeds,
789 bool gendiags,
790 float* tex_coords)
791 {
792
793 /*
794 *
795 * corners:
796 *
797 * [0][0] corner00 ------- corner01 [resx][0]
798 * | |
799 * | |
800 * [0][resy] corner10 -------- corner11 [resx][resy]
801 *
802 *
803 *
804 *
805 *
806 *
807 * "fixedgs" map:
808 *
809 * corner00 --> +1
810 * corner01 --> +2
811 * corner10 --> +4
812 * corner11 --> +8
813 * upper middle --> +16
814 * left middle --> +32
815 * right middle --> +64
816 * lower middle --> +128
817 * center --> +256
818 *
819 *
820 * tex_coords size (resx-1)*(resy-1)*12
821 *
822 *
823 *
824 * SINGLE QUAD INTERNALS
825 *
826 * 1) btSoftBody's nodes and links,
827 * diagonal link is optional ("gendiags")
828 *
829 *
830 * node00 ------ node01
831 * | .
832 * | .
833 * | .
834 * | .
835 * | .
836 * node10 node11
837 *
838 *
839 *
840 * 2) Faces:
841 * two triangles,
842 * UV Coordinates (hier example for single quad)
843 *
844 * (0,1) (0,1) (1,1)
845 * 1 |\ 3 \-----| 2
846 * | \ \ |
847 * | \ \ |
848 * | \ \ |
849 * | \ \ |
850 * 2 |-----\ 3 \| 1
851 * (0,0) (1,0) (1,0)
852 *
853 *
854 *
855 *
856 *
857 *
858 */
859
860 #define IDX(_x_,_y_) ((_y_)*rx+(_x_))
861 /* Create nodes */
862 if((resx<2)||(resy<2)) return(0);
863 const int rx=resx;
864 const int ry=resy;
865 const int tot=rx*ry;
866 btVector3* x=new btVector3[tot];
867 btScalar* m=new btScalar[tot];
868
869 int iy;
870
871 for(iy=0;iy<ry;++iy)
872 {
873 const btScalar ty=iy/(btScalar)(ry-1);
874 const btVector3 py0=lerp(corner00,corner01,ty);
875 const btVector3 py1=lerp(corner10,corner11,ty);
876 for(int ix=0;ix<rx;++ix)
877 {
878 const btScalar tx=ix/(btScalar)(rx-1);
879 x[IDX(ix,iy)]=lerp(py0,py1,tx);
880 m[IDX(ix,iy)]=1;
881 }
882 }
883 btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
884 if(fixeds&1) psb->setMass(IDX(0,0),0);
885 if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
886 if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
887 if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
888 if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0);
889 if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0);
890 if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0);
891 if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0);
892 if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0);
893 delete[] x;
894 delete[] m;
895
896
897 int z = 0;
898 /* Create links and faces */
899 for(iy=0;iy<ry;++iy)
900 {
901 for(int ix=0;ix<rx;++ix)
902 {
903 const bool mdx=(ix+1)<rx;
904 const bool mdy=(iy+1)<ry;
905
906 int node00=IDX(ix,iy);
907 int node01=IDX(ix+1,iy);
908 int node10=IDX(ix,iy+1);
909 int node11=IDX(ix+1,iy+1);
910
911 if(mdx) psb->appendLink(node00,node01);
912 if(mdy) psb->appendLink(node00,node10);
913 if(mdx&&mdy)
914 {
915 psb->appendFace(node00,node10,node11);
916 if (tex_coords) {
917 tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0);
918 tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1);
919 tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0);
920 tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2);
921 tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3);
922 tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2);
923 }
924 psb->appendFace(node11,node01,node00);
925 if (tex_coords) {
926 tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3);
927 tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2);
928 tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3);
929 tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1);
930 tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0);
931 tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1);
932 }
933 if (gendiags) psb->appendLink(node00,node11);
934 z += 12;
935 }
936 }
937 }
938 /* Finished */
939 #undef IDX
940 return(psb);
941 }
942
943 float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id)
944 {
945
946 /*
947 *
948 *
949 * node00 --- node01
950 * | |
951 * node10 --- node11
952 *
953 *
954 * ID map:
955 *
956 * node00 s --> 0
957 * node00 t --> 1
958 *
959 * node01 s --> 3
960 * node01 t --> 1
961 *
962 * node10 s --> 0
963 * node10 t --> 2
964 *
965 * node11 s --> 3
966 * node11 t --> 2
967 *
968 *
969 */
970
971 float tc=0.0f;
972 if (id == 0) {
973 tc = (1.0f/((resx-1))*ix);
974 }
975 else if (id==1) {
976 tc = (1.0f/((resy-1))*(resy-1-iy));
977 }
978 else if (id==2) {
979 tc = (1.0f/((resy-1))*(resy-1-iy-1));
980 }
981 else if (id==3) {
982 tc = (1.0f/((resx-1))*(ix+1));
983 }
984 return tc;
985 }
986 //
987 btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center,
988 const btVector3& radius,
989 int res)
990 {
991 struct Hammersley
992 {
993 static void Generate(btVector3* x,int n)
994 {
995 for(int i=0;i<n;i++)
996 {
997 btScalar p=0.5,t=0;
998 for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
999 btScalar w=2*t-1;
1000 btScalar a=(SIMD_PI+2*i*SIMD_PI)/n;
1001 btScalar s=btSqrt(1-w*w);
1002 *x++=btVector3(s*btCos(a),s*btSin(a),w);
1003 }
1004 }
1005 };
1006 btAlignedObjectArray<btVector3> vtx;
1007 vtx.resize(3+res);
1008 Hammersley::Generate(&vtx[0],vtx.size());
1009 for(int i=0;i<vtx.size();++i)
1010 {
1011 vtx[i]=vtx[i]*radius+center;
1012 }
1013 return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
1014 }
1015
1016
1017
1018 //
1019 btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
1020 const int* triangles,
1021 int ntriangles, bool randomizeConstraints)
1022 {
1023 int maxidx=0;
1024 int i,j,ni;
1025
1026 for(i=0,ni=ntriangles*3;i<ni;++i)
1027 {
1028 maxidx=btMax(triangles[i],maxidx);
1029 }
1030 ++maxidx;
1031 btAlignedObjectArray<bool> chks;
1032 btAlignedObjectArray<btVector3> vtx;
1033 chks.resize(maxidx*maxidx,false);
1034 vtx.resize(maxidx);
1035 for(i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
1036 {
1037 vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
1038 }
1039 btSoftBody* psb=new btSoftBody(&worldInfo,vtx.size(),&vtx[0],0);
1040 for( i=0,ni=ntriangles*3;i<ni;i+=3)
1041 {
1042 const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
1043 #define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
1044 for(int j=2,k=0;k<3;j=k++)
1045 {
1046 if(!chks[IDX(idx[j],idx[k])])
1047 {
1048 chks[IDX(idx[j],idx[k])]=true;
1049 chks[IDX(idx[k],idx[j])]=true;
1050 psb->appendLink(idx[j],idx[k]);
1051 }
1052 }
1053 #undef IDX
1054 psb->appendFace(idx[0],idx[1],idx[2]);
1055 }
1056
1057 if (randomizeConstraints)
1058 {
1059 psb->randomizeConstraints();
1060 }
1061
1062 return(psb);
1063 }
1064
1065 //
1066 btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
1067 int nvertices, bool randomizeConstraints)
1068 {
1069 HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
1070 HullResult hres;
1071 HullLibrary hlib;/*??*/
1072 hdsc.mMaxVertices=nvertices;
1073 hlib.CreateConvexHull(hdsc,hres);
1074 btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
1075 &hres.m_OutputVertices[0],0);
1076 for(int i=0;i<(int)hres.mNumFaces;++i)
1077 {
1078 const int idx[]={ static_cast<int>(hres.m_Indices[i*3+0]),
1079 static_cast<int>(hres.m_Indices[i*3+1]),
1080 static_cast<int>(hres.m_Indices[i*3+2])};
1081 if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
1082 if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
1083 if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
1084 psb->appendFace(idx[0],idx[1],idx[2]);
1085 }
1086 hlib.ReleaseResult(hres);
1087 if (randomizeConstraints)
1088 {
1089 psb->randomizeConstraints();
1090 }
1091 return(psb);
1092 }
1093
1094
1095
1096
1097 static int nextLine(const char* buffer)
1098 {
1099 int numBytesRead=0;
1100
1101 while (*buffer != '\n')
1102 {
1103 buffer++;
1104 numBytesRead++;
1105 }
1106
1107
1108 if (buffer[0]==0x0a)
1109 {
1110 buffer++;
1111 numBytesRead++;
1112 }
1113 return numBytesRead;
1114 }
1115
1116 /* Create from TetGen .ele, .face, .node data */
1117 btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
1118 const char* ele,
1119 const char* face,
1120 const char* node,
1121 bool bfacelinks,
1122 bool btetralinks,
1123 bool bfacesfromtetras)
1124 {
1125 btAlignedObjectArray<btVector3> pos;
1126 int nnode=0;
1127 int ndims=0;
1128 int nattrb=0;
1129 int hasbounds=0;
1130 int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
1131 result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
1132 node += nextLine(node);
1133
1134 pos.resize(nnode);
1135 for(int i=0;i<pos.size();++i)
1136 {
1137 int index=0;
1138 //int bound=0;
1139 float x,y,z;
1140 sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
1141
1142 // sn>>index;
1143 // sn>>x;sn>>y;sn>>z;
1144 node += nextLine(node);
1145
1146 //for(int j=0;j<nattrb;++j)
1147 // sn>>a;
1148
1149 //if(hasbounds)
1150 // sn>>bound;
1151
1152 pos[index].setX(btScalar(x));
1153 pos[index].setY(btScalar(y));
1154 pos[index].setZ(btScalar(z));
1155 }
1156 btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
1157 #if 0
1158 if(face&&face[0])
1159 {
1160 int nface=0;
1161 sf>>nface;sf>>hasbounds;
1162 for(int i=0;i<nface;++i)
1163 {
1164 int index=0;
1165 int bound=0;
1166 int ni[3];
1167 sf>>index;
1168 sf>>ni[0];sf>>ni[1];sf>>ni[2];
1169 sf>>bound;
1170 psb->appendFace(ni[0],ni[1],ni[2]);
1171 if(btetralinks)
1172 {
1173 psb->appendLink(ni[0],ni[1],0,true);
1174 psb->appendLink(ni[1],ni[2],0,true);
1175 psb->appendLink(ni[2],ni[0],0,true);
1176 }
1177 }
1178 }
1179 #endif
1180
1181 if(ele&&ele[0])
1182 {
1183 int ntetra=0;
1184 int ncorner=0;
1185 int neattrb=0;
1186 sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
1187 ele += nextLine(ele);
1188
1189 //se>>ntetra;se>>ncorner;se>>neattrb;
1190 for(int i=0;i<ntetra;++i)
1191 {
1192 int index=0;
1193 int ni[4];
1194
1195 //se>>index;
1196 //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
1197 sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
1198 ele+=nextLine(ele);
1199 //for(int j=0;j<neattrb;++j)
1200 // se>>a;
1201 psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
1202 if(btetralinks)
1203 {
1204 psb->appendLink(ni[0],ni[1],0,true);
1205 psb->appendLink(ni[1],ni[2],0,true);
1206 psb->appendLink(ni[2],ni[0],0,true);
1207 psb->appendLink(ni[0],ni[3],0,true);
1208 psb->appendLink(ni[1],ni[3],0,true);
1209 psb->appendLink(ni[2],ni[3],0,true);
1210 }
1211 }
1212 }
1213 printf("Nodes: %u\r\n",psb->m_nodes.size());
1214 printf("Links: %u\r\n",psb->m_links.size());
1215 printf("Faces: %u\r\n",psb->m_faces.size());
1216 printf("Tetras: %u\r\n",psb->m_tetras.size());
1217 return(psb);
1218 }
1219
sum
static T sum(const btAlignedObjectArray< T > &items)
Definition: btSoftBodyHelpers.cpp:84
LinkDeps_t
Definition: btSoftBodyHelpers.cpp:525
btSoftBody::Pose::m_scl
btMatrix3x3 m_scl
Definition: btSoftBody.h:318
btSoftBody::Face
Definition: btSoftBody.h:249
btSoftBody::Material::m_flags
int m_flags
Definition: btSoftBody.h:213
btSoftBody::Link
Definition: btSoftBody.h:235
fDrawFlags::Anchors
Definition: btSoftBodyHelpers.h:33
btSoftBody::sCti::m_normal
btVector3 m_normal
Definition: btSoftBody.h:189
btSoftBody::Note
Definition: btSoftBody.h:300
btSoftBody::Node
Definition: btSoftBody.h:222
btConvexHullComputer::edges
btAlignedObjectArray< Edge > edges
Definition: btConvexHullComputer.h:72
btSoftBodyHelpers::CreatePatchUV
static btSoftBody * CreatePatchUV(btSoftBodyWorldInfo &worldInfo, const btVector3 &corner00, const btVector3 &corner10, const btVector3 &corner01, const btVector3 &corner11, int resx, int resy, int fixeds, bool gendiags, float *tex_coords=0)
Definition: btSoftBodyHelpers.cpp:781
btSoftBody::Joint::eType::Angular
Definition: btSoftBody.h:491
btAlignedObjectArray
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
Definition: btAlignedObjectArray.h:53
btSin
btScalar btSin(btScalar x)
Definition: btScalar.h:477
IDX
#define IDX(_x_, _y_)
btSoftBody::Joint
Definition: btSoftBody.h:487
fDrawFlags::Contacts
Definition: btSoftBodyHelpers.h:32
btIDebugDraw::drawLine
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
btSoftBody::m_joints
tJointArray m_joints
Definition: btSoftBody.h:666
btSoftBodyHelpers::CreateEllipsoid
static btSoftBody * CreateEllipsoid(btSoftBodyWorldInfo &worldInfo, const btVector3 &center, const btVector3 &radius, int res)
Definition: btSoftBodyHelpers.cpp:987
btSoftBody::Tetra
Definition: btSoftBody.h:257
btSoftBodyHelpers::CreatePatch
static btSoftBody * CreatePatch(btSoftBodyWorldInfo &worldInfo, const btVector3 &corner00, const btVector3 &corner10, const btVector3 &corner01, const btVector3 &corner11, int resx, int resy, int fixeds, bool gendiags)
Definition: btSoftBodyHelpers.cpp:704
btSqrt
btScalar btSqrt(btScalar y)
Definition: btScalar.h:444
HullResult::m_Indices
btAlignedObjectArray< unsigned int > m_Indices
Definition: btConvexHull.h:42
btSoftBody::Cluster::m_nodes
btAlignedObjectArray< Node * > m_nodes
Definition: btSoftBody.h:325
btSoftBody::Tetra::m_n
Node * m_n[4]
Definition: btSoftBody.h:259
btDbvtAabbMm::Center
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:133
btSoftBody::Node::m_im
btScalar m_im
Definition: btSoftBody.h:229
btSoftBody::Cluster
Definition: btSoftBody.h:322
btSoftBody::m_fdbvt
btDbvt m_fdbvt
Definition: btSoftBody.h:672
btDbvt::m_root
btDbvtNode * m_root
Definition: btDbvt.h:262
REOP_NOT_DEPENDENT
#define REOP_NOT_DEPENDENT
Definition: btSoftBodyHelpers.cpp:534
btSoftBodyHelpers::CreateFromTetGenData
static btSoftBody * CreateFromTetGenData(btSoftBodyWorldInfo &worldInfo, const char *ele, const char *face, const char *node, bool bfacelinks, bool btetralinks, bool bfacesfromtetras)
Definition: btSoftBodyHelpers.cpp:1117
btSoftBodyHelpers::DrawFaceTree
static void DrawFaceTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:468
btSoftBody::appendLink
void appendLink(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:262
LinkDepsPtr_t
LinkDeps_t * LinkDepsPtr_t
Definition: btSoftBodyHelpers.cpp:531
btConvexHullComputer
Convex hull implementation based on Preparata and Hong See http://code.google.com/p/bullet/issues/det...
Definition: btConvexHullComputer.h:24
btSoftBody::m_nodes
tNodeArray m_nodes
Definition: btSoftBody.h:659
btSoftBody::m_links
tLinkArray m_links
Definition: btSoftBody.h:660
btDbvtAabbMm::Extents
DBVT_INLINE btVector3 Extents() const
Definition: btDbvt.h:135
btSoftBody::Face::m_n
Node * m_n[3]
Definition: btSoftBody.h:251
fDrawFlags::Nodes
Definition: btSoftBodyHelpers.h:27
btVector3::normalized
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:964
btSoftBodyHelpers::Draw
static void Draw(btSoftBody *psb, btIDebugDraw *idraw, int drawflags=fDrawFlags::Std)
Definition: btSoftBodyHelpers.cpp:161
add
static void add(btAlignedObjectArray< T > &items, const Q &value)
Definition: btSoftBodyHelpers.cpp:100
btSoftBody::appendFace
void appendFace(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:299
btSoftBody::m_tetras
tTetraArray m_tetras
Definition: btSoftBody.h:662
btSoftBodyHelpers::CreateFromConvexHull
static btSoftBody * CreateFromConvexHull(btSoftBodyWorldInfo &worldInfo, const btVector3 *vertices, int nvertices, bool randomizeConstraints=true)
Definition: btSoftBodyHelpers.cpp:1066
HullResult::mNumFaces
unsigned int mNumFaces
Definition: btConvexHull.h:40
btSoftBody::Note::m_text
const char * m_text
Definition: btSoftBody.h:302
drawBox
static void drawBox(btIDebugDraw *idraw, const btVector3 &mins, const btVector3 &maxs, const btVector3 &color)
Definition: btSoftBodyHelpers.cpp:35
btCross
btVector3 btCross(const btVector3 &v1, const btVector3 &v2)
Return the cross product of two vectors.
Definition: btVector3.h:931
btSoftBody::Pose::m_bframe
bool m_bframe
Definition: btSoftBody.h:312
btSoftBody::RContact
Definition: btSoftBody.h:267
btConvexHullComputer::Edge::getTargetVertex
int getTargetVertex() const
Definition: btConvexHullComputer.h:46
btIDebugDraw::draw3dText
virtual void draw3dText(const btVector3 &location, const char *textString)=0
SIMD_PI
#define SIMD_PI
Definition: btScalar.h:504
btCollisionObject::getWorldTransform
btTransform & getWorldTransform()
Definition: btCollisionObject.h:372
btSoftBody::Feature::m_material
Material * m_material
Definition: btSoftBody.h:219
btSoftBody::Note::m_offset
btVector3 m_offset
Definition: btSoftBody.h:303
btVector3::minAxis
int minAxis() const
Return the axis with the smallest value Note return values are 0,1,2 for x, y, or z...
Definition: btVector3.h:480
btSoftBody::Anchor
Definition: btSoftBody.h:289
mul
static void mul(btAlignedObjectArray< T > &items, const Q &value)
Definition: btSoftBodyHelpers.cpp:110
btTransform::getOrigin
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
HullLibrary::CreateConvexHull
HullError CreateConvexHull(const HullDesc &desc, HullResult &result)
Definition: btConvexHull.cpp:691
btSoftBody::Joint::Type
virtual eType::_ Type() const =0
btSoftBody::randomizeConstraints
void randomizeConstraints()
Definition: btSoftBody.cpp:1160
btVector3::x
const btScalar & x() const
Return the x value.
Definition: btVector3.h:587
btDbvtNode::childs
btDbvtNode * childs[2]
Definition: btDbvt.h:186
fDrawFlags::Joints
Definition: btSoftBodyHelpers.h:39
btSoftBodyHelpers::CreateRope
static btSoftBody * CreateRope(btSoftBodyWorldInfo &worldInfo, const btVector3 &from, const btVector3 &to, int res, int fixeds)
Definition: btSoftBodyHelpers.cpp:672
fDrawFlags::NodeTree
Definition: btSoftBodyHelpers.h:36
btSoftBodyHelpers::DrawInfos
static void DrawInfos(btSoftBody *psb, btIDebugDraw *idraw, bool masses, bool areas, bool stress)
Definition: btSoftBodyHelpers.cpp:433
btConvexHullComputer.h
btSoftBody::Link::m_n
Node * m_n[2]
Definition: btSoftBody.h:238
btSoftBody::appendTetra
void appendTetra(int model, Material *mat)
Definition: btSoftBody.cpp:334
btSoftBody::RContact::m_node
Node * m_node
Definition: btSoftBody.h:270
btVector3::y
const btScalar & y() const
Return the y value.
Definition: btVector3.h:589
btVector3::z
const btScalar & z() const
Return the z value.
Definition: btVector3.h:591
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
btSoftBody::fMaterial::DebugDraw
Definition: btSoftBody.h:152
btIDebugDraw
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
Definition: btIDebugDraw.h:29
btSoftBody::m_anchors
tAnchorArray m_anchors
Definition: btSoftBody.h:663
HullResult::m_OutputVertices
btAlignedObjectArray< btVector3 > m_OutputVertices
Definition: btConvexHull.h:39
btSoftBody::m_pose
Pose m_pose
Definition: btSoftBody.h:655
btSoftBody::Anchor::m_node
Node * m_node
Definition: btSoftBody.h:291
LinkDeps_t::value
int value
Definition: btSoftBodyHelpers.cpp:527
btSoftBodyHelpers::DrawNodeTree
static void DrawNodeTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:459
drawVertex
static void drawVertex(btIDebugDraw *idraw, const btVector3 &x, btScalar s, const btVector3 &c)
btSoftBodyHelpers.cpp by Nathanael Presson
Definition: btSoftBodyHelpers.cpp:26
btSoftBodyHelpers::DrawClusterTree
static void DrawClusterTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:477
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
fDrawFlags::FaceTree
Definition: btSoftBodyHelpers.h:37
btSoftBody::Note::m_coords
btScalar m_coords[4]
Definition: btSoftBody.h:306
btSoftBody::sCti::m_offset
btScalar m_offset
Definition: btSoftBody.h:190
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:155
QF_TRIANGLES
Definition: btConvexHull.h:50
btConvexHull.h
btConvexHullComputer::vertices
btAlignedObjectArray< btVector3 > vertices
Definition: btConvexHullComputer.h:69
HullResult
Definition: btConvexHull.h:27
btIDebugDraw::drawTriangle
virtual void drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &, const btVector3 &, const btVector3 &, const btVector3 &color, btScalar alpha)
Definition: btIDebugDraw.h:116
btSoftBody::Pose::m_com
btVector3 m_com
Definition: btSoftBody.h:316
btSoftBody::RContact::m_cti
sCti m_cti
Definition: btSoftBody.h:269
btSoftBody::Joint::m_refs
btVector3 m_refs[2]
Definition: btSoftBody.h:502
btSoftBody::Joint::m_bodies
Body m_bodies[2]
Definition: btSoftBody.h:501
btConvexHullComputer::Edge::getNextEdgeOfFace
const Edge * getNextEdgeOfFace() const
Definition: btConvexHullComputer.h:56
btSoftBody::Note::m_nodes
Node * m_nodes[4]
Definition: btSoftBody.h:305
btDbvtNode::isleaf
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:182
btSoftBody::m_cdbvt
btDbvt m_cdbvt
Definition: btSoftBody.h:673
btSoftBody::Cluster::m_lv
btVector3 m_lv
Definition: btSoftBody.h:337
btSoftBodyHelpers::CalculateUV
static float CalculateUV(int resx, int resy, int ix, int iy, int id)
Definition: btSoftBodyHelpers.cpp:943
HullResult::mNumOutputVertices
unsigned int mNumOutputVertices
Definition: btConvexHull.h:38
btSoftBody::m_notes
tNoteArray m_notes
Definition: btSoftBody.h:658
fDrawFlags::Faces
Definition: btSoftBodyHelpers.h:29
btSoftBodyHelpers::ReoptimizeLinkOrder
static void ReoptimizeLinkOrder(btSoftBody *psb)
Sort the list of links to move link calculations that are dependent upon earlier ones as far as possi...
Definition: btSoftBodyHelpers.cpp:538
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition: btAlignedObjectArray.h:218
btSoftBody::m_ndbvt
btDbvt m_ndbvt
Definition: btSoftBody.h:671
btSoftBody::Node::m_n
btVector3 m_n
Definition: btSoftBody.h:228
btDbvtNode::volume
btDbvtVolume volume
Definition: btDbvt.h:180
btConvexHullComputer::Edge
Definition: btConvexHullComputer.h:31
btSoftBody::Anchor::m_local
btVector3 m_local
Definition: btSoftBody.h:292
btDbvtNode::isinternal
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:183
btSoftBody::m_clusters
tClusterArray m_clusters
Definition: btSoftBody.h:674
drawTree
static void drawTree(btIDebugDraw *idraw, const btDbvtNode *node, int depth, const btVector3 &ncolor, const btVector3 &lcolor, int mindepth, int maxdepth)
Definition: btSoftBodyHelpers.cpp:57
btSoftBodyHelpers::CreateFromTriMesh
static btSoftBody * CreateFromTriMesh(btSoftBodyWorldInfo &worldInfo, const btScalar *vertices, const int *triangles, int ntriangles, bool randomizeConstraints=true)
Definition: btSoftBodyHelpers.cpp:1019
btSoftBody::Pose::m_rot
btMatrix3x3 m_rot
Definition: btSoftBody.h:317
btSoftBody::Body::xform
const btTransform & xform() const
Definition: btSoftBody.h:413
btMax
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:29
fDrawFlags::Normals
Definition: btSoftBodyHelpers.h:31
fDrawFlags::ClusterTree
Definition: btSoftBodyHelpers.h:38
btSoftBody::Note::m_rank
int m_rank
Definition: btSoftBody.h:304
LinkDeps_t::next
LinkDeps_t * next
Definition: btSoftBodyHelpers.cpp:529
btSoftBodyWorldInfo
Definition: btSoftBody.h:43
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
btConvexHullComputer::compute
btScalar compute(const void *coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
Definition: btConvexHullComputer.cpp:2658
btSoftBodyHelpers.h
HullLibrary
The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull m...
Definition: btConvexHull.h:184
nextLine
static int nextLine(const char *buffer)
Definition: btSoftBodyHelpers.cpp:1097
fDrawFlags::Links
Definition: btSoftBodyHelpers.h:28
fDrawFlags::Clusters
Definition: btSoftBodyHelpers.h:35
btDot
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:901
btSoftBody::Cluster::m_com
btVector3 m_com
Definition: btSoftBody.h:332
btSoftBody::Joint::eType::Linear
Definition: btSoftBody.h:490
btDbvtNode
Definition: btDbvt.h:178
average
static T average(const btAlignedObjectArray< T > &items)
Definition: btSoftBodyHelpers.cpp:120
HullLibrary::ReleaseResult
HullError ReleaseResult(HullResult &result)
Definition: btConvexHull.cpp:816
btSoftBody
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:71
btSoftBody::Anchor::m_body
btRigidBody * m_body
Definition: btSoftBody.h:293
HullDesc::mMaxVertices
unsigned int mMaxVertices
Definition: btConvexHull.h:104
fDrawFlags::Notes
Definition: btSoftBodyHelpers.h:34
fDrawFlags::Tetras
Definition: btSoftBodyHelpers.h:30
btSoftBody::setMass
void setMass(int node, btScalar mass)
Definition: btSoftBody.cpp:674
btConvexHullComputer::Edge::getSourceVertex
int getSourceVertex() const
Definition: btConvexHullComputer.h:41
btSoftBody::Node::m_x
btVector3 m_x
Definition: btSoftBody.h:224
btSoftBody::m_rcontacts
tRContactArray m_rcontacts
Definition: btSoftBody.h:664
btConvexHullComputer::faces
btAlignedObjectArray< int > faces
Definition: btConvexHullComputer.h:75
btSoftBody::Node::m_area
btScalar m_area
Definition: btSoftBody.h:230
btSoftBodyInternals.h
lerp
btVector3 lerp(const btVector3 &v1, const btVector3 &v2, const btScalar &t)
Return the linear interpolation between two vectors.
Definition: btVector3.h:947
btSoftBodyHelpers::DrawFrame
static void DrawFrame(btSoftBody *psb, btIDebugDraw *idraw)
Definition: btSoftBodyHelpers.cpp:648
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
btSoftBody::Cluster::m_av
btVector3 m_av
Definition: btSoftBody.h:338
btCos
btScalar btCos(btScalar x)
Definition: btScalar.h:476
btSoftBody::Pose::m_pos
tVector3Array m_pos
Definition: btSoftBody.h:314
btSoftBody::LJoint
Definition: btSoftBody.h:518
REOP_NODE_COMPLETE
#define REOP_NODE_COMPLETE
Definition: btSoftBodyHelpers.cpp:535
HullDesc
Definition: btConvexHull.h:56
btSoftBody::m_faces
tFaceArray m_faces
Definition: btSoftBody.h:661