diff --git a/modules/jolt_physics/config.py b/modules/jolt_physics/config.py index a42f27fbe12..dea89f0618f 100644 --- a/modules/jolt_physics/config.py +++ b/modules/jolt_physics/config.py @@ -1,5 +1,5 @@ def can_build(env, platform): - return not env["disable_3d"] + return not env["disable_3d"] and not env["arch"] == "ppc32" def configure(env): diff --git a/thirdparty/README.md b/thirdparty/README.md index d0ad28f44b3..4af4368085d 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -436,7 +436,7 @@ Files generated from upstream source: ## jolt_physics - Upstream: https://github.com/jrouwe/JoltPhysics -- Version: 5.2.1 (e3d3cdf644389b621914bb6e73d52ee3137591a7, 2024) +- Version: 5.2.1 (f094082aa2bbfcbebc725dbe8b8f65c7d5152886, 2024) - License: MIT Files extracted from upstream source: diff --git a/thirdparty/jolt_physics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h b/thirdparty/jolt_physics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h index 15717a2da74..c0feea7fe20 100644 --- a/thirdparty/jolt_physics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h +++ b/thirdparty/jolt_physics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h @@ -254,6 +254,15 @@ public: const Node *node = reinterpret_cast(inBufferStart + (node_properties << OFFSET_NON_SIGNIFICANT_BITS)); // Unpack bounds + #ifdef JPH_CPU_BIG_ENDIAN + Vec4 bounds_minx = HalfFloatConversion::ToFloat(UVec4(node->mBoundsMinX[0] + (node->mBoundsMinX[1] << 16), node->mBoundsMinX[2] + (node->mBoundsMinX[3] << 16), 0, 0)); + Vec4 bounds_miny = HalfFloatConversion::ToFloat(UVec4(node->mBoundsMinY[0] + (node->mBoundsMinY[1] << 16), node->mBoundsMinY[2] + (node->mBoundsMinY[3] << 16), 0, 0)); + Vec4 bounds_minz = HalfFloatConversion::ToFloat(UVec4(node->mBoundsMinZ[0] + (node->mBoundsMinZ[1] << 16), node->mBoundsMinZ[2] + (node->mBoundsMinZ[3] << 16), 0, 0)); + + Vec4 bounds_maxx = HalfFloatConversion::ToFloat(UVec4(node->mBoundsMaxX[0] + (node->mBoundsMaxX[1] << 16), node->mBoundsMaxX[2] + (node->mBoundsMaxX[3] << 16), 0, 0)); + Vec4 bounds_maxy = HalfFloatConversion::ToFloat(UVec4(node->mBoundsMaxY[0] + (node->mBoundsMaxY[1] << 16), node->mBoundsMaxY[2] + (node->mBoundsMaxY[3] << 16), 0, 0)); + Vec4 bounds_maxz = HalfFloatConversion::ToFloat(UVec4(node->mBoundsMaxZ[0] + (node->mBoundsMaxZ[1] << 16), node->mBoundsMaxZ[2] + (node->mBoundsMaxZ[3] << 16), 0, 0)); + #else UVec4 bounds_minxy = UVec4::sLoadInt4(reinterpret_cast(&node->mBoundsMinX[0])); Vec4 bounds_minx = HalfFloatConversion::ToFloat(bounds_minxy); Vec4 bounds_miny = HalfFloatConversion::ToFloat(bounds_minxy.Swizzle()); @@ -265,6 +274,7 @@ public: UVec4 bounds_maxyz = UVec4::sLoadInt4(reinterpret_cast(&node->mBoundsMaxY[0])); Vec4 bounds_maxy = HalfFloatConversion::ToFloat(bounds_maxyz); Vec4 bounds_maxz = HalfFloatConversion::ToFloat(bounds_maxyz.Swizzle()); + #endif // Load properties for 4 children UVec4 properties = UVec4::sLoadInt4(&node->mNodeProperties[0]); diff --git a/thirdparty/jolt_physics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h b/thirdparty/jolt_physics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h index 2168a5e43a7..b3c33c5155b 100644 --- a/thirdparty/jolt_physics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h +++ b/thirdparty/jolt_physics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h @@ -338,7 +338,7 @@ public: class DecodingContext { private: - /// Private helper functions to unpack the 1 vertex of 4 triangles (outX contains the x coordinate of triangle 0 .. 3 etc.) + /// Private helper function to unpack the 1 vertex of 4 triangles (outX contains the x coordinate of triangle 0 .. 3 etc.) JPH_INLINE void Unpack(const VertexData *inVertices, UVec4Arg inIndex, Vec4 &outX, Vec4 &outY, Vec4 &outZ) const { // Get compressed data @@ -356,6 +356,28 @@ public: outZ = Vec4::sFusedMultiplyAdd(zc.ToFloat(), mScaleZ, mOffsetZ); } + /// Private helper function to unpack 4 triangles from a triangle block + JPH_INLINE void Unpack(const TriangleBlock *inBlock, const VertexData *inVertices, Vec4 &outX1, Vec4 &outY1, Vec4 &outZ1, Vec4 &outX2, Vec4 &outY2, Vec4 &outZ2, Vec4 &outX3, Vec4 &outY3, Vec4 &outZ3) const + { + // Get the indices for the three vertices (reads 4 bytes extra, but these are the flags so that's ok) + UVec4 indices = UVec4::sLoadInt4(reinterpret_cast(&inBlock->mIndices[0])); + UVec4 iv1 = indices.Expand4Byte0(); + UVec4 iv2 = indices.Expand4Byte4(); + UVec4 iv3 = indices.Expand4Byte8(); + + #ifdef JPH_CPU_BIG_ENDIAN + // On big endian systems we need to reverse the bytes + iv1 = iv1.Swizzle(); + iv2 = iv2.Swizzle(); + iv3 = iv3.Swizzle(); + #endif + + // Decompress the triangle data + Unpack(inVertices, iv1, outX1, outY1, outZ1); + Unpack(inVertices, iv2, outX2, outY2, outZ2); + Unpack(inVertices, iv3, outX3, outY3, outZ3); + } + public: JPH_INLINE explicit DecodingContext(const TriangleHeader *inHeader) : mOffsetX(Vec4::sReplicate(inHeader->mOffset.x)), @@ -380,17 +402,9 @@ public: do { - // Get the indices for the three vertices (reads 4 bytes extra, but these are the flags so that's ok) - UVec4 indices = UVec4::sLoadInt4(reinterpret_cast(&t->mIndices[0])); - UVec4 iv1 = indices.Expand4Byte0(); - UVec4 iv2 = indices.Expand4Byte4(); - UVec4 iv3 = indices.Expand4Byte8(); - - // Decompress the triangle data + // Unpack the vertices for 4 triangles Vec4 v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z; - Unpack(vertices, iv1, v1x, v1y, v1z); - Unpack(vertices, iv2, v2x, v2y, v2z); - Unpack(vertices, iv3, v3x, v3y, v3z); + Unpack(t, vertices, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z); // Transpose it so we get normal vectors Mat44 v1 = Mat44(v1x, v1y, v1z, Vec4::sZero()).Transposed(); @@ -425,17 +439,9 @@ public: UVec4 start_triangle_idx = UVec4::sZero(); do { - // Get the indices for the three vertices (reads 4 bytes extra, but these are the flags so that's ok) - UVec4 indices = UVec4::sLoadInt4(reinterpret_cast(&t->mIndices[0])); - UVec4 iv1 = indices.Expand4Byte0(); - UVec4 iv2 = indices.Expand4Byte4(); - UVec4 iv3 = indices.Expand4Byte8(); - - // Decompress the triangle data + // Unpack the vertices for 4 triangles Vec4 v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z; - Unpack(vertices, iv1, v1x, v1y, v1z); - Unpack(vertices, iv2, v2x, v2y, v2z); - Unpack(vertices, iv3, v3x, v3y, v3z); + Unpack(t, vertices, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z); // Perform ray vs triangle test Vec4 distance = RayTriangle4(inRayOrigin, inRayDirection, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z); diff --git a/thirdparty/jolt_physics/Jolt/ConfigurationString.h b/thirdparty/jolt_physics/Jolt/ConfigurationString.h index 55e5d8c35ff..1ff1969b241 100644 --- a/thirdparty/jolt_physics/Jolt/ConfigurationString.h +++ b/thirdparty/jolt_physics/Jolt/ConfigurationString.h @@ -14,8 +14,23 @@ inline const char *GetConfigurationString() "x86 " #elif defined(JPH_CPU_ARM) "ARM " -#elif defined(JPH_PLATFORM_WASM) +#elif defined(JPH_CPU_RISCV) + "RISC-V " +#elif defined(JPH_CPU_PPC) + "PowerPC " + #ifdef JPH_CPU_BIG_ENDIAN + "(Big Endian) " + #else + "(Little Endian) " + #endif +#elif defined(JPH_CPU_LOONGARCH) + "LoongArch " +#elif defined(JPH_CPU_E2K) + "E2K " +#elif defined(JPH_CPU_WASM) "WASM " +#else + #error Unknown CPU architecture #endif #if JPH_CPU_ADDRESS_BITS == 64 "64-bit " diff --git a/thirdparty/jolt_physics/Jolt/Core/Array.h b/thirdparty/jolt_physics/Jolt/Core/Array.h index dd0a9e1ea04..a273f4eb50f 100644 --- a/thirdparty/jolt_physics/Jolt/Core/Array.h +++ b/thirdparty/jolt_physics/Jolt/Core/Array.h @@ -59,7 +59,7 @@ private: { for (T *destination_end = inDestination + inCount; inDestination < destination_end; ++inDestination, ++inSource) { - ::new (inDestination) T(std::move(*inSource)); + new (inDestination) T(std::move(*inSource)); inSource->~T(); } } @@ -67,7 +67,7 @@ private: { for (T *destination = inDestination + inCount - 1, *source = inSource + inCount - 1; destination >= inDestination; --destination, --source) { - ::new (destination) T(std::move(*source)); + new (destination) T(std::move(*source)); source->~T(); } } @@ -124,7 +124,7 @@ public: if constexpr (!std::is_trivially_constructible()) for (T *element = mElements + mSize, *element_end = mElements + inNewSize; element < element_end; ++element) - ::new (element) T; + new (element) T; mSize = inNewSize; } @@ -137,7 +137,7 @@ public: reserve(inNewSize); for (T *element = mElements + mSize, *element_end = mElements + inNewSize; element < element_end; ++element) - ::new (element) T(inValue); + new (element) T(inValue); mSize = inNewSize; } @@ -187,7 +187,7 @@ public: reserve(size_type(std::distance(inBegin, inEnd))); for (Iterator element = inBegin; element != inEnd; ++element) - ::new (&mElements[mSize++]) T(*element); + new (&mElements[mSize++]) T(*element); } /// Replace the contents of this array with inList @@ -197,7 +197,7 @@ public: reserve(size_type(inList.size())); for (const T &v : inList) - ::new (&mElements[mSize++]) T(v); + new (&mElements[mSize++]) T(v); } /// Default constructor @@ -281,7 +281,7 @@ public: grow(); T *element = mElements + mSize++; - ::new (element) T(inValue); + new (element) T(inValue); } inline void push_back(T &&inValue) @@ -289,7 +289,7 @@ public: grow(); T *element = mElements + mSize++; - ::new (element) T(std::move(inValue)); + new (element) T(std::move(inValue)); } /// Construct element at the back of the array @@ -299,7 +299,7 @@ public: grow(); T *element = mElements + mSize++; - ::new (element) T(std::forward(inValue)...); + new (element) T(std::forward(inValue)...); return *element; } @@ -365,7 +365,7 @@ public: move(element_end, element_begin, mSize - first_element); for (T *element = element_begin; element < element_end; ++element, ++inBegin) - ::new (element) T(*inBegin); + new (element) T(*inBegin); mSize += num_elements; } @@ -383,7 +383,7 @@ public: T *element = mElements + first_element; move(element + 1, element, mSize - first_element); - ::new (element) T(inValue); + new (element) T(inValue); mSize++; } diff --git a/thirdparty/jolt_physics/Jolt/Core/ByteBuffer.h b/thirdparty/jolt_physics/Jolt/Core/ByteBuffer.h index 48d19703f3e..610b1515570 100644 --- a/thirdparty/jolt_physics/Jolt/Core/ByteBuffer.h +++ b/thirdparty/jolt_physics/Jolt/Core/ByteBuffer.h @@ -41,7 +41,7 @@ public: // Construct elements for (Type *d = data, *d_end = data + inSize; d < d_end; ++d) - ::new (d) Type; + new (d) Type; // Return pointer return data; diff --git a/thirdparty/jolt_physics/Jolt/Core/Core.h b/thirdparty/jolt_physics/Jolt/Core/Core.h index a0ad97eeb63..01b6afbf19f 100644 --- a/thirdparty/jolt_physics/Jolt/Core/Core.h +++ b/thirdparty/jolt_physics/Jolt/Core/Core.h @@ -180,6 +180,18 @@ #define JPH_VECTOR_ALIGNMENT 8 // 32-bit ARM does not support aligning on the stack on 16 byte boundaries #define JPH_DVECTOR_ALIGNMENT 8 #endif +#elif defined(__riscv) + // RISC-V CPU architecture + #define JPH_CPU_RISCV + #if __riscv_xlen == 64 + #define JPH_CPU_ADDRESS_BITS 64 + #define JPH_VECTOR_ALIGNMENT 16 + #define JPH_DVECTOR_ALIGNMENT 32 + #else + #define JPH_CPU_ADDRESS_BITS 32 + #define JPH_VECTOR_ALIGNMENT 16 + #define JPH_DVECTOR_ALIGNMENT 8 + #endif #elif defined(JPH_PLATFORM_WASM) // WebAssembly CPU architecture #define JPH_CPU_WASM @@ -191,6 +203,29 @@ #define JPH_USE_SSE4_1 #define JPH_USE_SSE4_2 #endif +#elif defined(__powerpc__) || defined(__powerpc64__) + // PowerPC CPU architecture + #define JPH_CPU_PPC + #if defined(__powerpc64__) + #define JPH_CPU_ADDRESS_BITS 64 + #else + #define JPH_CPU_ADDRESS_BITS 32 + #endif + #ifdef _BIG_ENDIAN + #define JPH_CPU_BIG_ENDIAN + #endif + #define JPH_VECTOR_ALIGNMENT 16 + #define JPH_DVECTOR_ALIGNMENT 8 +#elif defined(__loongarch__) + // LoongArch CPU architecture + #define JPH_CPU_LOONGARCH + #if defined(__loongarch64) + #define JPH_CPU_ADDRESS_BITS 64 + #else + #define JPH_CPU_ADDRESS_BITS 32 + #endif + #define JPH_VECTOR_ALIGNMENT 16 + #define JPH_DVECTOR_ALIGNMENT 8 #elif defined(__e2k__) // E2K CPU architecture (MCST Elbrus 2000) #define JPH_CPU_E2K @@ -358,10 +393,10 @@ #elif defined(JPH_PLATFORM_LINUX) || defined(JPH_PLATFORM_ANDROID) || defined(JPH_PLATFORM_MACOS) || defined(JPH_PLATFORM_IOS) || defined(JPH_PLATFORM_FREEBSD) #if defined(JPH_CPU_X86) #define JPH_BREAKPOINT __asm volatile ("int $0x3") - #elif defined(JPH_CPU_ARM) - #define JPH_BREAKPOINT __builtin_trap() - #elif defined(JPH_CPU_E2K) + #elif defined(JPH_CPU_ARM) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_E2K) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH) #define JPH_BREAKPOINT __builtin_trap() + #else + #error Unknown CPU architecture #endif #elif defined(JPH_PLATFORM_WASM) #define JPH_BREAKPOINT do { } while (false) // Not supported diff --git a/thirdparty/jolt_physics/Jolt/Core/FPControlWord.h b/thirdparty/jolt_physics/Jolt/Core/FPControlWord.h index 0c8b3f1ff09..9fceee46369 100644 --- a/thirdparty/jolt_physics/Jolt/Core/FPControlWord.h +++ b/thirdparty/jolt_physics/Jolt/Core/FPControlWord.h @@ -126,6 +126,14 @@ private: uint32 mPrevState; }; +#elif defined(JPH_CPU_RISCV) + +// RISC-V only implements manually checking if exceptions occurred by reading the fcsr register. It doesn't generate exceptions. + +#elif defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH) + +// Not implemented right now + #else #error Unsupported CPU architecture diff --git a/thirdparty/jolt_physics/Jolt/Core/FPException.h b/thirdparty/jolt_physics/Jolt/Core/FPException.h index 3083f05c050..ef757802424 100644 --- a/thirdparty/jolt_physics/Jolt/Core/FPException.h +++ b/thirdparty/jolt_physics/Jolt/Core/FPException.h @@ -56,6 +56,14 @@ class FPExceptionDisableInvalid : public FPControlWord<0, FP_IOE> { }; /// Disable division by zero floating point exceptions class FPExceptionDisableDivByZero : public FPControlWord<0, FP_DZE> { }; +#elif defined(JPH_CPU_RISCV) + +#error "RISC-V only implements manually checking if exceptions occurred by reading the fcsr register. It doesn't generate exceptions. JPH_FLOATING_POINT_EXCEPTIONS_ENABLED must be disabled." + +#elif defined(JPH_CPU_PPC) + +#error PowerPC floating point exception handling to be implemented. JPH_FLOATING_POINT_EXCEPTIONS_ENABLED must be disabled. + #else #error Unsupported CPU architecture diff --git a/thirdparty/jolt_physics/Jolt/Core/FPFlushDenormals.h b/thirdparty/jolt_physics/Jolt/Core/FPFlushDenormals.h index 672a19dbecf..74a2c10b354 100644 --- a/thirdparty/jolt_physics/Jolt/Core/FPFlushDenormals.h +++ b/thirdparty/jolt_physics/Jolt/Core/FPFlushDenormals.h @@ -8,7 +8,7 @@ JPH_NAMESPACE_BEGIN -#if defined(JPH_CPU_WASM) +#if defined(JPH_CPU_WASM) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH) // Not supported class FPFlushDenormals { }; @@ -21,6 +21,8 @@ class FPFlushDenormals : public FPControlWord<_MM_FLUSH_ZERO_ON, _MM_FLUSH_ZERO_ #elif defined(JPH_CPU_ARM) && defined(JPH_COMPILER_MSVC) +/// Helper class that needs to be put on the stack to enable flushing denormals to zero +/// This can make floating point operations much faster when working with very small numbers class FPFlushDenormals : public FPControlWord<_DN_FLUSH, _MCW_DN> { }; #elif defined(JPH_CPU_ARM) diff --git a/thirdparty/jolt_physics/Jolt/Core/FixedSizeFreeList.inl b/thirdparty/jolt_physics/Jolt/Core/FixedSizeFreeList.inl index 29d4734c009..3fe40b8925c 100644 --- a/thirdparty/jolt_physics/Jolt/Core/FixedSizeFreeList.inl +++ b/thirdparty/jolt_physics/Jolt/Core/FixedSizeFreeList.inl @@ -79,7 +79,7 @@ uint32 FixedSizeFreeList::ConstructObject(Parameters &&... inParameters) // Allocation successful JPH_IF_ENABLE_ASSERTS(mNumFreeObjects.fetch_sub(1, memory_order_relaxed);) ObjectStorage &storage = GetStorage(first_free); - ::new (&storage.mObject) Object(std::forward(inParameters)...); + new (&storage.mObject) Object(std::forward(inParameters)...); storage.mNextFreeObject.store(first_free, memory_order_release); return first_free; } @@ -97,7 +97,7 @@ uint32 FixedSizeFreeList::ConstructObject(Parameters &&... inParameters) // Allocation successful JPH_IF_ENABLE_ASSERTS(mNumFreeObjects.fetch_sub(1, memory_order_relaxed);) ObjectStorage &storage = GetStorage(first_free); - ::new (&storage.mObject) Object(std::forward(inParameters)...); + new (&storage.mObject) Object(std::forward(inParameters)...); storage.mNextFreeObject.store(first_free, memory_order_release); return first_free; } diff --git a/thirdparty/jolt_physics/Jolt/Core/HashCombine.h b/thirdparty/jolt_physics/Jolt/Core/HashCombine.h index e04b54b7443..ab620841dc8 100644 --- a/thirdparty/jolt_physics/Jolt/Core/HashCombine.h +++ b/thirdparty/jolt_physics/Jolt/Core/HashCombine.h @@ -17,8 +17,8 @@ inline uint64 HashBytes(const void *inData, uint inSize, uint64 inSeed = 0xcbf29 uint64 hash = inSeed; for (const uint8 *data = reinterpret_cast(inData); data < reinterpret_cast(inData) + inSize; ++data) { - hash = hash ^ uint64(*data); - hash = hash * 0x100000001b3UL; + hash ^= uint64(*data); + hash *= 0x100000001b3UL; } return hash; } @@ -31,7 +31,7 @@ constexpr uint64 HashString(const char *inString, uint64 inSeed = 0xcbf29ce48422 for (const char *c = inString; *c != 0; ++c) { hash ^= uint64(*c); - hash = hash * 0x100000001b3UL; + hash *= 0x100000001b3UL; } return hash; } @@ -142,12 +142,33 @@ JPH_DEFINE_TRIVIAL_HASH(int) JPH_DEFINE_TRIVIAL_HASH(uint32) JPH_DEFINE_TRIVIAL_HASH(uint64) -/// @brief Helper function that hashes a single value into ioSeed -/// Taken from: https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x +/// Helper function that hashes a single value into ioSeed +/// Based on https://github.com/jonmaiga/mx3 by Jon Maiga template inline void HashCombine(uint64 &ioSeed, const T &inValue) { - ioSeed ^= Hash { } (inValue) + 0x9e3779b9 + (ioSeed << 6) + (ioSeed >> 2); + constexpr uint64 c = 0xbea225f9eb34556dUL; + + uint64 h = ioSeed; + uint64 x = Hash { } (inValue); + + // See: https://github.com/jonmaiga/mx3/blob/master/mx3.h + // mix_stream(h, x) + x *= c; + x ^= x >> 39; + h += x * c; + h *= c; + + // mix(h) + h ^= h >> 32; + h *= c; + h ^= h >> 29; + h *= c; + h ^= h >> 32; + h *= c; + h ^= h >> 29; + + ioSeed = h; } /// Hash combiner to use a custom struct in an unordered map or set @@ -174,11 +195,6 @@ inline uint64 HashCombineArgs(const FirstValue &inFirstValue, Values... inValues return seed; } -JPH_NAMESPACE_END - -JPH_SUPPRESS_WARNING_PUSH -JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") - #define JPH_MAKE_HASH_STRUCT(type, name, ...) \ struct [[nodiscard]] name \ { \ @@ -188,6 +204,22 @@ JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") } \ }; +#define JPH_MAKE_STD_HASH(type) \ + JPH_SUPPRESS_WARNING_PUSH \ + JPH_SUPPRESS_WARNINGS \ + namespace std \ + { \ + template<> \ + struct [[nodiscard]] hash \ + { \ + size_t operator()(const type &t) const \ + { \ + return size_t(::JPH::Hash{ }(t)); \ + } \ + }; \ + } \ + JPH_SUPPRESS_WARNING_POP + #define JPH_MAKE_HASHABLE(type, ...) \ JPH_SUPPRESS_WARNING_PUSH \ JPH_SUPPRESS_WARNINGS \ @@ -196,17 +228,7 @@ JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") template<> \ JPH_MAKE_HASH_STRUCT(type, Hash, __VA_ARGS__) \ } \ - namespace std \ - { \ - template<> \ - struct [[nodiscard]] hash \ - { \ - std::size_t operator()(const type &t) const \ - { \ - return std::size_t(::JPH::Hash{ }(t));\ - } \ - }; \ - } \ - JPH_SUPPRESS_WARNING_POP + JPH_SUPPRESS_WARNING_POP \ + JPH_MAKE_STD_HASH(type) -JPH_SUPPRESS_WARNING_POP +JPH_NAMESPACE_END diff --git a/thirdparty/jolt_physics/Jolt/Core/HashTable.h b/thirdparty/jolt_physics/Jolt/Core/HashTable.h index baca08255ba..9b69f9d0840 100644 --- a/thirdparty/jolt_physics/Jolt/Core/HashTable.h +++ b/thirdparty/jolt_physics/Jolt/Core/HashTable.h @@ -175,7 +175,7 @@ private: uint index = 0; for (const uint8 *control = mControl, *control_end = mControl + mMaxSize; control != control_end; ++control, ++index) if (*control & cBucketUsed) - ::new (mData + index) KeyValue(inRHS.mData[index]); + new (mData + index) KeyValue(inRHS.mData[index]); mSize = inRHS.mSize; } @@ -216,7 +216,7 @@ private: KeyValue *element = old_data + i; JPH_IF_ENABLE_ASSERTS(bool inserted =) InsertKey(HashTableDetail::sGetKey(*element), index); JPH_ASSERT(inserted); - ::new (mData + index) KeyValue(std::move(*element)); + new (mData + index) KeyValue(std::move(*element)); element->~KeyValue(); } @@ -601,7 +601,7 @@ public: size_type index; bool inserted = InsertKey(HashTableDetail::sGetKey(inValue), index); if (inserted) - ::new (mData + index) KeyValue(inValue); + new (mData + index) KeyValue(inValue); return std::make_pair(iterator(this, index), inserted); } @@ -800,7 +800,7 @@ public: // There's an empty bucket, move us there SetControlValue(dst, src_control); SetControlValue(src, cBucketEmpty); - ::new (mData + dst) KeyValue(std::move(mData[src])); + new (mData + dst) KeyValue(std::move(mData[src])); mData[src].~KeyValue(); break; } diff --git a/thirdparty/jolt_physics/Jolt/Core/Memory.h b/thirdparty/jolt_physics/Jolt/Core/Memory.h index d5b7c6a308b..b5f318db1cf 100644 --- a/thirdparty/jolt_physics/Jolt/Core/Memory.h +++ b/thirdparty/jolt_physics/Jolt/Core/Memory.h @@ -36,7 +36,11 @@ JPH_EXPORT void RegisterDefaultAllocator(); JPH_INLINE void *operator new (size_t inCount, std::align_val_t inAlignment) { return JPH::AlignedAllocate(inCount, static_cast(inAlignment)); } \ JPH_INLINE void operator delete (void *inPointer, [[maybe_unused]] std::align_val_t inAlignment) noexcept { JPH::AlignedFree(inPointer); } \ JPH_INLINE void *operator new[] (size_t inCount, std::align_val_t inAlignment) { return JPH::AlignedAllocate(inCount, static_cast(inAlignment)); } \ - JPH_INLINE void operator delete[] (void *inPointer, [[maybe_unused]] std::align_val_t inAlignment) noexcept { JPH::AlignedFree(inPointer); } + JPH_INLINE void operator delete[] (void *inPointer, [[maybe_unused]] std::align_val_t inAlignment) noexcept { JPH::AlignedFree(inPointer); } \ + JPH_INLINE void *operator new ([[maybe_unused]] size_t inCount, void *inPointer) noexcept { return inPointer; } \ + JPH_INLINE void operator delete ([[maybe_unused]] void *inPointer, [[maybe_unused]] void *inPlace) noexcept { /* Do nothing */ } \ + JPH_INLINE void *operator new[] ([[maybe_unused]] size_t inCount, void *inPointer) noexcept { return inPointer; } \ + JPH_INLINE void operator delete[] ([[maybe_unused]] void *inPointer, [[maybe_unused]] void *inPlace) noexcept { /* Do nothing */ } #else diff --git a/thirdparty/jolt_physics/Jolt/Core/Result.h b/thirdparty/jolt_physics/Jolt/Core/Result.h index ad2eab164bd..282b35adbb0 100644 --- a/thirdparty/jolt_physics/Jolt/Core/Result.h +++ b/thirdparty/jolt_physics/Jolt/Core/Result.h @@ -21,11 +21,11 @@ public: switch (inRHS.mState) { case EState::Valid: - ::new (&mResult) Type (inRHS.mResult); + new (&mResult) Type (inRHS.mResult); break; case EState::Error: - ::new (&mError) String(inRHS.mError); + new (&mError) String(inRHS.mError); break; case EState::Invalid: @@ -40,11 +40,11 @@ public: switch (inRHS.mState) { case EState::Valid: - ::new (&mResult) Type (std::move(inRHS.mResult)); + new (&mResult) Type (std::move(inRHS.mResult)); break; case EState::Error: - ::new (&mError) String(std::move(inRHS.mError)); + new (&mError) String(std::move(inRHS.mError)); break; case EState::Invalid: @@ -67,11 +67,11 @@ public: switch (inRHS.mState) { case EState::Valid: - ::new (&mResult) Type (inRHS.mResult); + new (&mResult) Type (inRHS.mResult); break; case EState::Error: - ::new (&mError) String(inRHS.mError); + new (&mError) String(inRHS.mError); break; case EState::Invalid: @@ -91,11 +91,11 @@ public: switch (inRHS.mState) { case EState::Valid: - ::new (&mResult) Type (std::move(inRHS.mResult)); + new (&mResult) Type (std::move(inRHS.mResult)); break; case EState::Error: - ::new (&mError) String(std::move(inRHS.mError)); + new (&mError) String(std::move(inRHS.mError)); break; case EState::Invalid: @@ -137,10 +137,10 @@ public: const Type & Get() const { JPH_ASSERT(IsValid()); return mResult; } /// Set the result value - void Set(const Type &inResult) { Clear(); ::new (&mResult) Type(inResult); mState = EState::Valid; } + void Set(const Type &inResult) { Clear(); new (&mResult) Type(inResult); mState = EState::Valid; } /// Set the result value (move value) - void Set(Type &&inResult) { Clear(); ::new (&mResult) Type(std::move(inResult)); mState = EState::Valid; } + void Set(Type &&inResult) { Clear(); new (&mResult) Type(std::move(inResult)); mState = EState::Valid; } /// Check if we had an error bool HasError() const { return mState == EState::Error; } @@ -149,9 +149,9 @@ public: const String & GetError() const { JPH_ASSERT(HasError()); return mError; } /// Set an error value - void SetError(const char *inError) { Clear(); ::new (&mError) String(inError); mState = EState::Error; } - void SetError(const string_view &inError) { Clear(); ::new (&mError) String(inError); mState = EState::Error; } - void SetError(String &&inError) { Clear(); ::new (&mError) String(std::move(inError)); mState = EState::Error; } + void SetError(const char *inError) { Clear(); new (&mError) String(inError); mState = EState::Error; } + void SetError(const string_view &inError) { Clear(); new (&mError) String(inError); mState = EState::Error; } + void SetError(String &&inError) { Clear(); new (&mError) String(std::move(inError)); mState = EState::Error; } private: union diff --git a/thirdparty/jolt_physics/Jolt/Core/StaticArray.h b/thirdparty/jolt_physics/Jolt/Core/StaticArray.h index fddaaa37a2c..421bf680f59 100644 --- a/thirdparty/jolt_physics/Jolt/Core/StaticArray.h +++ b/thirdparty/jolt_physics/Jolt/Core/StaticArray.h @@ -27,7 +27,7 @@ public: { JPH_ASSERT(inList.size() <= N); for (const T &v : inList) - ::new (reinterpret_cast(&mElements[mSize++])) T(v); + new (reinterpret_cast(&mElements[mSize++])) T(v); } /// Copy constructor @@ -35,7 +35,7 @@ public: { while (mSize < inRHS.mSize) { - ::new (&mElements[mSize]) T(inRHS[mSize]); + new (&mElements[mSize]) T(inRHS[mSize]); ++mSize; } } @@ -61,7 +61,7 @@ public: void push_back(const T &inElement) { JPH_ASSERT(mSize < N); - ::new (&mElements[mSize++]) T(inElement); + new (&mElements[mSize++]) T(inElement); } /// Construct element at the back of the array @@ -69,7 +69,7 @@ public: void emplace_back(A &&... inElement) { JPH_ASSERT(mSize < N); - ::new (&mElements[mSize++]) T(std::forward(inElement)...); + new (&mElements[mSize++]) T(std::forward(inElement)...); } /// Remove element from the back of the array @@ -103,7 +103,7 @@ public: JPH_ASSERT(inNewSize <= N); if constexpr (!std::is_trivially_constructible()) for (T *element = reinterpret_cast(mElements) + mSize, *element_end = reinterpret_cast(mElements) + inNewSize; element < element_end; ++element) - ::new (element) T; + new (element) T; if constexpr (!std::is_trivially_destructible()) for (T *element = reinterpret_cast(mElements) + inNewSize, *element_end = reinterpret_cast(mElements) + mSize; element < element_end; ++element) element->~T(); @@ -232,7 +232,7 @@ public: while (mSize < rhs_size) { - ::new (&mElements[mSize]) T(inRHS[mSize]); + new (&mElements[mSize]) T(inRHS[mSize]); ++mSize; } } @@ -253,7 +253,7 @@ public: while (mSize < rhs_size) { - ::new (&mElements[mSize]) T(inRHS[mSize]); + new (&mElements[mSize]) T(inRHS[mSize]); ++mSize; } } diff --git a/thirdparty/jolt_physics/Jolt/Core/TickCounter.h b/thirdparty/jolt_physics/Jolt/Core/TickCounter.h index 2b5410e3d9f..7701bd2dcd8 100644 --- a/thirdparty/jolt_physics/Jolt/Core/TickCounter.h +++ b/thirdparty/jolt_physics/Jolt/Core/TickCounter.h @@ -35,9 +35,7 @@ JPH_INLINE uint64 GetProcessorTickCount() uint64 val; asm volatile("mrs %0, cntvct_el0" : "=r" (val)); return val; -#elif defined(JPH_CPU_ARM) - return 0; // Not supported -#elif defined(JPH_CPU_WASM) +#elif defined(JPH_CPU_ARM) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_WASM) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH) return 0; // Not supported #else #error Undefined diff --git a/thirdparty/jolt_physics/Jolt/Core/UnorderedMap.h b/thirdparty/jolt_physics/Jolt/Core/UnorderedMap.h index f876e2849e2..236eaaa69f2 100644 --- a/thirdparty/jolt_physics/Jolt/Core/UnorderedMap.h +++ b/thirdparty/jolt_physics/Jolt/Core/UnorderedMap.h @@ -42,7 +42,7 @@ public: bool inserted = this->InsertKey(inKey, index); value_type &key_value = this->GetElement(index); if (inserted) - ::new (&key_value) value_type(inKey, Value()); + new (&key_value) value_type(inKey, Value()); return key_value.second; } @@ -52,7 +52,7 @@ public: size_type index; bool inserted = this->InsertKey(inKey, index); if (inserted) - ::new (&this->GetElement(index)) value_type(std::piecewise_construct, std::forward_as_tuple(inKey), std::forward_as_tuple(std::forward(inArgs)...)); + new (&this->GetElement(index)) value_type(std::piecewise_construct, std::forward_as_tuple(inKey), std::forward_as_tuple(std::forward(inArgs)...)); return std::make_pair(iterator(this, index), inserted); } @@ -62,7 +62,7 @@ public: size_type index; bool inserted = this->InsertKey(inKey, index); if (inserted) - ::new (&this->GetElement(index)) value_type(std::piecewise_construct, std::forward_as_tuple(std::move(inKey)), std::forward_as_tuple(std::forward(inArgs)...)); + new (&this->GetElement(index)) value_type(std::piecewise_construct, std::forward_as_tuple(std::move(inKey)), std::forward_as_tuple(std::forward(inArgs)...)); return std::make_pair(iterator(this, index), inserted); } diff --git a/thirdparty/jolt_physics/Jolt/Geometry/Ellipse.h b/thirdparty/jolt_physics/Jolt/Geometry/Ellipse.h index bfa508faae8..466d508bb87 100644 --- a/thirdparty/jolt_physics/Jolt/Geometry/Ellipse.h +++ b/thirdparty/jolt_physics/Jolt/Geometry/Ellipse.h @@ -38,7 +38,7 @@ public: // <=> (x', y') = (a^2 x / (t + a^2), b^2 y / (t + b^2)) // Requiring point to be on ellipse (substituting into [1]): g(t) = (a x / (t + a^2))^2 + (b y / (t + b^2))^2 - 1 = 0 - // Newton raphson iteration, starting at t = 0 + // Newton Raphson iteration, starting at t = 0 float t = 0.0f; for (;;) { diff --git a/thirdparty/jolt_physics/Jolt/Geometry/IndexedTriangle.h b/thirdparty/jolt_physics/Jolt/Geometry/IndexedTriangle.h index 7ebffc29c51..f118dae7495 100644 --- a/thirdparty/jolt_physics/Jolt/Geometry/IndexedTriangle.h +++ b/thirdparty/jolt_physics/Jolt/Geometry/IndexedTriangle.h @@ -65,6 +65,13 @@ public: return (Vec3(inVertices[mIdx[0]]) + Vec3(inVertices[mIdx[1]]) + Vec3(inVertices[mIdx[2]])) / 3.0f; } + /// Get the hash value of this structure + uint64 GetHash() const + { + static_assert(sizeof(IndexedTriangleNoMaterial) == 3 * sizeof(uint32), "Class should have no padding"); + return HashBytes(this, sizeof(IndexedTriangleNoMaterial)); + } + uint32 mIdx[3]; }; @@ -102,6 +109,13 @@ public: } } + /// Get the hash value of this structure + uint64 GetHash() const + { + static_assert(sizeof(IndexedTriangle) == 5 * sizeof(uint32), "Class should have no padding"); + return HashBytes(this, sizeof(IndexedTriangle)); + } + uint32 mMaterialIndex = 0; uint32 mUserData = 0; ///< User data that can be used for anything by the application, e.g. for tracking the original index of the triangle }; @@ -111,6 +125,6 @@ using IndexedTriangleList = Array; JPH_NAMESPACE_END -// Create a std::hash/JPH::Hash for IndexedTriangleNoMaterial and IndexedTriangle -JPH_MAKE_HASHABLE(JPH::IndexedTriangleNoMaterial, t.mIdx[0], t.mIdx[1], t.mIdx[2]) -JPH_MAKE_HASHABLE(JPH::IndexedTriangle, t.mIdx[0], t.mIdx[1], t.mIdx[2], t.mMaterialIndex, t.mUserData) +// Create a std::hash for IndexedTriangleNoMaterial and IndexedTriangle +JPH_MAKE_STD_HASH(JPH::IndexedTriangleNoMaterial) +JPH_MAKE_STD_HASH(JPH::IndexedTriangle) diff --git a/thirdparty/jolt_physics/Jolt/Geometry/RayAABox.h b/thirdparty/jolt_physics/Jolt/Geometry/RayAABox.h index 4506fadbb75..31970e7c1f6 100644 --- a/thirdparty/jolt_physics/Jolt/Geometry/RayAABox.h +++ b/thirdparty/jolt_physics/Jolt/Geometry/RayAABox.h @@ -36,7 +36,7 @@ JPH_INLINE float RayAABox(Vec3Arg inOrigin, const RayInvDirection &inInvDirectio Vec3 flt_min = Vec3::sReplicate(-FLT_MAX); Vec3 flt_max = Vec3::sReplicate(FLT_MAX); - // Test against all three axii simultaneously. + // Test against all three axes simultaneously. Vec3 t1 = (inBoundsMin - inOrigin) * inInvDirection.mInvDirection; Vec3 t2 = (inBoundsMax - inOrigin) * inInvDirection.mInvDirection; @@ -90,7 +90,7 @@ JPH_INLINE Vec4 RayAABox4(Vec3Arg inOrigin, const RayInvDirection &inInvDirectio Vec4 invdiry = inInvDirection.mInvDirection.SplatY(); Vec4 invdirz = inInvDirection.mInvDirection.SplatZ(); - // Test against all three axii simultaneously. + // Test against all three axes simultaneously. Vec4 t1x = (inBoundsMinX - originx) * invdirx; Vec4 t1y = (inBoundsMinY - originy) * invdiry; Vec4 t1z = (inBoundsMinZ - originz) * invdirz; @@ -139,7 +139,7 @@ JPH_INLINE void RayAABox(Vec3Arg inOrigin, const RayInvDirection &inInvDirection Vec3 flt_min = Vec3::sReplicate(-FLT_MAX); Vec3 flt_max = Vec3::sReplicate(FLT_MAX); - // Test against all three axii simultaneously. + // Test against all three axes simultaneously. Vec3 t1 = (inBoundsMin - inOrigin) * inInvDirection.mInvDirection; Vec3 t2 = (inBoundsMax - inOrigin) * inInvDirection.mInvDirection; @@ -178,7 +178,7 @@ JPH_INLINE bool RayAABoxHits(Vec3Arg inOrigin, const RayInvDirection &inInvDirec Vec3 flt_min = Vec3::sReplicate(-FLT_MAX); Vec3 flt_max = Vec3::sReplicate(FLT_MAX); - // Test against all three axii simultaneously. + // Test against all three axes simultaneously. Vec3 t1 = (inBoundsMin - inOrigin) * inInvDirection.mInvDirection; Vec3 t2 = (inBoundsMax - inOrigin) * inInvDirection.mInvDirection; diff --git a/thirdparty/jolt_physics/Jolt/Math/EigenValueSymmetric.h b/thirdparty/jolt_physics/Jolt/Math/EigenValueSymmetric.h index 920ddb9c9e7..dab0e69029f 100644 --- a/thirdparty/jolt_physics/Jolt/Math/EigenValueSymmetric.h +++ b/thirdparty/jolt_physics/Jolt/Math/EigenValueSymmetric.h @@ -11,7 +11,7 @@ JPH_NAMESPACE_BEGIN /// Function to determine the eigen vectors and values of a N x N real symmetric matrix /// by Jacobi transformations. This method is most suitable for N < 10. /// -/// Taken and adapted from Numerical Recipies paragraph 11.1 +/// Taken and adapted from Numerical Recipes paragraph 11.1 /// /// An eigen vector is a vector v for which \f$A \: v = \lambda \: v\f$ /// @@ -95,7 +95,7 @@ bool EigenValueSymmetric(const Matrix &inMatrix, Matrix &outEigVec, Vector &outE // On the first three sweeps use a fraction of the sum of the off diagonal elements as threshold // Note that we pick a minimum threshold of FLT_MIN because dividing by a denormalized number is likely to result in infinity. - float tresh = sweep < 4? 0.2f * avg_sm : FLT_MIN; // Original code: 0.0f instead of FLT_MIN + float thresh = sweep < 4? 0.2f * avg_sm : FLT_MIN; // Original code: 0.0f instead of FLT_MIN for (uint ip = 0; ip < n - 1; ++ip) for (uint iq = ip + 1; iq < n; ++iq) @@ -114,7 +114,7 @@ bool EigenValueSymmetric(const Matrix &inMatrix, Matrix &outEigVec, Vector &outE { a_pq = 0.0f; } - else if (abs_a_pq > tresh) + else if (abs_a_pq > thresh) { float h = eigval_q - eigval_p; float abs_h = abs(h); diff --git a/thirdparty/jolt_physics/Jolt/Math/GaussianElimination.h b/thirdparty/jolt_physics/Jolt/Math/GaussianElimination.h index f986cf3b3b0..5b4ce098ec7 100644 --- a/thirdparty/jolt_physics/Jolt/Math/GaussianElimination.h +++ b/thirdparty/jolt_physics/Jolt/Math/GaussianElimination.h @@ -14,7 +14,7 @@ JPH_NAMESPACE_BEGIN /// Set A to the matrix to invert, set B to identity and let GaussianElimination solve /// the equation, on return B will be the inverse of A. And A is destroyed. /// -/// Taken and adapted from Numerical Recipies in C paragraph 2.1 +/// Taken and adapted from Numerical Recipes in C paragraph 2.1 template bool GaussianElimination(MatrixA &ioA, MatrixB &ioB, float inTolerance = 1.0e-16f) { diff --git a/thirdparty/jolt_physics/Jolt/Math/Math.h b/thirdparty/jolt_physics/Jolt/Math/Math.h index 729d5403e39..221176eead7 100644 --- a/thirdparty/jolt_physics/Jolt/Math/Math.h +++ b/thirdparty/jolt_physics/Jolt/Math/Math.h @@ -72,7 +72,7 @@ JPH_INLINE constexpr T Sign(T inV) template constexpr bool IsPowerOf2(T inV) { - return (inV & (inV - 1)) == 0; + return inV > 0 && (inV & (inV - 1)) == 0; } /// Align inV up to the next inAlignment bytes @@ -120,8 +120,8 @@ inline uint CountTrailingZeros(uint32 inValue) return 32; return __builtin_ctz(inValue); #endif -#elif defined(JPH_CPU_E2K) - return inValue ? __builtin_ctz(inValue) : 32; +#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH) + return inValue ? __builtin_ctz(inValue) : 32; #else #error Undefined #endif @@ -150,8 +150,8 @@ inline uint CountLeadingZeros(uint32 inValue) #else return __builtin_clz(inValue); #endif -#elif defined(JPH_CPU_E2K) - return inValue ? __builtin_clz(inValue) : 32; +#elif defined(JPH_CPU_E2K) || defined(JPH_CPU_RISCV) || defined(JPH_CPU_PPC) || defined(JPH_CPU_LOONGARCH) + return inValue ? __builtin_clz(inValue) : 32; #else #error Undefined #endif diff --git a/thirdparty/jolt_physics/Jolt/Math/Vec3.inl b/thirdparty/jolt_physics/Jolt/Math/Vec3.inl index 5a47f40ce6b..dba99360d30 100644 --- a/thirdparty/jolt_physics/Jolt/Math/Vec3.inl +++ b/thirdparty/jolt_physics/Jolt/Math/Vec3.inl @@ -64,9 +64,7 @@ Vec3::Vec3(const Float3 &inV) mF32[0] = inV[0]; mF32[1] = inV[1]; mF32[2] = inV[2]; - #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED - mF32[3] = inV[2]; - #endif + mF32[3] = inV[2]; // Not strictly needed when JPH_FLOATING_POINT_EXCEPTIONS_ENABLED is off but prevents warnings about uninitialized variables #endif } @@ -82,9 +80,7 @@ Vec3::Vec3(float inX, float inY, float inZ) mF32[0] = inX; mF32[1] = inY; mF32[2] = inZ; - #ifdef JPH_FLOATING_POINT_EXCEPTIONS_ENABLED - mF32[3] = inZ; - #endif + mF32[3] = inZ; // Not strictly needed when JPH_FLOATING_POINT_EXCEPTIONS_ENABLED is off but prevents warnings about uninitialized variables #endif } diff --git a/thirdparty/jolt_physics/Jolt/Physics/Body/MotionQuality.h b/thirdparty/jolt_physics/Jolt/Physics/Body/MotionQuality.h index b1ba343c06a..6d944bda91c 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Body/MotionQuality.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Body/MotionQuality.h @@ -9,7 +9,7 @@ JPH_NAMESPACE_BEGIN /// Motion quality, or how well it detects collisions when it has a high velocity enum class EMotionQuality : uint8 { - /// Update the body in discrete steps. Body will tunnel throuh thin objects if its velocity is high enough. + /// Update the body in discrete steps. Body will tunnel through thin objects if its velocity is high enough. /// This is the cheapest way of simulating a body. Discrete, diff --git a/thirdparty/jolt_physics/Jolt/Physics/Character/Character.h b/thirdparty/jolt_physics/Jolt/Physics/Character/Character.h index db67f8b3b6b..cbf5d88dd51 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Character/Character.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Character/Character.h @@ -92,7 +92,7 @@ public: RVec3 GetPosition(bool inLockBodies = true) const; /// Set the position of the character, optionally activating it. - void SetPosition(RVec3Arg inPostion, EActivation inActivationMode = EActivation::Activate, bool inLockBodies = true); + void SetPosition(RVec3Arg inPosition, EActivation inActivationMode = EActivation::Activate, bool inLockBodies = true); /// Get the rotation of the character Quat GetRotation(bool inLockBodies = true) const; diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h index 8b6506e901d..937f9f07f08 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h @@ -75,7 +75,7 @@ public: virtual void RemoveBodies(BodyID *ioBodies, int inNumber) = 0; /// Call whenever the aabb of a body changes (can change order of ioBodies array) - /// inTakeLock should be false if we're between LockModifications/UnlockModificiations in which case care needs to be taken to not call this between UpdatePrepare/UpdateFinalize + /// inTakeLock should be false if we're between LockModifications/UnlockModifications, in which case care needs to be taken to not call this between UpdatePrepare/UpdateFinalize virtual void NotifyBodiesAABBChanged(BodyID *ioBodies, int inNumber, bool inTakeLock = true) = 0; /// Call whenever the layer (and optionally the aabb as well) of a body changes (can change order of ioBodies array) diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp index 717244c0238..3e11a90cbbc 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp @@ -350,7 +350,7 @@ void BroadPhaseQuadTree::NotifyBodiesAABBChanged(BodyID *ioBodies, int inNumber, // Find first body with different layer BodyID *b_mid = std::upper_bound(b_start, b_end, broadphase_layer, [tracking](BroadPhaseLayer::Type inLayer, BodyID inBodyID) { return inLayer < tracking[inBodyID.GetIndex()].mBroadPhaseLayer; }); - // Nodify all bodies of the same layer changed + // Notify all bodies of the same layer changed mLayers[broadphase_layer].NotifyBodiesAABBChanged(bodies, mTracking, b_start, int(b_mid - b_start)); // Repeat diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp index cfcf8ba3009..bec02560298 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp @@ -702,7 +702,7 @@ void QuadTree::WidenAndMarkNodeAndParentsChanged(uint32 inNodeIndex, const AABox bool QuadTree::TryInsertLeaf(TrackingVector &ioTracking, int inNodeIndex, NodeID inLeafID, const AABox &inLeafBounds, int inLeafNumBodies) { - // Tentively assign the node as parent + // Tentatively assign the node as parent bool leaf_is_node = inLeafID.IsNode(); if (leaf_is_node) { diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp index 166883be8da..69abfbaf311 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp @@ -104,7 +104,7 @@ float CastSphereVsTriangles::RayCylinder(Vec3Arg inRayDirection, Vec3Arg inCylin float c = axis_len_sq * (start.LengthSq() - Square(inRadius)) - Square(start_dot_axis); float det = Square(b) - a * c; // normally 4 * a * c but since both a and c need to be divided by 2 we lose the 4 if (det < 0.0f) - return FLT_MAX; // No solution to quadractic equation + return FLT_MAX; // No solution to quadratic equation // Solve fraction t where the ray hits the cylinder float t = -(b + sqrt(det)) / a; // normally divided by 2 * a but since a should be divided by 2 we lose the 2 diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h index 2c5f8f217ff..cfec81393c4 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/CollideShape.h @@ -59,7 +59,7 @@ public: Vec3 mContactPointOn1; ///< Contact point on the surface of shape 1 (in world space or relative to base offset) Vec3 mContactPointOn2; ///< Contact point on the surface of shape 2 (in world space or relative to base offset). If the penetration depth is 0, this will be the same as mContactPointOn1. Vec3 mPenetrationAxis; ///< Direction to move shape 2 out of collision along the shortest path (magnitude is meaningless, in world space). You can use -mPenetrationAxis.Normalized() as contact normal. - float mPenetrationDepth; ///< Penetration depth (move shape 2 by this distance to resolve the collision) + float mPenetrationDepth; ///< Penetration depth (move shape 2 by this distance to resolve the collision). If CollideShapeSettings::mMaxSeparationDistance > 0 this number can be negative to indicate that the objects are separated by -mPenetrationDepth. The contact points are the closest points in that case. SubShapeID mSubShapeID1; ///< Sub shape ID that identifies the face on shape 1 SubShapeID mSubShapeID2; ///< Sub shape ID that identifies the face on shape 2 BodyID mBodyID2; ///< BodyID to which shape 2 belongs to @@ -95,7 +95,8 @@ class CollideShapeSettings : public CollideSettingsBase public: JPH_OVERRIDE_NEW_DELETE - /// When > 0 contacts in the vicinity of the query shape can be found. All nearest contacts that are not further away than this distance will be found (unit: meter) + /// When > 0 contacts in the vicinity of the query shape can be found. All nearest contacts that are not further away than this distance will be found. + /// Note that in this case CollideShapeResult::mPenetrationDepth can become negative to indicate that objects are not overlapping. (unit: meter) float mMaxSeparationDistance = 0.0f; /// How backfacing triangles should be treated diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp index 1a1126e1905..5f1dc651af2 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp @@ -104,7 +104,7 @@ ConvexHullShape::ConvexHullShape(const ConvexHullShapeSettings &inSettings, Shap { Vec3 v3 = inSettings.mPoints[e->mStartIdx] - mCenterOfMass; - // Affine transform that transforms a unit tetrahedon (with vertices (0, 0, 0), (1, 0, 0), (0, 1, 0) and (0, 0, 1) to this tetrahedron + // Affine transform that transforms a unit tetrahedron (with vertices (0, 0, 0), (1, 0, 0), (0, 1, 0) and (0, 0, 1) to this tetrahedron Mat44 a(Vec4(v1, 0), Vec4(v2, 0), Vec4(v3, 0), Vec4(0, 0, 0, 1)); // Calculate covariance matrix for this tetrahedron diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/Shape.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/Shape.h index f43b79c3f0c..4d9bb5354b8 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/Shape.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/Shape.h @@ -331,7 +331,7 @@ public: /// Collect the leaf transformed shapes of all leaf shapes of this shape. /// inBox is the world space axis aligned box which leaf shapes should collide with. /// inPositionCOM/inRotation/inScale describes the transform of this shape. - /// inSubShapeIDCeator represents the current sub shape ID of this shape. + /// inSubShapeIDCreator represents the current sub shape ID of this shape. virtual void CollectTransformedShapes(const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale, const SubShapeIDCreator &inSubShapeIDCreator, TransformedShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) const; /// Transforms this shape and all of its children with inTransform, resulting shape(s) are passed to ioCollector. diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h index f33ca310e70..25e30c2b775 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h @@ -62,19 +62,4 @@ static_assert(alignof(SubShapeIDPair) == 4, "Assuming 4 byte aligned"); JPH_NAMESPACE_END -JPH_SUPPRESS_WARNINGS_STD_BEGIN - -namespace std -{ - /// Declare std::hash for SubShapeIDPair - template <> - struct hash - { - inline size_t operator () (const JPH::SubShapeIDPair &inRHS) const - { - return static_cast(inRHS.GetHash()); - } - }; -} - -JPH_SUPPRESS_WARNINGS_STD_END +JPH_MAKE_STD_HASH(JPH::SubShapeIDPair) diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp index d817644fb44..1bb9c58584d 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp @@ -313,7 +313,7 @@ MassProperties TaperedCylinderShape::GetMassProperties() const // Ixx(br,tr,b,t):=integrate(dix(x)+area(x)*x^2,x,b,t)*density(b,t); // Inertia tensor element yy: // Iyy(br,tr,b,t):=integrate(diy(x),x,b,t)*density(b,t); - // Note that we can simplfy Ixx by using: + // Note that we can simplify Ixx by using: // Ixx_delta(br,tr,b,t):=Ixx(br,tr,b,t)-Iyy(br,tr,b,t)/2; // For a cylinder this formula matches what is listed on the wiki: // factor(Ixx(r,r,-h/2,h/2)); diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TriangleShape.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TriangleShape.cpp index 5f2454bbb5b..5bfa05b9105 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TriangleShape.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/TriangleShape.cpp @@ -91,7 +91,7 @@ class TriangleShape::TriangleNoConvex final : public Support { public: TriangleNoConvex(Vec3Arg inV1, Vec3Arg inV2, Vec3Arg inV3) : - mTriangleSuport(inV1, inV2, inV3) + mTriangleSupport(inV1, inV2, inV3) { static_assert(sizeof(TriangleNoConvex) <= sizeof(SupportBuffer), "Buffer size too small"); JPH_ASSERT(IsAligned(this, alignof(TriangleNoConvex))); @@ -99,7 +99,7 @@ public: virtual Vec3 GetSupport(Vec3Arg inDirection) const override { - return mTriangleSuport.GetSupport(inDirection); + return mTriangleSupport.GetSupport(inDirection); } virtual float GetConvexRadius() const override @@ -108,7 +108,7 @@ public: } private: - TriangleConvexSupport mTriangleSuport; + TriangleConvexSupport mTriangleSupport; }; class TriangleShape::TriangleWithConvex final : public Support @@ -116,7 +116,7 @@ class TriangleShape::TriangleWithConvex final : public Support public: TriangleWithConvex(Vec3Arg inV1, Vec3Arg inV2, Vec3Arg inV3, float inConvexRadius) : mConvexRadius(inConvexRadius), - mTriangleSuport(inV1, inV2, inV3) + mTriangleSupport(inV1, inV2, inV3) { static_assert(sizeof(TriangleWithConvex) <= sizeof(SupportBuffer), "Buffer size too small"); JPH_ASSERT(IsAligned(this, alignof(TriangleWithConvex))); @@ -124,7 +124,7 @@ public: virtual Vec3 GetSupport(Vec3Arg inDirection) const override { - Vec3 support = mTriangleSuport.GetSupport(inDirection); + Vec3 support = mTriangleSupport.GetSupport(inDirection); float len = inDirection.Length(); if (len > 0.0f) support += (mConvexRadius / len) * inDirection; @@ -138,7 +138,7 @@ public: private: float mConvexRadius; - TriangleConvexSupport mTriangleSuport; + TriangleConvexSupport mTriangleSupport; }; const ConvexShape::Support *TriangleShape::GetSupportFunction(ESupportMode inMode, SupportBuffer &inBuffer, Vec3Arg inScale) const diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/TransformedShape.h b/thirdparty/jolt_physics/Jolt/Physics/Collision/TransformedShape.h index 887a8ee4411..4c410b3b6d6 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Collision/TransformedShape.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/TransformedShape.h @@ -89,7 +89,7 @@ public: inline Vec3 GetShapeScale() const { return Vec3::sLoadFloat3Unsafe(mShapeScale); } inline void SetShapeScale(Vec3Arg inScale) { inScale.StoreFloat3(&mShapeScale); } - /// Calculates the transform for this shapes's center of mass (excluding scale) + /// Calculates the transform for this shape's center of mass (excluding scale) inline RMat44 GetCenterOfMassTransform() const { return RMat44::sRotationTranslation(mShapeRotation, mShapePositionCOM); } /// Calculates the inverse of the transform for this shape's center of mass (excluding scale) diff --git a/thirdparty/jolt_physics/Jolt/Physics/Constraints/ContactConstraintManager.cpp b/thirdparty/jolt_physics/Jolt/Physics/Constraints/ContactConstraintManager.cpp index 928acdaa422..bae886ca4c9 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Constraints/ContactConstraintManager.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/Constraints/ContactConstraintManager.cpp @@ -136,7 +136,7 @@ JPH_INLINE void ContactConstraintManager::WorldContactPoint::TemplatedCalculateF float surface_velocity1 = inWorldSpaceTangent1.Dot(ws_surface_velocity); float surface_velocity2 = inWorldSpaceTangent2.Dot(ws_surface_velocity); - // Implement friction as 2 AxisContraintParts + // Implement friction as 2 AxisConstraintParts mFrictionConstraint1.TemplatedCalculateConstraintProperties(inInvM1, inInvI1, r1, inInvM2, inInvI2, r2, inWorldSpaceTangent1, surface_velocity1); mFrictionConstraint2.TemplatedCalculateConstraintProperties(inInvM1, inInvI1, r1, inInvM2, inInvI2, r2, inWorldSpaceTangent2, surface_velocity2); } diff --git a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h index eb8ecbbeaf8..0f2ed58ffe1 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h +++ b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSettings.h @@ -80,13 +80,19 @@ struct PhysicsSettings /// Number of solver position iterations to run uint mNumPositionSteps = 2; - /// Minimal velocity needed before a collision can be elastic (unit: m) + /// Minimal velocity needed before a collision can be elastic. If the relative velocity between colliding objects + /// in the direction of the contact normal is lower than this, the restitution will be zero regardless of the configured + /// value. This lets an object settle sooner. Must be a positive number. (unit: m) float mMinVelocityForRestitution = 1.0f; /// Time before object is allowed to go to sleep (unit: seconds) float mTimeBeforeSleep = 0.5f; - /// Velocity of points on bounding box of object below which an object can be considered sleeping (unit: m/s) + /// To detect if an object is sleeping, we use 3 points: + /// - The center of mass. + /// - The centers of the faces of the bounding box that are furthest away from the center. + /// The movement of these points is tracked and if the velocity of all 3 points is lower than this value, + /// the object is allowed to go to sleep. Must be a positive number. (unit: m/s) float mPointVelocitySleepThreshold = 0.03f; /// By default the simulation is deterministic, it is possible to turn this off by setting this setting to false. This will make the simulation run faster but it will no longer be deterministic. diff --git a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp index 3ea6beabfab..21569376492 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.cpp @@ -1443,7 +1443,7 @@ void PhysicsSystem::JobSolveVelocityConstraints(PhysicsUpdateContext *ioContext, } else if (check_split_islands) { - // If there are split islands, but we did't do any work, give up a time slice + // If there are split islands, but we didn't do any work, give up a time slice std::this_thread::yield(); } else @@ -2462,7 +2462,7 @@ void PhysicsSystem::JobSolvePositionConstraints(PhysicsUpdateContext *ioContext, } else if (check_split_islands) { - // If there are split islands, but we did't do any work, give up a time slice + // If there are split islands, but we didn't do any work, give up a time slice std::this_thread::yield(); } else diff --git a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.h b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.h index 5b1d1acf54c..b43d1e41232 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.h +++ b/thirdparty/jolt_physics/Jolt/Physics/PhysicsSystem.h @@ -65,7 +65,7 @@ public: /// Set the function that combines the restitution of two bodies and returns it /// Default method is max(restitution1, restitution1) - void SetCombineRestitution(ContactConstraintManager::CombineFunction inCombineRestition) { mContactManager.SetCombineRestitution(inCombineRestition); } + void SetCombineRestitution(ContactConstraintManager::CombineFunction inCombineRestitution) { mContactManager.SetCombineRestitution(inCombineRestitution); } ContactConstraintManager::CombineFunction GetCombineRestitution() const { return mContactManager.GetCombineRestitution(); } /// Set/get the shape filter that will be used during simulation. This can be used to exclude shapes within a body from colliding with each other. @@ -126,6 +126,8 @@ public: /// The world steps for a total of inDeltaTime seconds. This is divided in inCollisionSteps iterations. /// Each iteration consists of collision detection followed by an integration step. /// This function internally spawns jobs using inJobSystem and waits for them to complete, so no jobs will be running when this function returns. + /// The temp allocator is used, for example, to store the list of bodies that are in contact, how they form islands together + /// and data to solve the contacts between bodies. At the end of the Update call, all allocated memory will have been freed. EPhysicsUpdateError Update(float inDeltaTime, int inCollisionSteps, TempAllocator *inTempAllocator, JobSystem *inJobSystem); /// Saving state for replay diff --git a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp index 0aad94de88c..78eacd485a9 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp +++ b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp @@ -599,7 +599,7 @@ void SoftBodyMotionProperties::ApplyCollisionConstraintsAndUpdateVelocities(cons JPH_PROFILE_FUNCTION(); float dt = inContext.mSubStepDeltaTime; - float restitution_treshold = -2.0f * inContext.mGravity.Length() * dt; + float restitution_threshold = -2.0f * inContext.mGravity.Length() * dt; float vertex_radius = mSettings->mVertexRadius; for (Vertex &v : mVertices) if (v.mInvMass > 0.0f) @@ -674,7 +674,7 @@ void SoftBodyMotionProperties::ApplyCollisionConstraintsAndUpdateVelocities(cons // Calculate delta relative velocity due to restitution (equation 35) dv += v_normal; float prev_v_normal = (prev_v - v2).Dot(contact_normal); - if (prev_v_normal < restitution_treshold) + if (prev_v_normal < restitution_threshold) dv += cs.mRestitution * prev_v_normal * contact_normal; // Calculate impulse @@ -707,7 +707,7 @@ void SoftBodyMotionProperties::ApplyCollisionConstraintsAndUpdateVelocities(cons // Apply restitution (equation 35) v.mVelocity -= v_normal; float prev_v_normal = prev_v.Dot(contact_normal); - if (prev_v_normal < restitution_treshold) + if (prev_v_normal < restitution_threshold) v.mVelocity -= cs.mRestitution * prev_v_normal * contact_normal; } } @@ -1032,7 +1032,10 @@ void SoftBodyMotionProperties::SkinVertices([[maybe_unused]] RMat44Arg inCenterO const Mat44 *skin_matrices_end = skin_matrices + num_skin_matrices; const InvBind *inv_bind_matrix = mSettings->mInvBindMatrices.data(); for (Mat44 *s = skin_matrices; s < skin_matrices_end; ++s, ++inv_bind_matrix) + { + JPH_ASSERT(inv_bind_matrix->mJointIndex < inNumJoints); *s = inJointMatrices[inv_bind_matrix->mJointIndex] * inv_bind_matrix->mInvBind; + } // Skin the vertices JPH_IF_DEBUG_RENDERER(mSkinStateTransform = inCenterOfMassTransform;) diff --git a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h index af66b7a2e4a..8f53ced05aa 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h +++ b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h @@ -125,7 +125,7 @@ public: /// 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 - /// PhyicsSystem is that you might want to update a soft body immediately after updating an animated object + /// 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 diff --git a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h index d4b05a6ccda..4d7729bceda 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h +++ b/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h @@ -204,7 +204,7 @@ public: /// 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 tetrhedron + 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 }; diff --git a/thirdparty/jolt_physics/Jolt/Physics/Vehicle/TrackedVehicleController.h b/thirdparty/jolt_physics/Jolt/Physics/Vehicle/TrackedVehicleController.h index 8567c97073d..0bca9de5cd3 100644 --- a/thirdparty/jolt_physics/Jolt/Physics/Vehicle/TrackedVehicleController.h +++ b/thirdparty/jolt_physics/Jolt/Physics/Vehicle/TrackedVehicleController.h @@ -25,7 +25,7 @@ public: virtual void RestoreBinaryState(StreamIn &inStream) override; float mLongitudinalFriction = 4.0f; ///< Friction in forward direction of tire - float mLateralFriction = 2.0f; ///< Friction in sideway direction of tire + float mLateralFriction = 2.0f; ///< Friction in sideways direction of tire }; /// Wheel object specifically for TrackedVehicleController diff --git a/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.cpp b/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.cpp index 4bf87007e9a..27ff583f728 100644 --- a/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.cpp +++ b/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include JPH_NAMESPACE_BEGIN @@ -107,4 +109,57 @@ void SkeletalAnimation::Sample(float inTime, SkeletonPose &ioPose) const } } +void SkeletalAnimation::SaveBinaryState(StreamOut &inStream) const +{ + inStream.Write((uint32)mAnimatedJoints.size()); + for (const AnimatedJoint &j : mAnimatedJoints) + { + // Write Joint name and number of keyframes + inStream.Write(j.mJointName); + inStream.Write((uint32)j.mKeyframes.size()); + for (const Keyframe &k : j.mKeyframes) + { + inStream.Write(k.mTime); + inStream.Write(k.mRotation); + inStream.Write(k.mTranslation); + } + } + + // Save additional parameters + inStream.Write(mIsLooping); +} + +SkeletalAnimation::AnimationResult SkeletalAnimation::sRestoreFromBinaryState(StreamIn &inStream) +{ + AnimationResult result; + + Ref animation = new SkeletalAnimation; + + // Restore animated joints + uint32 len = 0; + inStream.Read(len); + animation->mAnimatedJoints.resize(len); + for (AnimatedJoint &j : animation->mAnimatedJoints) + { + // Read joint name + inStream.Read(j.mJointName); + + // Read keyframes + len = 0; + inStream.Read(len); + j.mKeyframes.resize(len); + for (Keyframe &k : j.mKeyframes) + { + inStream.Read(k.mTime); + inStream.Read(k.mRotation); + inStream.Read(k.mTranslation); + } + } + + // Read additional parameters + inStream.Read(animation->mIsLooping); + result.Set(animation); + return result; +} + JPH_NAMESPACE_END diff --git a/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.h b/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.h index 344c6046fa1..a5769f14c3c 100644 --- a/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.h +++ b/thirdparty/jolt_physics/Jolt/Skeleton/SkeletalAnimation.h @@ -5,6 +5,8 @@ #pragma once #include +#include +#include #include JPH_NAMESPACE_BEGIN @@ -62,6 +64,10 @@ public: /// Scale the size of all joints by inScale void ScaleJoints(float inScale); + /// If the animation is looping or not. If an animation is looping, the animation will continue playing after completion + void SetIsLooping(bool inIsLooping) { mIsLooping = inIsLooping; } + bool IsLooping() const { return mIsLooping; } + /// Get the (interpolated) joint transforms at time inTime void Sample(float inTime, SkeletonPose &ioPose) const; @@ -69,6 +75,14 @@ public: const AnimatedJointVector & GetAnimatedJoints() const { return mAnimatedJoints; } AnimatedJointVector & GetAnimatedJoints() { return mAnimatedJoints; } + /// Saves the state of this animation in binary form to inStream. + void SaveBinaryState(StreamOut &inStream) const; + + using AnimationResult = Result>; + + /// Restore a saved ragdoll from inStream + static AnimationResult sRestoreFromBinaryState(StreamIn &inStream); + private: AnimatedJointVector mAnimatedJoints; ///< List of joints and keyframes bool mIsLooping = true; ///< If this animation loops back to start