Skip to content

Commit a3d588d

Browse files
Merge pull request #67 from Devsh-Graphics-Programming/animations
Skeletons, Skins, Keyframes and Animation Library
2 parents cdc5f58 + 4316c44 commit a3d588d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2709
-2735
lines changed

examples_tests/04.Keyframe/main.cpp

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,70 @@ int main()
9090
auto* smgr = device->getSceneManager();
9191

9292
//
93-
core::smart_refctd_ptr<video::IGPUMeshBuffer> mb;
93+
asset::SBufferBinding<asset::ICPUBuffer> inverseBindPoses,jointAABBs;
94+
core::smart_refctd_ptr<asset::ICPUSkeleton> skeleton;
95+
{
96+
constexpr uint32_t kJointCount = 2u;
97+
asset::SBufferBinding<asset::ICPUBuffer> parentIDs,defaultTransforms,inverseBindPoses,jointAABBs;
98+
{
99+
parentIDs.buffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(asset::ICPUSkeleton)*kJointCount);
100+
{
101+
asset::ICPUSkeleton::joint_id_t parentJointIDs[] = { asset::ICPUSkeleton::invalid_joint_id,0u };
102+
memcpy(parentIDs.buffer->getPointer(),parentJointIDs,sizeof(parentJointIDs));
103+
}
104+
defaultTransforms.buffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(matrix3x4SIMD)*kJointCount);
105+
inverseBindPoses.buffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(matrix3x4SIMD)*kJointCount);
106+
{
107+
auto* dftTransforms = reinterpret_cast<matrix3x4SIMD*>(defaultTransforms.buffer->getPointer());
108+
auto* invBindPoses = reinterpret_cast<matrix3x4SIMD*>(inverseBindPoses.buffer->getPointer());
109+
for (auto i=0u; i<kJointCount; i++)
110+
{
111+
dftTransforms[i] = matrix3x4SIMD();
112+
dftTransforms[i].setTranslation(core::vectorSIMDf(0.f,float(i)*2.f-1.f,0.f));
113+
dftTransforms[i].getInverse(invBindPoses[i]);
114+
}
115+
}
116+
jointAABBs.buffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(aabbox3df)*kJointCount);
117+
}
118+
const char* jointNames[] = {"root","bendy"};
119+
skeleton = core::make_smart_refctd_ptr<asset::ICPUSkeleton>(std::move(parentIDs),std::move(defaultTransforms),&jointNames[0],&jointNames[0]+kJointCount);
120+
}
121+
core::smart_refctd_ptr<video::IGPUAnimationLibrary> gpuanimations;
122+
{
123+
constexpr uint32_t kKeyframeCount = 16u;
124+
constexpr uint32_t kAnimationCount = 3u;
125+
core::smart_refctd_ptr<asset::ICPUAnimationLibrary> animations;
126+
{
127+
asset::SBufferBinding<asset::ICPUBuffer> keyframes = {0ull,core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(asset::ICPUAnimationLibrary::Keyframe)*kKeyframeCount)};
128+
asset::SBufferBinding<asset::ICPUBuffer> timestamps = {0ull,core::make_smart_refctd_ptr<asset::ICPUBuffer>(sizeof(asset::ICPUAnimationLibrary::timestamp_t)*kKeyframeCount)};
129+
asset::SBufferRange<asset::ICPUBuffer> namedAnims;
130+
namedAnims.offset = 0ull;
131+
namedAnims.size = sizeof(asset::ICPUAnimationLibrary::Animation)*kAnimationCount;
132+
namedAnims.buffer = core::make_smart_refctd_ptr<asset::ICPUBuffer>(namedAnims.size);
133+
animations = core::make_smart_refctd_ptr<asset::ICPUAnimationLibrary>(std::move(keyframes),std::move(timestamps),kKeyframeCount,std::move(namedAnims));
134+
}
135+
{
136+
const uint32_t animationOffsets[] = { 0u,1u,2u };
137+
const asset::ICPUAnimationLibrary::Animation anims[] = {
138+
{0u,kKeyframeCount,asset::ICPUAnimationLibrary::Animation::EIM_NEAREST},
139+
{0u,kKeyframeCount,asset::ICPUAnimationLibrary::Animation::EIM_LINEAR},
140+
{0u,kKeyframeCount,asset::ICPUAnimationLibrary::Animation::EIM_CUBIC},
141+
};
142+
for (auto i=0u; i<kAnimationCount; i++)
143+
animations->getAnimation(animationOffsets[i]) = anims[i];
144+
const char* animationNames[] = { "moveNearest","moveLinear","moveCubic" };
145+
animations->addAnimationNames(animationNames,animationNames+kAnimationCount,animationOffsets);
146+
147+
for (auto i=0u; i<kAnimationCount; i++)
148+
{
149+
assert(animations->getAnimationOffsetFromName(animationNames[i]) == animationOffsets[i]);
150+
}
151+
}
152+
gpuanimations = driver->getGPUObjectsFromAssets<asset::ICPUAnimationLibrary>(&animations,&animations+1u)->begin()[0];
153+
}
154+
155+
//
156+
core::smart_refctd_ptr<video::IGPUMeshBuffer> gpumb;
94157
{
95158
VertexStruct vertices[8];
96159
vertices[0] = VertexStruct{{-1.f,-1.f,-1.f},{ 0, 0}};
@@ -101,6 +164,8 @@ int main()
101164
vertices[5] = VertexStruct{{ 1.f,-1.f, 1.f},{255,127}};
102165
vertices[6] = VertexStruct{{-1.f, 1.f, 1.f},{ 0,255}};
103166
vertices[7] = VertexStruct{{ 1.f, 1.f, 1.f},{127,255}};
167+
asset::SBufferBinding<asset::ICPUBuffer> bindings[asset::ICPUMeshBuffer::MAX_ATTR_BUF_BINDING_COUNT];
168+
bindings[0u] = {0u,core::make_smart_refctd_ptr<asset::CCustomAllocatorCPUBuffer<core::null_allocator<uint8_t>>>(sizeof(vertices),vertices,core::adopt_memory)};
104169

105170
uint16_t indices_indexed16[] =
106171
{
@@ -111,27 +176,28 @@ int main()
111176
0,2,4,2,4,6,
112177
1,3,5,3,5,7
113178
};
179+
asset::SBufferBinding<asset::ICPUBuffer> indexBinding{0u,core::make_smart_refctd_ptr<asset::CCustomAllocatorCPUBuffer<core::null_allocator<uint8_t>>>(sizeof(indices_indexed16),indices_indexed16,core::adopt_memory)};
114180

115181
asset::SPushConstantRange range[1] = {asset::ISpecializedShader::ESS_VERTEX,0u,sizeof(core::matrix4SIMD)};
116182

117-
auto createGPUSpecializedShaderFromSource = [=](const char* source, asset::ISpecializedShader::E_SHADER_STAGE stage)
183+
auto createSpecializedShaderFromSource = [=](const char* source, asset::ISpecializedShader::E_SHADER_STAGE stage)
118184
{
119185
auto spirv = device->getAssetManager()->getGLSLCompiler()->createSPIRVFromGLSL(source, stage, "main", "runtimeID");
120-
auto unspec = driver->createGPUShader(std::move(spirv));
121-
return driver->createGPUSpecializedShader(unspec.get(), { nullptr,nullptr,"main",stage });
186+
return core::make_smart_refctd_ptr<asset::ICPUSpecializedShader>(std::move(spirv),asset::ICPUSpecializedShader::SInfo{ nullptr,nullptr,"main",stage });
122187
};
123188
// origFilepath is only relevant when you have filesystem #includes in your shader
124-
auto createGPUSpecializedShaderFromSourceWithIncludes = [&](const char* source, asset::ISpecializedShader::E_SHADER_STAGE stage, const char* origFilepath)
189+
auto createSpecializedShaderFromSourceWithIncludes = [&](const char* source, asset::ISpecializedShader::E_SHADER_STAGE stage, const char* origFilepath)
125190
{
126191
auto resolved_includes = device->getAssetManager()->getGLSLCompiler()->resolveIncludeDirectives(source, stage, origFilepath);
127-
return createGPUSpecializedShaderFromSource(reinterpret_cast<const char*>(resolved_includes->getSPVorGLSL()->getPointer()), stage);
192+
return createSpecializedShaderFromSource(reinterpret_cast<const char*>(resolved_includes->getSPVorGLSL()->getPointer()), stage);
128193
};
129-
core::smart_refctd_ptr<video::IGPUSpecializedShader> shaders[2] =
194+
constexpr uint32_t kShaderCount = 2u;
195+
core::smart_refctd_ptr<asset::ICPUSpecializedShader> shaders[kShaderCount] =
130196
{
131-
createGPUSpecializedShaderFromSourceWithIncludes(vertexSource,asset::ISpecializedShader::ESS_VERTEX, "shader.vert"),
132-
createGPUSpecializedShaderFromSource(fragmentSource,asset::ISpecializedShader::ESS_FRAGMENT)
197+
createSpecializedShaderFromSourceWithIncludes(vertexSource,asset::ISpecializedShader::ESS_VERTEX, "shader.vert"),
198+
createSpecializedShaderFromSource(fragmentSource,asset::ISpecializedShader::ESS_FRAGMENT)
133199
};
134-
auto shadersPtr = reinterpret_cast<video::IGPUSpecializedShader**>(shaders);
200+
auto shadersPtr = reinterpret_cast<asset::ICPUSpecializedShader**>(shaders);
135201

136202
asset::SVertexInputParams inputParams;
137203
inputParams.enabledAttribFlags = 0b11u;
@@ -152,17 +218,19 @@ int main()
152218
asset::SStencilOpParams defaultStencil;
153219
asset::SRasterizationParams rasterParams;
154220
rasterParams.faceCullingMode = asset::EFCM_NONE;
155-
auto pipeline = driver->createGPURenderpassIndependentPipeline( nullptr,driver->createGPUPipelineLayout(range,range+1u,nullptr,nullptr,nullptr,nullptr),
156-
shadersPtr,shadersPtr+sizeof(shaders)/sizeof(core::smart_refctd_ptr<video::IGPUSpecializedShader>),
157-
inputParams,blendParams,assemblyParams,rasterParams);
158-
159-
asset::SBufferBinding<video::IGPUBuffer> bindings[video::IGPUMeshBuffer::MAX_ATTR_BUF_BINDING_COUNT];
160-
bindings[0u] = {0u,driver->createFilledDeviceLocalGPUBufferOnDedMem(sizeof(vertices),vertices)};
161-
mb = core::make_smart_refctd_ptr<video::IGPUMeshBuffer>(std::move(pipeline),nullptr,bindings,asset::SBufferBinding<video::IGPUBuffer>{0u,driver->createFilledDeviceLocalGPUBufferOnDedMem(sizeof(indices_indexed16),indices_indexed16)});
221+
auto pipeline = core::make_smart_refctd_ptr<asset::ICPURenderpassIndependentPipeline>(
222+
core::make_smart_refctd_ptr<asset::ICPUPipelineLayout>(range,range+1u,nullptr,nullptr,nullptr,nullptr),
223+
shadersPtr,shadersPtr+kShaderCount,
224+
inputParams,blendParams,assemblyParams,rasterParams
225+
);
226+
227+
auto mb = core::make_smart_refctd_ptr<asset::ICPUMeshBuffer>(std::move(pipeline),nullptr,bindings,std::move(indexBinding));
162228
{
229+
mb->setSkin(std::move(inverseBindPoses),std::move(jointAABBs),std::move(skeleton),1u);
163230
mb->setIndexType(asset::EIT_16BIT);
164231
mb->setIndexCount(2*3*6);
165232
}
233+
gpumb = driver->getGPUObjectsFromAssets<asset::ICPUMeshBuffer>(&mb,&mb+1u)->begin()[0];
166234
}
167235

168236

@@ -187,9 +255,9 @@ int main()
187255

188256
//! Stress test for memleaks aside from demo how to create meshes that live on the GPU RAM
189257
{
190-
driver->bindGraphicsPipeline(mb->getPipeline());
191-
driver->pushConstants(mb->getPipeline()->getLayout(), asset::ISpecializedShader::ESS_VERTEX, 0u, sizeof(core::matrix4SIMD), mvp.pointer());
192-
driver->drawMeshBuffer(mb.get());
258+
driver->bindGraphicsPipeline(gpumb->getPipeline());
259+
driver->pushConstants(gpumb->getPipeline()->getLayout(), asset::ISpecializedShader::ESS_VERTEX, 0u, sizeof(core::matrix4SIMD), mvp.pointer());
260+
driver->drawMeshBuffer(gpumb.get());
193261
}
194262
driver->endScene();
195263

examples_tests/18.MitsubaLoader/main.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ int main()
213213

214214
auto serializedLoader = core::make_smart_refctd_ptr<nbl::ext::MitsubaLoader::CSerializedLoader>(am);
215215
auto mitsubaLoader = core::make_smart_refctd_ptr<nbl::ext::MitsubaLoader::CMitsubaLoader>(am,fs);
216+
serializedLoader->initialize();
217+
mitsubaLoader->initialize();
216218
am->addAssetLoader(std::move(serializedLoader));
217219
am->addAssetLoader(std::move(mitsubaLoader));
218220

@@ -327,7 +329,11 @@ int main()
327329
// look out for this!!!
328330
// when added, CMitsubaLoader inserts its own include loader into GLSLCompiler
329331
// thats why i have to add it again here (after device recreation) to be able to compile shaders
330-
am->addAssetLoader(core::make_smart_refctd_ptr<nbl::ext::MitsubaLoader::CMitsubaLoader>(am, device->getFileSystem()));
332+
{
333+
auto mitsubaLoader = core::make_smart_refctd_ptr<nbl::ext::MitsubaLoader::CMitsubaLoader>(am, fs);
334+
mitsubaLoader->initialize();
335+
am->addAssetLoader(std::move(mitsubaLoader));
336+
}
331337

332338
core::smart_refctd_ptr<asset::ICPUDescriptorSetLayout> ds2layout;
333339
{

include/ISceneManager.h

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@ namespace scene
3434
class IDummyTransformationSceneNode;
3535
class IMeshLoader;
3636
class IMeshSceneNode;
37-
class IMeshSceneNodeInstanced;
3837
class IMeshWriter;
3938
class ISceneNode;
4039
class ISceneNodeAnimator;
41-
class ISceneNodeAnimatorCollisionResponse;
4240

4341
//! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff.
4442
/** All Scene nodes can be created only here. There is a always growing
@@ -183,25 +181,6 @@ namespace scene
183181
float jumpSpeed = 0.f, bool invertMouse=false,
184182
bool makeActive=true) = 0;
185183

186-
//! Adds a dummy transformation scene node to the scene tree.
187-
/** This scene node does not render itself, have a bounding box, a render method,
188-
and is as-if always visible ISceneNode.
189-
Its actually a base of ISceneNode, and it can be used for doing advanced transformations
190-
or structuring the scene tree.
191-
\return Pointer to the created scene node.
192-
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
193-
virtual IDummyTransformationSceneNode* addDummyTransformationSceneNode(
194-
IDummyTransformationSceneNode* parent=0, int32_t id=-1) = 0;
195-
196-
//! Gets the root scene node.
197-
/** This is the scene node which is parent
198-
of all scene nodes. The root scene node is a special scene node which
199-
only exists to manage all scene nodes. It will not be rendered and cannot
200-
be removed from the scene.
201-
\return Pointer to the root scene node.
202-
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
203-
virtual ISceneNode* getRootSceneNode() = 0;
204-
205184
//! Get the current active camera.
206185
/** \return The active camera is returned. Note that this can
207186
be NULL, if there was no camera created yet.
@@ -213,17 +192,6 @@ namespace scene
213192
\param camera: The new camera which should be active. */
214193
virtual void setActiveCamera(ICameraSceneNode* camera) = 0;
215194

216-
//! Adds a scene node to the deletion queue.
217-
/** The scene node is immediatly
218-
deleted when it's secure. Which means when the scene node does not
219-
execute animators and things like that. This method is for example
220-
used for deleting scene nodes by their scene node animators. In
221-
most other cases, a ISceneNode::remove() call is enough, using this
222-
deletion queue is not necessary.
223-
See ISceneManager::createDeleteAnimator() for details.
224-
\param node: Node to detete. */
225-
virtual void addToDeletionQueue(IDummyTransformationSceneNode* node) = 0;
226-
227195
//! Posts an input event to the environment.
228196
/** Usually you do not have to
229197
use this method, it is used by the internal engine. */

include/ISceneNode.h

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace scene
3939
const core::vector3df& rotation = core::vector3df(0,0,0),
4040
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f))
4141
: IDummyTransformationSceneNode(parent,position,rotation,scale),
42-
AutomaticCullingState(true), IsVisible(true), renderPriority(0x80000000u)
42+
AutomaticCullingState(true), IsVisible(true)
4343
{
4444
}
4545

@@ -61,31 +61,6 @@ namespace scene
6161
virtual void render() = 0;
6262

6363

64-
//! Get the axis aligned, not transformed bounding box of this node.
65-
/** This means that if this node is an animated 3d character,
66-
moving in a room, the bounding box will always be around the
67-
origin. To get the box in real world coordinates, just
68-
transform it with the matrix you receive with
69-
getAbsoluteTransformation() or simply use
70-
getTransformedBoundingBox(), which does the same.
71-
\return The non-transformed bounding box. */
72-
virtual const core::aabbox3d<float>& getBoundingBox() = 0;
73-
74-
75-
//! Get the axis aligned, transformed and animated absolute bounding box of this node.
76-
/** \return The transformed bounding box. */
77-
virtual const core::aabbox3d<float> getTransformedBoundingBox()
78-
{
79-
core::aabbox3d<float> box = getBoundingBox();
80-
AbsoluteTransformation.transformBoxEx(box);
81-
return box;
82-
}
83-
84-
inline const uint32_t& getRenderPriorityScore() const {return renderPriority;}
85-
86-
inline void setRenderPriorityScore(const uint32_t& nice) {renderPriority = nice;}
87-
88-
8964
//! Returns whether the node should be visible (only matters if all of its parents are visible).
9065
/** This is only an option set by the user, but has nothing to
9166
do with geometry culling
@@ -126,8 +101,6 @@ namespace scene
126101
//! Is the node visible?
127102
bool IsVisible;
128103

129-
uint32_t renderPriority;
130-
131104
static void OnAnimate_static(IDummyTransformationSceneNode* node, uint32_t timeMs) // could be pushed up to IDummyTransformationSceneNode
132105
{
133106
ISceneNode* tmp = static_cast<ISceneNode*>(node);

0 commit comments

Comments
 (0)