Saving progress. Parsing of nodes and scenes arrays of glb object
This commit is contained in:
parent
09df9f4e2d
commit
2dd4ad0d7b
@ -7,4 +7,5 @@ void generate_l1_gltf_headers() {
|
||||
SpanU8 l = cstr("l1"), ns = cstr("");
|
||||
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("GltfScene"), true, false);
|
||||
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("GltfNode"), true, false);
|
||||
generate_eve_span_company_for_non_primitive_non_clonable(l, ns, cstr("Gltf"), true, false);
|
||||
}
|
||||
|
||||
@ -5,8 +5,12 @@
|
||||
/* These headers are guarded */
|
||||
void generate_util_temp_very_base_headers() {
|
||||
SpanU8 l = cstr("l1"), ns = cstr("");
|
||||
SpanU8 T_codegen_VecAndSpan[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64")};
|
||||
SpanU8 T_codegen_Option[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64"), cstr("S64")};
|
||||
SpanU8 T_codegen_VecAndSpan[] = {
|
||||
cstr("U8"), cstr("U16"), cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64"), cstr("Flt32"), cstr("Flt64")
|
||||
};
|
||||
SpanU8 T_codegen_Option[] = {
|
||||
cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64"), cstr("S64"), cstr("Flt32"), cstr("Flt64")
|
||||
};
|
||||
SpanU8 T_codegen_VecAndSpan_of_Vec[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")};
|
||||
SpanU8 T_codegen_VecAndSpan_of_Span[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")};
|
||||
for (size_t i = 0; i < ARRAY_SIZE(T_codegen_VecAndSpan); i++) {
|
||||
@ -47,6 +51,13 @@ void generate_util_temp_very_base_headers() {
|
||||
VecU8_drop(SpanT);
|
||||
VecU8_drop(dependency);
|
||||
}
|
||||
|
||||
// todo: maybe make these for all other int types too
|
||||
generate_Option_templ_inst_guarded_header(l, ns, cstr("#include \"VecAndSpan_U8.h\""),
|
||||
(option_template_instantiation_op){.T = cstr("SpanU8"), .t_primitive = true});
|
||||
generate_Option_templ_inst_guarded_header(l, ns, cstr("#include \"VecAndSpan_U64.h\""),
|
||||
(option_template_instantiation_op){.T = cstr("VecU64"), .t_primitive = false});
|
||||
|
||||
generate_guarded_span_company_for_primitive(l, ns, cstr("CSTR"), cstr(""), true, false);
|
||||
|
||||
generate_ResultType_templ_inst_guarded_header(l, ns,
|
||||
|
||||
@ -12,6 +12,8 @@ typedef int8_t S8;
|
||||
typedef int16_t S16;
|
||||
typedef int32_t S32;
|
||||
typedef int64_t S64;
|
||||
typedef float Flt32;
|
||||
typedef double Flt64;
|
||||
|
||||
// todo: move these to util (l1) template instantiation too
|
||||
#define int_minmax_function_Definition(T) \
|
||||
|
||||
@ -238,32 +238,7 @@ GenericMeshTopology alice_expect_read_generic_mesh_from_obj_file(VecU8 file_path
|
||||
OptionGenericMeshTopology option = alice_read_generic_mesh_from_obj_file(file_path);
|
||||
return OptionGenericMeshTopology_expect(option);
|
||||
}
|
||||
|
||||
/* Temporary function for some experiments. Will rewrite/delete later */
|
||||
GenericMeshTopology alice_expect_read_generic_mesh_from_glb_file(VecU8 file_path) {
|
||||
GLBFileSegments segments;
|
||||
int code = glb_file_get_segments(VecU8_to_span(&file_path), &segments);
|
||||
if (code) {
|
||||
abortf("Something went wrong when reading glb container\n");
|
||||
}
|
||||
|
||||
/* default_scene "scene" : Option<index into scenes>
|
||||
*
|
||||
* scenes "scenes" : Vec<Scene> {
|
||||
* if "scenes" field is not present, it counts as empty vector }
|
||||
*
|
||||
* nodes "nodes" : Vec<Node> {
|
||||
* if "nodes" field is not present, it counts as empty vector }
|
||||
*/
|
||||
|
||||
OptionU32 default_scene = None_U32();
|
||||
|
||||
|
||||
|
||||
VecU8_print(VecU8_fmt("default_scene: %v\n",
|
||||
default_scene.variant == Option_None ? vcstr("None") : U64_stringification(default_scene.some)));
|
||||
|
||||
VecGenericMeshVertexInc vertices = VecGenericMeshVertexInc_new();
|
||||
VecU32 indexes = VecU32_new();
|
||||
return (GenericMeshTopology){.vertices = vertices, .indexes = indexes};
|
||||
}
|
||||
/*
|
||||
ret_error = VecU8_fmt("");
|
||||
goto destroy_everything_return_error;
|
||||
*/
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include "json_encoded.h"
|
||||
#include "../../../gen/l1/VecAndSpan_U64.h"
|
||||
#include "../../../gen/l1/OptionU32.h"
|
||||
#include "../../../gen/l1/OptionU64.h"
|
||||
#include "../../l1_5/core/quaternion.h"
|
||||
|
||||
/* todo: add big endian support */
|
||||
@ -11,7 +11,7 @@
|
||||
typedef struct {
|
||||
U32 version;
|
||||
Json gltf;
|
||||
/* If length is 0, BIN segment is absent */
|
||||
/* If length is 0, BIN segment is absent. Keeps pointing at original string */
|
||||
SpanU8 bin_segment;
|
||||
} GLBFileSegments;
|
||||
|
||||
@ -19,42 +19,54 @@ void GLBFileSegments_drop(GLBFileSegments self){
|
||||
Json_drop(self.gltf);
|
||||
}
|
||||
|
||||
/* Can point to some string (.ok can contain span). Be careful with lifetimes */
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
union {
|
||||
GLBFileSegments ok;
|
||||
// this one has infinite lifetime
|
||||
SpanU8 err;
|
||||
};
|
||||
} ResultGLBFileSegmentsOrSpanU8;
|
||||
|
||||
/* Returns positive on error, 0 on ok */
|
||||
int glb_file_get_segments(SpanU8 file, GLBFileSegments* ret){
|
||||
ResultGLBFileSegmentsOrSpanU8 glb_file_get_segments(SpanU8 file){
|
||||
if (file.len < 12) {
|
||||
return 1;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err, .err=cstr("too smol")};
|
||||
}
|
||||
SpanU8 json_segment = {0, 0}; // length of 0 means segment is absent
|
||||
SpanU8 bin_segment = {0, 0}; // length of 0 means segment is absent
|
||||
if (*(const U32*)file.data != 0x46546C67) {
|
||||
return 2;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err, .err=cstr("magic number is incorrect")};
|
||||
}
|
||||
U32 version = *(const U32*)(file.data + 4);
|
||||
/* Nobody cares about version */
|
||||
if (*(const U32*)(file.data + 8) != file.len) {
|
||||
return 3;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err, .err=cstr("incorrect glb file length")};;
|
||||
}
|
||||
U64 cur = 12;
|
||||
while (cur < file.len) {
|
||||
if (cur + 8 > file.len) {
|
||||
return 4;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err,
|
||||
.err=cstr("out-of-bounds when reading segment header")};;
|
||||
}
|
||||
U32 chunk_length = *(const U32*)(file.data + cur);
|
||||
U32 chunk_type = *(const U32*)(file.data + cur + 4);
|
||||
if (cur + 8 + chunk_length > file.len) {
|
||||
return 5;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err,
|
||||
.err=cstr("out-of-bounds when reading segment data")};;
|
||||
}
|
||||
SpanU8 cur_segment = SpanU8_span(file, cur + 8, chunk_length);
|
||||
if (chunk_type == 0x4E4F534A) {
|
||||
if (json_segment.len > 0) {
|
||||
/* Illegal! Two json segments */
|
||||
return 6;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err, .err=cstr("two json segments")};;
|
||||
}
|
||||
json_segment = cur_segment;
|
||||
} else if (chunk_type == 0x004E4942) {
|
||||
if (bin_segment.len > 0) {
|
||||
/* Illegal! Two bin segments */
|
||||
return 7;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err, .err=cstr("two bin segments")};;
|
||||
}
|
||||
bin_segment = cur_segment;
|
||||
}
|
||||
@ -62,17 +74,15 @@ int glb_file_get_segments(SpanU8 file, GLBFileSegments* ret){
|
||||
}
|
||||
if (json_segment.len == 0) {
|
||||
/* Illegal, no json segment */
|
||||
return 8;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err, .err=cstr("no json segment in glb file")};;
|
||||
}
|
||||
SpanU8_print(json_segment);
|
||||
printf("\n");
|
||||
OptionJson parsed_json = json_decode(json_segment, 15);
|
||||
if (parsed_json.variant == Option_None) {
|
||||
return 9;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Err, .err=cstr("syntax error in json segment")};;
|
||||
}
|
||||
/* Everything is correct */
|
||||
*ret = (GLBFileSegments){.version = version, .gltf = parsed_json.some, .bin_segment = bin_segment};
|
||||
return 0;
|
||||
return (ResultGLBFileSegmentsOrSpanU8){.variant = Result_Ok,
|
||||
.ok = (GLBFileSegments){.version = version, .gltf = parsed_json.some, .bin_segment = bin_segment}};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@ -87,10 +97,35 @@ void GltfScene_drop(GltfScene self) {
|
||||
|
||||
#include "../../../gen/l1/eve/VecGltfScene.h"
|
||||
|
||||
typedef enum {
|
||||
GltfNodeTransformation_none,
|
||||
GltfNodeTransformation_trs,
|
||||
GltfNodeTransformation_mat,
|
||||
} GltfNodeTransformation_variant;
|
||||
|
||||
typedef struct {
|
||||
vec3 translation;
|
||||
quaternion_t rotation;
|
||||
vec3 scale;
|
||||
} GltfNodeTransformationTRS;
|
||||
|
||||
typedef struct {
|
||||
GltfNodeTransformation_variant variant;
|
||||
union {
|
||||
GltfNodeTransformationTRS trs;
|
||||
mat4 mat;
|
||||
};
|
||||
} GltfNodeTransformation;
|
||||
|
||||
typedef struct {
|
||||
VecU8 name;
|
||||
VecU64 children;
|
||||
OptionU32 mesh;
|
||||
OptionU64 mesh;
|
||||
GltfNodeTransformation trans;
|
||||
|
||||
/* These are not specified in gltf file */
|
||||
bool has_parent;
|
||||
U64 parent; /* Relevant only when self.has_parent = true */
|
||||
} GltfNode;
|
||||
|
||||
void GltfNode_drop(GltfNode self) {
|
||||
@ -99,3 +134,274 @@ void GltfNode_drop(GltfNode self) {
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/eve/VecGltfNode.h"
|
||||
|
||||
#include "../../../gen/l1/VecAndSpan_VecU8.h"
|
||||
|
||||
typedef struct {
|
||||
VecVecU8 external_files;
|
||||
VecGltfNode nodes;
|
||||
VecGltfScene scenes;
|
||||
OptionU64 default_scene;
|
||||
} GltfFileStructure;
|
||||
|
||||
void GltfFileStructure_drop(GltfFileStructure self) {
|
||||
VecVecU8_drop(self.external_files);
|
||||
VecGltfNode_drop(self.nodes);
|
||||
VecGltfScene_drop(self.scenes);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
union {
|
||||
GltfFileStructure ok;
|
||||
VecU8 err;
|
||||
};
|
||||
} ResultGltfFileStructureOrVecU8;
|
||||
|
||||
ResultGltfFileStructureOrVecU8 glb_file_get_structure(GLBFileSegments* segments) {
|
||||
const Json* json = &segments->gltf;
|
||||
// VecU8_print(json_encode(json));
|
||||
// printf("\n");
|
||||
|
||||
/* default_scene "scene" : Option<index into scenes>
|
||||
*
|
||||
* scenes "scenes" : Vec<Scene> {
|
||||
* if "scenes" field is not present, it counts as empty vector }
|
||||
*
|
||||
* nodes "nodes" : Vec<Node> {
|
||||
* if "nodes" field is not present, it counts as empty vector }
|
||||
*/
|
||||
|
||||
VecU8 ret_error = VecU8_new();
|
||||
OptionU64 default_scene = None_U64();
|
||||
VecGltfScene scenes = VecGltfScene_new();
|
||||
VecGltfNode nodes = VecGltfNode_new();
|
||||
VecVecU8 external_files = VecVecU8_new();
|
||||
|
||||
|
||||
const Json* json_default_scene = Json_dict_at(json, cstr("scene"));
|
||||
if (json_default_scene) {
|
||||
default_scene = Json_try_as_u64(json_default_scene);
|
||||
if (default_scene.variant != Option_Some) {
|
||||
ret_error = VecU8_fmt("$scene is not an positive integer");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
|
||||
const Json* json_scenes = Json_dict_at(json, cstr("scenes"));
|
||||
if (json_scenes) {
|
||||
if (json_scenes->variant != Json_arr){
|
||||
ret_error = VecU8_fmt("$scenes is not an array");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
const VecJson* arr_scenes = &json_scenes->arr;
|
||||
scenes = VecGltfScene_new_reserved(arr_scenes->len);
|
||||
for (size_t i = 0; i < arr_scenes->len; i++) {
|
||||
const Json* json_scene = &arr_scenes->buf[i];
|
||||
|
||||
VecU8 name = VecU8_new(); // free
|
||||
const Json* json_name = Json_dict_at(json_scene, cstr("name"));
|
||||
if (json_name) {
|
||||
if (json_name->variant != Json_str) {
|
||||
ret_error = VecU8_fmt("$scenes[%u].name is not a string", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
name = VecU8_clone(&json_name->str);
|
||||
}
|
||||
|
||||
VecU64 cur_scene_nodes = VecU64_new();
|
||||
const Json* json_cur_scene_nodes = Json_dict_at(json_scene, cstr("nodes"));
|
||||
if (json_cur_scene_nodes) {
|
||||
OptionVecU64 opt_cs_nodes = Json_try_as_arr_of_u64(json_cur_scene_nodes);
|
||||
if (opt_cs_nodes.variant != Option_Some) {
|
||||
ret_error = VecU8_fmt("$scenes[%u].nodes is not an array of positive integers", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
cur_scene_nodes = opt_cs_nodes.some;
|
||||
}
|
||||
VecGltfScene_append(&scenes, (GltfScene){.name = name, .nodes = cur_scene_nodes});
|
||||
}
|
||||
}
|
||||
|
||||
const Json* json_nodes = Json_dict_at(json, cstr("nodes"));
|
||||
if (json_nodes) {
|
||||
if (json_nodes->variant != Json_arr) {
|
||||
ret_error = VecU8_fmt("$nodes is not an array");
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
const VecJson* arr_nodes = &json_nodes->arr;
|
||||
nodes = VecGltfNode_new_reserved(arr_nodes->len);
|
||||
for (size_t i = 0; i < arr_nodes->len; i++) {
|
||||
const Json* json_node = &arr_nodes->buf[i];
|
||||
|
||||
VecU8 name = VecU8_new(); // free
|
||||
const Json* json_name = Json_dict_at(json_node, cstr("name"));
|
||||
if (json_name) {
|
||||
if (json_name->variant != Json_str) {
|
||||
ret_error = VecU8_fmt("nodes[%u].name is not a string", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
name = VecU8_clone(&json_name->str);
|
||||
}
|
||||
|
||||
VecU64 children = VecU64_new();
|
||||
const Json* json_children = Json_dict_at(json_node, cstr("children"));
|
||||
if (json_children) {
|
||||
OptionVecU64 opt_children = Json_try_as_arr_of_u64(json_children);
|
||||
if (opt_children.variant != Option_Some) {
|
||||
ret_error = VecU8_fmt("$nodes[%u].children is not an array of positive integers", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
children = opt_children.some;
|
||||
}
|
||||
|
||||
OptionU64 mesh = None_U64();
|
||||
const Json* json_mesh = Json_dict_at(json_node, cstr("mesh"));
|
||||
if (json_mesh) {
|
||||
mesh = Json_try_as_u64(json_mesh);
|
||||
if (mesh.variant != Option_Some) {
|
||||
ret_error = VecU8_fmt("$nodes[%u].mesh is not an positive integer", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
|
||||
const Json* json_matrix = Json_dict_at(json_node, cstr("matrix"));
|
||||
const Json* json_translation = Json_dict_at(json_node, cstr("translation"));
|
||||
const Json* json_rotation = Json_dict_at(json_node, cstr("rotation"));
|
||||
const Json* json_scale = Json_dict_at(json_node, cstr("scale"));
|
||||
|
||||
bool has_trs = json_translation != NULL || json_rotation != NULL || json_scale != NULL;
|
||||
if (json_matrix && has_trs) {
|
||||
ret_error = VecU8_fmt("$nodes[%u] has both matrix and TRS present", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
|
||||
GltfNodeTransformation trans;
|
||||
if (json_matrix) {
|
||||
float md[16];
|
||||
if (!Json_try_as_MutSpanFlt32(json_matrix, (MutSpanFlt32){md, 16})) {
|
||||
ret_error = VecU8_fmt("nodes[%u].matrix is not an array of 16 floats", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
trans = (GltfNodeTransformation){.variant = GltfNodeTransformation_mat, .mat = {
|
||||
.x = {md[0], md[1], md[2], md[3]}, .y = {md[4], md[5], md[6], md[7]},
|
||||
.z = {md[8], md[9], md[10], md[11]}, .w = {md[12], md[13], md[14], md[15]}}};
|
||||
} else if (has_trs) {
|
||||
trans.variant = GltfNodeTransformation_trs;
|
||||
if (json_translation) {
|
||||
float data[3];
|
||||
if (!Json_try_as_MutSpanFlt32(json_translation, (MutSpanFlt32){data, 3})) {
|
||||
ret_error = VecU8_fmt("nodes[%u].translation is not an array of 3 floats", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
trans.trs.translation = (vec3){data[0], data[1], data[2]};
|
||||
} else {
|
||||
trans.trs.translation = (vec3){0};
|
||||
}
|
||||
if (json_rotation) {
|
||||
float data[4];
|
||||
if (!Json_try_as_MutSpanFlt32(json_rotation, (MutSpanFlt32){data, 4})) {
|
||||
ret_error = VecU8_fmt("nodes[%u].rotation is not an array of 4 floats", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
trans.trs.rotation = (quaternion_t){data[3], data[0], data[1], data[2]};
|
||||
} else {
|
||||
trans.trs.rotation = (quaternion_t){1, 0, 0, 0};
|
||||
}
|
||||
if (json_scale) {
|
||||
float data[3];
|
||||
if (!Json_try_as_MutSpanFlt32(json_scale, (MutSpanFlt32){data, 3})) {
|
||||
ret_error = VecU8_fmt("nodes[%u].scale is not an array of 3 floats", i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
trans.trs.scale = (vec3){data[0], data[1], data[2]};
|
||||
}
|
||||
} else {
|
||||
trans.variant = GltfNodeTransformation_none;
|
||||
}
|
||||
|
||||
VecGltfNode_append(&nodes, (GltfNode){.name = name, .children = children, .mesh = mesh,
|
||||
.trans = trans, .has_parent = false});
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we are doing some checks and filling fields that were not directly specified */
|
||||
for (size_t i = 0; i < nodes.len; i++) {
|
||||
const GltfNode* node = &nodes.buf[i];
|
||||
for (size_t jjj = 0; jjj < node->children.len; jjj++) {
|
||||
U64 n2 = node->children.buf[jjj];
|
||||
if (n2 >= nodes.len) {
|
||||
ret_error = VecU8_fmt("Node %u has child %u that is out-of-bounds of nodes array", i, n2);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
GltfNode* lower_node = &nodes.buf[n2];
|
||||
if (lower_node->has_parent) {
|
||||
ret_error = VecU8_fmt("Node %u has two parents (%u and %u)", n2, lower_node->parent, i);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
lower_node->has_parent = true;
|
||||
lower_node->parent = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t s = 0; s < scenes.len; s++) {
|
||||
const GltfScene* scene = &scenes.buf[s];
|
||||
for (size_t jjj = 0; jjj < scene->nodes.len; jjj++) {
|
||||
U64 n = scene->nodes.buf[jjj];
|
||||
if (n >= nodes.len) {
|
||||
ret_error = VecU8_fmt("Scene $u has child %u that is out-of-bounds of nodes array", s, n);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
const GltfNode* node = &nodes.buf[n];
|
||||
if (node->has_parent) {
|
||||
ret_error = VecU8_fmt("Scene %u specifies a non-root node %u", s, n);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (default_scene.variant == Option_Some && default_scene.some >= scenes.len) {
|
||||
ret_error = VecU8_fmt("Default scene %u is out-of-bounds of scenes array", default_scene.some);
|
||||
goto destroy_everything_return_error;
|
||||
}
|
||||
|
||||
/* Printing stuff (for test) */
|
||||
for (U64 i = 0; i < nodes.len; i++) {
|
||||
const GltfNode* node = &nodes.buf[i];
|
||||
VecU8 children_txt = VecU8_new();
|
||||
for (size_t j = 0; j < node->children.len; j++) {
|
||||
if (j)
|
||||
VecU8_append_cstr(&children_txt, ", ");
|
||||
U64_stringification_into_buf(node->children.buf[j], &children_txt);
|
||||
}
|
||||
VecU8_print(VecU8_fmt("Node #%u \"%r\": %v, children= [ %v ], %v\n", i, node->name,
|
||||
node->has_parent ? VecU8_fmt("parent= %u", node->parent) : vcstr("root node"),
|
||||
children_txt,
|
||||
node->mesh.variant == Option_Some ? VecU8_fmt("mesh= %u", node->mesh.some) : vcstr("no mesh")));
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < scenes.len; i++) {
|
||||
const GltfScene* scene = &scenes.buf[i];
|
||||
VecU8 nodes_txt = VecU8_new();
|
||||
for (size_t j = 0; j < scene->nodes.len; j++) {
|
||||
if (j)
|
||||
VecU8_append_cstr(&nodes_txt, ", ");
|
||||
U64_stringification_into_buf(scene->nodes.buf[j], &nodes_txt);
|
||||
}
|
||||
VecU8_print(VecU8_fmt("Scene #%u \"%r\": root nodes= [ %v ]\n", i, scene->name, nodes_txt));
|
||||
}
|
||||
|
||||
VecU8_print(VecU8_fmt("default_scene: %v\n",
|
||||
default_scene.variant == Option_None ? vcstr("None") : U64_stringification(default_scene.some)));
|
||||
/* End of debug print */
|
||||
|
||||
|
||||
/* ret_error stores nothing, nothing to free */
|
||||
return (ResultGltfFileStructureOrVecU8){.variant = Result_Ok, .ok = (GltfFileStructure){
|
||||
.nodes = nodes, .scenes = scenes, .default_scene = default_scene, .external_files = external_files}};
|
||||
destroy_everything_return_error:
|
||||
VecGltfNode_drop(nodes);
|
||||
VecGltfScene_drop(scenes);
|
||||
VecVecU8_drop(external_files);
|
||||
return (ResultGltfFileStructureOrVecU8){.variant = Result_Err, .err = ret_error};
|
||||
}
|
||||
|
||||
@ -103,12 +103,80 @@ const Json* Json_dict_at(const Json* self, SpanU8 key) {
|
||||
while (cur != d->NIL) {
|
||||
RBTreeNode_KVPVecU8ToJson* n = (RBTreeNode_KVPVecU8ToJson*)cur;
|
||||
if (SpanU8_less_SpanU8(VecU8_to_span(&n->key), key)) {
|
||||
cur = cur->left;
|
||||
} else if (SpanU8_less_SpanU8(key, VecU8_to_span(&n->key))) {
|
||||
cur = cur->right;
|
||||
} else if (SpanU8_less_SpanU8(key, VecU8_to_span(&n->key))) {
|
||||
cur = cur->left;
|
||||
} else {
|
||||
return &n->value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Random quality of life json functions */
|
||||
|
||||
#include "../../../gen/l1/OptionS64.h"
|
||||
|
||||
/* self must not be NULL */
|
||||
OptionS64 Json_try_as_int(const Json* self) {
|
||||
return self->variant == Json_integer ? Some_S64(self->integer) : None_S64();
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/OptionU64.h"
|
||||
|
||||
OptionU64 Json_try_as_u64(const Json* self) {
|
||||
return (self->variant == Json_integer && self->integer >= 0) ? Some_U64((U64)self->integer) : None_U64();
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/OptionSpanU8.h"
|
||||
|
||||
/* self must not be NULL, returns immutable string reference */
|
||||
OptionSpanU8 Json_try_as_str(const Json* self) {
|
||||
return self->variant == Json_str ? Some_SpanU8(VecU8_to_span(&self->str)) : None_SpanU8();
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/OptionFlt32.h"
|
||||
|
||||
OptionFlt32 Json_try_as_float(const Json* self) {
|
||||
if (self->variant == Json_integer)
|
||||
return Some_Flt32((float)self->integer);
|
||||
if (self->variant == Json_float)
|
||||
return Some_Flt32(self->float_num);
|
||||
return None_Flt32();
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/OptionVecU64.h"
|
||||
|
||||
OptionVecU64 Json_try_as_arr_of_u64(const Json* self) {
|
||||
if (self->variant != Json_arr)
|
||||
return None_VecU64();
|
||||
VecU64 res = VecU64_new_zeroinit(self->arr.len);
|
||||
for (size_t i = 0; i < self->arr.len; i++) {
|
||||
const Json* el = &self->arr.buf[i];
|
||||
if (el->variant != Json_integer || el->integer < 0) {
|
||||
VecU64_drop(res);
|
||||
return None_VecU64();
|
||||
}
|
||||
res.buf[i] = (U64)el->integer;
|
||||
}
|
||||
return Some_VecU64(res);
|
||||
}
|
||||
|
||||
#include "../../../gen/l1/VecAndSpan_Flt32.h"
|
||||
|
||||
/* true=ok, false=err */
|
||||
bool Json_try_as_MutSpanFlt32(const Json* self, MutSpanFlt32 ret) {
|
||||
if (self->variant != Json_arr)
|
||||
return false;
|
||||
size_t n = ret.len;
|
||||
if (self->arr.len != n)
|
||||
return false;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
const Json* el = &self->arr.buf[i];
|
||||
OptionFlt32 opt = Json_try_as_float(el);
|
||||
if (opt.variant != Option_Some)
|
||||
return false;
|
||||
ret.data[i] = opt.some;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -403,5 +403,24 @@ void run_app(){
|
||||
}
|
||||
|
||||
int main(){
|
||||
alice_expect_read_generic_mesh_from_glb_file(vcstr("./src/l3/models/skeleton.glb"));
|
||||
VecU8 file = read_file_by_path(vcstr("./src/l3/models/skeleton.glb"));
|
||||
ResultGLBFileSegmentsOrSpanU8 segments_r = glb_file_get_segments(VecU8_to_span(&file));
|
||||
if (segments_r.variant == Result_Err) {
|
||||
printf("Something went wrong when reading glb container\n");
|
||||
SpanU8_print(segments_r.err);
|
||||
printf("\n");
|
||||
VecU8_drop(file);
|
||||
abort();
|
||||
}
|
||||
ResultGltfFileStructureOrVecU8 structure_r = glb_file_get_structure(&segments_r.ok);
|
||||
if (structure_r.variant == Result_Err) {
|
||||
printf("Something when parsing gltf\n");
|
||||
VecU8_print(structure_r.err);
|
||||
printf("\n");
|
||||
GLBFileSegments_drop(segments_r.ok);
|
||||
VecU8_drop(file);
|
||||
abort();
|
||||
}
|
||||
GLBFileSegments_drop(segments_r.ok);
|
||||
VecU8_drop(file);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user