Blender  V2.59
btSoftBody.cpp
Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose,
00008 including commercial applications, and to alter it and redistribute it freely,
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00016 
00017 #include "btSoftBodyInternals.h"
00018 #include "BulletSoftBody/btSoftBodySolvers.h"
00019 #include "btSoftBodyData.h"
00020 #include "LinearMath/btSerializer.h"
00021 
00022 //
00023 btSoftBody::btSoftBody(btSoftBodyWorldInfo*     worldInfo,int node_count,  const btVector3* x,  const btScalar* m)
00024 :m_worldInfo(worldInfo),m_softBodySolver(0)
00025 {       
00026         /* Init         */ 
00027         initDefaults();
00028 
00029         /* Default material     */ 
00030         Material*       pm=appendMaterial();
00031         pm->m_kLST      =       1;
00032         pm->m_kAST      =       1;
00033         pm->m_kVST      =       1;
00034         pm->m_flags     =       fMaterial::Default;
00035 
00036         /* Nodes                        */ 
00037         const btScalar          margin=getCollisionShape()->getMargin();
00038         m_nodes.resize(node_count);
00039         for(int i=0,ni=node_count;i<ni;++i)
00040         {       
00041                 Node&   n=m_nodes[i];
00042                 ZeroInitialize(n);
00043                 n.m_x           =       x?*x++:btVector3(0,0,0);
00044                 n.m_q           =       n.m_x;
00045                 n.m_im          =       m?*m++:1;
00046                 n.m_im          =       n.m_im>0?1/n.m_im:0;
00047                 n.m_leaf        =       m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
00048                 n.m_material=   pm;
00049         }
00050         updateBounds(); 
00051 
00052 }
00053 
00054 btSoftBody::btSoftBody(btSoftBodyWorldInfo*     worldInfo)
00055 :m_worldInfo(worldInfo)
00056 {
00057         initDefaults();
00058 }
00059 
00060 
00061 void    btSoftBody::initDefaults()
00062 {
00063         m_internalType          =       CO_SOFT_BODY;
00064         m_cfg.aeromodel         =       eAeroModel::V_Point;
00065         m_cfg.kVCF                      =       1;
00066         m_cfg.kDG                       =       0;
00067         m_cfg.kLF                       =       0;
00068         m_cfg.kDP                       =       0;
00069         m_cfg.kPR                       =       0;
00070         m_cfg.kVC                       =       0;
00071         m_cfg.kDF                       =       (btScalar)0.2;
00072         m_cfg.kMT                       =       0;
00073         m_cfg.kCHR                      =       (btScalar)1.0;
00074         m_cfg.kKHR                      =       (btScalar)0.1;
00075         m_cfg.kSHR                      =       (btScalar)1.0;
00076         m_cfg.kAHR                      =       (btScalar)0.7;
00077         m_cfg.kSRHR_CL          =       (btScalar)0.1;
00078         m_cfg.kSKHR_CL          =       (btScalar)1;
00079         m_cfg.kSSHR_CL          =       (btScalar)0.5;
00080         m_cfg.kSR_SPLT_CL       =       (btScalar)0.5;
00081         m_cfg.kSK_SPLT_CL       =       (btScalar)0.5;
00082         m_cfg.kSS_SPLT_CL       =       (btScalar)0.5;
00083         m_cfg.maxvolume         =       (btScalar)1;
00084         m_cfg.timescale         =       1;
00085         m_cfg.viterations       =       0;
00086         m_cfg.piterations       =       1;      
00087         m_cfg.diterations       =       0;
00088         m_cfg.citerations       =       4;
00089         m_cfg.collisions        =       fCollision::Default;
00090         m_pose.m_bvolume        =       false;
00091         m_pose.m_bframe         =       false;
00092         m_pose.m_volume         =       0;
00093         m_pose.m_com            =       btVector3(0,0,0);
00094         m_pose.m_rot.setIdentity();
00095         m_pose.m_scl.setIdentity();
00096         m_tag                           =       0;
00097         m_timeacc                       =       0;
00098         m_bUpdateRtCst          =       true;
00099         m_bounds[0]                     =       btVector3(0,0,0);
00100         m_bounds[1]                     =       btVector3(0,0,0);
00101         m_worldTransform.setIdentity();
00102         setSolver(eSolverPresets::Positions);
00103         
00104         /* Collision shape      */ 
00106         m_collisionShape = new btSoftBodyCollisionShape(this);
00107         m_collisionShape->setMargin(0.25);
00108         
00109         m_initialWorldTransform.setIdentity();
00110 
00111         m_windVelocity = btVector3(0,0,0);
00112 
00113 }
00114 
00115 //
00116 btSoftBody::~btSoftBody()
00117 {
00118         //for now, delete the internal shape
00119         delete m_collisionShape;        
00120         int i;
00121 
00122         releaseClusters();
00123         for(i=0;i<m_materials.size();++i) 
00124                 btAlignedFree(m_materials[i]);
00125         for(i=0;i<m_joints.size();++i) 
00126                 btAlignedFree(m_joints[i]);
00127 }
00128 
00129 //
00130 bool                    btSoftBody::checkLink(int node0,int node1) const
00131 {
00132         return(checkLink(&m_nodes[node0],&m_nodes[node1]));
00133 }
00134 
00135 //
00136 bool                    btSoftBody::checkLink(const Node* node0,const Node* node1) const
00137 {
00138         const Node*     n[]={node0,node1};
00139         for(int i=0,ni=m_links.size();i<ni;++i)
00140         {
00141                 const Link&     l=m_links[i];
00142                 if(     (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
00143                         (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
00144                 {
00145                         return(true);
00146                 }
00147         }
00148         return(false);
00149 }
00150 
00151 //
00152 bool                    btSoftBody::checkFace(int node0,int node1,int node2) const
00153 {
00154         const Node*     n[]={   &m_nodes[node0],
00155                 &m_nodes[node1],
00156                 &m_nodes[node2]};
00157         for(int i=0,ni=m_faces.size();i<ni;++i)
00158         {
00159                 const Face&     f=m_faces[i];
00160                 int                     c=0;
00161                 for(int j=0;j<3;++j)
00162                 {
00163                         if(     (f.m_n[j]==n[0])||
00164                                 (f.m_n[j]==n[1])||
00165                                 (f.m_n[j]==n[2])) c|=1<<j; else break;
00166                 }
00167                 if(c==7) return(true);
00168         }
00169         return(false);
00170 }
00171 
00172 //
00173 btSoftBody::Material*           btSoftBody::appendMaterial()
00174 {
00175         Material*       pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
00176         if(m_materials.size()>0)
00177                 *pm=*m_materials[0];
00178         else
00179                 ZeroInitialize(*pm);
00180         m_materials.push_back(pm);
00181         return(pm);
00182 }
00183 
00184 //
00185 void                    btSoftBody::appendNote( const char* text,
00186                                                                            const btVector3& o,
00187                                                                            const btVector4& c,
00188                                                                            Node* n0,
00189                                                                            Node* n1,
00190                                                                            Node* n2,
00191                                                                            Node* n3)
00192 {
00193         Note    n;
00194         ZeroInitialize(n);
00195         n.m_rank                =       0;
00196         n.m_text                =       text;
00197         n.m_offset              =       o;
00198         n.m_coords[0]   =       c.x();
00199         n.m_coords[1]   =       c.y();
00200         n.m_coords[2]   =       c.z();
00201         n.m_coords[3]   =       c.w();
00202         n.m_nodes[0]    =       n0;n.m_rank+=n0?1:0;
00203         n.m_nodes[1]    =       n1;n.m_rank+=n1?1:0;
00204         n.m_nodes[2]    =       n2;n.m_rank+=n2?1:0;
00205         n.m_nodes[3]    =       n3;n.m_rank+=n3?1:0;
00206         m_notes.push_back(n);
00207 }
00208 
00209 //
00210 void                    btSoftBody::appendNote( const char* text,
00211                                                                            const btVector3& o,
00212                                                                            Node* feature)
00213 {
00214         appendNote(text,o,btVector4(1,0,0,0),feature);
00215 }
00216 
00217 //
00218 void                    btSoftBody::appendNote( const char* text,
00219                                                                            const btVector3& o,
00220                                                                            Link* feature)
00221 {
00222         static const btScalar   w=1/(btScalar)2;
00223         appendNote(text,o,btVector4(w,w,0,0),   feature->m_n[0],
00224                 feature->m_n[1]);
00225 }
00226 
00227 //
00228 void                    btSoftBody::appendNote( const char* text,
00229                                                                            const btVector3& o,
00230                                                                            Face* feature)
00231 {
00232         static const btScalar   w=1/(btScalar)3;
00233         appendNote(text,o,btVector4(w,w,w,0),   feature->m_n[0],
00234                 feature->m_n[1],
00235                 feature->m_n[2]);
00236 }
00237 
00238 //
00239 void                    btSoftBody::appendNode( const btVector3& x,btScalar m)
00240 {
00241         if(m_nodes.capacity()==m_nodes.size())
00242         {
00243                 pointersToIndices();
00244                 m_nodes.reserve(m_nodes.size()*2+1);
00245                 indicesToPointers();
00246         }
00247         const btScalar  margin=getCollisionShape()->getMargin();
00248         m_nodes.push_back(Node());
00249         Node&                   n=m_nodes[m_nodes.size()-1];
00250         ZeroInitialize(n);
00251         n.m_x                   =       x;
00252         n.m_q                   =       n.m_x;
00253         n.m_im                  =       m>0?1/m:0;
00254         n.m_material    =       m_materials[0];
00255         n.m_leaf                =       m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
00256 }
00257 
00258 //
00259 void                    btSoftBody::appendLink(int model,Material* mat)
00260 {
00261         Link    l;
00262         if(model>=0)
00263                 l=m_links[model];
00264         else
00265         { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
00266         m_links.push_back(l);
00267 }
00268 
00269 //
00270 void                    btSoftBody::appendLink( int node0,
00271                                                                            int node1,
00272                                                                            Material* mat,
00273                                                                            bool bcheckexist)
00274 {
00275         appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
00276 }
00277 
00278 //
00279 void                    btSoftBody::appendLink( Node* node0,
00280                                                                            Node* node1,
00281                                                                            Material* mat,
00282                                                                            bool bcheckexist)
00283 {
00284         if((!bcheckexist)||(!checkLink(node0,node1)))
00285         {
00286                 appendLink(-1,mat);
00287                 Link&   l=m_links[m_links.size()-1];
00288                 l.m_n[0]                =       node0;
00289                 l.m_n[1]                =       node1;
00290                 l.m_rl                  =       (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
00291                 m_bUpdateRtCst=true;
00292         }
00293 }
00294 
00295 //
00296 void                    btSoftBody::appendFace(int model,Material* mat)
00297 {
00298         Face    f;
00299         if(model>=0)
00300         { f=m_faces[model]; }
00301         else
00302         { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
00303         m_faces.push_back(f);
00304 }
00305 
00306 //
00307 void                    btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
00308 {
00309         if (node0==node1)
00310                 return;
00311         if (node1==node2)
00312                 return;
00313         if (node2==node0)
00314                 return;
00315 
00316         appendFace(-1,mat);
00317         Face&   f=m_faces[m_faces.size()-1];
00318         btAssert(node0!=node1);
00319         btAssert(node1!=node2);
00320         btAssert(node2!=node0);
00321         f.m_n[0]        =       &m_nodes[node0];
00322         f.m_n[1]        =       &m_nodes[node1];
00323         f.m_n[2]        =       &m_nodes[node2];
00324         f.m_ra          =       AreaOf( f.m_n[0]->m_x,
00325                 f.m_n[1]->m_x,
00326                 f.m_n[2]->m_x); 
00327         m_bUpdateRtCst=true;
00328 }
00329 
00330 //
00331 void                    btSoftBody::appendTetra(int model,Material* mat)
00332 {
00333 Tetra   t;
00334 if(model>=0)
00335         t=m_tetras[model];
00336         else
00337         { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; }
00338 m_tetras.push_back(t);
00339 }
00340 
00341 //
00342 void                    btSoftBody::appendTetra(int node0,
00343                                                                                 int node1,
00344                                                                                 int node2,
00345                                                                                 int node3,
00346                                                                                 Material* mat)
00347 {
00348         appendTetra(-1,mat);
00349         Tetra&  t=m_tetras[m_tetras.size()-1];
00350         t.m_n[0]        =       &m_nodes[node0];
00351         t.m_n[1]        =       &m_nodes[node1];
00352         t.m_n[2]        =       &m_nodes[node2];
00353         t.m_n[3]        =       &m_nodes[node3];
00354         t.m_rv          =       VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x);
00355         m_bUpdateRtCst=true;
00356 }
00357 
00358 //
00359 
00360 void                    btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies)
00361 {
00362         btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x;
00363         appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies);
00364 }
00365 
00366 //
00367 void                    btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies)
00368 {
00369         if (disableCollisionBetweenLinkedBodies)
00370         {
00371                 if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size())
00372                 {
00373                         m_collisionDisabledObjects.push_back(body);
00374                 }
00375         }
00376 
00377         Anchor  a;
00378         a.m_node                        =       &m_nodes[node];
00379         a.m_body                        =       body;
00380         a.m_local                       =       localPivot;
00381         a.m_node->m_battach     =       1;
00382         m_anchors.push_back(a);
00383 }
00384 
00385 //
00386 void                    btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
00387 {
00388         LJoint*         pj      =       new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
00389         pj->m_bodies[0] =       body0;
00390         pj->m_bodies[1] =       body1;
00391         pj->m_refs[0]   =       pj->m_bodies[0].xform().inverse()*specs.position;
00392         pj->m_refs[1]   =       pj->m_bodies[1].xform().inverse()*specs.position;
00393         pj->m_cfm               =       specs.cfm;
00394         pj->m_erp               =       specs.erp;
00395         pj->m_split             =       specs.split;
00396         m_joints.push_back(pj);
00397 }
00398 
00399 //
00400 void                    btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
00401 {
00402         appendLinearJoint(specs,m_clusters[0],body);
00403 }
00404 
00405 //
00406 void                    btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
00407 {
00408         appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
00409 }
00410 
00411 //
00412 void                    btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
00413 {
00414         AJoint*         pj      =       new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
00415         pj->m_bodies[0] =       body0;
00416         pj->m_bodies[1] =       body1;
00417         pj->m_refs[0]   =       pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
00418         pj->m_refs[1]   =       pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
00419         pj->m_cfm               =       specs.cfm;
00420         pj->m_erp               =       specs.erp;
00421         pj->m_split             =       specs.split;
00422         pj->m_icontrol  =       specs.icontrol;
00423         m_joints.push_back(pj);
00424 }
00425 
00426 //
00427 void                    btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
00428 {
00429         appendAngularJoint(specs,m_clusters[0],body);
00430 }
00431 
00432 //
00433 void                    btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
00434 {
00435         appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
00436 }
00437 
00438 //
00439 void                    btSoftBody::addForce(const btVector3& force)
00440 {
00441         for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
00442 }
00443 
00444 //
00445 void                    btSoftBody::addForce(const btVector3& force,int node)
00446 {
00447         Node&   n=m_nodes[node];
00448         if(n.m_im>0)
00449         {
00450                 n.m_f   +=      force;
00451         }
00452 }
00453 
00454 //
00455 void                    btSoftBody::addVelocity(const btVector3& velocity)
00456 {
00457         for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
00458 }
00459 
00460 /* Set velocity for the entire body                                                                             */ 
00461 void                            btSoftBody::setVelocity(        const btVector3& velocity)
00462 {
00463         for(int i=0,ni=m_nodes.size();i<ni;++i) 
00464         {
00465                 Node&   n=m_nodes[i];
00466                 if(n.m_im>0)
00467                 {
00468                         n.m_v   =       velocity;
00469                 }
00470         }
00471 }
00472 
00473 
00474 //
00475 void                    btSoftBody::addVelocity(const btVector3& velocity,int node)
00476 {
00477         Node&   n=m_nodes[node];
00478         if(n.m_im>0)
00479         {
00480                 n.m_v   +=      velocity;
00481         }
00482 }
00483 
00484 //
00485 void                    btSoftBody::setMass(int node,btScalar mass)
00486 {
00487         m_nodes[node].m_im=mass>0?1/mass:0;
00488         m_bUpdateRtCst=true;
00489 }
00490 
00491 //
00492 btScalar                btSoftBody::getMass(int node) const
00493 {
00494         return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
00495 }
00496 
00497 //
00498 btScalar                btSoftBody::getTotalMass() const
00499 {
00500         btScalar        mass=0;
00501         for(int i=0;i<m_nodes.size();++i)
00502         {
00503                 mass+=getMass(i);
00504         }
00505         return(mass);
00506 }
00507 
00508 //
00509 void                    btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
00510 {
00511         int i;
00512 
00513         if(fromfaces)
00514         {
00515 
00516                 for(i=0;i<m_nodes.size();++i)
00517                 {
00518                         m_nodes[i].m_im=0;
00519                 }
00520                 for(i=0;i<m_faces.size();++i)
00521                 {
00522                         const Face&             f=m_faces[i];
00523                         const btScalar  twicearea=AreaOf(       f.m_n[0]->m_x,
00524                                 f.m_n[1]->m_x,
00525                                 f.m_n[2]->m_x);
00526                         for(int j=0;j<3;++j)
00527                         {
00528                                 f.m_n[j]->m_im+=twicearea;
00529                         }
00530                 }
00531                 for( i=0;i<m_nodes.size();++i)
00532                 {
00533                         m_nodes[i].m_im=1/m_nodes[i].m_im;
00534                 }
00535         }
00536         const btScalar  tm=getTotalMass();
00537         const btScalar  itm=1/tm;
00538         for( i=0;i<m_nodes.size();++i)
00539         {
00540                 m_nodes[i].m_im/=itm*mass;
00541         }
00542         m_bUpdateRtCst=true;
00543 }
00544 
00545 //
00546 void                    btSoftBody::setTotalDensity(btScalar density)
00547 {
00548         setTotalMass(getVolume()*density,true);
00549 }
00550 
00551 //
00552 void                    btSoftBody::setVolumeMass(btScalar mass)
00553 {
00554 btAlignedObjectArray<btScalar>  ranks;
00555 ranks.resize(m_nodes.size(),0);
00556 int i;
00557 
00558 for(i=0;i<m_nodes.size();++i)
00559         {
00560         m_nodes[i].m_im=0;
00561         }
00562 for(i=0;i<m_tetras.size();++i)
00563         {
00564         const Tetra& t=m_tetras[i];
00565         for(int j=0;j<4;++j)
00566                 {
00567                 t.m_n[j]->m_im+=btFabs(t.m_rv);
00568                 ranks[int(t.m_n[j]-&m_nodes[0])]+=1;
00569                 }
00570         }
00571 for( i=0;i<m_nodes.size();++i)
00572         {
00573         if(m_nodes[i].m_im>0)
00574                 {
00575                 m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im;
00576                 }
00577         }
00578 setTotalMass(mass,false);
00579 }
00580 
00581 //
00582 void                    btSoftBody::setVolumeDensity(btScalar density)
00583 {
00584 btScalar        volume=0;
00585 for(int i=0;i<m_tetras.size();++i)
00586         {
00587         const Tetra& t=m_tetras[i];
00588         for(int j=0;j<4;++j)
00589                 {
00590                 volume+=btFabs(t.m_rv);
00591                 }
00592         }
00593 setVolumeMass(volume*density/6);
00594 }
00595 
00596 //
00597 void                    btSoftBody::transform(const btTransform& trs)
00598 {
00599         const btScalar  margin=getCollisionShape()->getMargin();
00600         ATTRIBUTE_ALIGNED16(btDbvtVolume)       vol;
00601         
00602         for(int i=0,ni=m_nodes.size();i<ni;++i)
00603         {
00604                 Node&   n=m_nodes[i];
00605                 n.m_x=trs*n.m_x;
00606                 n.m_q=trs*n.m_q;
00607                 n.m_n=trs.getBasis()*n.m_n;
00608                 vol = btDbvtVolume::FromCR(n.m_x,margin);
00609                 
00610                 m_ndbvt.update(n.m_leaf,vol);
00611         }
00612         updateNormals();
00613         updateBounds();
00614         updateConstants();
00615         m_initialWorldTransform = trs;
00616 }
00617 
00618 //
00619 void                    btSoftBody::translate(const btVector3& trs)
00620 {
00621         btTransform     t;
00622         t.setIdentity();
00623         t.setOrigin(trs);
00624         transform(t);
00625 }
00626 
00627 //
00628 void                    btSoftBody::rotate(     const btQuaternion& rot)
00629 {
00630         btTransform     t;
00631         t.setIdentity();
00632         t.setRotation(rot);
00633         transform(t);
00634 }
00635 
00636 //
00637 void                    btSoftBody::scale(const btVector3& scl)
00638 {
00639 
00640         const btScalar  margin=getCollisionShape()->getMargin();
00641         ATTRIBUTE_ALIGNED16(btDbvtVolume)       vol;
00642         
00643         for(int i=0,ni=m_nodes.size();i<ni;++i)
00644         {
00645                 Node&   n=m_nodes[i];
00646                 n.m_x*=scl;
00647                 n.m_q*=scl;
00648                 vol = btDbvtVolume::FromCR(n.m_x,margin);
00649                 m_ndbvt.update(n.m_leaf,vol);
00650         }
00651         updateNormals();
00652         updateBounds();
00653         updateConstants();
00654 }
00655 
00656 //
00657 void                    btSoftBody::setPose(bool bvolume,bool bframe)
00658 {
00659         m_pose.m_bvolume        =       bvolume;
00660         m_pose.m_bframe         =       bframe;
00661         int i,ni;
00662 
00663         /* Weights              */ 
00664         const btScalar  omass=getTotalMass();
00665         const btScalar  kmass=omass*m_nodes.size()*1000;
00666         btScalar                tmass=omass;
00667         m_pose.m_wgh.resize(m_nodes.size());
00668         for(i=0,ni=m_nodes.size();i<ni;++i)
00669         {
00670                 if(m_nodes[i].m_im<=0) tmass+=kmass;
00671         }
00672         for( i=0,ni=m_nodes.size();i<ni;++i)
00673         {
00674                 Node&   n=m_nodes[i];
00675                 m_pose.m_wgh[i]=        n.m_im>0                                        ?
00676                         1/(m_nodes[i].m_im*tmass)       :
00677                 kmass/tmass;
00678         }
00679         /* Pos          */ 
00680         const btVector3 com=evaluateCom();
00681         m_pose.m_pos.resize(m_nodes.size());
00682         for( i=0,ni=m_nodes.size();i<ni;++i)
00683         {
00684                 m_pose.m_pos[i]=m_nodes[i].m_x-com;
00685         }
00686         m_pose.m_volume =       bvolume?getVolume():0;
00687         m_pose.m_com    =       com;
00688         m_pose.m_rot.setIdentity();
00689         m_pose.m_scl.setIdentity();
00690         /* Aqq          */ 
00691         m_pose.m_aqq[0] =
00692                 m_pose.m_aqq[1] =
00693                 m_pose.m_aqq[2] =       btVector3(0,0,0);
00694         for( i=0,ni=m_nodes.size();i<ni;++i)
00695         {
00696                 const btVector3&        q=m_pose.m_pos[i];
00697                 const btVector3         mq=m_pose.m_wgh[i]*q;
00698                 m_pose.m_aqq[0]+=mq.x()*q;
00699                 m_pose.m_aqq[1]+=mq.y()*q;
00700                 m_pose.m_aqq[2]+=mq.z()*q;
00701         }
00702         m_pose.m_aqq=m_pose.m_aqq.inverse();
00703         updateConstants();
00704 }
00705 
00706 //
00707 btScalar                btSoftBody::getVolume() const
00708 {
00709         btScalar        vol=0;
00710         if(m_nodes.size()>0)
00711         {
00712                 int i,ni;
00713 
00714                 const btVector3 org=m_nodes[0].m_x;
00715                 for(i=0,ni=m_faces.size();i<ni;++i)
00716                 {
00717                         const Face&     f=m_faces[i];
00718                         vol+=btDot(f.m_n[0]->m_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
00719                 }
00720                 vol/=(btScalar)6;
00721         }
00722         return(vol);
00723 }
00724 
00725 //
00726 int                             btSoftBody::clusterCount() const
00727 {
00728         return(m_clusters.size());
00729 }
00730 
00731 //
00732 btVector3               btSoftBody::clusterCom(const Cluster* cluster)
00733 {
00734         btVector3               com(0,0,0);
00735         for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
00736         {
00737                 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
00738         }
00739         return(com*cluster->m_imass);
00740 }
00741 
00742 //
00743 btVector3               btSoftBody::clusterCom(int cluster) const
00744 {
00745         return(clusterCom(m_clusters[cluster]));
00746 }
00747 
00748 //
00749 btVector3               btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
00750 {
00751         return(cluster->m_lv+btCross(cluster->m_av,rpos));
00752 }
00753 
00754 //
00755 void                    btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
00756 {
00757         const btVector3 li=cluster->m_imass*impulse;
00758         const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
00759         cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
00760         cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
00761         cluster->m_nvimpulses++;
00762 }
00763 
00764 //
00765 void                    btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
00766 {
00767         const btVector3 li=cluster->m_imass*impulse;
00768         const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
00769         cluster->m_dimpulses[0]+=li;
00770         cluster->m_dimpulses[1]+=ai;
00771         cluster->m_ndimpulses++;
00772 }
00773 
00774 //
00775 void                    btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
00776 {
00777         if(impulse.m_asVelocity)        clusterVImpulse(cluster,rpos,impulse.m_velocity);
00778         if(impulse.m_asDrift)           clusterDImpulse(cluster,rpos,impulse.m_drift);
00779 }
00780 
00781 //
00782 void                    btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
00783 {
00784         const btVector3 ai=cluster->m_invwi*impulse;
00785         cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
00786         cluster->m_nvimpulses++;
00787 }
00788 
00789 //
00790 void                    btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
00791 {
00792         const btVector3 ai=cluster->m_invwi*impulse;
00793         cluster->m_dimpulses[1]+=ai;
00794         cluster->m_ndimpulses++;
00795 }
00796 
00797 //
00798 void                    btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
00799 {
00800         if(impulse.m_asVelocity)        clusterVAImpulse(cluster,impulse.m_velocity);
00801         if(impulse.m_asDrift)           clusterDAImpulse(cluster,impulse.m_drift);
00802 }
00803 
00804 //
00805 void                    btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
00806 {
00807         cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
00808         cluster->m_ndimpulses++;
00809 }
00810 
00811 struct NodeLinks
00812 {
00813     btAlignedObjectArray<int> m_links;
00814 };
00815 
00816 
00817 
00818 //
00819 int                             btSoftBody::generateBendingConstraints(int distance,Material* mat)
00820 {
00821         int i,j;
00822 
00823         if(distance>1)
00824         {
00825                 /* Build graph  */ 
00826                 const int               n=m_nodes.size();
00827                 const unsigned  inf=(~(unsigned)0)>>1;
00828                 unsigned*               adj=new unsigned[n*n];
00829                 
00830 
00831 #define IDX(_x_,_y_)    ((_y_)*n+(_x_))
00832                 for(j=0;j<n;++j)
00833                 {
00834                         for(i=0;i<n;++i)
00835                         {
00836                                 if(i!=j)
00837                                 {
00838                                         adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
00839                                 }
00840                                 else
00841                                 {
00842                                         adj[IDX(i,j)]=adj[IDX(j,i)]=0;
00843                                 }
00844                         }
00845                 }
00846                 for( i=0;i<m_links.size();++i)
00847                 {
00848                         const int       ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
00849                         const int       ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
00850                         adj[IDX(ia,ib)]=1;
00851                         adj[IDX(ib,ia)]=1;
00852                 }
00853 
00854 
00855                 //special optimized case for distance == 2
00856                 if (distance == 2)
00857                 {
00858 
00859                         btAlignedObjectArray<NodeLinks> nodeLinks;
00860 
00861 
00862                         /* Build node links */
00863                         nodeLinks.resize(m_nodes.size());
00864 
00865                         for( i=0;i<m_links.size();++i)
00866                         {
00867                                 const int       ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
00868                                 const int       ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
00869                                 if (nodeLinks[ia].m_links.findLinearSearch(ib)==nodeLinks[ia].m_links.size())
00870                                         nodeLinks[ia].m_links.push_back(ib);
00871 
00872                                 if (nodeLinks[ib].m_links.findLinearSearch(ia)==nodeLinks[ib].m_links.size())
00873                                         nodeLinks[ib].m_links.push_back(ia);
00874                         }
00875                         for (int ii=0;ii<nodeLinks.size();ii++)
00876                         {
00877                                 int i=ii;
00878 
00879                                 for (int jj=0;jj<nodeLinks[ii].m_links.size();jj++)
00880                                 {
00881                                         int k = nodeLinks[ii].m_links[jj];
00882                                         for (int kk=0;kk<nodeLinks[k].m_links.size();kk++)
00883                                         {
00884                                                 int j = nodeLinks[k].m_links[kk];
00885                                                 if (i!=j)
00886                                                 {
00887                                                         const unsigned  sum=adj[IDX(i,k)]+adj[IDX(k,j)];
00888                                                         btAssert(sum==2);
00889                                                         if(adj[IDX(i,j)]>sum)
00890                                                         {
00891                                                                 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
00892                                                         }
00893                                                 }
00894 
00895                                         }
00896                                 }
00897                         }
00898                 } else
00899                 {
00901                         for(int k=0;k<n;++k)
00902                         {
00903                                 for(j=0;j<n;++j)
00904                                 {
00905                                         for(i=j+1;i<n;++i)
00906                                         {
00907                                                 const unsigned  sum=adj[IDX(i,k)]+adj[IDX(k,j)];
00908                                                 if(adj[IDX(i,j)]>sum)
00909                                                 {
00910                                                         adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
00911                                                 }
00912                                         }
00913                                 }
00914                         }
00915                 }
00916 
00917 
00918                 /* Build links  */ 
00919                 int     nlinks=0;
00920                 for(j=0;j<n;++j)
00921                 {
00922                         for(i=j+1;i<n;++i)
00923                         {
00924                                 if(adj[IDX(i,j)]==(unsigned)distance)
00925                                 {
00926                                         appendLink(i,j,mat);
00927                                         m_links[m_links.size()-1].m_bbending=1;
00928                                         ++nlinks;
00929                                 }
00930                         }
00931                 }
00932                 delete[] adj;           
00933                 return(nlinks);
00934         }
00935         return(0);
00936 }
00937 
00938 //
00939 void                    btSoftBody::randomizeConstraints()
00940 {
00941         unsigned long   seed=243703;
00942 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
00943         int i,ni;
00944 
00945         for(i=0,ni=m_links.size();i<ni;++i)
00946         {
00947                 btSwap(m_links[i],m_links[NEXTRAND%ni]);
00948         }
00949         for(i=0,ni=m_faces.size();i<ni;++i)
00950         {
00951                 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
00952         }
00953 #undef NEXTRAND
00954 }
00955 
00956 //
00957 void                    btSoftBody::releaseCluster(int index)
00958 {
00959         Cluster*        c=m_clusters[index];
00960         if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
00961         c->~Cluster();
00962         btAlignedFree(c);
00963         m_clusters.remove(c);
00964 }
00965 
00966 //
00967 void                    btSoftBody::releaseClusters()
00968 {
00969         while(m_clusters.size()>0) releaseCluster(0);
00970 }
00971 
00972 //
00973 int                             btSoftBody::generateClusters(int k,int maxiterations)
00974 {
00975         int i;
00976         releaseClusters();
00977         m_clusters.resize(btMin(k,m_nodes.size()));
00978         for(i=0;i<m_clusters.size();++i)
00979         {
00980                 m_clusters[i]                   =       new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
00981                 m_clusters[i]->m_collide=       true;
00982         }
00983         k=m_clusters.size();
00984         if(k>0)
00985         {
00986                 /* Initialize           */ 
00987                 btAlignedObjectArray<btVector3> centers;
00988                 btVector3                                               cog(0,0,0);
00989                 int                                                             i;
00990                 for(i=0;i<m_nodes.size();++i)
00991                 {
00992                         cog+=m_nodes[i].m_x;
00993                         m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
00994                 }
00995                 cog/=(btScalar)m_nodes.size();
00996                 centers.resize(k,cog);
00997                 /* Iterate                      */ 
00998                 const btScalar  slope=16;
00999                 bool                    changed;
01000                 int                             iterations=0;
01001                 do      {
01002                         const btScalar  w=2-btMin<btScalar>(1,iterations/slope);
01003                         changed=false;
01004                         iterations++;   
01005                         int i;
01006 
01007                         for(i=0;i<k;++i)
01008                         {
01009                                 btVector3       c(0,0,0);
01010                                 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
01011                                 {
01012                                         c+=m_clusters[i]->m_nodes[j]->m_x;
01013                                 }
01014                                 if(m_clusters[i]->m_nodes.size())
01015                                 {
01016                                         c                       /=      (btScalar)m_clusters[i]->m_nodes.size();
01017                                         c                       =       centers[i]+(c-centers[i])*w;
01018                                         changed         |=      ((c-centers[i]).length2()>SIMD_EPSILON);
01019                                         centers[i]      =       c;
01020                                         m_clusters[i]->m_nodes.resize(0);
01021                                 }                       
01022                         }
01023                         for(i=0;i<m_nodes.size();++i)
01024                         {
01025                                 const btVector3 nx=m_nodes[i].m_x;
01026                                 int                             kbest=0;
01027                                 btScalar                kdist=ClusterMetric(centers[0],nx);
01028                                 for(int j=1;j<k;++j)
01029                                 {
01030                                         const btScalar  d=ClusterMetric(centers[j],nx);
01031                                         if(d<kdist)
01032                                         {
01033                                                 kbest=j;
01034                                                 kdist=d;
01035                                         }
01036                                 }
01037                                 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
01038                         }               
01039                 } while(changed&&(iterations<maxiterations));
01040                 /* Merge                */ 
01041                 btAlignedObjectArray<int>       cids;
01042                 cids.resize(m_nodes.size(),-1);
01043                 for(i=0;i<m_clusters.size();++i)
01044                 {
01045                         for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
01046                         {
01047                                 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
01048                         }
01049                 }
01050                 for(i=0;i<m_faces.size();++i)
01051                 {
01052                         const int idx[]={       int(m_faces[i].m_n[0]-&m_nodes[0]),
01053                                 int(m_faces[i].m_n[1]-&m_nodes[0]),
01054                                 int(m_faces[i].m_n[2]-&m_nodes[0])};
01055                         for(int j=0;j<3;++j)
01056                         {
01057                                 const int cid=cids[idx[j]];
01058                                 for(int q=1;q<3;++q)
01059                                 {
01060                                         const int kid=idx[(j+q)%3];
01061                                         if(cids[kid]!=cid)
01062                                         {
01063                                                 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
01064                                                 {
01065                                                         m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
01066                                                 }
01067                                         }
01068                                 }
01069                         }
01070                 }
01071                 /* Master               */ 
01072                 if(m_clusters.size()>1)
01073                 {
01074                         Cluster*        pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
01075                         pmaster->m_collide      =       false;
01076                         pmaster->m_nodes.reserve(m_nodes.size());
01077                         for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
01078                         m_clusters.push_back(pmaster);
01079                         btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
01080                 }
01081                 /* Terminate    */ 
01082                 for(i=0;i<m_clusters.size();++i)
01083                 {
01084                         if(m_clusters[i]->m_nodes.size()==0)
01085                         {
01086                                 releaseCluster(i--);
01087                         }
01088                 }
01089         } else
01090         {
01091                 //create a cluster for each tetrahedron (if tetrahedra exist) or each face
01092                 if (m_tetras.size())
01093                 {
01094                         m_clusters.resize(m_tetras.size());
01095                         for(i=0;i<m_clusters.size();++i)
01096                         {
01097                                 m_clusters[i]                   =       new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
01098                                 m_clusters[i]->m_collide=       true;
01099                         }
01100                         for (i=0;i<m_tetras.size();i++)
01101                         {
01102                                 for (int j=0;j<4;j++)
01103                                 {
01104                                         m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
01105                                 }
01106                         }
01107 
01108                 } else
01109                 {
01110                         m_clusters.resize(m_faces.size());
01111                         for(i=0;i<m_clusters.size();++i)
01112                         {
01113                                 m_clusters[i]                   =       new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
01114                                 m_clusters[i]->m_collide=       true;
01115                         }
01116 
01117                         for(i=0;i<m_faces.size();++i)
01118                         {
01119                                 for(int j=0;j<3;++j)
01120                                 {
01121                                         m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
01122                                 }
01123                         }
01124                 }
01125         }
01126 
01127         if (m_clusters.size())
01128         {
01129                 initializeClusters();
01130                 updateClusters();
01131 
01132 
01133                 //for self-collision
01134                 m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
01135                 {
01136                         for (int c0=0;c0<m_clusters.size();c0++)
01137                         {
01138                                 m_clusters[c0]->m_clusterIndex=c0;
01139                                 for (int c1=0;c1<m_clusters.size();c1++)
01140                                 {
01141                                         
01142                                         bool connected=false;
01143                                         Cluster* cla = m_clusters[c0];
01144                                         Cluster* clb = m_clusters[c1];
01145                                         for (int i=0;!connected&&i<cla->m_nodes.size();i++)
01146                                         {
01147                                                 for (int j=0;j<clb->m_nodes.size();j++)
01148                                                 {
01149                                                         if (cla->m_nodes[i] == clb->m_nodes[j])
01150                                                         {
01151                                                                 connected=true;
01152                                                                 break;
01153                                                         }
01154                                                 }
01155                                         }
01156                                         m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
01157                                 }
01158                         }
01159                 }
01160         }
01161 
01162         return(m_clusters.size());
01163 }
01164 
01165 //
01166 void                    btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
01167 {
01168         const Node*                     nbase = &m_nodes[0];
01169         int                                     ncount = m_nodes.size();
01170         btSymMatrix<int>        edges(ncount,-2);
01171         int                                     newnodes=0;
01172         int i,j,k,ni;
01173 
01174         /* Filter out           */ 
01175         for(i=0;i<m_links.size();++i)
01176         {
01177                 Link&   l=m_links[i];
01178                 if(l.m_bbending)
01179                 {
01180                         if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
01181                         {
01182                                 btSwap(m_links[i],m_links[m_links.size()-1]);
01183                                 m_links.pop_back();--i;
01184                         }
01185                 }       
01186         }
01187         /* Fill edges           */ 
01188         for(i=0;i<m_links.size();++i)
01189         {
01190                 Link&   l=m_links[i];
01191                 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
01192         }
01193         for(i=0;i<m_faces.size();++i)
01194         {       
01195                 Face&   f=m_faces[i];
01196                 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
01197                 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
01198                 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
01199         }
01200         /* Intersect            */ 
01201         for(i=0;i<ncount;++i)
01202         {
01203                 for(j=i+1;j<ncount;++j)
01204                 {
01205                         if(edges(i,j)==-1)
01206                         {
01207                                 Node&                   a=m_nodes[i];
01208                                 Node&                   b=m_nodes[j];
01209                                 const btScalar  t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
01210                                 if(t>0)
01211                                 {
01212                                         const btVector3 x=Lerp(a.m_x,b.m_x,t);
01213                                         const btVector3 v=Lerp(a.m_v,b.m_v,t);
01214                                         btScalar                m=0;
01215                                         if(a.m_im>0)
01216                                         {
01217                                                 if(b.m_im>0)
01218                                                 {
01219                                                         const btScalar  ma=1/a.m_im;
01220                                                         const btScalar  mb=1/b.m_im;
01221                                                         const btScalar  mc=Lerp(ma,mb,t);
01222                                                         const btScalar  f=(ma+mb)/(ma+mb+mc);
01223                                                         a.m_im=1/(ma*f);
01224                                                         b.m_im=1/(mb*f);
01225                                                         m=mc*f;
01226                                                 }
01227                                                 else
01228                                                 { a.m_im/=0.5;m=1/a.m_im; }
01229                                         }
01230                                         else
01231                                         {
01232                                                 if(b.m_im>0)
01233                                                 { b.m_im/=0.5;m=1/b.m_im; }
01234                                                 else
01235                                                         m=0;
01236                                         }
01237                                         appendNode(x,m);
01238                                         edges(i,j)=m_nodes.size()-1;
01239                                         m_nodes[edges(i,j)].m_v=v;
01240                                         ++newnodes;
01241                                 }
01242                         }
01243                 }
01244         }
01245         nbase=&m_nodes[0];
01246         /* Refine links         */ 
01247         for(i=0,ni=m_links.size();i<ni;++i)
01248         {
01249                 Link&           feat=m_links[i];
01250                 const int       idx[]={ int(feat.m_n[0]-nbase),
01251                         int(feat.m_n[1]-nbase)};
01252                 if((idx[0]<ncount)&&(idx[1]<ncount))
01253                 {
01254                         const int ni=edges(idx[0],idx[1]);
01255                         if(ni>0)
01256                         {
01257                                 appendLink(i);
01258                                 Link*           pft[]={ &m_links[i],
01259                                         &m_links[m_links.size()-1]};                    
01260                                 pft[0]->m_n[0]=&m_nodes[idx[0]];
01261                                 pft[0]->m_n[1]=&m_nodes[ni];
01262                                 pft[1]->m_n[0]=&m_nodes[ni];
01263                                 pft[1]->m_n[1]=&m_nodes[idx[1]];
01264                         }
01265                 }
01266         }
01267         /* Refine faces         */ 
01268         for(i=0;i<m_faces.size();++i)
01269         {
01270                 const Face&     feat=m_faces[i];
01271                 const int       idx[]={ int(feat.m_n[0]-nbase),
01272                         int(feat.m_n[1]-nbase),
01273                         int(feat.m_n[2]-nbase)};
01274                 for(j=2,k=0;k<3;j=k++)
01275                 {
01276                         if((idx[j]<ncount)&&(idx[k]<ncount))
01277                         {
01278                                 const int ni=edges(idx[j],idx[k]);
01279                                 if(ni>0)
01280                                 {
01281                                         appendFace(i);
01282                                         const int       l=(k+1)%3;
01283                                         Face*           pft[]={ &m_faces[i],
01284                                                 &m_faces[m_faces.size()-1]};
01285                                         pft[0]->m_n[0]=&m_nodes[idx[l]];
01286                                         pft[0]->m_n[1]=&m_nodes[idx[j]];
01287                                         pft[0]->m_n[2]=&m_nodes[ni];
01288                                         pft[1]->m_n[0]=&m_nodes[ni];
01289                                         pft[1]->m_n[1]=&m_nodes[idx[k]];
01290                                         pft[1]->m_n[2]=&m_nodes[idx[l]];
01291                                         appendLink(ni,idx[l],pft[0]->m_material);
01292                                         --i;break;
01293                                 }
01294                         }
01295                 }
01296         }
01297         /* Cut                          */ 
01298         if(cut)
01299         {       
01300                 btAlignedObjectArray<int>       cnodes;
01301                 const int                                       pcount=ncount;
01302                 int                                                     i;
01303                 ncount=m_nodes.size();
01304                 cnodes.resize(ncount,0);
01305                 /* Nodes                */ 
01306                 for(i=0;i<ncount;++i)
01307                 {
01308                         const btVector3 x=m_nodes[i].m_x;
01309                         if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
01310                         {
01311                                 const btVector3 v=m_nodes[i].m_v;
01312                                 btScalar                m=getMass(i);
01313                                 if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
01314                                 appendNode(x,m);
01315                                 cnodes[i]=m_nodes.size()-1;
01316                                 m_nodes[cnodes[i]].m_v=v;
01317                         }
01318                 }
01319                 nbase=&m_nodes[0];
01320                 /* Links                */ 
01321                 for(i=0,ni=m_links.size();i<ni;++i)
01322                 {
01323                         const int               id[]={  int(m_links[i].m_n[0]-nbase),
01324                                 int(m_links[i].m_n[1]-nbase)};
01325                         int                             todetach=0;
01326                         if(cnodes[id[0]]&&cnodes[id[1]])
01327                         {
01328                                 appendLink(i);
01329                                 todetach=m_links.size()-1;
01330                         }
01331                         else
01332                         {
01333                                 if((    (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
01334                                         (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
01335                                         todetach=i;
01336                         }
01337                         if(todetach)
01338                         {
01339                                 Link&   l=m_links[todetach];
01340                                 for(int j=0;j<2;++j)
01341                                 {
01342                                         int cn=cnodes[int(l.m_n[j]-nbase)];
01343                                         if(cn) l.m_n[j]=&m_nodes[cn];
01344                                 }                       
01345                         }
01346                 }
01347                 /* Faces                */ 
01348                 for(i=0,ni=m_faces.size();i<ni;++i)
01349                 {
01350                         Node**                  n=      m_faces[i].m_n;
01351                         if(     (ifn->Eval(n[0]->m_x)<accurary)&&
01352                                 (ifn->Eval(n[1]->m_x)<accurary)&&
01353                                 (ifn->Eval(n[2]->m_x)<accurary))
01354                         {
01355                                 for(int j=0;j<3;++j)
01356                                 {
01357                                         int cn=cnodes[int(n[j]-nbase)];
01358                                         if(cn) n[j]=&m_nodes[cn];
01359                                 }
01360                         }
01361                 }
01362                 /* Clean orphans        */ 
01363                 int                                                     nnodes=m_nodes.size();
01364                 btAlignedObjectArray<int>       ranks;
01365                 btAlignedObjectArray<int>       todelete;
01366                 ranks.resize(nnodes,0);
01367                 for(i=0,ni=m_links.size();i<ni;++i)
01368                 {
01369                         for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
01370                 }
01371                 for(i=0,ni=m_faces.size();i<ni;++i)
01372                 {
01373                         for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
01374                 }
01375                 for(i=0;i<m_links.size();++i)
01376                 {
01377                         const int       id[]={  int(m_links[i].m_n[0]-nbase),
01378                                 int(m_links[i].m_n[1]-nbase)};
01379                         const bool      sg[]={  ranks[id[0]]==1,
01380                                 ranks[id[1]]==1};
01381                         if(sg[0]||sg[1])
01382                         {
01383                                 --ranks[id[0]];
01384                                 --ranks[id[1]];
01385                                 btSwap(m_links[i],m_links[m_links.size()-1]);
01386                                 m_links.pop_back();--i;
01387                         }
01388                 }
01389 #if 0   
01390                 for(i=nnodes-1;i>=0;--i)
01391                 {
01392                         if(!ranks[i]) todelete.push_back(i);
01393                 }       
01394                 if(todelete.size())
01395                 {               
01396                         btAlignedObjectArray<int>&      map=ranks;
01397                         for(int i=0;i<nnodes;++i) map[i]=i;
01398                         PointersToIndices(this);
01399                         for(int i=0,ni=todelete.size();i<ni;++i)
01400                         {
01401                                 int             j=todelete[i];
01402                                 int&    a=map[j];
01403                                 int&    b=map[--nnodes];
01404                                 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
01405                                 btSwap(m_nodes[a],m_nodes[b]);
01406                                 j=a;a=b;b=j;                    
01407                         }
01408                         IndicesToPointers(this,&map[0]);
01409                         m_nodes.resize(nnodes);
01410                 }
01411 #endif
01412         }
01413         m_bUpdateRtCst=true;
01414 }
01415 
01416 //
01417 bool                    btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
01418 {
01419         return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
01420 }
01421 
01422 //
01423 bool                    btSoftBody::cutLink(int node0,int node1,btScalar position)
01424 {
01425         bool                    done=false;
01426         int i,ni;
01427         const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
01428         const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
01429         const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
01430         const btScalar  m=1;
01431         appendNode(x,m);
01432         appendNode(x,m);
01433         Node*                   pa=&m_nodes[node0];
01434         Node*                   pb=&m_nodes[node1];
01435         Node*                   pn[2]={ &m_nodes[m_nodes.size()-2],
01436                 &m_nodes[m_nodes.size()-1]};
01437         pn[0]->m_v=v;
01438         pn[1]->m_v=v;
01439         for(i=0,ni=m_links.size();i<ni;++i)
01440         {
01441                 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
01442                 if(mtch!=-1)
01443                 {
01444                         appendLink(i);
01445                         Link*   pft[]={&m_links[i],&m_links[m_links.size()-1]};
01446                         pft[0]->m_n[1]=pn[mtch];
01447                         pft[1]->m_n[0]=pn[1-mtch];
01448                         done=true;
01449                 }
01450         }
01451         for(i=0,ni=m_faces.size();i<ni;++i)
01452         {
01453                 for(int k=2,l=0;l<3;k=l++)
01454                 {
01455                         const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
01456                         if(mtch!=-1)
01457                         {
01458                                 appendFace(i);
01459                                 Face*   pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
01460                                 pft[0]->m_n[l]=pn[mtch];
01461                                 pft[1]->m_n[k]=pn[1-mtch];
01462                                 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
01463                                 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
01464                         }
01465                 }
01466         }
01467         if(!done)
01468         {
01469                 m_ndbvt.remove(pn[0]->m_leaf);
01470                 m_ndbvt.remove(pn[1]->m_leaf);
01471                 m_nodes.pop_back();
01472                 m_nodes.pop_back();
01473         }
01474         return(done);
01475 }
01476 
01477 //
01478 bool                    btSoftBody::rayTest(const btVector3& rayFrom,
01479                                                                         const btVector3& rayTo,
01480                                                                         sRayCast& results)
01481 {
01482         if(m_faces.size()&&m_fdbvt.empty()) 
01483                 initializeFaceTree();
01484 
01485         results.body    =       this;
01486         results.fraction = 1.f;
01487         results.feature =       eFeature::None;
01488         results.index   =       -1;
01489 
01490         return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
01491 }
01492 
01493 //
01494 void                    btSoftBody::setSolver(eSolverPresets::_ preset)
01495 {
01496         m_cfg.m_vsequence.clear();
01497         m_cfg.m_psequence.clear();
01498         m_cfg.m_dsequence.clear();
01499         switch(preset)
01500         {
01501         case    eSolverPresets::Positions:
01502                 m_cfg.m_psequence.push_back(ePSolver::Anchors);
01503                 m_cfg.m_psequence.push_back(ePSolver::RContacts);
01504                 m_cfg.m_psequence.push_back(ePSolver::SContacts);
01505                 m_cfg.m_psequence.push_back(ePSolver::Linear);  
01506                 break;  
01507         case    eSolverPresets::Velocities:
01508                 m_cfg.m_vsequence.push_back(eVSolver::Linear);
01509 
01510                 m_cfg.m_psequence.push_back(ePSolver::Anchors);
01511                 m_cfg.m_psequence.push_back(ePSolver::RContacts);
01512                 m_cfg.m_psequence.push_back(ePSolver::SContacts);
01513 
01514                 m_cfg.m_dsequence.push_back(ePSolver::Linear);
01515                 break;
01516         }
01517 }
01518 
01519 //
01520 void                    btSoftBody::predictMotion(btScalar dt)
01521 {
01522 
01523         int i,ni;
01524 
01525         /* Update                               */ 
01526         if(m_bUpdateRtCst)
01527         {
01528                 m_bUpdateRtCst=false;
01529                 updateConstants();
01530                 m_fdbvt.clear();
01531                 if(m_cfg.collisions&fCollision::VF_SS)
01532                 {
01533                         initializeFaceTree();                   
01534                 }
01535         }
01536 
01537         /* Prepare                              */ 
01538         m_sst.sdt               =       dt*m_cfg.timescale;
01539         m_sst.isdt              =       1/m_sst.sdt;
01540         m_sst.velmrg    =       m_sst.sdt*3;
01541         m_sst.radmrg    =       getCollisionShape()->getMargin();
01542         m_sst.updmrg    =       m_sst.radmrg*(btScalar)0.25;
01543         /* Forces                               */ 
01544         addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
01545         applyForces();
01546         /* Integrate                    */ 
01547         for(i=0,ni=m_nodes.size();i<ni;++i)
01548         {
01549                 Node&   n=m_nodes[i];
01550                 n.m_q   =       n.m_x;
01551                 n.m_v   +=      n.m_f*n.m_im*m_sst.sdt;
01552                 n.m_x   +=      n.m_v*m_sst.sdt;
01553                 n.m_f   =       btVector3(0,0,0);
01554         }
01555         /* Clusters                             */ 
01556         updateClusters();
01557         /* Bounds                               */ 
01558         updateBounds(); 
01559         /* Nodes                                */ 
01560         ATTRIBUTE_ALIGNED16(btDbvtVolume)       vol;
01561         for(i=0,ni=m_nodes.size();i<ni;++i)
01562         {
01563                 Node&   n=m_nodes[i];
01564                 vol = btDbvtVolume::FromCR(n.m_x,m_sst.radmrg);
01565                 m_ndbvt.update( n.m_leaf,
01566                         vol,
01567                         n.m_v*m_sst.velmrg,
01568                         m_sst.updmrg);
01569         }
01570         /* Faces                                */ 
01571         if(!m_fdbvt.empty())
01572         {
01573                 for(int i=0;i<m_faces.size();++i)
01574                 {
01575                         Face&                   f=m_faces[i];
01576                         const btVector3 v=(     f.m_n[0]->m_v+
01577                                 f.m_n[1]->m_v+
01578                                 f.m_n[2]->m_v)/3;
01579                         vol = VolumeOf(f,m_sst.radmrg);
01580                         m_fdbvt.update( f.m_leaf,
01581                                 vol,
01582                                 v*m_sst.velmrg,
01583                                 m_sst.updmrg);
01584                 }
01585         }
01586         /* Pose                                 */ 
01587         updatePose();
01588         /* Match                                */ 
01589         if(m_pose.m_bframe&&(m_cfg.kMT>0))
01590         {
01591                 const btMatrix3x3       posetrs=m_pose.m_rot;
01592                 for(int i=0,ni=m_nodes.size();i<ni;++i)
01593                 {
01594                         Node&   n=m_nodes[i];
01595                         if(n.m_im>0)
01596                         {
01597                                 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
01598                                 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
01599                         }
01600                 }
01601         }
01602         /* Clear contacts               */ 
01603         m_rcontacts.resize(0);
01604         m_scontacts.resize(0);
01605         /* Optimize dbvt's              */ 
01606         m_ndbvt.optimizeIncremental(1);
01607         m_fdbvt.optimizeIncremental(1);
01608         m_cdbvt.optimizeIncremental(1);
01609 }
01610 
01611 //
01612 void                    btSoftBody::solveConstraints()
01613 {
01614 
01615         /* Apply clusters               */ 
01616         applyClusters(false);
01617         /* Prepare links                */ 
01618 
01619         int i,ni;
01620 
01621         for(i=0,ni=m_links.size();i<ni;++i)
01622         {
01623                 Link&   l=m_links[i];
01624                 l.m_c3          =       l.m_n[1]->m_q-l.m_n[0]->m_q;
01625                 l.m_c2          =       1/(l.m_c3.length2()*l.m_c0);
01626         }
01627         /* Prepare anchors              */ 
01628         for(i=0,ni=m_anchors.size();i<ni;++i)
01629         {
01630                 Anchor&                 a=m_anchors[i];
01631                 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
01632                 a.m_c0  =       ImpulseMatrix(  m_sst.sdt,
01633                         a.m_node->m_im,
01634                         a.m_body->getInvMass(),
01635                         a.m_body->getInvInertiaTensorWorld(),
01636                         ra);
01637                 a.m_c1  =       ra;
01638                 a.m_c2  =       m_sst.sdt*a.m_node->m_im;
01639                 a.m_body->activate();
01640         }
01641         /* Solve velocities             */ 
01642         if(m_cfg.viterations>0)
01643         {
01644                 /* Solve                        */ 
01645                 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
01646                 {
01647                         for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
01648                         {
01649                                 getSolver(m_cfg.m_vsequence[iseq])(this,1);
01650                         }
01651                 }
01652                 /* Update                       */ 
01653                 for(i=0,ni=m_nodes.size();i<ni;++i)
01654                 {
01655                         Node&   n=m_nodes[i];
01656                         n.m_x   =       n.m_q+n.m_v*m_sst.sdt;
01657                 }
01658         }
01659         /* Solve positions              */ 
01660         if(m_cfg.piterations>0)
01661         {
01662                 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
01663                 {
01664                         const btScalar ti=isolve/(btScalar)m_cfg.piterations;
01665                         for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
01666                         {
01667                                 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
01668                         }
01669                 }
01670                 const btScalar  vc=m_sst.isdt*(1-m_cfg.kDP);
01671                 for(i=0,ni=m_nodes.size();i<ni;++i)
01672                 {
01673                         Node&   n=m_nodes[i];
01674                         n.m_v   =       (n.m_x-n.m_q)*vc;
01675                         n.m_f   =       btVector3(0,0,0);               
01676                 }
01677         }
01678         /* Solve drift                  */ 
01679         if(m_cfg.diterations>0)
01680         {
01681                 const btScalar  vcf=m_cfg.kVCF*m_sst.isdt;
01682                 for(i=0,ni=m_nodes.size();i<ni;++i)
01683                 {
01684                         Node&   n=m_nodes[i];
01685                         n.m_q   =       n.m_x;
01686                 }
01687                 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
01688                 {
01689                         for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
01690                         {
01691                                 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
01692                         }
01693                 }
01694                 for(int i=0,ni=m_nodes.size();i<ni;++i)
01695                 {
01696                         Node&   n=m_nodes[i];
01697                         n.m_v   +=      (n.m_x-n.m_q)*vcf;
01698                 }
01699         }
01700         /* Apply clusters               */ 
01701         dampClusters();
01702         applyClusters(true);
01703 }
01704 
01705 //
01706 void                    btSoftBody::staticSolve(int iterations)
01707 {
01708         for(int isolve=0;isolve<iterations;++isolve)
01709         {
01710                 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
01711                 {
01712                         getSolver(m_cfg.m_psequence[iseq])(this,1,0);
01713                 }
01714         }
01715 }
01716 
01717 //
01718 void                    btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
01719 {
01721 }
01722 
01723 //
01724 void                    btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
01725 {
01726         const int       nb=bodies.size();
01727         int                     iterations=0;
01728         int i;
01729 
01730         for(i=0;i<nb;++i)
01731         {
01732                 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
01733         }
01734         for(i=0;i<nb;++i)
01735         {
01736                 bodies[i]->prepareClusters(iterations);
01737         }
01738         for(i=0;i<iterations;++i)
01739         {
01740                 const btScalar sor=1;
01741                 for(int j=0;j<nb;++j)
01742                 {
01743                         bodies[j]->solveClusters(sor);
01744                 }
01745         }
01746         for(i=0;i<nb;++i)
01747         {
01748                 bodies[i]->cleanupClusters();
01749         }
01750 }
01751 
01752 //
01753 void                    btSoftBody::integrateMotion()
01754 {
01755         /* Update                       */ 
01756         updateNormals();
01757 }
01758 
01759 //
01760 btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
01761 {
01762         m_rayFrom = rayFrom;
01763         m_rayNormalizedDirection = (rayTo-rayFrom);
01764         m_rayTo = rayTo;
01765         m_mint  =       mxt;
01766         m_face  =       0;
01767         m_tests =       0;
01768 }
01769 
01770 //
01771 void                            btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
01772 {
01773         btSoftBody::Face&       f=*(btSoftBody::Face*)leaf->data;
01774         const btScalar          t=rayFromToTriangle(    m_rayFrom,m_rayTo,m_rayNormalizedDirection,
01775                 f.m_n[0]->m_x,
01776                 f.m_n[1]->m_x,
01777                 f.m_n[2]->m_x,
01778                 m_mint);
01779         if((t>0)&&(t<m_mint)) 
01780         { 
01781                 m_mint=t;m_face=&f; 
01782         }
01783         ++m_tests;
01784 }
01785 
01786 //
01787 btScalar                        btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayFrom,
01788                                                                                                                                    const btVector3& rayTo,
01789                                                                                                                                    const btVector3& rayNormalizedDirection,
01790                                                                                                                                    const btVector3& a,
01791                                                                                                                                    const btVector3& b,
01792                                                                                                                                    const btVector3& c,
01793                                                                                                                                    btScalar maxt)
01794 {
01795         static const btScalar   ceps=-SIMD_EPSILON*10;
01796         static const btScalar   teps=SIMD_EPSILON*10;
01797 
01798         const btVector3                 n=btCross(b-a,c-a);
01799         const btScalar                  d=btDot(a,n);
01800         const btScalar                  den=btDot(rayNormalizedDirection,n);
01801         if(!btFuzzyZero(den))
01802         {
01803                 const btScalar          num=btDot(rayFrom,n)-d;
01804                 const btScalar          t=-num/den;
01805                 if((t>teps)&&(t<maxt))
01806                 {
01807                         const btVector3 hit=rayFrom+rayNormalizedDirection*t;
01808                         if(     (btDot(n,btCross(a-hit,b-hit))>ceps)    &&                      
01809                                 (btDot(n,btCross(b-hit,c-hit))>ceps)    &&
01810                                 (btDot(n,btCross(c-hit,a-hit))>ceps))
01811                         {
01812                                 return(t);
01813                         }
01814                 }
01815         }
01816         return(-1);
01817 }
01818 
01819 //
01820 void                            btSoftBody::pointersToIndices()
01821 {
01822 #define PTR2IDX(_p_,_b_)        reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
01823         btSoftBody::Node*       base=&m_nodes[0];
01824         int i,ni;
01825 
01826         for(i=0,ni=m_nodes.size();i<ni;++i)
01827         {
01828                 if(m_nodes[i].m_leaf)
01829                 {
01830                         m_nodes[i].m_leaf->data=*(void**)&i;
01831                 }
01832         }
01833         for(i=0,ni=m_links.size();i<ni;++i)
01834         {
01835                 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
01836                 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
01837         }
01838         for(i=0,ni=m_faces.size();i<ni;++i)
01839         {
01840                 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
01841                 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
01842                 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
01843                 if(m_faces[i].m_leaf)
01844                 {
01845                         m_faces[i].m_leaf->data=*(void**)&i;
01846                 }
01847         }
01848         for(i=0,ni=m_anchors.size();i<ni;++i)
01849         {
01850                 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
01851         }
01852         for(i=0,ni=m_notes.size();i<ni;++i)
01853         {
01854                 for(int j=0;j<m_notes[i].m_rank;++j)
01855                 {
01856                         m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
01857                 }
01858         }
01859 #undef  PTR2IDX
01860 }
01861 
01862 //
01863 void                            btSoftBody::indicesToPointers(const int* map)
01864 {
01865 #define IDX2PTR(_p_,_b_)        map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]):     \
01866         (&(_b_)[(((char*)_p_)-(char*)0)])
01867         btSoftBody::Node*       base=&m_nodes[0];
01868         int i,ni;
01869 
01870         for(i=0,ni=m_nodes.size();i<ni;++i)
01871         {
01872                 if(m_nodes[i].m_leaf)
01873                 {
01874                         m_nodes[i].m_leaf->data=&m_nodes[i];
01875                 }
01876         }
01877         for(i=0,ni=m_links.size();i<ni;++i)
01878         {
01879                 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
01880                 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
01881         }
01882         for(i=0,ni=m_faces.size();i<ni;++i)
01883         {
01884                 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
01885                 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
01886                 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
01887                 if(m_faces[i].m_leaf)
01888                 {
01889                         m_faces[i].m_leaf->data=&m_faces[i];
01890                 }
01891         }
01892         for(i=0,ni=m_anchors.size();i<ni;++i)
01893         {
01894                 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
01895         }
01896         for(i=0,ni=m_notes.size();i<ni;++i)
01897         {
01898                 for(int j=0;j<m_notes[i].m_rank;++j)
01899                 {
01900                         m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
01901                 }
01902         }
01903 #undef  IDX2PTR
01904 }
01905 
01906 //
01907 int                                     btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
01908                                                                                 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
01909 {
01910         int     cnt=0;
01911         if(bcountonly||m_fdbvt.empty())
01912         {/* Full search */ 
01913                 btVector3 dir = rayTo-rayFrom;
01914                 dir.normalize();
01915 
01916                 for(int i=0,ni=m_faces.size();i<ni;++i)
01917                 {
01918                         const btSoftBody::Face& f=m_faces[i];
01919 
01920                         const btScalar                  t=RayFromToCaster::rayFromToTriangle(   rayFrom,rayTo,dir,
01921                                 f.m_n[0]->m_x,
01922                                 f.m_n[1]->m_x,
01923                                 f.m_n[2]->m_x,
01924                                 mint);
01925                         if(t>0)
01926                         {
01927                                 ++cnt;
01928                                 if(!bcountonly)
01929                                 {
01930                                         feature=btSoftBody::eFeature::Face;
01931                                         index=i;
01932                                         mint=t;
01933                                 }
01934                         }
01935                 }
01936         }
01937         else
01938         {/* Use dbvt    */ 
01939                 RayFromToCaster collider(rayFrom,rayTo,mint);
01940 
01941                 btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
01942                 if(collider.m_face)
01943                 {
01944                         mint=collider.m_mint;
01945                         feature=btSoftBody::eFeature::Face;
01946                         index=(int)(collider.m_face-&m_faces[0]);
01947                         cnt=1;
01948                 }
01949         }
01950         return(cnt);
01951 }
01952 
01953 //
01954 void                    btSoftBody::initializeFaceTree()
01955 {
01956         m_fdbvt.clear();
01957         for(int i=0;i<m_faces.size();++i)
01958         {
01959                 Face&   f=m_faces[i];
01960                 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
01961         }
01962 }
01963 
01964 //
01965 btVector3               btSoftBody::evaluateCom() const
01966 {
01967         btVector3       com(0,0,0);
01968         if(m_pose.m_bframe)
01969         {
01970                 for(int i=0,ni=m_nodes.size();i<ni;++i)
01971                 {
01972                         com+=m_nodes[i].m_x*m_pose.m_wgh[i];
01973                 }
01974         }
01975         return(com);
01976 }
01977 
01978 //
01979 bool                            btSoftBody::checkContact(       btCollisionObject* colObj,
01980                                                                                          const btVector3& x,
01981                                                                                          btScalar margin,
01982                                                                                          btSoftBody::sCti& cti) const
01983 {
01984         btVector3 nrm;
01985         btCollisionShape *shp = colObj->getCollisionShape();
01986         btRigidBody *tmpRigid = btRigidBody::upcast(colObj);
01987         const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObj->getWorldTransform();
01988         btScalar dst = 
01989                 m_worldInfo->m_sparsesdf.Evaluate(      
01990                         wtr.invXform(x),
01991                         shp,
01992                         nrm,
01993                         margin);
01994         if(dst<0)
01995         {
01996                 cti.m_colObj = colObj;
01997                 cti.m_normal = wtr.getBasis()*nrm;
01998                 cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst );
01999                 return(true);
02000         }
02001         return(false);
02002 }
02003 
02004 //
02005 void                                    btSoftBody::updateNormals()
02006 {
02007 
02008         const btVector3 zv(0,0,0);
02009         int i,ni;
02010 
02011         for(i=0,ni=m_nodes.size();i<ni;++i)
02012         {
02013                 m_nodes[i].m_n=zv;
02014         }
02015         for(i=0,ni=m_faces.size();i<ni;++i)
02016         {
02017                 btSoftBody::Face&       f=m_faces[i];
02018                 const btVector3         n=btCross(f.m_n[1]->m_x-f.m_n[0]->m_x,
02019                         f.m_n[2]->m_x-f.m_n[0]->m_x);
02020                 f.m_normal=n.normalized();
02021                 f.m_n[0]->m_n+=n;
02022                 f.m_n[1]->m_n+=n;
02023                 f.m_n[2]->m_n+=n;
02024         }
02025         for(i=0,ni=m_nodes.size();i<ni;++i)
02026         {
02027                 btScalar len = m_nodes[i].m_n.length();
02028                 if (len>SIMD_EPSILON)
02029                         m_nodes[i].m_n /= len;
02030         }
02031 }
02032 
02033 //
02034 void                                    btSoftBody::updateBounds()
02035 {
02036         /*if( m_acceleratedSoftBody )
02037         {
02038                 // If we have an accelerated softbody we need to obtain the bounds correctly
02039                 // For now (slightly hackily) just have a very large AABB
02040                 // TODO: Write get bounds kernel
02041                 // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
02042                 // probably do a test and exchange reasonably efficiently.
02043 
02044                 m_bounds[0] = btVector3(-1000, -1000, -1000);
02045                 m_bounds[1] = btVector3(1000, 1000, 1000);
02046 
02047         } else {*/
02048                 if(m_ndbvt.m_root)
02049                 {
02050                         const btVector3&        mins=m_ndbvt.m_root->volume.Mins();
02051                         const btVector3&        maxs=m_ndbvt.m_root->volume.Maxs();
02052                         const btScalar          csm=getCollisionShape()->getMargin();
02053                         const btVector3         mrg=btVector3(  csm,
02054                                 csm,
02055                                 csm)*1; // ??? to investigate...
02056                         m_bounds[0]=mins-mrg;
02057                         m_bounds[1]=maxs+mrg;
02058                         if(0!=getBroadphaseHandle())
02059                         {                                       
02060                                 m_worldInfo->m_broadphase->setAabb(     getBroadphaseHandle(),
02061                                         m_bounds[0],
02062                                         m_bounds[1],
02063                                         m_worldInfo->m_dispatcher);
02064                         }
02065                 }
02066                 else
02067                 {
02068                         m_bounds[0]=
02069                                 m_bounds[1]=btVector3(0,0,0);
02070                 }               
02071         //}
02072 }
02073 
02074 
02075 //
02076 void                                    btSoftBody::updatePose()
02077 {
02078         if(m_pose.m_bframe)
02079         {
02080                 btSoftBody::Pose&       pose=m_pose;
02081                 const btVector3         com=evaluateCom();
02082                 /* Com                  */ 
02083                 pose.m_com      =       com;
02084                 /* Rotation             */ 
02085                 btMatrix3x3             Apq;
02086                 const btScalar  eps=SIMD_EPSILON;
02087                 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
02088                 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
02089                 for(int i=0,ni=m_nodes.size();i<ni;++i)
02090                 {
02091                         const btVector3         a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
02092                         const btVector3&        b=pose.m_pos[i];
02093                         Apq[0]+=a.x()*b;
02094                         Apq[1]+=a.y()*b;
02095                         Apq[2]+=a.z()*b;
02096                 }
02097                 btMatrix3x3             r,s;
02098                 PolarDecompose(Apq,r,s);
02099                 pose.m_rot=r;
02100                 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
02101                 if(m_cfg.maxvolume>1)
02102                 {
02103                         const btScalar  idet=Clamp<btScalar>(   1/pose.m_scl.determinant(),
02104                                 1,m_cfg.maxvolume);
02105                         pose.m_scl=Mul(pose.m_scl,idet);
02106                 }
02107 
02108         }
02109 }
02110 
02111 //
02112 void                            btSoftBody::updateConstants()
02113 {
02114         int i,ni;
02115 
02116         /* Links                */ 
02117         for(i=0,ni=m_links.size();i<ni;++i)
02118         {
02119                 Link&           l=m_links[i];
02120                 Material&       m=*l.m_material;
02121                 l.m_rl  =       (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
02122                 l.m_c0  =       (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
02123                 l.m_c1  =       l.m_rl*l.m_rl;
02124         }
02125         /* Faces                */ 
02126         for(i=0,ni=m_faces.size();i<ni;++i)
02127         {
02128                 Face&           f=m_faces[i];
02129                 f.m_ra  =       AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
02130         }
02131         /* Area's               */ 
02132         btAlignedObjectArray<int>       counts;
02133         counts.resize(m_nodes.size(),0);
02134         for(i=0,ni=m_nodes.size();i<ni;++i)
02135         {
02136                 m_nodes[i].m_area       =       0;
02137         }
02138         for(i=0,ni=m_faces.size();i<ni;++i)
02139         {
02140                 btSoftBody::Face&       f=m_faces[i];
02141                 for(int j=0;j<3;++j)
02142                 {
02143                         const int index=(int)(f.m_n[j]-&m_nodes[0]);
02144                         counts[index]++;
02145                         f.m_n[j]->m_area+=btFabs(f.m_ra);
02146                 }
02147         }
02148         for(i=0,ni=m_nodes.size();i<ni;++i)
02149         {
02150                 if(counts[i]>0)
02151                         m_nodes[i].m_area/=(btScalar)counts[i];
02152                 else
02153                         m_nodes[i].m_area=0;
02154         }
02155 }
02156 
02157 //
02158 void                                    btSoftBody::initializeClusters()
02159 {
02160         int i;
02161 
02162         for( i=0;i<m_clusters.size();++i)
02163         {
02164                 Cluster&        c=*m_clusters[i];
02165                 c.m_imass=0;
02166                 c.m_masses.resize(c.m_nodes.size());
02167                 for(int j=0;j<c.m_nodes.size();++j)
02168                 {
02169                         if (c.m_nodes[j]->m_im==0)
02170                         {
02171                                 c.m_containsAnchor = true;
02172                                 c.m_masses[j]   =       BT_LARGE_FLOAT;
02173                         } else
02174                         {
02175                                 c.m_masses[j]   =       btScalar(1.)/c.m_nodes[j]->m_im;
02176                         }
02177                         c.m_imass               +=      c.m_masses[j];
02178                 }
02179                 c.m_imass               =       btScalar(1.)/c.m_imass;
02180                 c.m_com                 =       btSoftBody::clusterCom(&c);
02181                 c.m_lv                  =       btVector3(0,0,0);
02182                 c.m_av                  =       btVector3(0,0,0);
02183                 c.m_leaf                =       0;
02184                 /* Inertia      */ 
02185                 btMatrix3x3&    ii=c.m_locii;
02186                 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
02187                 {
02188                         int i,ni;
02189 
02190                         for(i=0,ni=c.m_nodes.size();i<ni;++i)
02191                         {
02192                                 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
02193                                 const btVector3 q=k*k;
02194                                 const btScalar  m=c.m_masses[i];
02195                                 ii[0][0]        +=      m*(q[1]+q[2]);
02196                                 ii[1][1]        +=      m*(q[0]+q[2]);
02197                                 ii[2][2]        +=      m*(q[0]+q[1]);
02198                                 ii[0][1]        -=      m*k[0]*k[1];
02199                                 ii[0][2]        -=      m*k[0]*k[2];
02200                                 ii[1][2]        -=      m*k[1]*k[2];
02201                         }
02202                 }
02203                 ii[1][0]=ii[0][1];
02204                 ii[2][0]=ii[0][2];
02205                 ii[2][1]=ii[1][2];
02206                 
02207                 ii = ii.inverse();
02208 
02209                 /* Frame        */ 
02210                 c.m_framexform.setIdentity();
02211                 c.m_framexform.setOrigin(c.m_com);
02212                 c.m_framerefs.resize(c.m_nodes.size());
02213                 {
02214                         int i;
02215                         for(i=0;i<c.m_framerefs.size();++i)
02216                         {
02217                                 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
02218                         }
02219                 }
02220         }
02221 }
02222 
02223 //
02224 void                                    btSoftBody::updateClusters()
02225 {
02226         BT_PROFILE("UpdateClusters");
02227         int i;
02228 
02229         for(i=0;i<m_clusters.size();++i)
02230         {
02231                 btSoftBody::Cluster&    c=*m_clusters[i];
02232                 const int                               n=c.m_nodes.size();
02233                 //const btScalar                        invn=1/(btScalar)n;
02234                 if(n)
02235                 {
02236                         /* Frame                                */ 
02237                         const btScalar  eps=btScalar(0.0001);
02238                         btMatrix3x3             m,r,s;
02239                         m[0]=m[1]=m[2]=btVector3(0,0,0);
02240                         m[0][0]=eps*1;
02241                         m[1][1]=eps*2;
02242                         m[2][2]=eps*3;
02243                         c.m_com=clusterCom(&c);
02244                         for(int i=0;i<c.m_nodes.size();++i)
02245                         {
02246                                 const btVector3         a=c.m_nodes[i]->m_x-c.m_com;
02247                                 const btVector3&        b=c.m_framerefs[i];
02248                                 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
02249                         }
02250                         PolarDecompose(m,r,s);
02251                         c.m_framexform.setOrigin(c.m_com);
02252                         c.m_framexform.setBasis(r);             
02253                         /* Inertia                      */ 
02254 #if 1/* Constant        */ 
02255                         c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
02256 #else
02257 #if 0/* Sphere  */ 
02258                         const btScalar  rk=(2*c.m_extents.length2())/(5*c.m_imass);
02259                         const btVector3 inertia(rk,rk,rk);
02260                         const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
02261                                 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
02262                                 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
02263 
02264                         c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
02265 #else/* Actual  */              
02266                         c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
02267                         for(int i=0;i<n;++i)
02268                         {
02269                                 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
02270                                 const btVector3         q=k*k;
02271                                 const btScalar          m=1/c.m_nodes[i]->m_im;
02272                                 c.m_invwi[0][0] +=      m*(q[1]+q[2]);
02273                                 c.m_invwi[1][1] +=      m*(q[0]+q[2]);
02274                                 c.m_invwi[2][2] +=      m*(q[0]+q[1]);
02275                                 c.m_invwi[0][1] -=      m*k[0]*k[1];
02276                                 c.m_invwi[0][2] -=      m*k[0]*k[2];
02277                                 c.m_invwi[1][2] -=      m*k[1]*k[2];
02278                         }
02279                         c.m_invwi[1][0]=c.m_invwi[0][1];
02280                         c.m_invwi[2][0]=c.m_invwi[0][2];
02281                         c.m_invwi[2][1]=c.m_invwi[1][2];
02282                         c.m_invwi=c.m_invwi.inverse();
02283 #endif
02284 #endif
02285                         /* Velocities                   */ 
02286                         c.m_lv=btVector3(0,0,0);
02287                         c.m_av=btVector3(0,0,0);
02288                         {
02289                                 int i;
02290 
02291                                 for(i=0;i<n;++i)
02292                                 {
02293                                         const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
02294                                         c.m_lv  +=      v;
02295                                         c.m_av  +=      btCross(c.m_nodes[i]->m_x-c.m_com,v);
02296                                 }
02297                         }
02298                         c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
02299                         c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
02300                         c.m_vimpulses[0]        =
02301                                 c.m_vimpulses[1]        = btVector3(0,0,0);
02302                         c.m_dimpulses[0]        =
02303                                 c.m_dimpulses[1]        = btVector3(0,0,0);
02304                         c.m_nvimpulses          = 0;
02305                         c.m_ndimpulses          = 0;
02306                         /* Matching                             */ 
02307                         if(c.m_matching>0)
02308                         {
02309                                 for(int j=0;j<c.m_nodes.size();++j)
02310                                 {
02311                                         Node&                   n=*c.m_nodes[j];
02312                                         const btVector3 x=c.m_framexform*c.m_framerefs[j];
02313                                         n.m_x=Lerp(n.m_x,x,c.m_matching);
02314                                 }
02315                         }                       
02316                         /* Dbvt                                 */ 
02317                         if(c.m_collide)
02318                         {
02319                                 btVector3       mi=c.m_nodes[0]->m_x;
02320                                 btVector3       mx=mi;
02321                                 for(int j=1;j<n;++j)
02322                                 {
02323                                         mi.setMin(c.m_nodes[j]->m_x);
02324                                         mx.setMax(c.m_nodes[j]->m_x);
02325                                 }                       
02326                                 ATTRIBUTE_ALIGNED16(btDbvtVolume)       bounds=btDbvtVolume::FromMM(mi,mx);
02327                                 if(c.m_leaf)
02328                                         m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
02329                                 else
02330                                         c.m_leaf=m_cdbvt.insert(bounds,&c);
02331                         }
02332                 }
02333         }
02334 
02335 
02336 }
02337 
02338 
02339 
02340 
02341 //
02342 void                                    btSoftBody::cleanupClusters()
02343 {
02344         for(int i=0;i<m_joints.size();++i)
02345         {
02346                 m_joints[i]->Terminate(m_sst.sdt);
02347                 if(m_joints[i]->m_delete)
02348                 {
02349                         btAlignedFree(m_joints[i]);
02350                         m_joints.remove(m_joints[i--]);
02351                 }       
02352         }
02353 }
02354 
02355 //
02356 void                                    btSoftBody::prepareClusters(int iterations)
02357 {
02358         for(int i=0;i<m_joints.size();++i)
02359         {
02360                 m_joints[i]->Prepare(m_sst.sdt,iterations);
02361         }
02362 }
02363 
02364 
02365 //
02366 void                                    btSoftBody::solveClusters(btScalar sor)
02367 {
02368         for(int i=0,ni=m_joints.size();i<ni;++i)
02369         {
02370                 m_joints[i]->Solve(m_sst.sdt,sor);
02371         }
02372 }
02373 
02374 //
02375 void                                    btSoftBody::applyClusters(bool drift)
02376 {
02377         BT_PROFILE("ApplyClusters");
02378 //      const btScalar                                  f0=m_sst.sdt;
02379         //const btScalar                                        f1=f0/2;
02380         btAlignedObjectArray<btVector3> deltas;
02381         btAlignedObjectArray<btScalar> weights;
02382         deltas.resize(m_nodes.size(),btVector3(0,0,0));
02383         weights.resize(m_nodes.size(),0);
02384         int i;
02385 
02386         if(drift)
02387         {
02388                 for(i=0;i<m_clusters.size();++i)
02389                 {
02390                         Cluster&        c=*m_clusters[i];
02391                         if(c.m_ndimpulses)
02392                         {
02393                                 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
02394                                 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
02395                         }
02396                 }
02397         }
02398         
02399         for(i=0;i<m_clusters.size();++i)
02400         {
02401                 Cluster&        c=*m_clusters[i];       
02402                 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
02403                 {
02404                         const btVector3         v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
02405                         const btVector3         w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
02406                         for(int j=0;j<c.m_nodes.size();++j)
02407                         {
02408                                 const int                       idx=int(c.m_nodes[j]-&m_nodes[0]);
02409                                 const btVector3&        x=c.m_nodes[j]->m_x;
02410                                 const btScalar          q=c.m_masses[j];
02411                                 deltas[idx]             +=      (v+btCross(w,x-c.m_com))*q;
02412                                 weights[idx]    +=      q;
02413                         }
02414                 }
02415         }
02416         for(i=0;i<deltas.size();++i)
02417         {
02418                 if(weights[i]>0) 
02419                 {
02420                         m_nodes[i].m_x+=deltas[i]/weights[i];
02421                 }
02422         }
02423 }
02424 
02425 //
02426 void                                    btSoftBody::dampClusters()
02427 {
02428         int i;
02429 
02430         for(i=0;i<m_clusters.size();++i)
02431         {
02432                 Cluster&        c=*m_clusters[i];       
02433                 if(c.m_ndamping>0)
02434                 {
02435                         for(int j=0;j<c.m_nodes.size();++j)
02436                         {
02437                                 Node&                   n=*c.m_nodes[j];
02438                                 if(n.m_im>0)
02439                                 {
02440                                         const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
02441                                         if(vx.length2()<=n.m_v.length2())
02442                                                 {
02443                                                 n.m_v   +=      c.m_ndamping*(vx-n.m_v);
02444                                                 }
02445                                 }
02446                         }
02447                 }
02448         }
02449 }
02450 
02451 //
02452 void                            btSoftBody::Joint::Prepare(btScalar dt,int)
02453 {
02454         m_bodies[0].activate();
02455         m_bodies[1].activate();
02456 }
02457 
02458 //
02459 void                            btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
02460 {
02461         static const btScalar   maxdrift=4;
02462         Joint::Prepare(dt,iterations);
02463         m_rpos[0]               =       m_bodies[0].xform()*m_refs[0];
02464         m_rpos[1]               =       m_bodies[1].xform()*m_refs[1];
02465         m_drift                 =       Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
02466         m_rpos[0]               -=      m_bodies[0].xform().getOrigin();
02467         m_rpos[1]               -=      m_bodies[1].xform().getOrigin();
02468         m_massmatrix    =       ImpulseMatrix(  m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
02469                 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
02470         if(m_split>0)
02471         {
02472                 m_sdrift        =       m_massmatrix*(m_drift*m_split);
02473                 m_drift         *=      1-m_split;
02474         }
02475         m_drift /=(btScalar)iterations;
02476 }
02477 
02478 //
02479 void                            btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
02480 {
02481         const btVector3         va=m_bodies[0].velocity(m_rpos[0]);
02482         const btVector3         vb=m_bodies[1].velocity(m_rpos[1]);
02483         const btVector3         vr=va-vb;
02484         btSoftBody::Impulse     impulse;
02485         impulse.m_asVelocity    =       1;
02486         impulse.m_velocity              =       m_massmatrix*(m_drift+vr*m_cfm)*sor;
02487         m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
02488         m_bodies[1].applyImpulse( impulse,m_rpos[1]);
02489 }
02490 
02491 //
02492 void                            btSoftBody::LJoint::Terminate(btScalar dt)
02493 {
02494         if(m_split>0)
02495         {
02496                 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
02497                 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
02498         }
02499 }
02500 
02501 //
02502 void                            btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
02503 {
02504         static const btScalar   maxdrift=SIMD_PI/16;
02505         m_icontrol->Prepare(this);
02506         Joint::Prepare(dt,iterations);
02507         m_axis[0]       =       m_bodies[0].xform().getBasis()*m_refs[0];
02508         m_axis[1]       =       m_bodies[1].xform().getBasis()*m_refs[1];
02509         m_drift         =       NormalizeAny(btCross(m_axis[1],m_axis[0]));
02510         m_drift         *=      btMin(maxdrift,btAcos(Clamp<btScalar>(btDot(m_axis[0],m_axis[1]),-1,+1)));
02511         m_drift         *=      m_erp/dt;
02512         m_massmatrix=   AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
02513         if(m_split>0)
02514         {
02515                 m_sdrift        =       m_massmatrix*(m_drift*m_split);
02516                 m_drift         *=      1-m_split;
02517         }
02518         m_drift /=(btScalar)iterations;
02519 }
02520 
02521 //
02522 void                            btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
02523 {
02524         const btVector3         va=m_bodies[0].angularVelocity();
02525         const btVector3         vb=m_bodies[1].angularVelocity();
02526         const btVector3         vr=va-vb;
02527         const btScalar          sp=btDot(vr,m_axis[0]);
02528         const btVector3         vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
02529         btSoftBody::Impulse     impulse;
02530         impulse.m_asVelocity    =       1;
02531         impulse.m_velocity              =       m_massmatrix*(m_drift+vc*m_cfm)*sor;
02532         m_bodies[0].applyAImpulse(-impulse);
02533         m_bodies[1].applyAImpulse( impulse);
02534 }
02535 
02536 //
02537 void                            btSoftBody::AJoint::Terminate(btScalar dt)
02538 {
02539         if(m_split>0)
02540         {
02541                 m_bodies[0].applyDAImpulse(-m_sdrift);
02542                 m_bodies[1].applyDAImpulse( m_sdrift);
02543         }
02544 }
02545 
02546 //
02547 void                            btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
02548 {
02549         Joint::Prepare(dt,iterations);
02550         const bool      dodrift=(m_life==0);
02551         m_delete=(++m_life)>m_maxlife;
02552         if(dodrift)
02553         {
02554                 m_drift=m_drift*m_erp/dt;
02555                 if(m_split>0)
02556                 {
02557                         m_sdrift        =       m_massmatrix*(m_drift*m_split);
02558                         m_drift         *=      1-m_split;
02559                 }
02560                 m_drift/=(btScalar)iterations;
02561         }
02562         else
02563         {
02564                 m_drift=m_sdrift=btVector3(0,0,0);
02565         }
02566 }
02567 
02568 //
02569 void                            btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
02570 {
02571         const btVector3         va=m_bodies[0].velocity(m_rpos[0]);
02572         const btVector3         vb=m_bodies[1].velocity(m_rpos[1]);
02573         const btVector3         vrel=va-vb;
02574         const btScalar          rvac=btDot(vrel,m_normal);
02575         btSoftBody::Impulse     impulse;
02576         impulse.m_asVelocity    =       1;
02577         impulse.m_velocity              =       m_drift;
02578         if(rvac<0)
02579         {
02580                 const btVector3 iv=m_normal*rvac;
02581                 const btVector3 fv=vrel-iv;
02582                 impulse.m_velocity      +=      iv+fv*m_friction;
02583         }
02584         impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
02585         
02586         if (m_bodies[0].m_soft==m_bodies[1].m_soft)
02587         {
02588                 if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&&
02589                         (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ()))
02590                 {
02591                         if (impulse.m_asVelocity)
02592                         {
02593                                 if (impulse.m_velocity.length() <m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
02594                                 {
02595                                         
02596                                 } else
02597                                 {
02598                                         m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]);
02599                                         m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]);
02600                                 }
02601                         }
02602                 }
02603         } else
02604         {
02605                 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
02606                 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
02607         }
02608 }
02609 
02610 //
02611 void                            btSoftBody::CJoint::Terminate(btScalar dt)
02612 {
02613         if(m_split>0)
02614         {
02615                 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
02616                 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
02617         }
02618 }
02619 
02620 //
02621 void                            btSoftBody::applyForces()
02622 {
02623 
02624         BT_PROFILE("SoftBody applyForces");
02625         const btScalar                                  dt =                    m_sst.sdt;
02626         const btScalar                                  kLF =                   m_cfg.kLF;
02627         const btScalar                                  kDG =                   m_cfg.kDG;
02628         const btScalar                                  kPR =                   m_cfg.kPR;
02629         const btScalar                                  kVC =                   m_cfg.kVC;
02630         const bool                                              as_lift =               kLF>0;
02631         const bool                                              as_drag =               kDG>0;
02632         const bool                                              as_pressure =   kPR!=0;
02633         const bool                                              as_volume =             kVC>0;
02634         const bool                                              as_aero =               as_lift ||
02635                                                                                                         as_drag         ;
02636         const bool                                              as_vaero =              as_aero &&
02637                                                                                                         (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
02638         const bool                                              as_faero =              as_aero &&
02639                                                                                                         (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
02640         const bool                                              use_medium =    as_aero;
02641         const bool                                              use_volume =    as_pressure     ||
02642                 as_volume       ;
02643         btScalar                                                volume =                0;
02644         btScalar                                                ivolumetp =             0;
02645         btScalar                                                dvolumetv =             0;
02646         btSoftBody::sMedium     medium;
02647         if(use_volume)
02648         {
02649                 volume          =       getVolume();
02650                 ivolumetp       =       1/btFabs(volume)*kPR;
02651                 dvolumetv       =       (m_pose.m_volume-volume)*kVC;
02652         }
02653         /* Per vertex forces                    */ 
02654         int i,ni;
02655 
02656         for(i=0,ni=m_nodes.size();i<ni;++i)
02657         {
02658                 btSoftBody::Node&       n=m_nodes[i];
02659                 if(n.m_im>0)
02660                 {
02661                         if(use_medium)
02662                         {
02663                                 EvaluateMedium(m_worldInfo, n.m_x, medium);
02664                                 medium.m_velocity = m_windVelocity;
02665                                 medium.m_density = m_worldInfo->air_density;
02666 
02667                                 /* Aerodynamics                 */ 
02668                                 if(as_vaero)
02669                                 {                               
02670                                         const btVector3 rel_v = n.m_v - medium.m_velocity;
02671                                         const btScalar  rel_v2 = rel_v.length2();
02672                                         if(rel_v2>SIMD_EPSILON)
02673                                         {
02674                                                 btVector3       nrm = n.m_n;
02675                                                 /* Setup normal         */ 
02676                                                 switch(m_cfg.aeromodel)
02677                                                 {
02678                                                 case    btSoftBody::eAeroModel::V_Point:
02679                                                         nrm = NormalizeAny(rel_v);
02680                                                         break;
02681                                                 case    btSoftBody::eAeroModel::V_TwoSided:
02682                                                         nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
02683                                                         break;                                                  
02684                                                 default:
02685                                                         {
02686                                                         }
02687                                                 }
02688                                                 const btScalar dvn = btDot(rel_v,nrm);
02689                                                 /* Compute forces       */ 
02690                                                 if(dvn>0)
02691                                                 {
02692                                                         btVector3               force(0,0,0);
02693                                                         const btScalar  c0      =       n.m_area * dvn * rel_v2/2;
02694                                                         const btScalar  c1      =       c0 * medium.m_density;
02695                                                         force   +=      nrm*(-c1*kLF);
02696                                                         force   +=      rel_v.normalized() * (-c1 * kDG);
02697                                                         ApplyClampedForce(n, force, dt);
02698                                                 }
02699                                         }
02700                                 }
02701                         }
02702                         /* Pressure                             */ 
02703                         if(as_pressure)
02704                         {
02705                                 n.m_f   +=      n.m_n*(n.m_area*ivolumetp);
02706                         }
02707                         /* Volume                               */ 
02708                         if(as_volume)
02709                         {
02710                                 n.m_f   +=      n.m_n*(n.m_area*dvolumetv);
02711                         }
02712                 }
02713         }
02714         /* Per face forces                              */ 
02715         for(i=0,ni=m_faces.size();i<ni;++i)
02716         {
02717                 btSoftBody::Face&       f=m_faces[i];
02718                 if(as_faero)
02719                 {
02720                         const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
02721                         const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
02722                         EvaluateMedium(m_worldInfo,x,medium);
02723                         const btVector3 rel_v=v-medium.m_velocity;
02724                         const btScalar  rel_v2=rel_v.length2();
02725                         if(rel_v2>SIMD_EPSILON)
02726                         {
02727                                 btVector3       nrm=f.m_normal;
02728                                 /* Setup normal         */ 
02729                                 switch(m_cfg.aeromodel)
02730                                 {
02731                                 case    btSoftBody::eAeroModel::F_TwoSided:
02732                                         nrm*=(btScalar)(btDot(nrm,rel_v)<0?-1:+1);break;
02733                                         default:
02734                                         {
02735                                         }
02736                                 }
02737                                 const btScalar  dvn=btDot(rel_v,nrm);
02738                                 /* Compute forces       */ 
02739                                 if(dvn>0)
02740                                 {
02741                                         btVector3               force(0,0,0);
02742                                         const btScalar  c0      =       f.m_ra*dvn*rel_v2;
02743                                         const btScalar  c1      =       c0*medium.m_density;
02744                                         force   +=      nrm*(-c1*kLF);
02745                                         force   +=      rel_v.normalized()*(-c1*kDG);
02746                                         force   /=      3;
02747                                         for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
02748                                 }
02749                         }
02750                 }
02751         }
02752 }
02753 
02754 //
02755 void                            btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
02756 {
02757         const btScalar  kAHR=psb->m_cfg.kAHR*kst;
02758         const btScalar  dt=psb->m_sst.sdt;
02759         for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
02760         {
02761                 const Anchor&           a=psb->m_anchors[i];
02762                 const btTransform&      t=a.m_body->getWorldTransform();
02763                 Node&                           n=*a.m_node;
02764                 const btVector3         wa=t*a.m_local;
02765                 const btVector3         va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
02766                 const btVector3         vb=n.m_x-n.m_q;
02767                 const btVector3         vr=(va-vb)+(wa-n.m_x)*kAHR;
02768                 const btVector3         impulse=a.m_c0*vr;
02769                 n.m_x+=impulse*a.m_c2;
02770                 a.m_body->applyImpulse(-impulse,a.m_c1);
02771         }
02772 }
02773 
02774 //
02775 void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
02776 {
02777         const btScalar  dt = psb->m_sst.sdt;
02778         const btScalar  mrg = psb->getCollisionShape()->getMargin();
02779         for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
02780         {
02781                 const RContact&         c = psb->m_rcontacts[i];
02782                 const sCti&                     cti = c.m_cti;  
02783                 btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj);
02784 
02785                 const btVector3         va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0);
02786                 const btVector3         vb = c.m_node->m_x-c.m_node->m_q;       
02787                 const btVector3         vr = vb-va;
02788                 const btScalar          dn = btDot(vr, cti.m_normal);           
02789                 if(dn<=SIMD_EPSILON)
02790                 {
02791                         const btScalar          dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg );
02792                         const btVector3         fv = vr - (cti.m_normal * dn);
02793                         // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
02794                         const btVector3         impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst );
02795                         c.m_node->m_x -= impulse * c.m_c2;
02796                         if (tmpRigid)
02797                                 tmpRigid->applyImpulse(impulse,c.m_c1);
02798                 }
02799         }
02800 }
02801 
02802 //
02803 void                            btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
02804 {
02805         for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
02806         {
02807                 const SContact&         c=psb->m_scontacts[i];
02808                 const btVector3&        nr=c.m_normal;
02809                 Node&                           n=*c.m_node;
02810                 Face&                           f=*c.m_face;
02811                 const btVector3         p=BaryEval(     f.m_n[0]->m_x,
02812                         f.m_n[1]->m_x,
02813                         f.m_n[2]->m_x,
02814                         c.m_weights);
02815                 const btVector3         q=BaryEval(     f.m_n[0]->m_q,
02816                         f.m_n[1]->m_q,
02817                         f.m_n[2]->m_q,
02818                         c.m_weights);                                                                                   
02819                 const btVector3         vr=(n.m_x-n.m_q)-(p-q);
02820                 btVector3                       corr(0,0,0);
02821                 btScalar dot = btDot(vr,nr);
02822                 if(dot<0)
02823                 {
02824                         const btScalar  j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p));
02825                         corr+=c.m_normal*j;
02826                 }
02827                 corr                    -=      ProjectOnPlane(vr,nr)*c.m_friction;
02828                 n.m_x                   +=      corr*c.m_cfm[0];
02829                 f.m_n[0]->m_x   -=      corr*(c.m_cfm[1]*c.m_weights.x());
02830                 f.m_n[1]->m_x   -=      corr*(c.m_cfm[1]*c.m_weights.y());
02831                 f.m_n[2]->m_x   -=      corr*(c.m_cfm[1]*c.m_weights.z());
02832         }
02833 }
02834 
02835 //
02836 void                            btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
02837 {
02838         for(int i=0,ni=psb->m_links.size();i<ni;++i)
02839         {                       
02840                 Link&   l=psb->m_links[i];
02841                 if(l.m_c0>0)
02842                 {
02843                         Node&                   a=*l.m_n[0];
02844                         Node&                   b=*l.m_n[1];
02845                         const btVector3 del=b.m_x-a.m_x;
02846                         const btScalar  len=del.length2();
02847                         if (l.m_c1+len > SIMD_EPSILON)
02848                         {
02849                                 const btScalar  k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
02850                                 a.m_x-=del*(k*a.m_im);
02851                                 b.m_x+=del*(k*b.m_im);
02852                         }
02853                 }
02854         }
02855 }
02856 
02857 //
02858 void                            btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
02859 {
02860         for(int i=0,ni=psb->m_links.size();i<ni;++i)
02861         {                       
02862                 Link&                   l=psb->m_links[i];
02863                 Node**                  n=l.m_n;
02864                 const btScalar  j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
02865                 n[0]->m_v+=     l.m_c3*(j*n[0]->m_im);
02866                 n[1]->m_v-=     l.m_c3*(j*n[1]->m_im);
02867         }
02868 }
02869 
02870 //
02871 btSoftBody::psolver_t   btSoftBody::getSolver(ePSolver::_ solver)
02872 {
02873         switch(solver)
02874         {
02875         case    ePSolver::Anchors:              
02876                 return(&btSoftBody::PSolve_Anchors);
02877         case    ePSolver::Linear:               
02878                 return(&btSoftBody::PSolve_Links);
02879         case    ePSolver::RContacts:    
02880                 return(&btSoftBody::PSolve_RContacts);
02881         case    ePSolver::SContacts:    
02882                 return(&btSoftBody::PSolve_SContacts);  
02883                 default:
02884                 {
02885                 }
02886         }
02887         return(0);
02888 }
02889 
02890 //
02891 btSoftBody::vsolver_t   btSoftBody::getSolver(eVSolver::_ solver)
02892 {
02893         switch(solver)
02894         {
02895         case    eVSolver::Linear:               return(&btSoftBody::VSolve_Links);
02896                 default:
02897                 {
02898                 }
02899         }
02900         return(0);
02901 }
02902 
02903 //
02904 void                    btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
02905 {
02906 
02907         switch(m_cfg.collisions&fCollision::RVSmask)
02908         {
02909         case    fCollision::SDF_RS:
02910                 {
02911                         btSoftColliders::CollideSDF_RS  docollide;              
02912                         btRigidBody*            prb1=btRigidBody::upcast(pco);
02913                         btTransform     wtr=pco->getWorldTransform();
02914 
02915                         const btTransform       ctr=pco->getWorldTransform();
02916                         const btScalar          timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
02917                         const btScalar          basemargin=getCollisionShape()->getMargin();
02918                         btVector3                       mins;
02919                         btVector3                       maxs;
02920                         ATTRIBUTE_ALIGNED16(btDbvtVolume)               volume;
02921                         pco->getCollisionShape()->getAabb(      pco->getWorldTransform(),
02922                                 mins,
02923                                 maxs);
02924                         volume=btDbvtVolume::FromMM(mins,maxs);
02925                         volume.Expand(btVector3(basemargin,basemargin,basemargin));             
02926                         docollide.psb           =       this;
02927                         docollide.m_colObj1 = pco;
02928                         docollide.m_rigidBody = prb1;
02929 
02930                         docollide.dynmargin     =       basemargin+timemargin;
02931                         docollide.stamargin     =       basemargin;
02932                         m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide);
02933                 }
02934                 break;
02935         case    fCollision::CL_RS:
02936                 {
02937                         btSoftColliders::CollideCL_RS   collider;
02938                         collider.Process(this,pco);
02939                 }
02940                 break;
02941         }
02942 }
02943 
02944 //
02945 void                    btSoftBody::defaultCollisionHandler(btSoftBody* psb)
02946 {
02947         const int cf=m_cfg.collisions&psb->m_cfg.collisions;
02948         switch(cf&fCollision::SVSmask)
02949         {
02950         case    fCollision::CL_SS:
02951                 {
02952                         
02953                         //support self-collision if CL_SELF flag set
02954                         if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF)
02955                         {
02956                                 btSoftColliders::CollideCL_SS   docollide;
02957                                 docollide.Process(this,psb);
02958                         }
02959                         
02960                 }
02961                 break;
02962         case    fCollision::VF_SS:
02963                 {
02964                         //only self-collision for Cluster, not Vertex-Face yet
02965                         if (this!=psb)
02966                         {
02967                                 btSoftColliders::CollideVF_SS   docollide;
02968                                 /* common                                       */ 
02969                                 docollide.mrg=  getCollisionShape()->getMargin()+
02970                                         psb->getCollisionShape()->getMargin();
02971                                 /* psb0 nodes vs psb1 faces     */ 
02972                                 docollide.psb[0]=this;
02973                                 docollide.psb[1]=psb;
02974                                 docollide.psb[0]->m_ndbvt.collideTT(    docollide.psb[0]->m_ndbvt.m_root,
02975                                         docollide.psb[1]->m_fdbvt.m_root,
02976                                         docollide);
02977                                 /* psb1 nodes vs psb0 faces     */ 
02978                                 docollide.psb[0]=psb;
02979                                 docollide.psb[1]=this;
02980                                 docollide.psb[0]->m_ndbvt.collideTT(    docollide.psb[0]->m_ndbvt.m_root,
02981                                         docollide.psb[1]->m_fdbvt.m_root,
02982                                         docollide);
02983                         }
02984                 }
02985                 break;
02986         default:
02987                 {
02988                         
02989                 }
02990         }
02991 }
02992 
02993 
02994 
02995 void btSoftBody::setWindVelocity( const btVector3 &velocity )
02996 {
02997         m_windVelocity = velocity;
02998 }
02999 
03000 
03001 const btVector3& btSoftBody::getWindVelocity()
03002 {
03003         return m_windVelocity;
03004 }
03005 
03006 
03007 
03008 int     btSoftBody::calculateSerializeBufferSize()      const
03009 {
03010         int sz = sizeof(btSoftBodyData);
03011         return sz;
03012 }
03013 
03015 const char*     btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
03016 {
03017         btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer;
03018 
03019         btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
03020 
03021         btHashMap<btHashPtr,int>        m_nodeIndexMap;
03022 
03023         sbd->m_numMaterials = m_materials.size();
03024         sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0;
03025 
03026         if (sbd->m_materials)
03027         {
03028                 int sz = sizeof(SoftBodyMaterialData*);
03029                 int numElem = sbd->m_numMaterials;
03030                 btChunk* chunk = serializer->allocate(sz,numElem);
03031                 //SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
03032                 SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
03033                 for (int i=0;i<numElem;i++,memPtr++)
03034                 {
03035                         btSoftBody::Material* mat = m_materials[i];
03036                         *memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
03037                         if (!serializer->findPointer(mat))
03038                         {
03039                                 //serialize it here
03040                                 btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1);
03041                                 SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
03042                                 memPtr->m_flags = mat->m_flags;
03043                                 memPtr->m_angularStiffness = mat->m_kAST;
03044                                 memPtr->m_linearStiffness = mat->m_kLST;
03045                                 memPtr->m_volumeStiffness = mat->m_kVST;
03046                                 serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat);
03047                         }
03048                 }
03049                 serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials);
03050         }
03051 
03052 
03053         
03054 
03055         sbd->m_numNodes = m_nodes.size();
03056         sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0;
03057         if (sbd->m_nodes)
03058         {
03059                 int sz = sizeof(SoftBodyNodeData);
03060                 int numElem = sbd->m_numNodes;
03061                 btChunk* chunk = serializer->allocate(sz,numElem);
03062                 SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
03063                 for (int i=0;i<numElem;i++,memPtr++)
03064                 {
03065                         m_nodes[i].m_f.serializeFloat( memPtr->m_accumulatedForce);
03066                         memPtr->m_area = m_nodes[i].m_area;
03067                         memPtr->m_attach = m_nodes[i].m_battach;
03068                         memPtr->m_inverseMass = m_nodes[i].m_im;
03069                         memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0;
03070                         m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
03071                         m_nodes[i].m_x.serializeFloat(memPtr->m_position);
03072                         m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
03073                         m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
03074                         m_nodeIndexMap.insert(&m_nodes[i],i);
03075                 }
03076                 serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes);
03077         }
03078 
03079         sbd->m_numLinks = m_links.size();
03080         sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
03081         if (sbd->m_links)
03082         {
03083                 int sz = sizeof(SoftBodyLinkData);
03084                 int numElem = sbd->m_numLinks;
03085                 btChunk* chunk = serializer->allocate(sz,numElem);
03086                 SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
03087                 for (int i=0;i<numElem;i++,memPtr++)
03088                 {
03089                         memPtr->m_bbending = m_links[i].m_bbending;
03090                         memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0;
03091                         memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1;
03092                         memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1;
03093                         btAssert(memPtr->m_nodeIndices[0]<m_nodes.size());
03094                         btAssert(memPtr->m_nodeIndices[1]<m_nodes.size());
03095                         memPtr->m_restLength = m_links[i].m_rl;
03096                 }
03097                 serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]);
03098 
03099         }
03100 
03101 
03102         sbd->m_numFaces = m_faces.size();
03103         sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0;
03104         if (sbd->m_faces)
03105         {
03106                 int sz = sizeof(SoftBodyFaceData);
03107                 int numElem = sbd->m_numFaces;
03108                 btChunk* chunk = serializer->allocate(sz,numElem);
03109                 SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
03110                 for (int i=0;i<numElem;i++,memPtr++)
03111                 {
03112                         memPtr->m_material = m_faces[i].m_material ?  (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0;
03113                         m_faces[i].m_normal.serializeFloat(     memPtr->m_normal);
03114                         for (int j=0;j<3;j++)
03115                         {
03116                                 memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1;
03117                         }
03118                         memPtr->m_restArea = m_faces[i].m_ra;
03119                 }
03120                 serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]);
03121         }
03122 
03123 
03124         sbd->m_numTetrahedra = m_tetras.size();
03125         sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0;
03126         if (sbd->m_tetrahedra)
03127         {
03128                 int sz = sizeof(SoftBodyTetraData);
03129                 int numElem = sbd->m_numTetrahedra;
03130                 btChunk* chunk = serializer->allocate(sz,numElem);
03131                 SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
03132                 for (int i=0;i<numElem;i++,memPtr++)
03133                 {
03134                         for (int j=0;j<4;j++)
03135                         {
03136                                 m_tetras[i].m_c0[j].serializeFloat(     memPtr->m_c0[j] );
03137                                 memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j]? m_tetras[j].m_n[j]-&m_nodes[0] : -1;
03138                         }
03139                         memPtr->m_c1 = m_tetras[i].m_c1;
03140                         memPtr->m_c2 = m_tetras[i].m_c2;
03141                         memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0;
03142                         memPtr->m_restVolume = m_tetras[i].m_rv;
03143                 }
03144                 serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]);
03145         }
03146 
03147         sbd->m_numAnchors = m_anchors.size();
03148         sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0;
03149         if (sbd->m_anchors)
03150         {
03151                 int sz = sizeof(SoftRigidAnchorData);
03152                 int numElem = sbd->m_numAnchors;
03153                 btChunk* chunk = serializer->allocate(sz,numElem);
03154                 SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
03155                 for (int i=0;i<numElem;i++,memPtr++)
03156                 {
03157                         m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
03158                         m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
03159                         memPtr->m_c2 = m_anchors[i].m_c2;
03160                         m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
03161                         memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1;
03162                         
03163                         memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*)  serializer->getUniquePointer((void*)m_anchors[i].m_body): 0;
03164                         btAssert(memPtr->m_nodeIndex < m_nodes.size());
03165                 }
03166                 serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]);
03167         }
03168         
03169 
03170         sbd->m_config.m_dynamicFriction = m_cfg.kDF;
03171         sbd->m_config.m_baumgarte = m_cfg.kVCF;
03172         sbd->m_config.m_pressure = m_cfg.kPR;
03173         sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
03174         sbd->m_config.m_lift = m_cfg.kLF;
03175         sbd->m_config.m_drag = m_cfg.kDG;
03176         sbd->m_config.m_positionIterations = m_cfg.piterations;
03177         sbd->m_config.m_driftIterations = m_cfg.diterations;
03178         sbd->m_config.m_clusterIterations = m_cfg.citerations;
03179         sbd->m_config.m_velocityIterations = m_cfg.viterations;
03180         sbd->m_config.m_maxVolume = m_cfg.maxvolume;
03181         sbd->m_config.m_damping = m_cfg.kDP;
03182         sbd->m_config.m_poseMatch = m_cfg.kMT;
03183         sbd->m_config.m_collisionFlags = m_cfg.collisions;
03184         sbd->m_config.m_volume = m_cfg.kVC;
03185         sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
03186         sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
03187         sbd->m_config.m_softContactHardness = m_cfg.kSHR;
03188         sbd->m_config.m_anchorHardness = m_cfg.kAHR;
03189         sbd->m_config.m_timeScale = m_cfg.timescale;
03190         sbd->m_config.m_maxVolume = m_cfg.maxvolume;
03191         sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
03192         sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
03193         sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
03194         sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
03195         sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
03196         sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
03197                 
03198         //pose for shape matching
03199         {
03200                 sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
03201 
03202                 int sz = sizeof(SoftBodyPoseData);
03203                 btChunk* chunk = serializer->allocate(sz,1);
03204                 SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
03205                 
03206                 m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
03207                 memPtr->m_bframe = m_pose.m_bframe;
03208                 memPtr->m_bvolume = m_pose.m_bvolume;
03209                 m_pose.m_com.serializeFloat(memPtr->m_com);
03210                 
03211                 memPtr->m_numPositions = m_pose.m_pos.size();
03212                 memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0;
03213                 if (memPtr->m_numPositions)
03214                 {
03215                         int numElem = memPtr->m_numPositions;
03216                         int sz = sizeof(btVector3Data);
03217                         btChunk* chunk = serializer->allocate(sz,numElem);
03218                         btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
03219                         for (int i=0;i<numElem;i++,memPtr++)
03220                         {
03221                                 m_pose.m_pos[i].serializeFloat(*memPtr);
03222                         }
03223                         serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]);
03224                 }
03225                 memPtr->m_restVolume = m_pose.m_volume;
03226                 m_pose.m_rot.serializeFloat(memPtr->m_rot);
03227                 m_pose.m_scl.serializeFloat(memPtr->m_scale);
03228 
03229                 memPtr->m_numWeigts = m_pose.m_wgh.size();
03230                 memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0;
03231                 if (memPtr->m_numWeigts)
03232                 {
03233                         
03234                         int numElem = memPtr->m_numWeigts;
03235                         int sz = sizeof(float);
03236                         btChunk* chunk = serializer->allocate(sz,numElem);
03237                         float* memPtr = (float*) chunk->m_oldPtr;
03238                         for (int i=0;i<numElem;i++,memPtr++)
03239                         {
03240                                 *memPtr = m_pose.m_wgh[i];
03241                         }
03242                         serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]);
03243                 }
03244 
03245                 serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose);
03246         }
03247 
03248         //clusters for convex-cluster collision detection
03249 
03250         sbd->m_numClusters = m_clusters.size();
03251         sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0;
03252         if (sbd->m_numClusters)
03253         {
03254                 int numElem = sbd->m_numClusters;
03255                 int sz = sizeof(SoftBodyClusterData);
03256                 btChunk* chunk = serializer->allocate(sz,numElem);
03257                 SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr;
03258                 for (int i=0;i<numElem;i++,memPtr++)
03259                 {
03260                         memPtr->m_adamping= m_clusters[i]->m_adamping;
03261                         m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
03262                         memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
03263                         memPtr->m_collide = m_clusters[i]->m_collide;
03264                         m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
03265                         memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
03266                         m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
03267                         m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
03268                         m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
03269                         memPtr->m_idmass = m_clusters[i]->m_idmass;
03270                         memPtr->m_imass = m_clusters[i]->m_imass;
03271                         m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
03272                         memPtr->m_ldamping = m_clusters[i]->m_ldamping;
03273                         m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
03274                         m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
03275                         memPtr->m_matching = m_clusters[i]->m_matching;
03276                         memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
03277                         memPtr->m_ndamping = m_clusters[i]->m_ndamping;
03278                         memPtr->m_ldamping = m_clusters[i]->m_ldamping;
03279                         memPtr->m_adamping = m_clusters[i]->m_adamping;
03280                         memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
03281 
03282                         memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
03283                         memPtr->m_numMasses = m_clusters[i]->m_masses.size();
03284                         memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
03285 
03286                         memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
03287                         m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
03288                         m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
03289                         memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
03290 
03291                         
03292 
03293                         memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
03294                         if (memPtr->m_framerefs)
03295                         {
03296                                 int numElem = memPtr->m_numFrameRefs;
03297                                 int sz = sizeof(btVector3FloatData);
03298                                 btChunk* chunk = serializer->allocate(sz,numElem);
03299                                 btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr;
03300                                 for (int j=0;j<numElem;j++,memPtr++)
03301                                 {
03302                                         m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
03303                                 }
03304                                 serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]);
03305                         }
03306                         
03307                         memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0;
03308                         if (memPtr->m_masses)
03309                         {
03310                                 int numElem = memPtr->m_numMasses;
03311                                 int sz = sizeof(float);
03312                                 btChunk* chunk = serializer->allocate(sz,numElem);
03313                                 float* memPtr = (float*) chunk->m_oldPtr;
03314                                 for (int j=0;j<numElem;j++,memPtr++)
03315                                 {
03316                                         *memPtr = m_clusters[i]->m_masses[j];
03317                                 }
03318                                 serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]);
03319                         }
03320 
03321                         memPtr->m_nodeIndices  = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0;
03322                         if (memPtr->m_nodeIndices )
03323                         {
03324                                 int numElem = memPtr->m_numMasses;
03325                                 int sz = sizeof(int);
03326                                 btChunk* chunk = serializer->allocate(sz,numElem);
03327                                 int* memPtr = (int*) chunk->m_oldPtr;
03328                                 for (int j=0;j<numElem;j++,memPtr++)
03329                                 {
03330                                         int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
03331                                         btAssert(indexPtr);
03332                                         *memPtr = *indexPtr;
03333                                 }
03334                                 serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes);
03335                         }
03336                 }
03337                 serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]);
03338 
03339         }
03340         
03341 
03342         
03343         sbd->m_numJoints = m_joints.size();
03344         sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0;
03345 
03346         if (sbd->m_joints)
03347         {
03348                 int sz = sizeof(btSoftBodyJointData);
03349                 int numElem = m_joints.size();
03350                 btChunk* chunk = serializer->allocate(sz,numElem);
03351                 btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
03352 
03353                 for (int i=0;i<numElem;i++,memPtr++)
03354                 {
03355                         memPtr->m_jointType = (int)m_joints[i]->Type();
03356                         m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
03357                         m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
03358                         memPtr->m_cfm = m_joints[i]->m_cfm;
03359                         memPtr->m_erp = m_joints[i]->m_erp;
03360                         memPtr->m_split = m_joints[i]->m_split;
03361                         memPtr->m_delete = m_joints[i]->m_delete;
03362                         
03363                         for (int j=0;j<4;j++)
03364                         {
03365                                 memPtr->m_relPosition[0].m_floats[j] = 0.f;
03366                                 memPtr->m_relPosition[1].m_floats[j] = 0.f;
03367                         }
03368                         memPtr->m_bodyA = 0;
03369                         memPtr->m_bodyB = 0;
03370                         if (m_joints[i]->m_bodies[0].m_soft)
03371                         {
03372                                 memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER;
03373                                 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
03374                         }
03375                         if (m_joints[i]->m_bodies[0].m_collisionObject)
03376                         {
03377                                 memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT;
03378                                 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
03379                         }
03380                         if (m_joints[i]->m_bodies[0].m_rigid)
03381                         {
03382                                 memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
03383                                 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
03384                         }
03385 
03386                         if (m_joints[i]->m_bodies[1].m_soft)
03387                         {
03388                                 memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER;
03389                                 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
03390                         }
03391                         if (m_joints[i]->m_bodies[1].m_collisionObject)
03392                         {
03393                                 memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT;
03394                                 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
03395                         }
03396                         if (m_joints[i]->m_bodies[1].m_rigid)
03397                         {
03398                                 memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
03399                                 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
03400                         }
03401                 }
03402                 serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]);
03403         }
03404 
03405 
03406         return btSoftBodyDataName;
03407 }
03408