Bullet Collision Detection & Physics Library: btSoftBodyHelpers.cpp Source File

Bullet Collision Detection & Physics Library

btSoftBodyHelpers.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
16
17 #include "btSoftBodyInternals.h"
18 #include <stdio.h>
19 #include <string>
20 #include <iostream>
21 #include <sstream>
22 #include <string.h>
23 #include <algorithm>
24 #include "btSoftBodyHelpers.h"
25 #include "LinearMath/btConvexHull.h"
26 #include "LinearMath/btConvexHullComputer.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 //
171 void btSoftBodyHelpers::Draw(btSoftBody* psb,
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;
194 btAlignedObjectArray<btVector3> vertices;
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 {
406 case btSoftBody::Joint::eType::Linear:
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;
417 case btSoftBody::Joint::eType::Angular:
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 //
439 void btSoftBodyHelpers::DrawInfos(btSoftBody* psb,
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 //
465 void btSoftBodyHelpers::DrawNodeTree(btSoftBody* psb,
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 //
474 void btSoftBodyHelpers::DrawFaceTree(btSoftBody* psb,
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 //
483 void btSoftBodyHelpers::DrawClusterTree(btSoftBody* psb,
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
529 class LinkDeps_t
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 };
536 typedef LinkDeps_t* LinkDepsPtr_t;
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 //
666 void btSoftBodyHelpers::DrawFrame(btSoftBody* psb,
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 //
690 btSoftBody* btSoftBodyHelpers::CreateRope(btSoftBodyWorldInfo& worldInfo, const btVector3& from,
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 //
722 btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo, const btVector3& corner00,
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 //
806 btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
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 //
1015 btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, const btVector3& center,
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 };
1035 btAlignedObjectArray<btVector3> vtx;
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 //
1046 btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo, const btScalar* vertices,
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;
1058 btAlignedObjectArray<bool> chks;
1059 btAlignedObjectArray<btVector3> vtx;
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 //
1093 btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
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 */
1140 btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
1141 const char* ele,
1142 const char* face,
1143 const char* node,
1144 bool bfacelinks,
1145 bool btetralinks,
1146 bool bfacesfromtetras)
1147 {
1148 btAlignedObjectArray<btVector3> pos;
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
1246 btSoftBody* btSoftBodyHelpers::CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file)
1247 {
1248 std::ifstream fs;
1249 fs.open(vtk_file);
1250 btAssert(fs);
1251
1252 typedef btAlignedObjectArray<int> Index;
1253 std::string line;
1254 btAlignedObjectArray<btVector3> X;
1255 btVector3 position;
1256 btAlignedObjectArray<Index> indices;
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 //printf("v %f %f %f\n", position.getX(), position.getY(), position.getZ());
1300 X[x_count++] = position;
1301 }
1302 else if (reading_tets)
1303 {
1304 int d;
1305 ss >> d;
1306 if (d != 4)
1307 {
1308 printf("Load deformable failed: Only Tetrahedra are supported in VTK file.\n");
1309 fs.close();
1310 return 0;
1311 }
1312 ss.ignore(128, ' '); // ignore "4"
1313 Index tet;
1314 tet.resize(4);
1315 for (size_t i = 0; i < 4; i++)
1316 {
1317 ss >> tet[i];
1318 //printf("%d ", tet[i]);
1319 }
1320 //printf("\n");
1321 indices[indices_count++] = tet;
1322 }
1323 }
1324 btSoftBody* psb = new btSoftBody(&worldInfo, n_points, &X[0], 0);
1325
1326 for (int i = 0; i < n_tets; ++i)
1327 {
1328 const Index& ni = indices[i];
1329 psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
1330 {
1331 psb->appendLink(ni[0], ni[1], 0, true);
1332 psb->appendLink(ni[1], ni[2], 0, true);
1333 psb->appendLink(ni[2], ni[0], 0, true);
1334 psb->appendLink(ni[0], ni[3], 0, true);
1335 psb->appendLink(ni[1], ni[3], 0, true);
1336 psb->appendLink(ni[2], ni[3], 0, true);
1337 }
1338 }
1339
1340 generateBoundaryFaces(psb);
1341 psb->initializeDmInverse();
1342 psb->m_tetraScratches.resize(psb->m_tetras.size());
1343 psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
1344 printf("Nodes: %u\r\n", psb->m_nodes.size());
1345 printf("Links: %u\r\n", psb->m_links.size());
1346 printf("Faces: %u\r\n", psb->m_faces.size());
1347 printf("Tetras: %u\r\n", psb->m_tetras.size());
1348
1349 fs.close();
1350 return psb;
1351 }
1352
1353 void btSoftBodyHelpers::generateBoundaryFaces(btSoftBody* psb)
1354 {
1355 int counter = 0;
1356 for (int i = 0; i < psb->m_nodes.size(); ++i)
1357 {
1358 psb->m_nodes[i].index = counter++;
1359 }
1360 typedef btAlignedObjectArray<int> Index;
1361 btAlignedObjectArray<Index> indices;
1362 indices.resize(psb->m_tetras.size());
1363 for (int i = 0; i < indices.size(); ++i)
1364 {
1365 Index index;
1366 index.push_back(psb->m_tetras[i].m_n[0]->index);
1367 index.push_back(psb->m_tetras[i].m_n[1]->index);
1368 index.push_back(psb->m_tetras[i].m_n[2]->index);
1369 index.push_back(psb->m_tetras[i].m_n[3]->index);
1370 indices[i] = index;
1371 }
1372
1373 std::map<std::vector<int>, std::vector<int> > dict;
1374 for (int i = 0; i < indices.size(); ++i)
1375 {
1376 for (int j = 0; j < 4; ++j)
1377 {
1378 std::vector<int> f;
1379 if (j == 0)
1380 {
1381 f.push_back(indices[i][1]);
1382 f.push_back(indices[i][0]);
1383 f.push_back(indices[i][2]);
1384 }
1385 if (j == 1)
1386 {
1387 f.push_back(indices[i][3]);
1388 f.push_back(indices[i][0]);
1389 f.push_back(indices[i][1]);
1390 }
1391 if (j == 2)
1392 {
1393 f.push_back(indices[i][3]);
1394 f.push_back(indices[i][1]);
1395 f.push_back(indices[i][2]);
1396 }
1397 if (j == 3)
1398 {
1399 f.push_back(indices[i][2]);
1400 f.push_back(indices[i][0]);
1401 f.push_back(indices[i][3]);
1402 }
1403 std::vector<int> f_sorted = f;
1404 std::sort(f_sorted.begin(), f_sorted.end());
1405 if (dict.find(f_sorted) != dict.end())
1406 {
1407 dict.erase(f_sorted);
1408 }
1409 else
1410 {
1411 dict.insert(std::make_pair(f_sorted, f));
1412 }
1413 }
1414 }
1415
1416 for (std::map<std::vector<int>, std::vector<int> >::iterator it = dict.begin(); it != dict.end(); ++it)
1417 {
1418 std::vector<int> f = it->second;
1419 psb->appendFace(f[0], f[1], f[2]);
1420 //printf("f %d %d %d\n", f[0] + 1, f[1] + 1, f[2] + 1);
1421 }
1422 }
1423
1424 //Write the surface mesh to an obj file.
1425 void btSoftBodyHelpers::writeObj(const char* filename, const btSoftBody* psb)
1426 {
1427 std::ofstream fs;
1428 fs.open(filename);
1429 btAssert(fs);
1430
1431 if (psb->m_tetras.size() > 0)
1432 {
1433 // For tetrahedron mesh, we need to re-index the surface mesh for it to be in obj file/
1434 std::map<int, int> dict;
1435 for (int i = 0; i < psb->m_faces.size(); i++)
1436 {
1437 for (int d = 0; d < 3; d++)
1438 {
1439 int index = psb->m_faces[i].m_n[d]->index;
1440 if (dict.find(index) == dict.end())
1441 {
1442 int dict_size = dict.size();
1443 dict[index] = dict_size;
1444 fs << "v";
1445 for (int k = 0; k < 3; k++)
1446 {
1447 fs << " " << psb->m_nodes[index].m_x[k];
1448 }
1449 fs << "\n";
1450 }
1451 }
1452 }
1453 // Write surface mesh.
1454 for (int i = 0; i < psb->m_faces.size(); ++i)
1455 {
1456 fs << "f";
1457 for (int n = 0; n < 3; n++)
1458 {
1459 fs << " " << dict[psb->m_faces[i].m_n[n]->index] + 1;
1460 }
1461 fs << "\n";
1462 }
1463 }
1464 else
1465 {
1466 // For trimesh, directly write out all the nodes and faces.xs
1467 for (int i = 0; i < psb->m_nodes.size(); ++i)
1468 {
1469 fs << "v";
1470 for (int d = 0; d < 3; d++)
1471 {
1472 fs << " " << psb->m_nodes[i].m_x[d];
1473 }
1474 fs << "\n";
1475 }
1476
1477 for (int i = 0; i < psb->m_faces.size(); ++i)
1478 {
1479 fs << "f";
1480 for (int n = 0; n < 3; n++)
1481 {
1482 fs << " " << psb->m_faces[i].m_n[n]->index + 1;
1483 }
1484 fs << "\n";
1485 }
1486 }
1487 fs.close();
1488 }
1489
1490 void btSoftBodyHelpers::duplicateFaces(const char* filename, const btSoftBody* psb)
1491 {
1492 std::ifstream fs_read;
1493 fs_read.open(filename);
1494 std::string line;
1495 btVector3 pos;
1496 btAlignedObjectArray<btAlignedObjectArray<int> > additional_faces;
1497 while (std::getline(fs_read, line))
1498 {
1499 std::stringstream ss(line);
1500 if (line[0] == 'v')
1501 {
1502 }
1503 else if (line[0] == 'f')
1504 {
1505 ss.ignore();
1506 int id0, id1, id2;
1507 ss >> id0;
1508 ss >> id1;
1509 ss >> id2;
1510 btAlignedObjectArray<int> new_face;
1511 new_face.push_back(id1);
1512 new_face.push_back(id0);
1513 new_face.push_back(id2);
1514 additional_faces.push_back(new_face);
1515 }
1516 }
1517 fs_read.close();
1518
1519 std::ofstream fs_write;
1520 fs_write.open(filename, std::ios_base::app);
1521 for (int i = 0; i < additional_faces.size(); ++i)
1522 {
1523 fs_write << "f";
1524 for (int n = 0; n < 3; n++)
1525 {
1526 fs_write << " " << additional_faces[i][n];
1527 }
1528 fs_write << "\n";
1529 }
1530 fs_write.close();
1531 }
1532
1533 // Given a simplex with vertices a,b,c,d, find the barycentric weights of p in this simplex
1534 void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary)
1535 {
1536 btVector3 vap = p - a;
1537 btVector3 vbp = p - b;
1538
1539 btVector3 vab = b - a;
1540 btVector3 vac = c - a;
1541 btVector3 vad = d - a;
1542
1543 btVector3 vbc = c - b;
1544 btVector3 vbd = d - b;
1545 btScalar va6 = (vbp.cross(vbd)).dot(vbc);
1546 btScalar vb6 = (vap.cross(vac)).dot(vad);
1547 btScalar vc6 = (vap.cross(vad)).dot(vab);
1548 btScalar vd6 = (vap.cross(vab)).dot(vac);
1549 btScalar v6 = btScalar(1) / (vab.cross(vac).dot(vad));
1550 bary = btVector4(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6);
1551 }
1552
1553 // Given a simplex with vertices a,b,c, find the barycentric weights of p in this simplex. bary[3] = 0.
1554 void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary)
1555 {
1556 btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
1557 btScalar d00 = btDot(v0, v0);
1558 btScalar d01 = btDot(v0, v1);
1559 btScalar d11 = btDot(v1, v1);
1560 btScalar d20 = btDot(v2, v0);
1561 btScalar d21 = btDot(v2, v1);
1562 btScalar invDenom = 1.0 / (d00 * d11 - d01 * d01);
1563 bary[1] = (d11 * d20 - d01 * d21) * invDenom;
1564 bary[2] = (d00 * d21 - d01 * d20) * invDenom;
1565 bary[0] = 1.0 - bary[1] - bary[2];
1566 bary[3] = 0;
1567 }
1568
1569 // Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
1570 // If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
1571 void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
1572 {
1573 psb->m_z.resize(0);
1574 psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
1575 psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
1576 for (int i = 0; i < psb->m_renderNodes.size(); ++i)
1577 {
1578 const btVector3& p = psb->m_renderNodes[i].m_x;
1579 btVector4 bary;
1580 btVector4 optimal_bary;
1581 btScalar min_bary_weight = -1e3;
1582 btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
1583 for (int j = 0; j < psb->m_tetras.size(); ++j)
1584 {
1585 const btSoftBody::Tetra& t = psb->m_tetras[j];
1586 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);
1587 btScalar new_min_bary_weight = bary[0];
1588 for (int k = 1; k < 4; ++k)
1589 {
1590 new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
1591 }
1592 if (new_min_bary_weight > min_bary_weight)
1593 {
1594 btAlignedObjectArray<const btSoftBody::Node*> parents;
1595 parents.push_back(t.m_n[0]);
1596 parents.push_back(t.m_n[1]);
1597 parents.push_back(t.m_n[2]);
1598 parents.push_back(t.m_n[3]);
1599 optimal_parents = parents;
1600 optimal_bary = bary;
1601 min_bary_weight = new_min_bary_weight;
1602 // stop searching if p is inside the tetrahedron at hand
1603 if (bary[0] >= 0. && bary[1] >= 0. && bary[2] >= 0. && bary[3] >= 0.)
1604 {
1605 break;
1606 }
1607 }
1608 }
1609 psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
1610 psb->m_renderNodesParents[i] = optimal_parents;
1611 }
1612 }
1613
1614 // Iterate through all render nodes to find the simulation triangle that's closest to the node in the barycentric sense.
1615 void btSoftBodyHelpers::extrapolateBarycentricWeights(btSoftBody* psb)
1616 {
1617 psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
1618 psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
1619 psb->m_z.resize(psb->m_renderNodes.size());
1620 for (int i = 0; i < psb->m_renderNodes.size(); ++i)
1621 {
1622 const btVector3& p = psb->m_renderNodes[i].m_x;
1623 btVector4 bary;
1624 btVector4 optimal_bary;
1625 btScalar min_bary_weight = -SIMD_INFINITY;
1626 btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
1627 btScalar dist = 0, optimal_dist = 0;
1628 for (int j = 0; j < psb->m_faces.size(); ++j)
1629 {
1630 const btSoftBody::Face& f = psb->m_faces[j];
1631 btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
1632 btVector3 unit_n = n.normalized();
1633 dist = (p - f.m_n[0]->m_x).dot(unit_n);
1634 btVector3 proj_p = p - dist * unit_n;
1635 getBarycentricWeights(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, proj_p, bary);
1636 btScalar new_min_bary_weight = bary[0];
1637 for (int k = 1; k < 3; ++k)
1638 {
1639 new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
1640 }
1641
1642 // p is out of the current best triangle, we found a traingle that's better
1643 bool better_than_closest_outisde = (new_min_bary_weight > min_bary_weight && min_bary_weight < 0.);
1644 // p is inside of the current best triangle, we found a triangle that's better
1645 bool better_than_best_inside = (new_min_bary_weight >= 0 && min_bary_weight >= 0 && btFabs(dist) < btFabs(optimal_dist));
1646
1647 if (better_than_closest_outisde || better_than_best_inside)
1648 {
1649 btAlignedObjectArray<const btSoftBody::Node*> parents;
1650 parents.push_back(f.m_n[0]);
1651 parents.push_back(f.m_n[1]);
1652 parents.push_back(f.m_n[2]);
1653 optimal_parents = parents;
1654 optimal_bary = bary;
1655 optimal_dist = dist;
1656 min_bary_weight = new_min_bary_weight;
1657 }
1658 }
1659 psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
1660 psb->m_renderNodesParents[i] = optimal_parents;
1661 psb->m_z[i] = optimal_dist;
1662 }
1663 }
btConvexHullComputer.h
btConvexHull.h
QF_TRIANGLES
@ QF_TRIANGLES
Definition: btConvexHull.h:50
sort
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
Definition: btImplicitQRSVD.h:668
btMax
const T & btMax(const T &a, const T &b)
Definition: btMinMax.h:27
btMin
const T & btMin(const T &a, const T &b)
Definition: btMinMax.h:21
dot
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
Definition: btQuaternion.h:888
SIMD_PI
#define SIMD_PI
Definition: btScalar.h:526
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
btSqrt
btScalar btSqrt(btScalar y)
Definition: btScalar.h:466
btSin
btScalar btSin(btScalar x)
Definition: btScalar.h:499
btFabs
btScalar btFabs(btScalar x)
Definition: btScalar.h:497
SIMD_INFINITY
#define SIMD_INFINITY
Definition: btScalar.h:544
btCos
btScalar btCos(btScalar x)
Definition: btScalar.h:498
btAssert
#define btAssert(x)
Definition: btScalar.h:153
average
static T average(const btAlignedObjectArray< T > &items)
Definition: btSoftBodyHelpers.cpp:130
REOP_NODE_COMPLETE
#define REOP_NODE_COMPLETE
Definition: btSoftBodyHelpers.cpp:540
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
mul
static void mul(btAlignedObjectArray< T > &items, const Q &value)
Definition: btSoftBodyHelpers.cpp:120
nextLine
static int nextLine(const char *buffer)
Definition: btSoftBodyHelpers.cpp:1121
add
static void add(btAlignedObjectArray< T > &items, const Q &value)
Definition: btSoftBodyHelpers.cpp:110
IDX
#define IDX(_x_, _y_)
sum
static T sum(const btAlignedObjectArray< T > &items)
Definition: btSoftBodyHelpers.cpp:94
drawBox
static void drawBox(btIDebugDraw *idraw, const btVector3 &mins, const btVector3 &maxs, const btVector3 &color)
Definition: btSoftBodyHelpers.cpp:39
REOP_NOT_DEPENDENT
#define REOP_NOT_DEPENDENT
Definition: btSoftBodyHelpers.cpp:539
drawVertex
static void drawVertex(btIDebugDraw *idraw, const btVector3 &x, btScalar s, const btVector3 &c)
btSoftBodyHelpers.cpp by Nathanael Presson
Definition: btSoftBodyHelpers.cpp:30
LinkDepsPtr_t
LinkDeps_t * LinkDepsPtr_t
Definition: btSoftBodyHelpers.cpp:536
btSoftBodyHelpers.h
btSoftBodyInternals.h
btDot
btScalar btDot(const btVector3 &v1, const btVector3 &v2)
Return the dot product between two vectors.
Definition: btVector3.h:890
btCross
btVector3 btCross(const btVector3 &v1, const btVector3 &v2)
Return the cross product of two vectors.
Definition: btVector3.h:918
lerp
btVector3 lerp(const btVector3 &v1, const btVector3 &v2, const btScalar &t)
Return the linear interpolation between two vectors.
Definition: btVector3.h:934
HullDesc
Definition: btConvexHull.h:56
HullDesc::mMaxVertices
unsigned int mMaxVertices
Definition: btConvexHull.h:103
HullLibrary
The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull m...
Definition: btConvexHull.h:183
HullLibrary::ReleaseResult
HullError ReleaseResult(HullResult &result)
Definition: btConvexHull.cpp:787
HullLibrary::CreateConvexHull
HullError CreateConvexHull(const HullDesc &desc, HullResult &result)
Definition: btConvexHull.cpp:670
HullResult
Definition: btConvexHull.h:28
HullResult::m_OutputVertices
btAlignedObjectArray< btVector3 > m_OutputVertices
Definition: btConvexHull.h:39
HullResult::m_Indices
btAlignedObjectArray< unsigned int > m_Indices
Definition: btConvexHull.h:42
HullResult::mNumOutputVertices
unsigned int mNumOutputVertices
Definition: btConvexHull.h:38
HullResult::mNumFaces
unsigned int mNumFaces
Definition: btConvexHull.h:40
LinkDeps_t
Definition: btSoftBodyHelpers.cpp:530
LinkDeps_t::value
int value
Definition: btSoftBodyHelpers.cpp:532
LinkDeps_t::next
LinkDeps_t * next
Definition: btSoftBodyHelpers.cpp:534
btAlignedObjectArray
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
Definition: btAlignedObjectArray.h:46
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:142
btAlignedObjectArray::resize
void resize(int newsize, const T &fillData=T())
Definition: btAlignedObjectArray.h:203
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:257
btCollisionObject::getWorldTransform
btTransform & getWorldTransform()
Definition: btCollisionObject.h:379
btConvexHullComputer::Edge
Definition: btConvexHullComputer.h:31
btConvexHullComputer::Edge::getNextEdgeOfFace
const Edge * getNextEdgeOfFace() const
Definition: btConvexHullComputer.h:55
btConvexHullComputer::Edge::getSourceVertex
int getSourceVertex() const
Definition: btConvexHullComputer.h:40
btConvexHullComputer::Edge::getTargetVertex
int getTargetVertex() const
Definition: btConvexHullComputer.h:45
btConvexHullComputer
Convex hull implementation based on Preparata and Hong See http://code.google.com/p/bullet/issues/det...
Definition: btConvexHullComputer.h:25
btConvexHullComputer::compute
btScalar compute(const void *coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
Definition: btConvexHullComputer.cpp:2653
btConvexHullComputer::vertices
btAlignedObjectArray< btVector3 > vertices
Definition: btConvexHullComputer.h:67
btConvexHullComputer::faces
btAlignedObjectArray< int > faces
Definition: btConvexHullComputer.h:76
btConvexHullComputer::edges
btAlignedObjectArray< Edge > edges
Definition: btConvexHullComputer.h:73
btIDebugDraw
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
Definition: btIDebugDraw.h:27
btIDebugDraw::drawLine
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
btIDebugDraw::draw3dText
virtual void draw3dText(const btVector3 &location, const char *textString)=0
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
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:50
btSoftBody
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:75
btSoftBody::m_cdbvt
btDbvt m_cdbvt
Definition: btSoftBody.h:835
btSoftBody::appendFace
void appendFace(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:429
btSoftBody::setMass
void setMass(int node, btScalar mass)
Definition: btSoftBody.cpp:920
btSoftBody::m_joints
tJointArray m_joints
Definition: btSoftBody.h:827
btSoftBody::m_tetraScratchesTn
btAlignedObjectArray< TetraScratch > m_tetraScratchesTn
Definition: btSoftBody.h:819
btSoftBody::m_pose
Pose m_pose
Definition: btSoftBody.h:808
btSoftBody::appendTetra
void appendTetra(int model, Material *mat)
Definition: btSoftBody.cpp:469
btSoftBody::m_tetras
tTetraArray m_tetras
Definition: btSoftBody.h:817
btSoftBody::m_tetraScratches
btAlignedObjectArray< TetraScratch > m_tetraScratches
Definition: btSoftBody.h:818
btSoftBody::m_renderNodesInterpolationWeights
btAlignedObjectArray< btVector4 > m_renderNodesInterpolationWeights
Definition: btSoftBody.h:846
btSoftBody::m_faces
tFaceArray m_faces
Definition: btSoftBody.h:815
btSoftBody::m_z
btAlignedObjectArray< btScalar > m_z
Definition: btSoftBody.h:848
btSoftBody::m_rcontacts
tRContactArray m_rcontacts
Definition: btSoftBody.h:822
btSoftBody::m_clusters
tClusterArray m_clusters
Definition: btSoftBody.h:836
btSoftBody::m_renderNodesParents
btAlignedObjectArray< btAlignedObjectArray< const btSoftBody::Node * > > m_renderNodesParents
Definition: btSoftBody.h:847
btSoftBody::m_renderNodes
tRenderNodeArray m_renderNodes
Definition: btSoftBody.h:813
btSoftBody::m_notes
tNoteArray m_notes
Definition: btSoftBody.h:811
btSoftBody::m_fdbvt
btDbvt m_fdbvt
Definition: btSoftBody.h:833
btSoftBody::m_links
tLinkArray m_links
Definition: btSoftBody.h:814
btSoftBody::m_anchors
tAnchorArray m_anchors
Definition: btSoftBody.h:820
btSoftBody::randomizeConstraints
void randomizeConstraints()
Definition: btSoftBody.cpp:1469
btSoftBody::m_nodes
tNodeArray m_nodes
Definition: btSoftBody.h:812
btSoftBody::appendLink
void appendLink(int model=-1, Material *mat=0)
Definition: btSoftBody.cpp:389
btSoftBody::initializeDmInverse
void initializeDmInverse()
Definition: btSoftBody.cpp:3454
btSoftBody::m_ndbvt
btDbvt m_ndbvt
Definition: btSoftBody.h:832
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:108
btTransform::getOrigin
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:113
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:82
btVector3::y
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
btVector3::setZ
void setZ(btScalar _z)
Set the z value.
Definition: btVector3.h:571
btVector3::z
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579
btVector3::cross
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:380
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
btVector3::dot
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:229
btVector3::normalized
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:949
btVector3::setY
void setY(btScalar _y)
Set the y value.
Definition: btVector3.h:569
btVector3::x
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
btVector3::setX
void setX(btScalar _x)
Set the x value.
Definition: btVector3.h:567
btVector3::getY
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btVector4
Definition: btVector3.h:1074
btDbvtAabbMm::Extents
DBVT_INLINE btVector3 Extents() const
Definition: btDbvt.h:136
btDbvtAabbMm::Center
DBVT_INLINE btVector3 Center() const
Definition: btDbvt.h:134
btDbvtNode
Definition: btDbvt.h:181
btDbvtNode::isinternal
DBVT_INLINE bool isinternal() const
Definition: btDbvt.h:185
btDbvtNode::childs
btDbvtNode * childs[2]
Definition: btDbvt.h:187
btDbvtNode::volume
btDbvtVolume volume
Definition: btDbvt.h:182
btDbvtNode::isleaf
DBVT_INLINE bool isleaf() const
Definition: btDbvt.h:184
btDbvt::m_root
btDbvtNode * m_root
Definition: btDbvt.h:302
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
btSoftBodyHelpers::writeObj
static void writeObj(const char *file, const btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1425
btSoftBodyHelpers::CreateFromTriMesh
static btSoftBody * CreateFromTriMesh(btSoftBodyWorldInfo &worldInfo, const btScalar *vertices, const int *triangles, int ntriangles, bool randomizeConstraints=true)
Definition: btSoftBodyHelpers.cpp:1046
btSoftBodyHelpers::extrapolateBarycentricWeights
static void extrapolateBarycentricWeights(btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1615
btSoftBodyHelpers::DrawNodeTree
static void DrawNodeTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:465
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:1534
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
btSoftBodyHelpers::CreateFromConvexHull
static btSoftBody * CreateFromConvexHull(btSoftBodyWorldInfo &worldInfo, const btVector3 *vertices, int nvertices, bool randomizeConstraints=true)
Definition: btSoftBodyHelpers.cpp:1093
btSoftBodyHelpers::CreateFromVtkFile
static btSoftBody * CreateFromVtkFile(btSoftBodyWorldInfo &worldInfo, const char *vtk_file)
Definition: btSoftBodyHelpers.cpp:1246
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
btSoftBodyHelpers::DrawFaceTree
static void DrawFaceTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:474
btSoftBodyHelpers::DrawInfos
static void DrawInfos(btSoftBody *psb, btIDebugDraw *idraw, bool masses, bool areas, bool stress)
Definition: btSoftBodyHelpers.cpp:439
btSoftBodyHelpers::CreateEllipsoid
static btSoftBody * CreateEllipsoid(btSoftBodyWorldInfo &worldInfo, const btVector3 &center, const btVector3 &radius, int res)
Definition: btSoftBodyHelpers.cpp:1015
btSoftBodyHelpers::DrawClusterTree
static void DrawClusterTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
Definition: btSoftBodyHelpers.cpp:483
btSoftBodyHelpers::CalculateUV
static float CalculateUV(int resx, int resy, int ix, int iy, int id)
Definition: btSoftBodyHelpers.cpp:968
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
btSoftBodyHelpers::generateBoundaryFaces
static void generateBoundaryFaces(btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1353
btSoftBodyHelpers::Draw
static void Draw(btSoftBody *psb, btIDebugDraw *idraw, int drawflags=fDrawFlags::Std)
Definition: btSoftBodyHelpers.cpp:171
btSoftBodyHelpers::duplicateFaces
static void duplicateFaces(const char *filename, const btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1490
btSoftBodyHelpers::DrawFrame
static void DrawFrame(btSoftBody *psb, btIDebugDraw *idraw)
Definition: btSoftBodyHelpers.cpp:666
btSoftBodyHelpers::CreateRope
static btSoftBody * CreateRope(btSoftBodyWorldInfo &worldInfo, const btVector3 &from, const btVector3 &to, int res, int fixeds)
Definition: btSoftBodyHelpers.cpp:690
btSoftBodyHelpers::interpolateBarycentricWeights
static void interpolateBarycentricWeights(btSoftBody *psb)
Definition: btSoftBodyHelpers.cpp:1571
btSoftBodyWorldInfo
Definition: btSoftBody.h:48
btSoftBody::Anchor
Definition: btSoftBody.h:425
btSoftBody::Anchor::m_local
btVector3 m_local
Definition: btSoftBody.h:427
btSoftBody::Anchor::m_body
btRigidBody * m_body
Definition: btSoftBody.h:428
btSoftBody::Anchor::m_node
Node * m_node
Definition: btSoftBody.h:426
btSoftBody::Body::xform
const btTransform & xform() const
Definition: btSoftBody.h:545
btSoftBody::Cluster
Definition: btSoftBody.h:458
btSoftBody::Cluster::m_nodes
btAlignedObjectArray< Node * > m_nodes
Definition: btSoftBody.h:460
btSoftBody::Cluster::m_com
btVector3 m_com
Definition: btSoftBody.h:467
btSoftBody::Cluster::m_lv
btVector3 m_lv
Definition: btSoftBody.h:472
btSoftBody::Cluster::m_av
btVector3 m_av
Definition: btSoftBody.h:473
btSoftBody::Face
Definition: btSoftBody.h:306
btSoftBody::Face::m_n
Node * m_n[3]
Definition: btSoftBody.h:307
btSoftBody::Feature::m_material
Material * m_material
Definition: btSoftBody.h:258
btSoftBody::Joint::eType::Linear
@ Linear
Definition: btSoftBody.h:625
btSoftBody::Joint::eType::Angular
@ Angular
Definition: btSoftBody.h:626
btSoftBody::Joint
Definition: btSoftBody.h:620
btSoftBody::Joint::m_bodies
Body m_bodies[2]
Definition: btSoftBody.h:637
btSoftBody::Joint::m_refs
btVector3 m_refs[2]
Definition: btSoftBody.h:638
btSoftBody::Joint::Type
virtual eType::_ Type() const =0
btSoftBody::LJoint
Definition: btSoftBody.h:655
btSoftBody::Link
Definition: btSoftBody.h:288
btSoftBody::Link::m_n
Node * m_n[2]
Definition: btSoftBody.h:290
btSoftBody::Material::m_flags
int m_flags
Definition: btSoftBody.h:252
btSoftBody::Node
Definition: btSoftBody.h:268
btSoftBody::Node::m_im
btScalar m_im
Definition: btSoftBody.h:275
btSoftBody::Node::m_area
btScalar m_area
Definition: btSoftBody.h:276
btSoftBody::Node::m_x
btVector3 m_x
Definition: btSoftBody.h:269
btSoftBody::Node::m_n
btVector3 m_n
Definition: btSoftBody.h:274
btSoftBody::Note
Definition: btSoftBody.h:436
btSoftBody::Note::m_coords
btScalar m_coords[4]
Definition: btSoftBody.h:441
btSoftBody::Note::m_offset
btVector3 m_offset
Definition: btSoftBody.h:438
btSoftBody::Note::m_rank
int m_rank
Definition: btSoftBody.h:439
btSoftBody::Note::m_nodes
Node * m_nodes[4]
Definition: btSoftBody.h:440
btSoftBody::Note::m_text
const char * m_text
Definition: btSoftBody.h:437
btSoftBody::Pose::m_scl
btMatrix3x3 m_scl
Definition: btSoftBody.h:453
btSoftBody::Pose::m_com
btVector3 m_com
Definition: btSoftBody.h:451
btSoftBody::Pose::m_pos
tVector3Array m_pos
Definition: btSoftBody.h:449
btSoftBody::Pose::m_rot
btMatrix3x3 m_rot
Definition: btSoftBody.h:452
btSoftBody::Pose::m_bframe
bool m_bframe
Definition: btSoftBody.h:447
btSoftBody::RContact
Definition: btSoftBody.h:342
btSoftBody::RContact::m_cti
sCti m_cti
Definition: btSoftBody.h:343
btSoftBody::RContact::m_node
Node * m_node
Definition: btSoftBody.h:344
btSoftBody::Tetra
Definition: btSoftBody.h:317
btSoftBody::Tetra::m_n
Node * m_n[4]
Definition: btSoftBody.h:318
btSoftBody::fMaterial::DebugDraw
@ DebugDraw
Definition: btSoftBody.h:189
btSoftBody::sCti::m_offset
btScalar m_offset
Definition: btSoftBody.h:228
btSoftBody::sCti::m_normal
btVector3 m_normal
Definition: btSoftBody.h:227
fDrawFlags::FaceTree
@ FaceTree
Definition: btSoftBodyHelpers.h:41
fDrawFlags::Faces
@ Faces
Definition: btSoftBodyHelpers.h:33
fDrawFlags::Links
@ Links
Definition: btSoftBodyHelpers.h:32
fDrawFlags::Clusters
@ Clusters
Definition: btSoftBodyHelpers.h:39
fDrawFlags::Anchors
@ Anchors
Definition: btSoftBodyHelpers.h:37
fDrawFlags::NodeTree
@ NodeTree
Definition: btSoftBodyHelpers.h:40
fDrawFlags::Tetras
@ Tetras
Definition: btSoftBodyHelpers.h:34
fDrawFlags::Normals
@ Normals
Definition: btSoftBodyHelpers.h:35
fDrawFlags::Contacts
@ Contacts
Definition: btSoftBodyHelpers.h:36
fDrawFlags::Notes
@ Notes
Definition: btSoftBodyHelpers.h:38
fDrawFlags::ClusterTree
@ ClusterTree
Definition: btSoftBodyHelpers.h:42
fDrawFlags::Joints
@ Joints
Definition: btSoftBodyHelpers.h:43
fDrawFlags::Nodes
@ Nodes
Definition: btSoftBodyHelpers.h:31