Skip to content

Commit

Permalink
integration
Browse files Browse the repository at this point in the history
  • Loading branch information
McCallisterRomer committed Jan 13, 2025
1 parent df557e9 commit ca1bf68
Show file tree
Hide file tree
Showing 29 changed files with 400 additions and 63 deletions.
4 changes: 4 additions & 0 deletions include/ncengine/asset/NcAsset.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace asset
struct BoneUpdateEventData;
struct ConvexHullUpdateEventData;
struct CubeMapUpdateEventData;
struct MeshColliderUpdateEventData;
struct MeshUpdateEventData;
struct SkeletalAnimationUpdateEventData;
struct TextureUpdateEventData;
Expand Down Expand Up @@ -51,6 +52,9 @@ class NcAsset : public Module
/** @brief Get the signal for ConvexHull load and unload events. */
virtual auto OnConvexHullUpdate() noexcept -> Signal<const ConvexHullUpdateEventData&>& = 0;

/** @brief Get the signal for MeshCollider load and unload events. */
virtual auto OnMeshColliderUpdate() noexcept -> Signal<const MeshColliderUpdateEventData&>& = 0;

/** @brief Get the signal for Font load and unload events. */
virtual auto OnFontUpdate() noexcept -> Signal<>& = 0;

Expand Down
6 changes: 5 additions & 1 deletion include/ncengine/physics/RigidBody.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class RigidBody
{
m_info.flags &= ~RigidBodyFlags::ContinuousDetection;
}

VerifyShapeSettings();
}

RigidBody(RigidBody&& other) noexcept
Expand Down Expand Up @@ -155,7 +157,7 @@ class RigidBody

/** @name Shape Functions */
auto GetShape() const -> const Shape& { return m_shape; }
void SetShape(const Shape& shape, const Vector3& transformScale, bool wake = true); // todo: how to update transform?
void SetShape(const Shape& shape, const Vector3& transformScale, bool wake = true);

/** @name Simulation Properties */
auto IsAwake() const -> bool;
Expand Down Expand Up @@ -273,6 +275,8 @@ class RigidBody
BodyHandle m_handle = nullptr;
Shape m_shape;
RigidBodyInfo m_info;

void VerifyShapeSettings();
};

template<>
Expand Down
13 changes: 12 additions & 1 deletion include/ncengine/physics/Shape.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ enum class ShapeType : uint8_t
Box,
Sphere,
Capsule,
ConvexHull
ConvexHull,
Mesh
};

/** @brief Get a valid scale for a shape given its current and desired scale values. */
Expand Down Expand Up @@ -56,6 +57,16 @@ struct Shape
return Shape{assetId, scale, ShapeType::ConvexHull};
}

/**
* @brief Make a shape from a MeshCollider asset.
* @note MeshColliders are only compatible with BodyType::Static.
*/
static constexpr auto MakeMesh(asset::AssetId assetId,
const Vector3& scale = Vector3::One()) -> Shape
{
return Shape{assetId, scale, ShapeType::Mesh};
}

auto GetLocalPosition() const -> const Vector3& { return m_localPosition; }
auto GetLocalScale() const -> const Vector3& { return m_localScale; }
auto GetAssetId() const -> asset::AssetId { return m_assetId; }
Expand Down
25 changes: 25 additions & 0 deletions include/ncengine/ui/ImGuiUtility.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ auto InputColor4(Vector4& value, const char* label) -> bool;
/** @brief Combobox UI widget. */
auto Combobox(std::string& value, const char* label, std::span<const std::string_view> items);

/** @brief Combobox UI widget that allows disabling selection of entries. */
auto FilteredCombobox(std::string& value, const char* label, std::span<const std::string_view> items, auto&& disableIf);

/** @brief Text input UI widget. */
auto InputText(std::string& value, const char* label) -> bool;

Expand Down Expand Up @@ -398,6 +401,28 @@ inline auto Combobox(std::string& value, const char* label, std::span<const std:
return false;
}

inline auto FilteredCombobox(std::string& value, const char* label, std::span<const std::string_view> items, auto&& disableIf)
{
if (ImGui::BeginCombo(label, value.c_str()))
{
const auto selected = std::ranges::find_if(items, [&disableIf](const auto& text)
{
IMGUI_SCOPE(DisableIf, disableIf(text));
return ImGui::Selectable(text.data());
});

ImGui::EndCombo();

if (selected != std::cend(items))
{
value = selected->data();
return true;
}
}

return false;
}

namespace internal
{
struct InputTextCallbackUserData
Expand Down
18 changes: 14 additions & 4 deletions sample/source/scenes/Benchmarks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@ constexpr auto g_assets = std::array{
std::string_view{nc::asset::CubeMesh},
std::string_view{nc::asset::SphereMesh},
std::string_view{nc::asset::CapsuleMesh},
std::string_view{nc::sample::RampMesh}
std::string_view{nc::sample::mesh::RampPath},
std::string_view{nc::sample::mesh::HalfPipePath}
};

const auto g_meshViews = std::array{
&nc::sample::mesh::Cube,
&nc::sample::mesh::Sphere,
&nc::sample::mesh::Capsule,
&nc::sample::mesh::Ramp
&nc::sample::mesh::Ramp,
&nc::sample::mesh::HalfPipe
};

// Need to store ptrs b/c deferred initialization
Expand Down Expand Up @@ -85,6 +87,12 @@ auto AssetCombo(std::string& selection) -> bool
return nc::ui::Combobox(selection, "##assetcombo", g_assets);
}

auto AssetComboExcludeMeshCollider(std::string& selection) -> bool
{
const auto disableMeshCollider = [](const auto& entry){ return entry == nc::sample::mesh::HalfPipePath; };
return nc::ui::FilteredCombobox(selection, "##assetcombo", g_assets, disableMeshCollider);
}

auto AddRigidBodyForMesh(nc::ecs::Ecs world, nc::Entity entity, std::string_view mesh, nc::BodyType type = nc::BodyType::Dynamic) -> nc::RigidBody&
{
auto shape = [&]()
Expand All @@ -95,8 +103,10 @@ auto AddRigidBodyForMesh(nc::ecs::Ecs world, nc::Entity entity, std::string_view
return nc::Shape::MakeSphere();
else if (mesh == nc::asset::CapsuleMesh)
return nc::Shape::MakeCapsule();
else if (mesh == nc::sample::RampMesh)
else if (mesh == nc::sample::convex_hull::RampPath)
return nc::Shape::MakeConvexHull(nc::sample::convex_hull::Ramp);
else if (mesh == nc::sample::mesh_collider::HalfpipePath)
return nc::Shape::MakeMesh(nc::sample::mesh_collider::Halfpipe);
else
throw nc::NcError(fmt::format("Unexpected mesh '{}'", mesh));
}();
Expand Down Expand Up @@ -363,7 +373,7 @@ void Widget()
ImGui::TableNextColumn();
InnerWidget<rigid_body>{}(halfCellWidth, [cellWidth](){
ImGui::SetNextItemWidth(cellWidth);
AssetCombo(rigid_body::Mesh);
AssetComboExcludeMeshCollider(rigid_body::Mesh);
});

ImGui::TableNextRow();
Expand Down
5 changes: 3 additions & 2 deletions sample/source/scenes/PhysicsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -777,15 +777,16 @@ void BuildRotatingSteps(ecs::Ecs world)

void BuildHalfPipes(ecs::Ecs world)
{
const auto halfPipe2 = world.Emplace<Entity>({
const auto halfPipe = world.Emplace<Entity>({
.position = Vector3{15.0f, 3.7f, 40.5f},
.rotation = Quaternion::FromEulerAngles(0.0f, 0.0f, -0.173f),
.scale = Vector3{10.0f, 3.0f, 5.0f},
.tag = "Half Pipe",
.flags = Entity::Flags::Static
});

world.Emplace<StaticMesh>(halfPipe2, mesh::HalfPipe, material::Blue);
world.Emplace<StaticMesh>(halfPipe, mesh::HalfPipe, material::Blue);
world.Emplace<RigidBody>(halfPipe, Shape::MakeMesh(mesh_collider::Halfpipe));
}

void BuildHinge(ecs::Ecs world)
Expand Down
33 changes: 18 additions & 15 deletions sample/source/scenes/SmokeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,23 @@ void SmokeTest::Load(ecs::Ecs world, ModuleProvider modules)

world.Emplace<PointLight>(pointLight);

const auto box1 = world.Emplace<Entity>({.position = Vector3{-1.0f, 0.0f, 0.0f}});
const auto box2 = world.Emplace<Entity>({.position = Vector3{ 1.0f, 0.0f, 0.0f}});
const auto sphere1 = world.Emplace<Entity>({.position = Vector3{-4.0f, 1.0f, 0.0f}});
const auto sphere2 = world.Emplace<Entity>({.position = Vector3{-3.0f, 0.0f, 0.0f}});
const auto capsule1 = world.Emplace<Entity>({.position = Vector3{ 3.5f, 0.0f, 0.0f}});
const auto capsule2 = world.Emplace<Entity>({.position = Vector3{ 3.5f, 3.0f, 0.0f}});
const auto hull = world.Emplace<Entity>({.position = Vector3{ 1.0f, 1.0f, 1.0f}});

world.Emplace<StaticMesh>(box1, mesh::Cube, material::Default);
world.Emplace<StaticMesh>(box2, mesh::Cube, material::Default);
world.Emplace<StaticMesh>(sphere1, mesh::Sphere, material::Default);
world.Emplace<StaticMesh>(sphere2, mesh::Sphere, material::Default);
world.Emplace<StaticMesh>(capsule1, mesh::Capsule, material::Default);
world.Emplace<StaticMesh>(capsule2, mesh::Capsule, material::Default);
world.Emplace<StaticMesh>(hull, mesh::Ramp, material::Default);
const auto box1 = world.Emplace<Entity>({.position = Vector3{-1.0f, 0.0f, 0.0f}});
const auto box2 = world.Emplace<Entity>({.position = Vector3{ 1.0f, 0.0f, 0.0f}});
const auto sphere1 = world.Emplace<Entity>({.position = Vector3{-4.0f, 1.0f, 0.0f}});
const auto sphere2 = world.Emplace<Entity>({.position = Vector3{-3.0f, 0.0f, 0.0f}});
const auto capsule1 = world.Emplace<Entity>({.position = Vector3{ 3.5f, 0.0f, 0.0f}});
const auto capsule2 = world.Emplace<Entity>({.position = Vector3{ 3.5f, 3.0f, 0.0f}});
const auto hull = world.Emplace<Entity>({.position = Vector3{ 1.0f, 1.0f, 1.0f}});
const auto halfpipe = world.Emplace<Entity>({.position = Vector3{ 0.0f, -7.0f, 0.0f}, .flags = Entity::Flags::Static});

world.Emplace<StaticMesh>(box1, mesh::Cube, material::Default);
world.Emplace<StaticMesh>(box2, mesh::Cube, material::Default);
world.Emplace<StaticMesh>(sphere1, mesh::Sphere, material::Default);
world.Emplace<StaticMesh>(sphere2, mesh::Sphere, material::Default);
world.Emplace<StaticMesh>(capsule1, mesh::Capsule, material::Default);
world.Emplace<StaticMesh>(capsule2, mesh::Capsule, material::Default);
world.Emplace<StaticMesh>(hull, mesh::Ramp, material::Default);
world.Emplace<StaticMesh>(halfpipe, mesh::HalfPipe, material::Default);

auto& box1Body = world.Emplace<RigidBody>(box1, Shape::MakeBox());
auto& box2Body = world.Emplace<RigidBody>(box2, Shape::MakeBox());
Expand All @@ -230,6 +232,7 @@ void SmokeTest::Load(ecs::Ecs world, ModuleProvider modules)
auto& capsule1Body = world.Emplace<RigidBody>(capsule1, Shape::MakeCapsule());
auto& capsule2Body = world.Emplace<RigidBody>(capsule2, Shape::MakeCapsule());
auto& hullBody = world.Emplace<RigidBody>(hull, Shape::MakeConvexHull(convex_hull::Ramp));
world.Emplace<RigidBody>(halfpipe, Shape::MakeMesh(mesh_collider::Halfpipe));

world.Emplace<CollisionListener>(
box1,
Expand Down
5 changes: 5 additions & 0 deletions sample/source/shared/Prefabs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ namespace convex_hull
asset::AssetId Ramp{MakeAnimId(RampPath)};
} // namespace convex_hull

namespace mesh_collider
{
asset::AssetId Halfpipe{MakeAnimId(HalfpipePath)};
} // namespace mesh_collider

asset::FontInfo UIFont{"SourceCodePro-Regular.ttf", 16.0f};

template<class LoadFunc>
Expand Down
13 changes: 8 additions & 5 deletions sample/source/shared/Prefabs.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@ namespace nc::sample
// Load Asset Files
void InitializeResources();

//
// Reload cached global asset views
void ReloadPrefabs();


// Mesh
constexpr auto HalfPipeMesh = "halfpipe.nca";
constexpr auto RampMesh = "ramp.nca";

namespace mesh
{
constexpr auto HalfPipePath = "halfpipe.nca";
Expand Down Expand Up @@ -79,6 +75,13 @@ constexpr auto RampPath = "ramp.nca";
extern asset::AssetId Ramp;
} // namespace collider

// MeshColliders
namespace mesh_collider
{
constexpr auto HalfpipePath = "halfpipe.nca";
extern asset::AssetId Halfpipe;
} // namespace mesh_collider

// Fonts
extern asset::FontInfo UIFont;
} // namespace nc::sample
5 changes: 5 additions & 0 deletions source/ncengine/asset/NcAssetImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ auto NcAssetImpl::OnConvexHullUpdate() noexcept -> Signal<const ConvexHullUpdate
return m_hullColliderManager->OnUpdate();
}

auto NcAssetImpl::OnMeshColliderUpdate() noexcept -> Signal<const MeshColliderUpdateEventData&>&
{
return m_concaveColliderManager->OnUpdate();
}

auto NcAssetImpl::OnFontUpdate() noexcept -> Signal<>&
{
return m_fontManager->OnUpdate();
Expand Down
1 change: 1 addition & 0 deletions source/ncengine/asset/NcAssetImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class NcAssetImpl : public NcAsset
auto OnTextureUpdate() noexcept -> Signal<const TextureUpdateEventData&>& override;
auto OnSkeletalAnimationUpdate() noexcept -> Signal<const SkeletalAnimationUpdateEventData&>& override;
auto OnConvexHullUpdate() noexcept -> Signal<const ConvexHullUpdateEventData&>& override;
auto OnMeshColliderUpdate() noexcept -> Signal<const MeshColliderUpdateEventData&>& override;
auto OnFontUpdate() noexcept -> Signal<>& override;
void LoadAssets(const AssetMap& assets) override;
auto GetLoadedAssets() const noexcept -> AssetMap override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ auto GetMeshView(nc::ShapeType shape) -> nc::asset::MeshView
return view;
}
case nc::ShapeType::ConvexHull:
case nc::ShapeType::Mesh:
{
/** @todo 567 currently have no renderable geometry for these */
static const auto view = AssetService<MeshView>::Get()->Acquire(CubeMesh);
Expand Down
5 changes: 4 additions & 1 deletion source/ncengine/physics/NcPhysicsImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ NcPhysicsImpl::NcPhysicsImpl(const config::MemorySettings& memorySettings,
std::unique_ptr<DeferredPhysicsCreateState> deferredState)
: m_ecs{world},
m_jolt{memorySettings, physicsSettings, dispatcher},
m_shapeFactory{ncAsset.OnConvexHullUpdate()},
m_shapeFactory{
ncAsset.OnConvexHullUpdate(),
ncAsset.OnMeshColliderUpdate()
},
m_constraintFactory{m_jolt.physicsSystem},
m_constraintManager{
m_jolt.physicsSystem,
Expand Down
3 changes: 2 additions & 1 deletion source/ncengine/physics/PhysicsUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ constexpr auto g_shapeTypeNames = std::array{
"Box"sv,
"Sphere"sv,
"Capsule"sv,
"ConvexHull"sv
"ConvexHull"sv,
"Mesh"sv,
};

constexpr auto g_constraintTypeNames = std::array{
Expand Down
10 changes: 10 additions & 0 deletions source/ncengine/physics/RigidBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void RigidBody::SetBodyType(BodyType type, bool wake)
}

m_info.type = type;
VerifyShapeSettings();
const auto id = ToBody(m_handle)->GetID();
s_ctx->interface.SetMotionType(id, ToMotionType(type), ToActivationMode(wake));
s_ctx->interface.SetObjectLayer(id, ToObjectLayer(m_info.type, IsTrigger()));
Expand Down Expand Up @@ -70,6 +71,7 @@ void RigidBody::SetAwakeState(bool wake)
void RigidBody::SetShape(const Shape& shape, const Vector3& transformScale, bool wake)
{
m_shape = shape;
VerifyShapeSettings();
const auto allowedScaling = ScalesWithTransform()
? ToJoltVec3(NormalizeScaleForShape(m_shape.GetType(), transformScale, transformScale))
: JPH::Vec3::sReplicate(1.0f);
Expand Down Expand Up @@ -316,4 +318,12 @@ auto RigidBody::SetSimulatedBodyScale(Transform& transform,
transform.SetScale(appliedScale);
return appliedScale;
}

void RigidBody::VerifyShapeSettings()
{
NC_ASSERT(
m_info.type == BodyType::Static || m_shape.GetType() != ShapeType::Mesh,
"ShapeType::Mesh requires BodyType::Static"
);
}
} // namespace nc
1 change: 1 addition & 0 deletions source/ncengine/physics/Shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ auto NormalizeScaleForShape(ShapeType shape,
{
case ShapeType::Box:
case ShapeType::ConvexHull:
case ShapeType::Mesh:
break;
case ShapeType::Sphere:
{
Expand Down
Loading

0 comments on commit ca1bf68

Please sign in to comment.