summaryrefslogtreecommitdiff
path: root/gfx/include/gfx/scene/animation.h
blob: d95b895533a6f25799385706a44a9f0967e59769 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#pragma once

#include "node.h"
#include "object.h"
#include <gfx/sizes.h>

#include <cstring.h>
#include <math/aabb3.h>
#include <math/defs.h>
#include <math/mat4.h>
#include <math/quat.h>
#include <math/vec3.h>

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

typedef struct Buffer    Buffer;
typedef struct SceneNode SceneNode;

typedef struct Anima    Anima;
typedef struct Joint    Joint;
typedef struct Skeleton Skeleton;

/// Index type used to store relative indices into arrays.
typedef uint16_t joint_idx;

/// Index value denoting no index.
static const joint_idx INDEX_NONE = (joint_idx)-1;

typedef struct Box {
  vec3 vertices[8];
} Box;

/// Joint descriptor.
typedef struct JointDesc {
  joint_idx parent;      /// Parent Joint; index into Anima's joints.
  mat4  inv_bind_matrix; /// Transforms the mesh into the joint's local space.
  aabb3 box;             /// Bounding box.
} JointDesc;

/// Skeleton descriptor.
typedef struct SkeletonDesc {
  size_t    num_joints;
  joint_idx joints[GFX_MAX_NUM_JOINTS]; /// Indices into Anima's joints array.
} SkeletonDesc;

/// Animation interpolation mode.
typedef enum AnimationInterpolation {
  StepInterpolation,
  LinearInterpolation,
  CubicSplineInterpolation
} AnimationInterpolation;

/// The kind of transformation applied by a Channel.
typedef enum ChannelType {
  RotationChannel,
  ScaleChannel,
  TranslationChannel,
  WeightsChannel
} ChannelType;

/// Animation keyframe descriptor.
///
/// The arrays should have as many entries as 'num_joints' in the SkeletonDesc.
typedef struct KeyframeDesc {
  R time; // Start time in [0, end animation time]
  union {
    vec3 translation;
    quat rotation;
  };
} KeyframeDesc;

/// Animation channel descriptor.
typedef struct ChannelDesc {
  joint_idx              target; /// Index into Anima's joints array.
  ChannelType            type;
  AnimationInterpolation interpolation;
  size_t                 num_keyframes;
  KeyframeDesc           keyframes[GFX_MAX_NUM_KEYFRAMES];
} ChannelDesc;

/// Animation descriptor.
typedef struct AnimationDesc {
  // TODO: Store a name hash for faster comparisons.
  sstring     name;         // Animation name. Required for playback.
  size_t      num_channels; // Number of channels.
  ChannelDesc channels[GFX_MAX_NUM_CHANNELS];
} AnimationDesc;

/// Anima object descriptor.
///
/// The last joint of the joints array at index 'num_joints - 1' must be the
/// root of all skeletons; specifically, the root of all joints that otherwise
/// would have no parent (a skeleton need not have its own root and can be a set
/// of disjoint node hierarchies).
typedef struct AnimaDesc {
  size_t        num_skeletons;
  size_t        num_animations;
  size_t        num_joints;
  SkeletonDesc  skeletons[GFX_MAX_NUM_SKELETONS];
  AnimationDesc animations[GFX_MAX_NUM_ANIMATIONS];
  JointDesc     joints[GFX_MAX_NUM_JOINTS];
} AnimaDesc;

/// Animation play settings.
typedef struct AnimationPlaySettings {
  const char* name; // Animation name.
  bool        loop; // Whether to loop the animation or just play once.
  // TODO: Add animation speed.
} AnimationPlaySettings;

/// Create an anima object.
Anima* gfx_make_anima(const AnimaDesc*);

/// Destroy the anima.
void gfx_destroy_anima(Anima**);

/// Play an animation (sets the current animation).
bool gfx_play_animation(Anima*, const AnimationPlaySettings*);

/// Update the current animation.
void gfx_update_animation(Anima*, R t);

/// Stop the current animation.
void gfx_stop_animation(Anima*);

/// Return the anima's ith skeleton.
const Skeleton* gfx_get_anima_skeleton(const Anima* anima, size_t i);

/// Return the number of joints in the skeleton.
size_t gfx_get_skeleton_num_joints(const Skeleton*);

/// Return true if the skeleton's ith joint has a bounding box.
///
/// IK joints that do not directly transform vertices have no bounding box.
bool gfx_joint_has_box(const Anima*, const Skeleton*, size_t joint);

/// Return the bounding box of the skeleton's ith joint.
///
/// IK joints that do not directly transform vertices have no box.
Box gfx_get_joint_box(const Anima*, const Skeleton*, size_t joint);