feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -106,7 +106,7 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
JPH_PROFILE_FUNCTION();
// Reset flag prior to collision detection
mNeedContactCallback = false;
mNeedContactCallback.store(false, memory_order_relaxed);
struct Collector : public CollideShapeBodyCollector
{
@ -170,7 +170,7 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
Array<LeafShape> mHits;
};
LeafShapeCollector collector;
body.GetShape()->CollectTransformedShapes(mLocalBounds, com.GetTranslation(), com.GetQuaternion(), Vec3::sReplicate(1.0f), SubShapeIDCreator(), collector, mShapeFilter);
body.GetShape()->CollectTransformedShapes(mLocalBounds, com.GetTranslation(), com.GetQuaternion(), Vec3::sOne(), SubShapeIDCreator(), collector, mShapeFilter);
if (collector.mHits.empty())
return;
@ -236,6 +236,7 @@ void SoftBodyMotionProperties::DetermineCollidingShapes(const SoftBodyUpdateCont
DefaultBroadPhaseLayerFilter broadphase_layer_filter = inSystem.GetDefaultBroadPhaseLayerFilter(layer);
DefaultObjectLayerFilter object_layer_filter = inSystem.GetDefaultLayerFilter(layer);
inSystem.GetBroadPhaseQuery().CollideAABox(world_bounds, collector, broadphase_layer_filter, object_layer_filter);
mNumSensors = uint(mCollidingSensors.size()); // Workaround for TSAN false positive: store mCollidingSensors.size() in a separate variable.
}
void SoftBodyMotionProperties::DetermineCollisionPlanes(uint inVertexStart, uint inNumVertices)
@ -269,7 +270,7 @@ void SoftBodyMotionProperties::DetermineSensorCollisions(CollidingSensor &ioSens
// We need a contact callback if one of the sensors collided
if (ioSensor.mHasContact)
mNeedContactCallback = true;
mNeedContactCallback.store(true, memory_order_relaxed);
}
void SoftBodyMotionProperties::ApplyPressure(const SoftBodyUpdateContext &inContext)
@ -315,7 +316,7 @@ void SoftBodyMotionProperties::IntegratePositions(const SoftBodyUpdateContext &i
// Integrate
Vec3 sub_step_gravity = inContext.mGravity * dt;
Vec3 sub_step_impulse = GetAccumulatedForce() * dt;
Vec3 sub_step_impulse = GetAccumulatedForce() * dt / max(float(mVertices.size()), 1.0f);
for (Vertex &v : mVertices)
if (v.mInvMass > 0.0f)
{
@ -621,7 +622,7 @@ void SoftBodyMotionProperties::ApplyCollisionConstraintsAndUpdateVelocities(cons
v.mHasContact = true;
// We need a contact callback if one of the vertices collided
mNeedContactCallback = true;
mNeedContactCallback.store(true, memory_order_relaxed);
// Note that we already calculated the velocity, so this does not affect the velocity (next iteration starts by setting previous position to current position)
CollidingShape &cs = mCollidingShapes[v.mCollidingShapeIndex];
@ -720,7 +721,7 @@ void SoftBodyMotionProperties::UpdateSoftBodyState(SoftBodyUpdateContext &ioCont
JPH_PROFILE_FUNCTION();
// Contact callback
if (mNeedContactCallback && ioContext.mContactListener != nullptr)
if (mNeedContactCallback.load(memory_order_relaxed) && ioContext.mContactListener != nullptr)
{
// Remove non-colliding sensors from the list
for (int i = int(mCollidingSensors.size()) - 1; i >= 0; --i)
@ -765,7 +766,7 @@ void SoftBodyMotionProperties::UpdateSoftBodyState(SoftBodyUpdateContext &ioCont
// Calculate linear/angular velocity of the body by averaging all vertices and bringing the value to world space
float num_vertices_divider = float(max(int(mVertices.size()), 1));
SetLinearVelocity(ioContext.mCenterOfMassTransform.Multiply3x3(linear_velocity / num_vertices_divider));
SetLinearVelocityClamped(ioContext.mCenterOfMassTransform.Multiply3x3(linear_velocity / num_vertices_divider));
SetAngularVelocity(ioContext.mCenterOfMassTransform.Multiply3x3(angular_velocity / num_vertices_divider));
if (mUpdatePosition)
@ -877,7 +878,7 @@ SoftBodyMotionProperties::EStatus SoftBodyMotionProperties::ParallelDetermineCol
// Process collision planes
uint num_vertices_to_process = min(SoftBodyUpdateContext::cVertexCollisionBatch, num_vertices - next_vertex);
DetermineCollisionPlanes(next_vertex, num_vertices_to_process);
uint vertices_processed = ioContext.mNumCollisionVerticesProcessed.fetch_add(SoftBodyUpdateContext::cVertexCollisionBatch, memory_order_release) + num_vertices_to_process;
uint vertices_processed = ioContext.mNumCollisionVerticesProcessed.fetch_add(SoftBodyUpdateContext::cVertexCollisionBatch, memory_order_acq_rel) + num_vertices_to_process;
if (vertices_processed >= num_vertices)
{
// Determine next state
@ -896,19 +897,18 @@ SoftBodyMotionProperties::EStatus SoftBodyMotionProperties::ParallelDetermineCol
SoftBodyMotionProperties::EStatus SoftBodyMotionProperties::ParallelDetermineSensorCollisions(SoftBodyUpdateContext &ioContext)
{
// Do a relaxed read to see if there are more sensors to process
uint num_sensors = (uint)mCollidingSensors.size();
if (ioContext.mNextSensorIndex.load(memory_order_relaxed) < num_sensors)
if (ioContext.mNextSensorIndex.load(memory_order_relaxed) < mNumSensors)
{
// Fetch next sensor to process
uint sensor_index = ioContext.mNextSensorIndex.fetch_add(1, memory_order_acquire);
if (sensor_index < num_sensors)
if (sensor_index < mNumSensors)
{
// Process this sensor
DetermineSensorCollisions(mCollidingSensors[sensor_index]);
// Determine next state
uint sensors_processed = ioContext.mNumSensorsProcessed.fetch_add(1, memory_order_release) + 1;
if (sensors_processed >= num_sensors)
uint sensors_processed = ioContext.mNumSensorsProcessed.fetch_add(1, memory_order_acq_rel) + 1;
if (sensors_processed >= mNumSensors)
StartFirstIteration(ioContext);
return EStatus::DidWork;
}
@ -961,7 +961,7 @@ SoftBodyMotionProperties::EStatus SoftBodyMotionProperties::ParallelApplyConstra
ProcessGroup(ioContext, next_group);
// Increment total number of groups processed
num_groups_processed = ioContext.mNumConstraintGroupsProcessed.fetch_add(1, memory_order_relaxed) + 1;
num_groups_processed = ioContext.mNumConstraintGroupsProcessed.fetch_add(1, memory_order_acq_rel) + 1;
}
if (num_groups_processed >= num_groups)
@ -981,7 +981,7 @@ SoftBodyMotionProperties::EStatus SoftBodyMotionProperties::ParallelApplyConstra
StartNextIteration(ioContext);
// Reset group logic
ioContext.mNumConstraintGroupsProcessed.store(0, memory_order_relaxed);
ioContext.mNumConstraintGroupsProcessed.store(0, memory_order_release);
ioContext.mNextConstraintGroup.store(0, memory_order_release);
}
else
@ -1002,7 +1002,7 @@ SoftBodyMotionProperties::EStatus SoftBodyMotionProperties::ParallelApplyConstra
SoftBodyMotionProperties::EStatus SoftBodyMotionProperties::ParallelUpdate(SoftBodyUpdateContext &ioContext, const PhysicsSettings &inPhysicsSettings)
{
switch (ioContext.mState.load(memory_order_relaxed))
switch (ioContext.mState.load(memory_order_acquire))
{
case SoftBodyUpdateContext::EState::DetermineCollisionPlanes:
return ParallelDetermineCollisionPlanes(ioContext);

View file

@ -286,10 +286,11 @@ private:
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)
bool mNeedContactCallback = false; ///< True if the soft body has collided with anything in the last update
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
};

View file

@ -328,6 +328,9 @@ void SoftBodyShape::sRegister()
{
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

View file

@ -541,6 +541,10 @@ void SoftBodySharedSettings::Optimize(OptimizationResults &outResults)
if (group_idx[i] == -1)
bounds.Encapsulate(Vec3(mVertices[i].mPosition));
// If the bounds are invalid, it means that there were no ungrouped vertices
if (!bounds.IsValid())
break;
// Determine longest and shortest axis
Vec3 bounds_size = bounds.GetSize();
uint max_axis = bounds_size.GetHighestComponentIndex();
@ -1029,4 +1033,147 @@ SoftBodySharedSettings::SettingsResult SoftBodySharedSettings::sRestoreWithMater
return result;
}
Ref<SoftBodySharedSettings> SoftBodySharedSettings::sCreateCube(uint inGridSize, float inGridSpacing)
{
const Vec3 cOffset = Vec3::sReplicate(-0.5f * inGridSpacing * (inGridSize - 1));
// Create settings
SoftBodySharedSettings *settings = new SoftBodySharedSettings;
for (uint z = 0; z < inGridSize; ++z)
for (uint y = 0; y < inGridSize; ++y)
for (uint x = 0; x < inGridSize; ++x)
{
SoftBodySharedSettings::Vertex v;
(cOffset + Vec3::sReplicate(inGridSpacing) * Vec3(float(x), float(y), float(z))).StoreFloat3(&v.mPosition);
settings->mVertices.push_back(v);
}
// Function to get the vertex index of a point on the cube
auto vertex_index = [inGridSize](uint inX, uint inY, uint inZ)
{
return inX + inY * inGridSize + inZ * inGridSize * inGridSize;
};
// Create edges
for (uint z = 0; z < inGridSize; ++z)
for (uint y = 0; y < inGridSize; ++y)
for (uint x = 0; x < inGridSize; ++x)
{
SoftBodySharedSettings::Edge e;
e.mVertex[0] = vertex_index(x, y, z);
if (x < inGridSize - 1)
{
e.mVertex[1] = vertex_index(x + 1, y, z);
settings->mEdgeConstraints.push_back(e);
}
if (y < inGridSize - 1)
{
e.mVertex[1] = vertex_index(x, y + 1, z);
settings->mEdgeConstraints.push_back(e);
}
if (z < inGridSize - 1)
{
e.mVertex[1] = vertex_index(x, y, z + 1);
settings->mEdgeConstraints.push_back(e);
}
}
settings->CalculateEdgeLengths();
// Tetrahedrons to fill a cube
const int tetra_indices[6][4][3] = {
{ {0, 0, 0}, {0, 1, 1}, {0, 0, 1}, {1, 1, 1} },
{ {0, 0, 0}, {0, 1, 0}, {0, 1, 1}, {1, 1, 1} },
{ {0, 0, 0}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1} },
{ {0, 0, 0}, {1, 0, 1}, {1, 0, 0}, {1, 1, 1} },
{ {0, 0, 0}, {1, 1, 0}, {0, 1, 0}, {1, 1, 1} },
{ {0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {1, 1, 1} }
};
// Create volume constraints
for (uint z = 0; z < inGridSize - 1; ++z)
for (uint y = 0; y < inGridSize - 1; ++y)
for (uint x = 0; x < inGridSize - 1; ++x)
for (uint t = 0; t < 6; ++t)
{
SoftBodySharedSettings::Volume v;
for (uint i = 0; i < 4; ++i)
v.mVertex[i] = vertex_index(x + tetra_indices[t][i][0], y + tetra_indices[t][i][1], z + tetra_indices[t][i][2]);
settings->mVolumeConstraints.push_back(v);
}
settings->CalculateVolumeConstraintVolumes();
// Create faces
for (uint y = 0; y < inGridSize - 1; ++y)
for (uint x = 0; x < inGridSize - 1; ++x)
{
SoftBodySharedSettings::Face f;
// Face 1
f.mVertex[0] = vertex_index(x, y, 0);
f.mVertex[1] = vertex_index(x, y + 1, 0);
f.mVertex[2] = vertex_index(x + 1, y + 1, 0);
settings->AddFace(f);
f.mVertex[1] = vertex_index(x + 1, y + 1, 0);
f.mVertex[2] = vertex_index(x + 1, y, 0);
settings->AddFace(f);
// Face 2
f.mVertex[0] = vertex_index(x, y, inGridSize - 1);
f.mVertex[1] = vertex_index(x + 1, y + 1, inGridSize - 1);
f.mVertex[2] = vertex_index(x, y + 1, inGridSize - 1);
settings->AddFace(f);
f.mVertex[1] = vertex_index(x + 1, y, inGridSize - 1);
f.mVertex[2] = vertex_index(x + 1, y + 1, inGridSize - 1);
settings->AddFace(f);
// Face 3
f.mVertex[0] = vertex_index(x, 0, y);
f.mVertex[1] = vertex_index(x + 1, 0, y + 1);
f.mVertex[2] = vertex_index(x, 0, y + 1);
settings->AddFace(f);
f.mVertex[1] = vertex_index(x + 1, 0, y);
f.mVertex[2] = vertex_index(x + 1, 0, y + 1);
settings->AddFace(f);
// Face 4
f.mVertex[0] = vertex_index(x, inGridSize - 1, y);
f.mVertex[1] = vertex_index(x, inGridSize - 1, y + 1);
f.mVertex[2] = vertex_index(x + 1, inGridSize - 1, y + 1);
settings->AddFace(f);
f.mVertex[1] = vertex_index(x + 1, inGridSize - 1, y + 1);
f.mVertex[2] = vertex_index(x + 1, inGridSize - 1, y);
settings->AddFace(f);
// Face 5
f.mVertex[0] = vertex_index(0, x, y);
f.mVertex[1] = vertex_index(0, x, y + 1);
f.mVertex[2] = vertex_index(0, x + 1, y + 1);
settings->AddFace(f);
f.mVertex[1] = vertex_index(0, x + 1, y + 1);
f.mVertex[2] = vertex_index(0, x + 1, y);
settings->AddFace(f);
// Face 6
f.mVertex[0] = vertex_index(inGridSize - 1, x, y);
f.mVertex[1] = vertex_index(inGridSize - 1, x + 1, y + 1);
f.mVertex[2] = vertex_index(inGridSize - 1, x, y + 1);
settings->AddFace(f);
f.mVertex[1] = vertex_index(inGridSize - 1, x + 1, y);
f.mVertex[2] = vertex_index(inGridSize - 1, x + 1, y + 1);
settings->AddFace(f);
}
// Optimize the settings
settings->Optimize();
return settings;
}
JPH_NAMESPACE_END

View file

@ -111,6 +111,12 @@ public:
/// 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
{