mirror of
https://github.com/godotengine/godot.git
synced 2025-01-22 10:32:54 -05:00
Jolt: Update to commit f094082aa, adding RISC-V, PPC64 and LoongArch support
Fixes #100557.
This commit is contained in:
parent
a7a2a12bfd
commit
4727f0707b
49 changed files with 350 additions and 166 deletions
|
@ -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):
|
||||
|
|
2
thirdparty/README.md
vendored
2
thirdparty/README.md
vendored
|
@ -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:
|
||||
|
|
|
@ -254,6 +254,15 @@ public:
|
|||
const Node *node = reinterpret_cast<const Node *>(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<const uint32 *>(&node->mBoundsMinX[0]));
|
||||
Vec4 bounds_minx = HalfFloatConversion::ToFloat(bounds_minxy);
|
||||
Vec4 bounds_miny = HalfFloatConversion::ToFloat(bounds_minxy.Swizzle<SWIZZLE_Z, SWIZZLE_W, SWIZZLE_UNUSED, SWIZZLE_UNUSED>());
|
||||
|
@ -265,6 +274,7 @@ public:
|
|||
UVec4 bounds_maxyz = UVec4::sLoadInt4(reinterpret_cast<const uint32 *>(&node->mBoundsMaxY[0]));
|
||||
Vec4 bounds_maxy = HalfFloatConversion::ToFloat(bounds_maxyz);
|
||||
Vec4 bounds_maxz = HalfFloatConversion::ToFloat(bounds_maxyz.Swizzle<SWIZZLE_Z, SWIZZLE_W, SWIZZLE_UNUSED, SWIZZLE_UNUSED>());
|
||||
#endif
|
||||
|
||||
// Load properties for 4 children
|
||||
UVec4 properties = UVec4::sLoadInt4(&node->mNodeProperties[0]);
|
||||
|
|
|
@ -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<const uint32 *>(&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<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X>();
|
||||
iv2 = iv2.Swizzle<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X>();
|
||||
iv3 = iv3.Swizzle<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X>();
|
||||
#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<const uint32 *>(&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<const uint32 *>(&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);
|
||||
|
|
|
@ -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 "
|
||||
|
|
22
thirdparty/jolt_physics/Jolt/Core/Array.h
vendored
22
thirdparty/jolt_physics/Jolt/Core/Array.h
vendored
|
@ -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<T>())
|
||||
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<A>(inValue)...);
|
||||
new (element) T(std::forward<A>(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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
41
thirdparty/jolt_physics/Jolt/Core/Core.h
vendored
41
thirdparty/jolt_physics/Jolt/Core/Core.h
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -79,7 +79,7 @@ uint32 FixedSizeFreeList<Object>::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<Parameters>(inParameters)...);
|
||||
new (&storage.mObject) Object(std::forward<Parameters>(inParameters)...);
|
||||
storage.mNextFreeObject.store(first_free, memory_order_release);
|
||||
return first_free;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ uint32 FixedSizeFreeList<Object>::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<Parameters>(inParameters)...);
|
||||
new (&storage.mObject) Object(std::forward<Parameters>(inParameters)...);
|
||||
storage.mNextFreeObject.store(first_free, memory_order_release);
|
||||
return first_free;
|
||||
}
|
||||
|
|
70
thirdparty/jolt_physics/Jolt/Core/HashCombine.h
vendored
70
thirdparty/jolt_physics/Jolt/Core/HashCombine.h
vendored
|
@ -17,8 +17,8 @@ inline uint64 HashBytes(const void *inData, uint inSize, uint64 inSeed = 0xcbf29
|
|||
uint64 hash = inSeed;
|
||||
for (const uint8 *data = reinterpret_cast<const uint8 *>(inData); data < reinterpret_cast<const uint8 *>(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 <typename T>
|
||||
inline void HashCombine(uint64 &ioSeed, const T &inValue)
|
||||
{
|
||||
ioSeed ^= Hash<T> { } (inValue) + 0x9e3779b9 + (ioSeed << 6) + (ioSeed >> 2);
|
||||
constexpr uint64 c = 0xbea225f9eb34556dUL;
|
||||
|
||||
uint64 h = ioSeed;
|
||||
uint64 x = Hash<T> { } (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<type> \
|
||||
{ \
|
||||
size_t operator()(const type &t) const \
|
||||
{ \
|
||||
return size_t(::JPH::Hash<type>{ }(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<type>, __VA_ARGS__) \
|
||||
} \
|
||||
namespace std \
|
||||
{ \
|
||||
template<> \
|
||||
struct [[nodiscard]] hash<type> \
|
||||
{ \
|
||||
std::size_t operator()(const type &t) const \
|
||||
{ \
|
||||
return std::size_t(::JPH::Hash<type>{ }(t));\
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
JPH_SUPPRESS_WARNING_POP
|
||||
JPH_SUPPRESS_WARNING_POP \
|
||||
JPH_MAKE_STD_HASH(type)
|
||||
|
||||
JPH_SUPPRESS_WARNING_POP
|
||||
JPH_NAMESPACE_END
|
||||
|
|
|
@ -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</* InsertAfterGrow= */ true>(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;
|
||||
}
|
||||
|
|
6
thirdparty/jolt_physics/Jolt/Core/Memory.h
vendored
6
thirdparty/jolt_physics/Jolt/Core/Memory.h
vendored
|
@ -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<size_t>(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<size_t>(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
|
||||
|
||||
|
|
26
thirdparty/jolt_physics/Jolt/Core/Result.h
vendored
26
thirdparty/jolt_physics/Jolt/Core/Result.h
vendored
|
@ -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
|
||||
|
|
14
thirdparty/jolt_physics/Jolt/Core/StaticArray.h
vendored
14
thirdparty/jolt_physics/Jolt/Core/StaticArray.h
vendored
|
@ -27,7 +27,7 @@ public:
|
|||
{
|
||||
JPH_ASSERT(inList.size() <= N);
|
||||
for (const T &v : inList)
|
||||
::new (reinterpret_cast<T *>(&mElements[mSize++])) T(v);
|
||||
new (reinterpret_cast<T *>(&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<A>(inElement)...);
|
||||
new (&mElements[mSize++]) T(std::forward<A>(inElement)...);
|
||||
}
|
||||
|
||||
/// Remove element from the back of the array
|
||||
|
@ -103,7 +103,7 @@ public:
|
|||
JPH_ASSERT(inNewSize <= N);
|
||||
if constexpr (!std::is_trivially_constructible<T>())
|
||||
for (T *element = reinterpret_cast<T *>(mElements) + mSize, *element_end = reinterpret_cast<T *>(mElements) + inNewSize; element < element_end; ++element)
|
||||
::new (element) T;
|
||||
new (element) T;
|
||||
if constexpr (!std::is_trivially_destructible<T>())
|
||||
for (T *element = reinterpret_cast<T *>(mElements) + inNewSize, *element_end = reinterpret_cast<T *>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Args>(inArgs)...));
|
||||
new (&this->GetElement(index)) value_type(std::piecewise_construct, std::forward_as_tuple(inKey), std::forward_as_tuple(std::forward<Args>(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<Args>(inArgs)...));
|
||||
new (&this->GetElement(index)) value_type(std::piecewise_construct, std::forward_as_tuple(std::move(inKey)), std::forward_as_tuple(std::forward<Args>(inArgs)...));
|
||||
return std::make_pair(iterator(this, index), inserted);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (;;)
|
||||
{
|
||||
|
|
|
@ -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<IndexedTriangle>;
|
|||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <class MatrixA, class MatrixB>
|
||||
bool GaussianElimination(MatrixA &ioA, MatrixB &ioB, float inTolerance = 1.0e-16f)
|
||||
{
|
||||
|
|
10
thirdparty/jolt_physics/Jolt/Math/Math.h
vendored
10
thirdparty/jolt_physics/Jolt/Math/Math.h
vendored
|
@ -72,7 +72,7 @@ JPH_INLINE constexpr T Sign(T inV)
|
|||
template <typename T>
|
||||
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
|
||||
|
|
8
thirdparty/jolt_physics/Jolt/Math/Vec3.inl
vendored
8
thirdparty/jolt_physics/Jolt/Math/Vec3.inl
vendored
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<JPH::SubShapeIDPair>
|
||||
{
|
||||
inline size_t operator () (const JPH::SubShapeIDPair &inRHS) const
|
||||
{
|
||||
return static_cast<size_t>(inRHS.GetHash());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
JPH_SUPPRESS_WARNINGS_STD_END
|
||||
JPH_MAKE_STD_HASH(JPH::SubShapeIDPair)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<Type1, Type2>(inInvM1, inInvI1, r1, inInvM2, inInvI2, r2, inWorldSpaceTangent1, surface_velocity1);
|
||||
mFrictionConstraint2.TemplatedCalculateConstraintProperties<Type1, Type2>(inInvM1, inInvI1, r1, inInvM2, inInvI2, r2, inWorldSpaceTangent2, surface_velocity2);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <Jolt/Skeleton/SkeletalAnimation.h>
|
||||
#include <Jolt/Skeleton/SkeletonPose.h>
|
||||
#include <Jolt/ObjectStream/TypeDeclarations.h>
|
||||
#include <Jolt/Core/StreamIn.h>
|
||||
#include <Jolt/Core/StreamOut.h>
|
||||
|
||||
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<SkeletalAnimation> 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
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <Jolt/Core/Reference.h>
|
||||
#include <Jolt/Core/Result.h>
|
||||
#include <Jolt/Core/StreamUtils.h>
|
||||
#include <Jolt/ObjectStream/SerializableObject.h>
|
||||
|
||||
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<Ref<SkeletalAnimation>>;
|
||||
|
||||
/// 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
|
||||
|
|
Loading…
Reference in a new issue