initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
55
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyContactListener.h
vendored
Normal file
55
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyContactListener.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
class Body;
|
||||
class SoftBodyManifold;
|
||||
|
||||
/// Return value for the OnSoftBodyContactValidate callback. Determines if the contact will be processed or not.
|
||||
enum class SoftBodyValidateResult
|
||||
{
|
||||
AcceptContact, ///< Accept this contact
|
||||
RejectContact, ///< Reject this contact
|
||||
};
|
||||
|
||||
/// Contact settings for a soft body contact.
|
||||
/// The values are filled in with their defaults by the system so the callback doesn't need to modify anything, but it can if it wants to.
|
||||
class SoftBodyContactSettings
|
||||
{
|
||||
public:
|
||||
float mInvMassScale1 = 1.0f; ///< Scale factor for the inverse mass of the soft body (0 = infinite mass, 1 = use original mass, 2 = body has half the mass). For the same contact pair, you should strive to keep the value the same over time.
|
||||
float mInvMassScale2 = 1.0f; ///< Scale factor for the inverse mass of the other body (0 = infinite mass, 1 = use original mass, 2 = body has half the mass). For the same contact pair, you should strive to keep the value the same over time.
|
||||
float mInvInertiaScale2 = 1.0f; ///< Scale factor for the inverse inertia of the other body (usually same as mInvMassScale2)
|
||||
bool mIsSensor; ///< If the contact should be treated as a sensor vs body contact (no collision response)
|
||||
};
|
||||
|
||||
/// A listener class that receives collision contact events for soft bodies against rigid bodies.
|
||||
/// It can be registered with the PhysicsSystem.
|
||||
class SoftBodyContactListener
|
||||
{
|
||||
public:
|
||||
/// Ensure virtual destructor
|
||||
virtual ~SoftBodyContactListener() = default;
|
||||
|
||||
/// Called whenever the soft body's aabox overlaps with another body's aabox (so receiving this callback doesn't tell if any of the vertices will collide).
|
||||
/// This callback can be used to change the behavior of the collision response for all vertices in the soft body or to completely reject the contact.
|
||||
/// Note that this callback is called when all bodies are locked, so don't use any locking functions!
|
||||
/// @param inSoftBody The soft body that collided. It is safe to access this as the soft body is only updated on the current thread.
|
||||
/// @param inOtherBody The other body that collided. Note that accessing the position/orientation/velocity of inOtherBody may result in a race condition as other threads may be modifying the body at the same time.
|
||||
/// @param ioSettings The settings for all contact points that are generated by this collision.
|
||||
/// @return Whether the contact should be processed or not.
|
||||
virtual SoftBodyValidateResult OnSoftBodyContactValidate([[maybe_unused]] const Body &inSoftBody, [[maybe_unused]] const Body &inOtherBody, [[maybe_unused]] SoftBodyContactSettings &ioSettings) { return SoftBodyValidateResult::AcceptContact; }
|
||||
|
||||
/// Called after all contact points for a soft body have been handled. You only receive one callback per body pair per simulation step and can use inManifold to iterate through all contacts.
|
||||
/// Note that this callback is called when all bodies are locked, so don't use any locking functions!
|
||||
/// You will receive a single callback for a soft body per simulation step for performance reasons, this callback will apply to all vertices in the soft body.
|
||||
/// @param inSoftBody The soft body that collided. It is safe to access this as the soft body is only updated on the current thread.
|
||||
/// @param inManifold The manifold that describes the contact surface between the two bodies. Other bodies may be modified by other threads during this callback.
|
||||
virtual void OnSoftBodyContactAdded([[maybe_unused]] const Body &inSoftBody, const SoftBodyManifold &inManifold) { /* Do nothing */ }
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
122
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.cpp
vendored
Normal file
122
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.cpp
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/ObjectStream/TypeDeclarations.h>
|
||||
#include <Jolt/Core/StreamIn.h>
|
||||
#include <Jolt/Core/StreamOut.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(SoftBodyCreationSettings)
|
||||
{
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mSettings)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mPosition)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mRotation)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mUserData)
|
||||
JPH_ADD_ENUM_ATTRIBUTE(SoftBodyCreationSettings, mObjectLayer)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mCollisionGroup)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mNumIterations)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mLinearDamping)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mMaxLinearVelocity)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mRestitution)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mFriction)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mPressure)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mGravityFactor)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mUpdatePosition)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mMakeRotationIdentity)
|
||||
JPH_ADD_ATTRIBUTE(SoftBodyCreationSettings, mAllowSleeping)
|
||||
}
|
||||
|
||||
void SoftBodyCreationSettings::SaveBinaryState(StreamOut &inStream) const
|
||||
{
|
||||
inStream.Write(mPosition);
|
||||
inStream.Write(mRotation);
|
||||
inStream.Write(mUserData);
|
||||
inStream.Write(mObjectLayer);
|
||||
mCollisionGroup.SaveBinaryState(inStream);
|
||||
inStream.Write(mNumIterations);
|
||||
inStream.Write(mLinearDamping);
|
||||
inStream.Write(mMaxLinearVelocity);
|
||||
inStream.Write(mRestitution);
|
||||
inStream.Write(mFriction);
|
||||
inStream.Write(mPressure);
|
||||
inStream.Write(mGravityFactor);
|
||||
inStream.Write(mUpdatePosition);
|
||||
inStream.Write(mMakeRotationIdentity);
|
||||
inStream.Write(mAllowSleeping);
|
||||
}
|
||||
|
||||
void SoftBodyCreationSettings::RestoreBinaryState(StreamIn &inStream)
|
||||
{
|
||||
inStream.Read(mPosition);
|
||||
inStream.Read(mRotation);
|
||||
inStream.Read(mUserData);
|
||||
inStream.Read(mObjectLayer);
|
||||
mCollisionGroup.RestoreBinaryState(inStream);
|
||||
inStream.Read(mNumIterations);
|
||||
inStream.Read(mLinearDamping);
|
||||
inStream.Read(mMaxLinearVelocity);
|
||||
inStream.Read(mRestitution);
|
||||
inStream.Read(mFriction);
|
||||
inStream.Read(mPressure);
|
||||
inStream.Read(mGravityFactor);
|
||||
inStream.Read(mUpdatePosition);
|
||||
inStream.Read(mMakeRotationIdentity);
|
||||
inStream.Read(mAllowSleeping);
|
||||
}
|
||||
|
||||
void SoftBodyCreationSettings::SaveWithChildren(StreamOut &inStream, SharedSettingsToIDMap *ioSharedSettingsMap, MaterialToIDMap *ioMaterialMap, GroupFilterToIDMap *ioGroupFilterMap) const
|
||||
{
|
||||
// Save creation settings
|
||||
SaveBinaryState(inStream);
|
||||
|
||||
// Save shared settings
|
||||
if (ioSharedSettingsMap != nullptr && ioMaterialMap != nullptr)
|
||||
mSettings->SaveWithMaterials(inStream, *ioSharedSettingsMap, *ioMaterialMap);
|
||||
else
|
||||
inStream.Write(~uint32(0));
|
||||
|
||||
// Save group filter
|
||||
StreamUtils::SaveObjectReference(inStream, mCollisionGroup.GetGroupFilter(), ioGroupFilterMap);
|
||||
}
|
||||
|
||||
SoftBodyCreationSettings::SBCSResult SoftBodyCreationSettings::sRestoreWithChildren(StreamIn &inStream, IDToSharedSettingsMap &ioSharedSettingsMap, IDToMaterialMap &ioMaterialMap, IDToGroupFilterMap &ioGroupFilterMap)
|
||||
{
|
||||
SBCSResult result;
|
||||
|
||||
// Read creation settings
|
||||
SoftBodyCreationSettings settings;
|
||||
settings.RestoreBinaryState(inStream);
|
||||
if (inStream.IsEOF() || inStream.IsFailed())
|
||||
{
|
||||
result.SetError("Error reading body creation settings");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read shared settings
|
||||
SoftBodySharedSettings::SettingsResult settings_result = SoftBodySharedSettings::sRestoreWithMaterials(inStream, ioSharedSettingsMap, ioMaterialMap);
|
||||
if (settings_result.HasError())
|
||||
{
|
||||
result.SetError(settings_result.GetError());
|
||||
return result;
|
||||
}
|
||||
settings.mSettings = settings_result.Get();
|
||||
|
||||
// Read group filter
|
||||
Result gfresult = StreamUtils::RestoreObjectReference(inStream, ioGroupFilterMap);
|
||||
if (gfresult.HasError())
|
||||
{
|
||||
result.SetError(gfresult.GetError());
|
||||
return result;
|
||||
}
|
||||
settings.mCollisionGroup.SetGroupFilter(gfresult.Get());
|
||||
|
||||
result.Set(settings);
|
||||
return result;
|
||||
}
|
||||
|
||||
JPH_NAMESPACE_END
|
73
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.h
vendored
Normal file
73
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.h
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Physics/SoftBody/SoftBodySharedSettings.h>
|
||||
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
||||
#include <Jolt/Physics/Collision/CollisionGroup.h>
|
||||
#include <Jolt/ObjectStream/SerializableObject.h>
|
||||
#include <Jolt/Core/StreamUtils.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
/// This class contains the information needed to create a soft body object
|
||||
/// Note: Soft bodies are still in development and come with several caveats. Read the Architecture and API documentation for more information!
|
||||
class JPH_EXPORT SoftBodyCreationSettings
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, SoftBodyCreationSettings)
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
SoftBodyCreationSettings() = default;
|
||||
SoftBodyCreationSettings(const SoftBodySharedSettings *inSettings, RVec3Arg inPosition, QuatArg inRotation, ObjectLayer inObjectLayer) : mSettings(inSettings), mPosition(inPosition), mRotation(inRotation), mObjectLayer(inObjectLayer) { }
|
||||
|
||||
/// Saves the state of this object in binary form to inStream. Doesn't store the shared settings nor the group filter.
|
||||
void SaveBinaryState(StreamOut &inStream) const;
|
||||
|
||||
/// Restore the state of this object from inStream. Doesn't restore the shared settings nor the group filter.
|
||||
void RestoreBinaryState(StreamIn &inStream);
|
||||
|
||||
using GroupFilterToIDMap = StreamUtils::ObjectToIDMap<GroupFilter>;
|
||||
using IDToGroupFilterMap = StreamUtils::IDToObjectMap<GroupFilter>;
|
||||
using SharedSettingsToIDMap = SoftBodySharedSettings::SharedSettingsToIDMap;
|
||||
using IDToSharedSettingsMap = SoftBodySharedSettings::IDToSharedSettingsMap;
|
||||
using MaterialToIDMap = StreamUtils::ObjectToIDMap<PhysicsMaterial>;
|
||||
using IDToMaterialMap = StreamUtils::IDToObjectMap<PhysicsMaterial>;
|
||||
|
||||
/// Save this body creation settings, its shared settings and group filter. Pass in an empty map in ioSharedSettingsMap / ioMaterialMap / ioGroupFilterMap or reuse the same map while saving multiple shapes to the same stream in order to avoid writing duplicates.
|
||||
/// Pass nullptr to ioSharedSettingsMap and ioMaterial map to skip saving shared settings and materials
|
||||
/// Pass nullptr to ioGroupFilterMap to skip saving group filters
|
||||
void SaveWithChildren(StreamOut &inStream, SharedSettingsToIDMap *ioSharedSettingsMap, MaterialToIDMap *ioMaterialMap, GroupFilterToIDMap *ioGroupFilterMap) const;
|
||||
|
||||
using SBCSResult = Result<SoftBodyCreationSettings>;
|
||||
|
||||
/// Restore a shape, all its children and materials. Pass in an empty map in ioSharedSettingsMap / ioMaterialMap / ioGroupFilterMap or reuse the same map while reading multiple shapes from the same stream in order to restore duplicates.
|
||||
static SBCSResult sRestoreWithChildren(StreamIn &inStream, IDToSharedSettingsMap &ioSharedSettingsMap, IDToMaterialMap &ioMaterialMap, IDToGroupFilterMap &ioGroupFilterMap);
|
||||
|
||||
RefConst<SoftBodySharedSettings> mSettings; ///< Defines the configuration of this soft body
|
||||
|
||||
RVec3 mPosition { RVec3::sZero() }; ///< Initial position of the soft body
|
||||
Quat mRotation { Quat::sIdentity() }; ///< Initial rotation of the soft body
|
||||
|
||||
/// User data value (can be used by application)
|
||||
uint64 mUserData = 0;
|
||||
|
||||
///@name Collision settings
|
||||
ObjectLayer mObjectLayer = 0; ///< The collision layer this body belongs to (determines if two objects can collide)
|
||||
CollisionGroup mCollisionGroup; ///< The collision group this body belongs to (determines if two objects can collide)
|
||||
|
||||
uint32 mNumIterations = 5; ///< Number of solver iterations
|
||||
float mLinearDamping = 0.1f; ///< Linear damping: dv/dt = -mLinearDamping * v
|
||||
float mMaxLinearVelocity = 500.0f; ///< Maximum linear velocity that a vertex can reach (m/s)
|
||||
float mRestitution = 0.0f; ///< Restitution when colliding
|
||||
float mFriction = 0.2f; ///< Friction coefficient when colliding
|
||||
float mPressure = 0.0f; ///< n * R * T, amount of substance * ideal gas constant * absolute temperature, see https://en.wikipedia.org/wiki/Pressure
|
||||
float mGravityFactor = 1.0f; ///< Value to multiply gravity with for this body
|
||||
bool mUpdatePosition = true; ///< Update the position of the body while simulating (set to false for something that is attached to the static world)
|
||||
bool mMakeRotationIdentity = true; ///< Bake specified mRotation in the vertices and set the body rotation to identity (simulation is slightly more accurate if the rotation of a soft body is kept to identity)
|
||||
bool mAllowSleeping = true; ///< If this body can go to sleep or not
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
74
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyManifold.h
vendored
Normal file
74
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyManifold.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
/// An interface to query which vertices of a soft body are colliding with other bodies
|
||||
class SoftBodyManifold
|
||||
{
|
||||
public:
|
||||
/// Get the vertices of the soft body for iterating
|
||||
const Array<SoftBodyVertex> & GetVertices() const { return mVertices; }
|
||||
|
||||
/// Check if a vertex has collided with something in this update
|
||||
JPH_INLINE bool HasContact(const SoftBodyVertex &inVertex) const
|
||||
{
|
||||
return inVertex.mHasContact;
|
||||
}
|
||||
|
||||
/// Get the local space contact point (multiply by GetCenterOfMassTransform() of the soft body to get world space)
|
||||
JPH_INLINE Vec3 GetLocalContactPoint(const SoftBodyVertex &inVertex) const
|
||||
{
|
||||
return inVertex.mPosition - inVertex.mCollisionPlane.SignedDistance(inVertex.mPosition) * inVertex.mCollisionPlane.GetNormal();
|
||||
}
|
||||
|
||||
/// Get the contact normal for the vertex (assumes there is a contact).
|
||||
JPH_INLINE Vec3 GetContactNormal(const SoftBodyVertex &inVertex) const
|
||||
{
|
||||
return -inVertex.mCollisionPlane.GetNormal();
|
||||
}
|
||||
|
||||
/// Get the body with which the vertex has collided in this update
|
||||
JPH_INLINE BodyID GetContactBodyID(const SoftBodyVertex &inVertex) const
|
||||
{
|
||||
return inVertex.mHasContact? mCollidingShapes[inVertex.mCollidingShapeIndex].mBodyID : BodyID();
|
||||
}
|
||||
|
||||
/// Get the number of sensors that are in contact with the soft body
|
||||
JPH_INLINE uint GetNumSensorContacts() const
|
||||
{
|
||||
return (uint)mCollidingSensors.size();
|
||||
}
|
||||
|
||||
/// Get the i-th sensor that is in contact with the soft body
|
||||
JPH_INLINE BodyID GetSensorContactBodyID(uint inIndex) const
|
||||
{
|
||||
return mCollidingSensors[inIndex].mBodyID;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Allow SoftBodyMotionProperties to construct us
|
||||
friend class SoftBodyMotionProperties;
|
||||
|
||||
/// Constructor
|
||||
explicit SoftBodyManifold(const SoftBodyMotionProperties *inMotionProperties) :
|
||||
mVertices(inMotionProperties->mVertices),
|
||||
mCollidingShapes(inMotionProperties->mCollidingShapes),
|
||||
mCollidingSensors(inMotionProperties->mCollidingSensors)
|
||||
{
|
||||
}
|
||||
|
||||
using CollidingShape = SoftBodyMotionProperties::CollidingShape;
|
||||
using CollidingSensor = SoftBodyMotionProperties::CollidingSensor;
|
||||
|
||||
const Array<SoftBodyVertex> & mVertices;
|
||||
const Array<CollidingShape> & mCollidingShapes;
|
||||
const Array<CollidingSensor> & mCollidingSensors;
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
1324
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp
vendored
Normal file
1324
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
298
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h
vendored
Normal file
298
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Geometry/AABox.h>
|
||||
#include <Jolt/Physics/Body/BodyID.h>
|
||||
#include <Jolt/Physics/Body/MotionProperties.h>
|
||||
#include <Jolt/Physics/Collision/TransformedShape.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodySharedSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyVertex.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyUpdateContext.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
class PhysicsSystem;
|
||||
class BodyInterface;
|
||||
class BodyLockInterface;
|
||||
struct PhysicsSettings;
|
||||
class Body;
|
||||
class Shape;
|
||||
class SoftBodyCreationSettings;
|
||||
class TempAllocator;
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
class DebugRenderer;
|
||||
enum class ESoftBodyConstraintColor;
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
|
||||
/// This class contains the runtime information of a soft body.
|
||||
//
|
||||
// Based on: XPBD, Extended Position Based Dynamics, Matthias Muller, Ten Minute Physics
|
||||
// See: https://matthias-research.github.io/pages/tenMinutePhysics/09-xpbd.pdf
|
||||
class JPH_EXPORT SoftBodyMotionProperties : public MotionProperties
|
||||
{
|
||||
public:
|
||||
using Vertex = SoftBodyVertex;
|
||||
using Edge = SoftBodySharedSettings::Edge;
|
||||
using Face = SoftBodySharedSettings::Face;
|
||||
using DihedralBend = SoftBodySharedSettings::DihedralBend;
|
||||
using Volume = SoftBodySharedSettings::Volume;
|
||||
using InvBind = SoftBodySharedSettings::InvBind;
|
||||
using SkinWeight = SoftBodySharedSettings::SkinWeight;
|
||||
using Skinned = SoftBodySharedSettings::Skinned;
|
||||
using LRA = SoftBodySharedSettings::LRA;
|
||||
|
||||
/// Initialize the soft body motion properties
|
||||
void Initialize(const SoftBodyCreationSettings &inSettings);
|
||||
|
||||
/// Get the shared settings of the soft body
|
||||
const SoftBodySharedSettings * GetSettings() const { return mSettings; }
|
||||
|
||||
/// Get the vertices of the soft body
|
||||
const Array<Vertex> & GetVertices() const { return mVertices; }
|
||||
Array<Vertex> & GetVertices() { return mVertices; }
|
||||
|
||||
/// Access an individual vertex
|
||||
const Vertex & GetVertex(uint inIndex) const { return mVertices[inIndex]; }
|
||||
Vertex & GetVertex(uint inIndex) { return mVertices[inIndex]; }
|
||||
|
||||
/// Get the materials of the soft body
|
||||
const PhysicsMaterialList & GetMaterials() const { return mSettings->mMaterials; }
|
||||
|
||||
/// Get the faces of the soft body
|
||||
const Array<Face> & GetFaces() const { return mSettings->mFaces; }
|
||||
|
||||
/// Access to an individual face
|
||||
const Face & GetFace(uint inIndex) const { return mSettings->mFaces[inIndex]; }
|
||||
|
||||
/// Get the number of solver iterations
|
||||
uint32 GetNumIterations() const { return mNumIterations; }
|
||||
void SetNumIterations(uint32 inNumIterations) { mNumIterations = inNumIterations; }
|
||||
|
||||
/// Get the pressure of the soft body
|
||||
float GetPressure() const { return mPressure; }
|
||||
void SetPressure(float inPressure) { mPressure = inPressure; }
|
||||
|
||||
/// Update the position of the body while simulating (set to false for something that is attached to the static world)
|
||||
bool GetUpdatePosition() const { return mUpdatePosition; }
|
||||
void SetUpdatePosition(bool inUpdatePosition) { mUpdatePosition = inUpdatePosition; }
|
||||
|
||||
/// Global setting to turn on/off skin constraints
|
||||
bool GetEnableSkinConstraints() const { return mEnableSkinConstraints; }
|
||||
void SetEnableSkinConstraints(bool inEnableSkinConstraints) { mEnableSkinConstraints = inEnableSkinConstraints; }
|
||||
|
||||
/// Multiplier applied to Skinned::mMaxDistance to allow tightening or loosening of the skin constraints. 0 to hard skin all vertices.
|
||||
float GetSkinnedMaxDistanceMultiplier() const { return mSkinnedMaxDistanceMultiplier; }
|
||||
void SetSkinnedMaxDistanceMultiplier(float inSkinnedMaxDistanceMultiplier) { mSkinnedMaxDistanceMultiplier = inSkinnedMaxDistanceMultiplier; }
|
||||
|
||||
/// Get local bounding box
|
||||
const AABox & GetLocalBounds() const { return mLocalBounds; }
|
||||
|
||||
/// Get the volume of the soft body. Note can become negative if the shape is inside out!
|
||||
float GetVolume() const { return GetVolumeTimesSix() / 6.0f; }
|
||||
|
||||
/// Calculate the total mass and inertia of this body based on the current state of the vertices
|
||||
void CalculateMassAndInertia();
|
||||
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
/// Draw the state of a soft body
|
||||
void DrawVertices(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const;
|
||||
void DrawVertexVelocities(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const;
|
||||
void DrawEdgeConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, ESoftBodyConstraintColor inConstraintColor) const;
|
||||
void DrawBendConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, ESoftBodyConstraintColor inConstraintColor) const;
|
||||
void DrawVolumeConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, ESoftBodyConstraintColor inConstraintColor) const;
|
||||
void DrawSkinConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, ESoftBodyConstraintColor inConstraintColor) const;
|
||||
void DrawLRAConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, ESoftBodyConstraintColor inConstraintColor) const;
|
||||
void DrawPredictedBounds(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const;
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
|
||||
/// Saving state for replay
|
||||
void SaveState(StateRecorder &inStream) const;
|
||||
|
||||
/// Restoring state for replay
|
||||
void RestoreState(StateRecorder &inStream);
|
||||
|
||||
/// Skin vertices to supplied joints, information is used by the skinned constraints.
|
||||
/// @param inCenterOfMassTransform Value of Body::GetCenterOfMassTransform().
|
||||
/// @param inJointMatrices The joint matrices must be expressed relative to inCenterOfMassTransform.
|
||||
/// @param inNumJoints Indicates how large the inJointMatrices array is (used only for validating out of bounds).
|
||||
/// @param inHardSkinAll Can be used to position all vertices on the skinned vertices and can be used to hard reset the soft body.
|
||||
/// @param ioTempAllocator Allocator.
|
||||
void SkinVertices(RMat44Arg inCenterOfMassTransform, const Mat44 *inJointMatrices, uint inNumJoints, bool inHardSkinAll, TempAllocator &ioTempAllocator);
|
||||
|
||||
/// This function allows you to update the soft body immediately without going through the PhysicsSystem.
|
||||
/// This is useful if the soft body is teleported and needs to 'settle' or it can be used if a the soft body
|
||||
/// is not added to the PhysicsSystem and needs to be updated manually. One reason for not adding it to the
|
||||
/// PhysicsSystem is that you might want to update a soft body immediately after updating an animated object
|
||||
/// that has the soft body attached to it. If the soft body is added to the PhysicsSystem it will be updated
|
||||
/// by it, so calling this function will effectively update it twice. Note that when you use this function,
|
||||
/// only the current thread will be used, whereas if you update through the PhysicsSystem, multiple threads may
|
||||
/// be used.
|
||||
/// Note that this will bypass any sleep checks. Since the dynamic objects that the soft body touches
|
||||
/// will not move during this call, there can be simulation artifacts if you call this function multiple times
|
||||
/// without running the physics simulation step.
|
||||
void CustomUpdate(float inDeltaTime, Body &ioSoftBody, PhysicsSystem &inSystem);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// FUNCTIONS BELOW THIS LINE ARE FOR INTERNAL USE ONLY
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/// Initialize the update context. Not part of the public API.
|
||||
void InitializeUpdateContext(float inDeltaTime, Body &inSoftBody, const PhysicsSystem &inSystem, SoftBodyUpdateContext &ioContext);
|
||||
|
||||
/// Do a broad phase check and collect all bodies that can possibly collide with this soft body. Not part of the public API.
|
||||
void DetermineCollidingShapes(const SoftBodyUpdateContext &inContext, const PhysicsSystem &inSystem, const BodyLockInterface &inBodyLockInterface);
|
||||
|
||||
/// Return code for ParallelUpdate
|
||||
enum class EStatus
|
||||
{
|
||||
NoWork = 1 << 0, ///< No work was done because other threads were still working on a batch that cannot run concurrently
|
||||
DidWork = 1 << 1, ///< Work was done to progress the update
|
||||
Done = 1 << 2, ///< All work is done
|
||||
};
|
||||
|
||||
/// Update the soft body, will process a batch of work. Not part of the public API.
|
||||
EStatus ParallelUpdate(SoftBodyUpdateContext &ioContext, const PhysicsSettings &inPhysicsSettings);
|
||||
|
||||
/// Update the velocities of all rigid bodies that we collided with. Not part of the public API.
|
||||
void UpdateRigidBodyVelocities(const SoftBodyUpdateContext &inContext, BodyInterface &inBodyInterface);
|
||||
|
||||
private:
|
||||
// SoftBodyManifold needs to have access to CollidingShape
|
||||
friend class SoftBodyManifold;
|
||||
|
||||
// Information about a leaf shape that we're colliding with
|
||||
struct LeafShape
|
||||
{
|
||||
LeafShape() = default;
|
||||
LeafShape(Mat44Arg inTransform, Vec3Arg inScale, const Shape *inShape) : mTransform(inTransform), mScale(inScale), mShape(inShape) { }
|
||||
|
||||
Mat44 mTransform; ///< Transform of the shape relative to the soft body
|
||||
Vec3 mScale; ///< Scale of the shape
|
||||
RefConst<Shape> mShape; ///< Shape
|
||||
};
|
||||
|
||||
// Collect information about the colliding bodies
|
||||
struct CollidingShape
|
||||
{
|
||||
/// Get the velocity of a point on this body
|
||||
Vec3 GetPointVelocity(Vec3Arg inPointRelativeToCOM) const
|
||||
{
|
||||
return mLinearVelocity + mAngularVelocity.Cross(inPointRelativeToCOM);
|
||||
}
|
||||
|
||||
Mat44 mCenterOfMassTransform; ///< Transform of the body relative to the soft body
|
||||
Array<LeafShape> mShapes; ///< Leaf shapes of the body we hit
|
||||
BodyID mBodyID; ///< Body ID of the body we hit
|
||||
EMotionType mMotionType; ///< Motion type of the body we hit
|
||||
float mInvMass; ///< Inverse mass of the body we hit
|
||||
float mFriction; ///< Combined friction of the two bodies
|
||||
float mRestitution; ///< Combined restitution of the two bodies
|
||||
float mSoftBodyInvMassScale; ///< Scale factor for the inverse mass of the soft body vertices
|
||||
bool mUpdateVelocities; ///< If the linear/angular velocity changed and the body needs to be updated
|
||||
Mat44 mInvInertia; ///< Inverse inertia in local space to the soft body
|
||||
Vec3 mLinearVelocity; ///< Linear velocity of the body in local space to the soft body
|
||||
Vec3 mAngularVelocity; ///< Angular velocity of the body in local space to the soft body
|
||||
Vec3 mOriginalLinearVelocity; ///< Linear velocity of the body in local space to the soft body at start
|
||||
Vec3 mOriginalAngularVelocity; ///< Angular velocity of the body in local space to the soft body at start
|
||||
};
|
||||
|
||||
// Collect information about the colliding sensors
|
||||
struct CollidingSensor
|
||||
{
|
||||
Mat44 mCenterOfMassTransform; ///< Transform of the body relative to the soft body
|
||||
Array<LeafShape> mShapes; ///< Leaf shapes of the body we hit
|
||||
BodyID mBodyID; ///< Body ID of the body we hit
|
||||
bool mHasContact; ///< If the sensor collided with the soft body
|
||||
};
|
||||
|
||||
// Information about the state of all skinned vertices
|
||||
struct SkinState
|
||||
{
|
||||
Vec3 mPreviousPosition = Vec3::sZero(); ///< Previous position of the skinned vertex, used to interpolate between the previous and current position
|
||||
Vec3 mPosition = Vec3::sNaN(); ///< Current position of the skinned vertex
|
||||
Vec3 mNormal = Vec3::sNaN(); ///< Normal of the skinned vertex
|
||||
};
|
||||
|
||||
/// Do a narrow phase check and determine the closest feature that we can collide with
|
||||
void DetermineCollisionPlanes(uint inVertexStart, uint inNumVertices);
|
||||
|
||||
/// Do a narrow phase check between a single sensor and the soft body
|
||||
void DetermineSensorCollisions(CollidingSensor &ioSensor);
|
||||
|
||||
/// Apply pressure force and update the vertex velocities
|
||||
void ApplyPressure(const SoftBodyUpdateContext &inContext);
|
||||
|
||||
/// Integrate the positions of all vertices by 1 sub step
|
||||
void IntegratePositions(const SoftBodyUpdateContext &inContext);
|
||||
|
||||
/// Enforce all bend constraints
|
||||
void ApplyDihedralBendConstraints(const SoftBodyUpdateContext &inContext, uint inStartIndex, uint inEndIndex);
|
||||
|
||||
/// Enforce all volume constraints
|
||||
void ApplyVolumeConstraints(const SoftBodyUpdateContext &inContext, uint inStartIndex, uint inEndIndex);
|
||||
|
||||
/// Enforce all skin constraints
|
||||
void ApplySkinConstraints(const SoftBodyUpdateContext &inContext, uint inStartIndex, uint inEndIndex);
|
||||
|
||||
/// Enforce all edge constraints
|
||||
void ApplyEdgeConstraints(const SoftBodyUpdateContext &inContext, uint inStartIndex, uint inEndIndex);
|
||||
|
||||
/// Enforce all LRA constraints
|
||||
void ApplyLRAConstraints(uint inStartIndex, uint inEndIndex);
|
||||
|
||||
/// Enforce all collision constraints & update all velocities according the XPBD algorithm
|
||||
void ApplyCollisionConstraintsAndUpdateVelocities(const SoftBodyUpdateContext &inContext);
|
||||
|
||||
/// Update the state of the soft body (position, velocity, bounds)
|
||||
void UpdateSoftBodyState(SoftBodyUpdateContext &ioContext, const PhysicsSettings &inPhysicsSettings);
|
||||
|
||||
/// Start the first solver iteration
|
||||
void StartFirstIteration(SoftBodyUpdateContext &ioContext);
|
||||
|
||||
/// Executes tasks that need to run on the start of an iteration (i.e. the stuff that can't run in parallel)
|
||||
void StartNextIteration(const SoftBodyUpdateContext &ioContext);
|
||||
|
||||
/// Helper function for ParallelUpdate that works on batches of collision planes
|
||||
EStatus ParallelDetermineCollisionPlanes(SoftBodyUpdateContext &ioContext);
|
||||
|
||||
/// Helper function for ParallelUpdate that works on sensor collisions
|
||||
EStatus ParallelDetermineSensorCollisions(SoftBodyUpdateContext &ioContext);
|
||||
|
||||
/// Helper function for ParallelUpdate that works on batches of constraints
|
||||
EStatus ParallelApplyConstraints(SoftBodyUpdateContext &ioContext, const PhysicsSettings &inPhysicsSettings);
|
||||
|
||||
/// Helper function to update a single group of constraints
|
||||
void ProcessGroup(const SoftBodyUpdateContext &ioContext, uint inGroupIndex);
|
||||
|
||||
/// Returns 6 times the volume of the soft body
|
||||
float GetVolumeTimesSix() const;
|
||||
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
/// Helper function to draw constraints
|
||||
template <typename GetEndIndex, typename DrawConstraint>
|
||||
inline void DrawConstraints(ESoftBodyConstraintColor inConstraintColor, const GetEndIndex &inGetEndIndex, const DrawConstraint &inDrawConstraint, ColorArg inBaseColor) const;
|
||||
|
||||
RMat44 mSkinStateTransform = RMat44::sIdentity(); ///< The matrix that transforms mSkinState to world space
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
|
||||
RefConst<SoftBodySharedSettings> mSettings; ///< Configuration of the particles and constraints
|
||||
Array<Vertex> mVertices; ///< Current state of all vertices in the simulation
|
||||
Array<CollidingShape> mCollidingShapes; ///< List of colliding shapes retrieved during the last update
|
||||
Array<CollidingSensor> mCollidingSensors; ///< List of colliding sensors retrieved during the last update
|
||||
Array<SkinState> mSkinState; ///< List of skinned positions (1-on-1 with mVertices but only those that are used by the skinning constraints are filled in)
|
||||
AABox mLocalBounds; ///< Bounding box of all vertices
|
||||
AABox mLocalPredictedBounds; ///< Predicted bounding box for all vertices using extrapolation of velocity by last step delta time
|
||||
uint32 mNumIterations; ///< Number of solver iterations
|
||||
uint mNumSensors; ///< Workaround for TSAN false positive: store mCollidingSensors.size() in a separate variable.
|
||||
float mPressure; ///< n * R * T, amount of substance * ideal gas constant * absolute temperature, see https://en.wikipedia.org/wiki/Pressure
|
||||
float mSkinnedMaxDistanceMultiplier = 1.0f; ///< Multiplier applied to Skinned::mMaxDistance to allow tightening or loosening of the skin constraints
|
||||
bool mUpdatePosition; ///< Update the position of the body while simulating (set to false for something that is attached to the static world)
|
||||
atomic<bool> mNeedContactCallback = false; ///< True if the soft body has collided with anything in the last update
|
||||
bool mEnableSkinConstraints = true; ///< If skin constraints are enabled
|
||||
bool mSkinStatePreviousPositionValid = false; ///< True if the skinning was updated in the last update so that the previous position of the skin state is valid
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
341
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyShape.cpp
vendored
Normal file
341
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyShape.cpp
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyShape.h>
|
||||
#include <Jolt/Core/Profiler.h>
|
||||
#include <Jolt/Geometry/RayTriangle.h>
|
||||
#include <Jolt/Physics/Collision/RayCast.h>
|
||||
#include <Jolt/Physics/Collision/CastResult.h>
|
||||
#include <Jolt/Physics/Collision/TransformedShape.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
|
||||
#include <Jolt/Physics/Collision/CastConvexVsTriangles.h>
|
||||
#include <Jolt/Physics/Collision/CastSphereVsTriangles.h>
|
||||
#include <Jolt/Physics/Collision/CollideConvexVsTriangles.h>
|
||||
#include <Jolt/Physics/Collision/CollideSphereVsTriangles.h>
|
||||
#include <Jolt/Physics/Collision/CollisionDispatch.h>
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
#include <Jolt/Renderer/DebugRenderer.h>
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
uint SoftBodyShape::GetSubShapeIDBits() const
|
||||
{
|
||||
// Ensure we have enough bits to encode our shape [0, n - 1]
|
||||
uint32 n = (uint32)mSoftBodyMotionProperties->GetFaces().size() - 1;
|
||||
return 32 - CountLeadingZeros(n);
|
||||
}
|
||||
|
||||
uint32 SoftBodyShape::GetFaceIndex(const SubShapeID &inSubShapeID) const
|
||||
{
|
||||
SubShapeID remainder;
|
||||
uint32 face_index = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
|
||||
JPH_ASSERT(remainder.IsEmpty());
|
||||
return face_index;
|
||||
}
|
||||
|
||||
AABox SoftBodyShape::GetLocalBounds() const
|
||||
{
|
||||
return mSoftBodyMotionProperties->GetLocalBounds();
|
||||
}
|
||||
|
||||
bool SoftBodyShape::CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const
|
||||
{
|
||||
JPH_PROFILE_FUNCTION();
|
||||
|
||||
uint num_triangle_bits = GetSubShapeIDBits();
|
||||
uint triangle_idx = uint(-1);
|
||||
|
||||
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
|
||||
for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
|
||||
{
|
||||
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
float fraction = RayTriangle(inRay.mOrigin, inRay.mDirection, x1, x2, x3);
|
||||
if (fraction < ioHit.mFraction)
|
||||
{
|
||||
// Store fraction
|
||||
ioHit.mFraction = fraction;
|
||||
|
||||
// Store triangle index
|
||||
triangle_idx = uint(&f - mSoftBodyMotionProperties->GetFaces().data());
|
||||
}
|
||||
}
|
||||
|
||||
if (triangle_idx == uint(-1))
|
||||
return false;
|
||||
|
||||
ioHit.mSubShapeID2 = inSubShapeIDCreator.PushID(triangle_idx, num_triangle_bits).GetID();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SoftBodyShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) const
|
||||
{
|
||||
JPH_PROFILE_FUNCTION();
|
||||
|
||||
// Test shape filter
|
||||
if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))
|
||||
return;
|
||||
|
||||
uint num_triangle_bits = GetSubShapeIDBits();
|
||||
|
||||
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
|
||||
for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
|
||||
{
|
||||
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
// Back facing check
|
||||
if (inRayCastSettings.mBackFaceModeTriangles == EBackFaceMode::IgnoreBackFaces && (x2 - x1).Cross(x3 - x1).Dot(inRay.mDirection) > 0.0f)
|
||||
continue;
|
||||
|
||||
// Test ray against triangle
|
||||
float fraction = RayTriangle(inRay.mOrigin, inRay.mDirection, x1, x2, x3);
|
||||
if (fraction < ioCollector.GetEarlyOutFraction())
|
||||
{
|
||||
// Better hit than the current hit
|
||||
RayCastResult hit;
|
||||
hit.mBodyID = TransformedShape::sGetBodyID(ioCollector.GetContext());
|
||||
hit.mFraction = fraction;
|
||||
hit.mSubShapeID2 = inSubShapeIDCreator.PushID(uint(&f - mSoftBodyMotionProperties->GetFaces().data()), num_triangle_bits).GetID();
|
||||
ioCollector.AddHit(hit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyShape::CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const
|
||||
{
|
||||
sCollidePointUsingRayCast(*this, inPoint, inSubShapeIDCreator, ioCollector, inShapeFilter);
|
||||
}
|
||||
|
||||
void SoftBodyShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
const PhysicsMaterial *SoftBodyShape::GetMaterial(const SubShapeID &inSubShapeID) const
|
||||
{
|
||||
SubShapeID remainder;
|
||||
uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
|
||||
JPH_ASSERT(remainder.IsEmpty());
|
||||
|
||||
const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);
|
||||
return mSoftBodyMotionProperties->GetMaterials()[f.mMaterialIndex];
|
||||
}
|
||||
|
||||
Vec3 SoftBodyShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const
|
||||
{
|
||||
SubShapeID remainder;
|
||||
uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
|
||||
JPH_ASSERT(remainder.IsEmpty());
|
||||
|
||||
const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);
|
||||
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
|
||||
|
||||
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
return (x2 - x1).Cross(x3 - x1).NormalizedOr(Vec3::sAxisY());
|
||||
}
|
||||
|
||||
void SoftBodyShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
|
||||
{
|
||||
SubShapeID remainder;
|
||||
uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
|
||||
JPH_ASSERT(remainder.IsEmpty());
|
||||
|
||||
const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);
|
||||
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
|
||||
|
||||
for (uint32 i : f.mVertex)
|
||||
outVertices.push_back(inCenterOfMassTransform * (inScale * vertices[i].mPosition));
|
||||
}
|
||||
|
||||
void SoftBodyShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const
|
||||
{
|
||||
outSubmergedVolume = 0.0f;
|
||||
outTotalVolume = mSoftBodyMotionProperties->GetVolume();
|
||||
outCenterOfBuoyancy = Vec3::sZero();
|
||||
}
|
||||
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
|
||||
void SoftBodyShape::Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const
|
||||
{
|
||||
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
|
||||
for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
|
||||
{
|
||||
RVec3 x1 = inCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;
|
||||
RVec3 x2 = inCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;
|
||||
RVec3 x3 = inCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
inRenderer->DrawTriangle(x1, x2, x3, inColor, DebugRenderer::ECastShadow::On);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
|
||||
struct SoftBodyShape::SBSGetTrianglesContext
|
||||
{
|
||||
Mat44 mCenterOfMassTransform;
|
||||
int mTriangleIndex;
|
||||
};
|
||||
|
||||
void SoftBodyShape::GetTrianglesStart(GetTrianglesContext &ioContext, [[maybe_unused]] const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const
|
||||
{
|
||||
SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);
|
||||
context.mCenterOfMassTransform = Mat44::sRotationTranslation(inRotation, inPositionCOM) * Mat44::sScale(inScale);
|
||||
context.mTriangleIndex = 0;
|
||||
}
|
||||
|
||||
int SoftBodyShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials) const
|
||||
{
|
||||
SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);
|
||||
|
||||
const Array<SoftBodyMotionProperties::Face> &faces = mSoftBodyMotionProperties->GetFaces();
|
||||
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
|
||||
const PhysicsMaterialList &materials = mSoftBodyMotionProperties->GetMaterials();
|
||||
|
||||
int num_triangles = min(inMaxTrianglesRequested, (int)faces.size() - context.mTriangleIndex);
|
||||
for (int i = 0; i < num_triangles; ++i)
|
||||
{
|
||||
const SoftBodyMotionProperties::Face &f = faces[context.mTriangleIndex + i];
|
||||
|
||||
Vec3 x1 = context.mCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = context.mCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = context.mCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
x1.StoreFloat3(outTriangleVertices++);
|
||||
x2.StoreFloat3(outTriangleVertices++);
|
||||
x3.StoreFloat3(outTriangleVertices++);
|
||||
|
||||
if (outMaterials != nullptr)
|
||||
*outMaterials++ = materials[f.mMaterialIndex];
|
||||
}
|
||||
|
||||
context.mTriangleIndex += num_triangles;
|
||||
return num_triangles;
|
||||
}
|
||||
|
||||
Shape::Stats SoftBodyShape::GetStats() const
|
||||
{
|
||||
return Stats(sizeof(*this), (uint)mSoftBodyMotionProperties->GetFaces().size());
|
||||
}
|
||||
|
||||
float SoftBodyShape::GetVolume() const
|
||||
{
|
||||
return mSoftBodyMotionProperties->GetVolume();
|
||||
}
|
||||
|
||||
void SoftBodyShape::sCollideConvexVsSoftBody(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, [[maybe_unused]] const ShapeFilter &inShapeFilter)
|
||||
{
|
||||
JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);
|
||||
const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);
|
||||
JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);
|
||||
const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);
|
||||
|
||||
const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();
|
||||
const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
|
||||
uint num_triangle_bits = shape2->GetSubShapeIDBits();
|
||||
|
||||
CollideConvexVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
|
||||
for (const SoftBodyMotionProperties::Face &f : faces)
|
||||
{
|
||||
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyShape::sCollideSphereVsSoftBody(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, [[maybe_unused]] const ShapeFilter &inShapeFilter)
|
||||
{
|
||||
JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::Sphere);
|
||||
const SphereShape *shape1 = static_cast<const SphereShape *>(inShape1);
|
||||
JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);
|
||||
const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);
|
||||
|
||||
const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();
|
||||
const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
|
||||
uint num_triangle_bits = shape2->GetSubShapeIDBits();
|
||||
|
||||
CollideSphereVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);
|
||||
for (const SoftBodyMotionProperties::Face &f : faces)
|
||||
{
|
||||
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyShape::sCastConvexVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, [[maybe_unused]] const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
|
||||
{
|
||||
JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);
|
||||
const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);
|
||||
|
||||
const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();
|
||||
const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
|
||||
uint num_triangle_bits = shape->GetSubShapeIDBits();
|
||||
|
||||
CastConvexVsTriangles caster(inShapeCast, inShapeCastSettings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
|
||||
for (const SoftBodyMotionProperties::Face &f : faces)
|
||||
{
|
||||
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyShape::sCastSphereVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, [[maybe_unused]] const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
|
||||
{
|
||||
JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);
|
||||
const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);
|
||||
|
||||
const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();
|
||||
const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
|
||||
uint num_triangle_bits = shape->GetSubShapeIDBits();
|
||||
|
||||
CastSphereVsTriangles caster(inShapeCast, inShapeCastSettings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
|
||||
for (const SoftBodyMotionProperties::Face &f : faces)
|
||||
{
|
||||
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
|
||||
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
|
||||
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
|
||||
|
||||
caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyShape::sRegister()
|
||||
{
|
||||
ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::SoftBody);
|
||||
f.mConstruct = nullptr; // Not supposed to be constructed by users!
|
||||
f.mColor = Color::sDarkGreen;
|
||||
|
||||
for (EShapeSubType s : sConvexSubShapeTypes)
|
||||
{
|
||||
CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::SoftBody, sCollideConvexVsSoftBody);
|
||||
CollisionDispatch::sRegisterCastShape(s, EShapeSubType::SoftBody, sCastConvexVsSoftBody);
|
||||
|
||||
CollisionDispatch::sRegisterCollideShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCollideShape);
|
||||
CollisionDispatch::sRegisterCastShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCastShape);
|
||||
}
|
||||
|
||||
// Specialized collision functions
|
||||
CollisionDispatch::sRegisterCollideShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCollideSphereVsSoftBody);
|
||||
CollisionDispatch::sRegisterCastShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCastSphereVsSoftBody);
|
||||
}
|
||||
|
||||
JPH_NAMESPACE_END
|
73
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyShape.h
vendored
Normal file
73
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyShape.h
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Physics/Collision/Shape/Shape.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
class SoftBodyMotionProperties;
|
||||
class CollideShapeSettings;
|
||||
|
||||
/// Shape used exclusively for soft bodies. Adds the ability to perform collision checks against soft bodies.
|
||||
class JPH_EXPORT SoftBodyShape final : public Shape
|
||||
{
|
||||
public:
|
||||
JPH_OVERRIDE_NEW_DELETE
|
||||
|
||||
/// Constructor
|
||||
SoftBodyShape() : Shape(EShapeType::SoftBody, EShapeSubType::SoftBody) { }
|
||||
|
||||
/// Determine amount of bits needed to encode sub shape id
|
||||
uint GetSubShapeIDBits() const;
|
||||
|
||||
/// Convert a sub shape ID back to a face index
|
||||
uint32 GetFaceIndex(const SubShapeID &inSubShapeID) const;
|
||||
|
||||
// See Shape
|
||||
virtual bool MustBeStatic() const override { return false; }
|
||||
virtual Vec3 GetCenterOfMass() const override { return Vec3::sZero(); }
|
||||
virtual AABox GetLocalBounds() const override;
|
||||
virtual uint GetSubShapeIDBitsRecursive() const override { return GetSubShapeIDBits(); }
|
||||
virtual float GetInnerRadius() const override { return 0.0f; }
|
||||
virtual MassProperties GetMassProperties() const override { return MassProperties(); }
|
||||
virtual const PhysicsMaterial * GetMaterial(const SubShapeID &inSubShapeID) const override;
|
||||
virtual Vec3 GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
|
||||
virtual void GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
|
||||
virtual void GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy
|
||||
#ifdef JPH_DEBUG_RENDERER // Not using JPH_IF_DEBUG_RENDERER for Doxygen
|
||||
, RVec3Arg inBaseOffset
|
||||
#endif
|
||||
) const override;
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
virtual void Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
virtual bool CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;
|
||||
virtual void CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
|
||||
virtual void CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
|
||||
virtual void CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const override;
|
||||
virtual void GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const override;
|
||||
virtual int GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override;
|
||||
virtual Stats GetStats() const override;
|
||||
virtual float GetVolume() const override;
|
||||
|
||||
// Register shape functions with the registry
|
||||
static void sRegister();
|
||||
|
||||
private:
|
||||
// Helper functions called by CollisionDispatch
|
||||
static void sCollideConvexVsSoftBody(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);
|
||||
static void sCollideSphereVsSoftBody(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);
|
||||
static void sCastConvexVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
|
||||
static void sCastSphereVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
|
||||
|
||||
struct SBSGetTrianglesContext;
|
||||
|
||||
friend class BodyManager;
|
||||
|
||||
const SoftBodyMotionProperties *mSoftBodyMotionProperties;
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
1179
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.cpp
vendored
Normal file
1179
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
341
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h
vendored
Normal file
341
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Core/Reference.h>
|
||||
#include <Jolt/Physics/Collision/PhysicsMaterial.h>
|
||||
#include <Jolt/Core/StreamUtils.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
/// This class defines the setup of all particles and their constraints.
|
||||
/// It is used during the simulation and can be shared between multiple soft bodies.
|
||||
class JPH_EXPORT SoftBodySharedSettings : public RefTarget<SoftBodySharedSettings>
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, SoftBodySharedSettings)
|
||||
|
||||
public:
|
||||
/// Which type of bend constraint should be created
|
||||
enum class EBendType
|
||||
{
|
||||
None, ///< No bend constraints will be created
|
||||
Distance, ///< A simple distance constraint
|
||||
Dihedral, ///< A dihedral bend constraint (most expensive, but also supports triangles that are initially not in the same plane)
|
||||
};
|
||||
|
||||
/// The type of long range attachment constraint to create
|
||||
enum class ELRAType
|
||||
{
|
||||
None, ///< Don't create a LRA constraint
|
||||
EuclideanDistance, ///< Create a LRA constraint based on Euclidean distance between the closest kinematic vertex and this vertex
|
||||
GeodesicDistance, ///< Create a LRA constraint based on the geodesic distance between the closest kinematic vertex and this vertex (follows the edge constraints)
|
||||
};
|
||||
|
||||
/// Per vertex attributes used during the CreateConstraints function.
|
||||
/// For an edge or shear constraint, the compliance is averaged between the two attached vertices.
|
||||
/// For a bend constraint, the compliance is averaged between the two vertices on the shared edge.
|
||||
struct JPH_EXPORT VertexAttributes
|
||||
{
|
||||
/// Constructor
|
||||
VertexAttributes() = default;
|
||||
VertexAttributes(float inCompliance, float inShearCompliance, float inBendCompliance, ELRAType inLRAType = ELRAType::None, float inLRAMaxDistanceMultiplier = 1.0f) : mCompliance(inCompliance), mShearCompliance(inShearCompliance), mBendCompliance(inBendCompliance), mLRAType(inLRAType), mLRAMaxDistanceMultiplier(inLRAMaxDistanceMultiplier) { }
|
||||
|
||||
float mCompliance = 0.0f; ///< The compliance of the normal edges. Set to FLT_MAX to disable regular edges for any edge involving this vertex.
|
||||
float mShearCompliance = 0.0f; ///< The compliance of the shear edges. Set to FLT_MAX to disable shear edges for any edge involving this vertex.
|
||||
float mBendCompliance = FLT_MAX; ///< The compliance of the bend edges. Set to FLT_MAX to disable bend edges for any bend constraint involving this vertex.
|
||||
ELRAType mLRAType = ELRAType::None; ///< The type of long range attachment constraint to create.
|
||||
float mLRAMaxDistanceMultiplier = 1.0f; ///< Multiplier for the max distance of the LRA constraint, e.g. 1.01 means the max distance is 1% longer than the calculated distance in the rest pose.
|
||||
};
|
||||
|
||||
/// Automatically create constraints based on the faces of the soft body
|
||||
/// @param inVertexAttributes A list of attributes for each vertex (1-on-1 with mVertices, note that if the list is smaller than mVertices the last element will be repeated). This defines the properties of the constraints that are created.
|
||||
/// @param inVertexAttributesLength The length of inVertexAttributes
|
||||
/// @param inBendType The type of bend constraint to create
|
||||
/// @param inAngleTolerance Shear edges are created when two connected triangles form a quad (are roughly in the same plane and form a square with roughly 90 degree angles). This defines the tolerance (in radians).
|
||||
void CreateConstraints(const VertexAttributes *inVertexAttributes, uint inVertexAttributesLength, EBendType inBendType = EBendType::Distance, float inAngleTolerance = DegreesToRadians(8.0f));
|
||||
|
||||
/// Calculate the initial lengths of all springs of the edges of this soft body (if you use CreateConstraint, this is already done)
|
||||
void CalculateEdgeLengths();
|
||||
|
||||
/// Calculate the max lengths for the long range attachment constraints based on Euclidean distance (if you use CreateConstraints, this is already done)
|
||||
/// @param inMaxDistanceMultiplier Multiplier for the max distance of the LRA constraint, e.g. 1.01 means the max distance is 1% longer than the calculated distance in the rest pose.
|
||||
void CalculateLRALengths(float inMaxDistanceMultiplier = 1.0f);
|
||||
|
||||
/// Calculate the constants for the bend constraints (if you use CreateConstraints, this is already done)
|
||||
void CalculateBendConstraintConstants();
|
||||
|
||||
/// Calculates the initial volume of all tetrahedra of this soft body
|
||||
void CalculateVolumeConstraintVolumes();
|
||||
|
||||
/// Calculate information needed to be able to calculate the skinned constraint normals at run-time
|
||||
void CalculateSkinnedConstraintNormals();
|
||||
|
||||
/// Information about the optimization of the soft body, the indices of certain elements may have changed.
|
||||
class OptimizationResults
|
||||
{
|
||||
public:
|
||||
Array<uint> mEdgeRemap; ///< Maps old edge index to new edge index
|
||||
Array<uint> mLRARemap; ///< Maps old LRA index to new LRA index
|
||||
Array<uint> mDihedralBendRemap; ///< Maps old dihedral bend index to new dihedral bend index
|
||||
Array<uint> mVolumeRemap; ///< Maps old volume constraint index to new volume constraint index
|
||||
Array<uint> mSkinnedRemap; ///< Maps old skinned constraint index to new skinned constraint index
|
||||
};
|
||||
|
||||
/// Optimize the soft body settings for simulation. This will reorder constraints so they can be executed in parallel.
|
||||
void Optimize(OptimizationResults &outResults);
|
||||
|
||||
/// Optimize the soft body settings without results
|
||||
void Optimize() { OptimizationResults results; Optimize(results); }
|
||||
|
||||
/// Clone this object
|
||||
Ref<SoftBodySharedSettings> Clone() const;
|
||||
|
||||
/// Saves the state of this object in binary form to inStream. Doesn't store the material list.
|
||||
void SaveBinaryState(StreamOut &inStream) const;
|
||||
|
||||
/// Restore the state of this object from inStream. Doesn't restore the material list.
|
||||
void RestoreBinaryState(StreamIn &inStream);
|
||||
|
||||
using SharedSettingsToIDMap = StreamUtils::ObjectToIDMap<SoftBodySharedSettings>;
|
||||
using IDToSharedSettingsMap = StreamUtils::IDToObjectMap<SoftBodySharedSettings>;
|
||||
using MaterialToIDMap = StreamUtils::ObjectToIDMap<PhysicsMaterial>;
|
||||
using IDToMaterialMap = StreamUtils::IDToObjectMap<PhysicsMaterial>;
|
||||
|
||||
/// Save this shared settings and its materials. Pass in an empty map ioSettingsMap / ioMaterialMap or reuse the same map while saving multiple settings objects to the same stream in order to avoid writing duplicates.
|
||||
void SaveWithMaterials(StreamOut &inStream, SharedSettingsToIDMap &ioSettingsMap, MaterialToIDMap &ioMaterialMap) const;
|
||||
|
||||
using SettingsResult = Result<Ref<SoftBodySharedSettings>>;
|
||||
|
||||
/// Restore a shape and materials. Pass in an empty map in ioSettingsMap / ioMaterialMap or reuse the same map while reading multiple settings objects from the same stream in order to restore duplicates.
|
||||
static SettingsResult sRestoreWithMaterials(StreamIn &inStream, IDToSharedSettingsMap &ioSettingsMap, IDToMaterialMap &ioMaterialMap);
|
||||
|
||||
/// Create a cube. This can be used to create a simple soft body for testing purposes.
|
||||
/// It will contain edge constraints, volume constraints and faces.
|
||||
/// @param inGridSize Number of points along each axis
|
||||
/// @param inGridSpacing Distance between points
|
||||
static Ref<SoftBodySharedSettings> sCreateCube(uint inGridSize, float inGridSpacing);
|
||||
|
||||
/// A vertex is a particle, the data in this structure is only used during creation of the soft body and not during simulation
|
||||
struct JPH_EXPORT Vertex
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Vertex)
|
||||
|
||||
/// Constructor
|
||||
Vertex() = default;
|
||||
Vertex(const Float3 &inPosition, const Float3 &inVelocity = Float3(0, 0, 0), float inInvMass = 1.0f) : mPosition(inPosition), mVelocity(inVelocity), mInvMass(inInvMass) { }
|
||||
|
||||
Float3 mPosition { 0, 0, 0 }; ///< Initial position of the vertex
|
||||
Float3 mVelocity { 0, 0, 0 }; ///< Initial velocity of the vertex
|
||||
float mInvMass = 1.0f; ///< Initial inverse of the mass of the vertex
|
||||
};
|
||||
|
||||
/// A face defines the surface of the body
|
||||
struct JPH_EXPORT Face
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Face)
|
||||
|
||||
/// Constructor
|
||||
Face() = default;
|
||||
Face(uint32 inVertex1, uint32 inVertex2, uint32 inVertex3, uint32 inMaterialIndex = 0) : mVertex { inVertex1, inVertex2, inVertex3 }, mMaterialIndex(inMaterialIndex) { }
|
||||
|
||||
/// Check if this is a degenerate face (a face which points to the same vertex twice)
|
||||
bool IsDegenerate() const { return mVertex[0] == mVertex[1] || mVertex[0] == mVertex[2] || mVertex[1] == mVertex[2]; }
|
||||
|
||||
uint32 mVertex[3]; ///< Indices of the vertices that form the face
|
||||
uint32 mMaterialIndex = 0; ///< Index of the material of the face in SoftBodySharedSettings::mMaterials
|
||||
};
|
||||
|
||||
/// An edge keeps two vertices at a constant distance using a spring: |x1 - x2| = rest length
|
||||
struct JPH_EXPORT Edge
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Edge)
|
||||
|
||||
/// Constructor
|
||||
Edge() = default;
|
||||
Edge(uint32 inVertex1, uint32 inVertex2, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2 }, mCompliance(inCompliance) { }
|
||||
|
||||
/// Return the lowest vertex index of this constraint
|
||||
uint32 GetMinVertexIndex() const { return min(mVertex[0], mVertex[1]); }
|
||||
|
||||
uint32 mVertex[2]; ///< Indices of the vertices that form the edge
|
||||
float mRestLength = 1.0f; ///< Rest length of the spring
|
||||
float mCompliance = 0.0f; ///< Inverse of the stiffness of the spring
|
||||
};
|
||||
|
||||
/**
|
||||
* A dihedral bend constraint keeps the angle between two triangles constant along their shared edge.
|
||||
*
|
||||
* x2
|
||||
* / \
|
||||
* / t0 \
|
||||
* x0----x1
|
||||
* \ t1 /
|
||||
* \ /
|
||||
* x3
|
||||
*
|
||||
* x0..x3 are the vertices, t0 and t1 are the triangles that share the edge x0..x1
|
||||
*
|
||||
* Based on:
|
||||
* - "Position Based Dynamics" - Matthias Muller et al.
|
||||
* - "Strain Based Dynamics" - Matthias Muller et al.
|
||||
* - "Simulation of Clothing with Folds and Wrinkles" - R. Bridson et al.
|
||||
*/
|
||||
struct JPH_EXPORT DihedralBend
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, DihedralBend)
|
||||
|
||||
/// Constructor
|
||||
DihedralBend() = default;
|
||||
DihedralBend(uint32 inVertex1, uint32 inVertex2, uint32 inVertex3, uint32 inVertex4, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2, inVertex3, inVertex4 }, mCompliance(inCompliance) { }
|
||||
|
||||
/// Return the lowest vertex index of this constraint
|
||||
uint32 GetMinVertexIndex() const { return min(min(mVertex[0], mVertex[1]), min(mVertex[2], mVertex[3])); }
|
||||
|
||||
uint32 mVertex[4]; ///< Indices of the vertices of the 2 triangles that share an edge (the first 2 vertices are the shared edge)
|
||||
float mCompliance = 0.0f; ///< Inverse of the stiffness of the constraint
|
||||
float mInitialAngle = 0.0f; ///< Initial angle between the normals of the triangles (pi - dihedral angle).
|
||||
};
|
||||
|
||||
/// Volume constraint, keeps the volume of a tetrahedron constant
|
||||
struct JPH_EXPORT Volume
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Volume)
|
||||
|
||||
/// Constructor
|
||||
Volume() = default;
|
||||
Volume(uint32 inVertex1, uint32 inVertex2, uint32 inVertex3, uint32 inVertex4, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2, inVertex3, inVertex4 }, mCompliance(inCompliance) { }
|
||||
|
||||
/// Return the lowest vertex index of this constraint
|
||||
uint32 GetMinVertexIndex() const { return min(min(mVertex[0], mVertex[1]), min(mVertex[2], mVertex[3])); }
|
||||
|
||||
uint32 mVertex[4]; ///< Indices of the vertices that form the tetrahedron
|
||||
float mSixRestVolume = 1.0f; ///< 6 times the rest volume of the tetrahedron (calculated by CalculateVolumeConstraintVolumes())
|
||||
float mCompliance = 0.0f; ///< Inverse of the stiffness of the constraint
|
||||
};
|
||||
|
||||
/// An inverse bind matrix take a skinned vertex from its bind pose into joint local space
|
||||
class JPH_EXPORT InvBind
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, InvBind)
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
InvBind() = default;
|
||||
InvBind(uint32 inJointIndex, Mat44Arg inInvBind) : mJointIndex(inJointIndex), mInvBind(inInvBind) { }
|
||||
|
||||
uint32 mJointIndex = 0; ///< Joint index to which this is attached
|
||||
Mat44 mInvBind = Mat44::sIdentity(); ///< The inverse bind matrix, this takes a vertex in its bind pose (Vertex::mPosition) to joint local space
|
||||
};
|
||||
|
||||
/// A joint and its skin weight
|
||||
class JPH_EXPORT SkinWeight
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, SkinWeight)
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
SkinWeight() = default;
|
||||
SkinWeight(uint32 inInvBindIndex, float inWeight) : mInvBindIndex(inInvBindIndex), mWeight(inWeight) { }
|
||||
|
||||
uint32 mInvBindIndex = 0; ///< Index in mInvBindMatrices
|
||||
float mWeight = 0.0f; ///< Weight with which it is skinned
|
||||
};
|
||||
|
||||
/// A constraint that skins a vertex to joints and limits the distance that the simulated vertex can travel from this vertex
|
||||
class JPH_EXPORT Skinned
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Skinned)
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
Skinned() = default;
|
||||
Skinned(uint32 inVertex, float inMaxDistance, float inBackStopDistance, float inBackStopRadius) : mVertex(inVertex), mMaxDistance(inMaxDistance), mBackStopDistance(inBackStopDistance), mBackStopRadius(inBackStopRadius) { }
|
||||
|
||||
/// Normalize the weights so that they add up to 1
|
||||
void NormalizeWeights()
|
||||
{
|
||||
// Get the total weight
|
||||
float total = 0.0f;
|
||||
for (const SkinWeight &w : mWeights)
|
||||
total += w.mWeight;
|
||||
|
||||
// Normalize
|
||||
if (total > 0.0f)
|
||||
for (SkinWeight &w : mWeights)
|
||||
w.mWeight /= total;
|
||||
}
|
||||
|
||||
/// Maximum number of skin weights
|
||||
static constexpr uint cMaxSkinWeights = 4;
|
||||
|
||||
uint32 mVertex = 0; ///< Index in mVertices which indicates which vertex is being skinned
|
||||
SkinWeight mWeights[cMaxSkinWeights]; ///< Skin weights, the bind pose of the vertex is assumed to be stored in Vertex::mPosition. The first weight that is zero indicates the end of the list. Weights should add up to 1.
|
||||
float mMaxDistance = FLT_MAX; ///< Maximum distance that this vertex can reach from the skinned vertex, disabled when FLT_MAX. 0 when you want to hard skin the vertex to the skinned vertex.
|
||||
float mBackStopDistance = FLT_MAX; ///< Disabled if mBackStopDistance >= mMaxDistance. The faces surrounding mVertex determine an average normal. mBackStopDistance behind the vertex in the opposite direction of this normal, the back stop sphere starts. The simulated vertex will be pushed out of this sphere and it can be used to approximate the volume of the skinned mesh behind the skinned vertex.
|
||||
float mBackStopRadius = 40.0f; ///< Radius of the backstop sphere. By default this is a fairly large radius so the sphere approximates a plane.
|
||||
uint32 mNormalInfo = 0; ///< Information needed to calculate the normal of this vertex, lowest 24 bit is start index in mSkinnedConstraintNormals, highest 8 bit is number of faces (generated by CalculateSkinnedConstraintNormals())
|
||||
};
|
||||
|
||||
/// A long range attachment constraint, this is a constraint that sets a max distance between a kinematic vertex and a dynamic vertex
|
||||
/// See: "Long Range Attachments - A Method to Simulate Inextensible Clothing in Computer Games", Tae-Yong Kim, Nuttapong Chentanez and Matthias Mueller-Fischer
|
||||
class JPH_EXPORT LRA
|
||||
{
|
||||
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, LRA)
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
LRA() = default;
|
||||
LRA(uint32 inVertex1, uint32 inVertex2, float inMaxDistance) : mVertex { inVertex1, inVertex2 }, mMaxDistance(inMaxDistance) { }
|
||||
|
||||
/// Return the lowest vertex index of this constraint
|
||||
uint32 GetMinVertexIndex() const { return min(mVertex[0], mVertex[1]); }
|
||||
|
||||
uint32 mVertex[2]; ///< The vertices that are connected. The first vertex should be kinematic, the 2nd dynamic.
|
||||
float mMaxDistance = 0.0f; ///< The maximum distance between the vertices
|
||||
};
|
||||
|
||||
/// Add a face to this soft body
|
||||
void AddFace(const Face &inFace) { JPH_ASSERT(!inFace.IsDegenerate()); mFaces.push_back(inFace); }
|
||||
|
||||
Array<Vertex> mVertices; ///< The list of vertices or particles of the body
|
||||
Array<Face> mFaces; ///< The list of faces of the body
|
||||
Array<Edge> mEdgeConstraints; ///< The list of edges or springs of the body
|
||||
Array<DihedralBend> mDihedralBendConstraints; ///< The list of dihedral bend constraints of the body
|
||||
Array<Volume> mVolumeConstraints; ///< The list of volume constraints of the body that keep the volume of tetrahedra in the soft body constant
|
||||
Array<Skinned> mSkinnedConstraints; ///< The list of vertices that are constrained to a skinned vertex
|
||||
Array<InvBind> mInvBindMatrices; ///< The list of inverse bind matrices for skinning vertices
|
||||
Array<LRA> mLRAConstraints; ///< The list of long range attachment constraints
|
||||
PhysicsMaterialList mMaterials { PhysicsMaterial::sDefault }; ///< The materials of the faces of the body, referenced by Face::mMaterialIndex
|
||||
float mVertexRadius = 0.0f; ///< How big the particles are, can be used to push the vertices a little bit away from the surface of other bodies to prevent z-fighting
|
||||
|
||||
private:
|
||||
friend class SoftBodyMotionProperties;
|
||||
|
||||
/// Calculate the closest kinematic vertex array
|
||||
void CalculateClosestKinematic();
|
||||
|
||||
/// Tracks the closest kinematic vertex
|
||||
struct ClosestKinematic
|
||||
{
|
||||
uint32 mVertex = 0xffffffff; ///< Vertex index of closest kinematic vertex
|
||||
float mDistance = FLT_MAX; ///< Distance to the closest kinematic vertex
|
||||
};
|
||||
|
||||
/// Tracks the end indices of the various constraint groups
|
||||
struct UpdateGroup
|
||||
{
|
||||
uint mEdgeEndIndex; ///< The end index of the edge constraints in this group
|
||||
uint mLRAEndIndex; ///< The end index of the LRA constraints in this group
|
||||
uint mDihedralBendEndIndex; ///< The end index of the dihedral bend constraints in this group
|
||||
uint mVolumeEndIndex; ///< The end index of the volume constraints in this group
|
||||
uint mSkinnedEndIndex; ///< The end index of the skinned constraints in this group
|
||||
};
|
||||
|
||||
Array<ClosestKinematic> mClosestKinematic; ///< The closest kinematic vertex to each vertex in mVertices
|
||||
Array<UpdateGroup> mUpdateGroups; ///< The end indices for each group of constraints that can be updated in parallel
|
||||
Array<uint32> mSkinnedConstraintNormals; ///< A list of indices in the mFaces array used by mSkinnedConstraints, calculated by CalculateSkinnedConstraintNormals()
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
59
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyUpdateContext.h
vendored
Normal file
59
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyUpdateContext.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Core/NonCopyable.h>
|
||||
#include <Jolt/Physics/Body/MotionProperties.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
class Body;
|
||||
class SoftBodyMotionProperties;
|
||||
class SoftBodyContactListener;
|
||||
class SimShapeFilter;
|
||||
|
||||
/// Temporary data used by the update of a soft body
|
||||
class SoftBodyUpdateContext : public NonCopyable
|
||||
{
|
||||
public:
|
||||
static constexpr uint cVertexCollisionBatch = 64; ///< Number of vertices to process in a batch in DetermineCollisionPlanes
|
||||
static constexpr uint cVertexConstraintBatch = 256; ///< Number of vertices to group for processing batches of constraints in ApplyEdgeConstraints
|
||||
|
||||
// Input
|
||||
Body * mBody; ///< Body that is being updated
|
||||
SoftBodyMotionProperties * mMotionProperties; ///< Motion properties of that body
|
||||
SoftBodyContactListener * mContactListener; ///< Contact listener to fire callbacks to
|
||||
const SimShapeFilter * mSimShapeFilter; ///< Shape filter to use for collision detection
|
||||
RMat44 mCenterOfMassTransform; ///< Transform of the body relative to the soft body
|
||||
Vec3 mGravity; ///< Gravity vector in local space of the soft body
|
||||
Vec3 mDisplacementDueToGravity; ///< Displacement of the center of mass due to gravity in the current time step
|
||||
float mDeltaTime; ///< Delta time for the current time step
|
||||
float mSubStepDeltaTime; ///< Delta time for each sub step
|
||||
|
||||
/// Describes progress in the current update
|
||||
enum class EState
|
||||
{
|
||||
DetermineCollisionPlanes, ///< Determine collision planes for vertices in parallel
|
||||
DetermineSensorCollisions, ///< Determine collisions with sensors in parallel
|
||||
ApplyConstraints, ///< Apply constraints in parallel
|
||||
Done ///< Update is finished
|
||||
};
|
||||
|
||||
// State of the update
|
||||
atomic<EState> mState { EState::DetermineCollisionPlanes };///< Current state of the update
|
||||
atomic<uint> mNextCollisionVertex { 0 }; ///< Next vertex to process for DetermineCollisionPlanes
|
||||
atomic<uint> mNumCollisionVerticesProcessed { 0 }; ///< Number of vertices processed by DetermineCollisionPlanes, used to determine if we can go to the next step
|
||||
atomic<uint> mNextSensorIndex { 0 }; ///< Next sensor to process for DetermineCollisionPlanes
|
||||
atomic<uint> mNumSensorsProcessed { 0 }; ///< Number of sensors processed by DetermineSensorCollisions, used to determine if we can go to the next step
|
||||
atomic<uint> mNextIteration { 0 }; ///< Next simulation iteration to process
|
||||
atomic<uint> mNextConstraintGroup { 0 }; ///< Next constraint group to process
|
||||
atomic<uint> mNumConstraintGroupsProcessed { 0 }; ///< Number of groups processed, used to determine if we can go to the next iteration
|
||||
|
||||
// Output
|
||||
Vec3 mDeltaPosition; ///< Delta position of the body in the current time step, should be applied after the update
|
||||
ECanSleep mCanSleep; ///< Can the body sleep? Should be applied after the update
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
36
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyVertex.h
vendored
Normal file
36
thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyVertex.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Jolt/Geometry/Plane.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
/// Run time information for a single particle of a soft body
|
||||
/// Note that at run-time you should only modify the inverse mass and/or velocity of a vertex to control the soft body.
|
||||
/// Modifying the position can lead to missed collisions.
|
||||
/// The other members are used internally by the soft body solver.
|
||||
class SoftBodyVertex
|
||||
{
|
||||
public:
|
||||
/// Reset collision information to prepare for a new collision check
|
||||
inline void ResetCollision()
|
||||
{
|
||||
mLargestPenetration = -FLT_MAX;
|
||||
mCollidingShapeIndex = -1;
|
||||
mHasContact = false;
|
||||
}
|
||||
|
||||
Vec3 mPreviousPosition; ///< Internal use only. Position at the previous time step
|
||||
Vec3 mPosition; ///< Position, relative to the center of mass of the soft body
|
||||
Vec3 mVelocity; ///< Velocity, relative to the center of mass of the soft body
|
||||
Plane mCollisionPlane; ///< Internal use only. Nearest collision plane, relative to the center of mass of the soft body
|
||||
int mCollidingShapeIndex; ///< Internal use only. Index in the colliding shapes list of the body we may collide with
|
||||
bool mHasContact; ///< True if the vertex has collided with anything in the last update
|
||||
float mLargestPenetration; ///< Internal use only. Used while finding the collision plane, stores the largest penetration found so far
|
||||
float mInvMass; ///< Inverse mass (1 / mass)
|
||||
};
|
||||
|
||||
JPH_NAMESPACE_END
|
Reference in New Issue
Block a user