Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
ModelComponent.cpp
1/*
2Copyright (C) 2018,2019,2021,2022,2025 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#include <array>
18#include <cstring>
19#include <cmath>
20#include <cassert>
22#include "aeongames/AeonEngine.hpp"
23#include "aeongames/Mesh.hpp"
24#include "aeongames/Pipeline.hpp"
25#include "aeongames/Skeleton.hpp"
26#include "aeongames/Animation.hpp"
28#include "aeongames/Buffer.hpp"
29#include "aeongames/Renderer.hpp"
30#include "aeongames/Node.hpp"
31#include "aeongames/Model.hpp"
32#include "ModelComponent.h"
33
34namespace AeonGames
35{
36 static const StringId ModelStringId{"Model Component"};
38 {
39 return ModelStringId;
40 }
41
43 ModelComponent::~ModelComponent() = default;
44
46 {
47 return ModelStringId;
48 }
49
50 static constexpr std::array<const StringId, 3> ModelComponentPropertyIds
51 {
52 {
53 {"Model"},
54 {"Active Animation"},
55 {"Starting Frame"},
56 }
57 };
58
60 {
61 return ModelComponentPropertyIds.size();
62 }
63
65 {
66 return ModelComponentPropertyIds.data();
67 }
68
70 {
71 switch ( aId )
72 {
73 case ModelComponentPropertyIds[0]:
74 return GetModel().GetPathString();
75 case ModelComponentPropertyIds[1]:
76 return GetActiveAnimation();
77 case ModelComponentPropertyIds[2]:
78 return GetStartingFrame();
79 }
80 return Property{};
81 }
82
83 void ModelComponent::SetProperty ( uint32_t aId, const Property& aProperty )
84 {
85 switch ( aId )
86 {
87 case ModelComponentPropertyIds[0]:
88 if ( std::holds_alternative<std::string> ( aProperty ) )
89 {
90 SetModel ( {"Model"_crc32, std::get<std::string> ( aProperty ) } );
91 }
92 else if ( std::holds_alternative<std::filesystem::path> ( aProperty ) )
93 {
94 SetModel ( {"Model"_crc32, std::get<std::filesystem::path> ( aProperty ).string() } );
95 }
96 else if ( std::holds_alternative<uint32_t> ( aProperty ) )
97 {
98 SetModel ( {"Model"_crc32, std::get<uint32_t> ( aProperty ) } );
99 }
100 break;
101 case ModelComponentPropertyIds[1]:
102 if ( std::holds_alternative<size_t> ( aProperty ) )
103 {
104 SetActiveAnimation ( std::get<size_t> ( aProperty ) );
105 }
106 break;
107 case ModelComponentPropertyIds[2]:
108 if ( std::holds_alternative<double> ( aProperty ) )
109 {
110 SetStartingFrame ( std::get<double> ( aProperty ) );
111 }
112 break;
113 }
114 }
115
117 {
118 mModel = aModel;
119 mModel.Store();
120 }
121
122 const ResourceId& ModelComponent::GetModel() const noexcept
123 {
124 return mModel;
125 }
126
127 void ModelComponent::SetActiveAnimation ( size_t aActiveAnimation ) noexcept
128 {
129 mActiveAnimation = aActiveAnimation;
130 mCurrentSample = mStartingFrame;
131 }
132
133 const size_t& ModelComponent::GetActiveAnimation() const noexcept
134 {
135 return mActiveAnimation;
136 }
137
138 void ModelComponent::SetStartingFrame ( double aAnimationDelta ) noexcept
139 {
140 mStartingFrame = mCurrentSample = aAnimationDelta;
141 }
142
143 const double& ModelComponent::GetStartingFrame() const noexcept
144 {
145 return mStartingFrame;
146 }
147
148 void ModelComponent::Update ( Node& aNode, double aDelta )
149 {
150 if ( auto model = mModel.Cast<Model>() )
151 {
152 AABB aabb;
153 for ( auto& i : model->GetAssemblies() )
154 {
155 if ( Mesh * mesh = std::get<0> ( i ).Cast<Mesh>() )
156 {
157 aabb += mesh->GetAABB();
158 }
159 }
160 aNode.SetAABB ( aabb );
161 const Skeleton* skeleton{ model->GetSkeleton() };
162 if ( skeleton )
163 {
164 float* skeleton_buffer = reinterpret_cast<float*> ( mSkeleton.data() );
165 assert ( ( skeleton->GetJoints().size() * sizeof ( float ) * 16 ) < mSkeleton.size() );
166 const std::vector<ResourceId>& animations = model->GetAnimations();
167 if ( animations.size() && animations.size() > mActiveAnimation )
168 {
169 // Use animation transforms
170 auto animation = animations[mActiveAnimation].Cast<Animation>();
171 mCurrentSample = animation->AddTimeToSample ( mCurrentSample, aDelta );
172 for ( size_t i = 0; i < skeleton->GetJoints().size(); ++i )
173 {
174 Matrix4x4 matrix{ animation->GetTransform ( i, mCurrentSample ) *
175 skeleton->GetJoints() [i].GetInvertedTransform() };
176 memcpy ( skeleton_buffer + ( i * 16 ), matrix.GetMatrix4x4(), sizeof ( float ) * 16 );
177 }
178 }
179 else
180 {
181 // No animation - use identity matrices (bind pose * inverse bind pose = identity)
182 Matrix4x4 identity{}; // Identity matrix
183 for ( size_t i = 0; i < skeleton->GetJoints().size(); ++i )
184 {
185 memcpy ( skeleton_buffer + ( i * 16 ), identity.GetMatrix4x4(), sizeof ( float ) * 16 );
186 }
187 }
188 }
189 }
190 }
191
192 void ModelComponent::Render ( const Node& aNode, Renderer& aRenderer, void* aWindowId )
193 {
194 if ( auto model = mModel.Cast<Model>() )
195 {
196 BufferAccessor* skeleton_accessor_ptr{nullptr};
197 BufferAccessor skeleton_accessor{};
198 const Skeleton* skeleton{model->GetSkeleton() };
199 if ( skeleton )
200 {
201 size_t used_bones_size = skeleton->GetJoints().size() * sizeof ( float ) * 16;
202 assert ( used_bones_size <= mSkeleton.size() );
203 skeleton_accessor = aRenderer.AllocateSingleFrameUniformMemory ( aWindowId, used_bones_size );
204 skeleton_accessor.WriteMemory ( 0, used_bones_size, mSkeleton.data() );
205 skeleton_accessor_ptr = &skeleton_accessor;
206 }
207 for ( auto& i : model->GetAssemblies() )
208 {
209 aRenderer.Render (
210 aWindowId,
211 aNode.GetGlobalTransform(),
212 *std::get<0> ( i ).Cast<Mesh>(),
213 *std::get<1> ( i ).Cast<Pipeline>(),
214 std::get<2> ( i ).Cast<Material>(),
215 skeleton_accessor_ptr );
216 }
217 }
218 }
219
220 void ModelComponent::ProcessMessage ( Node& aNode, uint32_t aMessageType, const void* aMessageData )
221 {
222 }
223}
Header for 4x4 matrix class.
Provides the DLL_PROTOBUF export/import macro for protobuf wrapper classes.
Axis Aligned Bounding Box class.
Definition AABB.hpp:34
Stores skeletal animation data including keyframes and bone transforms.
Definition Animation.hpp:29
DLL double AddTimeToSample(double aSample, double aTime) const
Advance a sample position by a time delta.
Provides access to a region within a memory pool buffer.
DLL void WriteMemory(size_t aOffset, size_t aSize, const void *aData=nullptr) const
Write data into the buffer region.
Represents a surface material with uniform properties and texture samplers.
Definition Material.hpp:38
4 by 4 matrix in colum mayor order.
Definition Matrix4x4.hpp:35
DLL const float *const GetMatrix4x4() const
Get a pointer to the internal matrix data.
Definition Matrix4x4.cpp:53
Represents a polygon mesh with vertex attributes and index data.
Definition Mesh.hpp:31
void Update(Node &aNode, double aDelta) final
Update the component state.
void SetModel(const ResourceId &aModel)
Sets the model resource.
size_t GetPropertyCount() const final
Get the number of properties exposed by this component.
void ProcessMessage(Node &aNode, uint32_t aMessageType, const void *aMessageData) final
Process an incoming message.
void SetProperty(uint32_t, const Property &aProperty) final
Set the value aProperty for the property identified by aId.
void SetActiveAnimation(size_t aActiveAnimation) noexcept
Sets the active animation index.
ModelComponent()
Default constructor.
void Render(const Node &aNode, Renderer &aRenderer, void *aWindowId) final
Render the component.
const ResourceId & GetModel() const noexcept
Returns the current model resource identifier.
void SetStartingFrame(double aAnimationDelta) noexcept
Sets the starting frame for the active animation.
Property GetProperty(const StringId &aId) const final
Get the value of a property.
static const StringId & GetClassId()
Returns the class identifier for the ModelComponent.
const double & GetStartingFrame() const noexcept
Returns the starting frame for the active animation.
const StringId * GetPropertyInfoArray() const final
Get the array of property identifiers.
const size_t & GetActiveAnimation() const noexcept
Returns the active animation index.
const StringId & GetId() const final
Get the unique identifier for this component type.
Represents a 3D model composed of assemblies (pipeline, material, mesh), a skeleton,...
Definition Model.hpp:35
Scene graph node representing an entity in the game world.
Definition Node.hpp:54
DLL void SetAABB(const AABB &aAABB)
Set the axis-aligned bounding box.
Definition Node.cpp:194
DLL const Transform & GetGlobalTransform() const
Get the global (world-space) transform.
Definition Node.cpp:125
Rendering pipeline resource.
Definition Pipeline.hpp:122
Abstract base class for rendering backends.
Definition Renderer.hpp:44
virtual void Render(void *aWindowId, const Matrix4x4 &aModelMatrix, const Mesh &aMesh, const Pipeline &aPipeline, const Material *aMaterial=nullptr, const BufferAccessor *aSkeleton=nullptr, Topology aTopology=Topology::TRIANGLE_LIST, uint32_t aVertexStart=0, uint32_t aVertexCount=0xffffffff, uint32_t aInstanceCount=1, uint32_t aFirstInstance=0) const =0
Issues a draw call for a mesh with the given pipeline and optional material.
virtual BufferAccessor AllocateSingleFrameUniformMemory(void *aWindowId, size_t aSize)=0
Allocates uniform buffer memory that is valid for a single frame.
Identifies a resource by its type and path CRC32 hashes.
void Store() const
Construct and store the resource in the cache if not already present.
std::string GetPathString() const
Get the original resource path string from the hash.
Skeletal animation resource containing a hierarchy of joints.
Definition Skeleton.hpp:30
DLL const std::vector< Joint > & GetJoints() const
Get the joint list.
Definition Skeleton.cpp:124
CRC-based compile-time string identifier.
Definition StringId.hpp:31
<- This is here just for the literals
Definition AABB.hpp:31
std::variant< int, long, long long, unsigned, unsigned long, unsigned long long, float, double, std::string, std::filesystem::path > Property
A variant type that can hold any commonly used property value.
Definition Property.hpp:31