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>
20 #include <iostream>
21 #include <sstream>
22 #include <string.h>
23 #include <algorithm>
24 #include "btSoftBodyHelpers.h"
27 #include <map>
28 #include <vector>
29 
30 static void drawVertex(btIDebugDraw* idraw,
31  const btVector3& x, btScalar s, const btVector3& c)
32 {
33  idraw->drawLine(x - btVector3(s, 0, 0), x + btVector3(s, 0, 0), c);
34  idraw->drawLine(x - btVector3(0, s, 0), x + btVector3(0, s, 0), c);
35  idraw->drawLine(x - btVector3(0, 0, s), x + btVector3(0, 0, s), c);
36 }
37 
38 //
39 static void drawBox(btIDebugDraw* idraw,
40  const btVector3& mins,
41  const btVector3& maxs,
42  const btVector3& color)
43 {
44  const btVector3 c[] = {btVector3(mins.x(), mins.y(), mins.z()),
45  btVector3(maxs.x(), mins.y(), mins.z()),
46  btVector3(maxs.x(), maxs.y(), mins.z()),
47  btVector3(mins.x(), maxs.y(), mins.z()),
48  btVector3(mins.x(), mins.y(), maxs.z()),
49  btVector3(maxs.x(), mins.y(), maxs.z()),
50  btVector3(maxs.x(), maxs.y(), maxs.z()),
51  btVector3(mins.x(), maxs.y(), maxs.z())};
52  idraw->drawLine(c[0], c[1], color);
53  idraw->drawLine(c[1], c[2], color);
54  idraw->drawLine(c[2], c[3], color);
55  idraw->drawLine(c[3], c[0], color);
56  idraw->drawLine(c[4], c[5], color);
57  idraw->drawLine(c[5], c[6], color);
58  idraw->drawLine(c[6], c[7], color);
59  idraw->drawLine(c[7], c[4], color);
60  idraw->drawLine(c[0], c[4], color);
61  idraw->drawLine(c[1], c[5], color);
62  idraw->drawLine(c[2], c[6], color);
63  idraw->drawLine(c[3], c[7], color);
64 }
65 
66 //
67 static void drawTree(btIDebugDraw* idraw,
68  const btDbvtNode* node,
69  int depth,
70  const btVector3& ncolor,
71  const btVector3& lcolor,
72  int mindepth,
73  int maxdepth)
74 {
75  if (node)
76  {
77  if (node->isinternal() && ((depth < maxdepth) || (maxdepth < 0)))
78  {
79  drawTree(idraw, node->childs[0], depth + 1, ncolor, lcolor, mindepth, maxdepth);
80  drawTree(idraw, node->childs[1], depth + 1, ncolor, lcolor, mindepth, maxdepth);
81  }
82  if (depth >= mindepth)
83  {
84  const btScalar scl = (btScalar)(node->isinternal() ? 1 : 1);
85  const btVector3 mi = node->volume.Center() - node->volume.Extents() * scl;
86  const btVector3 mx = node->volume.Center() + node->volume.Extents() * scl;
87  drawBox(idraw, mi, mx, node->isleaf() ? lcolor : ncolor);
88  }
89  }
90 }
91 
92 //
93 template <typename T>
94 static inline T sum(const btAlignedObjectArray<T>& items)
95 {
96  T v;
97  if (items.size())
98  {
99  v = items[0];
100  for (int i = 1, ni = items.size(); i < ni; ++i)
101  {
102  v += items[i];
103  }
104  }
105  return (v);
106 }
107 
108 //
109 template <typename T, typename Q>
110 static inline void add(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, typename Q>
120 static inline void mul(btAlignedObjectArray<T>& items, const Q& value)
121 {
122  for (int i = 0, ni = items.size(); i < ni; ++i)
123  {
124  items[i] *= value;
125  }
126 }
127 
128 //
129 template <typename T>
130 static inline T average(const btAlignedObjectArray<T>& items)
131 {
132  const btScalar n = (btScalar)(items.size() > 0 ? items.size() : 1);
133  return (sum(items) / n);
134 }
135 
136 #if 0
137 //
138  inline static btScalar tetravolume(const btVector3& x0,
139  const btVector3& x1,
140  const btVector3& x2,
141  const btVector3& x3)
142 {
143  const btVector3 a=x1-x0;
144  const btVector3 b=x2-x0;
145  const btVector3 c=x3-x0;
146  return(btDot(a,btCross(b,c)));
147 }
148 #endif
149 
150 //
151 #if 0
152 static btVector3 stresscolor(btScalar stress)
153 {
154  static const btVector3 spectrum[]= { btVector3(1,0,1),
155  btVector3(0,0,1),
156  btVector3(0,1,1),
157  btVector3(0,1,0),
158  btVector3(1,1,0),
159  btVector3(1,0,0),
160  btVector3(1,0,0)};
161  static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
162  static const btScalar one=1;
163  stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
164  const int sel=(int)stress;
165  const btScalar frc=stress-sel;
166  return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
167 }
168 #endif
169 
170 //
172  btIDebugDraw* idraw,
173  int drawflags)
174 {
175  const btScalar scl = (btScalar)0.1;
176  const btScalar nscl = scl * 5;
177  const btVector3 lcolor = btVector3(0, 0, 0);
178  const btVector3 ncolor = btVector3(1, 1, 1);
179  const btVector3 ccolor = btVector3(1, 0, 0);
180  int i, j, nj;
181 
182  /* Clusters */
183  if (0 != (drawflags & fDrawFlags::Clusters))
184  {
185  srand(1806);
186  for (i = 0; i < psb->m_clusters.size(); ++i)
187  {
188  if (psb->m_clusters[i]->m_collide)
189  {
190  btVector3 color(rand() / (btScalar)RAND_MAX,
191  rand() / (btScalar)RAND_MAX,
192  rand() / (btScalar)RAND_MAX);
193  color = color.normalized() * 0.75;
195  vertices.resize(psb->m_clusters[i]->m_nodes.size());
196  for (j = 0, nj = vertices.size(); j < nj; ++j)
197  {
198  vertices[j] = psb->m_clusters[i]->m_nodes[j]->m_x;
199  }
200 #define USE_NEW_CONVEX_HULL_COMPUTER
201 #ifdef USE_NEW_CONVEX_HULL_COMPUTER
202  btConvexHullComputer computer;
203  int stride = sizeof(btVector3);
204  int count = vertices.size();
205  btScalar shrink = 0.f;
206  btScalar shrinkClamp = 0.f;
207  computer.compute(&vertices[0].getX(), stride, count, shrink, shrinkClamp);
208  for (int i = 0; i < computer.faces.size(); i++)
209  {
210  int face = computer.faces[i];
211  //printf("face=%d\n",face);
212  const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
213  const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
214 
215  int v0 = firstEdge->getSourceVertex();
216  int v1 = firstEdge->getTargetVertex();
217  while (edge != firstEdge)
218  {
219  int v2 = edge->getTargetVertex();
220  idraw->drawTriangle(computer.vertices[v0], computer.vertices[v1], computer.vertices[v2], color, 1);
221  edge = edge->getNextEdgeOfFace();
222  v0 = v1;
223  v1 = v2;
224  };
225  }
226 #else
227 
228  HullDesc hdsc(QF_TRIANGLES, vertices.size(), &vertices[0]);
229  HullResult hres;
230  HullLibrary hlib;
231  hdsc.mMaxVertices = vertices.size();
232  hlib.CreateConvexHull(hdsc, hres);
233  const btVector3 center = average(hres.m_OutputVertices);
234  add(hres.m_OutputVertices, -center);
235  mul(hres.m_OutputVertices, (btScalar)1);
236  add(hres.m_OutputVertices, center);
237  for (j = 0; j < (int)hres.mNumFaces; ++j)
238  {
239  const int idx[] = {hres.m_Indices[j * 3 + 0], hres.m_Indices[j * 3 + 1], hres.m_Indices[j * 3 + 2]};
240  idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
241  hres.m_OutputVertices[idx[1]],
242  hres.m_OutputVertices[idx[2]],
243  color, 1);
244  }
245  hlib.ReleaseResult(hres);
246 #endif
247  }
248  /* Velocities */
249 #if 0
250  for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
251  {
252  const btSoftBody::Cluster& c=psb->m_clusters[i];
253  const btVector3 r=c.m_nodes[j]->m_x-c.m_com;
254  const btVector3 v=c.m_lv+btCross(c.m_av,r);
255  idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
256  }
257 #endif
258  /* Frame */
259  // btSoftBody::Cluster& c=*psb->m_clusters[i];
260  // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
261  // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
262  // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
263  }
264  }
265  else
266  {
267  /* Nodes */
268  if (0 != (drawflags & fDrawFlags::Nodes))
269  {
270  for (i = 0; i < psb->m_nodes.size(); ++i)
271  {
272  const btSoftBody::Node& n = psb->m_nodes[i];
273  if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
274  idraw->drawLine(n.m_x - btVector3(scl, 0, 0), n.m_x + btVector3(scl, 0, 0), btVector3(1, 0, 0));
275  idraw->drawLine(n.m_x - btVector3(0, scl, 0), n.m_x + btVector3(0, scl, 0), btVector3(0, 1, 0));
276  idraw->drawLine(n.m_x - btVector3(0, 0, scl), n.m_x + btVector3(0, 0, scl), btVector3(0, 0, 1));
277  }
278  }
279  /* Links */
280  if (0 != (drawflags & fDrawFlags::Links))
281  {
282  for (i = 0; i < psb->m_links.size(); ++i)
283  {
284  const btSoftBody::Link& l = psb->m_links[i];
285  if (0 == (l.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
286  idraw->drawLine(l.m_n[0]->m_x, l.m_n[1]->m_x, lcolor);
287  }
288  }
289  /* Normals */
290  if (0 != (drawflags & fDrawFlags::Normals))
291  {
292  for (i = 0; i < psb->m_nodes.size(); ++i)
293  {
294  const btSoftBody::Node& n = psb->m_nodes[i];
295  if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
296  const btVector3 d = n.m_n * nscl;
297  idraw->drawLine(n.m_x, n.m_x + d, ncolor);
298  idraw->drawLine(n.m_x, n.m_x - d, ncolor * 0.5);
299  }
300  }
301  /* Contacts */
302  if (0 != (drawflags & fDrawFlags::Contacts))
303  {
304  static const btVector3 axis[] = {btVector3(1, 0, 0),
305  btVector3(0, 1, 0),
306  btVector3(0, 0, 1)};
307  for (i = 0; i < psb->m_rcontacts.size(); ++i)
308  {
309  const btSoftBody::RContact& c = psb->m_rcontacts[i];
310  const btVector3 o = c.m_node->m_x - c.m_cti.m_normal *
311  (btDot(c.m_node->m_x, c.m_cti.m_normal) + c.m_cti.m_offset);
312  const btVector3 x = btCross(c.m_cti.m_normal, axis[c.m_cti.m_normal.minAxis()]).normalized();
313  const btVector3 y = btCross(x, c.m_cti.m_normal).normalized();
314  idraw->drawLine(o - x * nscl, o + x * nscl, ccolor);
315  idraw->drawLine(o - y * nscl, o + y * nscl, ccolor);
316  idraw->drawLine(o, o + c.m_cti.m_normal * nscl * 3, btVector3(1, 1, 0));
317  }
318  }
319  /* Faces */
320  if (0 != (drawflags & fDrawFlags::Faces))
321  {
322  const btScalar scl = (btScalar)0.8;
323  const btScalar alp = (btScalar)1;
324  const btVector3 col(0, (btScalar)0.7, 0);
325  for (i = 0; i < psb->m_faces.size(); ++i)
326  {
327  const btSoftBody::Face& f = psb->m_faces[i];
328  if (0 == (f.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
329  const btVector3 x[] = {f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x};
330  const btVector3 c = (x[0] + x[1] + x[2]) / 3;
331  idraw->drawTriangle((x[0] - c) * scl + c,
332  (x[1] - c) * scl + c,
333  (x[2] - c) * scl + c,
334  col, alp);
335  }
336  }
337  /* Tetras */
338  if (0 != (drawflags & fDrawFlags::Tetras))
339  {
340  const btScalar scl = (btScalar)0.8;
341  const btScalar alp = (btScalar)1;
342  const btVector3 col((btScalar)0.3, (btScalar)0.3, (btScalar)0.7);
343  for (int i = 0; i < psb->m_tetras.size(); ++i)
344  {
345  const btSoftBody::Tetra& t = psb->m_tetras[i];
346  if (0 == (t.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
347  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};
348  const btVector3 c = (x[0] + x[1] + x[2] + x[3]) / 4;
349  idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[2] - c) * scl + c, col, alp);
350  idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
351  idraw->drawTriangle((x[1] - c) * scl + c, (x[2] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
352  idraw->drawTriangle((x[2] - c) * scl + c, (x[0] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
353  }
354  }
355  }
356  /* Anchors */
357  if (0 != (drawflags & fDrawFlags::Anchors))
358  {
359  for (i = 0; i < psb->m_anchors.size(); ++i)
360  {
361  const btSoftBody::Anchor& a = psb->m_anchors[i];
362  const btVector3 q = a.m_body->getWorldTransform() * a.m_local;
363  drawVertex(idraw, a.m_node->m_x, 0.25, btVector3(1, 0, 0));
364  drawVertex(idraw, q, 0.25, btVector3(0, 1, 0));
365  idraw->drawLine(a.m_node->m_x, q, btVector3(1, 1, 1));
366  }
367  for (i = 0; i < psb->m_nodes.size(); ++i)
368  {
369  const btSoftBody::Node& n = psb->m_nodes[i];
370  if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
371  if (n.m_im <= 0)
372  {
373  drawVertex(idraw, n.m_x, 0.25, btVector3(1, 0, 0));
374  }
375  }
376  }
377 
378  /* Notes */
379  if (0 != (drawflags & fDrawFlags::Notes))
380  {
381  for (i = 0; i < psb->m_notes.size(); ++i)
382  {
383  const btSoftBody::Note& n = psb->m_notes[i];
384  btVector3 p = n.m_offset;
385  for (int j = 0; j < n.m_rank; ++j)
386  {
387  p += n.m_nodes[j]->m_x * n.m_coords[j];
388  }
389  idraw->draw3dText(p, n.m_text);
390  }
391  }
392  /* Node tree */
393  if (0 != (drawflags & fDrawFlags::NodeTree)) DrawNodeTree(psb, idraw);
394  /* Face tree */
395  if (0 != (drawflags & fDrawFlags::FaceTree)) DrawFaceTree(psb, idraw);
396  /* Cluster tree */
397  if (0 != (drawflags & fDrawFlags::ClusterTree)) DrawClusterTree(psb, idraw);
398  /* Joints */
399  if (0 != (drawflags & fDrawFlags::Joints))
400  {
401  for (i = 0; i < psb->m_joints.size(); ++i)
402  {
403  const btSoftBody::Joint* pj = psb->m_joints[i];
404  switch (pj->Type())
405  {
407  {
408  const btSoftBody::LJoint* pjl = (const btSoftBody::LJoint*)pj;
409  const btVector3 a0 = pj->m_bodies[0].xform() * pjl->m_refs[0];
410  const btVector3 a1 = pj->m_bodies[1].xform() * pjl->m_refs[1];
411  idraw->drawLine(pj->m_bodies[0].xform().getOrigin(), a0, btVector3(1, 1, 0));
412  idraw->drawLine(pj->m_bodies[1].xform().getOrigin(), a1, btVector3(0, 1, 1));
413  drawVertex(idraw, a0, 0.25, btVector3(1, 1, 0));
414  drawVertex(idraw, a1, 0.25, btVector3(0, 1, 1));
415  }
416  break;
418  {
419  //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj;
420  const btVector3 o0 = pj->m_bodies[0].xform().getOrigin();
421  const btVector3 o1 = pj->m_bodies[1].xform().getOrigin();
422  const btVector3 a0 = pj->m_bodies[0].xform().getBasis() * pj->m_refs[0];
423  const btVector3 a1 = pj->m_bodies[1].xform().getBasis() * pj->m_refs[1];
424  idraw->drawLine(o0, o0 + a0 * 10, btVector3(1, 1, 0));
425  idraw->drawLine(o0, o0 + a1 * 10, btVector3(1, 1, 0));
426  idraw->drawLine(o1, o1 + a0 * 10, btVector3(0, 1, 1));
427  idraw->drawLine(o1, o1 + a1 * 10, btVector3(0, 1, 1));
428  break;
429  }
430  default:
431  {
432  }
433  }
434  }
435  }
436 }
437 
438 //
440  btIDebugDraw* idraw,
441  bool masses,
442  bool areas,
443  bool /*stress*/)
444 {
445  for (int i = 0; i < psb->m_nodes.size(); ++i)
446  {
447  const btSoftBody::Node& n = psb->m_nodes[i];
448  char text[2048] = {0};
449  char buff[1024];
450  if (masses)
451  {
452  sprintf(buff, " M(%.2f)", 1 / n.m_im);
453  strcat(text, buff);
454  }
455  if (areas)
456  {
457  sprintf(buff, " A(%.2f)", n.m_area);
458  strcat(text, buff);
459  }
460  if (text[0]) idraw->draw3dText(n.m_x, text);
461  }
462 }
463 
464 //
466  btIDebugDraw* idraw,
467  int mindepth,
468  int maxdepth)
469 {
470  drawTree(idraw, psb->m_ndbvt.m_root, 0, btVector3(1, 0, 1), btVector3(1, 1, 1), mindepth, maxdepth);
471 }
472 
473 //
475  btIDebugDraw* idraw,
476  int mindepth,
477  int maxdepth)
478 {
479  drawTree(idraw, psb->m_fdbvt.m_root, 0, btVector3(0, 1, 0), btVector3(1, 0, 0), mindepth, maxdepth);
480 }
481 
482 //
484  btIDebugDraw* idraw,
485  int mindepth,
486  int maxdepth)
487 {
488  drawTree(idraw, psb->m_cdbvt.m_root, 0, btVector3(0, 1, 1), btVector3(1, 0, 0), mindepth, maxdepth);
489 }
490 
491 //The btSoftBody object from the BulletSDK includes an array of Nodes and Links. These links appear
492 // to be first set up to connect a node to between 5 and 6 of its neighbors [480 links],
493 //and then to the rest of the nodes after the execution of the Floyd-Warshall graph algorithm
494 //[another 930 links].
495 //The way the links are stored by default, we have a number of cases where adjacent links share a node in common
496 // - this leads to the creation of a data dependency through memory.
497 //The PSolve_Links() function reads and writes nodes as it iterates over each link.
498 //So, we now have the possibility of a data dependency between iteration X
499 //that processes link L with iteration X+1 that processes link L+1
500 //because L and L+1 have one node in common, and iteration X updates the positions of that node,
501 //and iteration X+1 reads in the position of that shared node.
502 //
503 //Such a memory dependency limits the ability of a modern CPU to speculate beyond
504 //a certain point because it has to respect a possible dependency
505 //- this prevents the CPU from making full use of its out-of-order resources.
506 //If we re-order the links such that we minimize the cases where a link L and L+1 share a common node,
507 //we create a temporal gap between when the node position is written,
508 //and when it is subsequently read. This in turn allows the CPU to continue execution without
509 //risking a dependency violation. Such a reordering would result in significant speedups on
510 //modern CPUs with lots of execution resources.
511 //In our testing, we see it have a tremendous impact not only on the A7,
512 //but also on all x86 cores that ship with modern Macs.
513 //The attached source file includes a single function (ReoptimizeLinkOrder) which can be called on a
514 //btSoftBody object in the solveConstraints() function before the actual solver is invoked,
515 //or right after generateBendingConstraints() once we have all 1410 links.
516 
517 //===================================================================
518 //
519 //
520 // This function takes in a list of interdependent Links and tries
521 // to maximize the distance between calculation
522 // of dependent links. This increases the amount of parallelism that can
523 // be exploited by out-of-order instruction processors with large but
524 // (inevitably) finite instruction windows.
525 //
526 //===================================================================
527 
528 // A small structure to track lists of dependent link calculations
530 {
531 public:
532  int value; // A link calculation that is dependent on this one
533  // Positive values = "input A" while negative values = "input B"
534  LinkDeps_t* next; // Next dependence in the list
535 };
537 
538 // Dependency list constants
539 #define REOP_NOT_DEPENDENT -1
540 #define REOP_NODE_COMPLETE -2 // Must be less than REOP_NOT_DEPENDENT
541 
542 void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody* psb /* This can be replaced by a btSoftBody pointer */)
543 {
544  int i, nLinks = psb->m_links.size(), nNodes = psb->m_nodes.size();
545  btSoftBody::Link* lr;
546  int ar, br;
547  btSoftBody::Node* node0 = &(psb->m_nodes[0]);
548  btSoftBody::Node* node1 = &(psb->m_nodes[1]);
549  LinkDepsPtr_t linkDep;
550  int readyListHead, readyListTail, linkNum, linkDepFrees, depLink;
551 
552  // Allocate temporary buffers
553  int* nodeWrittenAt = new int[nNodes + 1]; // What link calculation produced this node's current values?
554  int* linkDepA = new int[nLinks]; // Link calculation input is dependent upon prior calculation #N
555  int* linkDepB = new int[nLinks];
556  int* readyList = new int[nLinks]; // List of ready-to-process link calculations (# of links, maximum)
557  LinkDeps_t* linkDepFreeList = new LinkDeps_t[2 * nLinks]; // Dependent-on-me list elements (2x# of links, maximum)
558  LinkDepsPtr_t* linkDepListStarts = new LinkDepsPtr_t[nLinks]; // Start nodes of dependent-on-me lists, one for each link
559 
560  // Copy the original, unsorted links to a side buffer
561  btSoftBody::Link* linkBuffer = new btSoftBody::Link[nLinks];
562  memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link) * nLinks);
563 
564  // Clear out the node setup and ready list
565  for (i = 0; i < nNodes + 1; i++)
566  {
567  nodeWrittenAt[i] = REOP_NOT_DEPENDENT;
568  }
569  for (i = 0; i < nLinks; i++)
570  {
571  linkDepListStarts[i] = NULL;
572  }
573  readyListHead = readyListTail = linkDepFrees = 0;
574 
575  // Initial link analysis to set up data structures
576  for (i = 0; i < nLinks; i++)
577  {
578  // Note which prior link calculations we are dependent upon & build up dependence lists
579  lr = &(psb->m_links[i]);
580  ar = (lr->m_n[0] - node0) / (node1 - node0);
581  br = (lr->m_n[1] - node0) / (node1 - node0);
582  if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT)
583  {
584  linkDepA[i] = nodeWrittenAt[ar];
585  linkDep = &linkDepFreeList[linkDepFrees++];
586  linkDep->value = i;
587  linkDep->next = linkDepListStarts[nodeWrittenAt[ar]];
588  linkDepListStarts[nodeWrittenAt[ar]] = linkDep;
589  }
590  else
591  {
592  linkDepA[i] = REOP_NOT_DEPENDENT;
593  }
594  if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT)
595  {
596  linkDepB[i] = nodeWrittenAt[br];
597  linkDep = &linkDepFreeList[linkDepFrees++];
598  linkDep->value = -(i + 1);
599  linkDep->next = linkDepListStarts[nodeWrittenAt[br]];
600  linkDepListStarts[nodeWrittenAt[br]] = linkDep;
601  }
602  else
603  {
604  linkDepB[i] = REOP_NOT_DEPENDENT;
605  }
606 
607  // Add this link to the initial ready list, if it is not dependent on any other links
608  if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT))
609  {
610  readyList[readyListTail++] = i;
611  linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE; // Probably not needed now
612  }
613 
614  // Update the nodes to mark which ones are calculated by this link
615  nodeWrittenAt[ar] = nodeWrittenAt[br] = i;
616  }
617 
618  // Process the ready list and create the sorted list of links
619  // -- By treating the ready list as a queue, we maximize the distance between any
620  // inter-dependent node calculations
621  // -- All other (non-related) nodes in the ready list will automatically be inserted
622  // in between each set of inter-dependent link calculations by this loop
623  i = 0;
624  while (readyListHead != readyListTail)
625  {
626  // Use ready list to select the next link to process
627  linkNum = readyList[readyListHead++];
628  // Copy the next-to-calculate link back into the original link array
629  psb->m_links[i++] = linkBuffer[linkNum];
630 
631  // Free up any link inputs that are dependent on this one
632  linkDep = linkDepListStarts[linkNum];
633  while (linkDep)
634  {
635  depLink = linkDep->value;
636  if (depLink >= 0)
637  {
638  linkDepA[depLink] = REOP_NOT_DEPENDENT;
639  }
640  else
641  {
642  depLink = -depLink - 1;
643  linkDepB[depLink] = REOP_NOT_DEPENDENT;
644  }
645  // Add this dependent link calculation to the ready list if *both* inputs are clear
646  if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT))
647  {
648  readyList[readyListTail++] = depLink;
649  linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE; // Probably not needed now
650  }
651  linkDep = linkDep->next;
652  }
653  }
654 
655  // Delete the temporary buffers
656  delete[] nodeWrittenAt;
657  delete[] linkDepA;
658  delete[] linkDepB;
659  delete[] readyList;
660  delete[] linkDepFreeList;
661  delete[] linkDepListStarts;
662  delete[] linkBuffer;
663 }
664 
665 //
667  btIDebugDraw* idraw)
668 {
669  if (psb->m_pose.m_bframe)
670  {
671  static const btScalar ascl = 10;
672  static const btScalar nscl = (btScalar)0.1;
673  const btVector3 com = psb->m_pose.m_com;
674  const btMatrix3x3 trs = psb->m_pose.m_rot * psb->m_pose.m_scl;
675  const btVector3 Xaxis = (trs * btVector3(1, 0, 0)).normalized();
676  const btVector3 Yaxis = (trs * btVector3(0, 1, 0)).normalized();
677  const btVector3 Zaxis = (trs * btVector3(0, 0, 1)).normalized();
678  idraw->drawLine(com, com + Xaxis * ascl, btVector3(1, 0, 0));
679  idraw->drawLine(com, com + Yaxis * ascl, btVector3(0, 1, 0));
680  idraw->drawLine(com, com + Zaxis * ascl, btVector3(0, 0, 1));
681  for (int i = 0; i < psb->m_pose.m_pos.size(); ++i)
682  {
683  const btVector3 x = com + trs * psb->m_pose.m_pos[i];
684  drawVertex(idraw, x, nscl, btVector3(1, 0, 1));
685  }
686  }
687 }
688 
689 //
691  const btVector3& to,
692  int res,
693  int fixeds)
694 {
695  /* Create nodes */
696  const int r = res + 2;
697  btVector3* x = new btVector3[r];
698  btScalar* m = new btScalar[r];
699  int i;
700 
701  for (i = 0; i < r; ++i)
702  {
703  const btScalar t = i / (btScalar)(r - 1);
704  x[i] = lerp(from, to, t);
705  m[i] = 1;
706  }
707  btSoftBody* psb = new btSoftBody(&worldInfo, r, x, m);
708  if (fixeds & 1) psb->setMass(0, 0);
709  if (fixeds & 2) psb->setMass(r - 1, 0);
710  delete[] x;
711  delete[] m;
712  /* Create links */
713  for (i = 1; i < r; ++i)
714  {
715  psb->appendLink(i - 1, i);
716  }
717  /* Finished */
718  return (psb);
719 }
720 
721 //
723  const btVector3& corner10,
724  const btVector3& corner01,
725  const btVector3& corner11,
726  int resx,
727  int resy,
728  int fixeds,
729  bool gendiags,
730  btScalar perturbation)
731 {
732 #define IDX(_x_, _y_) ((_y_)*rx + (_x_))
733  /* Create nodes */
734  if ((resx < 2) || (resy < 2)) return (0);
735  const int rx = resx;
736  const int ry = resy;
737  const int tot = rx * ry;
738  btVector3* x = new btVector3[tot];
739  btScalar* m = new btScalar[tot];
740  int iy;
741 
742  for (iy = 0; iy < ry; ++iy)
743  {
744  const btScalar ty = iy / (btScalar)(ry - 1);
745  const btVector3 py0 = lerp(corner00, corner01, ty);
746  const btVector3 py1 = lerp(corner10, corner11, ty);
747  for (int ix = 0; ix < rx; ++ix)
748  {
749  const btScalar tx = ix / (btScalar)(rx - 1);
750  btScalar pert = perturbation * btScalar(rand())/RAND_MAX;
751  btVector3 temp1 = py1;
752  temp1.setY(py1.getY() + pert);
753  btVector3 temp = py0;
754  pert = perturbation * btScalar(rand())/RAND_MAX;
755  temp.setY(py0.getY() + pert);
756  x[IDX(ix, iy)] = lerp(temp, temp1, tx);
757  m[IDX(ix, iy)] = 1;
758  }
759  }
760  btSoftBody* psb = new btSoftBody(&worldInfo, tot, x, m);
761  if (fixeds & 1) psb->setMass(IDX(0, 0), 0);
762  if (fixeds & 2) psb->setMass(IDX(rx - 1, 0), 0);
763  if (fixeds & 4) psb->setMass(IDX(0, ry - 1), 0);
764  if (fixeds & 8) psb->setMass(IDX(rx - 1, ry - 1), 0);
765  delete[] x;
766  delete[] m;
767  /* Create links and faces */
768  for (iy = 0; iy < ry; ++iy)
769  {
770  for (int ix = 0; ix < rx; ++ix)
771  {
772  const int idx = IDX(ix, iy);
773  const bool mdx = (ix + 1) < rx;
774  const bool mdy = (iy + 1) < ry;
775  if (mdx) psb->appendLink(idx, IDX(ix + 1, iy));
776  if (mdy) psb->appendLink(idx, IDX(ix, iy + 1));
777  if (mdx && mdy)
778  {
779  if ((ix + iy) & 1)
780  {
781  psb->appendFace(IDX(ix, iy), IDX(ix + 1, iy), IDX(ix + 1, iy + 1));
782  psb->appendFace(IDX(ix, iy), IDX(ix + 1, iy + 1), IDX(ix, iy + 1));
783  if (gendiags)
784  {
785  psb->appendLink(IDX(ix, iy), IDX(ix + 1, iy + 1));
786  }
787  }
788  else
789  {
790  psb->appendFace(IDX(ix, iy + 1), IDX(ix, iy), IDX(ix + 1, iy));
791  psb->appendFace(IDX(ix, iy + 1), IDX(ix + 1, iy), IDX(ix + 1, iy + 1));
792  if (gendiags)
793  {
794  psb->appendLink(IDX(ix + 1, iy), IDX(ix, iy + 1));
795  }
796  }
797  }
798  }
799  }
800  /* Finished */
801 #undef IDX
802  return (psb);
803 }
804 
805 //
807  const btVector3& corner00,
808  const btVector3& corner10,
809  const btVector3& corner01,
810  const btVector3& corner11,
811  int resx,
812  int resy,
813  int fixeds,
814  bool gendiags,
815  float* tex_coords)
816 {
817  /*
818  *
819  * corners:
820  *
821  * [0][0] corner00 ------- corner01 [resx][0]
822  * | |
823  * | |
824  * [0][resy] corner10 -------- corner11 [resx][resy]
825  *
826  *
827  *
828  *
829  *
830  *
831  * "fixedgs" map:
832  *
833  * corner00 --> +1
834  * corner01 --> +2
835  * corner10 --> +4
836  * corner11 --> +8
837  * upper middle --> +16
838  * left middle --> +32
839  * right middle --> +64
840  * lower middle --> +128
841  * center --> +256
842  *
843  *
844  * tex_coords size (resx-1)*(resy-1)*12
845  *
846  *
847  *
848  * SINGLE QUAD INTERNALS
849  *
850  * 1) btSoftBody's nodes and links,
851  * diagonal link is optional ("gendiags")
852  *
853  *
854  * node00 ------ node01
855  * | .
856  * | .
857  * | .
858  * | .
859  * | .
860  * node10 node11
861  *
862  *
863  *
864  * 2) Faces:
865  * two triangles,
866  * UV Coordinates (hier example for single quad)
867  *
868  * (0,1) (0,1) (1,1)
869  * 1 |\ 3 \-----| 2
870  * | \ \ |
871  * | \ \ |
872  * | \ \ |
873  * | \ \ |
874  * 2 |-----\ 3 \| 1
875  * (0,0) (1,0) (1,0)
876  *
877  *
878  *
879  *
880  *
881  *
882  */
883 
884 #define IDX(_x_, _y_) ((_y_)*rx + (_x_))
885  /* Create nodes */
886  if ((resx < 2) || (resy < 2)) return (0);
887  const int rx = resx;
888  const int ry = resy;
889  const int tot = rx * ry;
890  btVector3* x = new btVector3[tot];
891  btScalar* m = new btScalar[tot];
892 
893  int iy;
894 
895  for (iy = 0; iy < ry; ++iy)
896  {
897  const btScalar ty = iy / (btScalar)(ry - 1);
898  const btVector3 py0 = lerp(corner00, corner01, ty);
899  const btVector3 py1 = lerp(corner10, corner11, ty);
900  for (int ix = 0; ix < rx; ++ix)
901  {
902  const btScalar tx = ix / (btScalar)(rx - 1);
903  x[IDX(ix, iy)] = lerp(py0, py1, tx);
904  m[IDX(ix, iy)] = 1;
905  }
906  }
907  btSoftBody* psb = new btSoftBody(&worldInfo, tot, x, m);
908  if (fixeds & 1) psb->setMass(IDX(0, 0), 0);
909  if (fixeds & 2) psb->setMass(IDX(rx - 1, 0), 0);
910  if (fixeds & 4) psb->setMass(IDX(0, ry - 1), 0);
911  if (fixeds & 8) psb->setMass(IDX(rx - 1, ry - 1), 0);
912  if (fixeds & 16) psb->setMass(IDX((rx - 1) / 2, 0), 0);
913  if (fixeds & 32) psb->setMass(IDX(0, (ry - 1) / 2), 0);
914  if (fixeds & 64) psb->setMass(IDX(rx - 1, (ry - 1) / 2), 0);
915  if (fixeds & 128) psb->setMass(IDX((rx - 1) / 2, ry - 1), 0);
916  if (fixeds & 256) psb->setMass(IDX((rx - 1) / 2, (ry - 1) / 2), 0);
917  delete[] x;
918  delete[] m;
919 
920  int z = 0;
921  /* Create links and faces */
922  for (iy = 0; iy < ry; ++iy)
923  {
924  for (int ix = 0; ix < rx; ++ix)
925  {
926  const bool mdx = (ix + 1) < rx;
927  const bool mdy = (iy + 1) < ry;
928 
929  int node00 = IDX(ix, iy);
930  int node01 = IDX(ix + 1, iy);
931  int node10 = IDX(ix, iy + 1);
932  int node11 = IDX(ix + 1, iy + 1);
933 
934  if (mdx) psb->appendLink(node00, node01);
935  if (mdy) psb->appendLink(node00, node10);
936  if (mdx && mdy)
937  {
938  psb->appendFace(node00, node10, node11);
939  if (tex_coords)
940  {
941  tex_coords[z + 0] = CalculateUV(resx, resy, ix, iy, 0);
942  tex_coords[z + 1] = CalculateUV(resx, resy, ix, iy, 1);
943  tex_coords[z + 2] = CalculateUV(resx, resy, ix, iy, 0);
944  tex_coords[z + 3] = CalculateUV(resx, resy, ix, iy, 2);
945  tex_coords[z + 4] = CalculateUV(resx, resy, ix, iy, 3);
946  tex_coords[z + 5] = CalculateUV(resx, resy, ix, iy, 2);
947  }
948  psb->appendFace(node11, node01, node00);
949  if (tex_coords)
950  {
951  tex_coords[z + 6] = CalculateUV(resx, resy, ix, iy, 3);
952  tex_coords[z + 7] = CalculateUV(resx, resy, ix, iy, 2);
953  tex_coords[z + 8] = CalculateUV(resx, resy, ix, iy, 3);
954  tex_coords[z + 9] = CalculateUV(resx, resy, ix, iy, 1);
955  tex_coords[z + 10] = CalculateUV(resx, resy, ix, iy, 0);
956  tex_coords[z + 11] = CalculateUV(resx, resy, ix, iy, 1);
957  }
958  if (gendiags) psb->appendLink(node00, node11);
959  z += 12;
960  }
961  }
962  }
963  /* Finished */
964 #undef IDX
965  return (psb);
966 }
967 
968 float btSoftBodyHelpers::CalculateUV(int resx, int resy, int ix, int iy, int id)
969 {
970  /*
971  *
972  *
973  * node00 --- node01
974  * | |
975  * node10 --- node11
976  *
977  *
978  * ID map:
979  *
980  * node00 s --> 0
981  * node00 t --> 1
982  *
983  * node01 s --> 3
984  * node01 t --> 1
985  *
986  * node10 s --> 0
987  * node10 t --> 2
988  *
989  * node11 s --> 3
990  * node11 t --> 2
991  *
992  *
993  */
994 
995  float tc = 0.0f;
996  if (id == 0)
997  {
998  tc = (1.0f / ((resx - 1)) * ix);
999  }
1000  else if (id == 1)
1001  {
1002  tc = (1.0f / ((resy - 1)) * (resy - 1 - iy));
1003  }
1004  else if (id == 2)
1005  {
1006  tc = (1.0f / ((resy - 1)) * (resy - 1 - iy - 1));
1007  }
1008  else if (id == 3)
1009  {
1010  tc = (1.0f / ((resx - 1)) * (ix + 1));
1011  }
1012  return tc;
1013 }
1014 //
1016  const btVector3& radius,
1017  int res)
1018 {
1019  struct Hammersley
1020  {
1021  static void Generate(btVector3* x, int n)
1022  {
1023  for (int i = 0; i < n; i++)
1024  {
1025  btScalar p = 0.5, t = 0;
1026  for (int j = i; j; p *= 0.5, j >>= 1)
1027  if (j & 1) t += p;
1028  btScalar w = 2 * t - 1;
1029  btScalar a = (SIMD_PI + 2 * i * SIMD_PI) / n;
1030  btScalar s = btSqrt(1 - w * w);
1031  *x++ = btVector3(s * btCos(a), s * btSin(a), w);
1032  }
1033  }
1034  };
1036  vtx.resize(3 + res);
1037  Hammersley::Generate(&vtx[0], vtx.size());
1038  for (int i = 0; i < vtx.size(); ++i)
1039  {
1040  vtx[i] = vtx[i] * radius + center;
1041  }
1042  return (CreateFromConvexHull(worldInfo, &vtx[0], vtx.size()));
1043 }
1044 
1045 //
1047  const int* triangles,
1048  int ntriangles, bool randomizeConstraints)
1049 {
1050  int maxidx = 0;
1051  int i, j, ni;
1052 
1053  for (i = 0, ni = ntriangles * 3; i < ni; ++i)
1054  {
1055  maxidx = btMax(triangles[i], maxidx);
1056  }
1057  ++maxidx;
1060  chks.resize(maxidx * maxidx, false);
1061  vtx.resize(maxidx);
1062  for (i = 0, j = 0, ni = maxidx * 3; i < ni; ++j, i += 3)
1063  {
1064  vtx[j] = btVector3(vertices[i], vertices[i + 1], vertices[i + 2]);
1065  }
1066  btSoftBody* psb = new btSoftBody(&worldInfo, vtx.size(), &vtx[0], 0);
1067  for (i = 0, ni = ntriangles * 3; i < ni; i += 3)
1068  {
1069  const int idx[] = {triangles[i], triangles[i + 1], triangles[i + 2]};
1070 #define IDX(_x_, _y_) ((_y_)*maxidx + (_x_))
1071  for (int j = 2, k = 0; k < 3; j = k++)
1072  {
1073  if (!chks[IDX(idx[j], idx[k])])
1074  {
1075  chks[IDX(idx[j], idx[k])] = true;
1076  chks[IDX(idx[k], idx[j])] = true;
1077  psb->appendLink(idx[j], idx[k]);
1078  }
1079  }
1080 #undef IDX
1081  psb->appendFace(idx[0], idx[1], idx[2]);
1082  }
1083 
1084  if (randomizeConstraints)
1085  {
1086  psb->randomizeConstraints();
1087  }
1088 
1089  return (psb);
1090 }
1091 
1092 //
1094  int nvertices, bool randomizeConstraints)
1095 {
1096  HullDesc hdsc(QF_TRIANGLES, nvertices, vertices);
1097  HullResult hres;
1098  HullLibrary hlib; /*??*/
1099  hdsc.mMaxVertices = nvertices;
1100  hlib.CreateConvexHull(hdsc, hres);
1101  btSoftBody* psb = new btSoftBody(&worldInfo, (int)hres.mNumOutputVertices,
1102  &hres.m_OutputVertices[0], 0);
1103  for (int i = 0; i < (int)hres.mNumFaces; ++i)
1104  {
1105  const int idx[] = {static_cast<int>(hres.m_Indices[i * 3 + 0]),
1106  static_cast<int>(hres.m_Indices[i * 3 + 1]),
1107  static_cast<int>(hres.m_Indices[i * 3 + 2])};
1108  if (idx[0] < idx[1]) psb->appendLink(idx[0], idx[1]);
1109  if (idx[1] < idx[2]) psb->appendLink(idx[1], idx[2]);
1110  if (idx[2] < idx[0]) psb->appendLink(idx[2], idx[0]);
1111  psb->appendFace(idx[0], idx[1], idx[2]);
1112  }
1113  hlib.ReleaseResult(hres);
1114  if (randomizeConstraints)
1115  {
1116  psb->randomizeConstraints();
1117  }
1118  return (psb);
1119 }
1120 
1121 static int nextLine(const char* buffer)
1122 {
1123  int numBytesRead = 0;
1124 
1125  while (*buffer != '\n')
1126  {
1127  buffer++;
1128  numBytesRead++;
1129  }
1130 
1131  if (buffer[0] == 0x0a)
1132  {
1133  buffer++;
1134  numBytesRead++;
1135  }
1136  return numBytesRead;
1137 }
1138 
1139 /* Create from TetGen .ele, .face, .node data */
1141  const char* ele,
1142  const char* face,
1143  const char* node,
1144  bool bfacelinks,
1145  bool btetralinks,
1146  bool bfacesfromtetras)
1147 {
1149  int nnode = 0;
1150  int ndims = 0;
1151  int nattrb = 0;
1152  int hasbounds = 0;
1153  int result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
1154  result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
1155  node += nextLine(node);
1156 
1157  pos.resize(nnode);
1158  for (int i = 0; i < pos.size(); ++i)
1159  {
1160  int index = 0;
1161  //int bound=0;
1162  float x, y, z;
1163  sscanf(node, "%d %f %f %f", &index, &x, &y, &z);
1164 
1165  // sn>>index;
1166  // sn>>x;sn>>y;sn>>z;
1167  node += nextLine(node);
1168 
1169  //for(int j=0;j<nattrb;++j)
1170  // sn>>a;
1171 
1172  //if(hasbounds)
1173  // sn>>bound;
1174 
1175  pos[index].setX(btScalar(x));
1176  pos[index].setY(btScalar(y));
1177  pos[index].setZ(btScalar(z));
1178  }
1179  btSoftBody* psb = new btSoftBody(&worldInfo, nnode, &pos[0], 0);
1180 #if 0
1181 if(face&&face[0])
1182  {
1183  int nface=0;
1184  sf>>nface;sf>>hasbounds;
1185  for(int i=0;i<nface;++i)
1186  {
1187  int index=0;
1188  int bound=0;
1189  int ni[3];
1190  sf>>index;
1191  sf>>ni[0];sf>>ni[1];sf>>ni[2];
1192  sf>>bound;
1193  psb->appendFace(ni[0],ni[1],ni[2]);
1194  if(btetralinks)
1195  {
1196  psb->appendLink(ni[0],ni[1],0,true);
1197  psb->appendLink(ni[1],ni[2],0,true);
1198  psb->appendLink(ni[2],ni[0],0,true);
1199  }
1200  }
1201  }
1202 #endif
1203 
1204  if (ele && ele[0])
1205  {
1206  int ntetra = 0;
1207  int ncorner = 0;
1208  int neattrb = 0;
1209  sscanf(ele, "%d %d %d", &ntetra, &ncorner, &neattrb);
1210  ele += nextLine(ele);
1211 
1212  //se>>ntetra;se>>ncorner;se>>neattrb;
1213  for (int i = 0; i < ntetra; ++i)
1214  {
1215  int index = 0;
1216  int ni[4];
1217 
1218  //se>>index;
1219  //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
1220  sscanf(ele, "%d %d %d %d %d", &index, &ni[0], &ni[1], &ni[2], &ni[3]);
1221  ele += nextLine(ele);
1222  //for(int j=0;j<neattrb;++j)
1223  // se>>a;
1224  psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
1225  if (btetralinks)
1226  {
1227  psb->appendLink(ni[0], ni[1], 0, true);
1228  psb->appendLink(ni[1], ni[2], 0, true);
1229  psb->appendLink(ni[2], ni[0], 0, true);
1230  psb->appendLink(ni[0], ni[3], 0, true);
1231  psb->appendLink(ni[1], ni[3], 0, true);
1232  psb->appendLink(ni[2], ni[3], 0, true);
1233  }
1234  }
1235  }
1236  psb->initializeDmInverse();
1237  psb->m_tetraScratches.resize(psb->m_tetras.size());
1238  psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
1239  printf("Nodes: %u\r\n", psb->m_nodes.size());
1240  printf("Links: %u\r\n", psb->m_links.size());
1241  printf("Faces: %u\r\n", psb->m_faces.size());
1242  printf("Tetras: %u\r\n", psb->m_tetras.size());
1243  return (psb);
1244 }
1245 
1247 {
1248  std::ifstream fs;
1249  fs.open(vtk_file);
1250  btAssert(fs);
1251 
1252  typedef btAlignedObjectArray<int> Index;
1253  std::string line;
1255  btVector3 position;
1257  bool reading_points = false;
1258  bool reading_tets = false;
1259  size_t n_points = 0;
1260  size_t n_tets = 0;
1261  size_t x_count = 0;
1262  size_t indices_count = 0;
1263  while (std::getline(fs, line))
1264  {
1265  std::stringstream ss(line);
1266  if (line.size() == (size_t)(0))
1267  {
1268  }
1269  else if (line.substr(0, 6) == "POINTS")
1270  {
1271  reading_points = true;
1272  reading_tets = false;
1273  ss.ignore(128, ' '); // ignore "POINTS"
1274  ss >> n_points;
1275  X.resize(n_points);
1276  }
1277  else if (line.substr(0, 5) == "CELLS")
1278  {
1279  reading_points = false;
1280  reading_tets = true;
1281  ss.ignore(128, ' '); // ignore "CELLS"
1282  ss >> n_tets;
1283  indices.resize(n_tets);
1284  }
1285  else if (line.substr(0, 10) == "CELL_TYPES")
1286  {
1287  reading_points = false;
1288  reading_tets = false;
1289  }
1290  else if (reading_points)
1291  {
1292  btScalar p;
1293  ss >> p;
1294  position.setX(p);
1295  ss >> p;
1296  position.setY(p);
1297  ss >> p;
1298  position.setZ(p);
1299  X[x_count++] = position;
1300  }
1301  else if (reading_tets)
1302  {
1303  ss.ignore(128, ' '); // ignore "4"
1304  Index tet;
1305  tet.resize(4);
1306  for (size_t i = 0; i < 4; i++)
1307  {
1308  ss >> tet[i];
1309  }
1310  indices[indices_count++] = tet;
1311  }
1312  }
1313  btSoftBody* psb = new btSoftBody(&worldInfo, n_points, &X[0], 0);
1314 
1315  for (int i = 0; i < n_tets; ++i)
1316  {
1317  const Index& ni = indices[i];
1318  psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
1319  {
1320  psb->appendLink(ni[0], ni[1], 0, true);
1321  psb->appendLink(ni[1], ni[2], 0, true);
1322  psb->appendLink(ni[2], ni[0], 0, true);
1323  psb->appendLink(ni[0], ni[3], 0, true);
1324  psb->appendLink(ni[1], ni[3], 0, true);
1325  psb->appendLink(ni[2], ni[3], 0, true);
1326  }
1327  }
1328 
1329 
1330  generateBoundaryFaces(psb);
1331  psb->initializeDmInverse();
1332  psb->m_tetraScratches.resize(psb->m_tetras.size());
1333  psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
1334  printf("Nodes: %u\r\n", psb->m_nodes.size());
1335  printf("Links: %u\r\n", psb->m_links.size());
1336  printf("Faces: %u\r\n", psb->m_faces.size());
1337  printf("Tetras: %u\r\n", psb->m_tetras.size());
1338 
1339  fs.close();
1340  return psb;
1341 }
1342 
1344 {
1345  int counter = 0;
1346  for (int i = 0; i < psb->m_nodes.size(); ++i)
1347  {
1348  psb->m_nodes[i].index = counter++;
1349  }
1350  typedef btAlignedObjectArray<int> Index;
1352  indices.resize(psb->m_tetras.size());
1353  for (int i = 0; i < indices.size(); ++i)
1354  {
1355  Index index;
1356  index.push_back(psb->m_tetras[i].m_n[0]->index);
1357  index.push_back(psb->m_tetras[i].m_n[1]->index);
1358  index.push_back(psb->m_tetras[i].m_n[2]->index);
1359  index.push_back(psb->m_tetras[i].m_n[3]->index);
1360  indices[i] = index;
1361  }
1362 
1363  std::map<std::vector<int>, std::vector<int> > dict;
1364  for (int i = 0; i < indices.size(); ++i)
1365  {
1366  for (int j = 0; j < 4; ++j)
1367  {
1368  std::vector<int> f;
1369  if (j == 0)
1370  {
1371  f.push_back(indices[i][1]);
1372  f.push_back(indices[i][0]);
1373  f.push_back(indices[i][2]);
1374  }
1375  if (j == 1)
1376  {
1377  f.push_back(indices[i][3]);
1378  f.push_back(indices[i][0]);
1379  f.push_back(indices[i][1]);
1380  }
1381  if (j == 2)
1382  {
1383  f.push_back(indices[i][3]);
1384  f.push_back(indices[i][1]);
1385  f.push_back(indices[i][2]);
1386  }
1387  if (j == 3)
1388  {
1389  f.push_back(indices[i][2]);
1390  f.push_back(indices[i][0]);
1391  f.push_back(indices[i][3]);
1392  }
1393  std::vector<int> f_sorted = f;
1394  std::sort(f_sorted.begin(), f_sorted.end());
1395  if (dict.find(f_sorted) != dict.end())
1396  {
1397  dict.erase(f_sorted);
1398  }
1399  else
1400  {
1401  dict.insert(std::make_pair(f_sorted, f));
1402  }
1403  }
1404  }
1405 
1406  for (std::map<std::vector<int>, std::vector<int> >::iterator it = dict.begin(); it != dict.end(); ++it)
1407  {
1408  std::vector<int> f = it->second;
1409  psb->appendFace(f[0], f[1], f[2]);
1410  }
1411 }
1412 
1413 void btSoftBodyHelpers::writeObj(const char* filename, const btSoftBody* psb)
1414 {
1415  std::ofstream fs;
1416  fs.open(filename);
1417  btAssert(fs);
1418  for (int i = 0; i < psb->m_nodes.size(); ++i)
1419  {
1420  fs << "v";
1421  for (int d = 0; d < 3; d++)
1422  {
1423  fs << " " << psb->m_nodes[i].m_x[d];
1424  }
1425  fs << "\n";
1426  }
1427 
1428  for (int i = 0; i < psb->m_faces.size(); ++i)
1429  {
1430  fs << "f";
1431  for (int n = 0; n < 3; n++)
1432  {
1433  fs << " " << psb->m_faces[i].m_n[n]->index + 1;
1434  }
1435  fs << "\n";
1436  }
1437  fs.close();
1438 }
1439 
1440 void btSoftBodyHelpers::duplicateFaces(const char* filename, const btSoftBody* psb)
1441 {
1442  std::ifstream fs_read;
1443  fs_read.open(filename);
1444  std::string line;
1445  btVector3 pos;
1447  while (std::getline(fs_read, line))
1448  {
1449  std::stringstream ss(line);
1450  if (line[0] == 'v')
1451  {
1452  }
1453  else if (line[0] == 'f')
1454  {
1455  ss.ignore();
1456  int id0, id1, id2;
1457  ss >> id0;
1458  ss >> id1;
1459  ss >> id2;
1460  btAlignedObjectArray<int> new_face;
1461  new_face.push_back(id1);
1462  new_face.push_back(id0);
1463  new_face.push_back(id2);
1464  additional_faces.push_back(new_face);
1465  }
1466  }
1467  fs_read.close();
1468 
1469  std::ofstream fs_write;
1470  fs_write.open(filename, std::ios_base::app);
1471  for (int i = 0; i < additional_faces.size(); ++i)
1472  {
1473  fs_write << "f";
1474  for (int n = 0; n < 3; n++)
1475  {
1476  fs_write << " " << additional_faces[i][n];
1477  }
1478  fs_write << "\n";
1479  }
1480  fs_write.close();
1481 }
1482 
1483 // Given a simplex with vertices a,b,c,d, find the barycentric weights of p in this simplex
1484 void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary)
1485 {
1486  btVector3 vap = p - a;
1487  btVector3 vbp = p - b;
1488 
1489  btVector3 vab = b - a;
1490  btVector3 vac = c - a;
1491  btVector3 vad = d - a;
1492 
1493  btVector3 vbc = c - b;
1494  btVector3 vbd = d - b;
1495  btScalar va6 = (vbp.cross(vbd)).dot(vbc);
1496  btScalar vb6 = (vap.cross(vac)).dot(vad);
1497  btScalar vc6 = (vap.cross(vad)).dot(vab);
1498  btScalar vd6 = (vap.cross(vab)).dot(vac);
1499  btScalar v6 = btScalar(1) / (vab.cross(vac).dot(vad));
1500  bary = btVector4(va6*v6, vb6*v6, vc6*v6, vd6*v6);
1501 }
1502 
1503 // Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
1504 // If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
1506 {
1509  for (int i = 0; i < psb->m_renderNodes.size(); ++i)
1510  {
1511  const btVector3& p = psb->m_renderNodes[i].m_x;
1512  btVector4 bary;
1513  btVector4 optimal_bary;
1514  btScalar min_bary_weight = -1e3;
1516  bool found = false;
1517  for (int j = 0; j < psb->m_tetras.size(); ++j)
1518  {
1519  const btSoftBody::Tetra& t = psb->m_tetras[j];
1520  getBarycentricWeights(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x, p, bary);
1521  btScalar new_min_bary_weight = bary[0];
1522  for (int k = 1; k < 4; ++k)
1523  {
1524  new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
1525  }
1526  if (new_min_bary_weight > min_bary_weight)
1527  {
1529  parents.push_back(t.m_n[0]);
1530  parents.push_back(t.m_n[1]);
1531  parents.push_back(t.m_n[2]);
1532  parents.push_back(t.m_n[3]);
1533  optimal_parents = parents;
1534  optimal_bary = bary;
1535  min_bary_weight = new_min_bary_weight;
1536  // stop searching if p is inside the tetrahedron at hand
1537  if (bary[0]>=0. && bary[1]>=0. && bary[2]>=0. && bary[3]>=0.)
1538  {
1539  break;
1540  }
1541  }
1542  }
1543  psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
1544  psb->m_renderNodesParents[i] = optimal_parents;
1545  }
1546 }
HullResult::mNumFaces
unsigned int mNumFaces
Definition: btConvexHull.h:40
btConvexHullComputer::Edge::getNextEdgeOfFace
const Edge * getNextEdgeOfFace() const
Definition: btConvexHullComputer.h:55
btSoftBody::Cluster
Definition: btSoftBody.h:433
btSoftBody::Body::xform
const btTransform & xform() const
Definition: btSoftBody.h:521
btSoftBody::Joint::m_refs
btVector3 m_refs[2]
Definition: btSoftBody.h:614
btSoftBodyHelpers::DrawClusterTree
static void DrawClusterTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:483
REOP_NODE_COMPLETE
#define REOP_NODE_COMPLETE
Definition: btSoftBodyHelpers.cpp:540
HullLibrary::ReleaseResult
HullError ReleaseResult(HullResult &result)
Definition: btConvexHull.cpp:787
fDrawFlags::FaceTree
Definition: btSoftBodyHelpers.h:41
HullDesc::mMaxVertices
unsigned int mMaxVertices
Definition: btConvexHull.h:103
btSoftBody::appendLink
void appendLink(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:276
btSoftBody::Anchor::m_node
Node * m_node
Definition: btSoftBody.h:402
btSoftBody::m_links
tLinkArray m_links
Definition: btSoftBody.h:779
btSoftBodyHelpers::CreatePatch
static btSoftBody * CreatePatch(btSoftBodyWorldInfo &worldInfo, const btVector3 &corner00, const btVector3 &corner10, const btVector3 &corner01, const btVector3 &corner11, int resx, int resy, int fixeds, bool gendiags, btScalar perturbation=0.)
Definition: btSoftBodyHelpers.cpp:722
btIDebugDraw::drawTriangle
virtual void drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &, const btVector3 &, const btVector3 &, const btVector3 &color, btScalar alpha)
Definition: btIDebugDraw.h:114
dot
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
Definition: btQuaternion.h:888
btConvexHullComputer::vertices
btAlignedObjectArray< btVector3 > vertices
Definition: btConvexHullComputer.h:67
btSoftBody::m_tetras
tTetraArray m_tetras
Definition: btSoftBody.h:782
IDX
#define IDX(_x_, _y_)
btSoftBody::appendFace
void appendFace(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:316
btSoftBody::Cluster::m_com
btVector3 m_com
Definition: btSoftBody.h:443
btSoftBodyHelpers::CreateFromVtkFile
static btSoftBody * CreateFromVtkFile(btSoftBodyWorldInfo &worldInfo, const char *vtk_file)
Definition: btSoftBodyHelpers.cpp:1246
sort
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
Definition: btImplicitQRSVD.h:668
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
btSoftBody::Note::m_coords
btScalar m_coords[4]
Definition: btSoftBody.h:417
btSoftBody::Cluster::m_av
btVector3 m_av
Definition: btSoftBody.h:449
btSoftBody::Pose::m_com
btVector3 m_com
Definition: btSoftBody.h:427
btConvexHullComputer::Edge::getTargetVertex
int getTargetVertex() const
Definition: btConvexHullComputer.h:45
btSoftBody::Node::m_n
btVector3 m_n
Definition: btSoftBody.h:263
btVector3::setZ
void setZ(btScalar _z)
Set the z value.
Definition: btVector3.h:571
btSoftBody::Pose::m_bframe
bool m_bframe
Definition: btSoftBody.h:423
btConvexHullComputer::Edge::getSourceVertex
int getSourceVertex() const
Definition: btConvexHullComputer.h:40
btSoftBody::Joint::Type
virtual eType::_ Type() const =0
btSoftBodyHelpers::CreateFromTriMesh
static btSoftBody * CreateFromTriMesh(btSoftBodyWorldInfo &worldInfo, const btScalar *vertices, const int *triangles, int ntriangles, bool randomizeConstraints=true)
Definition: btSoftBodyHelpers.cpp:1046
btSoftBodyHelpers::DrawNodeTree
static void DrawNodeTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:465
btVector3::cross
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:380
btSoftBody::Note::m_offset
btVector3 m_offset
Definition: btSoftBody.h:414
btSoftBody::m_anchors
tAnchorArray m_anchors
Definition: btSoftBody.h:785
btSoftBodyHelpers::interpolateBarycentricWeights
static void interpolateBarycentricWeights(btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1505
HullResult::m_OutputVertices
btAlignedObjectArray< btVector3 > m_OutputVertices
Definition: btConvexHull.h:39
btSoftBody::m_pose
Pose m_pose
Definition: btSoftBody.h:773
btSoftBody::m_renderNodes
tNodeArray m_renderNodes
Definition: btSoftBody.h:778
REOP_NOT_DEPENDENT
#define REOP_NOT_DEPENDENT
Definition: btSoftBodyHelpers.cpp:539
btVector3::dot
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:229
SIMD_PI
#define SIMD_PI
Definition: btScalar.h:526
btConvexHullComputer.h
btCross
btVector3 btCross(const btVector3 &v1, const btVector3 &v2)
Return the cross product of two vectors.
Definition: btVector3.h:918
btSoftBody::m_faces
tFaceArray m_faces
Definition: btSoftBody.h:780
btIDebugDraw::draw3dText
virtual void draw3dText(const btVector3 &location, const char *textString)=0
btSoftBodyHelpers::CreateRope
static btSoftBody * CreateRope(btSoftBodyWorldInfo &worldInfo, const btVector3 &from, const btVector3 &to, int res, int fixeds)
Definition: btSoftBodyHelpers.cpp:690
btSoftBody::Anchor
Definition: btSoftBody.h:400
btSoftBody::Pose::m_rot
btMatrix3x3 m_rot
Definition: btSoftBody.h:428
btConvexHullComputer::faces
btAlignedObjectArray< int > faces
Definition: btConvexHullComputer.h:73
LinkDepsPtr_t
LinkDeps_t * LinkDepsPtr_t
Definition: btSoftBodyHelpers.cpp:536
btSoftBodyHelpers::DrawFrame
static void DrawFrame(btSoftBody *psb, btIDebugDraw *idraw)
Definition: btSoftBodyHelpers.cpp:666
QF_TRIANGLES
Definition: btConvexHull.h:50
fDrawFlags::Notes
Definition: btSoftBodyHelpers.h:38
HullLibrary
The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull m...
Definition: btConvexHull.h:182
add
static void add(btAlignedObjectArray< T > &items, const Q &value)
Definition: btSoftBodyHelpers.cpp:110
btSoftBody::fMaterial::DebugDraw
Definition: btSoftBody.h:183
btSoftBody::Note
Definition: btSoftBody.h:411
btSoftBody::m_notes
tNoteArray m_notes
Definition: btSoftBody.h:776
btSoftBody::m_cdbvt
btDbvt m_cdbvt
Definition: btSoftBody.h:799
btMin
const T & btMin(const T &a, const T &b)
Definition: btMinMax.h:21
btSoftBody::Node
Definition: btSoftBody.h:255
btSoftBodyWorldInfo
Definition: btSoftBody.h:45
btSoftBody::randomizeConstraints
void randomizeConstraints()
Definition: btSoftBody.cpp:1270
HullResult::mNumOutputVertices
unsigned int mNumOutputVertices
Definition: btConvexHull.h:38
btSoftBodyHelpers::CreatePatchUV
static btSoftBody * CreatePatchUV(btSoftBodyWorldInfo &worldInfo, const btVector3 &corner00, const btVector3 &corner10, const btVector3 &corner01, const btVector3 &corner11, int resx, int resy, int fixeds, bool gendiags, float *tex_coords=0)
Definition: btSoftBodyHelpers.cpp:806
btMax
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:27
btSoftBody::m_tetraScratches
btAlignedObjectArray< TetraScratch > m_tetraScratches
Definition: btSoftBody.h:783
btVector3::y
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
btSoftBody::m_renderNodesInterpolationWeights
btAlignedObjectArray< btVector4 > m_renderNodesInterpolationWeights
Definition: btSoftBody.h:807
btVector4
Definition: btVector3.h:1073
btSoftBody::Note::m_rank
int m_rank
Definition: btSoftBody.h:415
btSoftBody::Tetra
Definition: btSoftBody.h:295
fDrawFlags::Anchors
Definition: btSoftBodyHelpers.h:37
btSoftBody::m_renderNodesParents
btAlignedObjectArray< btAlignedObjectArray< const btSoftBody::Node * > > m_renderNodesParents
Definition: btSoftBody.h:808
btCollisionObject::getWorldTransform
btTransform & getWorldTransform()
Definition: btCollisionObject.h:367
btSoftBody::RContact::m_node
Node * m_node
Definition: btSoftBody.h:321
btSoftBody::Cluster::m_nodes
btAlignedObjectArray< Node * > m_nodes
Definition: btSoftBody.h:436
btAssert
#define btAssert(x)
Definition: btScalar.h:153
btSin
btScalar btSin(btScalar x)
Definition: btScalar.h:499
HullLibrary::CreateConvexHull
HullError CreateConvexHull(const HullDesc &desc, HullResult &result)
Definition: btConvexHull.cpp:670
fDrawFlags::Links
Definition: btSoftBodyHelpers.h:32
btSoftBody::Anchor::m_body
btRigidBody * m_body
Definition: btSoftBody.h:404
btSoftBodyHelpers::getBarycentricWeights
static void getBarycentricWeights(const btVector3 &a, const btVector3 &b, const btVector3 &c, const btVector3 &d, const btVector3 &p, btVector4 &bary)
Definition: btSoftBodyHelpers.cpp:1484
btSoftBody::Node::m_x
btVector3 m_x
Definition: btSoftBody.h:257
btSoftBody::Joint::eType::Linear
Definition: btSoftBody.h:601
btSoftBodyHelpers::CreateEllipsoid
static btSoftBody * CreateEllipsoid(btSoftBodyWorldInfo &worldInfo, const btVector3 &center, const btVector3 &radius, int res)
Definition: btSoftBodyHelpers.cpp:1015
btIDebugDraw
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
Definition: btIDebugDraw.h:26
btVector3::setX
void setX(btScalar _x)
Set the x value.
Definition: btVector3.h:567
drawBox
static void drawBox(btIDebugDraw *idraw, const btVector3 &mins, const btVector3 &maxs, const btVector3 &color)
Definition: btSoftBodyHelpers.cpp:39
btSoftBody::RContact
Definition: btSoftBody.h:318
LinkDeps_t::value
int value
Definition: btSoftBodyHelpers.cpp:532
btSoftBody::m_ndbvt
btDbvt m_ndbvt
Definition: btSoftBody.h:797
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition: btAlignedObjectArray.h:203
btSoftBody::Face
Definition: btSoftBody.h:285
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:108
btSoftBody::m_tetraScratchesTn
btAlignedObjectArray< TetraScratch > m_tetraScratchesTn
Definition: btSoftBody.h:784
btSoftBodyHelpers::CreateFromTetGenData
static btSoftBody * CreateFromTetGenData(btSoftBodyWorldInfo &worldInfo, const char *ele, const char *face, const char *node, bool bfacelinks, bool btetralinks, bool bfacesfromtetras)
Definition: btSoftBodyHelpers.cpp:1140
btConvexHullComputer::edges
btAlignedObjectArray< Edge > edges
Definition: btConvexHullComputer.h:70
mul
static void mul(btAlignedObjectArray< T > &items, const Q &value)
Definition: btSoftBodyHelpers.cpp:120
fDrawFlags::Normals
Definition: btSoftBodyHelpers.h:35
fDrawFlags::Contacts
Definition: btSoftBodyHelpers.h:36
btDbvtNode::childs
btDbvtNode * childs[2]
Definition: btDbvt.h:187
btConvexHullComputer
Convex hull implementation based on Preparata and Hong See http://code.google.com/p/bullet/issues/det...
Definition: btConvexHullComputer.h:24
btCos
btScalar btCos(btScalar x)
Definition: btScalar.h:498
btVector3::setY
void setY(btScalar _y)
Set the y value.
Definition: btVector3.h:569
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:46
btSoftBody::Cluster::m_lv
btVector3 m_lv
Definition: btSoftBody.h:448
fDrawFlags::Clusters
Definition: btSoftBodyHelpers.h:39
btSoftBody::Joint::m_bodies
Body m_bodies[2]
Definition: btSoftBody.h:613
fDrawFlags::Faces
Definition: btSoftBodyHelpers.h:33
fDrawFlags::Joints
Definition: btSoftBodyHelpers.h:43
HullDesc
Definition: btConvexHull.h:55
drawVertex
static void drawVertex(btIDebugDraw *idraw, const btVector3 &x, btScalar s, const btVector3 &c)
btSoftBodyHelpers.cpp by Nathanael Presson
Definition: btSoftBodyHelpers.cpp:30
btDbvtNode::volume
btDbvtVolume volume
Definition: btDbvt.h:182
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
btSoftBody::sCti::m_normal
btVector3 m_normal
Definition: btSoftBody.h:221
btSoftBody::sCti::m_offset
btScalar m_offset
Definition: btSoftBody.h:222
btTransform::getOrigin
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:113
btSoftBody::Anchor::m_local
btVector3 m_local
Definition: btSoftBody.h:403
btSoftBody::Node::m_area
btScalar m_area
Definition: btSoftBody.h:265
btDbvtAabbMm::Extents
DBVT_INLINE btVector3 Extents() const
Definition: btDbvt.h:136
btIDebugDraw::drawLine
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
btAlignedObjectArray
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
Definition: btAlignedObjectArray.h:45
btVector3::getY
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btSoftBodyHelpers::DrawInfos
static void DrawInfos(btSoftBody *psb, btIDebugDraw *idraw, bool masses, bool areas, bool stress)
Definition: btSoftBodyHelpers.cpp:439
btSoftBody::m_rcontacts
tRContactArray m_rcontacts
Definition: btSoftBody.h:787
btSoftBody::Joint::eType::Angular
Definition: btSoftBody.h:602
btDbvt::m_root
btDbvtNode * m_root
Definition: btDbvt.h:302
btSoftBodyHelpers::writeObj
static void writeObj(const char *file, const btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1413
btSoftBody::Feature::m_material
Material * m_material
Definition: btSoftBody.h:252
btSoftBodyHelpers::ReoptimizeLinkOrder
static void ReoptimizeLinkOrder(btSoftBody *psb)
Sort the list of links to move link calculations that are dependent upon earlier ones as far as possi...
Definition: btSoftBodyHelpers.cpp:542
btDbvtNode::isinternal
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:185
btDot
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:890
btSoftBody::RContact::m_cti
sCti m_cti
Definition: btSoftBody.h:320
btVector3::x
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
btSoftBody
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:72
btSoftBody::Tetra::m_n
Node * m_n[4]
Definition: btSoftBody.h:297
btSoftBodyHelpers.h
btSoftBody::appendTetra
void appendTetra(int model, Material *mat)
Definition: btSoftBody.cpp:356
btConvexHullComputer::Edge
Definition: btConvexHullComputer.h:30
HullResult
Definition: btConvexHull.h:27
lerp
btVector3 lerp(const btVector3 &v1, const btVector3 &v2, const btScalar &t)
Return the linear interpolation between two vectors.
Definition: btVector3.h:934
drawTree
static void drawTree(btIDebugDraw *idraw, const btDbvtNode *node, int depth, const btVector3 &ncolor, const btVector3 &lcolor, int mindepth, int maxdepth)
Definition: btSoftBodyHelpers.cpp:67
btDbvtNode::isleaf
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:184
fDrawFlags::NodeTree
Definition: btSoftBodyHelpers.h:40
btSoftBodyHelpers::Draw
static void Draw(btSoftBody *psb, btIDebugDraw *idraw, int drawflags=fDrawFlags::Std)
Definition: btSoftBodyHelpers.cpp:171
btSoftBodyInternals.h
btSoftBody::Pose::m_pos
tVector3Array m_pos
Definition: btSoftBody.h:425
fDrawFlags::ClusterTree
Definition: btSoftBodyHelpers.h:42
btSoftBodyHelpers::generateBoundaryFaces
static void generateBoundaryFaces(btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1343
btSoftBody::Face::m_n
Node * m_n[3]
Definition: btSoftBody.h:287
btSoftBody::m_clusters
tClusterArray m_clusters
Definition: btSoftBody.h:800
HullResult::m_Indices
btAlignedObjectArray< unsigned int > m_Indices
Definition: btConvexHull.h:42
btVector3::minAxis
int minAxis() const
Return the axis with the smallest value Note return values are 0,1,2 for x, y, or z.
Definition: btVector3.h:470
btSoftBodyHelpers::CalculateUV
static float CalculateUV(int resx, int resy, int ix, int iy, int id)
Definition: btSoftBodyHelpers.cpp:968
btSoftBody::setMass
void setMass(int node, btScalar mass)
Definition: btSoftBody.cpp:789
btConvexHullComputer::compute
btScalar compute(const void *coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
Definition: btConvexHullComputer.cpp:2653
btSoftBody::Pose::m_scl
btMatrix3x3 m_scl
Definition: btSoftBody.h:429
nextLine
static int nextLine(const char *buffer)
Definition: btSoftBodyHelpers.cpp:1121
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:257
btSoftBody::Material::m_flags
int m_flags
Definition: btSoftBody.h:246
btSoftBody::m_fdbvt
btDbvt m_fdbvt
Definition: btSoftBody.h:798
btSoftBody::Note::m_text
const char * m_text
Definition: btSoftBody.h:413
LinkDeps_t
Definition: btSoftBodyHelpers.cpp:529
btDbvtNode
Definition: btDbvt.h:180
btSoftBodyHelpers::DrawFaceTree
static void DrawFaceTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:474
btSqrt
btScalar btSqrt(btScalar y)
Definition: btScalar.h:466
btSoftBody::Node::m_im
btScalar m_im
Definition: btSoftBody.h:264
btSoftBody::Note::m_nodes
Node * m_nodes[4]
Definition: btSoftBody.h:416
average
static T average(const btAlignedObjectArray< T > &items)
Definition: btSoftBodyHelpers.cpp:130
btSoftBody::m_joints
tJointArray m_joints
Definition: btSoftBody.h:792
btDbvtAabbMm::Center
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:134
btSoftBodyHelpers::CreateFromConvexHull
static btSoftBody * CreateFromConvexHull(btSoftBodyWorldInfo &worldInfo, const btVector3 *vertices, int nvertices, bool randomizeConstraints=true)
Definition: btSoftBodyHelpers.cpp:1093
btVector3::normalized
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:949
LinkDeps_t::next
LinkDeps_t * next
Definition: btSoftBodyHelpers.cpp:534
fDrawFlags::Tetras
Definition: btSoftBodyHelpers.h:34
sum
static T sum(const btAlignedObjectArray< T > &items)
Definition: btSoftBodyHelpers.cpp:94
fDrawFlags::Nodes
Definition: btSoftBodyHelpers.h:31
btConvexHull.h
btSoftBody::initializeDmInverse
void initializeDmInverse()
Definition: btSoftBody.cpp:3080
btVector3::z
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:142
btSoftBody::m_nodes
tNodeArray m_nodes
Definition: btSoftBody.h:777
btSoftBodyHelpers::duplicateFaces
static void duplicateFaces(const char *filename, const btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1440
btSoftBody::LJoint
Definition: btSoftBody.h:630
btSoftBody::Joint
Definition: btSoftBody.h:595