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