Guest User

Untitled

a guest
Sep 3rd, 2015
587
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.14 KB | None | 0 0
  1. //
  2. // Copyright (c) 2008-2015 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22.  
  23. #include "../Precompiled.h"
  24.  
  25. #include "../Core/Context.h"
  26. #include "../Core/Profiler.h"
  27. #include "../IO/Log.h"
  28. #include "../IO/MemoryBuffer.h"
  29. #include "../Physics/CollisionShape.h"
  30. #include "../Physics/Constraint.h"
  31. #include "../Physics/PhysicsUtils.h"
  32. #include "../Physics/PhysicsWorld.h"
  33. #include "../Physics/SoftBody.h"
  34. #include "../Resource/ResourceCache.h"
  35. #include "../Resource/ResourceEvents.h"
  36. #include "../Scene/Scene.h"
  37. #include "../Scene/SceneEvents.h"
  38. #include "../Scene/SmoothedTransform.h"
  39.  
  40. #include "../Graphics/Model.h"
  41. #include "../Graphics/Geometry.h"
  42. #include "../Graphics/VertexBuffer.h"
  43. #include "../Graphics/IndexBuffer.h"
  44. #include "../Graphics/Drawable.h"
  45. #include "../Graphics/Batch.h"
  46.  
  47.  
  48.  
  49. #include <Bullet/BulletSoftBody/btSoftBody.h>
  50. #include <Bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h>
  51. #include <Bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h>
  52. #include <Bullet/BulletSoftBody/btSoftBodyHelpers.h>
  53. #include <Bullet/BulletCollision/CollisionShapes/btCompoundShape.h>
  54.  
  55. namespace Urho3D
  56. {
  57.  
  58. static const float DEFAULT_SOFT_BODY_MASS = 1.0f;
  59. static const float DEFAULT_FRICTION = 0.5f;
  60. static const float DEFAULT_RESTITUTION = 0.0f;
  61. static const float DEFAULT_ROLLING_FRICTION = 0.0f;
  62. static const unsigned DEFAULT_COLLISION_LAYER = 0x1;
  63. static const unsigned DEFAULT_COLLISION_MASK = M_MAX_UNSIGNED;
  64.  
  65. extern const char* PHYSICS_CATEGORY;
  66.  
  67. SoftBody::SoftBody(Context* context) :
  68.     Component(context),
  69.     body_(0),
  70.     gravityOverride_(Vector3::ZERO),
  71.     centerOfMass_(Vector3::ZERO),
  72.     mass_(DEFAULT_SOFT_BODY_MASS),
  73.     collisionLayer_(DEFAULT_COLLISION_LAYER),
  74.     collisionMask_(DEFAULT_COLLISION_MASK),
  75.     lastPosition_(Vector3::ZERO),
  76.     lastRotation_(Quaternion::IDENTITY),
  77.     useGravity_(true),
  78.     readdBody_(false),
  79.     inWorld_(false),
  80.     enableMassUpdate_(true),
  81.     model_(0)
  82. {
  83.     // constructor
  84. }
  85.  
  86. SoftBody::~SoftBody()
  87. {
  88.     ReleaseBody();
  89.  
  90.     if (physicsWorld_)
  91.         physicsWorld_->RemoveSoftBody(this);
  92.    
  93.     if (model_)
  94.     {
  95.         delete model_;
  96.         model_ = 0;
  97.     }
  98. }
  99.  
  100. void SoftBody::RegisterObject(Context* context)
  101. {
  102.     context->RegisterFactory<SoftBody>(PHYSICS_CATEGORY);
  103.  
  104.     ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
  105.     MIXED_ACCESSOR_ATTRIBUTE("Physics Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE | AM_NOEDIT);
  106.     MIXED_ACCESSOR_ATTRIBUTE("Physics Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE | AM_NOEDIT);
  107.     ATTRIBUTE("Mass", float, mass_, DEFAULT_SOFT_BODY_MASS, AM_DEFAULT);
  108.     ATTRIBUTE("Collision Layer", int, collisionLayer_, DEFAULT_COLLISION_LAYER, AM_DEFAULT);
  109.     ATTRIBUTE("Collision Mask", int, collisionMask_, DEFAULT_COLLISION_MASK, AM_DEFAULT);
  110.     ACCESSOR_ATTRIBUTE("Use Gravity", GetUseGravity, SetUseGravity, bool, true, AM_DEFAULT);
  111.     ACCESSOR_ATTRIBUTE("Gravity Override", GetGravityOverride, SetGravityOverride, Vector3, Vector3::ZERO, AM_DEFAULT);
  112. }
  113.  
  114. void SoftBody::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
  115. {
  116.     Serializable::OnSetAttribute(attr, src);
  117.  
  118.     // Change of any non-accessor attribute requires the rigid body to be re-added to the physics world
  119.     if (!attr.accessor_)
  120.         readdBody_ = true;
  121. }
  122.  
  123. void SoftBody::ApplyAttributes()
  124. {
  125.     if (readdBody_)
  126.         AddBodyToWorld();
  127. }
  128.  
  129. void SoftBody::OnSetEnabled()
  130. {
  131.     bool enabled = IsEnabledEffective();
  132.  
  133.     if (enabled && !inWorld_)
  134.         AddBodyToWorld();
  135.     else if (!enabled && inWorld_)
  136.         RemoveBodyFromWorld();
  137. }
  138.  
  139. void SoftBody::getWorldTransform(btTransform& worldTrans) const
  140. {
  141.     // We may be in a pathological state where a SoftBody exists without a scene node when this callback is fired,
  142.     // so check to be sure
  143.     if (node_)
  144.     {
  145.         lastPosition_ = node_->GetWorldPosition();
  146.         lastRotation_ = node_->GetWorldRotation();
  147.         worldTrans.setOrigin(ToBtVector3(lastPosition_ + lastRotation_ * centerOfMass_));
  148.         worldTrans.setRotation(ToBtQuaternion(lastRotation_));
  149.     }
  150. }
  151.  
  152. void SoftBody::setWorldTransform(const btTransform& worldTrans)
  153. {
  154.     Quaternion newWorldRotation = ToQuaternion(worldTrans.getRotation());
  155.     Vector3 newWorldPosition = ToVector3(worldTrans.getOrigin()) - newWorldRotation * centerOfMass_;
  156.     SoftBody* parentSoftBody = 0;
  157.  
  158.     // It is possible that the SoftBody component has been kept alive via a shared pointer,
  159.     // while its scene node has already been destroyed
  160.     if (node_)
  161.     {
  162.         // If the rigid body is parented to another rigid body, can not set the transform immediately.
  163.         // In that case store it to PhysicsWorld for delayed assignment
  164.         Node* parent = node_->GetParent();
  165.         if (parent != GetScene() && parent)
  166.             parentSoftBody = parent->GetComponent<SoftBody>();
  167.  
  168.         if (!parentSoftBody)
  169.             ApplyWorldTransform(newWorldPosition, newWorldRotation);
  170.         else
  171.         {
  172.             DelayedWorldTransformSoftBody delayed;
  173.             delayed.softBody_ = this;
  174.             delayed.parentSoftBody_ = parentSoftBody;
  175.             delayed.worldPosition_ = newWorldPosition;
  176.             delayed.worldRotation_ = newWorldRotation;
  177.             physicsWorld_->AddDelayedWorldTransformSoftBody(delayed);
  178.         }
  179.  
  180.         MarkNetworkUpdate();
  181.     }
  182. }
  183.  
  184. void SoftBody::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
  185. {
  186.     if (debug && physicsWorld_ && body_ && IsEnabledEffective())
  187.     {
  188.         physicsWorld_->SetDebugRenderer(debug);
  189.         physicsWorld_->SetDebugDepthTest(depthTest);
  190.  
  191.         btDynamicsWorld* world = physicsWorld_->GetWorld();
  192.         //world->debugDrawObject(body_->getWorldTransform(), shiftedCompoundShape_, IsActive() ? btVector3(1.0f, 1.0f, 1.0f) : btVector3(0.0f, 1.0f, 0.0f));
  193.  
  194.         physicsWorld_->SetDebugRenderer(0);
  195.     }
  196. }
  197.  
  198. void SoftBody::SetMass(float mass)
  199. {
  200.     mass = Max(mass, 0.0f);
  201.  
  202.     if (mass != mass_)
  203.     {
  204.         mass_ = mass;
  205.         AddBodyToWorld();
  206.         MarkNetworkUpdate();
  207.     }
  208. }
  209.  
  210. void SoftBody::SetPosition(const Vector3& position)
  211. {
  212.     if (body_)
  213.     {
  214.         btTransform& worldTrans = body_->getWorldTransform();
  215.         worldTrans.setOrigin(ToBtVector3(position + ToQuaternion(worldTrans.getRotation()) * centerOfMass_));
  216.  
  217.         // When forcing the physics position, set also interpolated position so that there is no jitter
  218.         btTransform interpTrans = body_->getInterpolationWorldTransform();
  219.         interpTrans.setOrigin(worldTrans.getOrigin());
  220.         body_->setInterpolationWorldTransform(interpTrans);
  221.  
  222.         Activate();
  223.         MarkNetworkUpdate();
  224.     }
  225. }
  226.  
  227. void SoftBody::SetRotation(const Quaternion& rotation)
  228. {
  229.     if (body_)
  230.     {
  231.         Vector3 oldPosition = GetPosition();
  232.         btTransform& worldTrans = body_->getWorldTransform();
  233.         worldTrans.setRotation(ToBtQuaternion(rotation));
  234.         if (!centerOfMass_.Equals(Vector3::ZERO))
  235.             worldTrans.setOrigin(ToBtVector3(oldPosition + rotation * centerOfMass_));
  236.  
  237.         btTransform interpTrans = body_->getInterpolationWorldTransform();
  238.         interpTrans.setRotation(worldTrans.getRotation());
  239.         if (!centerOfMass_.Equals(Vector3::ZERO))
  240.             interpTrans.setOrigin(worldTrans.getOrigin());
  241.         body_->setInterpolationWorldTransform(interpTrans);
  242.         //body_->updateInertiaTensor();
  243.  
  244.         Activate();
  245.         MarkNetworkUpdate();
  246.     }
  247. }
  248.  
  249. void SoftBody::SetTransform(const Vector3& position, const Quaternion& rotation)
  250. {
  251.     if (body_)
  252.     {
  253.         btTransform& worldTrans = body_->getWorldTransform();
  254.         worldTrans.setRotation(ToBtQuaternion(rotation));
  255.         worldTrans.setOrigin(ToBtVector3(position + rotation * centerOfMass_));
  256.  
  257.         btTransform interpTrans = body_->getInterpolationWorldTransform();
  258.         interpTrans.setOrigin(worldTrans.getOrigin());
  259.         interpTrans.setRotation(worldTrans.getRotation());
  260.         body_->setInterpolationWorldTransform(interpTrans);
  261.         //body_->updateInertiaTensor();
  262.  
  263.         Activate();
  264.         MarkNetworkUpdate();
  265.     }
  266. }
  267.  
  268.  
  269. void SoftBody::SetUseGravity(bool enable)
  270. {
  271.     if (enable != useGravity_)
  272.     {
  273.         useGravity_ = enable;
  274.         UpdateGravity();
  275.         MarkNetworkUpdate();
  276.     }
  277. }
  278.  
  279. void SoftBody::SetGravityOverride(const Vector3& gravity)
  280. {
  281.     if (gravity != gravityOverride_)
  282.     {
  283.         gravityOverride_ = gravity;
  284.         UpdateGravity();
  285.         MarkNetworkUpdate();
  286.     }
  287. }
  288.  
  289. void SoftBody::SetCollisionLayer(unsigned layer)
  290. {
  291.     if (layer != collisionLayer_)
  292.     {
  293.         collisionLayer_ = layer;
  294.         AddBodyToWorld();
  295.         MarkNetworkUpdate();
  296.     }
  297. }
  298.  
  299. void SoftBody::SetCollisionMask(unsigned mask)
  300. {
  301.     if (mask != collisionMask_)
  302.     {
  303.         collisionMask_ = mask;
  304.         AddBodyToWorld();
  305.         MarkNetworkUpdate();
  306.     }
  307. }
  308.  
  309. void SoftBody::SetCollisionLayerAndMask(unsigned layer, unsigned mask)
  310. {
  311.     if (layer != collisionLayer_ || mask != collisionMask_)
  312.     {
  313.         collisionLayer_ = layer;
  314.         collisionMask_ = mask;
  315.         AddBodyToWorld();
  316.         MarkNetworkUpdate();
  317.     }
  318. }
  319.  
  320. void SoftBody::Activate()
  321. {
  322.     if (body_ && mass_ > 0.0f)
  323.         body_->activate(true);
  324. }
  325.  
  326. void SoftBody::ReAddBodyToWorld()
  327. {
  328.     if (body_ && inWorld_)
  329.         AddBodyToWorld();
  330. }
  331.  
  332. void SoftBody::DisableMassUpdate()
  333. {
  334.     enableMassUpdate_ = false;
  335. }
  336.  
  337. void SoftBody::EnableMassUpdate()
  338. {
  339.     if (!enableMassUpdate_)
  340.     {
  341.         enableMassUpdate_ = true;
  342.         UpdateMass();
  343.     }
  344. }
  345.  
  346. Vector3 SoftBody::GetPosition() const
  347. {
  348.     if (body_)
  349.     {
  350.         const btTransform& transform = body_->getWorldTransform();
  351.         return ToVector3(transform.getOrigin()) - ToQuaternion(transform.getRotation()) * centerOfMass_;
  352.     }
  353.     else
  354.         return Vector3::ZERO;
  355. }
  356.  
  357. Quaternion SoftBody::GetRotation() const
  358. {
  359.     return body_ ? ToQuaternion(body_->getWorldTransform().getRotation()) : Quaternion::IDENTITY;
  360. }
  361.  
  362. void SoftBody::ApplyWorldTransform(const Vector3& newWorldPosition, const Quaternion& newWorldRotation)
  363. {
  364.     // In case of holding an extra reference to the SoftBody, this could be called in a situation
  365.     // where node is already null
  366.     if (!node_ || !physicsWorld_)
  367.         return;
  368.  
  369.     physicsWorld_->SetApplyingTransforms(true);
  370.  
  371.     // Apply transform to the SmoothedTransform component instead of node transform if available
  372.     if (smoothedTransform_)
  373.     {
  374.         smoothedTransform_->SetTargetWorldPosition(newWorldPosition);
  375.         smoothedTransform_->SetTargetWorldRotation(newWorldRotation);
  376.         lastPosition_ = newWorldPosition;
  377.         lastRotation_ = newWorldRotation;
  378.     }
  379.     else
  380.     {
  381.         node_->SetWorldPosition(newWorldPosition);
  382.         node_->SetWorldRotation(newWorldRotation);
  383.         lastPosition_ = node_->GetWorldPosition();
  384.         lastRotation_ = node_->GetWorldRotation();
  385.     }
  386.  
  387.     physicsWorld_->SetApplyingTransforms(false);
  388. }
  389.  
  390. void SoftBody::UpdateMass()
  391. {
  392.     if (!body_ || !enableMassUpdate_)
  393.         return;
  394.  
  395.     if (mass_ > 0.0f)
  396.         body_->setTotalMass(mass_, true);
  397.  
  398. }
  399.  
  400. void SoftBody::UpdateGravity()
  401. {
  402.     if (physicsWorld_ && body_)
  403.     {
  404.         btSoftRigidDynamicsWorld* world_ = (btSoftRigidDynamicsWorld*)physicsWorld_->GetWorld();
  405.         btSoftBodyWorldInfo* softBodyWorldInfo_ = physicsWorld_->GetSoftBodyWorld();
  406.  
  407.         if (useGravity_)
  408.         {
  409.             // If override vector is zero, use world's gravity
  410.             if (gravityOverride_ == Vector3::ZERO)
  411.                 softBodyWorldInfo_->m_gravity = world_->getGravity();
  412.             else
  413.                 softBodyWorldInfo_->m_gravity = ToBtVector3(gravityOverride_);
  414.         }
  415.         else
  416.             softBodyWorldInfo_->m_gravity = btVector3(0.0f, 0.0f, 0.0f);
  417.     }
  418. }
  419.  
  420. void SoftBody::ReleaseBody()
  421. {
  422.     if (body_)
  423.     {
  424.         RemoveBodyFromWorld();
  425.  
  426.         delete body_;
  427.         body_ = 0;
  428.     }
  429. }
  430.  
  431. void SoftBody::OnMarkedDirty(Node* node)
  432. {
  433.     // If node transform changes, apply it back to the physics transform. However, do not do this when a SmoothedTransform
  434.     // is in use, because in that case the node transform will be constantly updated into smoothed, possibly non-physical
  435.     // states; rather follow the SmoothedTransform target transform directly
  436.     // Also, for kinematic objects Bullet asks the position from us, so we do not need to apply ourselves
  437.     if ((!physicsWorld_ || !physicsWorld_->IsApplyingTransforms()) && !smoothedTransform_)
  438.     {
  439.         // Physics operations are not safe from worker threads
  440.         Scene* scene = GetScene();
  441.         if (scene && scene->IsThreadedUpdate())
  442.         {
  443.             scene->DelayedMarkedDirty(this);
  444.             return;
  445.         }
  446.  
  447.         // Check if transform has changed from the last one set in ApplyWorldTransform()
  448.         Vector3 newPosition = node_->GetWorldPosition();
  449.         Quaternion newRotation = node_->GetWorldRotation();
  450.  
  451.         if (!newRotation.Equals(lastRotation_))
  452.         {
  453.             lastRotation_ = newRotation;
  454.             SetRotation(newRotation);
  455.         }
  456.         if (!newPosition.Equals(lastPosition_))
  457.         {
  458.             lastPosition_ = newPosition;
  459.             SetPosition(newPosition);
  460.         }
  461.     }
  462. }
  463.  
  464. void SoftBody::OnNodeSet(Node* node)
  465. {
  466.     if (node)
  467.         node->AddListener(this);
  468. }
  469.  
  470. void SoftBody::OnSceneSet(Scene* scene)
  471. {
  472.     if (scene)
  473.     {
  474.         if (scene == node_)
  475.             LOGWARNING(GetTypeName() + " should not be created to the root scene node");
  476.  
  477.         physicsWorld_ = scene->GetOrCreateComponent<PhysicsWorld>();
  478.         physicsWorld_->AddSoftBody(this);
  479.  
  480.         AddBodyToWorld();
  481.     }
  482.     else
  483.     {
  484.         ReleaseBody();
  485.  
  486.         if (physicsWorld_)
  487.             physicsWorld_->RemoveSoftBody(this);
  488.     }
  489. }
  490.  
  491. void SoftBody::AddBodyToWorld()
  492. {
  493.     if (!physicsWorld_)
  494.         return;
  495.  
  496.     PROFILE(AddBodyToWorld);
  497.  
  498.     if (mass_ < 0.0f)
  499.         mass_ = 0.0f;
  500.  
  501.     if (body_)
  502.         RemoveBodyFromWorld();
  503.     else
  504.     {
  505.         btSoftBodyWorldInfo* softBodyWorldInfo_ = GetPhysicsWorld()->GetSoftBodyWorld();
  506.         body_ = new btSoftBody(softBodyWorldInfo_);
  507.         body_->setUserPointer(this);
  508.     }
  509.  
  510.     UpdateMass();
  511.     UpdateGravity();
  512.  
  513.     int flags = body_->getCollisionFlags();
  514.     body_->setCollisionFlags(flags);
  515.     body_->forceActivationState(mass_ > 0.0f ? DISABLE_DEACTIVATION : ISLAND_SLEEPING);
  516.  
  517.     if (!IsEnabledEffective())
  518.         return;
  519.  
  520.     btSoftRigidDynamicsWorld* world = (btSoftRigidDynamicsWorld*)physicsWorld_->GetWorld();
  521.     world->addSoftBody(body_, (short)collisionLayer_, (short)collisionMask_);
  522.     inWorld_ = true;
  523.     readdBody_ = false;
  524.  
  525.     if (mass_ > 0.0f)
  526.         Activate();
  527. }
  528.  
  529. void SoftBody::RemoveBodyFromWorld()
  530. {
  531.     if (physicsWorld_ && body_ && inWorld_)
  532.     {
  533.         btSoftRigidDynamicsWorld* world = (btSoftRigidDynamicsWorld*)physicsWorld_->GetWorld();
  534.         world->removeSoftBody(body_);
  535.         inWorld_ = false;
  536.     }
  537. }
  538.  
  539. bool SoftBody::IsActive() const
  540. {
  541.     return body_ ? body_->isActive() : false;
  542. }
  543.  
  544. void SoftBody::SetModel(Model* model)
  545. {
  546.     if (model != model_)
  547.     {
  548.         model_ = SharedPtr<Model>(model);
  549.         UpdateSoftBodyFromModel();
  550.     }
  551. }
  552.  
  553. void SoftBody::UpdateSoftBodyFromModel()
  554. {
  555.     if (model_)
  556.     {
  557.         bool sucess = false;
  558.  
  559.         if (body_)
  560.         {
  561.             RemoveBodyFromWorld();
  562.         }
  563.  
  564.         // get only first geometry
  565.         if (model_->GetNumGeometries() > 0)
  566.         {
  567.             Geometry* geometry = model_->GetGeometry(0, 0);
  568.            
  569.             VertexBuffer* vb = geometry->GetVertexBuffer(0);
  570.             IndexBuffer* ib = geometry->GetIndexBuffer();
  571.             sucess = CreateBodyFromTriMesh(vb, ib, true);
  572.         }
  573.  
  574.         // add it
  575.         if (sucess)
  576.         {
  577.             AddBodyToWorld();
  578.         }
  579.     }
  580. }
  581.  
  582. bool SoftBody::CreateBodyFromTriMesh(VertexBuffer* vb, IndexBuffer* ib, bool randomizeConstraints)
  583. {
  584.     bool bConstructed = false;
  585.  
  586.     if (vb && ib)
  587.     {
  588.         btAlignedObjectArray<bool>      chks;
  589.         btAlignedObjectArray<btVector3>   vtx;
  590.  
  591.         // save vertexbuffer ptr
  592.         VertexBuffer* m_pVertexBuffer = vb;
  593.  
  594.         // copy vertex buffer
  595.         const unsigned char *pVertexData = (const unsigned char*)m_pVertexBuffer->Lock(0, m_pVertexBuffer->GetVertexCount());
  596.  
  597.         if (pVertexData)
  598.         {
  599.             unsigned numVertices = m_pVertexBuffer->GetVertexCount();
  600.             unsigned vertexSize = m_pVertexBuffer->GetVertexSize();
  601.  
  602.             vtx.resize(numVertices);
  603.  
  604.             // copy the original verts
  605.             for (unsigned i = 0; i < numVertices; ++i)
  606.             {
  607.                 const Vector3& src = *reinterpret_cast<const Vector3*>(pVertexData + i * vertexSize);
  608.                 vtx[i] = ToBtVector3(src);
  609.             }
  610.             m_pVertexBuffer->Unlock();
  611.         }
  612.  
  613.         // Create softbody
  614.         btSoftBodyWorldInfo* softBodyWorldInfo_ = GetPhysicsWorld()->GetSoftBodyWorld();           
  615.         body_ = new btSoftBody(softBodyWorldInfo_, vtx.size(), &vtx[0], 0);
  616.  
  617.         // copy indexbuffer
  618.         const unsigned *pIndexData = (const unsigned *)ib->Lock(0, ib->GetIndexCount());
  619.         const unsigned short *pUShortData = (const unsigned short *)pIndexData;
  620.         if (pIndexData)
  621.         {
  622.             unsigned numIndeces = ib->GetIndexCount();
  623.             unsigned indexSize = ib->GetIndexSize();
  624.  
  625.             int ntriangles = (int)numIndeces / 3;
  626.             int maxidx = 0;
  627.             int i;
  628.  
  629.             if (indexSize == sizeof(unsigned short))
  630.             {
  631.                 for (i = 0; i < (int)numIndeces; ++i)
  632.                 {
  633.                     unsigned uidx = pUShortData[i];
  634.                     maxidx = Max(uidx, maxidx);
  635.                 }
  636.             }
  637.             else if (indexSize == sizeof(unsigned))
  638.             {
  639.                 for (i = 0; i < (int)numIndeces; ++i)
  640.                 {
  641.                     unsigned uidx = pIndexData[i];
  642.                     maxidx = Max(uidx, maxidx);
  643.                 }
  644.             }
  645.             ++maxidx;
  646.             chks.resize(maxidx*maxidx, false);
  647.  
  648.             for (i = 0; i < (int)numIndeces; i += 3)
  649.             {
  650.                 int idx[3];
  651.                 if (indexSize == sizeof(unsigned short))
  652.                 {
  653.                     idx[0] = (int)pUShortData[i];
  654.                     idx[1] = (int)pUShortData[i + 1];
  655.                     idx[2] = (int)pUShortData[i + 2];
  656.                 }
  657.                 else
  658.                 {
  659.                     idx[0] = (int)pIndexData[i];
  660.                     idx[1] = (int)pIndexData[i + 1];
  661.                     idx[2] = (int)pIndexData[i + 2];
  662.                 }
  663.  
  664. #define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
  665.                 for (int j = 2, k = 0; k<3; j = k++)
  666.                 {
  667.                     if (!chks[IDX(idx[j], idx[k])])
  668.                     {
  669.                         chks[IDX(idx[j], idx[k])] = true;
  670.                         chks[IDX(idx[k], idx[j])] = true;
  671.                         body_->appendLink(idx[j], idx[k]);
  672.                     }
  673.                 }
  674. #undef IDX
  675.                 body_->appendFace(idx[0], idx[1], idx[2]);
  676.             }
  677.             ib->Unlock();
  678.         }
  679.  
  680.         if (randomizeConstraints)
  681.         {
  682.             body_->randomizeConstraints();
  683.         }
  684.  
  685.         // straight out of bullet's softbody demo for trimesh
  686.         body_->m_materials[0]->m_kLST = 0.1;
  687.         body_->m_cfg.kMT = 0.05;
  688.  
  689.         btMatrix3x3   m;
  690.         m.setEulerZYX(0, 0, 0);
  691.  
  692.         // create methods for these
  693.         if (node_)
  694.         {
  695.             SetPosition(node_->GetWorldPosition());
  696.             body_->transform(btTransform(m, btVector3(0, 0, 0)));
  697.             body_->scale(ToBtVector3(node_->GetWorldScale()));
  698.         }
  699.         UpdateMass();
  700.  
  701.         body_->setPose(true, true); // i don't know what this does
  702.  
  703.         bConstructed = true;
  704.     }
  705.  
  706.     return bConstructed;
  707. }
  708.  
  709. void SoftBody::InitDrawable(Drawable* drawable)
  710. {
  711.     if (body_  && physicsWorld_)
  712.     if (drawable)
  713.     {
  714.         Vector<SourceBatch> batch = drawable->GetBatches();
  715.         if (batch.Size() > 0)
  716.         {
  717.        
  718.             VertexBuffer* destVb = batch[0].geometry_->GetVertexBuffer(0);
  719.             IndexBuffer* destIb = batch[0].geometry_->GetIndexBuffer();
  720.  
  721.             // copy original data as first
  722.             Geometry* geometry = model_->GetGeometry(0, 0);
  723.             VertexBuffer* originalVb = geometry->GetVertexBuffer(0);
  724.             IndexBuffer* originalIb = geometry->GetIndexBuffer();
  725.  
  726.             unsigned int vbCount = originalVb->GetVertexCount();
  727.             unsigned int vertSize = originalVb->GetVertexSize();
  728.             unsigned int ibCount = originalIb->GetIndexCount();
  729.  
  730.             destVb->SetSize(vbCount*vertSize, originalVb->GetElementMask(), true);
  731.             destIb->SetSize(ibCount, originalIb->GetIndexSize() == 4 ? true : false, true);
  732.            
  733.         }
  734.     }
  735.  
  736. }
  737.  
  738. void SoftBody::UpdateDrawable(Drawable* drawable)
  739. {
  740.     if (body_  && physicsWorld_)
  741.         if (drawable)
  742.         {
  743.             Vector<SourceBatch> batch = drawable->GetBatches();
  744.             if (batch.Size() > 0)
  745.             {
  746.                 VertexBuffer* destVb = batch[0].geometry_->GetVertexBuffer(0);
  747.                 IndexBuffer* destIb = batch[0].geometry_->GetIndexBuffer();
  748.  
  749.                 // copy original data at first
  750.                 Geometry* geometry = model_->GetGeometry(0, 0);
  751.                 VertexBuffer* originalVb = geometry->GetVertexBuffer(0);
  752.                 IndexBuffer* originalIb = geometry->GetIndexBuffer();
  753.  
  754.                 unsigned int vbCount = originalVb->GetVertexCount();
  755.                 unsigned int vertSize = originalVb->GetVertexSize();
  756.                 unsigned int ibCount = originalIb->GetIndexCount();
  757.                
  758.  
  759.                 if (destVb->SetSize(vertSize * vbCount, originalVb->GetElementMask(), true))
  760.                 {
  761.                     char* destPointer = (char*) destVb->Lock(0, vbCount, true);
  762.                     char* sourcePointer = (char*)originalVb->Lock(0, vbCount, false);
  763.  
  764.                     memcpy(destPointer, sourcePointer, vertSize * vbCount);
  765.  
  766.                     destVb->Unlock();
  767.                     originalVb->Unlock();
  768.  
  769.                     // and after copy nodes from softbody
  770.                     destPointer = (char*)destVb->Lock(0, vbCount);
  771.                     for (unsigned int i = 0; i < body_->m_nodes.size(); i++)
  772.                     {
  773.                         btSoftBody::Node& n = body_->m_nodes[i];
  774.                         Vector3 &src = *reinterpret_cast<Vector3*>(destPointer + i * vertSize);
  775.                         src = ToVector3(n.m_x);
  776.                     }
  777.  
  778.                     destVb->Unlock();
  779.  
  780.                 }
  781.             }
  782.         }
  783. }
  784.  
  785.  
  786.  
  787. }
Advertisement
Add Comment
Please, Sign In to add comment