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 #if 0
127 //
128  inline static btScalar tetravolume(const btVector3& x0,
129  const btVector3& x1,
130  const btVector3& x2,
131  const btVector3& x3)
132 {
133  const btVector3 a=x1-x0;
134  const btVector3 b=x2-x0;
135  const btVector3 c=x3-x0;
136  return(btDot(a,btCross(b,c)));
137 }
138 #endif
139 
140 //
141 #if 0
142 static btVector3 stresscolor(btScalar stress)
143 {
144  static const btVector3 spectrum[]= { btVector3(1,0,1),
145  btVector3(0,0,1),
146  btVector3(0,1,1),
147  btVector3(0,1,0),
148  btVector3(1,1,0),
149  btVector3(1,0,0),
150  btVector3(1,0,0)};
151  static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
152  static const btScalar one=1;
153  stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
154  const int sel=(int)stress;
155  const btScalar frc=stress-sel;
156  return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
157 }
158 #endif
159 
160 //
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);
226  mul(hres.m_OutputVertices,(btScalar)1);
227  add(hres.m_OutputVertices,center);
228  for(j=0;j<(int)hres.mNumFaces;++j)
229  {
230  const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]};
231  idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
232  hres.m_OutputVertices[idx[1]],
233  hres.m_OutputVertices[idx[2]],
234  color,1);
235  }
236  hlib.ReleaseResult(hres);
237 #endif
238 
239  }
240  /* Velocities */
241 #if 0
242  for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
243  {
244  const btSoftBody::Cluster& c=psb->m_clusters[i];
245  const btVector3 r=c.m_nodes[j]->m_x-c.m_com;
246  const btVector3 v=c.m_lv+btCross(c.m_av,r);
247  idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
248  }
249 #endif
250  /* Frame */
251  // btSoftBody::Cluster& c=*psb->m_clusters[i];
252  // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
253  // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
254  // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
255  }
256  }
257  else
258  {
259  /* Nodes */
260  if(0!=(drawflags&fDrawFlags::Nodes))
261  {
262  for(i=0;i<psb->m_nodes.size();++i)
263  {
264  const btSoftBody::Node& n=psb->m_nodes[i];
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*
304  const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
305  const btVector3 y=btCross(x,c.m_cti.m_normal).normalized();
306  idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
307  idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
308  idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
309  }
310  }
311  /* Faces */
312  if(0!=(drawflags&fDrawFlags::Faces))
313  {
314  const btScalar scl=(btScalar)0.8;
315  const btScalar alp=(btScalar)1;
316  const btVector3 col(0,(btScalar)0.7,0);
317  for(i=0;i<psb->m_faces.size();++i)
318  {
319  const btSoftBody::Face& f=psb->m_faces[i];
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];
354  const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
355  drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
356  drawVertex(idraw,q,0.25,btVector3(0,1,0));
357  idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
358  }
359  for(i=0;i<psb->m_nodes.size();++i)
360  {
361  const btSoftBody::Node& n=psb->m_nodes[i];
363  if(n.m_im<=0)
364  {
365  drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
366  }
367  }
368  }
369 
370 
371  /* Notes */
372  if(0!=(drawflags&fDrawFlags::Notes))
373  {
374  for(i=0;i<psb->m_notes.size();++i)
375  {
376  const btSoftBody::Note& n=psb->m_notes[i];
377  btVector3 p=n.m_offset;
378  for(int j=0;j<n.m_rank;++j)
379  {
380  p+=n.m_nodes[j]->m_x*n.m_coords[j];
381  }
382  idraw->draw3dText(p,n.m_text);
383  }
384  }
385  /* Node tree */
386  if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw);
387  /* Face tree */
388  if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw);
389  /* Cluster tree */
390  if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw);
391  /* Joints */
392  if(0!=(drawflags&fDrawFlags::Joints))
393  {
394  for(i=0;i<psb->m_joints.size();++i)
395  {
396  const btSoftBody::Joint* pj=psb->m_joints[i];
397  switch(pj->Type())
398  {
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
525 class LinkDeps_t {
526  public:
527  int value; // A link calculation that is dependent on this one
528  // Positive values = "input A" while negative values = "input B"
529  LinkDeps_t *next; // Next dependence in the list
530 };
532 
533 // Dependency list constants
534 #define REOP_NOT_DEPENDENT -1
535 #define REOP_NODE_COMPLETE -2 // Must be less than REOP_NOT_DEPENDENT
536 
537 
538 void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody *psb /* This can be replaced by a btSoftBody pointer */)
539 {
540  int i, nLinks=psb->m_links.size(), nNodes=psb->m_nodes.size();
541  btSoftBody::Link *lr;
542  int ar, br;
543  btSoftBody::Node *node0 = &(psb->m_nodes[0]);
544  btSoftBody::Node *node1 = &(psb->m_nodes[1]);
545  LinkDepsPtr_t linkDep;
546  int readyListHead, readyListTail, linkNum, linkDepFrees, depLink;
547 
548  // Allocate temporary buffers
549  int *nodeWrittenAt = new int[nNodes+1]; // What link calculation produced this node's current values?
550  int *linkDepA = new int[nLinks]; // Link calculation input is dependent upon prior calculation #N
551  int *linkDepB = new int[nLinks];
552  int *readyList = new int[nLinks]; // List of ready-to-process link calculations (# of links, maximum)
553  LinkDeps_t *linkDepFreeList = new LinkDeps_t[2*nLinks]; // Dependent-on-me list elements (2x# of links, maximum)
554  LinkDepsPtr_t *linkDepListStarts = new LinkDepsPtr_t[nLinks]; // Start nodes of dependent-on-me lists, one for each link
555 
556  // Copy the original, unsorted links to a side buffer
557  btSoftBody::Link *linkBuffer = new btSoftBody::Link[nLinks];
558  memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link)*nLinks);
559 
560  // Clear out the node setup and ready list
561  for (i=0; i < nNodes+1; i++) {
562  nodeWrittenAt[i] = REOP_NOT_DEPENDENT;
563  }
564  for (i=0; i < nLinks; i++) {
565  linkDepListStarts[i] = NULL;
566  }
567  readyListHead = readyListTail = linkDepFrees = 0;
568 
569  // Initial link analysis to set up data structures
570  for (i=0; i < nLinks; i++) {
571 
572  // Note which prior link calculations we are dependent upon & build up dependence lists
573  lr = &(psb->m_links[i]);
574  ar = (lr->m_n[0] - node0)/(node1 - node0);
575  br = (lr->m_n[1] - node0)/(node1 - node0);
576  if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT) {
577  linkDepA[i] = nodeWrittenAt[ar];
578  linkDep = &linkDepFreeList[linkDepFrees++];
579  linkDep->value = i;
580  linkDep->next = linkDepListStarts[nodeWrittenAt[ar]];
581  linkDepListStarts[nodeWrittenAt[ar]] = linkDep;
582  } else {
583  linkDepA[i] = REOP_NOT_DEPENDENT;
584  }
585  if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT) {
586  linkDepB[i] = nodeWrittenAt[br];
587  linkDep = &linkDepFreeList[linkDepFrees++];
588  linkDep->value = -(i+1);
589  linkDep->next = linkDepListStarts[nodeWrittenAt[br]];
590  linkDepListStarts[nodeWrittenAt[br]] = linkDep;
591  } else {
592  linkDepB[i] = REOP_NOT_DEPENDENT;
593  }
594 
595  // Add this link to the initial ready list, if it is not dependent on any other links
596  if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT)) {
597  readyList[readyListTail++] = i;
598  linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE; // Probably not needed now
599  }
600 
601  // Update the nodes to mark which ones are calculated by this link
602  nodeWrittenAt[ar] = nodeWrittenAt[br] = i;
603  }
604 
605  // Process the ready list and create the sorted list of links
606  // -- By treating the ready list as a queue, we maximize the distance between any
607  // inter-dependent node calculations
608  // -- All other (non-related) nodes in the ready list will automatically be inserted
609  // in between each set of inter-dependent link calculations by this loop
610  i = 0;
611  while (readyListHead != readyListTail) {
612  // Use ready list to select the next link to process
613  linkNum = readyList[readyListHead++];
614  // Copy the next-to-calculate link back into the original link array
615  psb->m_links[i++] = linkBuffer[linkNum];
616 
617  // Free up any link inputs that are dependent on this one
618  linkDep = linkDepListStarts[linkNum];
619  while (linkDep) {
620  depLink = linkDep->value;
621  if (depLink >= 0) {
622  linkDepA[depLink] = REOP_NOT_DEPENDENT;
623  } else {
624  depLink = -depLink - 1;
625  linkDepB[depLink] = REOP_NOT_DEPENDENT;
626  }
627  // Add this dependent link calculation to the ready list if *both* inputs are clear
628  if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT)) {
629  readyList[readyListTail++] = depLink;
630  linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE; // Probably not needed now
631  }
632  linkDep = linkDep->next;
633  }
634  }
635 
636  // Delete the temporary buffers
637  delete [] nodeWrittenAt;
638  delete [] linkDepA;
639  delete [] linkDepB;
640  delete [] readyList;
641  delete [] linkDepFreeList;
642  delete [] linkDepListStarts;
643  delete [] linkBuffer;
644 }
645 
646 
647 //
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 
943 float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id)
944 {
945 
946  /*
947  *
948  *
949  * node00 --- node01
950  * | |
951  * node10 --- node11
952  *
953  *
954  * ID map:
955  *
956  * node00 s --> 0
957  * node00 t --> 1
958  *
959  * node01 s --> 3
960  * node01 t --> 1
961  *
962  * node10 s --> 0
963  * node10 t --> 2
964  *
965  * node11 s --> 3
966  * node11 t --> 2
967  *
968  *
969  */
970 
971  float tc=0.0f;
972  if (id == 0) {
973  tc = (1.0f/((resx-1))*ix);
974  }
975  else if (id==1) {
976  tc = (1.0f/((resy-1))*(resy-1-iy));
977  }
978  else if (id==2) {
979  tc = (1.0f/((resy-1))*(resy-1-iy-1));
980  }
981  else if (id==3) {
982  tc = (1.0f/((resx-1))*(ix+1));
983  }
984  return tc;
985 }
986 //
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 
1097 static int nextLine(const char* buffer)
1098 {
1099  int numBytesRead=0;
1100 
1101  while (*buffer != '\n')
1102  {
1103  buffer++;
1104  numBytesRead++;
1105  }
1106 
1107 
1108  if (buffer[0]==0x0a)
1109  {
1110  buffer++;
1111  numBytesRead++;
1112  }
1113  return numBytesRead;
1114 }
1115 
1116 /* Create from TetGen .ele, .face, .node data */
1118  const char* ele,
1119  const char* face,
1120  const char* node,
1121  bool bfacelinks,
1122  bool btetralinks,
1123  bool bfacesfromtetras)
1124 {
1126 int nnode=0;
1127 int ndims=0;
1128 int nattrb=0;
1129 int hasbounds=0;
1130 int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
1131 result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
1132 node += nextLine(node);
1133 
1134 pos.resize(nnode);
1135 for(int i=0;i<pos.size();++i)
1136  {
1137  int index=0;
1138  //int bound=0;
1139  float x,y,z;
1140  sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
1141 
1142 // sn>>index;
1143 // sn>>x;sn>>y;sn>>z;
1144  node += nextLine(node);
1145 
1146  //for(int j=0;j<nattrb;++j)
1147  // sn>>a;
1148 
1149  //if(hasbounds)
1150  // sn>>bound;
1151 
1152  pos[index].setX(btScalar(x));
1153  pos[index].setY(btScalar(y));
1154  pos[index].setZ(btScalar(z));
1155  }
1156 btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
1157 #if 0
1158 if(face&&face[0])
1159  {
1160  int nface=0;
1161  sf>>nface;sf>>hasbounds;
1162  for(int i=0;i<nface;++i)
1163  {
1164  int index=0;
1165  int bound=0;
1166  int ni[3];
1167  sf>>index;
1168  sf>>ni[0];sf>>ni[1];sf>>ni[2];
1169  sf>>bound;
1170  psb->appendFace(ni[0],ni[1],ni[2]);
1171  if(btetralinks)
1172  {
1173  psb->appendLink(ni[0],ni[1],0,true);
1174  psb->appendLink(ni[1],ni[2],0,true);
1175  psb->appendLink(ni[2],ni[0],0,true);
1176  }
1177  }
1178  }
1179 #endif
1180 
1181 if(ele&&ele[0])
1182  {
1183  int ntetra=0;
1184  int ncorner=0;
1185  int neattrb=0;
1186  sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
1187  ele += nextLine(ele);
1188 
1189  //se>>ntetra;se>>ncorner;se>>neattrb;
1190  for(int i=0;i<ntetra;++i)
1191  {
1192  int index=0;
1193  int ni[4];
1194 
1195  //se>>index;
1196  //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
1197  sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
1198  ele+=nextLine(ele);
1199  //for(int j=0;j<neattrb;++j)
1200  // se>>a;
1201  psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
1202  if(btetralinks)
1203  {
1204  psb->appendLink(ni[0],ni[1],0,true);
1205  psb->appendLink(ni[1],ni[2],0,true);
1206  psb->appendLink(ni[2],ni[0],0,true);
1207  psb->appendLink(ni[0],ni[3],0,true);
1208  psb->appendLink(ni[1],ni[3],0,true);
1209  psb->appendLink(ni[2],ni[3],0,true);
1210  }
1211  }
1212  }
1213 printf("Nodes: %u\r\n",psb->m_nodes.size());
1214 printf("Links: %u\r\n",psb->m_links.size());
1215 printf("Faces: %u\r\n",psb->m_faces.size());
1216 printf("Tetras: %u\r\n",psb->m_tetras.size());
1217 return(psb);
1218 }
1219 
static T sum(const btAlignedObjectArray< T > &items)
btMatrix3x3 m_scl
Definition: btSoftBody.h:318
const Edge * getNextEdgeOfFace() const
btVector3 m_normal
Definition: btSoftBody.h:189
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:182
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:477
#define IDX(_x_, _y_)
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
tJointArray m_joints
Definition: btSoftBody.h:666
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:444
btAlignedObjectArray< unsigned int > m_Indices
Definition: btConvexHull.h:42
btAlignedObjectArray< Node * > m_nodes
Definition: btSoftBody.h:325
btDbvt m_fdbvt
Definition: btSoftBody.h:672
btDbvtNode * m_root
Definition: btDbvt.h:262
#define REOP_NOT_DEPENDENT
const btTransform & xform() const
Definition: btSoftBody.h:413
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:262
LinkDeps_t * LinkDepsPtr_t
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:183
Convex hull implementation based on Preparata and Hong See http://code.google.com/p/bullet/issues/det...
tNodeArray m_nodes
Definition: btSoftBody.h:659
tLinkArray m_links
Definition: btSoftBody.h:660
Node * m_n[3]
Definition: btSoftBody.h:251
const btScalar & x() const
Return the x value.
Definition: btVector3.h:587
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:299
tTetraArray m_tetras
Definition: btSoftBody.h:662
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:302
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:933
virtual void draw3dText(const btVector3 &location, const char *textString)=0
#define SIMD_PI
Definition: btScalar.h:504
btTransform & getWorldTransform()
Material * m_material
Definition: btSoftBody.h:219
btVector3 m_offset
Definition: btSoftBody.h:303
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)
virtual eType::_ Type() const =0
void randomizeConstraints()
btDbvtNode * childs[2]
Definition: btDbvt.h:186
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:334
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:29
tAnchorArray m_anchors
Definition: btSoftBody.h:663
btAlignedObjectArray< btVector3 > m_OutputVertices
Definition: btConvexHull.h:39
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:133
Pose m_pose
Definition: btSoftBody.h:655
const btScalar & y() const
Return the y value.
Definition: btVector3.h:589
DBVT_INLINE btVector3 Extents() const
Definition: btDbvt.h:135
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:306
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:116
btVector3 m_com
Definition: btSoftBody.h:316
btVector3 m_refs[2]
Definition: btSoftBody.h:502
Node * m_nodes[4]
Definition: btSoftBody.h:305
btDbvt m_cdbvt
Definition: btSoftBody.h:673
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:966
unsigned int mNumOutputVertices
Definition: btConvexHull.h:38
tNoteArray m_notes
Definition: btSoftBody.h:658
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:671
btVector3 m_n
Definition: btSoftBody.h:228
btDbvtVolume volume
Definition: btDbvt.h:180
btVector3 m_local
Definition: btSoftBody.h:292
tClusterArray m_clusters
Definition: btSoftBody.h:674
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:317
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
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:29
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:903
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:293
unsigned int mMaxVertices
Definition: btConvexHull.h:104
void setMass(int node, btScalar mass)
Definition: btSoftBody.cpp:674
btVector3 m_x
Definition: btSoftBody.h:224
tRContactArray m_rcontacts
Definition: btSoftBody.h:664
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:949
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:292
btScalar btCos(btScalar x)
Definition: btScalar.h:476
tVector3Array m_pos
Definition: btSoftBody.h:314
#define REOP_NODE_COMPLETE
tFaceArray m_faces
Definition: btSoftBody.h:661
const btScalar & z() const
Return the z value.
Definition: btVector3.h:591