Path: blob/master/thirdparty/jolt_physics/patches/0005-backport-upstream-commit-449b645.patch
45998 views
diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h1index cfec8139..134f300d 1006442--- a/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h3+++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h4@@ -101,6 +101,9 @@ public:56/// How backfacing triangles should be treated7EBackFaceMode mBackFaceMode = EBackFaceMode::IgnoreBackFaces;8+9+ /// Max squared distance to consider a vertex to be the same as another vertex, used by the internal edge removal algorithm to determine if two edges are shared. (unit: meter^2)10+ float mInternalEdgeRemovalVertexToleranceSq = cDefaultInternalEdgeRemovalVertexToleranceSq;11};1213JPH_NAMESPACE_END14diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h15index cec7d7be..eee55022 10064416--- a/thirdparty/jolt_physics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h17+++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h18@@ -31,7 +31,7 @@ class InternalEdgeRemovingCollector : public CollideShapeCollector19{20for (const Voided &vf : mVoidedFeatures)21if (vf.mSubShapeID == inSubShapeID22- && inV.IsClose(Vec3::sLoadFloat3Unsafe(vf.mFeature), 1.0e-8f))23+ && inV.IsClose(Vec3::sLoadFloat3Unsafe(vf.mFeature), mVertexToleranceSq))24return true;25return false;26}27@@ -76,13 +76,15 @@ class InternalEdgeRemovingCollector : public CollideShapeCollector2829public:30/// Constructor, configures a collector to be called with all the results that do not hit internal edges31- explicit InternalEdgeRemovingCollector(CollideShapeCollector &inChainedCollector32+ explicit InternalEdgeRemovingCollector(CollideShapeCollector &inChainedCollector,33+ float inVertexToleranceSq34#ifdef JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG35, RVec3Arg inBaseOffset36#endif // JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG37) :38CollideShapeCollector(inChainedCollector),39- mChainedCollector(inChainedCollector)40+ mChainedCollector(inChainedCollector),41+ mVertexToleranceSq(inVertexToleranceSq)42#ifdef JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG43, mBaseOffset(inBaseOffset)44#endif // JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG45@@ -249,7 +251,7 @@ public:46JPH_ASSERT(inCollideShapeSettings.mActiveEdgeMode == EActiveEdgeMode::CollideWithAll); // Won't work without colliding with all edges47JPH_ASSERT(inCollideShapeSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces); // Won't work without collecting faces4849- InternalEdgeRemovingCollector wrapper(ioCollector50+ InternalEdgeRemovingCollector wrapper(ioCollector, inCollideShapeSettings.mInternalEdgeRemovalVertexToleranceSq51#ifdef JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG52, inBaseOffset53#endif // JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG54@@ -271,6 +273,7 @@ private:55CollideShapeCollector & mChainedCollector;56Array<Voided, STLLocalAllocator<Voided, cMaxLocalVoidedFeatures>> mVoidedFeatures;57Array<CollideShapeResult, STLLocalAllocator<CollideShapeResult, cMaxLocalDelayedResults>> mDelayedResults;58+ float mVertexToleranceSq; // Max squared distance to consider a vertex to be the same as another vertex, used to determine if a feature is voided59#ifdef JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG60RVec3 mBaseOffset; // Base offset for the query, used to draw the results in the right place61#endif // JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG62diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp63index 670cee33..1a8c2c78 10064464--- a/thirdparty/jolt_physics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp65+++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp66@@ -301,7 +301,7 @@ void NarrowPhaseQuery::CollideShapeWithInternalEdgeRemoval(const Shape *inShape,67settings.mActiveEdgeMode = EActiveEdgeMode::CollideWithAll;68settings.mCollectFacesMode = ECollectFacesMode::CollectFaces;6970- InternalEdgeRemovingCollector wrapper(ioCollector71+ InternalEdgeRemovingCollector wrapper(ioCollector, settings.mInternalEdgeRemovalVertexToleranceSq72#ifdef JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG73, inBaseOffset74#endif // JPH_INTERNAL_EDGE_REMOVING_COLLECTOR_DEBUG75diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp76index ff55f4ba..d859b22e 10064477--- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp78+++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp79@@ -185,9 +185,9 @@ uint32 HeightFieldShapeSettings::CalculateBitsPerSampleForError(float inMaxError80// Not accurate enough, increase bits per sample81bits_per_sample++;8283- // Don't go above 8 bits per sample84- if (bits_per_sample == 8)85- return bits_per_sample;86+ // Don't go above cMaxBitsPerSample bits per sample87+ if (bits_per_sample == cMaxBitsPerSample)88+ return cMaxBitsPerSample;89}90}91}92@@ -416,7 +416,7 @@ void HeightFieldShape::StoreMaterialIndices(const HeightFieldShapeSettings &inSe9394void HeightFieldShape::CacheValues()95{96- mSampleMask = uint8((uint32(1) << mBitsPerSample) - 1);97+ mSampleMask = uint16((uint32(1) << mBitsPerSample) - 1);98}99100void HeightFieldShape::AllocateBuffers()101@@ -424,7 +424,7 @@ void HeightFieldShape::AllocateBuffers()102uint num_blocks = GetNumBlocks();103uint max_stride = (num_blocks + 1) >> 1;104mRangeBlocksSize = sGridOffsets[sGetMaxLevel(num_blocks) - 1] + Square(max_stride);105- mHeightSamplesSize = (mSampleCount * mSampleCount * mBitsPerSample + 7) / 8 + 1;106+ mHeightSamplesSize = (mSampleCount * mSampleCount * mBitsPerSample + 7) / 8 + 2; // Since we read 3 bytes per sample, we need 2 extra bytes of padding107mActiveEdgesSize = (Square(mSampleCount - 1) * 3 + 7) / 8 + 1; // See explanation at HeightFieldShape::CalculateActiveEdges108109JPH_ASSERT(mRangeBlocks == nullptr && mHeightSamples == nullptr && mActiveEdges == nullptr);110@@ -457,9 +457,9 @@ HeightFieldShape::HeightFieldShape(const HeightFieldShapeSettings &inSettings, S111}112113// Check bits per sample114- if (inSettings.mBitsPerSample < 1 || inSettings.mBitsPerSample > 8)115+ if (inSettings.mBitsPerSample < 1 || inSettings.mBitsPerSample > HeightFieldShapeConstants::cMaxBitsPerSample)116{117- outResult.SetError("HeightFieldShape: Bits per sample must be in the range [1, 8]!");118+ outResult.SetError("HeightFieldShape: Bits per sample must be in the range [1, 16]!");119return;120}121122@@ -727,9 +727,10 @@ HeightFieldShape::HeightFieldShape(const HeightFieldShapeSettings &inSettings, S123uint byte_pos = sample >> 3;124uint bit_pos = sample & 0b111;125output_value <<= bit_pos;126- JPH_ASSERT(byte_pos + 1 < mHeightSamplesSize);127+ JPH_ASSERT(byte_pos + 2 < mHeightSamplesSize); // We read max 16 bits which could be spread out over 3 bytes128mHeightSamples[byte_pos] |= uint8(output_value);129mHeightSamples[byte_pos + 1] |= uint8(output_value >> 8);130+ mHeightSamples[byte_pos + 2] |= uint8(output_value >> 16);131sample += inSettings.mBitsPerSample;132}133134@@ -816,7 +817,7 @@ inline void HeightFieldShape::GetBlockOffsetAndScale(uint inBlockX, uint inBlock135outBlockScale = float(block.mMax[n] - block.mMin[n]) / float(mSampleMask);136}137138-inline uint8 HeightFieldShape::GetHeightSample(uint inX, uint inY) const139+inline uint16 HeightFieldShape::GetHeightSample(uint inX, uint inY) const140{141JPH_ASSERT(inX < mSampleCount);142JPH_ASSERT(inY < mSampleCount);143@@ -827,16 +828,16 @@ inline uint8 HeightFieldShape::GetHeightSample(uint inX, uint inY) const144uint bit_pos = sample & 0b111;145146// Fetch the height sample value147- JPH_ASSERT(byte_pos + 1 < mHeightSamplesSize);148+ JPH_ASSERT(byte_pos + 2 < mHeightSamplesSize); // We read max 16 bits which could be spread out over 3 bytes149const uint8 *height_samples = mHeightSamples + byte_pos;150- uint16 height_sample = uint16(height_samples[0]) | uint16(uint16(height_samples[1]) << 8);151- return uint8(height_sample >> bit_pos) & mSampleMask;152+ uint32 height_sample = uint32(height_samples[0]) | (uint32(height_samples[1]) << 8) | (uint32(height_samples[2]) << 16);153+ return uint16(height_sample >> bit_pos) & mSampleMask;154}155156inline Vec3 HeightFieldShape::GetPosition(uint inX, uint inY, float inBlockOffset, float inBlockScale, bool &outNoCollision) const157{158// Get quantized value159- uint8 height_sample = GetHeightSample(inX, inY);160+ uint16 height_sample = GetHeightSample(inX, inY);161outNoCollision = height_sample == mSampleMask;162163// Add 0.5 to the quantized value to minimize the error (see constructor)164@@ -980,7 +981,7 @@ void HeightFieldShape::GetHeights(uint inX, uint inY, uint inSizeX, uint inSizeY165uint output_y = block_y * mBlockSize + sample_y;166167// Get quantized value168- uint8 height_sample = GetHeightSample(inX + output_x, inY + output_y);169+ uint16 height_sample = GetHeightSample(inX + output_x, inY + output_y);170171// Dequantize172float h = height_sample != mSampleMask? offset + height_sample * scale : cNoCollisionValue;173@@ -1129,7 +1130,7 @@ void HeightFieldShape::SetHeights(uint inX, uint inY, uint inSizeX, uint inSizeY174{175// Quantize height176float h = heights[sample_y * heights_stride + sample_x];177- uint8 quantized_height = h != cNoCollisionValue? uint8(Clamp((int)floor((h - offset) / scale), 0, int(mSampleMask) - 1)) : mSampleMask;178+ uint16 quantized_height = h != cNoCollisionValue? uint16(Clamp((int)floor((h - offset) / scale), 0, int(mSampleMask) - 1)) : mSampleMask;179180// Determine bit position of sample181uint sample = ((affected_y + sample_y) * mSampleCount + affected_x + sample_x) * uint(mBitsPerSample);182@@ -1137,13 +1138,14 @@ void HeightFieldShape::SetHeights(uint inX, uint inY, uint inSizeX, uint inSizeY183uint bit_pos = sample & 0b111;184185// Update the height value sample186- JPH_ASSERT(byte_pos + 1 < mHeightSamplesSize);187+ JPH_ASSERT(byte_pos + 2 < mHeightSamplesSize); // We read max 16 bits which could be spread out over 3 bytes188uint8 *height_samples = mHeightSamples + byte_pos;189- uint16 height_sample = uint16(height_samples[0]) | uint16(uint16(height_samples[1]) << 8);190- height_sample &= ~(uint16(mSampleMask) << bit_pos);191- height_sample |= uint16(quantized_height) << bit_pos;192+ uint32 height_sample = uint32(height_samples[0]) | (uint32(height_samples[1]) << 8) | (uint32(height_samples[2]) << 16);193+ height_sample &= ~(uint32(mSampleMask) << bit_pos);194+ height_sample |= uint32(quantized_height) << bit_pos;195height_samples[0] = uint8(height_sample);196height_samples[1] = uint8(height_sample >> 8);197+ height_samples[2] = uint8(height_sample >> 16);198}199}200201diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.h202index 5aa6de88..c9bdc605 100644203--- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.h204+++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.h205@@ -33,6 +33,9 @@ namespace HeightFieldShapeConstants206/// When height samples are converted to 16 bit:207constexpr uint16 cNoCollisionValue16 = 0xffff; ///< This is the magic value for 'no collision'208constexpr uint16 cMaxHeightValue16 = 0xfffe; ///< This is the maximum allowed height value209+210+ /// Maximum value for HeightFieldShapeSettings::mBitsPerSample211+ constexpr uint32 cMaxBitsPerSample = 16;212};213214/// Class that constructs a HeightFieldShape215@@ -63,7 +66,7 @@ public:216217/// Given mBlockSize, mSampleCount and mHeightSamples, calculate the amount of bits needed to stay below absolute error inMaxError218/// @param inMaxError Maximum allowed error in mHeightSamples after compression (note that this does not take mScale.Y into account)219- /// @return Needed bits per sample in the range [1, 8].220+ /// @return Needed bits per sample in the range [1, 16].221uint32 CalculateBitsPerSampleForError(float inMaxError) const;222223/// The height field is a surface defined by: mOffset + mScale * (x, mHeightSamples[y * mSampleCount + x], y).224@@ -83,12 +86,12 @@ public:225uint32 mMaterialsCapacity = 0;226227/// The heightfield is divided in blocks of mBlockSize * mBlockSize * 2 triangles and the acceleration structure culls blocks only,228- /// bigger block sizes reduce memory consumption but also reduce query performance. Sensible values are [2, 8], does not need to be229+ /// bigger block sizes reduce memory consumption but also reduce query performance. Valid values are [2, 8], does not need to be230/// a power of 2. Note that at run-time we'll perform one more grid subdivision, so the effective block size is half of what is provided here.231uint32 mBlockSize = 2;232233- /// How many bits per sample to use to compress the height field. Can be in the range [1, 8].234- /// Note that each sample is compressed relative to the min/max value of its block of mBlockSize * mBlockSize pixels so the effective precision is higher.235+ /// How many bits per sample to use to compress the height field. Can be in the range [1, 16].236+ /// Note that each sample is compressed relative to the min/max value of its block of mBlockSize * mBlockSize samples so the effective precision is higher.237/// Also note that increasing mBlockSize saves more memory than reducing the amount of bits per sample.238uint32 mBitsPerSample = 8;239240@@ -307,7 +310,7 @@ private:241inline void GetBlockOffsetAndScale(uint inBlockX, uint inBlockY, uint inRangeBlockOffset, uint inRangeBlockStride, float &outBlockOffset, float &outBlockScale) const;242243/// Get the height sample at position (inX, inY)244- inline uint8 GetHeightSample(uint inX, uint inY) const;245+ inline uint16 GetHeightSample(uint inX, uint inY) const;246247/// Faster version of GetPosition when block offset and scale are already known248inline Vec3 GetPosition(uint inX, uint inY, float inBlockOffset, float inBlockScale, bool &outNoCollision) const;249@@ -358,7 +361,7 @@ private:250uint32 mRangeBlocksSize = 0; ///< Size of mRangeBlocks in elements251uint32 mActiveEdgesSize = 0; ///< Size of mActiveEdges in bytes252uint8 mBitsPerSample = 8; ///< See HeightFieldShapeSettings::mBitsPerSample253- uint8 mSampleMask = 0xff; ///< All bits set for a sample: (1 << mBitsPerSample) - 1, used to indicate that there's no collision254+ uint16 mSampleMask = 0xff; ///< All bits set for a sample: (1 << mBitsPerSample) - 1, used to indicate that there's no collision255uint16 mMinSample = HeightFieldShapeConstants::cNoCollisionValue16; ///< Min and max value in mHeightSamples quantized to 16 bit, for calculating bounding box256uint16 mMaxSample = HeightFieldShapeConstants::cNoCollisionValue16;257RangeBlock * mRangeBlocks = nullptr; ///< Hierarchical grid of range data describing the height variations within 1 block. The grid for level <level> starts at offset sGridOffsets[<level>]258diff --git a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h259index 1109e253..cbd88d1a 100644260--- a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h261+++ b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h262@@ -16,7 +16,10 @@ constexpr float cDefaultPenetrationTolerance = 1.0e-4f; ///< Stop when there's l263constexpr float cDefaultConvexRadius = 0.05f;264265/// Used by (Tapered)CapsuleShape to determine when supporting face is an edge rather than a point (unit: meter)266-static constexpr float cCapsuleProjectionSlop = 0.02f;267+constexpr float cCapsuleProjectionSlop = 0.02f;268+269+/// Max squared distance to consider a vertex to be the same as another vertex, used by the internal edge removal algorithm to determine if two edges are shared (unit: meter^2)270+constexpr float cDefaultInternalEdgeRemovalVertexToleranceSq = 1.0e-8f;271272/// Maximum amount of jobs to allow273constexpr int cMaxPhysicsJobs = 2048;274@@ -73,6 +76,9 @@ struct PhysicsSettings275/// Maximum allowed distance between old and new contact point to preserve contact forces for warm start (units: meter^2)276float mContactPointPreserveLambdaMaxDistSq = Square(0.01f); ///< 1 cm277278+ /// Max squared distance to consider a vertex to be the same as another vertex, used by the internal edge removal algorithm to determine if two edges are shared. (unit: meter^2)279+ float mInternalEdgeRemovalVertexToleranceSq = cDefaultInternalEdgeRemovalVertexToleranceSq;280+281/// Number of solver velocity iterations to run282/// Note that this needs to be >= 2 in order for friction to work (friction is applied using the non-penetration impulse from the previous iteration)283uint mNumVelocitySteps = 10;284diff --git a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp285index 7b4babfc..c2ead513 100644286--- a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp287+++ b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp288@@ -1096,6 +1096,7 @@ void PhysicsSystem::ProcessBodyPair(ContactAllocator &ioContactAllocator, const289settings.mActiveEdgeMode = mPhysicsSettings.mCheckActiveEdges? EActiveEdgeMode::CollideOnlyWithActive : EActiveEdgeMode::CollideWithAll;290settings.mMaxSeparationDistance = body1->IsSensor() || body2->IsSensor()? 0.0f : mPhysicsSettings.mSpeculativeContactDistance;291settings.mActiveEdgeMovementDirection = body1->GetLinearVelocity() - body2->GetLinearVelocity();292+ settings.mInternalEdgeRemovalVertexToleranceSq = mPhysicsSettings.mInternalEdgeRemovalVertexToleranceSq;293294// Create shape filter295SimShapeFilterWrapper shape_filter(mSimShapeFilter, body1);2962.52.0.windows.1297298299