Bullet Collision Detection & Physics Library
btSoftBodyHelpers.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. 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"
23
24
25//
26static 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//
35static 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//
57static 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//
83template <typename T>
84static 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//
99template <typename T,typename Q>
100static 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//
109template <typename T,typename Q>
110static 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//
119template <typename T>
120static 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
142static 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//
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;
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);
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];
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];
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];
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*
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];
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];
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];
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];
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];
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 {
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;
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//
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//
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//
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//
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
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};
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
538void 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();
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//
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//
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//
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//
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
943float 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//
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 };
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//
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;
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//
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
1097static 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 */
1118 const char* ele,
1119 const char* face,
1120 const char* node,
1121 bool bfacelinks,
1122 bool btetralinks,
1123 bool bfacesfromtetras)
1124{
1126int nnode=0;
1127int ndims=0;
1128int nattrb=0;
1129int hasbounds=0;
1130int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
1131result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
1132node += nextLine(node);
1133
1134pos.resize(nnode);
1135for(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 }
1156btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
1157#if 0
1158if(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
1181if(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 }
1213printf("Nodes: %u\r\n",psb->m_nodes.size());
1214printf("Links: %u\r\n",psb->m_links.size());
1215printf("Faces: %u\r\n",psb->m_faces.size());
1216printf("Tetras: %u\r\n",psb->m_tetras.size());
1217return(psb);
1218}
1219
@ QF_TRIANGLES
Definition: btConvexHull.h:50
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:29
#define SIMD_PI
Definition: btScalar.h:504
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
btScalar btSqrt(btScalar y)
Definition: btScalar.h:444
btScalar btSin(btScalar x)
Definition: btScalar.h:477
btScalar btCos(btScalar x)
Definition: btScalar.h:476
static T average(const btAlignedObjectArray< T > &items)
#define REOP_NODE_COMPLETE
static void drawTree(btIDebugDraw *idraw, const btDbvtNode *node, int depth, const btVector3 &ncolor, const btVector3 &lcolor, int mindepth, int maxdepth)
static void mul(btAlignedObjectArray< T > &items, const Q &value)
static int nextLine(const char *buffer)
static void add(btAlignedObjectArray< T > &items, const Q &value)
#define IDX(_x_, _y_)
static T sum(const btAlignedObjectArray< T > &items)
static void drawBox(btIDebugDraw *idraw, const btVector3 &mins, const btVector3 &maxs, const btVector3 &color)
#define REOP_NOT_DEPENDENT
static void drawVertex(btIDebugDraw *idraw, const btVector3 &x, btScalar s, const btVector3 &c)
btSoftBodyHelpers.cpp by Nathanael Presson
LinkDeps_t * LinkDepsPtr_t
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:901
btVector3 btCross(const btVector3 &v1, const btVector3 &v2)
Return the cross product of two vectors.
Definition: btVector3.h:931
btVector3 lerp(const btVector3 &v1, const btVector3 &v2, const btScalar &t)
Return the linear interpolation between two vectors.
Definition: btVector3.h:947
unsigned int mMaxVertices
Definition: btConvexHull.h:104
The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull m...
Definition: btConvexHull.h:185
HullError ReleaseResult(HullResult &result)
HullError CreateConvexHull(const HullDesc &desc, HullResult &result)
btAlignedObjectArray< btVector3 > m_OutputVertices
Definition: btConvexHull.h:39
btAlignedObjectArray< unsigned int > m_Indices
Definition: btConvexHull.h:42
unsigned int mNumOutputVertices
Definition: btConvexHull.h:38
unsigned int mNumFaces
Definition: btConvexHull.h:40
LinkDeps_t * next
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
int size() const
return the number of elements in the array
void resize(int newsize, const T &fillData=T())
btTransform & getWorldTransform()
const Edge * getNextEdgeOfFace() const
Convex hull implementation based on Preparata and Hong See http://code.google.com/p/bullet/issues/det...
btScalar compute(const void *coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
btAlignedObjectArray< btVector3 > vertices
btAlignedObjectArray< int > faces
btAlignedObjectArray< Edge > edges
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
Definition: btIDebugDraw.h:30
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
virtual void draw3dText(const btVector3 &location, const char *textString)=0
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
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:72
btDbvt m_cdbvt
Definition: btSoftBody.h:673
void appendFace(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:299
void setMass(int node, btScalar mass)
Definition: btSoftBody.cpp:674
tJointArray m_joints
Definition: btSoftBody.h:666
Pose m_pose
Definition: btSoftBody.h:655
void appendTetra(int model, Material *mat)
Definition: btSoftBody.cpp:334
tTetraArray m_tetras
Definition: btSoftBody.h:662
tFaceArray m_faces
Definition: btSoftBody.h:661
tRContactArray m_rcontacts
Definition: btSoftBody.h:664
tClusterArray m_clusters
Definition: btSoftBody.h:674
tNoteArray m_notes
Definition: btSoftBody.h:658
btDbvt m_fdbvt
Definition: btSoftBody.h:672
tLinkArray m_links
Definition: btSoftBody.h:660
tAnchorArray m_anchors
Definition: btSoftBody.h:663
void randomizeConstraints()
tNodeArray m_nodes
Definition: btSoftBody.h:659
void appendLink(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:262
btDbvt m_ndbvt
Definition: btSoftBody.h:671
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:84
const btScalar & z() const
Return the z value.
Definition: btVector3.h:591
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
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:964
const btScalar & x() const
Return the x value.
Definition: btVector3.h:587
const btScalar & y() const
Return the y value.
Definition: btVector3.h:589
DBVT_INLINE btVector3 Extents() const
Definition: btDbvt.h:135
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:133
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:183
btDbvtNode * childs[2]
Definition: btDbvt.h:186
btDbvtVolume volume
Definition: btDbvt.h:180
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:182
btDbvtNode * m_root
Definition: btDbvt.h:262
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)
static btSoftBody * CreateFromTriMesh(btSoftBodyWorldInfo &worldInfo, const btScalar *vertices, const int *triangles, int ntriangles, bool randomizeConstraints=true)
static void DrawNodeTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
static btSoftBody * CreateFromTetGenData(btSoftBodyWorldInfo &worldInfo, const char *ele, const char *face, const char *node, bool bfacelinks, bool btetralinks, bool bfacesfromtetras)
static btSoftBody * CreateFromConvexHull(btSoftBodyWorldInfo &worldInfo, const btVector3 *vertices, int nvertices, bool randomizeConstraints=true)
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)
static void ReoptimizeLinkOrder(btSoftBody *psb)
Sort the list of links to move link calculations that are dependent upon earlier ones as far as possi...
static void DrawFaceTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
static void DrawInfos(btSoftBody *psb, btIDebugDraw *idraw, bool masses, bool areas, bool stress)
static btSoftBody * CreateEllipsoid(btSoftBodyWorldInfo &worldInfo, const btVector3 &center, const btVector3 &radius, int res)
static void DrawClusterTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
static float CalculateUV(int resx, int resy, int ix, int iy, int id)
static void Draw(btSoftBody *psb, btIDebugDraw *idraw, int drawflags=fDrawFlags::Std)
static void DrawFrame(btSoftBody *psb, btIDebugDraw *idraw)
static btSoftBody * CreateRope(btSoftBodyWorldInfo &worldInfo, const btVector3 &from, const btVector3 &to, int res, int fixeds)
btVector3 m_local
Definition: btSoftBody.h:292
btRigidBody * m_body
Definition: btSoftBody.h:293
const btTransform & xform() const
Definition: btSoftBody.h:413
btAlignedObjectArray< Node * > m_nodes
Definition: btSoftBody.h:325
Node * m_n[3]
Definition: btSoftBody.h:251
Material * m_material
Definition: btSoftBody.h:219
btVector3 m_refs[2]
Definition: btSoftBody.h:502
virtual eType::_ Type() const =0
btScalar m_area
Definition: btSoftBody.h:230
btVector3 m_x
Definition: btSoftBody.h:224
btVector3 m_n
Definition: btSoftBody.h:228
btScalar m_coords[4]
Definition: btSoftBody.h:306
btVector3 m_offset
Definition: btSoftBody.h:303
Node * m_nodes[4]
Definition: btSoftBody.h:305
const char * m_text
Definition: btSoftBody.h:302
btMatrix3x3 m_scl
Definition: btSoftBody.h:318
btVector3 m_com
Definition: btSoftBody.h:316
tVector3Array m_pos
Definition: btSoftBody.h:314
btMatrix3x3 m_rot
Definition: btSoftBody.h:317
btScalar m_offset
Definition: btSoftBody.h:190
btVector3 m_normal
Definition: btSoftBody.h:189