Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesh Component Serialization #860

Merged
merged 4 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/ncengine/graphics/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ class SkinnedMesh : public MeshBase
void SetMesh(const asset::MeshView& meshAsset);

/** @name Animation Functions */
auto GetAnimationController() -> SkeletalAnimationController& { return m_controller; }
auto GetAnimationController() const -> const SkeletalAnimationController& { return m_controller; }
auto GetAnimationController() -> SkeletalAnimationController& { return m_controller; }

private:
SkeletalAnimationController m_controller;
Expand Down
7 changes: 4 additions & 3 deletions include/ncengine/graphics/SkeletalAnimationController.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ class SkeletalAnimationController
auto AddState(LoopAnimation&& properties) -> AnimationStateId;
auto AddState(PlayOnceAnimation&& properties) -> AnimationStateId;
auto AddState(StopAnimation&& properties) -> AnimationStateId;
void SetAnimation(AnimationStateId stateId, uint64_t animationId);
auto GetAnimation(AnimationStateId stateId) const -> asset::AssetId;
void SetAnimation(AnimationStateId stateId, asset::AssetId animationId);
auto GetDefaultTransitionDuration() const -> float { return m_defaultTransitionDuration; }
void SetDefaultTransitionDuration(float dur) { m_defaultTransitionDuration = dur; }

Expand All @@ -116,12 +117,12 @@ class SkeletalAnimationController
* Immediate transitions interrupt the state machine and move to the specified state. Control is returned to
* the state machine upon the exit condition being met, or the immediate animation finishing, for PlayOnce.
*/
void LoopImmediate(uint64_t animId,
void LoopImmediate(asset::AssetId animId,
TransitionCondition&& exitWhen,
AnimationStateId exitTo = RootAnimationState,
float transitionDuration = UseDefaultTransitionDuration);

void PlayOnceImmediate(uint64_t animId,
void PlayOnceImmediate(asset::AssetId animId,
AnimationStateId exitTo = RootAnimationState,
float transitionDuration = UseDefaultTransitionDuration);

Expand Down
10 changes: 5 additions & 5 deletions source/ncengine/engine/registration/GraphicsTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ namespace nc
{
void RegisterGraphicsTypes(ecs::ComponentRegistry& registry, size_t maxEntities)
{
Register<StaticMesh>(
Register<StaticMesh>(
registry,
maxEntities,
StaticMeshId,
"StaticMesh",
ui::editor::StaticMeshUIWidget,
CreateStaticMesh,
nullptr,
nullptr
SerializeStaticMesh,
DeserializeStaticMesh
);

Register<SkinnedMesh>(
Expand All @@ -27,8 +27,8 @@ void RegisterGraphicsTypes(ecs::ComponentRegistry& registry, size_t maxEntities)
"SkinnedMesh",
ui::editor::SkinnedMeshUIWidget,
CreateSkinnedMesh,
nullptr,
nullptr
SerializeSkinnedMesh,
DeserializeSkinnedMesh
);

Register<ParticleEmitter>(
Expand Down
15 changes: 10 additions & 5 deletions source/ncengine/graphics2/SkeletalAnimationController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace nc
{
SkeletalAnimationController::SkeletalAnimationController(uint64_t animationId,
SkeletalAnimationController::SkeletalAnimationController(asset::AssetId animationId,
float defaultTransitionDuration)
: m_states{4ull, MaxAnimationStates},
m_defaultTransitionDuration{defaultTransitionDuration}
Expand All @@ -20,7 +20,7 @@ SkeletalAnimationController::SkeletalAnimationController(uint64_t animationId,
);
}

auto SkeletalAnimationController::GetCurrentAnimationId() const -> uint64_t
auto SkeletalAnimationController::GetCurrentAnimationId() const -> asset::AssetId
{
// Id is cached here if queued transition overwrote the current id (e.g. immediate -> immediate)
if (m_prevAnimId != asset::NullAssetId)
Expand Down Expand Up @@ -74,7 +74,12 @@ auto SkeletalAnimationController::AddState(StopAnimation&& properties) -> Animat
});
}

void SkeletalAnimationController::SetAnimation(AnimationStateId stateId, uint64_t animationId)
auto SkeletalAnimationController::GetAnimation(AnimationStateId stateId) const -> asset::AssetId
{
return m_states.at(stateId).animId;
}

void SkeletalAnimationController::SetAnimation(AnimationStateId stateId, asset::AssetId animationId)
{
const auto oldId = std::exchange(m_states.at(stateId).animId, animationId);
if (m_activeState == stateId)
Expand All @@ -84,7 +89,7 @@ void SkeletalAnimationController::SetAnimation(AnimationStateId stateId, uint64_
}
}

void SkeletalAnimationController::LoopImmediate(uint64_t animId,
void SkeletalAnimationController::LoopImmediate(asset::AssetId animId,
TransitionCondition&& exitWhen,
AnimationStateId exitTo,
float transitionDuration)
Expand All @@ -99,7 +104,7 @@ void SkeletalAnimationController::LoopImmediate(uint64_t animId,
});
}

void SkeletalAnimationController::PlayOnceImmediate(uint64_t animId,
void SkeletalAnimationController::PlayOnceImmediate(asset::AssetId animId,
AnimationStateId exitTo,
float transitionDuration)
{
Expand Down
76 changes: 76 additions & 0 deletions source/ncengine/serialize/ComponentSerialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "ncengine/audio/AudioSource.h"
#include "ncengine/graphics/Light.h"
#include "ncengine/graphics/ParticleEmitter.h"
#include "ncengine/graphics/Mesh.h"
#include "ncengine/physics/Constraints.h"
#include "ncengine/physics/RigidBody.h"
#include "ncengine/serialize/SceneSerialization.h"
Expand All @@ -28,6 +29,33 @@ void Deserialize(std::istream& stream, TextureView& out)
}
} // namespace asset

void SerializeMaterialDesc(std::ostream& stream, const MaterialInstance& out)
{
const auto& properties = out.GetProperties();
serialize::Serialize(stream, std::string{out.GetName()}); // don't want to serialize as string_view!
serialize::Serialize(stream, out.GetPasses());
serialize::Serialize(stream, properties.diffuseTexture); // serialize properties individually so we hit the special handling for textures
serialize::Serialize(stream, properties.normalTexture);
serialize::Serialize(stream, properties.gradientStart);
serialize::Serialize(stream, properties.gradientEnd);
serialize::Serialize(stream, properties.outlineColor);
serialize::Serialize(stream, properties.outlineWidth);
}

auto DeserializeMaterialDesc(std::istream& stream) -> MaterialDesc
{
auto out = MaterialDesc{};
serialize::Deserialize(stream, out.name);
serialize::Deserialize(stream, out.passes);
serialize::Deserialize(stream, out.properties.diffuseTexture);
serialize::Deserialize(stream, out.properties.normalTexture);
serialize::Deserialize(stream, out.properties.gradientStart);
serialize::Deserialize(stream, out.properties.gradientEnd);
serialize::Deserialize(stream, out.properties.outlineColor);
serialize::Deserialize(stream, out.properties.outlineWidth);
return out;
}

void SerializeAudioSource(std::ostream& stream, const audio::AudioSource& out, const SerializationContext& ctx, const std::any&)
{
serialize::Serialize(stream, ctx.entityMap.at(out.ParentEntity()));
Expand Down Expand Up @@ -58,6 +86,54 @@ auto DeserializeDirectionalLight(std::istream& stream, const DeserializationCont
return out;
}

void SerializeSkinnedMesh(std::ostream& stream, const SkinnedMesh& out, const SerializationContext& ctx, const std::any&)
{
serialize::Serialize(stream, ctx.entityMap.at(out.GetEntity()));
serialize::Serialize(stream, out.GetMeshId());
SerializeMaterialDesc(stream, out.GetMaterial());
serialize::Serialize(stream, out.GetAnimationController().GetAnimation(RootAnimationState));
}

auto DeserializeSkinnedMesh(std::istream& stream, const DeserializationContext& ctx, const std::any&) -> SkinnedMesh
{
auto entityId = uint32_t{};
auto meshId = asset::AssetId{};
auto animId = asset::AssetId{};
serialize::Deserialize(stream, entityId);
serialize::Deserialize(stream, meshId);
auto materialDesc = DeserializeMaterialDesc(stream);
serialize::Deserialize(stream, animId);

return SkinnedMesh{
ctx.entityMap.at(entityId),
asset::AcquireMeshAsset(meshId),
materialDesc,
animId
};
}

void SerializeStaticMesh(std::ostream& stream, const StaticMesh& out, const SerializationContext& ctx, const std::any&)
{
serialize::Serialize(stream, ctx.entityMap.at(out.GetEntity()));
serialize::Serialize(stream, out.GetMeshId());
SerializeMaterialDesc(stream, out.GetMaterial());
}

auto DeserializeStaticMesh(std::istream& stream, const DeserializationContext& ctx, const std::any&) -> StaticMesh
{
auto entityId = uint32_t{};
auto meshId = asset::AssetId{};
serialize::Deserialize(stream, entityId);
serialize::Deserialize(stream, meshId);
auto materialDesc = DeserializeMaterialDesc(stream);

return StaticMesh{
ctx.entityMap.at(entityId),
asset::AcquireMeshAsset(meshId),
materialDesc
};
}

void SerializeParticleEmitter(std::ostream& stream, const ParticleEmitter& out, const SerializationContext& ctx, const std::any&)
{
serialize::Serialize(stream, ctx.entityMap.at(out.GetEntity()));
Expand Down
4 changes: 4 additions & 0 deletions source/ncengine/serialize/ComponentSerialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ void SerializeParticleEmitter(std::ostream& stream, const ParticleEmitter& out,
auto DeserializeParticleEmitter(std::istream& stream, const DeserializationContext& ctx, const std::any&) -> ParticleEmitter;
void SerializePointLight(std::ostream& stream, const PointLight& out, const SerializationContext& ctx, const std::any&);
auto DeserializePointLight(std::istream& stream, const DeserializationContext& ctx, const std::any&) -> PointLight;
void SerializeSkinnedMesh(std::ostream& stream, const SkinnedMesh& out, const SerializationContext& ctx, const std::any&);
auto DeserializeSkinnedMesh(std::istream& stream, const DeserializationContext& ctx, const std::any&) -> SkinnedMesh;
void SerializeStaticMesh(std::ostream& stream, const StaticMesh& out, const SerializationContext& ctx, const std::any&);
auto DeserializeStaticMesh(std::istream& stream, const DeserializationContext& ctx, const std::any&) -> StaticMesh;
void SerializeSpotLight(std::ostream& stream, const SpotLight& out, const SerializationContext& ctx, const std::any&);
auto DeserializeSpotLight(std::istream& stream, const DeserializationContext& ctx, const std::any&) -> SpotLight;
void SerializeRigidBody(std::ostream& stream, const RigidBody& out, const SerializationContext&, const std::any&);
Expand Down
7 changes: 7 additions & 0 deletions test/ncengine/serialize/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ add_executable(ComponentSerialization_integration_tests
${NC_SOURCE_DIR}/serialize/ComponentSerialization.cpp
${NC_SOURCE_DIR}/audio/AudioSource.cpp
${NC_SOURCE_DIR}/ecs/Transform.cpp
${NC_SOURCE_DIR}/graphics2/GraphicsUtility.cpp
${NC_SOURCE_DIR}/graphics2/Material.cpp
${NC_SOURCE_DIR}/graphics2/Mesh.cpp
${NC_SOURCE_DIR}/graphics2/ParticleEmitter.cpp
${NC_SOURCE_DIR}/graphics2/SkeletalAnimationController.cpp
${NC_SOURCE_DIR}/graphics2/frontend/subsystem/MaterialRegistry.cpp
${NC_SOURCE_DIR}/graphics2/frontend/subsystem/MeshSubsystem.cpp
${NC_SOURCE_DIR}/graphics2/frontend/subsystem/TransformCache.cpp
)

target_include_directories(ComponentSerialization_integration_tests
Expand Down
Loading
Loading