Files
coven/modules/ufbx/test/hash_scene.h

1319 lines
43 KiB
C

#ifndef UFBXT_HASH_SCENE_H_INCLUDED
#define UFBXT_HASH_SCENE_H_INCLUDED
#include "testing_basics.h"
#include <stdio.h>
#include <assert.h>
typedef struct ufbxt_hash {
uint64_t state;
bool dumping;
FILE *dump_file;
size_t indent;
bool at_tag;
bool at_value;
bool big_endian;
} ufbxt_hash;
ufbxt_noinline static void ufbxt_hash_init(ufbxt_hash *h, FILE *dump_file)
{
memset(h, 0, sizeof(ufbxt_hash));
h->state = UINT64_C(0xcbf29ce484222325);
{
uint8_t buf[2];
uint16_t val = 0xbbaa;
memcpy(buf, &val, 2);
h->big_endian = buf[0] == 0xbb;
}
if (dump_file) {
h->dumping = true;
h->dump_file = dump_file;
}
}
ufbxt_noinline static uint64_t ufbxt_hash_finish(ufbxt_hash *h)
{
if (h->dump_file) {
fflush(h->dump_file);
}
return h->state;
}
ufbxt_noinline static void ufbxt_push_tag(ufbxt_hash *h, const char *tag)
{
if (!h->dumping) return;
if (tag[0] == '&') {
tag++;
}
if (!strncmp(tag, "v->", 3)) {
tag += 3;
} else if (!strncmp(tag, "v.", 2)) {
tag += 2;
}
if (h->at_tag) {
fprintf(h->dump_file, "{\n");
h->indent += 1;
}
for (size_t i = 0; i < h->indent; i++) {
fprintf(h->dump_file, " ");
}
fprintf(h->dump_file, "%s: ", tag);
h->at_tag = true;
}
ufbxt_noinline static void ufbxt_push_tag_index(ufbxt_hash *h, size_t index)
{
if (!h->dumping) return;
char buf[128];
snprintf(buf, sizeof(buf), "[%zu]", index);
ufbxt_push_tag(h, buf);
}
ufbxt_noinline static void ufbxt_pop_tag(ufbxt_hash *h)
{
if (!h->dumping) return;
if (h->at_value || h->at_tag) {
fprintf(h->dump_file, "\n");
h->at_value = false;
h->at_tag = false;
} else {
h->indent -= 1;
for (size_t i = 0; i < h->indent; i++) {
fprintf(h->dump_file, " ");
}
fprintf(h->dump_file, "}\n");
}
}
ufbxt_noinline static void ufbxt_dump_data(ufbxt_hash *h, const void *data, size_t size, bool reverse)
{
assert(h->at_tag && !h->at_value);
h->at_tag = false;
h->at_value = true;
const char *d = (const char*)data;
if (reverse) {
for (size_t i = size; i > 0; i--) {
uint32_t b = (uint32_t)(uint8_t)d[i - 1];
fprintf(h->dump_file, "%02x", b);
}
} else {
for (size_t i = 0; i < size; i++) {
uint32_t b = (uint32_t)(uint8_t)d[i];
fprintf(h->dump_file, "%02x", b);
}
}
}
ufbxt_noinline static void ufbxt_hash_data(ufbxt_hash *h, const void *data, size_t size)
{
const char *d = (const char*)data;
uint64_t state = h->state;
for (size_t i = 0; i < size; i++) {
state = (state ^ (uint8_t)d[i]) * UINT64_C(0x00000100000001B3);
}
h->state = state;
if (h->dumping) {
ufbxt_dump_data(h, data, size, false);
}
}
ufbxt_noinline static void ufbxt_hash_endian_data(ufbxt_hash *h, const void *data, size_t size)
{
bool reverse = !h->big_endian;
assert(size == 1 || size == 2 || size == 4 || size == 8);
const char *d = (const char*)data;
uint64_t state = h->state;
if (reverse) {
for (size_t i = size; i > 0; i--) {
state = (state ^ (uint8_t)d[i - 1]) * UINT64_C(0x00000100000001B3);
}
} else {
for (size_t i = 0; i < size; i++) {
state = (state ^ (uint8_t)d[i]) * UINT64_C(0x00000100000001B3);
}
}
h->state = state;
if (h->dumping) {
ufbxt_dump_data(h, data, size, true);
}
}
#define ufbxt_hash_pod_imp(h, v) ufbxt_hash_endian_data((h), &(v), sizeof((v)))
#define ufbxt_hash_pod(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_pod_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_float_imp(ufbxt_hash *h, float v)
{
if (v == v) {
ufbxt_hash_pod_imp(h, v);
} else {
uint32_t u = UINT32_MAX;
ufbxt_hash_pod_imp(h, u);
}
}
ufbxt_noinline static void ufbxt_hash_double_imp(ufbxt_hash *h, double v)
{
if (v == v) {
ufbxt_hash_pod_imp(h, v);
} else {
uint64_t u = UINT64_MAX;
ufbxt_hash_pod_imp(h, u);
}
}
ufbxt_noinline static void ufbxt_hash_real_imp(ufbxt_hash *h, ufbx_real v)
{
if (v == v) {
ufbxt_hash_pod_imp(h, v);
} else {
uint64_t u = UINT64_MAX;
ufbxt_hash_pod_imp(h, u);
}
}
ufbxt_noinline static void ufbxt_hash_size_t_imp(ufbxt_hash *h, size_t v)
{
uint64_t u = v;
ufbxt_hash_pod_imp(h, u);
}
#define ufbxt_hash_float(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_float_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_double(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_double_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_real(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_real_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_size_t(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_size_t_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_vec2_imp(ufbxt_hash *h, ufbx_vec2 v)
{
ufbxt_hash_real(h, v.x);
ufbxt_hash_real(h, v.y);
}
ufbxt_noinline static void ufbxt_hash_vec3_imp(ufbxt_hash *h, ufbx_vec3 v)
{
ufbxt_hash_real(h, v.x);
ufbxt_hash_real(h, v.y);
ufbxt_hash_real(h, v.z);
}
ufbxt_noinline static void ufbxt_hash_vec4_imp(ufbxt_hash *h, ufbx_vec4 v)
{
ufbxt_hash_real(h, v.x);
ufbxt_hash_real(h, v.y);
ufbxt_hash_real(h, v.z);
ufbxt_hash_real(h, v.w);
}
ufbxt_noinline static void ufbxt_hash_quat_imp(ufbxt_hash *h, ufbx_quat v)
{
ufbxt_hash_real(h, v.x);
ufbxt_hash_real(h, v.y);
ufbxt_hash_real(h, v.z);
ufbxt_hash_real(h, v.w);
}
#define ufbxt_hash_vec2(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_vec2_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_vec3(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_vec3_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_vec4(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_vec4_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_quat(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_quat_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_transform_imp(ufbxt_hash *h, ufbx_transform v)
{
ufbxt_hash_vec3(h, v.translation);
ufbxt_hash_quat(h, v.rotation);
ufbxt_hash_vec3(h, v.scale);
}
ufbxt_noinline static void ufbxt_hash_matrix_imp(ufbxt_hash *h, ufbx_matrix v)
{
ufbxt_hash_vec3(h, v.cols[0]);
ufbxt_hash_vec3(h, v.cols[1]);
ufbxt_hash_vec3(h, v.cols[2]);
ufbxt_hash_vec3(h, v.cols[3]);
}
ufbxt_noinline static void ufbxt_hash_string_imp(ufbxt_hash *h, ufbx_string v)
{
ufbxt_hash_size_t(h, v.length);
ufbxt_push_tag(h, "v.data");
ufbxt_hash_data(h, v.data, v.length + 1);
ufbxt_pop_tag(h);
}
ufbxt_noinline static void ufbxt_hash_blob_imp(ufbxt_hash *h, ufbx_blob v)
{
ufbxt_hash_size_t(h, v.size);
ufbxt_push_tag(h, "v.data");
ufbxt_hash_data(h, v.data, v.size);
ufbxt_pop_tag(h);
}
#define ufbxt_hash_transform(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_transform_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_matrix(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_matrix_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_string(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_string_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_blob(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_blob_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_element_ref_imp(ufbxt_hash *h, const void *v)
{
const ufbx_element *elem = (const ufbx_element*)v;
uint32_t id = elem ? elem->element_id : UINT32_MAX;
ufbxt_hash_pod(h, id);
}
ufbxt_noinline static void ufbxt_hash_prop_ref_imp(ufbxt_hash *h, const ufbx_prop *prop)
{
if (!prop) {
uint32_t zero = UINT32_MAX;
ufbxt_hash_pod(h, zero);
} else {
ufbxt_hash_string(h, prop->name);
}
}
#define ufbxt_hash_prop_ref(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_prop_ref_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_element_ref(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_element_ref_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_connection_imp(ufbxt_hash *h, ufbx_connection v)
{
ufbxt_hash_element_ref(h, v.src);
ufbxt_hash_element_ref(h, v.dst);
ufbxt_hash_string(h, v.src_prop);
ufbxt_hash_string(h, v.dst_prop);
}
#define ufbxt_hash_connection(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_connection_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_array(h, v, func) do { \
ufbxt_push_tag(h, #v); \
for (size_t i = 0; i < sizeof(v) / sizeof(*(v)); i++) { \
ufbxt_push_tag_index(h, i); \
func((h), (v)[i]); \
ufbxt_pop_tag(h); \
} \
ufbxt_pop_tag(h); \
} while (0)
#define ufbxt_hash_list(h, v, func) do { \
ufbxt_push_tag(h, #v); \
size_t count = (v).count; \
ufbxt_hash_size_t((h), count); \
ufbxt_push_tag(h, "data"); \
for (size_t i = 0; i < count; i++) { \
ufbxt_push_tag_index(h, i); \
func((h), (v).data[i]); \
ufbxt_pop_tag(h); \
} \
ufbxt_pop_tag(h); \
ufbxt_pop_tag(h); \
} while (0)
#define ufbxt_hash_list_ptr(h, v, func) do { \
ufbxt_push_tag(h, #v); \
size_t count = (v).count; \
ufbxt_hash_size_t((h), count); \
ufbxt_push_tag(h, "data"); \
for (size_t i = 0; i < count; i++) { \
ufbxt_push_tag_index(h, i); \
func((h), &(v).data[i]); \
ufbxt_pop_tag(h); \
} \
ufbxt_pop_tag(h); \
ufbxt_pop_tag(h); \
} while (0)
ufbxt_noinline static void ufbxt_hash_prop_imp(ufbxt_hash *h, const ufbx_prop *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_pod(h, v->_internal_key);
ufbxt_hash_pod(h, v->type);
ufbxt_hash_pod(h, v->flags);
ufbxt_hash_string(h, v->value_str);
ufbxt_hash_blob(h, v->value_blob);
ufbxt_hash_pod(h, v->value_int);
ufbxt_hash_vec4(h, v->value_vec4);
}
#define ufbxt_hash_prop(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_prop_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_dom_value_imp(ufbxt_hash *h, const ufbx_dom_value *v)
{
ufbxt_hash_pod(h, v->type);
ufbxt_hash_string(h, v->value_str);
size_t count = (size_t)v->value_int;
if (v->type == UFBX_DOM_VALUE_ARRAY_RAW_STRING) {
const ufbx_string *vs = (const ufbx_string*)v->value_blob.data;
for (size_t i = 0; i < count; i++) {
ufbxt_hash_string(h, vs[i]);
}
} else if (v->type == UFBX_DOM_VALUE_ARRAY_F32) {
const float *vs = (const float*)v->value_blob.data;
for (size_t i = 0; i < count; i++) {
ufbxt_hash_float(h, vs[i]);
}
} else if (v->type == UFBX_DOM_VALUE_ARRAY_F64) {
const double *vs = (const double*)v->value_blob.data;
for (size_t i = 0; i < count; i++) {
ufbxt_hash_double(h, vs[i]);
}
} else {
ufbxt_hash_blob(h, v->value_blob);
}
ufbxt_hash_pod(h, v->value_int);
ufbxt_hash_double(h, v->value_float);
}
#define ufbxt_hash_dom_value(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_dom_value_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_dom_node_imp(ufbxt_hash *h, const ufbx_dom_node *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_list(h, v->children, ufbxt_hash_dom_node_imp);
ufbxt_hash_list_ptr(h, v->values, ufbxt_hash_dom_value_imp);
}
#define ufbxt_hash_dom_node(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_dom_node_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_props_imp(ufbxt_hash *h, const ufbx_props *v)
{
ufbxt_hash_list_ptr(h, v->props, ufbxt_hash_prop_imp);
ufbxt_hash_size_t(h, v->num_animated);
if (v->defaults) {
ufbxt_push_tag(h, "defaults");
ufbxt_hash_props_imp(h, v->defaults);
ufbxt_pop_tag(h);
}
}
#define ufbxt_hash_props(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_props_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_element_imp(ufbxt_hash *h, const ufbx_element *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_props(h, &v->props);
ufbxt_hash_pod(h, v->element_id);
ufbxt_hash_pod(h, v->typed_id);
ufbxt_hash_list(h, v->instances, ufbxt_hash_element_ref_imp);
ufbxt_hash_pod(h, v->type);
ufbxt_hash_list(h, v->connections_src, ufbxt_hash_connection_imp);
ufbxt_hash_list(h, v->connections_dst, ufbxt_hash_connection_imp);
}
ufbxt_noinline static void ufbxt_hash_unknown_imp(ufbxt_hash *h, const ufbx_unknown *v)
{
ufbxt_hash_string(h, v->type);
ufbxt_hash_string(h, v->super_type);
ufbxt_hash_string(h, v->sub_type);
}
ufbxt_noinline static void ufbxt_hash_node_imp(ufbxt_hash *h, const ufbx_node *v)
{
ufbxt_hash_element_ref(h, v->parent);
ufbxt_hash_list(h, v->children, ufbxt_hash_element_ref_imp);
ufbxt_hash_element_ref(h, v->mesh);
ufbxt_hash_element_ref(h, v->light);
ufbxt_hash_element_ref(h, v->camera);
ufbxt_hash_element_ref(h, v->bone);
ufbxt_hash_element_ref(h, v->attrib);
ufbxt_hash_element_ref(h, v->geometry_transform_helper);
ufbxt_hash_pod(h, v->attrib_type);
ufbxt_hash_list(h, v->all_attribs, ufbxt_hash_element_ref_imp);
ufbxt_hash_pod(h, v->inherit_type);
ufbxt_hash_transform(h, v->local_transform);
ufbxt_hash_transform(h, v->geometry_transform);
ufbxt_hash_pod(h, v->rotation_order);
ufbxt_hash_vec3(h, v->euler_rotation);
ufbxt_hash_transform(h, v->world_transform);
ufbxt_hash_matrix(h, v->node_to_parent);
ufbxt_hash_matrix(h, v->node_to_world);
ufbxt_hash_matrix(h, v->geometry_to_node);
ufbxt_hash_matrix(h, v->geometry_to_world);
ufbxt_hash_quat(h, v->adjust_pre_rotation);
ufbxt_hash_vec3(h, v->adjust_pre_scale);
ufbxt_hash_quat(h, v->adjust_post_rotation);
ufbxt_hash_pod(h, v->visible);
ufbxt_hash_pod(h, v->is_root);
ufbxt_hash_pod(h, v->has_geometry_transform);
ufbxt_hash_pod(h, v->has_adjust_transform);
ufbxt_hash_pod(h, v->is_geometry_transform_helper);
ufbxt_hash_pod(h, v->node_depth);
ufbxt_hash_list(h, v->materials, ufbxt_hash_element_ref_imp);
}
ufbxt_noinline static void ufbxt_hash_vertex_real_imp(ufbxt_hash *h, const ufbx_vertex_real *v)
{
ufbxt_hash_pod(h, v->exists);
ufbxt_hash_list(h, v->values, ufbxt_hash_real_imp);
ufbxt_hash_list(h, v->indices, ufbxt_hash_pod_imp);
ufbxt_hash_size_t(h, v->value_reals);
ufbxt_hash_pod(h, v->unique_per_vertex);
}
ufbxt_noinline static void ufbxt_hash_vertex_vec2_imp(ufbxt_hash *h, const ufbx_vertex_vec2 *v)
{
ufbxt_hash_pod(h, v->exists);
ufbxt_hash_list(h, v->values, ufbxt_hash_vec2_imp);
ufbxt_hash_list(h, v->indices, ufbxt_hash_pod_imp);
ufbxt_hash_size_t(h, v->value_reals);
ufbxt_hash_pod(h, v->unique_per_vertex);
}
ufbxt_noinline static void ufbxt_hash_vertex_vec3_imp(ufbxt_hash *h, const ufbx_vertex_vec3 *v)
{
ufbxt_hash_pod(h, v->exists);
ufbxt_hash_list(h, v->values, ufbxt_hash_vec3_imp);
ufbxt_hash_list(h, v->indices, ufbxt_hash_pod_imp);
ufbxt_hash_size_t(h, v->value_reals);
ufbxt_hash_pod(h, v->unique_per_vertex);
}
ufbxt_noinline static void ufbxt_hash_vertex_vec4_imp(ufbxt_hash *h, const ufbx_vertex_vec4 *v)
{
ufbxt_hash_pod(h, v->exists);
ufbxt_hash_list(h, v->values, ufbxt_hash_vec4);
ufbxt_hash_list(h, v->indices, ufbxt_hash_pod);
ufbxt_hash_size_t(h, v->value_reals);
ufbxt_hash_pod(h, v->unique_per_vertex);
}
#define ufbxt_hash_vertex_real(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_vertex_real_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_vertex_vec2(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_vertex_vec2_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_vertex_vec3(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_vertex_vec3_imp(h, v), ufbxt_pop_tag(h))
#define ufbxt_hash_vertex_vec4(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_vertex_vec4_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_uv_set_imp(ufbxt_hash *h, const ufbx_uv_set *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_pod(h, v->index);
ufbxt_hash_vertex_vec2(h, &v->vertex_uv);
ufbxt_hash_vertex_vec3(h, &v->vertex_tangent);
ufbxt_hash_vertex_vec3(h, &v->vertex_bitangent);
}
ufbxt_noinline static void ufbxt_hash_color_set_imp(ufbxt_hash *h, const ufbx_color_set *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_pod(h, v->index);
ufbxt_hash_vertex_vec4(h, &v->vertex_color);
}
ufbxt_noinline static void ufbxt_hash_mesh_material_imp(ufbxt_hash *h, const ufbx_mesh_material *v)
{
ufbxt_hash_element_ref(h, v->material);
ufbxt_hash_size_t(h, v->num_faces);
ufbxt_hash_size_t(h, v->num_triangles);
ufbxt_hash_size_t(h, v->num_empty_faces);
ufbxt_hash_size_t(h, v->num_point_faces);
ufbxt_hash_size_t(h, v->num_line_faces);
ufbxt_hash_list(h, v->face_indices, ufbxt_hash_pod_imp);
}
ufbxt_noinline static void ufbxt_hash_face_group_imp(ufbxt_hash *h, const ufbx_face_group *v)
{
ufbxt_hash_pod(h, v->id);
ufbxt_hash_string(h, v->name);
ufbxt_hash_size_t(h, v->num_faces);
ufbxt_hash_size_t(h, v->num_triangles);
ufbxt_hash_list(h, v->face_indices, ufbxt_hash_pod_imp);
}
ufbxt_noinline static void ufbxt_hash_subdivision_weight_range_imp(ufbxt_hash *h, ufbx_subdivision_weight_range v)
{
ufbxt_hash_pod(h, v.weight_begin);
ufbxt_hash_pod(h, v.num_weights);
}
ufbxt_noinline static void ufbxt_hash_subdivision_weight_imp(ufbxt_hash *h, ufbx_subdivision_weight v)
{
ufbxt_hash_real(h, v.weight);
ufbxt_hash_pod(h, v.index);
}
ufbxt_noinline static void ufbxt_hash_subdivision_result_imp(ufbxt_hash *h, const ufbx_subdivision_result *v)
{
ufbxt_hash_list(h, v->source_vertex_ranges, ufbxt_hash_subdivision_weight_range_imp);
ufbxt_hash_list(h, v->source_vertex_weights, ufbxt_hash_subdivision_weight_imp);
ufbxt_hash_list(h, v->skin_cluster_ranges, ufbxt_hash_subdivision_weight_range_imp);
ufbxt_hash_list(h, v->skin_cluster_weights, ufbxt_hash_subdivision_weight_imp);
}
ufbxt_noinline static void ufbxt_hash_face_imp(ufbxt_hash *h, ufbx_face v)
{
ufbxt_hash_pod(h, v.index_begin);
ufbxt_hash_pod(h, v.num_indices);
}
ufbxt_noinline static void ufbxt_hash_edge_imp(ufbxt_hash *h, ufbx_edge v)
{
ufbxt_hash_pod(h, v.a);
ufbxt_hash_pod(h, v.b);
}
#define ufbxt_hash_subdivision_result(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_subdivision_result_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_mesh_imp(ufbxt_hash *h, const ufbx_mesh *v)
{
ufbxt_hash_size_t(h, v->num_vertices);
ufbxt_hash_size_t(h, v->num_indices);
ufbxt_hash_size_t(h, v->num_faces);
ufbxt_hash_size_t(h, v->num_triangles);
ufbxt_hash_size_t(h, v->num_edges);
ufbxt_hash_list(h, v->faces, ufbxt_hash_face_imp);
ufbxt_hash_list(h, v->face_smoothing, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->face_material, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->face_group, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->face_hole, ufbxt_hash_pod_imp);
ufbxt_hash_size_t(h, v->max_face_triangles);
ufbxt_hash_size_t(h, v->num_empty_faces);
ufbxt_hash_size_t(h, v->num_point_faces);
ufbxt_hash_size_t(h, v->num_line_faces);
ufbxt_hash_list(h, v->edges, ufbxt_hash_edge_imp);
ufbxt_hash_list(h, v->edge_smoothing, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->edge_crease, ufbxt_hash_real_imp);
ufbxt_hash_list(h, v->edge_visibility, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->vertex_indices, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->vertices, ufbxt_hash_vec3_imp);
ufbxt_hash_list(h, v->vertex_first_index, ufbxt_hash_pod_imp);
ufbxt_hash_vertex_vec3(h, &v->vertex_position);
ufbxt_hash_vertex_vec3(h, &v->vertex_normal);
ufbxt_hash_vertex_vec2(h, &v->vertex_uv);
ufbxt_hash_vertex_vec3(h, &v->vertex_tangent);
ufbxt_hash_vertex_vec3(h, &v->vertex_bitangent);
ufbxt_hash_vertex_vec4(h, &v->vertex_color);
ufbxt_hash_vertex_real(h, &v->vertex_crease);
ufbxt_hash_list_ptr(h, v->uv_sets, ufbxt_hash_uv_set_imp);
ufbxt_hash_list_ptr(h, v->color_sets, ufbxt_hash_color_set_imp);
ufbxt_hash_list_ptr(h, v->materials, ufbxt_hash_mesh_material_imp);
ufbxt_hash_list_ptr(h, v->face_groups, ufbxt_hash_face_group_imp);
ufbxt_hash_pod(h, v->skinned_is_local);
ufbxt_hash_vertex_vec3(h, &v->skinned_position);
ufbxt_hash_vertex_vec3(h, &v->skinned_normal);
ufbxt_hash_list(h, v->skin_deformers, ufbxt_hash_element_ref_imp);
ufbxt_hash_list(h, v->blend_deformers, ufbxt_hash_element_ref_imp);
ufbxt_hash_list(h, v->cache_deformers, ufbxt_hash_element_ref_imp);
ufbxt_hash_list(h, v->all_deformers, ufbxt_hash_element_ref_imp);
ufbxt_hash_pod(h, v->subdivision_preview_levels);
ufbxt_hash_pod(h, v->subdivision_render_levels);
ufbxt_hash_pod(h, v->subdivision_display_mode);
ufbxt_hash_pod(h, v->subdivision_boundary);
ufbxt_hash_pod(h, v->subdivision_uv_boundary);
ufbxt_hash_pod(h, v->subdivision_evaluated);
if (v->subdivision_result) ufbxt_hash_subdivision_result(h, v->subdivision_result);
ufbxt_hash_pod(h, v->from_tessellated_nurbs);
}
ufbxt_noinline static void ufbxt_hash_light_imp(ufbxt_hash *h, const ufbx_light *v)
{
ufbxt_hash_vec3(h, v->color);
ufbxt_hash_real(h, v->intensity);
ufbxt_hash_vec3(h, v->local_direction);
ufbxt_hash_pod(h, v->type);
ufbxt_hash_pod(h, v->decay);
ufbxt_hash_pod(h, v->area_shape);
ufbxt_hash_real(h, v->inner_angle);
ufbxt_hash_real(h, v->outer_angle);
ufbxt_hash_pod(h, v->cast_light);
ufbxt_hash_pod(h, v->cast_shadows);
}
ufbxt_noinline static void ufbxt_hash_camera_imp(ufbxt_hash *h, const ufbx_camera *v)
{
ufbxt_hash_pod(h, v->resolution_is_pixels);
ufbxt_hash_vec2(h, v->resolution);
ufbxt_hash_vec2(h, v->field_of_view_deg);
ufbxt_hash_vec2(h, v->field_of_view_tan);
ufbxt_hash_pod(h, v->aspect_mode);
ufbxt_hash_pod(h, v->aperture_mode);
ufbxt_hash_pod(h, v->gate_fit);
ufbxt_hash_pod(h, v->aperture_format);
ufbxt_hash_real(h, v->focal_length_mm);
ufbxt_hash_vec2(h, v->film_size_inch);
ufbxt_hash_vec2(h, v->aperture_size_inch);
ufbxt_hash_real(h, v->squeeze_ratio);
}
ufbxt_noinline static void ufbxt_hash_bone_imp(ufbxt_hash *h, const ufbx_bone *v)
{
ufbxt_hash_real(h, v->radius);
ufbxt_hash_real(h, v->relative_length);
ufbxt_hash_pod(h, v->is_root);
}
ufbxt_noinline static void ufbxt_hash_empty_imp(ufbxt_hash *h, const ufbx_empty *v)
{
}
ufbxt_noinline static void ufbxt_hash_nurbs_basis_imp(ufbxt_hash *h, const ufbx_nurbs_basis *v)
{
ufbxt_hash_pod(h, v->order);
ufbxt_hash_pod(h, v->topology);
ufbxt_hash_list(h, v->knot_vector, ufbxt_hash_real_imp);
ufbxt_hash_real(h, v->t_min);
ufbxt_hash_real(h, v->t_max);
ufbxt_hash_list(h, v->spans, ufbxt_hash_real_imp);
ufbxt_hash_pod(h, v->is_2d);
ufbxt_hash_size_t(h, v->num_wrap_control_points);
ufbxt_hash_pod(h, v->valid);
}
#define ufbxt_hash_nurbs_basis(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_nurbs_basis_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_line_segment_imp(ufbxt_hash *h, ufbx_line_segment v)
{
ufbxt_hash_pod(h, v.index_begin);
ufbxt_hash_pod(h, v.num_indices);
}
ufbxt_noinline static void ufbxt_hash_line_curve_imp(ufbxt_hash *h, const ufbx_line_curve *v)
{
ufbxt_hash_vec3(h, v->color);
ufbxt_hash_list(h, v->control_points, ufbxt_hash_vec3_imp);
ufbxt_hash_list(h, v->point_indices, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->segments, ufbxt_hash_line_segment_imp);
ufbxt_hash_pod(h, v->from_tessellated_nurbs);
}
ufbxt_noinline static void ufbxt_hash_nurbs_curve_imp(ufbxt_hash *h, const ufbx_nurbs_curve *v)
{
ufbxt_hash_nurbs_basis(h, &v->basis);
ufbxt_hash_list(h, v->control_points, ufbxt_hash_vec4_imp);
}
ufbxt_noinline static void ufbxt_hash_nurbs_surface_imp(ufbxt_hash *h, const ufbx_nurbs_surface *v)
{
ufbxt_hash_nurbs_basis(h, &v->basis_u);
ufbxt_hash_nurbs_basis(h, &v->basis_v);
ufbxt_hash_size_t(h, v->num_control_points_u);
ufbxt_hash_size_t(h, v->num_control_points_v);
ufbxt_hash_list(h, v->control_points, ufbxt_hash_vec4_imp);
ufbxt_hash_pod(h, v->span_subdivision_u);
ufbxt_hash_pod(h, v->span_subdivision_v);
ufbxt_hash_pod(h, v->flip_normals);
ufbxt_hash_element_ref(h, v->material);
}
ufbxt_noinline static void ufbxt_hash_nurbs_trim_surface_imp(ufbxt_hash *h, const ufbx_nurbs_trim_surface *v)
{
}
ufbxt_noinline static void ufbxt_hash_nurbs_trim_boundary_imp(ufbxt_hash *h, const ufbx_nurbs_trim_boundary *v)
{
}
ufbxt_noinline static void ufbxt_hash_procedural_geometry_imp(ufbxt_hash *h, const ufbx_procedural_geometry *v)
{
}
ufbxt_noinline static void ufbxt_hash_stereo_camera_imp(ufbxt_hash *h, const ufbx_stereo_camera *v)
{
ufbxt_hash_element_ref(h, v->left);
ufbxt_hash_element_ref(h, v->right);
}
ufbxt_noinline static void ufbxt_hash_camera_switcher_imp(ufbxt_hash *h, const ufbx_camera_switcher *v)
{
}
ufbxt_noinline static void ufbxt_hash_marker_imp(ufbxt_hash *h, const ufbx_marker *v)
{
ufbxt_hash_pod(h, v->type);
}
ufbxt_noinline static void ufbxt_hash_lod_level_imp(ufbxt_hash *h, ufbx_lod_level v)
{
ufbxt_hash_real(h, v.distance);
ufbxt_hash_pod(h, v.display);
}
ufbxt_noinline static void ufbxt_hash_lod_group_imp(ufbxt_hash *h, const ufbx_lod_group *v)
{
ufbxt_hash_pod(h, v->relative_distances);
ufbxt_hash_list(h, v->lod_levels, ufbxt_hash_lod_level_imp);
ufbxt_hash_pod(h, v->ignore_parent_transform);
ufbxt_hash_pod(h, v->use_distance_limit);
ufbxt_hash_real(h, v->distance_limit_min);
ufbxt_hash_real(h, v->distance_limit_max);
}
ufbxt_noinline static void ufbxt_hash_skin_vertex_imp(ufbxt_hash *h, ufbx_skin_vertex v)
{
ufbxt_hash_pod(h, v.weight_begin);
ufbxt_hash_pod(h, v.num_weights);
ufbxt_hash_real(h, v.dq_weight);
}
ufbxt_noinline static void ufbxt_hash_skin_weight_imp(ufbxt_hash *h, ufbx_skin_weight v)
{
ufbxt_hash_pod(h, v.cluster_index);
ufbxt_hash_real(h, v.weight);
}
ufbxt_noinline static void ufbxt_hash_skin_deformer_imp(ufbxt_hash *h, const ufbx_skin_deformer *v)
{
ufbxt_hash_pod(h, v->skinning_method);
ufbxt_hash_list(h, v->clusters, ufbxt_hash_element_ref_imp);
ufbxt_hash_list(h, v->vertices, ufbxt_hash_skin_vertex_imp);
ufbxt_hash_list(h, v->weights, ufbxt_hash_skin_weight_imp);
ufbxt_hash_size_t(h, v->max_weights_per_vertex);
ufbxt_hash_size_t(h, v->num_dq_weights);
ufbxt_hash_list(h, v->dq_vertices, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->dq_weights, ufbxt_hash_real_imp);
}
ufbxt_noinline static void ufbxt_hash_skin_cluster_imp(ufbxt_hash *h, const ufbx_skin_cluster *v)
{
ufbxt_hash_element_ref(h, v->bone_node);
ufbxt_hash_matrix(h, v->geometry_to_bone);
ufbxt_hash_matrix(h, v->mesh_node_to_bone);
ufbxt_hash_matrix(h, v->bind_to_world);
ufbxt_hash_matrix(h, v->geometry_to_world);
ufbxt_hash_transform(h, v->geometry_to_world_transform);
ufbxt_hash_size_t(h, v->num_weights);
ufbxt_hash_list(h, v->vertices, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->weights, ufbxt_hash_real_imp);
}
ufbxt_noinline static void ufbxt_hash_blend_deformer_imp(ufbxt_hash *h, const ufbx_blend_deformer *v)
{
ufbxt_hash_list(h, v->channels, ufbxt_hash_element_ref_imp);
}
ufbxt_noinline static void ufbxt_hash_blend_keyframe_imp(ufbxt_hash *h, const ufbx_blend_keyframe *v)
{
ufbxt_hash_element_ref(h, v->shape);
ufbxt_hash_real(h, v->target_weight);
ufbxt_hash_real(h, v->effective_weight);
}
ufbxt_noinline static void ufbxt_hash_blend_channel_imp(ufbxt_hash *h, const ufbx_blend_channel *v)
{
ufbxt_hash_real(h, v->weight);
ufbxt_hash_list_ptr(h, v->keyframes, ufbxt_hash_blend_keyframe_imp);
}
ufbxt_noinline static void ufbxt_hash_blend_shape_imp(ufbxt_hash *h, const ufbx_blend_shape *v)
{
ufbxt_hash_size_t(h, v->num_offsets);
ufbxt_hash_list(h, v->offset_vertices, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->position_offsets, ufbxt_hash_vec3_imp);
ufbxt_hash_list(h, v->normal_offsets, ufbxt_hash_vec3_imp);
}
ufbxt_noinline static void ufbxt_hash_cache_frame_imp(ufbxt_hash *h, const ufbx_cache_frame *v)
{
ufbxt_hash_string(h, v->channel);
ufbxt_hash_double(h, v->time);
ufbxt_hash_pod(h, v->file_format);
ufbxt_hash_pod(h, v->data_format);
ufbxt_hash_pod(h, v->data_encoding);
ufbxt_hash_pod(h, v->data_offset);
ufbxt_hash_pod(h, v->data_count);
ufbxt_hash_pod(h, v->data_element_bytes);
ufbxt_hash_pod(h, v->data_total_bytes);
}
ufbxt_noinline static void ufbxt_hash_cache_channel_imp(ufbxt_hash *h, const ufbx_cache_channel *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_pod(h, v->interpretation);
ufbxt_hash_string(h, v->interpretation_name);
ufbxt_hash_list_ptr(h, v->frames, ufbxt_hash_cache_frame_imp);
}
ufbxt_noinline static void ufbxt_hash_geometry_cache_imp(ufbxt_hash *h, const ufbx_geometry_cache *v)
{
ufbxt_hash_list_ptr(h, v->channels, ufbxt_hash_cache_channel_imp);
ufbxt_hash_list_ptr(h, v->frames, ufbxt_hash_cache_frame_imp);
ufbxt_hash_list(h, v->extra_info, ufbxt_hash_string_imp);
}
#define ufbxt_hash_geometry_cache(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_geometry_cache_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_cache_deformer_imp(ufbxt_hash *h, const ufbx_cache_deformer *v)
{
ufbxt_hash_string(h, v->channel);
ufbxt_hash_element_ref(h, v->file);
}
ufbxt_noinline static void ufbxt_hash_cache_file_imp(ufbxt_hash *h, const ufbx_cache_file *v)
{
ufbxt_hash_string(h, v->absolute_filename);
ufbxt_hash_string(h, v->relative_filename);
ufbxt_hash_blob(h, v->raw_absolute_filename);
ufbxt_hash_blob(h, v->raw_relative_filename);
if (v->external_cache) ufbxt_hash_geometry_cache(h, v->external_cache);
}
ufbxt_noinline static void ufbxt_hash_material_map_imp(ufbxt_hash *h, const ufbx_material_map *v)
{
ufbxt_hash_vec4(h, v->value_vec4);
ufbxt_hash_pod(h, v->value_int);
ufbxt_hash_element_ref(h, v->texture);
ufbxt_hash_pod(h, v->has_value);
ufbxt_hash_pod(h, v->texture_enabled);
ufbxt_hash_pod(h, v->value_components);
}
ufbxt_noinline static void ufbxt_hash_material_feature_imp(ufbxt_hash *h, const ufbx_material_feature_info *v)
{
ufbxt_hash_pod(h, v->enabled);
ufbxt_hash_pod(h, v->is_explicit);
}
ufbxt_noinline static void ufbxt_hash_material_texture_imp(ufbxt_hash *h, const ufbx_material_texture *v)
{
ufbxt_hash_string(h, v->material_prop);
ufbxt_hash_string(h, v->shader_prop);
ufbxt_hash_element_ref(h, v->texture);
}
ufbxt_noinline static void ufbxt_hash_material_imp(ufbxt_hash *h, const ufbx_material *v)
{
ufbxt_push_tag(h, "fbx");
for (size_t i = 0; i < UFBX_MATERIAL_FBX_MAP_COUNT; i++) {
ufbxt_push_tag_index(h, i);
ufbxt_hash_material_map_imp(h, &v->fbx.maps[i]);
ufbxt_pop_tag(h);
}
ufbxt_pop_tag(h);
ufbxt_push_tag(h, "pbr");
for (size_t i = 0; i < UFBX_MATERIAL_PBR_MAP_COUNT; i++) {
ufbxt_push_tag_index(h, i);
ufbxt_hash_material_map_imp(h, &v->pbr.maps[i]);
ufbxt_pop_tag(h);
}
ufbxt_pop_tag(h);
ufbxt_push_tag(h, "features");
for (size_t i = 0; i < UFBX_MATERIAL_FEATURE_COUNT; i++) {
ufbxt_push_tag_index(h, i);
ufbxt_hash_material_feature_imp(h, &v->features.features[i]);
ufbxt_pop_tag(h);
}
ufbxt_pop_tag(h);
ufbxt_hash_pod(h, v->shader_type);
ufbxt_hash_element_ref(h, v->shader);
ufbxt_hash_string(h, v->shading_model_name);
ufbxt_hash_string(h, v->shader_prop_prefix);
ufbxt_hash_list_ptr(h, v->textures, ufbxt_hash_material_texture_imp);
}
ufbxt_noinline static void ufbxt_hash_texture_layer_imp(ufbxt_hash *h, const ufbx_texture_layer v)
{
ufbxt_hash_element_ref(h, v.texture);
ufbxt_hash_pod(h, v.blend_mode);
ufbxt_hash_real(h, v.alpha);
}
ufbxt_noinline static void ufbxt_hash_shader_texture_input_imp(ufbxt_hash *h, const ufbx_shader_texture_input *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_vec4(h, v->value_vec4);
ufbxt_hash_pod(h, v->value_int);
ufbxt_hash_string(h, v->value_str);
ufbxt_hash_blob(h, v->value_blob);
ufbxt_hash_element_ref(h, v->texture);
ufbxt_hash_pod(h, v->texture_enabled);
ufbxt_hash_prop_ref(h, v->prop);
ufbxt_hash_prop_ref(h, v->texture_prop);
ufbxt_hash_prop_ref(h, v->texture_enabled_prop);
}
ufbxt_noinline static void ufbxt_hash_shader_texture_imp(ufbxt_hash *h, const ufbx_shader_texture *v)
{
ufbxt_hash_pod(h, v->type);
ufbxt_hash_string(h, v->shader_name);
ufbxt_hash_pod(h, v->shader_type_id);
ufbxt_hash_list_ptr(h, v->inputs, ufbxt_hash_shader_texture_input_imp);
ufbxt_hash_string(h, v->shader_source);
ufbxt_hash_blob(h, v->raw_shader_source);
ufbxt_hash_element_ref(h, v->main_texture);
ufbxt_hash_pod(h, v->main_texture_output_index);
ufbxt_hash_string(h, v->prop_prefix);
}
#define ufbxt_hash_shader_texture(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_shader_texture_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_texture_imp(ufbxt_hash *h, const ufbx_texture *v)
{
ufbxt_hash_pod(h, v->type);
ufbxt_hash_string(h, v->absolute_filename);
ufbxt_hash_string(h, v->relative_filename);
ufbxt_hash_blob(h, v->raw_absolute_filename);
ufbxt_hash_blob(h, v->raw_relative_filename);
ufbxt_hash_blob(h, v->content);
ufbxt_hash_element_ref(h, v->video);
ufbxt_hash_pod(h, v->file_index);
ufbxt_hash_pod(h, v->has_file);
ufbxt_hash_list(h, v->layers, ufbxt_hash_texture_layer_imp);
ufbxt_hash_string(h, v->uv_set);
ufbxt_hash_pod(h, v->wrap_u);
ufbxt_hash_pod(h, v->wrap_v);
ufbxt_hash_pod(h, v->has_uv_transform);
ufbxt_hash_transform(h, v->uv_transform);
ufbxt_hash_matrix(h, v->texture_to_uv);
ufbxt_hash_matrix(h, v->uv_to_texture);
ufbxt_hash_list(h, v->file_textures, ufbxt_hash_element_ref_imp);
if (v->shader) {
ufbxt_hash_shader_texture(h, v->shader);
}
}
ufbxt_noinline static void ufbxt_hash_video_imp(ufbxt_hash *h, const ufbx_video *v)
{
ufbxt_hash_string(h, v->absolute_filename);
ufbxt_hash_string(h, v->relative_filename);
ufbxt_hash_blob(h, v->raw_absolute_filename);
ufbxt_hash_blob(h, v->raw_relative_filename);
ufbxt_hash_blob(h, v->content);
}
ufbxt_noinline static void ufbxt_hash_shader_imp(ufbxt_hash *h, const ufbx_shader *v)
{
ufbxt_hash_pod(h, v->type);
ufbxt_hash_list(h, v->bindings, ufbxt_hash_element_ref_imp);
}
ufbxt_noinline static void ufbxt_hash_shader_prop_binding_imp(ufbxt_hash *h, ufbx_shader_prop_binding v)
{
ufbxt_hash_string(h, v.shader_prop);
ufbxt_hash_string(h, v.material_prop);
}
ufbxt_noinline static void ufbxt_hash_shader_binding_imp(ufbxt_hash *h, const ufbx_shader_binding *v)
{
ufbxt_hash_list(h, v->prop_bindings, ufbxt_hash_shader_prop_binding_imp);
}
ufbxt_noinline static void ufbxt_hash_anim_layer_desc_imp(ufbxt_hash *h, ufbx_anim_layer_desc v)
{
ufbxt_hash_element_ref(h, v.layer);
ufbxt_hash_real(h, v.weight);
}
ufbxt_noinline static void ufbxt_hash_anim_imp(ufbxt_hash *h, const ufbx_anim *v)
{
ufbxt_hash_list(h, v->layers, ufbxt_hash_anim_layer_desc_imp);
ufbxt_hash_pod(h, v->ignore_connections);
ufbxt_hash_double(h, v->time_begin);
ufbxt_hash_double(h, v->time_end);
}
#define ufbxt_hash_anim(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_anim_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_anim_stack_imp(ufbxt_hash *h, const ufbx_anim_stack *v)
{
ufbxt_hash_double(h, v->time_begin);
ufbxt_hash_double(h, v->time_end);
ufbxt_hash_list(h, v->layers, ufbxt_hash_element_ref_imp);
ufbxt_hash_anim(h, &v->anim);
}
ufbxt_noinline static void ufbxt_hash_anim_prop_imp(ufbxt_hash *h, const ufbx_anim_prop *v)
{
ufbxt_hash_element_ref(h, v->element);
ufbxt_hash_pod(h, v->_internal_key);
ufbxt_hash_string(h, v->prop_name);
ufbxt_hash_element_ref(h, v->anim_value);
}
ufbxt_noinline static void ufbxt_hash_anim_layer_imp(ufbxt_hash *h, const ufbx_anim_layer *v)
{
ufbxt_hash_real(h, v->weight);
ufbxt_hash_pod(h, v->weight_is_animated);
ufbxt_hash_pod(h, v->blended);
ufbxt_hash_pod(h, v->additive);
ufbxt_hash_pod(h, v->compose_rotation);
ufbxt_hash_pod(h, v->compose_scale);
ufbxt_hash_list(h, v->anim_values, ufbxt_hash_element_ref_imp);
ufbxt_hash_list_ptr(h, v->anim_props, ufbxt_hash_anim_prop_imp);
ufbxt_hash_anim(h, &v->anim);
ufbxt_hash_pod(h, v->_min_element_id);
ufbxt_hash_pod(h, v->_max_element_id);
ufbxt_hash_pod(h, v->_element_id_bitmask[0]);
ufbxt_hash_pod(h, v->_element_id_bitmask[1]);
ufbxt_hash_pod(h, v->_element_id_bitmask[2]);
ufbxt_hash_pod(h, v->_element_id_bitmask[3]);
}
ufbxt_noinline static void ufbxt_hash_anim_value_imp(ufbxt_hash *h, const ufbx_anim_value *v)
{
ufbxt_hash_vec3(h, v->default_value);
ufbxt_hash_array(h, v->curves, ufbxt_hash_element_ref_imp);
}
ufbxt_noinline static void ufbxt_hash_tangent_imp(ufbxt_hash *h, ufbx_tangent v)
{
ufbxt_hash_float(h, v.dx);
ufbxt_hash_float(h, v.dy);
}
#define ufbxt_hash_tangent(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_tangent_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_keyframe_imp(ufbxt_hash *h, const ufbx_keyframe *v)
{
ufbxt_hash_double(h, v->time);
ufbxt_hash_real(h, v->value);
ufbxt_hash_pod(h, v->interpolation);
ufbxt_hash_tangent(h, v->left);
ufbxt_hash_tangent(h, v->right);
}
ufbxt_noinline static void ufbxt_hash_anim_curve_imp(ufbxt_hash *h, const ufbx_anim_curve *v)
{
ufbxt_hash_list_ptr(h, v->keyframes, ufbxt_hash_keyframe_imp);
}
ufbxt_noinline static void ufbxt_hash_display_layer_imp(ufbxt_hash *h, const ufbx_display_layer *v)
{
ufbxt_hash_list(h, v->nodes, ufbxt_hash_element_ref_imp);
ufbxt_hash_pod(h, v->visible);
ufbxt_hash_pod(h, v->frozen);
ufbxt_hash_vec3(h, v->ui_color);
}
ufbxt_noinline static void ufbxt_hash_selection_set_imp(ufbxt_hash *h, const ufbx_selection_set *v)
{
ufbxt_hash_list(h, v->nodes, ufbxt_hash_element_ref_imp);
}
ufbxt_noinline static void ufbxt_hash_selection_node_imp(ufbxt_hash *h, const ufbx_selection_node *v)
{
ufbxt_hash_element_ref(h, v->target_node);
ufbxt_hash_element_ref(h, v->target_mesh);
ufbxt_hash_pod(h, v->include_node);
ufbxt_hash_list(h, v->vertices, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->edges, ufbxt_hash_pod_imp);
ufbxt_hash_list(h, v->faces, ufbxt_hash_pod_imp);
}
ufbxt_noinline static void ufbxt_hash_character_imp(ufbxt_hash *h, const ufbx_character *v)
{
}
ufbxt_noinline static void ufbxt_hash_constraint_target_imp(ufbxt_hash *h, const ufbx_constraint_target *v)
{
ufbxt_hash_element_ref(h, v->node);
ufbxt_hash_real(h, v->weight);
ufbxt_hash_transform(h, v->transform);
}
ufbxt_noinline static void ufbxt_hash_constraint_imp(ufbxt_hash *h, const ufbx_constraint *v)
{
ufbxt_hash_pod(h, v->type);
ufbxt_hash_string(h, v->type_name);
ufbxt_hash_element_ref(h, v->node);
ufbxt_hash_list_ptr(h, v->targets, ufbxt_hash_constraint_target_imp);
ufbxt_hash_real(h, v->weight);
ufbxt_hash_pod(h, v->active);
ufbxt_hash_array(h, v->constrain_translation, ufbxt_hash_pod_imp);
ufbxt_hash_array(h, v->constrain_rotation, ufbxt_hash_pod_imp);
ufbxt_hash_array(h, v->constrain_scale, ufbxt_hash_pod_imp);
ufbxt_hash_transform(h, v->transform_offset);
ufbxt_hash_vec3(h, v->aim_vector);
ufbxt_hash_pod(h, v->aim_up_type);
ufbxt_hash_element_ref(h, v->aim_up_node);
ufbxt_hash_vec3(h, v->aim_up_vector);
ufbxt_hash_element_ref(h, v->ik_effector);
ufbxt_hash_element_ref(h, v->ik_end_node);
ufbxt_hash_vec3(h, v->ik_pole_vector);
}
ufbxt_noinline static void ufbxt_hash_bone_pose_imp(ufbxt_hash *h, const ufbx_bone_pose *v)
{
ufbxt_hash_element_ref(h, v->bone_node);
ufbxt_hash_matrix(h, v->bone_to_world);
}
ufbxt_noinline static void ufbxt_hash_pose_imp(ufbxt_hash *h, const ufbx_pose *v)
{
ufbxt_hash_pod(h, v->bind_pose);
ufbxt_hash_list_ptr(h, v->bone_poses, ufbxt_hash_bone_pose_imp);
}
ufbxt_noinline static void ufbxt_hash_metadata_object_imp(ufbxt_hash *h, const ufbx_metadata_object *v)
{
}
ufbxt_noinline static void ufbxt_hash_texture_file_imp(ufbxt_hash *h, const ufbx_texture_file *v)
{
ufbxt_hash_pod(h, v->index);
ufbxt_hash_string(h, v->absolute_filename);
ufbxt_hash_string(h, v->relative_filename);
ufbxt_hash_blob(h, v->raw_absolute_filename);
ufbxt_hash_blob(h, v->raw_relative_filename);
ufbxt_hash_blob(h, v->content);
}
ufbxt_noinline static void ufbxt_hash_name_element_imp(ufbxt_hash *h, const ufbx_name_element *v)
{
ufbxt_hash_string(h, v->name);
ufbxt_hash_pod(h, v->type);
ufbxt_hash_pod(h, v->_internal_key);
ufbxt_hash_element_ref(h, v->element);
}
ufbxt_noinline static void ufbxt_hash_application_imp(ufbxt_hash *h, const ufbx_application *v)
{
ufbxt_hash_string(h, v->vendor);
ufbxt_hash_string(h, v->name);
ufbxt_hash_string(h, v->version);
}
#define ufbxt_hash_application(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_application_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_warning_imp(ufbxt_hash *h, const ufbx_warning *v)
{
ufbxt_hash_pod(h, v->type);
ufbxt_hash_size_t(h, v->count);
// `v->description` omitted as it contains path-specific string
}
ufbxt_noinline static void ufbxt_hash_metadata_imp(ufbxt_hash *h, const ufbx_metadata *v)
{
ufbxt_hash_pod(h, v->ascii);
ufbxt_hash_pod(h, v->version);
ufbxt_hash_string(h, v->creator);
ufbxt_hash_pod(h, v->is_unsafe);
ufbxt_hash_pod(h, v->big_endian);
ufbxt_hash_pod(h, v->exporter);
ufbxt_hash_pod(h, v->exporter_version);
ufbxt_hash_props(h, &v->scene_props);
ufbxt_hash_application(h, &v->original_application);
ufbxt_hash_application(h, &v->latest_application);
ufbxt_hash_list_ptr(h, v->warnings, ufbxt_hash_warning_imp);
}
#define ufbxt_hash_metadata(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_metadata_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_coordinate_axes_imp(ufbxt_hash *h, ufbx_coordinate_axes v)
{
ufbxt_hash_pod(h, v.right);
ufbxt_hash_pod(h, v.up);
ufbxt_hash_pod(h, v.front);
}
#define ufbxt_hash_coordinate_axes(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_coordinate_axes_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_scene_settings_imp(ufbxt_hash *h, const ufbx_scene_settings *v)
{
ufbxt_hash_props(h, &v->props);
ufbxt_hash_coordinate_axes(h, v->axes);
ufbxt_hash_real(h, v->unit_meters);
ufbxt_hash_double(h, v->frames_per_second);
ufbxt_hash_vec3(h, v->ambient_color);
ufbxt_hash_pod(h, v->time_mode);
ufbxt_hash_pod(h, v->time_protocol);
ufbxt_hash_pod(h, v->snap_mode);
ufbxt_hash_pod(h, v->original_axis_up);
ufbxt_hash_pod(h, v->original_unit_meters);
}
#define ufbxt_hash_scene_settings(h, v) (ufbxt_push_tag(h, #v), ufbxt_hash_scene_settings_imp(h, v), ufbxt_pop_tag(h))
ufbxt_noinline static void ufbxt_hash_scene_imp(ufbxt_hash *h, const ufbx_scene *v)
{
ufbxt_hash_metadata(h, &v->metadata);
ufbxt_hash_scene_settings(h, &v->settings);
ufbxt_hash_element_ref(h, v->root_node);
ufbxt_hash_anim(h, &v->anim);
ufbxt_hash_anim(h, &v->combined_anim);
ufbxt_hash_list(h, v->elements, ufbxt_hash_element_imp);
ufbxt_hash_list(h, v->unknowns, ufbxt_hash_unknown_imp);
ufbxt_hash_list(h, v->nodes, ufbxt_hash_node_imp);
ufbxt_hash_list(h, v->meshes, ufbxt_hash_mesh_imp);
ufbxt_hash_list(h, v->lights, ufbxt_hash_light_imp);
ufbxt_hash_list(h, v->cameras, ufbxt_hash_camera_imp);
ufbxt_hash_list(h, v->bones, ufbxt_hash_bone_imp);
ufbxt_hash_list(h, v->empties, ufbxt_hash_empty_imp);
ufbxt_hash_list(h, v->line_curves, ufbxt_hash_line_curve_imp);
ufbxt_hash_list(h, v->nurbs_curves, ufbxt_hash_nurbs_curve_imp);
ufbxt_hash_list(h, v->nurbs_surfaces, ufbxt_hash_nurbs_surface_imp);
ufbxt_hash_list(h, v->nurbs_trim_surfaces, ufbxt_hash_nurbs_trim_surface_imp);
ufbxt_hash_list(h, v->nurbs_trim_boundaries, ufbxt_hash_nurbs_trim_boundary_imp);
ufbxt_hash_list(h, v->procedural_geometries, ufbxt_hash_procedural_geometry_imp);
ufbxt_hash_list(h, v->stereo_cameras, ufbxt_hash_stereo_camera_imp);
ufbxt_hash_list(h, v->camera_switchers, ufbxt_hash_camera_switcher_imp);
ufbxt_hash_list(h, v->markers, ufbxt_hash_marker_imp);
ufbxt_hash_list(h, v->lod_groups, ufbxt_hash_lod_group_imp);
ufbxt_hash_list(h, v->skin_deformers, ufbxt_hash_skin_deformer_imp);
ufbxt_hash_list(h, v->skin_clusters, ufbxt_hash_skin_cluster_imp);
ufbxt_hash_list(h, v->blend_deformers, ufbxt_hash_blend_deformer_imp);
ufbxt_hash_list(h, v->blend_channels, ufbxt_hash_blend_channel_imp);
ufbxt_hash_list(h, v->blend_shapes, ufbxt_hash_blend_shape_imp);
ufbxt_hash_list(h, v->cache_deformers, ufbxt_hash_cache_deformer_imp);
ufbxt_hash_list(h, v->cache_files, ufbxt_hash_cache_file_imp);
ufbxt_hash_list(h, v->materials, ufbxt_hash_material_imp);
ufbxt_hash_list(h, v->textures, ufbxt_hash_texture_imp);
ufbxt_hash_list(h, v->videos, ufbxt_hash_video_imp);
ufbxt_hash_list(h, v->shaders, ufbxt_hash_shader_imp);
ufbxt_hash_list(h, v->shader_bindings, ufbxt_hash_shader_binding_imp);
ufbxt_hash_list(h, v->anim_stacks, ufbxt_hash_anim_stack_imp);
ufbxt_hash_list(h, v->anim_layers, ufbxt_hash_anim_layer_imp);
ufbxt_hash_list(h, v->anim_values, ufbxt_hash_anim_value_imp);
ufbxt_hash_list(h, v->anim_curves, ufbxt_hash_anim_curve_imp);
ufbxt_hash_list(h, v->display_layers, ufbxt_hash_display_layer_imp);
ufbxt_hash_list(h, v->selection_sets, ufbxt_hash_selection_set_imp);
ufbxt_hash_list(h, v->selection_nodes, ufbxt_hash_selection_node_imp);
ufbxt_hash_list(h, v->characters, ufbxt_hash_character_imp);
ufbxt_hash_list(h, v->constraints, ufbxt_hash_constraint_imp);
ufbxt_hash_list(h, v->poses, ufbxt_hash_pose_imp);
ufbxt_hash_list(h, v->metadata_objects, ufbxt_hash_metadata_object_imp);
ufbxt_hash_list_ptr(h, v->texture_files, ufbxt_hash_texture_file_imp);
ufbxt_hash_list(h, v->connections_src, ufbxt_hash_connection_imp);
ufbxt_hash_list(h, v->connections_dst, ufbxt_hash_connection_imp);
ufbxt_hash_list_ptr(h, v->elements_by_name, ufbxt_hash_name_element_imp);
if (v->dom_root) ufbxt_hash_dom_node(h, v->dom_root);
}
ufbxt_noinline static uint64_t ufbxt_hash_scene(const ufbx_scene *v, FILE *dump_file)
{
ufbxt_hash h;
ufbxt_hash_init(&h, dump_file);
ufbxt_hash_scene_imp(&h, v);
return ufbxt_hash_finish(&h);
}
#endif