2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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:
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.
15 ///btSoftBodyHelpers.cpp by Nathanael Presson
17 #include "btSoftBodyInternals.h"
20 #include "btSoftBodyHelpers.h"
21 #include "LinearMath/btConvexHull.h"
22 #include "LinearMath/btConvexHullComputer.h"
26 static void drawVertex( btIDebugDraw* idraw,
27 const btVector3& x,btScalar s,const btVector3& c)
29 idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
30 idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c);
31 idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
35 static void drawBox( btIDebugDraw* idraw,
36 const btVector3& mins,
37 const btVector3& maxs,
38 const btVector3& color)
40 const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()),
41 btVector3(maxs.x(),mins.y(),mins.z()),
42 btVector3(maxs.x(),maxs.y(),mins.z()),
43 btVector3(mins.x(),maxs.y(),mins.z()),
44 btVector3(mins.x(),mins.y(),maxs.z()),
45 btVector3(maxs.x(),mins.y(),maxs.z()),
46 btVector3(maxs.x(),maxs.y(),maxs.z()),
47 btVector3(mins.x(),maxs.y(),maxs.z())};
48 idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color);
49 idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color);
50 idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color);
51 idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color);
52 idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color);
53 idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color);
57 static void drawTree( btIDebugDraw* idraw,
58 const btDbvtNode* node,
60 const btVector3& ncolor,
61 const btVector3& lcolor,
67 if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
69 drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth);
70 drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth);
74 const btScalar scl=(btScalar)(node->isinternal()?1:1);
75 const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl;
76 const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl;
77 drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
84 static inline T sum(const btAlignedObjectArray<T>& items)
90 for(int i=1,ni=items.size();i<ni;++i)
99 template <typename T,typename Q>
100 static inline void add(btAlignedObjectArray<T>& items,const Q& value)
102 for(int i=0,ni=items.size();i<ni;++i)
109 template <typename T,typename Q>
110 static inline void mul(btAlignedObjectArray<T>& items,const Q& value)
112 for(int i=0,ni=items.size();i<ni;++i)
119 template <typename T>
120 static inline T average(const btAlignedObjectArray<T>& items)
122 const btScalar n=(btScalar)(items.size()>0?items.size():1);
123 return(sum(items)/n);
127 static inline btScalar tetravolume(const btVector3& x0,
132 const btVector3 a=x1-x0;
133 const btVector3 b=x2-x0;
134 const btVector3 c=x3-x0;
135 return(btDot(a,btCross(b,c)));
140 static btVector3 stresscolor(btScalar stress)
142 static const btVector3 spectrum[]= { btVector3(1,0,1),
149 static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
150 static const btScalar one=1;
151 stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
152 const int sel=(int)stress;
153 const btScalar frc=stress-sel;
154 return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
159 void btSoftBodyHelpers::Draw( btSoftBody* psb,
163 const btScalar scl=(btScalar)0.1;
164 const btScalar nscl=scl*5;
165 const btVector3 lcolor=btVector3(0,0,0);
166 const btVector3 ncolor=btVector3(1,1,1);
167 const btVector3 ccolor=btVector3(1,0,0);
171 if(0!=(drawflags&fDrawFlags::Clusters))
174 for(i=0;i<psb->m_clusters.size();++i)
176 if(psb->m_clusters[i]->m_collide)
178 btVector3 color( rand()/(btScalar)RAND_MAX,
179 rand()/(btScalar)RAND_MAX,
180 rand()/(btScalar)RAND_MAX);
181 color=color.normalized()*0.75;
182 btAlignedObjectArray<btVector3> vertices;
183 vertices.resize(psb->m_clusters[i]->m_nodes.size());
184 for(j=0,nj=vertices.size();j<nj;++j)
186 vertices[j]=psb->m_clusters[i]->m_nodes[j]->m_x;
188 #define USE_NEW_CONVEX_HULL_COMPUTER
189 #ifdef USE_NEW_CONVEX_HULL_COMPUTER
190 btConvexHullComputer computer;
191 int stride = sizeof(btVector3);
192 int count = vertices.size();
194 btScalar shrinkClamp=0.f;
195 computer.compute(&vertices[0].getX(),stride,count,shrink,shrinkClamp);
196 for (int i=0;i<computer.faces.size();i++)
199 int face = computer.faces[i];
200 //printf("face=%d\n",face);
201 const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
202 const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
204 int v0 = firstEdge->getSourceVertex();
205 int v1 = firstEdge->getTargetVertex();
206 while (edge!=firstEdge)
208 int v2 = edge->getTargetVertex();
209 idraw->drawTriangle(computer.vertices[v0],computer.vertices[v1],computer.vertices[v2],color,1);
210 edge = edge->getNextEdgeOfFace();
217 HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]);
220 hdsc.mMaxVertices=vertices.size();
221 hlib.CreateConvexHull(hdsc,hres);
222 const btVector3 center=average(hres.m_OutputVertices);
223 add(hres.m_OutputVertices,-center);
224 mul(hres.m_OutputVertices,(btScalar)1);
225 add(hres.m_OutputVertices,center);
226 for(j=0;j<(int)hres.mNumFaces;++j)
228 const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]};
229 idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
230 hres.m_OutputVertices[idx[1]],
231 hres.m_OutputVertices[idx[2]],
234 hlib.ReleaseResult(hres);
240 for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
242 const btSoftBody::Cluster& c=psb->m_clusters[i];
243 const btVector3 r=c.m_nodes[j]->m_x-c.m_com;
244 const btVector3 v=c.m_lv+btCross(c.m_av,r);
245 idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
249 // btSoftBody::Cluster& c=*psb->m_clusters[i];
250 // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
251 // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
252 // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
258 if(0!=(drawflags&fDrawFlags::Nodes))
260 for(i=0;i<psb->m_nodes.size();++i)
262 const btSoftBody::Node& n=psb->m_nodes[i];
263 if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
264 idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
265 idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
266 idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
270 if(0!=(drawflags&fDrawFlags::Links))
272 for(i=0;i<psb->m_links.size();++i)
274 const btSoftBody::Link& l=psb->m_links[i];
275 if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
276 idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor);
280 if(0!=(drawflags&fDrawFlags::Normals))
282 for(i=0;i<psb->m_nodes.size();++i)
284 const btSoftBody::Node& n=psb->m_nodes[i];
285 if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
286 const btVector3 d=n.m_n*nscl;
287 idraw->drawLine(n.m_x,n.m_x+d,ncolor);
288 idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
292 if(0!=(drawflags&fDrawFlags::Contacts))
294 static const btVector3 axis[]={btVector3(1,0,0),
297 for(i=0;i<psb->m_rcontacts.size();++i)
299 const btSoftBody::RContact& c=psb->m_rcontacts[i];
300 const btVector3 o= c.m_node->m_x-c.m_cti.m_normal*
301 (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset);
302 const btVector3 x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
303 const btVector3 y=btCross(x,c.m_cti.m_normal).normalized();
304 idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
305 idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
306 idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
310 if(0!=(drawflags&fDrawFlags::Faces))
312 const btScalar scl=(btScalar)0.8;
313 const btScalar alp=(btScalar)1;
314 const btVector3 col(0,(btScalar)0.7,0);
315 for(i=0;i<psb->m_faces.size();++i)
317 const btSoftBody::Face& f=psb->m_faces[i];
318 if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
319 const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
320 const btVector3 c=(x[0]+x[1]+x[2])/3;
321 idraw->drawTriangle((x[0]-c)*scl+c,
328 if(0!=(drawflags&fDrawFlags::Tetras))
330 const btScalar scl=(btScalar)0.8;
331 const btScalar alp=(btScalar)1;
332 const btVector3 col((btScalar)0.3,(btScalar)0.3,(btScalar)0.7);
333 for(int i=0;i<psb->m_tetras.size();++i)
335 const btSoftBody::Tetra& t=psb->m_tetras[i];
336 if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
337 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};
338 const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
339 idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
340 idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
341 idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
342 idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
347 if(0!=(drawflags&fDrawFlags::Anchors))
349 for(i=0;i<psb->m_anchors.size();++i)
351 const btSoftBody::Anchor& a=psb->m_anchors[i];
352 const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
353 drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
354 drawVertex(idraw,q,0.25,btVector3(0,1,0));
355 idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
357 for(i=0;i<psb->m_nodes.size();++i)
359 const btSoftBody::Node& n=psb->m_nodes[i];
360 if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
363 drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
370 if(0!=(drawflags&fDrawFlags::Notes))
372 for(i=0;i<psb->m_notes.size();++i)
374 const btSoftBody::Note& n=psb->m_notes[i];
375 btVector3 p=n.m_offset;
376 for(int j=0;j<n.m_rank;++j)
378 p+=n.m_nodes[j]->m_x*n.m_coords[j];
380 idraw->draw3dText(p,n.m_text);
384 if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw);
386 if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw);
388 if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw);
390 if(0!=(drawflags&fDrawFlags::Joints))
392 for(i=0;i<psb->m_joints.size();++i)
394 const btSoftBody::Joint* pj=psb->m_joints[i];
397 case btSoftBody::Joint::eType::Linear:
399 const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj;
400 const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0];
401 const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1];
402 idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0));
403 idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1));
404 drawVertex(idraw,a0,0.25,btVector3(1,1,0));
405 drawVertex(idraw,a1,0.25,btVector3(0,1,1));
408 case btSoftBody::Joint::eType::Angular:
410 //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj;
411 const btVector3 o0=pj->m_bodies[0].xform().getOrigin();
412 const btVector3 o1=pj->m_bodies[1].xform().getOrigin();
413 const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0];
414 const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1];
415 idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0));
416 idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0));
417 idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1));
418 idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1));
431 void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
437 for(int i=0;i<psb->m_nodes.size();++i)
439 const btSoftBody::Node& n=psb->m_nodes[i];
444 sprintf(buff," M(%.2f)",1/n.m_im);
449 sprintf(buff," A(%.2f)",n.m_area);
452 if(text[0]) idraw->draw3dText(n.m_x,text);
457 void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb,
462 drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth);
466 void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb,
471 drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth);
475 void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb,
480 drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth);
484 void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
487 if(psb->m_pose.m_bframe)
489 static const btScalar ascl=10;
490 static const btScalar nscl=(btScalar)0.1;
491 const btVector3 com=psb->m_pose.m_com;
492 const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl;
493 const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized();
494 const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized();
495 const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized();
496 idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
497 idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
498 idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
499 for(int i=0;i<psb->m_pose.m_pos.size();++i)
501 const btVector3 x=com+trs*psb->m_pose.m_pos[i];
502 drawVertex(idraw,x,nscl,btVector3(1,0,1));
508 btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from,
515 btVector3* x=new btVector3[r];
516 btScalar* m=new btScalar[r];
521 const btScalar t=i/(btScalar)(r-1);
522 x[i]=lerp(from,to,t);
525 btSoftBody* psb= new btSoftBody(&worldInfo,r,x,m);
526 if(fixeds&1) psb->setMass(0,0);
527 if(fixeds&2) psb->setMass(r-1,0);
533 psb->appendLink(i-1,i);
540 btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
541 const btVector3& corner10,
542 const btVector3& corner01,
543 const btVector3& corner11,
549 #define IDX(_x_,_y_) ((_y_)*rx+(_x_))
551 if((resx<2)||(resy<2)) return(0);
555 btVector3* x=new btVector3[tot];
556 btScalar* m=new btScalar[tot];
561 const btScalar ty=iy/(btScalar)(ry-1);
562 const btVector3 py0=lerp(corner00,corner01,ty);
563 const btVector3 py1=lerp(corner10,corner11,ty);
564 for(int ix=0;ix<rx;++ix)
566 const btScalar tx=ix/(btScalar)(rx-1);
567 x[IDX(ix,iy)]=lerp(py0,py1,tx);
571 btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
572 if(fixeds&1) psb->setMass(IDX(0,0),0);
573 if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
574 if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
575 if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
578 /* Create links and faces */
581 for(int ix=0;ix<rx;++ix)
583 const int idx=IDX(ix,iy);
584 const bool mdx=(ix+1)<rx;
585 const bool mdy=(iy+1)<ry;
586 if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
587 if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
592 psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
593 psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
596 psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
601 psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
602 psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
605 psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
617 btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
618 const btVector3& corner00,
619 const btVector3& corner10,
620 const btVector3& corner01,
621 const btVector3& corner11,
633 * [0][0] corner00 ------- corner01 [resx][0]
636 * [0][resy] corner10 -------- corner11 [resx][resy]
649 * upper middle --> +16
650 * left middle --> +32
651 * right middle --> +64
652 * lower middle --> +128
656 * tex_coords size (resx-1)*(resy-1)*12
660 * SINGLE QUAD INTERNALS
662 * 1) btSoftBody's nodes and links,
663 * diagonal link is optional ("gendiags")
666 * node00 ------ node01
678 * UV Coordinates (hier example for single quad)
696 #define IDX(_x_,_y_) ((_y_)*rx+(_x_))
698 if((resx<2)||(resy<2)) return(0);
702 btVector3* x=new btVector3[tot];
703 btScalar* m=new btScalar[tot];
709 const btScalar ty=iy/(btScalar)(ry-1);
710 const btVector3 py0=lerp(corner00,corner01,ty);
711 const btVector3 py1=lerp(corner10,corner11,ty);
712 for(int ix=0;ix<rx;++ix)
714 const btScalar tx=ix/(btScalar)(rx-1);
715 x[IDX(ix,iy)]=lerp(py0,py1,tx);
719 btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
720 if(fixeds&1) psb->setMass(IDX(0,0),0);
721 if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
722 if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
723 if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
724 if(fixeds&16) psb->setMass(IDX((rx-1)/2,0),0);
725 if(fixeds&32) psb->setMass(IDX(0,(ry-1)/2),0);
726 if(fixeds&64) psb->setMass(IDX(rx-1,(ry-1)/2),0);
727 if(fixeds&128) psb->setMass(IDX((rx-1)/2,ry-1),0);
728 if(fixeds&256) psb->setMass(IDX((rx-1)/2,(ry-1)/2),0);
734 /* Create links and faces */
737 for(int ix=0;ix<rx;++ix)
739 const bool mdx=(ix+1)<rx;
740 const bool mdy=(iy+1)<ry;
742 int node00=IDX(ix,iy);
743 int node01=IDX(ix+1,iy);
744 int node10=IDX(ix,iy+1);
745 int node11=IDX(ix+1,iy+1);
747 if(mdx) psb->appendLink(node00,node01);
748 if(mdy) psb->appendLink(node00,node10);
751 psb->appendFace(node00,node10,node11);
753 tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0);
754 tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1);
755 tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0);
756 tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2);
757 tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3);
758 tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2);
760 psb->appendFace(node11,node01,node00);
762 tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3);
763 tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2);
764 tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3);
765 tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1);
766 tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0);
767 tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1);
769 if (gendiags) psb->appendLink(node00,node11);
779 float btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id)
809 tc = (1.0f/((resx-1))*ix);
812 tc = (1.0f/((resy-1))*(resy-1-iy));
815 tc = (1.0f/((resy-1))*(resy-1-iy-1));
818 tc = (1.0f/((resx-1))*(ix+1));
823 btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center,
824 const btVector3& radius,
829 static void Generate(btVector3* x,int n)
834 for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
836 btScalar a=(SIMD_PI+2*i*SIMD_PI)/n;
837 btScalar s=btSqrt(1-w*w);
838 *x++=btVector3(s*btCos(a),s*btSin(a),w);
842 btAlignedObjectArray<btVector3> vtx;
844 Hammersley::Generate(&vtx[0],vtx.size());
845 for(int i=0;i<vtx.size();++i)
847 vtx[i]=vtx[i]*radius+center;
849 return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
855 btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
856 const int* triangles,
857 int ntriangles, bool randomizeConstraints)
862 for(i=0,ni=ntriangles*3;i<ni;++i)
864 maxidx=btMax(triangles[i],maxidx);
867 btAlignedObjectArray<bool> chks;
868 btAlignedObjectArray<btVector3> vtx;
869 chks.resize(maxidx*maxidx,false);
871 for(i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
873 vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
875 btSoftBody* psb=new btSoftBody(&worldInfo,vtx.size(),&vtx[0],0);
876 for( i=0,ni=ntriangles*3;i<ni;i+=3)
878 const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
879 #define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
880 for(int j=2,k=0;k<3;j=k++)
882 if(!chks[IDX(idx[j],idx[k])])
884 chks[IDX(idx[j],idx[k])]=true;
885 chks[IDX(idx[k],idx[j])]=true;
886 psb->appendLink(idx[j],idx[k]);
890 psb->appendFace(idx[0],idx[1],idx[2]);
893 if (randomizeConstraints)
895 psb->randomizeConstraints();
902 btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
903 int nvertices, bool randomizeConstraints)
905 HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
907 HullLibrary hlib;/*??*/
908 hdsc.mMaxVertices=nvertices;
909 hlib.CreateConvexHull(hdsc,hres);
910 btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
911 &hres.m_OutputVertices[0],0);
912 for(int i=0;i<(int)hres.mNumFaces;++i)
914 const int idx[]={ hres.m_Indices[i*3+0],
915 hres.m_Indices[i*3+1],
916 hres.m_Indices[i*3+2]};
917 if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
918 if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
919 if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
920 psb->appendFace(idx[0],idx[1],idx[2]);
922 hlib.ReleaseResult(hres);
923 if (randomizeConstraints)
925 psb->randomizeConstraints();
933 static int nextLine(const char* buffer)
937 while (*buffer != '\n')
952 /* Create from TetGen .ele, .face, .node data */
953 btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
959 bool bfacesfromtetras)
961 btAlignedObjectArray<btVector3> pos;
966 int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
967 result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
968 node += nextLine(node);
971 for(int i=0;i<pos.size();++i)
976 sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
979 // sn>>x;sn>>y;sn>>z;
980 node += nextLine(node);
982 //for(int j=0;j<nattrb;++j)
988 pos[index].setX(btScalar(x));
989 pos[index].setY(btScalar(y));
990 pos[index].setZ(btScalar(z));
992 btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
997 sf>>nface;sf>>hasbounds;
998 for(int i=0;i<nface;++i)
1004 sf>>ni[0];sf>>ni[1];sf>>ni[2];
1006 psb->appendFace(ni[0],ni[1],ni[2]);
1009 psb->appendLink(ni[0],ni[1],0,true);
1010 psb->appendLink(ni[1],ni[2],0,true);
1011 psb->appendLink(ni[2],ni[0],0,true);
1022 sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
1023 ele += nextLine(ele);
1025 //se>>ntetra;se>>ncorner;se>>neattrb;
1026 for(int i=0;i<ntetra;++i)
1032 //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
1033 sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
1035 //for(int j=0;j<neattrb;++j)
1037 psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
1040 psb->appendLink(ni[0],ni[1],0,true);
1041 psb->appendLink(ni[1],ni[2],0,true);
1042 psb->appendLink(ni[2],ni[0],0,true);
1043 psb->appendLink(ni[0],ni[3],0,true);
1044 psb->appendLink(ni[1],ni[3],0,true);
1045 psb->appendLink(ni[2],ni[3],0,true);
1049 printf("Nodes: %u\r\n",psb->m_nodes.size());
1050 printf("Links: %u\r\n",psb->m_links.size());
1051 printf("Faces: %u\r\n",psb->m_faces.size());
1052 printf("Tetras: %u\r\n",psb->m_tetras.size());