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"
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 //
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;
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];
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];
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];
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*
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];
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];
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];
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  {
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;
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 //
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 //
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 //
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 //
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 };
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 //
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 //
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 //
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 //
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 //
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  };
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 //
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;
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 //
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 */
1116  const char* ele,
1117  const char* face,
1118  const char* node,
1119  bool bfacelinks,
1120  bool btetralinks,
1121  bool bfacesfromtetras)
1122 {
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 
static T sum(const btAlignedObjectArray< T > &items)
btMatrix3x3 m_scl
Definition: btSoftBody.h:315
const Edge * getNextEdgeOfFace() const
btVector3 m_normal
Definition: btSoftBody.h:189
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:181
btAlignedObjectArray< Edge > edges
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)
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
btScalar btSin(btScalar x)
Definition: btScalar.h:451
#define IDX(_x_, _y_)
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
tJointArray m_joints
Definition: btSoftBody.h:663
static btSoftBody * CreateEllipsoid(btSoftBodyWorldInfo &worldInfo, const btVector3 &center, const btVector3 &radius, int res)
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)
btScalar btSqrt(btScalar y)
Definition: btScalar.h:418
btAlignedObjectArray< unsigned int > m_Indices
Definition: btConvexHull.h:42
btAlignedObjectArray< Node * > m_nodes
Definition: btSoftBody.h:322
btDbvt m_fdbvt
Definition: btSoftBody.h:669
btDbvtNode * m_root
Definition: btDbvt.h:258
#define REOP_NOT_DEPENDENT
const btTransform & xform() const
Definition: btSoftBody.h:410
static btSoftBody * CreateFromTetGenData(btSoftBodyWorldInfo &worldInfo, const char *ele, const char *face, const char *node, bool bfacelinks, bool btetralinks, bool bfacesfromtetras)
static void DrawFaceTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
void appendLink(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:260
LinkDeps_t * LinkDepsPtr_t
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:182
Convex hull implementation based on Preparata and Hong See http://code.google.com/p/bullet/issues/det...
tNodeArray m_nodes
Definition: btSoftBody.h:656
tLinkArray m_links
Definition: btSoftBody.h:657
Node * m_n[3]
Definition: btSoftBody.h:248
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
static void Draw(btSoftBody *psb, btIDebugDraw *idraw, int drawflags=fDrawFlags::Std)
static void add(btAlignedObjectArray< T > &items, const Q &value)
void appendFace(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:297
tTetraArray m_tetras
Definition: btSoftBody.h:659
static btSoftBody * CreateFromConvexHull(btSoftBodyWorldInfo &worldInfo, const btVector3 *vertices, int nvertices, bool randomizeConstraints=true)
unsigned int mNumFaces
Definition: btConvexHull.h:40
const char * m_text
Definition: btSoftBody.h:299
static void drawBox(btIDebugDraw *idraw, const btVector3 &mins, const btVector3 &maxs, const btVector3 &color)
btVector3 btCross(const btVector3 &v1, const btVector3 &v2)
Return the cross product of two vectors.
Definition: btVector3.h:919
virtual void draw3dText(const btVector3 &location, const char *textString)=0
#define SIMD_PI
Definition: btScalar.h:476
btTransform & getWorldTransform()
Material * m_material
Definition: btSoftBody.h:219
btVector3 m_offset
Definition: btSoftBody.h:300
static void mul(btAlignedObjectArray< T > &items, const Q &value)
int size() const
return the number of elements in the array
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
HullError CreateConvexHull(const HullDesc &desc, HullResult &result)
void randomizeConstraints()
btDbvtNode * childs[2]
Definition: btDbvt.h:185
static btSoftBody * CreateRope(btSoftBodyWorldInfo &worldInfo, const btVector3 &from, const btVector3 &to, int res, int fixeds)
static void DrawInfos(btSoftBody *psb, btIDebugDraw *idraw, bool masses, bool areas, bool stress)
void appendTetra(int model, Material *mat)
Definition: btSoftBody.cpp:332
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
Definition: btIDebugDraw.h:28
tAnchorArray m_anchors
Definition: btSoftBody.h:660
btAlignedObjectArray< btVector3 > m_OutputVertices
Definition: btConvexHull.h:39
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:132
Pose m_pose
Definition: btSoftBody.h:652
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
DBVT_INLINE btVector3 Extents() const
Definition: btDbvt.h:134
static void DrawNodeTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
static void drawVertex(btIDebugDraw *idraw, const btVector3 &x, btScalar s, const btVector3 &c)
btSoftBodyHelpers.cpp by Nathanael Presson
static void DrawClusterTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
btScalar m_coords[4]
Definition: btSoftBody.h:303
btScalar m_offset
Definition: btSoftBody.h:190
btAlignedObjectArray< btVector3 > vertices
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:87
btVector3 m_com
Definition: btSoftBody.h:313
btVector3 m_refs[2]
Definition: btSoftBody.h:499
Node * m_nodes[4]
Definition: btSoftBody.h:302
btDbvt m_cdbvt
Definition: btSoftBody.h:670
static float CalculateUV(int resx, int resy, int ix, int iy, int id)
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:952
unsigned int mNumOutputVertices
Definition: btConvexHull.h:38
tNoteArray m_notes
Definition: btSoftBody.h:655
static void ReoptimizeLinkOrder(btSoftBody *psb)
Sort the list of links to move link calculations that are dependent upon earlier ones as far as possi...
void resize(int newsize, const T &fillData=T())
btDbvt m_ndbvt
Definition: btSoftBody.h:668
btVector3 m_n
Definition: btSoftBody.h:228
btDbvtVolume volume
Definition: btDbvt.h:179
btVector3 m_local
Definition: btSoftBody.h:289
tClusterArray m_clusters
Definition: btSoftBody.h:671
static void drawTree(btIDebugDraw *idraw, const btDbvtNode *node, int depth, const btVector3 &ncolor, const btVector3 &lcolor, int mindepth, int maxdepth)
static btSoftBody * CreateFromTriMesh(btSoftBodyWorldInfo &worldInfo, const btScalar *vertices, const int *triangles, int ntriangles, bool randomizeConstraints=true)
btMatrix3x3 m_rot
Definition: btSoftBody.h:314
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:468
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:29
virtual eType::_ Type() const =0
LinkDeps_t * next
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
btScalar compute(const void *coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull m...
Definition: btConvexHull.h:184
static int nextLine(const char *buffer)
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:889
static T average(const btAlignedObjectArray< T > &items)
HullError ReleaseResult(HullResult &result)
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:71
btRigidBody * m_body
Definition: btSoftBody.h:290
unsigned int mMaxVertices
Definition: btConvexHull.h:104
void setMass(int node, btScalar mass)
Definition: btSoftBody.cpp:672
btVector3 m_x
Definition: btSoftBody.h:224
tRContactArray m_rcontacts
Definition: btSoftBody.h:661
btAlignedObjectArray< int > faces
btScalar m_area
Definition: btSoftBody.h:230
btVector3 lerp(const btVector3 &v1, const btVector3 &v2, const btScalar &t)
Return the linear interpolation between two vectors.
Definition: btVector3.h:935
static void DrawFrame(btSoftBody *psb, btIDebugDraw *idraw)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:278
btScalar btCos(btScalar x)
Definition: btScalar.h:450
tVector3Array m_pos
Definition: btSoftBody.h:311
#define REOP_NODE_COMPLETE
tFaceArray m_faces
Definition: btSoftBody.h:658
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579
static btScalar tetravolume(const btVector3 &x0, const btVector3 &x1, const btVector3 &x2, const btVector3 &x3)