Skip to content

Commit a3846ec

Browse files
Radient: add morph target component support
1 parent 67a3209 commit a3846ec

16 files changed

Lines changed: 491 additions & 6 deletions

‎Radient/CMakeLists.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ set(SOURCE
5656
src/Render/Tessera/RadientTesseraSkinData.cpp
5757
src/Scene/Components/RadientMaterialBindingsStorage.cpp
5858
src/Scene/Components/RadientMeshComponentStorage.cpp
59+
src/Scene/Components/RadientMorphComponentStorage.cpp
5960
src/Scene/Components/RadientSkinComponentStorage.cpp
6061
src/Scene/RadientSceneImpl.cpp
6162
src/Scene/RadientSceneState.cpp
@@ -119,6 +120,7 @@ set(INCLUDE
119120
include/Render/Tessera/RadientTesseraMaterialCache.hpp
120121
include/Render/Tessera/RadientTesseraRenderTechnique.hpp
121122
include/Render/Tessera/RadientTesseraSkinData.hpp
123+
include/Scene/Components/RadientMorphComponentStorage.hpp
122124
)
123125

124126
set(INTERFACE
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2026 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#pragma once
28+
29+
#include "RadientMorphTargets.h"
30+
#include "RadientScene.h"
31+
#include "RefCntAutoPtr.hpp"
32+
33+
namespace Diligent
34+
{
35+
36+
struct MorphComponentStorage
37+
{
38+
RadientMorphComponent Component;
39+
RefCntAutoPtr<IRadientMorphTargetWeights> pWeights;
40+
41+
MorphComponentStorage();
42+
43+
MorphComponentStorage(const MorphComponentStorage&) = delete;
44+
MorphComponentStorage& operator=(const MorphComponentStorage&) = delete;
45+
46+
MorphComponentStorage(MorphComponentStorage&& Rhs) noexcept;
47+
MorphComponentStorage& operator=(MorphComponentStorage&& Rhs) noexcept;
48+
49+
void Assign(const RadientMorphComponent& Morph);
50+
51+
private:
52+
void FixupPointers();
53+
};
54+
55+
} // namespace Diligent

‎Radient/include/Scene/RadientSceneImpl.hpp‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ class RadientSceneImpl final : public ObjectBase<IRadientScene>
9595
virtual RADIENT_STATUS DILIGENT_CALL_TYPE GetSkin(RadientEntityID Entity,
9696
RadientSkinComponent& Skin) const override final;
9797

98+
virtual RADIENT_STATUS DILIGENT_CALL_TYPE GetMorph(RadientEntityID Entity,
99+
RadientMorphComponent& Morph) const override final;
100+
98101
virtual RADIENT_STATUS DILIGENT_CALL_TYPE HasComponent(RadientEntityID Entity,
99102
RadientComponentTypeID ComponentType,
100103
Bool& HasComponent) const override final;

‎Radient/include/Scene/RadientSceneState.hpp‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "FlagEnum.h"
3131
#include "Scene/Components/RadientMaterialBindingsStorage.hpp"
3232
#include "Scene/Components/RadientMeshComponentStorage.hpp"
33+
#include "Scene/Components/RadientMorphComponentStorage.hpp"
3334
#include "Scene/Components/RadientSkinComponentStorage.hpp"
3435

3536
#include "entt/entity/registry.hpp"
@@ -70,6 +71,7 @@ class RadientSceneState
7071
const RadientMeshRendererComponent& Renderer;
7172
const RadientMaterialBindingsComponent* pMaterialBindings = nullptr;
7273
const RadientSkinComponent* pSkin = nullptr;
74+
const RadientMorphComponent* pMorph = nullptr;
7375
const RadientMatrix4x4& WorldMatrix;
7476
const Bool& EffectiveVisible;
7577
};
@@ -142,6 +144,7 @@ class RadientSceneState
142144
RADIENT_STATUS GetCachedWorldMatrix(RadientEntityID Entity, RadientMatrix4x4& Matrix) const;
143145
RADIENT_STATUS GetCamera(RadientEntityID Entity, RadientCameraComponent& Camera) const;
144146
RADIENT_STATUS GetSkin(RadientEntityID Entity, RadientSkinComponent& Skin) const;
147+
RADIENT_STATUS GetMorph(RadientEntityID Entity, RadientMorphComponent& Morph) const;
145148
RADIENT_STATUS HasComponent(RadientEntityID Entity, RadientComponentTypeID ComponentType, Bool& HasComponent) const;
146149

147150
const RadientSceneRevisions& GetSceneRevisions() const;
@@ -177,6 +180,7 @@ class RadientSceneState
177180
RADIENT_STATUS SetCamera(RadientEntityID Entity, const RadientCameraComponent& Camera);
178181
RADIENT_STATUS SetMesh(RadientEntityID Entity, const RadientMeshComponent& Mesh);
179182
RADIENT_STATUS SetSkin(RadientEntityID Entity, const RadientSkinComponent& Skin);
183+
RADIENT_STATUS SetMorph(RadientEntityID Entity, const RadientMorphComponent& Morph);
180184
RADIENT_STATUS SetMeshRenderer(RadientEntityID Entity, const RadientMeshRendererComponent& Renderer);
181185
RADIENT_STATUS SetMaterialBindings(RadientEntityID Entity, const RadientMaterialBindingsComponent& Bindings);
182186
RADIENT_STATUS SetLight(RadientEntityID Entity, const RadientLightComponent& Light);
@@ -204,7 +208,7 @@ class RadientSceneState
204208
{
205209
CHANGE_FLAG_NONE = 0u,
206210

207-
// Mesh, mesh renderer, material bindings, or skin changed.
211+
// Mesh, mesh renderer, material bindings, skin, or morph changed.
208212
CHANGE_FLAG_DRAWABLES = 1u << 0u,
209213

210214
// Light component data changed.
@@ -455,13 +459,15 @@ inline RadientSceneState::RenderableMesh RadientSceneState::MakeRenderableMesh(e
455459

456460
const MaterialBindingsStorage* pMaterialBindings = m_Registry.try_get<MaterialBindingsStorage>(Entity);
457461
const SkinComponentStorage* pSkin = m_Registry.try_get<SkinComponentStorage>(Entity);
462+
const MorphComponentStorage* pMorph = m_Registry.try_get<MorphComponentStorage>(Entity);
458463

459464
return RenderableMesh{
460465
EntityData.ID,
461466
MeshStorage.Component,
462467
Renderer,
463468
pMaterialBindings != nullptr ? &pMaterialBindings->Component : nullptr,
464469
pSkin != nullptr ? &pSkin->Component : nullptr,
470+
pMorph != nullptr ? &pMorph->Component : nullptr,
465471
WorldTransform.Matrix,
466472
EffectiveVisible.Visible};
467473
}

‎Radient/include/Scene/RadientSceneWriterImpl.hpp‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ class RadientSceneWriterImpl final : public ObjectBase<IRadientSceneWriter>
7979
virtual RADIENT_STATUS DILIGENT_CALL_TYPE SetSkin(RadientEntityID Entity,
8080
const RadientSkinComponent& Skin) override final;
8181

82+
virtual RADIENT_STATUS DILIGENT_CALL_TYPE SetMorph(RadientEntityID Entity,
83+
const RadientMorphComponent& Morph) override final;
84+
8285
virtual RADIENT_STATUS DILIGENT_CALL_TYPE SetMeshRenderer(RadientEntityID Entity,
8386
const RadientMeshRendererComponent& Renderer) override final;
8487

‎Radient/interface/RadientScene.h‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ typedef struct RadientSceneCreateInfo RadientSceneCreateInfo;
106106
/// Scene revisions grouped by renderer-relevant data category.
107107
struct RadientSceneRevisions
108108
{
109-
/// Mesh, mesh renderer, or material binding data changed.
109+
/// Mesh, mesh renderer, material binding, skin, or morph data changed.
110110
RadientRevision Drawables DEFAULT_INITIALIZER(0);
111111

112112
/// Light component data changed.
@@ -573,6 +573,13 @@ DILIGENT_BEGIN_INTERFACE(IRadientScene, IObject)
573573
RadientEntityID Entity,
574574
RadientSkinComponent REF Skin) CONST PURE;
575575

576+
/// Gets morph component. The returned weights pointer is borrowed from the
577+
/// scene and remains valid until the component is changed or removed. The
578+
/// caller may retain it when a longer lifetime is required.
579+
VIRTUAL RADIENT_STATUS METHOD(GetMorph)(THIS_
580+
RadientEntityID Entity,
581+
RadientMorphComponent REF Morph) CONST PURE;
582+
576583
/// Checks if the entity has the requested component.
577584
VIRTUAL RADIENT_STATUS METHOD(HasComponent)(THIS_
578585
RadientEntityID Entity,
@@ -602,6 +609,7 @@ DILIGENT_END_INTERFACE
602609
# define IRadientScene_GetCachedWorldMatrix(This, ...) CALL_IFACE_METHOD(RadientScene, GetCachedWorldMatrix, This, __VA_ARGS__)
603610
# define IRadientScene_GetCamera(This, ...) CALL_IFACE_METHOD(RadientScene, GetCamera, This, __VA_ARGS__)
604611
# define IRadientScene_GetSkin(This, ...) CALL_IFACE_METHOD(RadientScene, GetSkin, This, __VA_ARGS__)
612+
# define IRadientScene_GetMorph(This, ...) CALL_IFACE_METHOD(RadientScene, GetMorph, This, __VA_ARGS__)
605613
# define IRadientScene_HasComponent(This, ...) CALL_IFACE_METHOD(RadientScene, HasComponent, This, __VA_ARGS__)
606614
# define IRadientScene_GetSceneRevisions(This) CALL_IFACE_METHOD(RadientScene, GetSceneRevisions, This)
607615

‎Radient/interface/RadientSceneWriter.h‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ DILIGENT_BEGIN_INTERFACE(IRadientSceneWriter, IObject)
9090
RadientEntityID Entity,
9191
const RadientCameraComponent REF Camera) PURE;
9292

93-
/// Adds or updates a mesh component.
93+
/// Adds or updates a mesh component. Replacing the mesh removes an existing
94+
/// morph component if its weights belong to a different mesh.
9495
VIRTUAL RADIENT_STATUS METHOD(SetMesh)(THIS_
9596
RadientEntityID Entity,
9697
const RadientMeshComponent REF Mesh) PURE;
@@ -100,6 +101,12 @@ DILIGENT_BEGIN_INTERFACE(IRadientSceneWriter, IObject)
100101
RadientEntityID Entity,
101102
const RadientSkinComponent REF Skin) PURE;
102103

104+
/// Adds or updates a morph component. The weights must belong to the mesh
105+
/// currently assigned to the entity.
106+
VIRTUAL RADIENT_STATUS METHOD(SetMorph)(THIS_
107+
RadientEntityID Entity,
108+
const RadientMorphComponent REF Morph) PURE;
109+
103110
/// Adds or updates a mesh renderer component.
104111
VIRTUAL RADIENT_STATUS METHOD(SetMeshRenderer)(THIS_
105112
RadientEntityID Entity,
@@ -144,6 +151,7 @@ DILIGENT_END_INTERFACE
144151
# define IRadientSceneWriter_SetCamera(This, ...) CALL_IFACE_METHOD(RadientSceneWriter, SetCamera, This, __VA_ARGS__)
145152
# define IRadientSceneWriter_SetMesh(This, ...) CALL_IFACE_METHOD(RadientSceneWriter, SetMesh, This, __VA_ARGS__)
146153
# define IRadientSceneWriter_SetSkin(This, ...) CALL_IFACE_METHOD(RadientSceneWriter, SetSkin, This, __VA_ARGS__)
154+
# define IRadientSceneWriter_SetMorph(This, ...) CALL_IFACE_METHOD(RadientSceneWriter, SetMorph, This, __VA_ARGS__)
147155
# define IRadientSceneWriter_SetMeshRenderer(This, ...) CALL_IFACE_METHOD(RadientSceneWriter, SetMeshRenderer, This, __VA_ARGS__)
148156
# define IRadientSceneWriter_SetMaterialBindings(This, ...) CALL_IFACE_METHOD(RadientSceneWriter, SetMaterialBindings, This, __VA_ARGS__)
149157
# define IRadientSceneWriter_SetLight(This, ...) CALL_IFACE_METHOD(RadientSceneWriter, SetLight, This, __VA_ARGS__)

‎Radient/interface/RadientTypes.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ static DILIGENT_CONSTEXPR RadientComponentTypeID RADIENT_COMPONENT_TYPE_MESH_REN
125125
static DILIGENT_CONSTEXPR RadientComponentTypeID RADIENT_COMPONENT_TYPE_LIGHT = 5;
126126
static DILIGENT_CONSTEXPR RadientComponentTypeID RADIENT_COMPONENT_TYPE_MATERIAL_BINDINGS = 6;
127127
static DILIGENT_CONSTEXPR RadientComponentTypeID RADIENT_COMPONENT_TYPE_SKIN = 7;
128+
static DILIGENT_CONSTEXPR RadientComponentTypeID RADIENT_COMPONENT_TYPE_MORPH = 8;
128129

129130
/// Asset reference used by scenes, components, and render features.
130131
struct RadientAssetReference
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2026 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#include "Scene/Components/RadientMorphComponentStorage.hpp"
28+
29+
#include <utility>
30+
31+
namespace Diligent
32+
{
33+
34+
MorphComponentStorage::MorphComponentStorage() = default;
35+
36+
MorphComponentStorage::MorphComponentStorage(MorphComponentStorage&& Rhs) noexcept :
37+
Component{Rhs.Component},
38+
pWeights{std::move(Rhs.pWeights)}
39+
{
40+
FixupPointers();
41+
Rhs.Component = {};
42+
}
43+
44+
MorphComponentStorage& MorphComponentStorage::operator=(MorphComponentStorage&& Rhs) noexcept
45+
{
46+
if (this != &Rhs)
47+
{
48+
Component = Rhs.Component;
49+
pWeights = std::move(Rhs.pWeights);
50+
FixupPointers();
51+
Rhs.Component = {};
52+
}
53+
54+
return *this;
55+
}
56+
57+
void MorphComponentStorage::Assign(const RadientMorphComponent& Morph)
58+
{
59+
Component = Morph;
60+
pWeights = Morph.pWeights;
61+
FixupPointers();
62+
}
63+
64+
void MorphComponentStorage::FixupPointers()
65+
{
66+
Component.pWeights = pWeights;
67+
}
68+
69+
} // namespace Diligent

‎Radient/src/Scene/RadientSceneImpl.cpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ RADIENT_STATUS RadientSceneImpl::GetSkin(RadientEntityID Entity, RadientSkinComp
125125
return m_pState->GetSkin(Entity, Skin);
126126
}
127127

128+
RADIENT_STATUS RadientSceneImpl::GetMorph(RadientEntityID Entity, RadientMorphComponent& Morph) const
129+
{
130+
return m_pState->GetMorph(Entity, Morph);
131+
}
132+
128133
RADIENT_STATUS RadientSceneImpl::HasComponent(RadientEntityID Entity, RadientComponentTypeID ComponentType, Bool& HasComponent) const
129134
{
130135
return m_pState->HasComponent(Entity, ComponentType, HasComponent);

0 commit comments

Comments
 (0)