Skip to content

Commit cb3d6bc

Browse files
committed
Documentation for gltf animation; use scod to generate docs
1 parent 55fe358 commit cb3d6bc

3 files changed

Lines changed: 141 additions & 12 deletions

File tree

dub.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,7 @@
6060
"extensions/nuklear",
6161
"extensions/physfs",
6262
"init-exec"
63-
]
63+
],
64+
65+
"-ddoxTool": "scod"
6466
}

src/dagon/core/package.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ DEALINGS IN THE SOFTWARE.
2828
/**
2929
* Provides the core modules and foundational utilities for Dagon applications.
3030
*
31+
* Description:
3132
* The `dagon.core` package includes modules for application management,
3233
* configuration, event handling, input, key codes, locale detection, logging,
3334
* persistent storage, property system, time management, virtual file system,

src/dagon/resource/gltf/animation.d

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
2424
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2525
DEALINGS IN THE SOFTWARE.
2626
*/
27+
28+
/**
29+
* GLTF 2.0 animation.
30+
*
31+
* The `dagon.resource.gltf.animation` module defines classes for representing
32+
* and evaluating GLTF animation samplers, channels, and animation clips.
33+
* Animation playback, blending, and update logic are included.
34+
*
35+
* Copyright: Denis Feklushkin, Timur Gafarov 2025
36+
* License: $(LINK2 https://boost.org/LICENSE_1_0.txt, Boost License 1.0).
37+
* Authors: Denis Feklushkin, Timur Gafarov
38+
*/
2739
module dagon.resource.gltf.animation;
2840

2941
import std.stdio;
@@ -45,31 +57,49 @@ import dagon.resource.gltf.accessor;
4557
import dagon.resource.gltf.node;
4658
import dagon.resource.gltf.skin;
4759

60+
/**
61+
* Interpolation types supported by GLTF animation samplers.
62+
*/
4863
enum InterpolationType: string
4964
{
5065
Linear = "LINEAR",
5166
Step = "STEP",
5267
CubicSpline = "CUBICSPLINE"
5368
}
5469

70+
/**
71+
* Animation target property types (translation, rotation, scale).
72+
*/
5573
enum TRSType: string
5674
{
5775
Translation = "translation",
5876
Rotation = "rotation",
5977
Scale = "scale",
6078
}
6179

80+
/**
81+
* Represents a GLTF animation sampler, which defines keyframe times,
82+
* values, and interpolation.
83+
*/
6284
class GLTFAnimationSampler: Owner
6385
{
64-
InterpolationType interpolation; // optional, LINEAR by default
65-
GLTFAccessor input; // required, contains times (in seconds) for each keyframe.
66-
GLTFAccessor output; // required, contains values (of any Accessor.Type) for the animated property at each keyframe.
86+
/// Interpolation type (linear, step, cubic spline). Only LINEAR is supported at the moment
87+
InterpolationType interpolation;
88+
89+
/// Accessor for keyframe times (in seconds).
90+
GLTFAccessor input;
91+
92+
/// Accessor for keyframe values.
93+
GLTFAccessor output;
6794

6895
this(Owner o)
6996
{
7097
super(o);
7198
}
7299

100+
/**
101+
* Returns the duration of the animation sampler in seconds.
102+
*/
73103
float duration()
74104
{
75105
const timeline = input.getSlice!float;
@@ -79,7 +109,17 @@ class GLTFAnimationSampler: Owner
79109
return 0.0f;
80110
}
81111

82-
/// Returns: beginning translation sample number
112+
/**
113+
* Finds the keyframe sample indices and times for a given animation time.
114+
*
115+
* Params:
116+
* t = Current animation time.
117+
* previousTime = Output: previous keyframe time.
118+
* nextTime = Output: next keyframe time.
119+
* loopTime = Output: wrapped time within the animation duration.
120+
* Returns:
121+
* Index of the previous keyframe.
122+
*/
83123
size_t getSampleByTime(in Time t, out float previousTime, out float nextTime, out float loopTime)
84124
{
85125
assert(input.dataType == GLTFDataType.Scalar);
@@ -122,22 +162,38 @@ class GLTFAnimationSampler: Owner
122162
}
123163
}
124164

165+
/**
166+
* Represents a GLTF animation channel, which targets a node and property (TRS).
167+
*/
125168
class GLTFAnimationChannel: Owner
126169
{
127-
GLTFAnimationSampler sampler; // required
128-
TRSType targetPath; // required
129-
GLTFNode targetNode; // optional: When undefined, the animated object MAY be defined by an extension.
170+
/// The animation sampler for this channel.
171+
GLTFAnimationSampler sampler;
172+
173+
/// The property being animated (translation, rotation, scale).
174+
TRSType targetPath;
175+
176+
/// The node being animated.
177+
GLTFNode targetNode;
130178

131179
this(Owner o)
132180
{
133181
super(o);
134182
}
135183
}
136184

185+
/**
186+
* Represents a GLTF animation clip, containing samplers and channels.
187+
*/
137188
class GLTFAnimation: Owner
138189
{
190+
/// Animation name.
139191
string name;
192+
193+
/// Animation samplers.
140194
Array!GLTFAnimationSampler samplers;
195+
196+
/// Animation channels.
141197
Array!GLTFAnimationChannel channels;
142198

143199
this(Owner o)
@@ -151,6 +207,9 @@ class GLTFAnimation: Owner
151207
channels.free();
152208
}
153209

210+
/**
211+
* Returns the duration of the animation in seconds.
212+
*/
154213
float duration()
155214
{
156215
float d = 0.0f;
@@ -162,10 +221,18 @@ class GLTFAnimation: Owner
162221
}
163222
}
164223

224+
/**
225+
* `Entity`` component for playing a GLTF animation on an entity.
226+
*/
165227
class GLTFAnimationComponent: EntityComponent
166228
{
229+
/// The animation to play.
167230
GLTFAnimation animation;
231+
232+
/// Current animation time.
168233
Time time;
234+
235+
/// True if the animation is playing.
169236
bool playing;
170237

171238
this(EventManager em, Entity e, GLTFAnimation animation, bool playing = false)
@@ -177,21 +244,25 @@ class GLTFAnimationComponent: EntityComponent
177244
e.transformMode = TransformMode.Matrix;
178245
}
179246

247+
/// Starts animation playback.
180248
void play()
181249
{
182250
playing = true;
183251
}
184252

253+
/// Pauses animation playback.
185254
void pause()
186255
{
187256
playing = false;
188257
}
189258

259+
/// Resets animation time to zero.
190260
void reset()
191261
{
192262
time.elapsed = 0;
193263
}
194264

265+
/// Updates the animation and applies transforms to the entity.
195266
override void update(Time t)
196267
{
197268
if (playing)
@@ -246,9 +317,15 @@ class GLTFAnimationComponent: EntityComponent
246317
}
247318
}
248319

320+
/**
321+
* GPU skinning pose for a GLTF skin and animation.
322+
*/
249323
class GLTFPose: Pose
250324
{
325+
/// The GLTFSkin being posed.
251326
GLTFSkin skin;
327+
328+
/// The animation to play.
252329
GLTFAnimation animation;
253330

254331
this(GLTFSkin skin, Owner o)
@@ -270,6 +347,7 @@ class GLTFPose: Pose
270347
Delete(boneMatrices);
271348
}
272349

350+
/// Updates the pose for the current animation time.
273351
override void update(Time t)
274352
{
275353
if (playing)
@@ -350,41 +428,65 @@ class GLTFPose: Pose
350428
}
351429
}
352430

431+
/**
432+
* TRS (Translation, Rotation, Scale) structure for joint transforms.
433+
*/
353434
struct TRS
354435
{
355436
Vector3f translation;
356437
Quaternionf rotation;
357438
Vector3f scaling;
358439
}
359440

441+
/**
442+
* Animation playback mode (loop or once).
443+
*/
360444
enum PlayMode
361445
{
362446
Loop,
363447
Once
364448
}
365449

366-
/*
367-
* A Pose that supports smooth transition between animations
450+
/**
451+
* A pose that supports smooth blending between GLTF animations.
368452
*/
369453
class GLTFBlendedPose: Pose
370454
{
455+
/// The GLTFSkin being posed.
371456
GLTFSkin skin;
372457

458+
/// Current TRS pose for each joint.
373459
TRS[] currentPose;
460+
461+
/// Next TRS pose for blending.
374462
TRS[] nextPose;
375463

464+
/// Previous animation.
376465
GLTFAnimation previousAnimation;
466+
467+
/// Current animation.
377468
GLTFAnimation animation;
469+
470+
/// Next animation.
378471
GLTFAnimation nextAnimation;
472+
473+
/// Blend factor between animations.
379474
float blendAlpha = 0.0f;
475+
476+
/// Blend speed.
380477
float blendSpeed = 0.0f;
478+
381479
float previousBlendSpeed = 0.0f;
480+
481+
/// Duration of the current animation.
382482
float animationDuration = 0.0f;
483+
484+
/// Playback mode (loop or once).
383485
PlayMode playMode = PlayMode.Loop;
384486

385-
this(GLTFSkin skin, Owner o)
487+
this(GLTFSkin skin, Owner owner)
386488
{
387-
super(o);
489+
super(owner);
388490
this.skin = skin;
389491

390492
if (skin.joints.length)
@@ -408,6 +510,14 @@ class GLTFBlendedPose: Pose
408510
Delete(nextPose);
409511
}
410512

513+
/**
514+
* Applies an animation to the pose at a given time.
515+
*
516+
* Params:
517+
* anim = The animation to apply.
518+
* time = The animation time.
519+
* outPose = Output array of TRS for each joint.
520+
*/
411521
void applyAnimation(GLTFAnimation anim, Time time, TRS[] outPose)
412522
{
413523
if (anim)
@@ -471,6 +581,13 @@ class GLTFBlendedPose: Pose
471581
}
472582
}
473583

584+
/**
585+
* Switches to a new animation immediately.
586+
*
587+
* Params:
588+
* anim = The new animation.
589+
* playMode = Playback mode (loop or once).
590+
*/
474591
void switchToAnimation(GLTFAnimation anim, PlayMode playMode = PlayMode.Loop)
475592
{
476593
if (anim !is animation)
@@ -483,6 +600,14 @@ class GLTFBlendedPose: Pose
483600
}
484601
}
485602

603+
/**
604+
* Switches to a new animation smoothly.
605+
*
606+
* Params:
607+
* anim = The new animation.
608+
* transitionDuration = Duration of the blend (optional).
609+
* playMode = Playback mode (loop or once).
610+
*/
486611
void switchToAnimation(GLTFAnimation anim, float transitionDuration, PlayMode playMode = PlayMode.Loop)
487612
{
488613
if (anim !is animation)
@@ -498,6 +623,7 @@ class GLTFBlendedPose: Pose
498623
}
499624
}
500625

626+
/// Updates the blended pose and applies transforms to the skin.
501627
override void update(Time t)
502628
{
503629
applyAnimation(animation, time, currentPose);

0 commit comments

Comments
 (0)