From 06112592fde703244b7554e3916d1fafe45c7026 Mon Sep 17 00:00:00 2001 From: "erwin.coumans" Date: Thu, 1 Sep 2011 01:53:45 +0000 Subject: [PATCH] Add another wind model, that doesn't clamp the maximum force. Thanks to saggitasaggita for the patch, see http://code.google.com/p/bullet/issues/detail?id=532 --- Demos/SoftDemo/SoftDemo.cpp | 56 +++++++++++++- src/BulletSoftBody/btSoftBody.cpp | 124 +++++++++++++++++++++--------- src/BulletSoftBody/btSoftBody.h | 12 +-- 3 files changed, 147 insertions(+), 45 deletions(-) diff --git a/Demos/SoftDemo/SoftDemo.cpp b/Demos/SoftDemo/SoftDemo.cpp index e11779c2a..4328259ea 100644 --- a/Demos/SoftDemo/SoftDemo.cpp +++ b/Demos/SoftDemo/SoftDemo.cpp @@ -40,7 +40,7 @@ extern float eye[3]; extern int glutScreenWidth; extern int glutScreenHeight; -static bool sDemoMode = true; +static bool sDemoMode = false; const int maxProxies = 32766; const int maxOverlap = 65535; @@ -52,7 +52,7 @@ static btRigidBody* staticBody = 0; static float waveheight = 5.f; const float TRIANGLE_SIZE=8.f; -unsigned current_demo=23; +unsigned current_demo=12; #define DEMO_MODE_TIMEOUT 15.f //15 seconds for each demo @@ -557,7 +557,58 @@ static void Init_Aero(SoftDemo* pdemo) } pdemo->m_autocam=true; +} +static void Init_Aero2(SoftDemo* pdemo) +{ + //TRACEDEMO + const btScalar s=5; + const int segments=10; + const int count=5; + btVector3 pos(-s*segments, 0, 0); + btScalar gap = 0.5; + + for(int i=0;im_softBodyWorldInfo,btVector3(-s,0,-s*3), + btVector3(+s,0,-s*3), + btVector3(-s,0,+s), + btVector3(+s,0,+s), + segments,segments*3, + 1+2,true); + + psb->getCollisionShape()->setMargin(0.5); + btSoftBody::Material* pm=psb->appendMaterial(); + pm->m_kLST = 0.0004; + pm->m_flags -= btSoftBody::fMaterial::DebugDraw; + psb->generateBendingConstraints(2,pm); + + psb->m_cfg.kLF = 0.05; + psb->m_cfg.kDG = 0.01; + + //psb->m_cfg.kLF = 0.004; + //psb->m_cfg.kDG = 0.0003; + + psb->m_cfg.piterations = 2; + psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSidedLiftDrag; + + + psb->setWindVelocity(btVector3(4, -12.0, -25.0)); + + btTransform trs; + btQuaternion rot; + pos += btVector3(s*2 + gap, 0, 0); + rot.setRotation(btVector3(1, 0, 0), btScalar(SIMD_PI/2)); + trs.setIdentity(); + trs.setOrigin(pos); + trs.setRotation(rot); + psb->transform(trs); + psb->setTotalMass(2.0); + + pdemo->getSoftDynamicsWorld()->addSoftBody(psb); + } + + pdemo->m_autocam=true; } // @@ -1273,6 +1324,7 @@ static void Init_TetraCube(SoftDemo* pdemo) Init_Collide3, Init_Impact, Init_Aero, + Init_Aero2, Init_Friction, Init_Torus, Init_TorusMatch, diff --git a/src/BulletSoftBody/btSoftBody.cpp b/src/BulletSoftBody/btSoftBody.cpp index 11f8e4145..877004d79 100644 --- a/src/BulletSoftBody/btSoftBody.cpp +++ b/src/BulletSoftBody/btSoftBody.cpp @@ -2701,35 +2701,51 @@ void btSoftBody::applyForces() /* Aerodynamics */ if(as_vaero) { - const btVector3 rel_v = n.m_v - medium.m_velocity; + const btVector3 rel_v = n.m_v - medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); const btScalar rel_v2 = rel_v.length2(); + if(rel_v2>SIMD_EPSILON) { - btVector3 nrm = n.m_n; - /* Setup normal */ - switch(m_cfg.aeromodel) + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = n.m_n; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag) { - case btSoftBody::eAeroModel::V_Point: - nrm = NormalizeAny(rel_v); - break; - case btSoftBody::eAeroModel::V_TwoSided: nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); - break; - default: - { - } + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * n.m_area; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + n.m_f += fDrag; + n.m_f += fLift; } - const btScalar dvn = btDot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided) { - btVector3 force(0,0,0); - const btScalar c0 = n.m_area * dvn * rel_v2/2; - const btScalar c1 = c0 * medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized() * (-c1 * kDG); - ApplyClampedForce(n, force, dt); - } + if (btSoftBody::eAeroModel::V_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn = btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = n.m_area * dvn * rel_v2/2; + const btScalar c1 = c0 * medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized() * (-c1 * kDG); + ApplyClampedForce(n, force, dt); + } + } } } } @@ -2754,31 +2770,63 @@ void btSoftBody::applyForces() const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; EvaluateMedium(m_worldInfo,x,medium); + medium.m_velocity = m_windVelocity; + medium.m_density = m_worldInfo->air_density; const btVector3 rel_v=v-medium.m_velocity; + const btScalar rel_v_len = rel_v.length(); const btScalar rel_v2=rel_v.length2(); + if(rel_v2>SIMD_EPSILON) { - btVector3 nrm=f.m_normal; - /* Setup normal */ - switch(m_cfg.aeromodel) + const btVector3 rel_v_nrm = rel_v.normalized(); + btVector3 nrm = f.m_normal; + + if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag) { - case btSoftBody::eAeroModel::F_TwoSided: - nrm*=(btScalar)(btDot(nrm,rel_v)<0?-1:+1);break; - default: + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + btVector3 fDrag(0, 0, 0); + btVector3 fLift(0, 0, 0); + + btScalar n_dot_v = nrm.dot(rel_v_nrm); + btScalar tri_area = 0.5f * f.m_ra; + + fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm); + + // Check angle of attack + // cos(10º) = 0.98480 + if ( 0 < n_dot_v && n_dot_v < 0.98480f) + fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm)); + + fDrag /= 3; + fLift /= 3; + + for(int j=0;j<3;++j) { + if (f.m_n[j]->m_im>0) + { + f.m_n[j]->m_f += fDrag; + f.m_n[j]->m_f += fLift; + } } } - const btScalar dvn=btDot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) + else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided) { - btVector3 force(0,0,0); - const btScalar c0 = f.m_ra*dvn*rel_v2; - const btScalar c1 = c0*medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized()*(-c1*kDG); - force /= 3; - for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); + if (btSoftBody::eAeroModel::F_TwoSided) + nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1); + + const btScalar dvn=btDot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = f.m_ra*dvn*rel_v2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + force /= 3; + for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); + } } } } diff --git a/src/BulletSoftBody/btSoftBody.h b/src/BulletSoftBody/btSoftBody.h index ec2f1a68b..79bde1dfd 100644 --- a/src/BulletSoftBody/btSoftBody.h +++ b/src/BulletSoftBody/btSoftBody.h @@ -80,11 +80,13 @@ public: ///eAeroModel struct eAeroModel { enum _ { - V_Point, ///Vertex normals are oriented toward velocity - V_TwoSided, ///Vertex normals are fliped to match velocity - V_OneSided, ///Vertex normals are taken as it is - F_TwoSided, ///Face normals are fliped to match velocity - F_OneSided, ///Face normals are taken as it is + V_Point, ///Vertex normals are oriented toward velocity + V_TwoSided, ///Vertex normals are flipped to match velocity + V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied + V_OneSided, ///Vertex normals are taken as it is + F_TwoSided, ///Face normals are flipped to match velocity + F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied + F_OneSided, ///Face normals are taken as it is END };};