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