Implement animation info extraction form glTF JSON
This commit is contained in:
1 parent
7243b51149
commit
f24a920e66
1 file changed
+376
-72
+376
-72
@@ -29,7 +29,7 @@ static_assert(
|
|||||||
#define VERSION 2
|
#define VERSION 2
|
||||||
|
|
||||||
#define MAX_STRING_SIZE 128
|
#define MAX_STRING_SIZE 128
|
||||||
#define MAX_JOINT_COUNT 32
|
#define MAX_BONE_COUNT 32
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CHUNK_TYPE_JSON = 0x4e4f534a, // "JSON"
|
CHUNK_TYPE_JSON = 0x4e4f534a, // "JSON"
|
||||||
@@ -80,10 +80,34 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t inverse_bind_matrices;
|
uint32_t inverse_bind_matrices;
|
||||||
uint32_t joints[MAX_JOINT_COUNT];
|
uint32_t joints[MAX_BONE_COUNT];
|
||||||
uint32_t joint_count;
|
uint32_t joint_count;
|
||||||
} skin_t;
|
} skin_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ANIMATION_PROPERTY_TRANSLATION,
|
||||||
|
ANIMATION_PROPERTY_ROTATION,
|
||||||
|
ANIMATION_PROPERTY_SCALE,
|
||||||
|
} animation_property_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t sampler;
|
||||||
|
uint32_t node;
|
||||||
|
animation_property_t property;
|
||||||
|
} animation_channel_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t times;
|
||||||
|
uint32_t values;
|
||||||
|
} animation_sampler_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t times;
|
||||||
|
uint32_t translations;
|
||||||
|
uint32_t rotations;
|
||||||
|
uint32_t scales;
|
||||||
|
} animation_component_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t view;
|
uint32_t view;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
@@ -99,6 +123,12 @@ typedef struct {
|
|||||||
accessor_t weights;
|
accessor_t weights;
|
||||||
accessor_t indices;
|
accessor_t indices;
|
||||||
accessor_t inverse_bind_matrices;
|
accessor_t inverse_bind_matrices;
|
||||||
|
struct {
|
||||||
|
accessor_t times[MAX_BONE_COUNT];
|
||||||
|
accessor_t translations[MAX_BONE_COUNT];
|
||||||
|
accessor_t rotations[MAX_BONE_COUNT];
|
||||||
|
accessor_t scales[MAX_BONE_COUNT];
|
||||||
|
} animation;
|
||||||
} accessors_t;
|
} accessors_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -114,6 +144,12 @@ typedef struct {
|
|||||||
view_t weights;
|
view_t weights;
|
||||||
view_t indices;
|
view_t indices;
|
||||||
view_t inverse_bind_matrices;
|
view_t inverse_bind_matrices;
|
||||||
|
struct {
|
||||||
|
view_t times[MAX_BONE_COUNT];
|
||||||
|
view_t translations[MAX_BONE_COUNT];
|
||||||
|
view_t rotations[MAX_BONE_COUNT];
|
||||||
|
view_t scales[MAX_BONE_COUNT];
|
||||||
|
} animation;
|
||||||
} views_t;
|
} views_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -129,6 +165,13 @@ typedef struct {
|
|||||||
gltf_info_member_t weights;
|
gltf_info_member_t weights;
|
||||||
gltf_info_member_t indices;
|
gltf_info_member_t indices;
|
||||||
gltf_info_member_t inverse_bind_matrices;
|
gltf_info_member_t inverse_bind_matrices;
|
||||||
|
struct {
|
||||||
|
gltf_info_member_t times[MAX_BONE_COUNT];
|
||||||
|
gltf_info_member_t translations[MAX_BONE_COUNT];
|
||||||
|
gltf_info_member_t rotations[MAX_BONE_COUNT];
|
||||||
|
gltf_info_member_t scales[MAX_BONE_COUNT];
|
||||||
|
size_t keyframe_count;
|
||||||
|
} animation;
|
||||||
size_t vertex_count, index_count, bone_count;
|
size_t vertex_count, index_count, bone_count;
|
||||||
} gltf_info_t;
|
} gltf_info_t;
|
||||||
|
|
||||||
@@ -426,7 +469,7 @@ static skin_t read_skins(const uint8_t *p)
|
|||||||
assert(*p == '[');
|
assert(*p == '[');
|
||||||
++p;
|
++p;
|
||||||
for (skin.joint_count = 0; *p != ']'; ++skin.joint_count) {
|
for (skin.joint_count = 0; *p != ']'; ++skin.joint_count) {
|
||||||
assert(skin.joint_count < MAX_JOINT_COUNT);
|
assert(skin.joint_count < MAX_BONE_COUNT);
|
||||||
skin.joints[skin.joint_count] = read_uint(&p);
|
skin.joints[skin.joint_count] = read_uint(&p);
|
||||||
|
|
||||||
if (*p == ',')
|
if (*p == ',')
|
||||||
@@ -447,7 +490,7 @@ static skin_t read_skins(const uint8_t *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void read_joint_children(
|
static void read_joint_children(
|
||||||
const uint8_t **p, skin_t skin, bone_t bones[MAX_JOINT_COUNT],
|
const uint8_t **p, skin_t skin, bone_t bones[MAX_BONE_COUNT],
|
||||||
uint32_t parent)
|
uint32_t parent)
|
||||||
{
|
{
|
||||||
assert(**p == '[');
|
assert(**p == '[');
|
||||||
@@ -473,7 +516,7 @@ static void read_joint_children(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_joints(const uint8_t *p, skin_t skin, bone_t bones[MAX_JOINT_COUNT])
|
read_joints(const uint8_t *p, skin_t skin, bone_t bones[MAX_BONE_COUNT])
|
||||||
{
|
{
|
||||||
char buffer[MAX_STRING_SIZE];
|
char buffer[MAX_STRING_SIZE];
|
||||||
|
|
||||||
@@ -525,6 +568,209 @@ read_joints(const uint8_t *p, skin_t skin, bone_t bones[MAX_JOINT_COUNT])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static animation_property_t read_animation_property(const uint8_t **p)
|
||||||
|
{
|
||||||
|
char buffer[MAX_STRING_SIZE];
|
||||||
|
read_string(p, buffer);
|
||||||
|
if (strcmp("translation", buffer) == 0)
|
||||||
|
return ANIMATION_PROPERTY_TRANSLATION;
|
||||||
|
else if (strcmp("rotation", buffer) == 0)
|
||||||
|
return ANIMATION_PROPERTY_ROTATION;
|
||||||
|
else if (strcmp("scale", buffer) == 0)
|
||||||
|
return ANIMATION_PROPERTY_SCALE;
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t read_animation_channels(
|
||||||
|
const uint8_t *p, animation_channel_t channels[3 * MAX_BONE_COUNT])
|
||||||
|
{
|
||||||
|
char buffer[MAX_STRING_SIZE];
|
||||||
|
|
||||||
|
assert(*p == '[');
|
||||||
|
++p;
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; *p != ']'; ++i) {
|
||||||
|
assert(i < 3 * MAX_BONE_COUNT);
|
||||||
|
|
||||||
|
bool sampler = false;
|
||||||
|
bool node = false;
|
||||||
|
bool property = false;
|
||||||
|
|
||||||
|
assert(*p == '{');
|
||||||
|
++p;
|
||||||
|
while (*p != '}') {
|
||||||
|
read_string(&p, buffer);
|
||||||
|
assert(*p == ':');
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (strcmp("sampler", buffer) == 0) {
|
||||||
|
channels[i].sampler = read_uint(&p);
|
||||||
|
sampler = true;
|
||||||
|
} else if (strcmp("target", buffer) == 0) {
|
||||||
|
assert(*p == '{');
|
||||||
|
++p;
|
||||||
|
while (*p != '}') {
|
||||||
|
read_string(&p, buffer);
|
||||||
|
assert(*p == ':');
|
||||||
|
++p;
|
||||||
|
if (strcmp("node", buffer) == 0) {
|
||||||
|
channels[i].node = read_uint(&p);
|
||||||
|
node = true;
|
||||||
|
} else if (strcmp("path", buffer) == 0) {
|
||||||
|
channels[i].property = read_animation_property(&p);
|
||||||
|
property = true;
|
||||||
|
} else {
|
||||||
|
skip_value(&p);
|
||||||
|
}
|
||||||
|
if (*p == ',')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
} else {
|
||||||
|
skip_value(&p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == ',')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
|
||||||
|
assert(sampler);
|
||||||
|
assert(node);
|
||||||
|
assert(property);
|
||||||
|
|
||||||
|
if (*p == ',')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t read_animation_samplers(
|
||||||
|
const uint8_t *p, animation_sampler_t samplers[3 * MAX_BONE_COUNT])
|
||||||
|
{
|
||||||
|
char buffer[MAX_STRING_SIZE];
|
||||||
|
|
||||||
|
assert(*p == '[');
|
||||||
|
++p;
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; *p != ']'; ++i) {
|
||||||
|
assert(i < 3 * MAX_BONE_COUNT);
|
||||||
|
|
||||||
|
bool times = false;
|
||||||
|
bool values = false;
|
||||||
|
|
||||||
|
assert(*p == '{');
|
||||||
|
++p;
|
||||||
|
while (*p != '}') {
|
||||||
|
read_string(&p, buffer);
|
||||||
|
assert(*p == ':');
|
||||||
|
++p;
|
||||||
|
|
||||||
|
if (strcmp("input", buffer) == 0) {
|
||||||
|
samplers[i].times = read_uint(&p);
|
||||||
|
times = true;
|
||||||
|
} else if (strcmp("output", buffer) == 0) {
|
||||||
|
samplers[i].values = read_uint(&p);
|
||||||
|
values = true;
|
||||||
|
} else if (strcmp("interpolation", buffer) == 0) {
|
||||||
|
read_string(&p, buffer);
|
||||||
|
assert(strcmp("LINEAR", buffer) == 0);
|
||||||
|
} else {
|
||||||
|
skip_value(&p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == ',')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
|
||||||
|
assert(times);
|
||||||
|
assert(values);
|
||||||
|
|
||||||
|
if (*p == ',')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_animations(
|
||||||
|
const uint8_t *p, skin_t skin, animation_component_t *animation)
|
||||||
|
{
|
||||||
|
char buffer[MAX_STRING_SIZE];
|
||||||
|
animation_channel_t channels[3 * MAX_BONE_COUNT];
|
||||||
|
animation_sampler_t samplers[3 * MAX_BONE_COUNT];
|
||||||
|
|
||||||
|
assert(*p == '[');
|
||||||
|
++p;
|
||||||
|
|
||||||
|
assert(*p == '{');
|
||||||
|
++p;
|
||||||
|
|
||||||
|
const uint8_t *channels_json = nullptr;
|
||||||
|
const uint8_t *samplers_json = nullptr;
|
||||||
|
while (*p != '}') {
|
||||||
|
read_string(&p, buffer);
|
||||||
|
assert(*p == ':');
|
||||||
|
++p;
|
||||||
|
if (strcmp("channels", buffer) == 0)
|
||||||
|
channels_json = p;
|
||||||
|
else if (strcmp("samplers", buffer) == 0)
|
||||||
|
samplers_json = p;
|
||||||
|
skip_value(&p);
|
||||||
|
if (*p == ',')
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
assert(*p == ']'); // Only support one animation for now
|
||||||
|
|
||||||
|
assert(channels_json != nullptr);
|
||||||
|
assert(samplers_json != nullptr);
|
||||||
|
const size_t channel_count
|
||||||
|
= read_animation_channels(channels_json, channels);
|
||||||
|
const size_t sampler_count
|
||||||
|
= read_animation_samplers(samplers_json, samplers);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < skin.joint_count; ++i) {
|
||||||
|
// Initialise animation component with sentinel values
|
||||||
|
animation[i].times = UINT32_MAX;
|
||||||
|
animation[i].translations = UINT32_MAX;
|
||||||
|
animation[i].rotations = UINT32_MAX;
|
||||||
|
animation[i].scales = UINT32_MAX;
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < channel_count; ++j) {
|
||||||
|
if (channels[j].node != skin.joints[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
assert(channels[j].sampler < sampler_count);
|
||||||
|
const animation_sampler_t *sampler
|
||||||
|
= samplers + channels[j].sampler;
|
||||||
|
if (animation[i].times == UINT32_MAX)
|
||||||
|
animation[i].times = sampler->times;
|
||||||
|
else
|
||||||
|
assert(animation[i].times == sampler->times);
|
||||||
|
|
||||||
|
switch (channels[j].property) {
|
||||||
|
case ANIMATION_PROPERTY_TRANSLATION:
|
||||||
|
animation[i].translations = sampler->values;
|
||||||
|
break;
|
||||||
|
case ANIMATION_PROPERTY_ROTATION:
|
||||||
|
animation[i].rotations = sampler->values;
|
||||||
|
break;
|
||||||
|
case ANIMATION_PROPERTY_SCALE:
|
||||||
|
animation[i].scales = sampler->values;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static component_type_t read_component_type(const uint8_t **p)
|
static component_type_t read_component_type(const uint8_t **p)
|
||||||
{
|
{
|
||||||
const uint32_t component = read_uint(p);
|
const uint32_t component = read_uint(p);
|
||||||
@@ -539,10 +785,14 @@ static accessor_type_t read_accessor_type(const uint8_t **p)
|
|||||||
read_string(p, buffer);
|
read_string(p, buffer);
|
||||||
if (strcmp("SCALAR", buffer) == 0)
|
if (strcmp("SCALAR", buffer) == 0)
|
||||||
return ACCESSOR_TYPE_SCALAR;
|
return ACCESSOR_TYPE_SCALAR;
|
||||||
|
else if (strcmp("VEC2", buffer) == 0)
|
||||||
|
return ACCESSOR_TYPE_VEC2;
|
||||||
else if (strcmp("VEC3", buffer) == 0)
|
else if (strcmp("VEC3", buffer) == 0)
|
||||||
return ACCESSOR_TYPE_VEC3;
|
return ACCESSOR_TYPE_VEC3;
|
||||||
else if (strcmp("VEC4", buffer) == 0)
|
else if (strcmp("VEC4", buffer) == 0)
|
||||||
return ACCESSOR_TYPE_VEC4;
|
return ACCESSOR_TYPE_VEC4;
|
||||||
|
else if (strcmp("MAT3", buffer) == 0)
|
||||||
|
return ACCESSOR_TYPE_MAT3;
|
||||||
else if (strcmp("MAT4", buffer) == 0)
|
else if (strcmp("MAT4", buffer) == 0)
|
||||||
return ACCESSOR_TYPE_MAT4;
|
return ACCESSOR_TYPE_MAT4;
|
||||||
else
|
else
|
||||||
@@ -585,36 +835,44 @@ static accessor_t read_accessor(const uint8_t **p)
|
|||||||
return accessor;
|
return accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static accessors_t read_accessors(const uint8_t *p, mesh_t mesh, skin_t skin)
|
static accessors_t read_accessors(
|
||||||
|
const uint8_t *p, mesh_t mesh, skin_t skin,
|
||||||
|
const animation_component_t *animation)
|
||||||
{
|
{
|
||||||
accessors_t accessors = {};
|
accessors_t accessors = {};
|
||||||
assert(*p == '[');
|
assert(*p == '[');
|
||||||
++p;
|
++p;
|
||||||
for (uint32_t i = 0; *p != ']'; ++i) {
|
for (uint32_t i = 0; *p != ']'; ++i) {
|
||||||
if (i == mesh.normals)
|
const accessor_t accessor = read_accessor(&p);
|
||||||
accessors.normals = read_accessor(&p);
|
|
||||||
else if (i == mesh.positions)
|
|
||||||
accessors.positions = read_accessor(&p);
|
|
||||||
else if (i == mesh.bone_indices)
|
|
||||||
accessors.bone_indices = read_accessor(&p);
|
|
||||||
else if (i == mesh.weights)
|
|
||||||
accessors.weights = read_accessor(&p);
|
|
||||||
else if (i == mesh.indices)
|
|
||||||
accessors.indices = read_accessor(&p);
|
|
||||||
else if (i == skin.inverse_bind_matrices)
|
|
||||||
accessors.inverse_bind_matrices = read_accessor(&p);
|
|
||||||
else
|
|
||||||
skip_value(&p);
|
|
||||||
if (*p == ',')
|
if (*p == ',')
|
||||||
++p;
|
++p;
|
||||||
|
|
||||||
|
if (i == mesh.normals) {
|
||||||
|
accessors.normals = accessor;
|
||||||
|
} else if (i == mesh.positions) {
|
||||||
|
accessors.positions = accessor;
|
||||||
|
} else if (i == mesh.bone_indices) {
|
||||||
|
accessors.bone_indices = accessor;
|
||||||
|
} else if (i == mesh.weights) {
|
||||||
|
accessors.weights = accessor;
|
||||||
|
} else if (i == mesh.indices) {
|
||||||
|
accessors.indices = accessor;
|
||||||
|
} else if (i == skin.inverse_bind_matrices) {
|
||||||
|
accessors.inverse_bind_matrices = accessor;
|
||||||
|
} else {
|
||||||
|
for (uint32_t j = 0; j < skin.joint_count; ++j) {
|
||||||
|
if (i == animation[j].times)
|
||||||
|
accessors.animation.times[j] = accessor;
|
||||||
|
else if (i == animation[j].translations)
|
||||||
|
accessors.animation.translations[j] = accessor;
|
||||||
|
else if (i == animation[j].rotations)
|
||||||
|
accessors.animation.rotations[j] = accessor;
|
||||||
|
else if (i == animation[j].scales)
|
||||||
|
accessors.animation.scales[j] = accessor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(accessors.normals.count != 0);
|
|
||||||
assert(accessors.positions.count != 0);
|
|
||||||
assert(accessors.bone_indices.count != 0);
|
|
||||||
assert(accessors.weights.count != 0);
|
|
||||||
assert(accessors.indices.count != 0);
|
|
||||||
assert(accessors.inverse_bind_matrices.count != 0);
|
|
||||||
return accessors;
|
return accessors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,40 +908,44 @@ static view_t read_view(const uint8_t **p)
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
static views_t read_views(const uint8_t *p, accessors_t accessors)
|
static views_t
|
||||||
|
read_views(const uint8_t *p, accessors_t accessors, size_t bone_count)
|
||||||
{
|
{
|
||||||
views_t views = {};
|
views_t views = {};
|
||||||
|
|
||||||
assert(*p == '[');
|
assert(*p == '[');
|
||||||
++p;
|
++p;
|
||||||
for (uint32_t i = 0; *p != ']'; ++i) {
|
|
||||||
if (i == accessors.normals.view)
|
|
||||||
views.normals = read_view(&p);
|
|
||||||
else if (i == accessors.positions.view)
|
|
||||||
views.positions = read_view(&p);
|
|
||||||
else if (i == accessors.bone_indices.view)
|
|
||||||
views.bone_indices = read_view(&p);
|
|
||||||
else if (i == accessors.weights.view)
|
|
||||||
views.weights = read_view(&p);
|
|
||||||
else if (i == accessors.indices.view)
|
|
||||||
views.indices = read_view(&p);
|
|
||||||
else if (i == accessors.inverse_bind_matrices.view)
|
|
||||||
views.inverse_bind_matrices = read_view(&p);
|
|
||||||
else
|
|
||||||
skip_value(&p);
|
|
||||||
|
|
||||||
|
for (uint32_t i = 0; *p != ']'; ++i) {
|
||||||
|
const view_t view = read_view(&p);
|
||||||
if (*p == ',')
|
if (*p == ',')
|
||||||
++p;
|
++p;
|
||||||
|
|
||||||
|
if (i == accessors.normals.view)
|
||||||
|
views.normals = view;
|
||||||
|
if (i == accessors.positions.view)
|
||||||
|
views.positions = view;
|
||||||
|
if (i == accessors.bone_indices.view)
|
||||||
|
views.bone_indices = view;
|
||||||
|
if (i == accessors.weights.view)
|
||||||
|
views.weights = view;
|
||||||
|
if (i == accessors.indices.view)
|
||||||
|
views.indices = view;
|
||||||
|
if (i == accessors.inverse_bind_matrices.view)
|
||||||
|
views.inverse_bind_matrices = view;
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < bone_count; ++j) {
|
||||||
|
if (i == accessors.animation.times[j].view)
|
||||||
|
views.animation.times[j] = view;
|
||||||
|
else if (i == accessors.animation.translations[j].view)
|
||||||
|
views.animation.translations[j] = view;
|
||||||
|
else if (i == accessors.animation.rotations[j].view)
|
||||||
|
views.animation.rotations[j] = view;
|
||||||
|
else if (i == accessors.animation.scales[j].view)
|
||||||
|
views.animation.scales[j] = view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accessors.normals.view == accessors.positions.view)
|
|
||||||
views.positions = views.normals;
|
|
||||||
|
|
||||||
assert(views.normals.len != 0);
|
|
||||||
assert(views.positions.len != 0);
|
|
||||||
assert(views.bone_indices.len != 0);
|
|
||||||
assert(views.weights.len != 0);
|
|
||||||
assert(views.indices.len != 0);
|
|
||||||
assert(views.inverse_bind_matrices.len != 0);
|
|
||||||
return views;
|
return views;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,6 +975,7 @@ static gltf_info_t read_json(const uint8_t *json)
|
|||||||
const uint8_t *meshes_json = nullptr;
|
const uint8_t *meshes_json = nullptr;
|
||||||
const uint8_t *skins_json = nullptr;
|
const uint8_t *skins_json = nullptr;
|
||||||
const uint8_t *nodes_json = nullptr;
|
const uint8_t *nodes_json = nullptr;
|
||||||
|
const uint8_t *animations_json = nullptr;
|
||||||
const uint8_t *accessors_json = nullptr;
|
const uint8_t *accessors_json = nullptr;
|
||||||
const uint8_t *views_json = nullptr;
|
const uint8_t *views_json = nullptr;
|
||||||
while (*json != '}') {
|
while (*json != '}') {
|
||||||
@@ -725,6 +988,8 @@ static gltf_info_t read_json(const uint8_t *json)
|
|||||||
skins_json = json;
|
skins_json = json;
|
||||||
else if (strcmp("nodes", buffer) == 0)
|
else if (strcmp("nodes", buffer) == 0)
|
||||||
nodes_json = json;
|
nodes_json = json;
|
||||||
|
else if (strcmp("animations", buffer) == 0)
|
||||||
|
animations_json = json;
|
||||||
else if (strcmp("accessors", buffer) == 0)
|
else if (strcmp("accessors", buffer) == 0)
|
||||||
accessors_json = json;
|
accessors_json = json;
|
||||||
else if (strcmp("bufferViews", buffer) == 0)
|
else if (strcmp("bufferViews", buffer) == 0)
|
||||||
@@ -736,37 +1001,54 @@ static gltf_info_t read_json(const uint8_t *json)
|
|||||||
assert(meshes_json != nullptr);
|
assert(meshes_json != nullptr);
|
||||||
assert(skins_json != nullptr);
|
assert(skins_json != nullptr);
|
||||||
assert(nodes_json != nullptr);
|
assert(nodes_json != nullptr);
|
||||||
|
assert(animations_json != nullptr);
|
||||||
assert(accessors_json != nullptr);
|
assert(accessors_json != nullptr);
|
||||||
assert(views_json != nullptr);
|
assert(views_json != nullptr);
|
||||||
|
|
||||||
const mesh_t mesh = read_meshes(meshes_json);
|
const mesh_t mesh = read_meshes(meshes_json);
|
||||||
const skin_t skin = read_skins(skins_json);
|
const skin_t skin = read_skins(skins_json);
|
||||||
|
|
||||||
bone_t *bones = calloc(skin.joint_count, sizeof(bone_t));
|
bone_t *bones = calloc(skin.joint_count, sizeof(bone_t));
|
||||||
assert(bones != nullptr);
|
assert(bones != nullptr);
|
||||||
read_joints(nodes_json, skin, bones);
|
read_joints(nodes_json, skin, bones);
|
||||||
|
|
||||||
const accessors_t accessors = read_accessors(accessors_json, mesh, skin);
|
animation_component_t animation[MAX_BONE_COUNT];
|
||||||
const views_t views = read_views(views_json, accessors);
|
read_animations(animations_json, skin, animation);
|
||||||
|
|
||||||
|
const accessors_t accessors
|
||||||
|
= read_accessors(accessors_json, mesh, skin, animation);
|
||||||
|
const views_t views
|
||||||
|
= read_views(views_json, accessors, skin.joint_count);
|
||||||
|
|
||||||
// Verify data types
|
// Verify data types
|
||||||
assert(
|
assert(accessors.normals.component == COMPONENT_TYPE_F32);
|
||||||
accessors.normals.component == COMPONENT_TYPE_F32
|
assert(accessors.normals.type == ACCESSOR_TYPE_VEC3);
|
||||||
&& accessors.normals.type == ACCESSOR_TYPE_VEC3);
|
assert(accessors.positions.component == COMPONENT_TYPE_F32);
|
||||||
assert(
|
assert(accessors.positions.type == ACCESSOR_TYPE_VEC3);
|
||||||
accessors.positions.component == COMPONENT_TYPE_F32
|
assert(accessors.bone_indices.component == COMPONENT_TYPE_U16);
|
||||||
&& accessors.positions.type == ACCESSOR_TYPE_VEC3);
|
assert(accessors.bone_indices.type == ACCESSOR_TYPE_VEC4);
|
||||||
assert(
|
assert(accessors.weights.component == COMPONENT_TYPE_F32);
|
||||||
accessors.bone_indices.component == COMPONENT_TYPE_U16
|
assert(accessors.weights.type == ACCESSOR_TYPE_VEC4);
|
||||||
&& accessors.bone_indices.type == ACCESSOR_TYPE_VEC4);
|
assert(accessors.indices.component == COMPONENT_TYPE_U16);
|
||||||
assert(
|
assert(accessors.indices.type == ACCESSOR_TYPE_SCALAR);
|
||||||
accessors.weights.component == COMPONENT_TYPE_F32
|
assert(accessors.inverse_bind_matrices.component == COMPONENT_TYPE_F32);
|
||||||
&& accessors.weights.type == ACCESSOR_TYPE_VEC4);
|
assert(accessors.inverse_bind_matrices.type == ACCESSOR_TYPE_MAT4);
|
||||||
assert(
|
for (unsigned i = 0; i < skin.joint_count; ++i) {
|
||||||
accessors.indices.component == COMPONENT_TYPE_U16
|
assert(accessors.animation.times[i].component == COMPONENT_TYPE_F32);
|
||||||
&& accessors.indices.type == ACCESSOR_TYPE_SCALAR);
|
assert(accessors.animation.times[i].type == ACCESSOR_TYPE_SCALAR);
|
||||||
assert(
|
assert(
|
||||||
accessors.inverse_bind_matrices.component == COMPONENT_TYPE_F32
|
accessors.animation.translations[i].component
|
||||||
&& accessors.inverse_bind_matrices.type == ACCESSOR_TYPE_MAT4);
|
== COMPONENT_TYPE_F32);
|
||||||
|
assert(
|
||||||
|
accessors.animation.translations[i].type == ACCESSOR_TYPE_VEC3);
|
||||||
|
assert(
|
||||||
|
accessors.animation.rotations[i].component
|
||||||
|
== COMPONENT_TYPE_F32);
|
||||||
|
assert(accessors.animation.rotations[i].type == ACCESSOR_TYPE_VEC4);
|
||||||
|
assert(
|
||||||
|
accessors.animation.scales[i].component == COMPONENT_TYPE_F32);
|
||||||
|
assert(accessors.animation.scales[i].type == ACCESSOR_TYPE_VEC3);
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the vertex count is consistent
|
// Ensure the vertex count is consistent
|
||||||
assert(
|
assert(
|
||||||
@@ -777,7 +1059,16 @@ static gltf_info_t read_json(const uint8_t *json)
|
|||||||
// Ensure the joint count is consistent
|
// Ensure the joint count is consistent
|
||||||
assert(accessors.inverse_bind_matrices.count == skin.joint_count);
|
assert(accessors.inverse_bind_matrices.count == skin.joint_count);
|
||||||
|
|
||||||
return (gltf_info_t) {
|
// Ensure keyframe count is consistent
|
||||||
|
const size_t keyframe_count = accessors.animation.times[0].count;
|
||||||
|
for (unsigned i = 0; i < skin.joint_count; ++i) {
|
||||||
|
assert(accessors.animation.times[i].count == keyframe_count);
|
||||||
|
assert(accessors.animation.translations[i].count == keyframe_count);
|
||||||
|
assert(accessors.animation.rotations[i].count == keyframe_count);
|
||||||
|
assert(accessors.animation.scales[i].count == keyframe_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
gltf_info_t info = {
|
||||||
.bones = bones,
|
.bones = bones,
|
||||||
.positions = info_member(accessors.positions, views.positions),
|
.positions = info_member(accessors.positions, views.positions),
|
||||||
.normals = info_member(accessors.normals, views.normals),
|
.normals = info_member(accessors.normals, views.normals),
|
||||||
@@ -790,7 +1081,20 @@ static gltf_info_t read_json(const uint8_t *json)
|
|||||||
.inverse_bind_matrices = info_member(
|
.inverse_bind_matrices = info_member(
|
||||||
accessors.inverse_bind_matrices, views.inverse_bind_matrices),
|
accessors.inverse_bind_matrices, views.inverse_bind_matrices),
|
||||||
.bone_count = skin.joint_count,
|
.bone_count = skin.joint_count,
|
||||||
|
.animation = { .keyframe_count = keyframe_count },
|
||||||
};
|
};
|
||||||
|
for (unsigned i = 0; i < info.bone_count; ++i) {
|
||||||
|
info.animation.times[i] = info_member(
|
||||||
|
accessors.animation.times[i], views.animation.times[i]);
|
||||||
|
info.animation.translations[i] = info_member(
|
||||||
|
accessors.animation.translations[i],
|
||||||
|
views.animation.translations[i]);
|
||||||
|
info.animation.rotations[i] = info_member(
|
||||||
|
accessors.animation.rotations[i], views.animation.rotations[i]);
|
||||||
|
info.animation.scales[i] = info_member(
|
||||||
|
accessors.animation.scales[i], views.animation.scales[i]);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_vertices(
|
static void load_vertices(
|
||||||
|
|||||||
Reference in new issue
Block a user