Преглед изворни кода

Added option to compile without ObjectStream to reduce library size (#1105)

Jorrit Rouwe пре 1 година
родитељ
комит
dc3ea78722
43 измењених фајлова са 471 додато и 233 уклоњено
  1. 21 0
      .github/workflows/build.yml
  2. 3 0
      Build/CMakeLists.txt
  3. 1 0
      Build/README.md
  4. 3 0
      Build/cmake_vs2022_cl_no_object_stream.bat
  5. 3 0
      Jolt/ConfigurationString.h
  6. 7 2
      Jolt/Core/Core.h
  7. 2 0
      Jolt/Core/Factory.cpp
  8. 6 0
      Jolt/Core/RTTI.cpp
  9. 4 0
      Jolt/Core/RTTI.h
  10. 32 21
      Jolt/Jolt.cmake
  11. 4 0
      Jolt/ObjectStream/ObjectStream.cpp
  12. 4 0
      Jolt/ObjectStream/ObjectStream.h
  13. 4 0
      Jolt/ObjectStream/ObjectStreamBinaryIn.cpp
  14. 4 0
      Jolt/ObjectStream/ObjectStreamBinaryIn.h
  15. 5 0
      Jolt/ObjectStream/ObjectStreamBinaryOut.cpp
  16. 4 0
      Jolt/ObjectStream/ObjectStreamBinaryOut.h
  17. 4 0
      Jolt/ObjectStream/ObjectStreamIn.cpp
  18. 4 0
      Jolt/ObjectStream/ObjectStreamIn.h
  19. 4 0
      Jolt/ObjectStream/ObjectStreamOut.cpp
  20. 4 0
      Jolt/ObjectStream/ObjectStreamOut.h
  21. 4 0
      Jolt/ObjectStream/ObjectStreamTextIn.cpp
  22. 4 0
      Jolt/ObjectStream/ObjectStreamTextIn.h
  23. 4 0
      Jolt/ObjectStream/ObjectStreamTextOut.cpp
  24. 4 0
      Jolt/ObjectStream/ObjectStreamTextOut.h
  25. 4 0
      Jolt/ObjectStream/SerializableAttribute.h
  26. 9 0
      Jolt/ObjectStream/SerializableAttributeEnum.h
  27. 9 0
      Jolt/ObjectStream/SerializableAttributeTyped.h
  28. 9 0
      Jolt/ObjectStream/SerializableObject.h
  29. 1 0
      Jolt/RegisterTypes.cpp
  30. 6 0
      PerformanceTest/PerformanceTest.cpp
  31. 5 0
      PerformanceTest/RagdollScene.h
  32. 22 16
      Samples/Samples.cmake
  33. 11 3
      Samples/SamplesApp.cpp
  34. 5 0
      Samples/Tests/Character/CharacterBaseTest.cpp
  35. 4 0
      Samples/Tests/General/HighSpeedTest.cpp
  36. 2 0
      Samples/Tests/General/LoadSaveSceneTest.cpp
  37. 17 6
      Samples/Tests/General/MultithreadedTest.cpp
  38. 16 6
      Samples/Tests/General/SensorTest.cpp
  39. 2 178
      Samples/Tests/Rig/CreateRigTest.cpp
  40. 4 0
      Samples/Tests/Vehicle/VehicleTest.cpp
  41. 189 0
      Samples/Utils/RagdollLoader.cpp
  42. 10 0
      Samples/Utils/RagdollLoader.h
  43. 7 1
      UnitTests/UnitTests.cmake

+ 21 - 0
.github/workflows/build.yml

@@ -189,6 +189,27 @@ jobs:
       working-directory: ${{github.workspace}}/Build/VS2022_CL/${{matrix.build_type}}
       run: ./UnitTests.exe
 
+  msvc_cl_no_object_stream:
+    runs-on: windows-latest
+    name: Visual Studio CL - No Object Stream
+    strategy:
+        fail-fast: false
+        matrix:
+            build_type: [Debug, Distribution]
+
+    steps:
+    - name: Checkout Code
+      uses: actions/checkout@v4
+    - name: Add msbuild to PATH
+      uses: microsoft/setup-msbuild@v2
+    - name: Configure CMake
+      run: cmake -B ${{github.workspace}}/Build/VS2022_CL -G "Visual Studio 17 2022" -A x64 Build -DENABLE_OBJECT_STREAM=NO
+    - name: Build
+      run: msbuild Build\VS2022_CL\JoltPhysics.sln /property:Configuration=${{matrix.build_type}} -m
+    - name: Test
+      working-directory: ${{github.workspace}}/Build/VS2022_CL/${{matrix.build_type}}
+      run: ./UnitTests.exe
+
   msvc_cl_dll:
     runs-on: windows-latest
     name: Visual Studio CL Shared Library

+ 3 - 0
Build/CMakeLists.txt

@@ -76,6 +76,9 @@ option(DISABLE_CUSTOM_ALLOCATOR "Disable support for a custom memory allocator"
 # Setting this option will force the library to use the STL vector instead of the custom Array class
 option(USE_STD_VECTOR "Use std::vector instead of own Array class" OFF)
 
+# Setting this option will compile the ObjectStream class and RTTI attribute information
+option(ENABLE_OBJECT_STREAM "Compile the ObjectStream class and RTTI attribute information" ON)
+
 include(CMakeDependentOption)
 
 # Ability to toggle between the static and DLL versions of the MSVC runtime library

+ 1 - 0
Build/README.md

@@ -31,6 +31,7 @@ There are a number of user configurable defines that turn on/off certain feature
 		<li>JPH_CROSS_PLATFORM_DETERMINISTIC - Turns on behavior to attempt cross platform determinism. If this is set, JPH_USE_FMADD is ignored.</li>
 		<li>JPH_ENABLE_ASSERTS - Compiles the library so that it rises an assert in case of failures. The library ignores these failures otherwise.</li>
 		<li>JPH_DOUBLE_PRECISION - Compiles the library so that all positions are stored in doubles instead of floats. This makes larger worlds possible.</li>
+		<li>JPH_OBJECT_STREAM - Includes the code to serialize physics data in the ObjectStream format (mostly used by the examples).</li>
 	</ul>
 </details>
 

+ 3 - 0
Build/cmake_vs2022_cl_no_object_stream.bat

@@ -0,0 +1,3 @@
+@echo off
+cmake -S . -B VS2022_CL_NO_OBJ_STR -G "Visual Studio 17 2022" -A x64 -DENABLE_OBJECT_STREAM=OFF %*
+echo Open VS2022_CL_NO_OBJ_STR\JoltPhysics.sln to build the project.

+ 3 - 0
Jolt/ConfigurationString.h

@@ -76,6 +76,9 @@ inline const char *GetConfigurationString()
 #ifdef JPH_ENABLE_ASSERTS
 		"(Assertions) "
 #endif
+#ifdef JPH_OBJECT_STREAM
+		"(ObjectStream) "
+#endif
 #ifdef JPH_DEBUG
 		"(Debug) "
 #endif

+ 7 - 2
Jolt/Core/Core.h

@@ -60,7 +60,12 @@
 #else
 	#define JPH_VERSION_FEATURE_BIT_10 0
 #endif
-#define JPH_VERSION_FEATURES (uint64(JPH_VERSION_FEATURE_BIT_1) | (JPH_VERSION_FEATURE_BIT_2 << 1) | (JPH_VERSION_FEATURE_BIT_3 << 2) | (JPH_VERSION_FEATURE_BIT_4 << 3) | (JPH_VERSION_FEATURE_BIT_5 << 4) | (JPH_VERSION_FEATURE_BIT_6 << 5) | (JPH_VERSION_FEATURE_BIT_7 << 6) | (JPH_VERSION_FEATURE_BIT_8 << 7) | (JPH_VERSION_FEATURE_BIT_9 << 8) | (JPH_VERSION_FEATURE_BIT_10 << 9))
+#ifdef JPH_OBJECT_STREAM
+	#define JPH_VERSION_FEATURE_BIT_11 1
+#else
+	#define JPH_VERSION_FEATURE_BIT_11 0
+#endif
+#define JPH_VERSION_FEATURES (uint64(JPH_VERSION_FEATURE_BIT_1) | (JPH_VERSION_FEATURE_BIT_2 << 1) | (JPH_VERSION_FEATURE_BIT_3 << 2) | (JPH_VERSION_FEATURE_BIT_4 << 3) | (JPH_VERSION_FEATURE_BIT_5 << 4) | (JPH_VERSION_FEATURE_BIT_6 << 5) | (JPH_VERSION_FEATURE_BIT_7 << 6) | (JPH_VERSION_FEATURE_BIT_8 << 7) | (JPH_VERSION_FEATURE_BIT_9 << 8) | (JPH_VERSION_FEATURE_BIT_10 << 9) | (JPH_VERSION_FEATURE_BIT_11 << 10))
 
 // Combine the version and features in a single ID
 #define JPH_VERSION_ID ((JPH_VERSION_FEATURES << 24) | (JPH_VERSION_MAJOR << 16) | (JPH_VERSION_MINOR << 8) | JPH_VERSION_PATCH)
@@ -467,7 +472,7 @@ static_assert(sizeof(void *) == (JPH_CPU_ADDRESS_BITS == 64? 8 : 4), "Invalid si
 #elif defined(JPH_COMPILER_GCC)
 	// On gcc 14 using always_inline in debug mode causes error: "inlining failed in call to 'always_inline' 'XXX': function not considered for inlining"
 	// See: https://github.com/jrouwe/JoltPhysics/issues/1096
-	#if __GNUC__ >= 14 && defined(JPH_DEBUG) 
+	#if __GNUC__ >= 14 && defined(JPH_DEBUG)
 		#define JPH_INLINE inline
 	#else
 		#define JPH_INLINE __inline__ __attribute__((always_inline))

+ 2 - 0
Jolt/Core/Factory.cpp

@@ -49,6 +49,7 @@ bool Factory::Register(const RTTI *inRTTI)
 		if (!Register(inRTTI->GetBaseClass(i)))
 			return false;
 
+#ifdef JPH_OBJECT_STREAM
 	// Register attribute classes
 	for (int i = 0; i < inRTTI->GetAttributeCount(); ++i)
 	{
@@ -56,6 +57,7 @@ bool Factory::Register(const RTTI *inRTTI)
 		if (rtti != nullptr && !Register(rtti))
 			return false;
 	}
+#endif // JPH_OBJECT_STREAM
 
 	return true;
 }

+ 6 - 0
Jolt/Core/RTTI.cpp

@@ -70,9 +70,11 @@ void RTTI::AddBaseClass(const RTTI *inRTTI, int inOffset)
 	base.mOffset = inOffset;
 	mBaseClasses.push_back(base);
 
+#ifdef JPH_OBJECT_STREAM
 	// Add attributes of base class
 	for (const SerializableAttribute &a : inRTTI->mAttributes)
 		mAttributes.push_back(SerializableAttribute(a, inOffset));
+#endif // JPH_OBJECT_STREAM
 }
 
 bool RTTI::operator == (const RTTI &inRHS) const
@@ -125,6 +127,8 @@ const void *RTTI::CastTo(const void *inObject, const RTTI *inRTTI) const
 	return nullptr;
 }
 
+#ifdef JPH_OBJECT_STREAM
+
 void RTTI::AddAttribute(const SerializableAttribute &inAttribute)
 {
 	mAttributes.push_back(inAttribute);
@@ -140,4 +144,6 @@ const SerializableAttribute &RTTI::GetAttribute(int inIdx) const
 	return mAttributes[inIdx];
 }
 
+#endif // JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_END

+ 4 - 0
Jolt/Core/RTTI.h

@@ -162,10 +162,12 @@ public:
 	/// Cast inObject of this type to object of type inRTTI, returns nullptr if the cast is unsuccessful
 	const void *				CastTo(const void *inObject, const RTTI *inRTTI) const;
 
+#ifdef JPH_OBJECT_STREAM
 	/// Attribute access
 	void						AddAttribute(const SerializableAttribute &inAttribute);
 	int							GetAttributeCount() const;
 	const SerializableAttribute & GetAttribute(int inIdx) const;
+#endif // JPH_OBJECT_STREAM
 
 protected:
 	/// Base class information
@@ -180,7 +182,9 @@ protected:
 	StaticArray<BaseClass, 4>	mBaseClasses;												///< Names of base classes
 	pCreateObjectFunction		mCreate;													///< Pointer to a function that will create a new instance of this class
 	pDestructObjectFunction		mDestruct;													///< Pointer to a function that will destruct an object of this class
+#ifdef JPH_OBJECT_STREAM
 	StaticArray<SerializableAttribute, 32> mAttributes;										///< All attributes of this class
+#endif // JPH_OBJECT_STREAM
 };
 
 //////////////////////////////////////////////////////////////////////////////////////////

+ 32 - 21
Jolt/Jolt.cmake

@@ -139,29 +139,8 @@ set(JOLT_PHYSICS_SRC_FILES
 	${JOLT_PHYSICS_ROOT}/Math/Vec8.h
 	${JOLT_PHYSICS_ROOT}/Math/Vec8.inl
 	${JOLT_PHYSICS_ROOT}/Math/Vector.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/GetPrimitiveTypeOfType.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStream.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStream.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryIn.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryIn.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryOut.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryOut.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamIn.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamIn.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamOut.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamOut.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextIn.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextIn.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextOut.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextOut.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTypes.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableAttribute.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableAttributeEnum.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableAttributeTyped.h
 	${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableObject.cpp
 	${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableObject.h
-	${JOLT_PHYSICS_ROOT}/ObjectStream/TypeDeclarations.cpp
-	${JOLT_PHYSICS_ROOT}/ObjectStream/TypeDeclarations.h
 	${JOLT_PHYSICS_ROOT}/Physics/Body/AllowedDOFs.h
 	${JOLT_PHYSICS_ROOT}/Physics/Body/Body.cpp
 	${JOLT_PHYSICS_ROOT}/Physics/Body/Body.h
@@ -450,6 +429,33 @@ set(JOLT_PHYSICS_SRC_FILES
 	${JOLT_PHYSICS_ROOT}/TriangleSplitter/TriangleSplitterMorton.h
 )
 
+if (ENABLE_OBJECT_STREAM)
+	set(JOLT_PHYSICS_SRC_FILES
+		${JOLT_PHYSICS_SRC_FILES}
+		${JOLT_PHYSICS_ROOT}/ObjectStream/GetPrimitiveTypeOfType.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStream.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStream.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryIn.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryIn.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryOut.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamBinaryOut.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamIn.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamIn.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamOut.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamOut.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextIn.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextIn.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextOut.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTextOut.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/ObjectStreamTypes.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableAttribute.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableAttributeEnum.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/SerializableAttributeTyped.h
+		${JOLT_PHYSICS_ROOT}/ObjectStream/TypeDeclarations.cpp
+		${JOLT_PHYSICS_ROOT}/ObjectStream/TypeDeclarations.h
+	)
+endif()
+
 if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
 	# Add natvis file
 	set(JOLT_PHYSICS_SRC_FILES ${JOLT_PHYSICS_SRC_FILES} ${JOLT_PHYSICS_ROOT}/Jolt.natvis)
@@ -556,6 +562,11 @@ elseif (PROFILER_IN_DEBUG_AND_RELEASE)
 	target_compile_definitions(Jolt PUBLIC "$<$<CONFIG:Debug,Release,ReleaseASAN,ReleaseUBSAN>:JPH_PROFILE_ENABLED>")
 endif()
 
+# Compile the ObjectStream class and RTTI attribute information
+if (ENABLE_OBJECT_STREAM)
+	target_compile_definitions(Jolt PUBLIC JPH_OBJECT_STREAM)
+endif()
+
 # Emit the instruction set definitions to ensure that child projects use the same settings even if they override the used instruction sets (a mismatch causes link errors)
 function(EMIT_X86_INSTRUCTION_SET_DEFINITIONS)
 	if (USE_AVX512)

+ 4 - 0
Jolt/ObjectStream/ObjectStream.cpp

@@ -6,6 +6,8 @@
 
 #include <Jolt/ObjectStream/ObjectStream.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 // Define macro to declare functions for a specific primitive type
@@ -32,3 +34,5 @@ JPH_NAMESPACE_BEGIN
 #include <Jolt/ObjectStream/ObjectStreamTypes.h>
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStream.h

@@ -10,6 +10,8 @@
 #include <Jolt/Core/NonCopyable.h>
 #include <Jolt/ObjectStream/SerializableAttribute.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 /// Base class for object stream input and output streams.
@@ -327,3 +329,5 @@ void OSWriteData(IObjectStreamOut &ioStream, const RefConst<T> &inRef)
 }
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamBinaryIn.cpp

@@ -4,6 +4,8 @@
 
 #include <Jolt/Jolt.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 #include <Jolt/ObjectStream/ObjectStreamBinaryIn.h>
 
 JPH_NAMESPACE_BEGIN
@@ -228,3 +230,5 @@ bool ObjectStreamBinaryIn::ReadPrimitiveData(DMat44 &outPrimitive)
 }
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamBinaryIn.h

@@ -6,6 +6,8 @@
 
 #include <Jolt/ObjectStream/ObjectStreamIn.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 /// Implementation of ObjectStream binary input stream.
@@ -49,3 +51,5 @@ private:
 };
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 5 - 0
Jolt/ObjectStream/ObjectStreamBinaryOut.cpp

@@ -4,6 +4,8 @@
 
 #include <Jolt/Jolt.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 #include <Jolt/ObjectStream/ObjectStreamBinaryOut.h>
 #include <Jolt/Core/StringTools.h>
 
@@ -148,3 +150,6 @@ void ObjectStreamBinaryOut::WritePrimitiveData(const DMat44 &inPrimitive)
 }
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM
+

+ 4 - 0
Jolt/ObjectStream/ObjectStreamBinaryOut.h

@@ -6,6 +6,8 @@
 
 #include <Jolt/ObjectStream/ObjectStreamOut.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 /// Implementation of ObjectStream binary output stream.
@@ -49,3 +51,5 @@ private:
 };
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamIn.cpp

@@ -4,6 +4,8 @@
 
 #include <Jolt/Jolt.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 #include <Jolt/Core/Factory.h>
 #include <Jolt/Core/UnorderedSet.h>
 #include <Jolt/ObjectStream/ObjectStreamIn.h>
@@ -615,3 +617,5 @@ bool ObjectStreamIn::SkipAttributeData(int inArrayDepth, EOSDataType inDataType,
 }
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamIn.h

@@ -13,6 +13,8 @@ JPH_SUPPRESS_WARNINGS_STD_BEGIN
 #include <fstream>
 JPH_SUPPRESS_WARNINGS_STD_END
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 /// ObjectStreamIn contains all logic for reading an object from disk. It is the base
@@ -142,3 +144,5 @@ private:
 };
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamOut.cpp

@@ -9,6 +9,8 @@
 #include <Jolt/ObjectStream/ObjectStreamBinaryOut.h>
 #include <Jolt/ObjectStream/TypeDeclarations.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 ObjectStreamOut::ObjectStreamOut(ostream &inStream) :
@@ -162,3 +164,5 @@ void ObjectStreamOut::WritePointerData(const RTTI *inRTTI, const void *inPointer
 }
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamOut.h

@@ -14,6 +14,8 @@ JPH_SUPPRESS_WARNINGS_STD_BEGIN
 #include <fstream>
 JPH_SUPPRESS_WARNINGS_STD_END
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 template <class T> using Queue = std::queue<T, std::deque<T, STLAllocator<T>>>;
@@ -98,3 +100,5 @@ private:
 };
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamTextIn.cpp

@@ -4,6 +4,8 @@
 
 #include <Jolt/Jolt.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 #include <Jolt/ObjectStream/ObjectStreamTextIn.h>
 
 JPH_NAMESPACE_BEGIN
@@ -390,3 +392,5 @@ bool ObjectStreamTextIn::ReadWord(String &outWord)
 }
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamTextIn.h

@@ -6,6 +6,8 @@
 
 #include <Jolt/ObjectStream/ObjectStreamIn.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 /// Implementation of ObjectStream text input stream.
@@ -47,3 +49,5 @@ private:
 };
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamTextOut.cpp

@@ -4,6 +4,8 @@
 
 #include <Jolt/Jolt.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 #include <Jolt/ObjectStream/ObjectStreamTextOut.h>
 #include <Jolt/Core/StringTools.h>
 
@@ -225,3 +227,5 @@ void ObjectStreamTextOut::WriteWord(const string_view &inWord)
 }
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/ObjectStreamTextOut.h

@@ -6,6 +6,8 @@
 
 #include <Jolt/ObjectStream/ObjectStreamOut.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 /// Implementation of ObjectStream text output stream.
@@ -54,3 +56,5 @@ private:
 };
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 4 - 0
Jolt/ObjectStream/SerializableAttribute.h

@@ -4,6 +4,8 @@
 
 #pragma once
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 class RTTI;
@@ -105,3 +107,5 @@ private:
 };
 
 JPH_NAMESPACE_END
+
+#endif // JPH_OBJECT_STREAM

+ 9 - 0
Jolt/ObjectStream/SerializableAttributeEnum.h

@@ -7,6 +7,8 @@
 #include <Jolt/ObjectStream/SerializableAttribute.h>
 #include <Jolt/ObjectStream/ObjectStream.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -56,3 +58,10 @@ inline void AddSerializableAttributeEnum(RTTI &inRTTI, uint inOffset, const char
 	JPH_ADD_ENUM_ATTRIBUTE_WITH_ALIAS(class_name, member_name, #member_name);
 
 JPH_NAMESPACE_END
+
+#else
+
+#define JPH_ADD_ENUM_ATTRIBUTE_WITH_ALIAS(...)
+#define JPH_ADD_ENUM_ATTRIBUTE(...)
+
+#endif // JPH_OBJECT_STREAM

+ 9 - 0
Jolt/ObjectStream/SerializableAttributeTyped.h

@@ -8,6 +8,8 @@
 #include <Jolt/ObjectStream/GetPrimitiveTypeOfType.h>
 #include <Jolt/ObjectStream/ObjectStream.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 JPH_NAMESPACE_BEGIN
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -49,3 +51,10 @@ inline void AddSerializableAttributeTyped(RTTI &inRTTI, uint inOffset, const cha
 	JPH_ADD_ATTRIBUTE_WITH_ALIAS(class_name, member_name, #member_name)
 
 JPH_NAMESPACE_END
+
+#else
+
+#define JPH_ADD_ATTRIBUTE_WITH_ALIAS(...)
+#define JPH_ADD_ATTRIBUTE(...)
+
+#endif // JPH_OBJECT_STREAM

+ 9 - 0
Jolt/ObjectStream/SerializableObject.h

@@ -12,6 +12,8 @@ JPH_NAMESPACE_BEGIN
 // Helper macros
 //////////////////////////////////////////////////////////////////////////////////////////
 
+#ifdef JPH_OBJECT_STREAM
+
 // JPH_DECLARE_SERIALIZATION_FUNCTIONS
 #define JPH_DECLARE_SERIALIZATION_FUNCTIONS(linkage, prefix, class_name)											\
 	linkage prefix bool	OSReadData(IObjectStreamIn &ioStream, class_name &inInstance);								\
@@ -63,6 +65,13 @@ JPH_NAMESPACE_BEGIN
 		ioStream.WriteName(#class_name);																			\
 	}
 
+#else
+
+#define JPH_DECLARE_SERIALIZATION_FUNCTIONS(...)
+#define JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(...)
+
+#endif // JPH_OBJECT_STREAM
+
 //////////////////////////////////////////////////////////////////////////////////////////
 // Use these macros on non-virtual objects to make them serializable
 //////////////////////////////////////////////////////////////////////////////////////////

+ 1 - 0
Jolt/RegisterTypes.cpp

@@ -93,6 +93,7 @@ void RegisterTypesInternal(uint64 inVersionID)
 		check_bit(8, "JPH_DISABLE_CUSTOM_ALLOCATOR");
 		check_bit(9, "JPH_OBJECT_LAYER_BITS");
 		check_bit(10, "JPH_ENABLE_ASSERTS");
+		check_bit(11, "JPH_OBJECT_STREAM");
 		std::abort();
 	}
 

+ 6 - 0
PerformanceTest/PerformanceTest.cpp

@@ -74,7 +74,11 @@ int main(int argc, char** argv)
 	RegisterDefaultAllocator();
 
 	// Helper function that creates the default scene
+#ifdef JPH_OBJECT_STREAM
 	auto create_ragdoll_scene = []{ return unique_ptr<PerformanceTestScene>(new RagdollScene(4, 10, 0.6f)); };
+#else
+	auto create_ragdoll_scene = []{ return unique_ptr<PerformanceTestScene>(new ConvexVsMeshScene); };
+#endif // JPH_OBJECT_STREAM
 
 	// Parse command line parameters
 	int specified_quality = -1;
@@ -100,8 +104,10 @@ int main(int argc, char** argv)
 			// Parse scene
 			if (strcmp(arg + 3, "Ragdoll") == 0)
 				scene = create_ragdoll_scene();
+#ifdef JPH_OBJECT_STREAM
 			else if (strcmp(arg + 3, "RagdollSinglePile") == 0)
 				scene = unique_ptr<PerformanceTestScene>(new RagdollScene(1, 160, 0.4f));
+#endif // JPH_OBJECT_STREAM
 			else if (strcmp(arg + 3, "ConvexVsMesh") == 0)
 				scene = unique_ptr<PerformanceTestScene>(new ConvexVsMeshScene);
 			else if (strcmp(arg + 3, "Pyramid") == 0)

+ 5 - 0
PerformanceTest/RagdollScene.h

@@ -15,6 +15,8 @@
 #include "PerformanceTestScene.h"
 #include "Layers.h"
 
+#ifdef JPH_OBJECT_STREAM
+
 // A scene that loads a part of a Horizon Zero Dawn level and drops many ragdolls on the terrain (motors enabled)
 class RagdollScene : public PerformanceTestScene
 {
@@ -138,3 +140,6 @@ private:
 	Ref<PhysicsScene>		mBackground;
 	Array<Ref<Ragdoll>>		mRagdolls;
 };
+
+#endif // JPH_OBJECT_STREAM
+

+ 22 - 16
Samples/Samples.cmake

@@ -149,24 +149,8 @@ set(SAMPLES_SRC_FILES
 	${SAMPLES_ROOT}/Tests/General/WallTest.h
 	${SAMPLES_ROOT}/Tests/General/ActivateDuringUpdateTest.cpp
 	${SAMPLES_ROOT}/Tests/General/ActivateDuringUpdateTest.h
-	${SAMPLES_ROOT}/Tests/Rig/BigWorldTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/BigWorldTest.h
 	${SAMPLES_ROOT}/Tests/Rig/CreateRigTest.cpp
 	${SAMPLES_ROOT}/Tests/Rig/CreateRigTest.h
-	${SAMPLES_ROOT}/Tests/Rig/KinematicRigTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/KinematicRigTest.h
-	${SAMPLES_ROOT}/Tests/Rig/LoadSaveBinaryRigTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/LoadSaveBinaryRigTest.h
-	${SAMPLES_ROOT}/Tests/Rig/LoadSaveRigTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/LoadSaveRigTest.h
-	${SAMPLES_ROOT}/Tests/Rig/LoadRigTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/LoadRigTest.h
-	${SAMPLES_ROOT}/Tests/Rig/PoweredRigTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/PoweredRigTest.h
-	${SAMPLES_ROOT}/Tests/Rig/RigPileTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/RigPileTest.h
-	${SAMPLES_ROOT}/Tests/Rig/SkeletonMapperTest.cpp
-	${SAMPLES_ROOT}/Tests/Rig/SkeletonMapperTest.h
 	${SAMPLES_ROOT}/Tests/SoftBody/SoftBodyBendConstraintTest.cpp
 	${SAMPLES_ROOT}/Tests/SoftBody/SoftBodyBendConstraintTest.h
 	${SAMPLES_ROOT}/Tests/SoftBody/SoftBodyContactListenerTest.cpp
@@ -282,6 +266,28 @@ set(SAMPLES_SRC_FILES
 	${SAMPLES_ROOT}/Utils/SoftBodyCreator.h
 )
 
+if (ENABLE_OBJECT_STREAM)
+	set(SAMPLES_SRC_FILES
+		${SAMPLES_SRC_FILES}
+		${SAMPLES_ROOT}/Tests/Rig/BigWorldTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/BigWorldTest.h
+		${SAMPLES_ROOT}/Tests/Rig/KinematicRigTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/KinematicRigTest.h
+		${SAMPLES_ROOT}/Tests/Rig/LoadSaveBinaryRigTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/LoadSaveBinaryRigTest.h
+		${SAMPLES_ROOT}/Tests/Rig/LoadSaveRigTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/LoadSaveRigTest.h
+		${SAMPLES_ROOT}/Tests/Rig/LoadRigTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/LoadRigTest.h
+		${SAMPLES_ROOT}/Tests/Rig/PoweredRigTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/PoweredRigTest.h
+		${SAMPLES_ROOT}/Tests/Rig/RigPileTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/RigPileTest.h
+		${SAMPLES_ROOT}/Tests/Rig/SkeletonMapperTest.cpp
+		${SAMPLES_ROOT}/Tests/Rig/SkeletonMapperTest.h
+	)
+endif()
+
 # Group source files
 source_group(TREE ${SAMPLES_ROOT} FILES ${SAMPLES_SRC_FILES})
 

+ 11 - 3
Samples/SamplesApp.cpp

@@ -90,7 +90,6 @@ JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, ChangeMotionQualityTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, ChangeMotionTypeTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, ChangeShapeTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, ChangeObjectLayerTest)
-JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, LoadSaveSceneTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, LoadSaveBinaryTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, BigVsSmallTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, ActiveEdgesTest)
@@ -105,6 +104,9 @@ JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, TwoDFunnelTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, AllowedDOFsTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, ShapeFilterTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, GyroscopicForceTest)
+#ifdef JPH_OBJECT_STREAM
+JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, LoadSaveSceneTest)
+#endif // JPH_OBJECT_STREAM
 
 static TestNameAndRTTI sGeneralTests[] =
 {
@@ -131,7 +133,9 @@ static TestNameAndRTTI sGeneralTests[] =
 	{ "Change Motion Type",					JPH_RTTI(ChangeMotionTypeTest) },
 	{ "Change Shape",						JPH_RTTI(ChangeShapeTest) },
 	{ "Change Object Layer",				JPH_RTTI(ChangeObjectLayerTest) },
+#ifdef JPH_OBJECT_STREAM
 	{ "Load/Save Scene",					JPH_RTTI(LoadSaveSceneTest) },
+#endif // JPH_OBJECT_STREAM
 	{ "Load/Save Binary",					JPH_RTTI(LoadSaveBinaryTest) },
 	{ "Big vs Small",						JPH_RTTI(BigVsSmallTest) },
 	{ "Active Edges",						JPH_RTTI(ActiveEdgesTest) },
@@ -255,6 +259,7 @@ static TestNameAndRTTI sScaledShapeTests[] =
 };
 
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, CreateRigTest)
+#ifdef JPH_OBJECT_STREAM
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, LoadRigTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, KinematicRigTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, PoweredRigTest)
@@ -263,10 +268,12 @@ JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, LoadSaveRigTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, LoadSaveBinaryRigTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, SkeletonMapperTest)
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, BigWorldTest)
+#endif // JPH_OBJECT_STREAM
 
 static TestNameAndRTTI sRigTests[] =
 {
 	{ "Create Rig",							JPH_RTTI(CreateRigTest) },
+#ifdef JPH_OBJECT_STREAM
 	{ "Load Rig",							JPH_RTTI(LoadRigTest) },
 	{ "Load / Save Rig",					JPH_RTTI(LoadSaveRigTest) },
 	{ "Load / Save Binary Rig",				JPH_RTTI(LoadSaveBinaryRigTest) },
@@ -275,6 +282,7 @@ static TestNameAndRTTI sRigTests[] =
 	{ "Skeleton Mapper",					JPH_RTTI(SkeletonMapperTest) },
 	{ "Rig Pile",							JPH_RTTI(RigPileTest) },
 	{ "Big World",							JPH_RTTI(BigWorldTest) }
+#endif // JPH_OBJECT_STREAM
 };
 
 JPH_DECLARE_RTTI_FOR_FACTORY(JPH_NO_EXPORT, CharacterTest)
@@ -606,7 +614,7 @@ SamplesApp::SamplesApp()
 		else
 		{
 			// Search for the test
-			const RTTI *test = JPH_RTTI(LoadRigTest);
+			const RTTI *test = JPH_RTTI(CreateRigTest);
 			for (TestCategory &c : sAllCategories)
 				for (uint i = 0; i < c.mNumTests; ++i)
 				{
@@ -626,7 +634,7 @@ SamplesApp::SamplesApp()
 	else
 	{
 		// Otherwise start default test
-		StartTest(JPH_RTTI(LoadRigTest));
+		StartTest(JPH_RTTI(CreateRigTest));
 	}
 }
 

+ 5 - 0
Samples/Tests/Character/CharacterBaseTest.cpp

@@ -31,8 +31,10 @@ const char *CharacterBaseTest::sScenes[] =
 	"PerlinHeightField",
 	"ObstacleCourse",
 	"InitiallyIntersecting",
+#ifdef JPH_OBJECT_STREAM
 	"Terrain1",
 	"Terrain2",
+#endif // JPH_OBJECT_STREAM
 };
 
 const char *CharacterBaseTest::sSceneName = "ObstacleCourse";
@@ -494,6 +496,7 @@ void CharacterBaseTest::Initialize()
 			mSensorBody = mBodyInterface->CreateAndAddBody(sensor, EActivation::Activate);
 		}
 	}
+#ifdef JPH_OBJECT_STREAM
 	else
 	{
 		// Load scene
@@ -508,6 +511,8 @@ void CharacterBaseTest::Initialize()
 		}
 		scene->CreateBodies(mPhysicsSystem);
 	}
+#endif // JPH_OBJECT_STREAM
+
 
 	// Create capsule shapes for all stances
 	switch (sShapeType)

+ 4 - 0
Samples/Tests/General/HighSpeedTest.cpp

@@ -328,6 +328,7 @@ void HighSpeedTest::CreateConvexOnLargeTriangles()
 
 void HighSpeedTest::CreateConvexOnTerrain1()
 {
+#ifdef JPH_OBJECT_STREAM
 	// Load scene
 	Ref<PhysicsScene> scene;
 	if (!ObjectStreamIn::sReadObject("Assets/terrain1.bof", scene))
@@ -336,6 +337,9 @@ void HighSpeedTest::CreateConvexOnTerrain1()
 		body.mObjectLayer = Layers::NON_MOVING;
 	scene->FixInvalidScales();
 	scene->CreateBodies(mPhysicsSystem);
+#else
+	CreateFloor();
+#endif // JPH_OBJECT_STREAM
 
 	CreateFastSmallConvexObjects();
 }

+ 2 - 0
Samples/Tests/General/LoadSaveSceneTest.cpp

@@ -200,6 +200,7 @@ Ref<PhysicsScene> LoadSaveSceneTest::sCreateScene()
 
 void LoadSaveSceneTest::Initialize()
 {
+#ifdef JPH_OBJECT_STREAM
 	Ref<PhysicsScene> scene = sCreateScene();
 
 	stringstream data;
@@ -221,4 +222,5 @@ void LoadSaveSceneTest::Initialize()
 
 	// Instantiate scene
 	scene->CreateBodies(mPhysicsSystem);
+#endif // JPH_OBJECT_STREAM
 }

+ 17 - 6
Samples/Tests/General/MultithreadedTest.cpp

@@ -135,20 +135,31 @@ void MultithreadedTest::RagdollSpawner()
 	const int cMaxRagdolls = 50;
 #endif
 
+#ifdef JPH_OBJECT_STREAM
 	// Load ragdoll
 	Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
 	if (ragdoll_settings == nullptr)
 		FatalError("Could not load ragdoll");
-
-	// Load animation
-	Ref<SkeletalAnimation> animation;
-	if (!ObjectStreamIn::sReadObject("Assets/Human/Dead_Pose1.tof", animation))
-		FatalError("Could not open animation");
+#else
+	// Create a ragdoll from code
+	Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sCreate();
+#endif // JPH_OBJECT_STREAM
 
 	// Create pose
 	SkeletonPose ragdoll_pose;
 	ragdoll_pose.SetSkeleton(ragdoll_settings->GetSkeleton());
-	animation->Sample(0.0f, ragdoll_pose);
+	{
+#ifdef JPH_OBJECT_STREAM
+		Ref<SkeletalAnimation> animation;
+		if (!ObjectStreamIn::sReadObject("Assets/Human/Dead_Pose1.tof", animation))
+			FatalError("Could not open animation");
+		animation->Sample(0.0f, ragdoll_pose);
+#else
+		Ref<Ragdoll> temp_ragdoll = ragdoll_settings->CreateRagdoll(0, 0, mPhysicsSystem);
+		temp_ragdoll->GetPose(ragdoll_pose);
+		ragdoll_pose.CalculateJointStates();
+#endif // JPH_OBJECT_STREAM
+	}
 
 	default_random_engine random;
 	uniform_real_distribution<float> from_y(0, 10);

+ 16 - 6
Samples/Tests/General/SensorTest.cpp

@@ -69,20 +69,30 @@ void SensorTest::Initialize()
 	for (const RVec3 &p : static_positions)
 		mBodyInterface->CreateAndAddBody(BodyCreationSettings(new BoxShape(Vec3::sReplicate(0.5f)), p, Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING), EActivation::Activate);
 
+#ifdef JPH_OBJECT_STREAM
 	// Load ragdoll
 	Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
 	if (ragdoll_settings == nullptr)
 		FatalError("Could not load ragdoll");
-
-	// Load animation
-	Ref<SkeletalAnimation> animation;
-	if (!ObjectStreamIn::sReadObject("Assets/Human/Dead_Pose1.tof", animation))
-		FatalError("Could not open animation");
+#else
+	Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sCreate();
+#endif // JPH_OBJECT_STREAM
 
 	// Create pose
 	SkeletonPose ragdoll_pose;
 	ragdoll_pose.SetSkeleton(ragdoll_settings->GetSkeleton());
-	animation->Sample(0.0f, ragdoll_pose);
+	{
+#ifdef JPH_OBJECT_STREAM
+		Ref<SkeletalAnimation> animation;
+		if (!ObjectStreamIn::sReadObject("Assets/Human/Dead_Pose1.tof", animation))
+			FatalError("Could not open animation");
+		animation->Sample(0.0f, ragdoll_pose);
+#else
+		Ref<Ragdoll> temp_ragdoll = ragdoll_settings->CreateRagdoll(0, 0, mPhysicsSystem);
+		temp_ragdoll->GetPose(ragdoll_pose);
+		ragdoll_pose.CalculateJointStates();
+#endif // JPH_OBJECT_STREAM
+	}
 	ragdoll_pose.SetRootOffset(RVec3(0, 30, 0));
 	ragdoll_pose.CalculateJointMatrices();
 

+ 2 - 178
Samples/Tests/Rig/CreateRigTest.cpp

@@ -5,9 +5,8 @@
 #include <TestFramework.h>
 
 #include <Tests/Rig/CreateRigTest.h>
-#include <Jolt/Physics/Collision/Shape/CapsuleShape.h>
-#include <Jolt/Physics/Constraints/SwingTwistConstraint.h>
 #include <Application/DebugUI.h>
+#include <Utils/RagdollLoader.h>
 #include <Layers.h>
 
 JPH_IMPLEMENT_RTTI_VIRTUAL(CreateRigTest)
@@ -25,183 +24,8 @@ void CreateRigTest::Initialize()
 	// Floor
 	CreateFloor();
 
-	// Create skeleton
-	Ref<Skeleton> skeleton = new Skeleton;
-	uint lower_body = skeleton->AddJoint("LowerBody");
-	uint mid_body = skeleton->AddJoint("MidBody", lower_body);
-	uint upper_body = skeleton->AddJoint("UpperBody", mid_body);
-	/*uint head =*/ skeleton->AddJoint("Head", upper_body);
-	uint upper_arm_l = skeleton->AddJoint("UpperArmL", upper_body);
-	uint upper_arm_r = skeleton->AddJoint("UpperArmR", upper_body);
-	/*uint lower_arm_l =*/ skeleton->AddJoint("LowerArmL", upper_arm_l);
-	/*uint lower_arm_r =*/ skeleton->AddJoint("LowerArmR", upper_arm_r);
-	uint upper_leg_l = skeleton->AddJoint("UpperLegL", lower_body);
-	uint upper_leg_r = skeleton->AddJoint("UpperLegR", lower_body);
-	/*uint lower_leg_l =*/ skeleton->AddJoint("LowerLegL", upper_leg_l);
-	/*uint lower_leg_r =*/ skeleton->AddJoint("LowerLegR", upper_leg_r);
-
-	// Create shapes for limbs
-	Ref<Shape> shapes[] = {
-		new CapsuleShape(0.15f, 0.10f),		// Lower Body
-		new CapsuleShape(0.15f, 0.10f),		// Mid Body
-		new CapsuleShape(0.15f, 0.10f),		// Upper Body
-		new CapsuleShape(0.075f, 0.10f),	// Head
-		new CapsuleShape(0.15f, 0.06f),		// Upper Arm L
-		new CapsuleShape(0.15f, 0.06f),		// Upper Arm R
-		new CapsuleShape(0.15f, 0.05f),		// Lower Arm L
-		new CapsuleShape(0.15f, 0.05f),		// Lower Arm R
-		new CapsuleShape(0.2f, 0.075f),		// Upper Leg L
-		new CapsuleShape(0.2f, 0.075f),		// Upper Leg R
-		new CapsuleShape(0.2f, 0.06f),		// Lower Leg L
-		new CapsuleShape(0.2f, 0.06f),		// Lower Leg R
-	};
-
-	// Positions of body parts in world space
-	RVec3 positions[] = {
-		RVec3(0, 1.15f, 0),					// Lower Body
-		RVec3(0, 1.35f, 0),					// Mid Body
-		RVec3(0, 1.55f, 0),					// Upper Body
-		RVec3(0, 1.825f, 0),				// Head
-		RVec3(-0.425f, 1.55f, 0),			// Upper Arm L
-		RVec3(0.425f, 1.55f, 0),			// Upper Arm R
-		RVec3(-0.8f, 1.55f, 0),				// Lower Arm L
-		RVec3(0.8f, 1.55f, 0),				// Lower Arm R
-		RVec3(-0.15f, 0.8f, 0),				// Upper Leg L
-		RVec3(0.15f, 0.8f, 0),				// Upper Leg R
-		RVec3(-0.15f, 0.3f, 0),				// Lower Leg L
-		RVec3(0.15f, 0.3f, 0),				// Lower Leg R
-	};
-
-	// Rotations of body parts in world space
-	Quat rotations[] = {
-		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Lower Body
-		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Mid Body
-		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Upper Body
-		Quat::sIdentity(),									 // Head
-		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Upper Arm L
-		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Upper Arm R
-		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Lower Arm L
-		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Lower Arm R
-		Quat::sIdentity(),									 // Upper Leg L
-		Quat::sIdentity(),									 // Upper Leg R
-		Quat::sIdentity(),									 // Lower Leg L
-		Quat::sIdentity()									 // Lower Leg R
-	};
-
-	// World space constraint positions
-	RVec3 constraint_positions[] = {
-		RVec3::sZero(),				// Lower Body (unused, there's no parent)
-		RVec3(0, 1.25f, 0),			// Mid Body
-		RVec3(0, 1.45f, 0),			// Upper Body
-		RVec3(0, 1.65f, 0),			// Head
-		RVec3(-0.225f, 1.55f, 0),	// Upper Arm L
-		RVec3(0.225f, 1.55f, 0),	// Upper Arm R
-		RVec3(-0.65f, 1.55f, 0),	// Lower Arm L
-		RVec3(0.65f, 1.55f, 0),		// Lower Arm R
-		RVec3(-0.15f, 1.05f, 0),	// Upper Leg L
-		RVec3(0.15f, 1.05f, 0),		// Upper Leg R
-		RVec3(-0.15f, 0.55f, 0),	// Lower Leg L
-		RVec3(0.15f, 0.55f, 0),		// Lower Leg R
-	};
-
-	// World space twist axis directions
-	Vec3 twist_axis[] = {
-		Vec3::sZero(),				// Lower Body (unused, there's no parent)
-		Vec3::sAxisY(),				// Mid Body
-		Vec3::sAxisY(),				// Upper Body
-		Vec3::sAxisY(),				// Head
-		-Vec3::sAxisX(),			// Upper Arm L
-		Vec3::sAxisX(),				// Upper Arm R
-		-Vec3::sAxisX(),			// Lower Arm L
-		Vec3::sAxisX(),				// Lower Arm R
-		-Vec3::sAxisY(),			// Upper Leg L
-		-Vec3::sAxisY(),			// Upper Leg R
-		-Vec3::sAxisY(),			// Lower Leg L
-		-Vec3::sAxisY(),			// Lower Leg R
-	};
-
-	// Constraint limits
-	float twist_angle[] = {
-		0.0f,		// Lower Body (unused, there's no parent)
-		5.0f,		// Mid Body
-		5.0f,		// Upper Body
-		90.0f,		// Head
-		45.0f,		// Upper Arm L
-		45.0f,		// Upper Arm R
-		45.0f,		// Lower Arm L
-		45.0f,		// Lower Arm R
-		45.0f,		// Upper Leg L
-		45.0f,		// Upper Leg R
-		45.0f,		// Lower Leg L
-		45.0f,		// Lower Leg R
-	};
-
-	float normal_angle[] = {
-		0.0f,		// Lower Body (unused, there's no parent)
-		10.0f,		// Mid Body
-		10.0f,		// Upper Body
-		45.0f,		// Head
-		90.0f,		// Upper Arm L
-		90.0f,		// Upper Arm R
-		0.0f,		// Lower Arm L
-		0.0f,		// Lower Arm R
-		45.0f,		// Upper Leg L
-		45.0f,		// Upper Leg R
-		0.0f,		// Lower Leg L
-		0.0f,		// Lower Leg R
-	};
-
-	float plane_angle[] = {
-		0.0f,		// Lower Body (unused, there's no parent)
-		10.0f,		// Mid Body
-		10.0f,		// Upper Body
-		45.0f,		// Head
-		45.0f,		// Upper Arm L
-		45.0f,		// Upper Arm R
-		90.0f,		// Lower Arm L
-		90.0f,		// Lower Arm R
-		45.0f,		// Upper Leg L
-		45.0f,		// Upper Leg R
-		60.0f,		// Lower Leg L (cheating here, a knee is not symmetric, we should have rotated the twist axis)
-		60.0f,		// Lower Leg R
-	};
-
-	// Create ragdoll settings
-	Ref<RagdollSettings> settings = new RagdollSettings;
-	settings->mSkeleton = skeleton;
-	settings->mParts.resize(skeleton->GetJointCount());
-	for (int p = 0; p < skeleton->GetJointCount(); ++p)
-	{
-		RagdollSettings::Part &part = settings->mParts[p];
-		part.SetShape(shapes[p]);
-		part.mPosition = positions[p];
-		part.mRotation = rotations[p];
-		part.mMotionType = EMotionType::Dynamic;
-		part.mObjectLayer = Layers::MOVING;
-
-		// First part is the root, doesn't have a parent and doesn't have a constraint
-		if (p > 0)
-		{
-			SwingTwistConstraintSettings *constraint = new SwingTwistConstraintSettings;
-			constraint->mDrawConstraintSize = 0.1f;
-			constraint->mPosition1 = constraint->mPosition2 = constraint_positions[p];
-			constraint->mTwistAxis1 = constraint->mTwistAxis2 = twist_axis[p];
-			constraint->mPlaneAxis1 = constraint->mPlaneAxis2 = Vec3::sAxisZ();
-			constraint->mTwistMinAngle = -DegreesToRadians(twist_angle[p]);
-			constraint->mTwistMaxAngle = DegreesToRadians(twist_angle[p]);
-			constraint->mNormalHalfConeAngle = DegreesToRadians(normal_angle[p]);
-			constraint->mPlaneHalfConeAngle = DegreesToRadians(plane_angle[p]);
-			part.mToParent = constraint;
-		}
-	}
-
-	// Optional: Stabilize the inertia of the limbs
-	settings->Stabilize();
-
-	// Disable parent child collisions so that we don't get collisions between constrained bodies
-	settings->DisableParentChildCollisions();
-
 	// Create ragdoll
+	Ref<RagdollSettings> settings = RagdollLoader::sCreate();
 	mRagdoll = settings->CreateRagdoll(0, 0, mPhysicsSystem);
 	mRagdoll->AddToPhysicsSystem(EActivation::Activate);
 }

+ 4 - 0
Samples/Tests/Vehicle/VehicleTest.cpp

@@ -30,7 +30,9 @@ const char *VehicleTest::sScenes[] =
 	"Step",
 	"Dynamic Step",
 	"Playground",
+#ifdef JPH_OBJECT_STREAM
 	"Terrain1",
+#endif // JPH_OBJECT_STREAM
 };
 
 const char *VehicleTest::sSceneName = "Playground";
@@ -111,6 +113,7 @@ void VehicleTest::Initialize()
 
 		CreateRubble();
 	}
+#ifdef JPH_OBJECT_STREAM
 	else
 	{
 		// Load scene
@@ -122,6 +125,7 @@ void VehicleTest::Initialize()
 		scene->FixInvalidScales();
 		scene->CreateBodies(mPhysicsSystem);
 	}
+#endif // JPH_OBJECT_STREAM
 }
 
 void VehicleTest::CreateBridge()

+ 189 - 0
Samples/Utils/RagdollLoader.cpp

@@ -12,11 +12,14 @@
 #include <Jolt/Physics/Constraints/SliderConstraint.h>
 #include <Jolt/Physics/Constraints/ConeConstraint.h>
 #include <Jolt/Physics/Constraints/SwingTwistConstraint.h>
+#include <Jolt/Physics/Collision/Shape/CapsuleShape.h>
 #include <Jolt/ObjectStream/ObjectStreamIn.h>
 #include <Jolt/ObjectStream/ObjectStreamOut.h>
 #include <Layers.h>
 #include <Utils/Log.h>
 
+#ifdef JPH_OBJECT_STREAM
+
 RagdollSettings *RagdollLoader::sLoad(const char *inFileName, EMotionType inMotionType, EConstraintOverride inConstraintOverride)
 {
 	// Read the ragdoll
@@ -111,3 +114,189 @@ RagdollSettings *RagdollLoader::sLoad(const char *inFileName, EMotionType inMoti
 
 	return ragdoll;
 }
+
+#endif // JPH_OBJECT_STREAM
+
+RagdollSettings *RagdollLoader::sCreate()
+{
+	// Create skeleton
+	Ref<Skeleton> skeleton = new Skeleton;
+	uint lower_body = skeleton->AddJoint("LowerBody");
+	uint mid_body = skeleton->AddJoint("MidBody", lower_body);
+	uint upper_body = skeleton->AddJoint("UpperBody", mid_body);
+	/*uint head =*/ skeleton->AddJoint("Head", upper_body);
+	uint upper_arm_l = skeleton->AddJoint("UpperArmL", upper_body);
+	uint upper_arm_r = skeleton->AddJoint("UpperArmR", upper_body);
+	/*uint lower_arm_l =*/ skeleton->AddJoint("LowerArmL", upper_arm_l);
+	/*uint lower_arm_r =*/ skeleton->AddJoint("LowerArmR", upper_arm_r);
+	uint upper_leg_l = skeleton->AddJoint("UpperLegL", lower_body);
+	uint upper_leg_r = skeleton->AddJoint("UpperLegR", lower_body);
+	/*uint lower_leg_l =*/ skeleton->AddJoint("LowerLegL", upper_leg_l);
+	/*uint lower_leg_r =*/ skeleton->AddJoint("LowerLegR", upper_leg_r);
+
+	// Create shapes for limbs
+	Ref<Shape> shapes[] = {
+		new CapsuleShape(0.15f, 0.10f),		// Lower Body
+		new CapsuleShape(0.15f, 0.10f),		// Mid Body
+		new CapsuleShape(0.15f, 0.10f),		// Upper Body
+		new CapsuleShape(0.075f, 0.10f),	// Head
+		new CapsuleShape(0.15f, 0.06f),		// Upper Arm L
+		new CapsuleShape(0.15f, 0.06f),		// Upper Arm R
+		new CapsuleShape(0.15f, 0.05f),		// Lower Arm L
+		new CapsuleShape(0.15f, 0.05f),		// Lower Arm R
+		new CapsuleShape(0.2f, 0.075f),		// Upper Leg L
+		new CapsuleShape(0.2f, 0.075f),		// Upper Leg R
+		new CapsuleShape(0.2f, 0.06f),		// Lower Leg L
+		new CapsuleShape(0.2f, 0.06f),		// Lower Leg R
+	};
+
+	// Positions of body parts in world space
+	RVec3 positions[] = {
+		RVec3(0, 1.15f, 0),					// Lower Body
+		RVec3(0, 1.35f, 0),					// Mid Body
+		RVec3(0, 1.55f, 0),					// Upper Body
+		RVec3(0, 1.825f, 0),				// Head
+		RVec3(-0.425f, 1.55f, 0),			// Upper Arm L
+		RVec3(0.425f, 1.55f, 0),			// Upper Arm R
+		RVec3(-0.8f, 1.55f, 0),				// Lower Arm L
+		RVec3(0.8f, 1.55f, 0),				// Lower Arm R
+		RVec3(-0.15f, 0.8f, 0),				// Upper Leg L
+		RVec3(0.15f, 0.8f, 0),				// Upper Leg R
+		RVec3(-0.15f, 0.3f, 0),				// Lower Leg L
+		RVec3(0.15f, 0.3f, 0),				// Lower Leg R
+	};
+
+	// Rotations of body parts in world space
+	Quat rotations[] = {
+		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Lower Body
+		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Mid Body
+		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Upper Body
+		Quat::sIdentity(),									 // Head
+		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Upper Arm L
+		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Upper Arm R
+		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Lower Arm L
+		Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI),		 // Lower Arm R
+		Quat::sIdentity(),									 // Upper Leg L
+		Quat::sIdentity(),									 // Upper Leg R
+		Quat::sIdentity(),									 // Lower Leg L
+		Quat::sIdentity()									 // Lower Leg R
+	};
+
+	// World space constraint positions
+	RVec3 constraint_positions[] = {
+		RVec3::sZero(),				// Lower Body (unused, there's no parent)
+		RVec3(0, 1.25f, 0),			// Mid Body
+		RVec3(0, 1.45f, 0),			// Upper Body
+		RVec3(0, 1.65f, 0),			// Head
+		RVec3(-0.225f, 1.55f, 0),	// Upper Arm L
+		RVec3(0.225f, 1.55f, 0),	// Upper Arm R
+		RVec3(-0.65f, 1.55f, 0),	// Lower Arm L
+		RVec3(0.65f, 1.55f, 0),		// Lower Arm R
+		RVec3(-0.15f, 1.05f, 0),	// Upper Leg L
+		RVec3(0.15f, 1.05f, 0),		// Upper Leg R
+		RVec3(-0.15f, 0.55f, 0),	// Lower Leg L
+		RVec3(0.15f, 0.55f, 0),		// Lower Leg R
+	};
+
+	// World space twist axis directions
+	Vec3 twist_axis[] = {
+		Vec3::sZero(),				// Lower Body (unused, there's no parent)
+		Vec3::sAxisY(),				// Mid Body
+		Vec3::sAxisY(),				// Upper Body
+		Vec3::sAxisY(),				// Head
+		-Vec3::sAxisX(),			// Upper Arm L
+		Vec3::sAxisX(),				// Upper Arm R
+		-Vec3::sAxisX(),			// Lower Arm L
+		Vec3::sAxisX(),				// Lower Arm R
+		-Vec3::sAxisY(),			// Upper Leg L
+		-Vec3::sAxisY(),			// Upper Leg R
+		-Vec3::sAxisY(),			// Lower Leg L
+		-Vec3::sAxisY(),			// Lower Leg R
+	};
+
+	// Constraint limits
+	float twist_angle[] = {
+		0.0f,		// Lower Body (unused, there's no parent)
+		5.0f,		// Mid Body
+		5.0f,		// Upper Body
+		90.0f,		// Head
+		45.0f,		// Upper Arm L
+		45.0f,		// Upper Arm R
+		45.0f,		// Lower Arm L
+		45.0f,		// Lower Arm R
+		45.0f,		// Upper Leg L
+		45.0f,		// Upper Leg R
+		45.0f,		// Lower Leg L
+		45.0f,		// Lower Leg R
+	};
+
+	float normal_angle[] = {
+		0.0f,		// Lower Body (unused, there's no parent)
+		10.0f,		// Mid Body
+		10.0f,		// Upper Body
+		45.0f,		// Head
+		90.0f,		// Upper Arm L
+		90.0f,		// Upper Arm R
+		0.0f,		// Lower Arm L
+		0.0f,		// Lower Arm R
+		45.0f,		// Upper Leg L
+		45.0f,		// Upper Leg R
+		0.0f,		// Lower Leg L
+		0.0f,		// Lower Leg R
+	};
+
+	float plane_angle[] = {
+		0.0f,		// Lower Body (unused, there's no parent)
+		10.0f,		// Mid Body
+		10.0f,		// Upper Body
+		45.0f,		// Head
+		45.0f,		// Upper Arm L
+		45.0f,		// Upper Arm R
+		90.0f,		// Lower Arm L
+		90.0f,		// Lower Arm R
+		45.0f,		// Upper Leg L
+		45.0f,		// Upper Leg R
+		60.0f,		// Lower Leg L (cheating here, a knee is not symmetric, we should have rotated the twist axis)
+		60.0f,		// Lower Leg R
+	};
+
+	// Create ragdoll settings
+	RagdollSettings *settings = new RagdollSettings;
+	settings->mSkeleton = skeleton;
+	settings->mParts.resize(skeleton->GetJointCount());
+	for (int p = 0; p < skeleton->GetJointCount(); ++p)
+	{
+		RagdollSettings::Part &part = settings->mParts[p];
+		part.SetShape(shapes[p]);
+		part.mPosition = positions[p];
+		part.mRotation = rotations[p];
+		part.mMotionType = EMotionType::Dynamic;
+		part.mObjectLayer = Layers::MOVING;
+
+		// First part is the root, doesn't have a parent and doesn't have a constraint
+		if (p > 0)
+		{
+			SwingTwistConstraintSettings *constraint = new SwingTwistConstraintSettings;
+			constraint->mDrawConstraintSize = 0.1f;
+			constraint->mPosition1 = constraint->mPosition2 = constraint_positions[p];
+			constraint->mTwistAxis1 = constraint->mTwistAxis2 = twist_axis[p];
+			constraint->mPlaneAxis1 = constraint->mPlaneAxis2 = Vec3::sAxisZ();
+			constraint->mTwistMinAngle = -DegreesToRadians(twist_angle[p]);
+			constraint->mTwistMaxAngle = DegreesToRadians(twist_angle[p]);
+			constraint->mNormalHalfConeAngle = DegreesToRadians(normal_angle[p]);
+			constraint->mPlaneHalfConeAngle = DegreesToRadians(plane_angle[p]);
+			part.mToParent = constraint;
+		}
+	}
+
+	// Optional: Stabilize the inertia of the limbs
+	settings->Stabilize();
+
+	// Disable parent child collisions so that we don't get collisions between constrained bodies
+	settings->DisableParentChildCollisions();
+
+	// Calculate the map needed for GetBodyIndexToConstraintIndex()
+	settings->CalculateBodyIndexToConstraintIndex();
+
+	return settings;
+}

+ 10 - 0
Samples/Utils/RagdollLoader.h

@@ -9,6 +9,8 @@ namespace JPH {
 	enum class EMotionType : uint8;
 }
 
+#ifdef JPH_OBJECT_STREAM
+
 enum class EConstraintOverride
 {
 	TypeFixed,
@@ -19,8 +21,16 @@ enum class EConstraintOverride
 	TypeRagdoll,
 };
 
+#endif // JPH_OBJECT_STREAM
+
 class RagdollLoader
 {
 public:
+#ifdef JPH_OBJECT_STREAM
+	/// Load a ragdoll from an ObjectStream file
 	static RagdollSettings *		sLoad(const char *inFileName, EMotionType inMotionType, EConstraintOverride inConstraintOverride = EConstraintOverride::TypeRagdoll);
+#endif // JPH_OBJECT_STREAM
+
+	/// Create a ragdoll from code
+	static RagdollSettings *		sCreate();
 };

+ 7 - 1
UnitTests/UnitTests.cmake

@@ -34,7 +34,6 @@ set(UNIT_TESTS_SRC_FILES
 	${UNIT_TESTS_ROOT}/Math/Vec3Tests.cpp
 	${UNIT_TESTS_ROOT}/Math/Vec4Tests.cpp
 	${UNIT_TESTS_ROOT}/Math/VectorTests.cpp
-	${UNIT_TESTS_ROOT}/ObjectStream/ObjectStreamTest.cpp
 	${UNIT_TESTS_ROOT}/Physics/ActiveEdgesTests.cpp
 	${UNIT_TESTS_ROOT}/Physics/BroadPhaseTests.cpp
 	${UNIT_TESTS_ROOT}/Physics/CastShapeTests.cpp
@@ -72,5 +71,12 @@ set(UNIT_TESTS_SRC_FILES
 	${UNIT_TESTS_ROOT}/UnitTests.cmake
 )
 
+if (ENABLE_OBJECT_STREAM)
+	set(UNIT_TESTS_SRC_FILES
+		${UNIT_TESTS_SRC_FILES}
+		${UNIT_TESTS_ROOT}/ObjectStream/ObjectStreamTest.cpp
+	)
+endif()
+
 # Group source files
 source_group(TREE ${UNIT_TESTS_ROOT} FILES ${UNIT_TESTS_SRC_FILES})