Simulant  21.12-1292
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
skeleton.h
1 #pragma once
2 
3 #include <cstdint>
4 
5 #include "../../math/quaternion.h"
6 #include "../../math/vec3.h"
7 #include "../../meshes/mesh.h"
8 
9 #define MAX_JOINTS_PER_VERTEX 4
10 #define MAX_JOINTS_PER_MESH 64
11 
12 namespace smlt {
13 
14 struct Bone;
15 class Skeleton;
16 
17 /* This is an index into the vertex data array
18  * that and the weight that this joint affects that
19  * vertex */
20 struct JointVertex {
21  std::size_t vertex_id = 0;
22  float weight = 0.0f;
23 };
24 
25 class Joint {
26  friend class Skeleton;
27 
28 public:
29  Joint(Skeleton* skeleton):
30  skeleton_(skeleton) {
31 
32  // Just give a joint a bit of memory for
33  // vertices to start with
34  vertices_.reserve(32);
35  }
36 
37  void rotate_to(const Quaternion& q);
38  void move_to(const smlt::Vec3& v);
39 
40  std::string name() const;
41  void set_name(const std::string& name);
42 
43  Bone* link_to(Joint* other);
44 
45  Joint* parent() const;
46  std::size_t id() const;
47  void set_id(std::size_t id) {
48  id_ = id;
49  }
50 
51  const smlt::Quaternion& rotation() const {
52  return rotation_;
53  }
54 
55  const smlt::Vec3& translation() const {
56  return translation_;
57  }
58 
59  const smlt::Quaternion& absolute_rotation() const {
60  return absolute_rotation_;
61  }
62 
63  const smlt::Vec3 absolute_translation() const {
64  return absolute_translation_;
65  }
66 
67 private:
68  friend class Rig;
69 
70  Skeleton* skeleton_ = nullptr;
71  std::size_t id_ = 0; // 0 == root
72 
73  Joint* parent_ = nullptr;
74 
75  char name_[33] = {}; // 32 + \0
76 
77  Quaternion rotation_;
78  Quaternion absolute_rotation_;
79 
80  Vec3 translation_;
81  Vec3 absolute_translation_;
82 
83  std::vector<JointVertex> vertices_;
84 
85  void recalc_absolute_transformation();
86 };
87 
88 struct Bone {
89  Joint* joints[2] = {nullptr, nullptr};
90 };
91 
92 class Mesh;
93 
94 class Skeleton {
95  friend class Joint;
96 public:
97  Skeleton(Mesh* mesh, std::size_t num_joints):
98  mesh_(mesh) {
99  joints_.resize(num_joints, Joint(this));
100  }
101 
102  Joint* joint(std::size_t idx) {
103  return &joints_[idx];
104  }
105 
106  const Joint* joint(std::size_t idx) const {
107  return &joints_[idx];
108  }
109 
110  Joint* find_joint(const std::string& name) {
111  for(auto& joint: joints_) {
112  if(joint.name_ == name) {
113  return &joint;
114  }
115  }
116 
117  return nullptr;
118  }
119 
120  std::size_t joint_count() const {
121  return joints_.size();
122  }
123 
124  void attach_vertex_to_joint(std::size_t j, std::size_t vertex_index, float weight) {
125  JointVertex v;
126  v.vertex_id = vertex_index;
127  v.weight = weight;
128  joint(j)->vertices_.push_back(v);
129  }
130 
131 private:
132  friend class SkeletalFrameUnpacker;
133 
134  Mesh* mesh_ = nullptr;
135  std::vector<Joint> joints_;
136 
137  Bone bones_[MAX_JOINTS_PER_MESH];
138  uint8_t bone_count_ = 0;
139 };
140 
141 struct JointState {
142  /* The translation and rotation from the parent joint */
143  smlt::Quaternion rotation;
144  smlt::Vec3 translation;
145 
146  /* The absolute rotation/translation taking into account all
147  * parents */
148  smlt::Quaternion absolute_rotation;
149  smlt::Vec3 absolute_translation;
150 };
151 
153  std::vector<JointState> joints;
154 };
155 
157  int32_t joints[MAX_JOINTS_PER_VERTEX] = {-1, -1, -1, -1};
158  float weights[MAX_JOINTS_PER_VERTEX] = {0, 0, 0, 0};
159 };
160 
161 /* This processes the skeleton and updates the vertex
162  * data with the new vertex positions and normals */
164 public:
165  SkeletalFrameUnpacker(Mesh* mesh, std::size_t num_frames, std::size_t num_vertices);
166 
167  void prepare_unpack(
168  uint32_t current_frame,
169  uint32_t next_frame,
170  float t, Rig* const rig,
171  Debug* const debug=nullptr
172  ) override;
173 
174  virtual void unpack_frame(
175  const uint32_t current_frame,
176  const uint32_t next_frame,
177  const float t,
178  Rig* const rig,
179  VertexData* const out,
180  Debug* const debug=nullptr
181  ) override;
182 
183  void set_joint_state_at_frame(std::size_t frame, std::size_t joint, JointState state) {
184  assert(frame < skeleton_frames_.size());
185  assert(joint < skeleton_frames_[frame].joints.size());
186 
187  skeleton_frames_[frame].joints[joint] = state;
188  }
189 
190  const JointState& joint_state_at_frame(std::size_t frame, std::size_t joint) const {
191  assert(frame < skeleton_frames_.size());
192  assert(joint < skeleton_frames_[frame].joints.size());
193 
194  return skeleton_frames_[frame].joints[joint];
195  }
196 
197  /* Recursively visit joints from the root (0) and
198  * recalculate the absolute_rotation and translation
199  * for each. */
200  void rebuild_key_frame_absolute_transforms();
201 
202  const SkeletonVertex* vertex_at(std::size_t i);
203 
204  bool link_vertex_to_joint(std::size_t vertex, std::size_t j, float weight) {
205  auto vert = &vertices_[vertex];
206  for(uint8_t i = 0; i < MAX_JOINTS_PER_VERTEX; ++i) {
207  if(vert->joints[i] < 0) {
208  vert->joints[i] = j;
209  vert->weights[i] = weight;
210  return true;
211  }
212  }
213 
214  return false;
215  }
216 
217  const std::vector<SkeletonVertex>& vertices() const {
218  return vertices_;
219  }
220 private:
221  Mesh* mesh_ = nullptr;
222 
223  /* Key frames for skeletal animation */
224  std::vector<SkeletonFrame> skeleton_frames_;
225  std::vector<SkeletonVertex> vertices_;
226 };
227 
228 }
smlt::VertexData
Definition: vertex_data.h:60
smlt::Vec3
Definition: vec3.h:25
smlt::Quaternion
Definition: quaternion.h:22
smlt::JointVertex
Definition: skeleton.h:20
smlt::Skeleton
Definition: skeleton.h:94
smlt::SkeletonVertex
Definition: skeleton.h:156
smlt
Definition: animation.cpp:25
smlt::JointState
Definition: skeleton.h:141
smlt::SkeletonFrame
Definition: skeleton.h:152
smlt::Joint
Definition: skeleton.h:25
smlt::Mesh
Definition: mesh.h:127
smlt::FrameUnpacker
Definition: mesh.h:65
smlt::SkeletalFrameUnpacker
Definition: skeleton.h:163
smlt::Rig
Definition: rig.h:50
smlt::Debug
Definition: debug.h:28
smlt::Bone
Definition: skeleton.h:88