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

Bullet Collision Detection & Physics Library

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