Skip to content

Commit

Permalink
Embedding assets into the application bundle on macOS (#1453)
Browse files Browse the repository at this point in the history
* All asset reads go through the AssetStream class
* Implemented alert for macOS

Fixes #1452
  • Loading branch information
jrouwe authored Jan 12, 2025
1 parent 74b5814 commit e030a57
Show file tree
Hide file tree
Showing 31 changed files with 307 additions and 99 deletions.
2 changes: 1 addition & 1 deletion JoltViewer/JoltViewer.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ source_group(TREE ${JOLT_VIEWER_ROOT} FILES ${JOLT_VIEWER_SRC_FILES})

# Create JoltViewer executable
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
add_executable(JoltViewer MACOSX_BUNDLE ${JOLT_VIEWER_SRC_FILES})
add_executable(JoltViewer MACOSX_BUNDLE ${JOLT_VIEWER_SRC_FILES} ${TEST_FRAMEWORK_ASSETS})
set_property(TARGET JoltViewer PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/iOS/JoltViewerInfo.plist")
set_property(TARGET JoltViewer PROPERTY XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.joltphysics.joltviewer")
else()
Expand Down
31 changes: 30 additions & 1 deletion Samples/Samples.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,41 @@ if (ENABLE_OBJECT_STREAM)
)
endif()

# Assets used by the samples
set(SAMPLES_ASSETS
${PHYSICS_REPO_ROOT}/Assets/convex_hulls.bin
${PHYSICS_REPO_ROOT}/Assets/heightfield1.bin
${PHYSICS_REPO_ROOT}/Assets/Human/dead_pose1.tof
${PHYSICS_REPO_ROOT}/Assets/Human/dead_pose2.tof
${PHYSICS_REPO_ROOT}/Assets/Human/dead_pose3.tof
${PHYSICS_REPO_ROOT}/Assets/Human/dead_pose4.tof
${PHYSICS_REPO_ROOT}/Assets/Human/jog_hd.tof
${PHYSICS_REPO_ROOT}/Assets/Human/neutral.tof
${PHYSICS_REPO_ROOT}/Assets/Human/neutral_hd.tof
${PHYSICS_REPO_ROOT}/Assets/Human/skeleton_hd.tof
${PHYSICS_REPO_ROOT}/Assets/Human/sprint.tof
${PHYSICS_REPO_ROOT}/Assets/Human/walk.tof
${PHYSICS_REPO_ROOT}/Assets/Human.tof
${PHYSICS_REPO_ROOT}/Assets/Racetracks/Zandvoort.csv
${PHYSICS_REPO_ROOT}/Assets/terrain1.bof
${PHYSICS_REPO_ROOT}/Assets/terrain2.bof
)

# Group source files
source_group(TREE ${SAMPLES_ROOT} FILES ${SAMPLES_SRC_FILES})

# Create Samples executable
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
add_executable(Samples MACOSX_BUNDLE ${SAMPLES_SRC_FILES})
# macOS configuration
add_executable(Samples MACOSX_BUNDLE ${SAMPLES_SRC_FILES} ${TEST_FRAMEWORK_ASSETS} ${SAMPLES_ASSETS})

# Make sure that all samples assets move to the Resources folder in the package
foreach(ASSET_FILE ${SAMPLES_ASSETS})
string(REPLACE ${PHYSICS_REPO_ROOT}/Assets "Resources" ASSET_DST ${ASSET_FILE})
get_filename_component(ASSET_DST ${ASSET_DST} DIRECTORY)
set_source_files_properties(${ASSET_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION ${ASSET_DST})
endforeach()

set_property(TARGET Samples PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/iOS/SamplesInfo.plist")
set_property(TARGET Samples PROPERTY XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.joltphysics.samples")
else()
Expand Down
4 changes: 3 additions & 1 deletion Samples/Tests/Character/CharacterBaseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <Application/DebugUI.h>
#include <Layers.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
#include <Renderer/DebugRendererImp.h>

JPH_IMPLEMENT_RTTI_ABSTRACT(CharacterBaseTest)
Expand Down Expand Up @@ -563,7 +564,8 @@ void CharacterBaseTest::Initialize()
{
// Load scene
Ref<PhysicsScene> scene;
if (!ObjectStreamIn::sReadObject((String("Assets/") + sSceneName + ".bof").c_str(), scene))
AssetStream stream(String(sSceneName) + ".bof", std::ios::in | std::ios::binary);
if (!ObjectStreamIn::sReadObject(stream.Get(), scene))
FatalError("Failed to load scene");
scene->FixInvalidScales();
for (BodyCreationSettings &settings : scene->GetBodies())
Expand Down
37 changes: 18 additions & 19 deletions Samples/Tests/ConvexCollision/ConvexHullShrinkTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <Jolt/Geometry/ConvexSupport.h>
#include <Jolt/Physics/Collision/Shape/ConvexHullShape.h>
#include <Renderer/DebugRendererImp.h>
#include <Utils/AssetStream.h>

JPH_SUPPRESS_WARNINGS_STD_BEGIN
#include <fstream>
Expand Down Expand Up @@ -91,29 +92,27 @@ void ConvexHullShrinkTest::Initialize()

// Open the external file with hulls
// A stream containing predefined convex hulls
ifstream points_stream("Assets/convex_hulls.bin", std::ios::binary);
if (points_stream.is_open())
AssetStream points_asset_stream("convex_hulls.bin", std::ios::in | std::ios::binary);
std::istream &points_stream = points_asset_stream.Get();
for (;;)
{
for (;;)
{
// Read the length of the next point cloud
uint32 len = 0;
points_stream.read((char *)&len, sizeof(len));
if (points_stream.eof())
break;
// Read the length of the next point cloud
uint32 len = 0;
points_stream.read((char *)&len, sizeof(len));
if (points_stream.eof())
break;

// Read the points
if (len > 0)
// Read the points
if (len > 0)
{
Points p;
for (uint32 i = 0; i < len; ++i)
{
Points p;
for (uint32 i = 0; i < len; ++i)
{
Float3 v;
points_stream.read((char *)&v, sizeof(v));
p.push_back(Vec3(v));
}
mPoints.push_back(std::move(p));
Float3 v;
points_stream.read((char *)&v, sizeof(v));
p.push_back(Vec3(v));
}
mPoints.push_back(std::move(p));
}
}
}
Expand Down
37 changes: 18 additions & 19 deletions Samples/Tests/ConvexCollision/ConvexHullTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Tests/ConvexCollision/ConvexHullTest.h>
#include <Jolt/Geometry/ConvexHullBuilder.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
#include <Utils/DebugRendererSP.h>

JPH_SUPPRESS_WARNINGS_STD_BEGIN
Expand Down Expand Up @@ -457,29 +458,27 @@ void ConvexHullTest::Initialize()

// Open the external file with hulls
// A stream containing predefined convex hulls
ifstream points_stream("Assets/convex_hulls.bin", std::ios::binary);
if (points_stream.is_open())
AssetStream points_asset_stream("convex_hulls.bin", std::ios::in | std::ios::binary);
std::istream &points_stream = points_asset_stream.Get();
for (;;)
{
for (;;)
// Read the length of the next point cloud
uint32 len = 0;
points_stream.read((char *)&len, sizeof(len));
if (points_stream.eof())
break;

// Read the points
if (len > 0)
{
// Read the length of the next point cloud
uint32 len = 0;
points_stream.read((char *)&len, sizeof(len));
if (points_stream.eof())
break;

// Read the points
if (len > 0)
Points p;
for (uint32 i = 0; i < len; ++i)
{
Points p;
for (uint32 i = 0; i < len; ++i)
{
Float3 v;
points_stream.read((char *)&v, sizeof(v));
p.push_back(Vec3(v));
}
mPoints.push_back(std::move(p));
Float3 v;
points_stream.read((char *)&v, sizeof(v));
p.push_back(Vec3(v));
}
mPoints.push_back(std::move(p));
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion Samples/Tests/General/HighSpeedTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <Jolt/ObjectStream/ObjectStreamIn.h>
#include <Application/DebugUI.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
#include <Layers.h>

JPH_IMPLEMENT_RTTI_VIRTUAL(HighSpeedTest)
Expand Down Expand Up @@ -330,7 +331,8 @@ void HighSpeedTest::CreateConvexOnTerrain1()
#ifdef JPH_OBJECT_STREAM
// Load scene
Ref<PhysicsScene> scene;
if (!ObjectStreamIn::sReadObject("Assets/terrain1.bof", scene))
AssetStream stream("terrain1.bof", std::ios::in | std::ios::binary);
if (!ObjectStreamIn::sReadObject(stream.Get(), scene))
FatalError("Failed to load scene");
for (BodyCreationSettings &body : scene->GetBodies())
body.mObjectLayer = Layers::NON_MOVING;
Expand Down
6 changes: 4 additions & 2 deletions Samples/Tests/General/MultithreadedTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <Layers.h>
#include <Utils/RagdollLoader.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
#include <Renderer/DebugRendererImp.h>

JPH_IMPLEMENT_RTTI_VIRTUAL(MultithreadedTest)
Expand Down Expand Up @@ -137,7 +138,7 @@ void MultithreadedTest::RagdollSpawner()

#ifdef JPH_OBJECT_STREAM
// Load ragdoll
Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic);
if (ragdoll_settings == nullptr)
FatalError("Could not load ragdoll");
#else
Expand All @@ -151,7 +152,8 @@ void MultithreadedTest::RagdollSpawner()
{
#ifdef JPH_OBJECT_STREAM
Ref<SkeletalAnimation> animation;
if (!ObjectStreamIn::sReadObject("Assets/Human/dead_pose1.tof", animation))
AssetStream stream("Human/dead_pose1.tof", std::ios::in);
if (!ObjectStreamIn::sReadObject(stream.Get(), animation))
FatalError("Could not open animation");
animation->Sample(0.0f, ragdoll_pose);
#else
Expand Down
6 changes: 4 additions & 2 deletions Samples/Tests/General/SensorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <Jolt/ObjectStream/ObjectStreamIn.h>
#include <Utils/RagdollLoader.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
#include <Layers.h>
#include <Renderer/DebugRendererImp.h>

Expand Down Expand Up @@ -71,7 +72,7 @@ void SensorTest::Initialize()

#ifdef JPH_OBJECT_STREAM
// Load ragdoll
Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
Ref<RagdollSettings> ragdoll_settings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic);
if (ragdoll_settings == nullptr)
FatalError("Could not load ragdoll");
#else
Expand All @@ -84,7 +85,8 @@ void SensorTest::Initialize()
{
#ifdef JPH_OBJECT_STREAM
Ref<SkeletalAnimation> animation;
if (!ObjectStreamIn::sReadObject("Assets/Human/dead_pose1.tof", animation))
AssetStream stream("Human/dead_pose1.tof", std::ios::in);
if (!ObjectStreamIn::sReadObject(stream.Get(), animation))
FatalError("Could not open animation");
animation->Sample(0.0f, ragdoll_pose);
#else
Expand Down
6 changes: 4 additions & 2 deletions Samples/Tests/Rig/BigWorldTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <Renderer/DebugRendererImp.h>
#include <Layers.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
#include <random>

JPH_IMPLEMENT_RTTI_VIRTUAL(BigWorldTest)
Expand All @@ -39,11 +40,12 @@ void BigWorldTest::Initialize()
RefConst<Shape> shape = floor.GetShape();

// Load ragdoll
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic);

// Load animation
Ref<SkeletalAnimation> animation;
if (!ObjectStreamIn::sReadObject("Assets/Human/dead_pose1.tof", animation))
AssetStream stream("Human/dead_pose1.tof", std::ios::in);
if (!ObjectStreamIn::sReadObject(stream.Get(), animation))
FatalError("Could not open animation");
SkeletonPose pose;
pose.SetSkeleton(settings->GetSkeleton());
Expand Down
7 changes: 4 additions & 3 deletions Samples/Tests/Rig/KinematicRigTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <Application/DebugUI.h>
#include <Layers.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>

JPH_IMPLEMENT_RTTI_VIRTUAL(KinematicRigTest)
{
Expand Down Expand Up @@ -50,15 +51,15 @@ void KinematicRigTest::Initialize()
}

// Load ragdoll
mRagdollSettings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Kinematic);
mRagdollSettings = RagdollLoader::sLoad("Human.tof", EMotionType::Kinematic);

// Create ragdoll
mRagdoll = mRagdollSettings->CreateRagdoll(0, 0, mPhysicsSystem);
mRagdoll->AddToPhysicsSystem(EActivation::Activate);

// Load animation
String filename = String("Assets/Human/") + sAnimationName + ".tof";
if (!ObjectStreamIn::sReadObject(filename.c_str(), mAnimation))
AssetStream stream(String("Human/") + sAnimationName + ".tof", std::ios::in);
if (!ObjectStreamIn::sReadObject(stream.Get(), mAnimation))
FatalError("Could not open animation");

// Initialize pose
Expand Down
2 changes: 1 addition & 1 deletion Samples/Tests/Rig/LoadRigTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void LoadRigTest::Initialize()
CreateFloor();

// Load ragdoll
mRagdollSettings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic, sConstraintType);
mRagdollSettings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic, sConstraintType);

// Create ragdoll
mRagdoll = mRagdollSettings->CreateRagdoll(0, 0, mPhysicsSystem);
Expand Down
2 changes: 1 addition & 1 deletion Samples/Tests/Rig/LoadSaveBinaryRigTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void LoadSaveBinaryRigTest::Initialize()

{
// Load ragdoll
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic);

// Add an additional constraint between the left and right arm to test loading/saving of additional constraints
const Skeleton *skeleton = settings->GetSkeleton();
Expand Down
2 changes: 1 addition & 1 deletion Samples/Tests/Rig/LoadSaveRigTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void LoadSaveRigTest::Initialize()

{
// Load ragdoll
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic);

// Add an additional constraint between the left and right arm to test loading/saving of additional constraints
const Skeleton *skeleton = settings->GetSkeleton();
Expand Down
7 changes: 4 additions & 3 deletions Samples/Tests/Rig/PoweredRigTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <Application/DebugUI.h>
#include <Utils/RagdollLoader.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>

JPH_IMPLEMENT_RTTI_VIRTUAL(PoweredRigTest)
{
Expand Down Expand Up @@ -40,15 +41,15 @@ void PoweredRigTest::Initialize()
CreateFloor();

// Load ragdoll
mRagdollSettings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
mRagdollSettings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic);

// Create ragdoll
mRagdoll = mRagdollSettings->CreateRagdoll(0, 0, mPhysicsSystem);
mRagdoll->AddToPhysicsSystem(EActivation::Activate);

// Load animation
String filename = String("Assets/Human/") + sAnimationName + ".tof";
if (!ObjectStreamIn::sReadObject(filename.c_str(), mAnimation))
AssetStream stream(String("Human/") + sAnimationName + ".tof", std::ios::in);
if (!ObjectStreamIn::sReadObject(stream.Get(), mAnimation))
FatalError("Could not open animation");

// Initialize pose
Expand Down
9 changes: 6 additions & 3 deletions Samples/Tests/Rig/RigPileTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <Application/DebugUI.h>
#include <Layers.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
#include <random>

JPH_IMPLEMENT_RTTI_VIRTUAL(RigPileTest)
Expand Down Expand Up @@ -64,7 +65,8 @@ void RigPileTest::Initialize()
{
// Load scene
Ref<PhysicsScene> scene;
if (!ObjectStreamIn::sReadObject((String("Assets/") + sSceneName + ".bof").c_str(), scene))
AssetStream stream(String(sSceneName) + ".bof", std::ios::in | std::ios::binary);
if (!ObjectStreamIn::sReadObject(stream.Get(), scene))
FatalError("Failed to load scene");
for (BodyCreationSettings &body : scene->GetBodies())
body.mObjectLayer = Layers::NON_MOVING;
Expand All @@ -73,14 +75,15 @@ void RigPileTest::Initialize()
}

// Load ragdoll
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Assets/Human.tof", EMotionType::Dynamic);
Ref<RagdollSettings> settings = RagdollLoader::sLoad("Human.tof", EMotionType::Dynamic);

// Load animation
const int cAnimationCount = 4;
Ref<SkeletalAnimation> animation[cAnimationCount];
for (int i = 0; i < cAnimationCount; ++i)
{
if (!ObjectStreamIn::sReadObject(StringFormat("Assets/Human/dead_pose%d.tof", i + 1).c_str(), animation[i]))
AssetStream stream(StringFormat("Human/dead_pose%d.tof", i + 1), std::ios::in);
if (!ObjectStreamIn::sReadObject(stream.Get(), animation[i]))
FatalError("Could not open animation");
}

Expand Down
Loading

0 comments on commit e030a57

Please sign in to comment.