Foundation
Loading...
Searching...
No Matches
cgltf_write.h
Go to the documentation of this file.
1
30#ifndef CGLTF_WRITE_H_INCLUDED__
31#define CGLTF_WRITE_H_INCLUDED__
32
33#include "cgltf.h"
34
35#include <stddef.h>
36#include <stdbool.h>
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, const cgltf_data* data);
43cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data);
44
45#ifdef __cplusplus
46}
47#endif
48
49#endif /* #ifndef CGLTF_WRITE_H_INCLUDED__ */
50
51/*
52 *
53 * Stop now, if you are only interested in the API.
54 * Below, you find the implementation.
55 *
56 */
57
58#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
59/* This makes MSVC/CLion intellisense work. */
60#define CGLTF_WRITE_IMPLEMENTATION
61#endif
62
63#ifdef CGLTF_WRITE_IMPLEMENTATION
64
65#include <assert.h>
66#include <stdio.h>
67#include <stdint.h>
68#include <stdlib.h>
69#include <string.h>
70#include <float.h>
71
72#define CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM (1 << 0)
73#define CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT (1 << 1)
74#define CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS (1 << 2)
75#define CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL (1 << 3)
76#define CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION (1 << 4)
77#define CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT (1 << 5)
78#define CGLTF_EXTENSION_FLAG_MATERIALS_IOR (1 << 6)
79#define CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR (1 << 7)
80#define CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION (1 << 8)
81#define CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN (1 << 9)
82#define CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS (1 << 10)
83#define CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME (1 << 11)
84#define CGLTF_EXTENSION_FLAG_TEXTURE_BASISU (1 << 12)
85#define CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH (1 << 13)
86#define CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING (1 << 14)
87#define CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE (1 << 15)
88#define CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY (1 << 16)
89#define CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION (1 << 17)
90#define CGLTF_EXTENSION_FLAG_TEXTURE_WEBP (1 << 18)
91#define CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION (1 << 19)
92#define CGLTF_EXTENSION_FLAG_MATERIALS_SUBSURFACE (1 << 20)
93#define CGLTF_EXTENSION_FLAG_CAMERA_LENS (1 << 21)
94
95typedef struct {
96 char* buffer;
97 cgltf_size buffer_size;
98 cgltf_size remaining;
99 char* cursor;
100 cgltf_size tmp;
101 cgltf_size chars_written;
102 const cgltf_data* data;
103 int depth;
104 const char* indent;
105 int needs_comma;
106 uint32_t extension_flags;
107 uint32_t required_extension_flags;
108} cgltf_write_context;
109
110#define CGLTF_MIN(a, b) (a < b ? a : b)
111
112#ifdef FLT_DECIMAL_DIG
113 // FLT_DECIMAL_DIG is C11
114 #define CGLTF_DECIMAL_DIG (FLT_DECIMAL_DIG)
115#else
116 #define CGLTF_DECIMAL_DIG 9
117#endif
118
119#define CGLTF_SPRINTF(...) { \
120 assert(context->cursor || (!context->cursor && context->remaining == 0)); \
121 context->tmp = snprintf ( context->cursor, context->remaining, __VA_ARGS__ ); \
122 context->chars_written += context->tmp; \
123 if (context->cursor) { \
124 context->cursor += context->tmp; \
125 context->remaining -= context->tmp; \
126 } }
127
128#define CGLTF_SNPRINTF(length, ...) { \
129 assert(context->cursor || (!context->cursor && context->remaining == 0)); \
130 context->tmp = snprintf ( context->cursor, CGLTF_MIN(length + 1, context->remaining), __VA_ARGS__ ); \
131 context->chars_written += length; \
132 if (context->cursor) { \
133 context->cursor += length; \
134 context->remaining -= length; \
135 } }
136
137#define CGLTF_WRITE_IDXPROP(label, val, start) if (val) { \
138 cgltf_write_indent(context); \
139 CGLTF_SPRINTF("\"%s\": %d", label, (int) (val - start)); \
140 context->needs_comma = 1; }
141
142#define CGLTF_WRITE_IDXARRPROP(label, dim, vals, start) if (vals) { \
143 cgltf_write_indent(context); \
144 CGLTF_SPRINTF("\"%s\": [", label); \
145 for (int i = 0; i < (int)(dim); ++i) { \
146 int idx = (int) (vals[i] - start); \
147 if (i != 0) CGLTF_SPRINTF(","); \
148 CGLTF_SPRINTF(" %d", idx); \
149 } \
150 CGLTF_SPRINTF(" ]"); \
151 context->needs_comma = 1; }
152
153#define CGLTF_WRITE_TEXTURE_INFO(label, info) if (info.texture) { \
154 cgltf_write_line(context, "\"" label "\": {"); \
155 CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
156 cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
157 if (info.has_transform) { \
158 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
159 cgltf_write_texture_transform(context, &info.transform); \
160 } \
161 cgltf_write_line(context, "}"); }
162
163#define CGLTF_WRITE_NORMAL_TEXTURE_INFO(label, info) if (info.texture) { \
164 cgltf_write_line(context, "\"" label "\": {"); \
165 CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
166 cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
167 cgltf_write_floatprop(context, "scale", info.scale, 1.0f); \
168 if (info.has_transform) { \
169 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
170 cgltf_write_texture_transform(context, &info.transform); \
171 } \
172 cgltf_write_line(context, "}"); }
173
174#define CGLTF_WRITE_OCCLUSION_TEXTURE_INFO(label, info) if (info.texture) { \
175 cgltf_write_line(context, "\"" label "\": {"); \
176 CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
177 cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
178 cgltf_write_floatprop(context, "strength", info.scale, 1.0f); \
179 if (info.has_transform) { \
180 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
181 cgltf_write_texture_transform(context, &info.transform); \
182 } \
183 cgltf_write_line(context, "}"); }
184
185#ifndef CGLTF_CONSTS
186#define GlbHeaderSize 12
187#define GlbChunkHeaderSize 8
188static const uint32_t GlbVersion = 2;
189static const uint32_t GlbMagic = 0x46546C67;
190static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
191static const uint32_t GlbMagicBinChunk = 0x004E4942;
192#define CGLTF_CONSTS
193#endif
194
195static void cgltf_write_indent(cgltf_write_context* context)
196{
197 if (context->needs_comma)
198 {
199 CGLTF_SPRINTF(",\n");
200 context->needs_comma = 0;
201 }
202 else
203 {
204 CGLTF_SPRINTF("\n");
205 }
206 for (int i = 0; i < context->depth; ++i)
207 {
208 CGLTF_SPRINTF("%s", context->indent);
209 }
210}
211
212static void cgltf_write_line(cgltf_write_context* context, const char* line)
213{
214 if (line[0] == ']' || line[0] == '}')
215 {
216 --context->depth;
217 context->needs_comma = 0;
218 }
219 cgltf_write_indent(context);
220 CGLTF_SPRINTF("%s", line);
221 cgltf_size last = (cgltf_size)(strlen(line) - 1);
222 if (line[0] == ']' || line[0] == '}')
223 {
224 context->needs_comma = 1;
225 }
226 if (line[last] == '[' || line[last] == '{')
227 {
228 ++context->depth;
229 context->needs_comma = 0;
230 }
231}
232
233static void cgltf_write_strprop(cgltf_write_context* context, const char* label, const char* val)
234{
235 if (val)
236 {
237 cgltf_write_indent(context);
238 CGLTF_SPRINTF("\"%s\": \"%s\"", label, val);
239 context->needs_comma = 1;
240 }
241}
242
243static void cgltf_write_extras(cgltf_write_context* context, const cgltf_extras* extras)
244{
245 if (extras->data)
246 {
247 cgltf_write_indent(context);
248 CGLTF_SPRINTF("\"extras\": %s", extras->data);
249 context->needs_comma = 1;
250 }
251 else
252 {
253 cgltf_size length = extras->end_offset - extras->start_offset;
254 if (length > 0 && context->data->json)
255 {
256 char* json_string = ((char*) context->data->json) + extras->start_offset;
257 cgltf_write_indent(context);
258 CGLTF_SPRINTF("%s", "\"extras\": ");
259 CGLTF_SNPRINTF(length, "%.*s", (int)(extras->end_offset - extras->start_offset), json_string);
260 context->needs_comma = 1;
261 }
262 }
263}
264
265static void cgltf_write_stritem(cgltf_write_context* context, const char* item)
266{
267 cgltf_write_indent(context);
268 CGLTF_SPRINTF("\"%s\"", item);
269 context->needs_comma = 1;
270}
271
272static void cgltf_write_intprop(cgltf_write_context* context, const char* label, int val, int def)
273{
274 if (val != def)
275 {
276 cgltf_write_indent(context);
277 CGLTF_SPRINTF("\"%s\": %d", label, val);
278 context->needs_comma = 1;
279 }
280}
281
282static void cgltf_write_sizeprop(cgltf_write_context* context, const char* label, cgltf_size val, cgltf_size def)
283{
284 if (val != def)
285 {
286 cgltf_write_indent(context);
287 CGLTF_SPRINTF("\"%s\": %zu", label, val);
288 context->needs_comma = 1;
289 }
290}
291
292static void cgltf_write_floatprop(cgltf_write_context* context, const char* label, float val, float def)
293{
294 if (val != def)
295 {
296 cgltf_write_indent(context);
297 CGLTF_SPRINTF("\"%s\": ", label);
298 CGLTF_SPRINTF("%.*g", CGLTF_DECIMAL_DIG, val);
299 context->needs_comma = 1;
300
301 if (context->cursor)
302 {
303 char *decimal_comma = strchr(context->cursor - context->tmp, ',');
304 if (decimal_comma)
305 {
306 *decimal_comma = '.';
307 }
308 }
309 }
310}
311
312static void cgltf_write_boolprop_optional(cgltf_write_context* context, const char* label, bool val, bool def)
313{
314 if (val != def)
315 {
316 cgltf_write_indent(context);
317 CGLTF_SPRINTF("\"%s\": %s", label, val ? "true" : "false");
318 context->needs_comma = 1;
319 }
320}
321
322static void cgltf_write_floatarrayprop(cgltf_write_context* context, const char* label, const cgltf_float* vals, cgltf_size dim)
323{
324 cgltf_write_indent(context);
325 CGLTF_SPRINTF("\"%s\": [", label);
326 for (cgltf_size i = 0; i < dim; ++i)
327 {
328 if (i != 0)
329 {
330 CGLTF_SPRINTF(", %.*g", CGLTF_DECIMAL_DIG, vals[i]);
331 }
332 else
333 {
334 CGLTF_SPRINTF("%.*g", CGLTF_DECIMAL_DIG, vals[i]);
335 }
336 }
337 CGLTF_SPRINTF("]");
338 context->needs_comma = 1;
339}
340
341static bool cgltf_check_floatarray(const float* vals, int dim, float val) {
342 while (dim--)
343 {
344 if (vals[dim] != val)
345 {
346 return true;
347 }
348 }
349 return false;
350}
351
352static int cgltf_int_from_component_type(cgltf_component_type ctype)
353{
354 switch (ctype)
355 {
356 case cgltf_component_type_r_8: return 5120;
357 case cgltf_component_type_r_8u: return 5121;
358 case cgltf_component_type_r_16: return 5122;
359 case cgltf_component_type_r_16u: return 5123;
360 case cgltf_component_type_r_32u: return 5125;
361 case cgltf_component_type_r_32f: return 5126;
362 default: return 0;
363 }
364}
365
366static int cgltf_int_from_primitive_type(cgltf_primitive_type ctype)
367{
368 switch (ctype)
369 {
370 case cgltf_primitive_type_points: return 0;
371 case cgltf_primitive_type_lines: return 1;
372 case cgltf_primitive_type_line_loop: return 2;
373 case cgltf_primitive_type_line_strip: return 3;
374 case cgltf_primitive_type_triangles: return 4;
377 default: return -1;
378 }
379}
380
381static const char* cgltf_str_from_alpha_mode(cgltf_alpha_mode alpha_mode)
382{
383 switch (alpha_mode)
384 {
385 case cgltf_alpha_mode_mask: return "MASK";
386 case cgltf_alpha_mode_blend: return "BLEND";
387 default: return NULL;
388 }
389}
390
391static const char* cgltf_str_from_type(cgltf_type type)
392{
393 switch (type)
394 {
395 case cgltf_type_scalar: return "SCALAR";
396 case cgltf_type_vec2: return "VEC2";
397 case cgltf_type_vec3: return "VEC3";
398 case cgltf_type_vec4: return "VEC4";
399 case cgltf_type_mat2: return "MAT2";
400 case cgltf_type_mat3: return "MAT3";
401 case cgltf_type_mat4: return "MAT4";
402 default: return NULL;
403 }
404}
405
406static cgltf_size cgltf_dim_from_type(cgltf_type type)
407{
408 switch (type)
409 {
410 case cgltf_type_scalar: return 1;
411 case cgltf_type_vec2: return 2;
412 case cgltf_type_vec3: return 3;
413 case cgltf_type_vec4: return 4;
414 case cgltf_type_mat2: return 4;
415 case cgltf_type_mat3: return 9;
416 case cgltf_type_mat4: return 16;
417 default: return 0;
418 }
419}
420
421static const char* cgltf_str_from_camera_type(cgltf_camera_type camera_type)
422{
423 switch (camera_type)
424 {
425 case cgltf_camera_type_perspective: return "perspective";
426 case cgltf_camera_type_orthographic: return "orthographic";
427 default: return NULL;
428 }
429}
430
431static const char* cgltf_str_from_light_type(cgltf_light_type light_type)
432{
433 switch (light_type)
434 {
435 case cgltf_light_type_directional: return "directional";
436 case cgltf_light_type_point: return "point";
437 case cgltf_light_type_spot: return "spot";
438 default: return NULL;
439 }
440}
441
442static void cgltf_write_texture_transform(cgltf_write_context* context, const cgltf_texture_transform* transform)
443{
444 cgltf_write_line(context, "\"extensions\": {");
445 cgltf_write_line(context, "\"KHR_texture_transform\": {");
446 if (cgltf_check_floatarray(transform->offset, 2, 0.0f))
447 {
448 cgltf_write_floatarrayprop(context, "offset", transform->offset, 2);
449 }
450 cgltf_write_floatprop(context, "rotation", transform->rotation, 0.0f);
451 if (cgltf_check_floatarray(transform->scale, 2, 1.0f))
452 {
453 cgltf_write_floatarrayprop(context, "scale", transform->scale, 2);
454 }
455 if (transform->has_texcoord)
456 {
457 cgltf_write_intprop(context, "texCoord", transform->texcoord, -1);
458 }
459 cgltf_write_line(context, "}");
460 cgltf_write_line(context, "}");
461}
462
463static void cgltf_write_asset(cgltf_write_context* context, const cgltf_asset* asset)
464{
465 cgltf_write_line(context, "\"asset\": {");
466 cgltf_write_strprop(context, "copyright", asset->copyright);
467 cgltf_write_strprop(context, "generator", asset->generator);
468 cgltf_write_strprop(context, "version", asset->version);
469 cgltf_write_strprop(context, "min_version", asset->min_version);
470 cgltf_write_extras(context, &asset->extras);
471 cgltf_write_line(context, "}");
472}
473
474static void cgltf_write_primitive(cgltf_write_context* context, const cgltf_primitive* prim)
475{
476 cgltf_write_intprop(context, "mode", cgltf_int_from_primitive_type(prim->type), 4);
477 CGLTF_WRITE_IDXPROP("indices", prim->indices, context->data->accessors);
478 CGLTF_WRITE_IDXPROP("material", prim->material, context->data->materials);
479 cgltf_write_line(context, "\"attributes\": {");
480 for (cgltf_size i = 0; i < prim->attributes_count; ++i)
481 {
482 const cgltf_attribute* attr = prim->attributes + i;
483 CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors);
484 }
485 cgltf_write_line(context, "}");
486
487 if (prim->targets_count)
488 {
489 cgltf_write_line(context, "\"targets\": [");
490 for (cgltf_size i = 0; i < prim->targets_count; ++i)
491 {
492 cgltf_write_line(context, "{");
493 for (cgltf_size j = 0; j < prim->targets[i].attributes_count; ++j)
494 {
495 const cgltf_attribute* attr = prim->targets[i].attributes + j;
496 CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors);
497 }
498 cgltf_write_line(context, "}");
499 }
500 cgltf_write_line(context, "]");
501 }
502 cgltf_write_extras(context, &prim->extras);
503
504 if (prim->has_draco_mesh_compression || prim->mappings_count > 0)
505 {
506 cgltf_write_line(context, "\"extensions\": {");
507
509 {
510 context->extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION;
511 if (prim->attributes_count == 0 || prim->indices == 0)
512 {
513 context->required_extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION;
514 }
515
516 cgltf_write_line(context, "\"KHR_draco_mesh_compression\": {");
517 CGLTF_WRITE_IDXPROP("bufferView", prim->draco_mesh_compression.buffer_view, context->data->buffer_views);
518 cgltf_write_line(context, "\"attributes\": {");
519 for (cgltf_size i = 0; i < prim->draco_mesh_compression.attributes_count; ++i)
520 {
521 const cgltf_attribute* attr = prim->draco_mesh_compression.attributes + i;
522 CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors);
523 }
524 cgltf_write_line(context, "}");
525 cgltf_write_line(context, "}");
526 }
527
528 if (prim->mappings_count > 0)
529 {
530 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS;
531 cgltf_write_line(context, "\"KHR_materials_variants\": {");
532 cgltf_write_line(context, "\"mappings\": [");
533 for (cgltf_size i = 0; i < prim->mappings_count; ++i)
534 {
535 const cgltf_material_mapping* map = prim->mappings + i;
536 cgltf_write_line(context, "{");
537 CGLTF_WRITE_IDXPROP("material", map->material, context->data->materials);
538
539 cgltf_write_indent(context);
540 CGLTF_SPRINTF("\"variants\": [%d]", (int)map->variant);
541 context->needs_comma = 1;
542
543 cgltf_write_extras(context, &map->extras);
544 cgltf_write_line(context, "}");
545 }
546 cgltf_write_line(context, "]");
547 cgltf_write_line(context, "}");
548 }
549
550 cgltf_write_line(context, "}");
551 }
552}
553
554static void cgltf_write_mesh(cgltf_write_context* context, const cgltf_mesh* mesh)
555{
556 cgltf_write_line(context, "{");
557 cgltf_write_strprop(context, "name", mesh->name);
558
559 cgltf_write_line(context, "\"primitives\": [");
560 for (cgltf_size i = 0; i < mesh->primitives_count; ++i)
561 {
562 cgltf_write_line(context, "{");
563 cgltf_write_primitive(context, mesh->primitives + i);
564 cgltf_write_line(context, "}");
565 }
566 cgltf_write_line(context, "]");
567
568 if (mesh->weights_count > 0)
569 {
570 cgltf_write_floatarrayprop(context, "weights", mesh->weights, mesh->weights_count);
571 }
572
573 cgltf_write_extras(context, &mesh->extras);
574 cgltf_write_line(context, "}");
575}
576
577static void cgltf_write_buffer_view(cgltf_write_context* context, const cgltf_buffer_view* view)
578{
579 cgltf_write_line(context, "{");
580 cgltf_write_strprop(context, "name", view->name);
581 CGLTF_WRITE_IDXPROP("buffer", view->buffer, context->data->buffers);
582 cgltf_write_sizeprop(context, "byteLength", view->size, (cgltf_size)-1);
583 cgltf_write_sizeprop(context, "byteOffset", view->offset, 0);
584 cgltf_write_sizeprop(context, "byteStride", view->stride, 0);
585 // NOTE: We skip writing "target" because the spec says its usage can be inferred.
586 cgltf_write_extras(context, &view->extras);
587 cgltf_write_line(context, "}");
588}
589
590
591static void cgltf_write_buffer(cgltf_write_context* context, const cgltf_buffer* buffer)
592{
593 cgltf_write_line(context, "{");
594 cgltf_write_strprop(context, "name", buffer->name);
595 cgltf_write_strprop(context, "uri", buffer->uri);
596 cgltf_write_sizeprop(context, "byteLength", buffer->size, (cgltf_size)-1);
597 cgltf_write_extras(context, &buffer->extras);
598 cgltf_write_line(context, "}");
599}
600
601static void cgltf_write_material(cgltf_write_context* context, const cgltf_material* material)
602{
603 cgltf_write_line(context, "{");
604 cgltf_write_strprop(context, "name", material->name);
605 if (material->alpha_mode == cgltf_alpha_mode_mask)
606 {
607 cgltf_write_floatprop(context, "alphaCutoff", material->alpha_cutoff, 0.5f);
608 }
609 cgltf_write_boolprop_optional(context, "doubleSided", (bool)material->double_sided, false);
610 // cgltf_write_boolprop_optional(context, "unlit", material->unlit, false);
611
612 if (material->unlit)
613 {
614 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT;
615 }
616
617 if (material->has_pbr_specular_glossiness)
618 {
619 context->extension_flags |= CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS;
620 }
621
622 if (material->has_clearcoat)
623 {
624 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT;
625 }
626
627 if (material->has_transmission)
628 {
629 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION;
630 }
631
632 if (material->has_volume)
633 {
634 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME;
635 }
636
637 if (material->has_ior)
638 {
639 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IOR;
640 }
641
642 if (material->has_specular)
643 {
644 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR;
645 }
646
647 if (material->has_sheen)
648 {
649 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN;
650 }
651
652 if (material->has_emissive_strength)
653 {
654 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH;
655 }
656
657 if (material->has_iridescence)
658 {
659 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE;
660 }
661
662 if (material->has_diffuse_transmission)
663 {
664 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION;
665 }
666
667 if (material->has_subsurface)
668 {
669 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SUBSURFACE;
670 }
671
672 if (material->has_anisotropy)
673 {
674 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY;
675 }
676
677 if (material->has_dispersion)
678 {
679 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION;
680 }
681
682 if (material->has_pbr_metallic_roughness)
683 {
684 const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness;
685 cgltf_write_line(context, "\"pbrMetallicRoughness\": {");
686 CGLTF_WRITE_TEXTURE_INFO("baseColorTexture", params->base_color_texture);
687 CGLTF_WRITE_TEXTURE_INFO("metallicRoughnessTexture", params->metallic_roughness_texture);
688 cgltf_write_floatprop(context, "metallicFactor", params->metallic_factor, 1.0f);
689 cgltf_write_floatprop(context, "roughnessFactor", params->roughness_factor, 1.0f);
690 if (cgltf_check_floatarray(params->base_color_factor, 4, 1.0f))
691 {
692 cgltf_write_floatarrayprop(context, "baseColorFactor", params->base_color_factor, 4);
693 }
694 cgltf_write_line(context, "}");
695 }
696
697 if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength || material->has_iridescence || material->has_anisotropy || material->has_dispersion || material->has_diffuse_transmission || material->has_subsurface)
698 {
699 cgltf_write_line(context, "\"extensions\": {");
700 if (material->has_clearcoat)
701 {
702 const cgltf_clearcoat* params = &material->clearcoat;
703 cgltf_write_line(context, "\"KHR_materials_clearcoat\": {");
704 CGLTF_WRITE_TEXTURE_INFO("clearcoatTexture", params->clearcoat_texture);
705 CGLTF_WRITE_TEXTURE_INFO("clearcoatRoughnessTexture", params->clearcoat_roughness_texture);
706 CGLTF_WRITE_NORMAL_TEXTURE_INFO("clearcoatNormalTexture", params->clearcoat_normal_texture);
707 cgltf_write_floatprop(context, "clearcoatFactor", params->clearcoat_factor, 0.0f);
708 cgltf_write_floatprop(context, "clearcoatRoughnessFactor", params->clearcoat_roughness_factor, 0.0f);
709 cgltf_write_line(context, "}");
710 }
711 if (material->has_ior)
712 {
713 const cgltf_ior* params = &material->ior;
714 cgltf_write_line(context, "\"KHR_materials_ior\": {");
715 cgltf_write_floatprop(context, "ior", params->ior, 1.5f);
716 cgltf_write_line(context, "}");
717 }
718 if (material->has_specular)
719 {
720 const cgltf_specular* params = &material->specular;
721 cgltf_write_line(context, "\"KHR_materials_specular\": {");
722 CGLTF_WRITE_TEXTURE_INFO("specularTexture", params->specular_texture);
723 CGLTF_WRITE_TEXTURE_INFO("specularColorTexture", params->specular_color_texture);
724 cgltf_write_floatprop(context, "specularFactor", params->specular_factor, 1.0f);
725 if (cgltf_check_floatarray(params->specular_color_factor, 3, 1.0f))
726 {
727 cgltf_write_floatarrayprop(context, "specularColorFactor", params->specular_color_factor, 3);
728 }
729 cgltf_write_line(context, "}");
730 }
731 if (material->has_transmission)
732 {
733 const cgltf_transmission* params = &material->transmission;
734 cgltf_write_line(context, "\"KHR_materials_transmission\": {");
735 CGLTF_WRITE_TEXTURE_INFO("transmissionTexture", params->transmission_texture);
736 cgltf_write_floatprop(context, "transmissionFactor", params->transmission_factor, 0.0f);
737 cgltf_write_line(context, "}");
738 }
739 if (material->has_volume)
740 {
741 const cgltf_volume* params = &material->volume;
742 cgltf_write_line(context, "\"KHR_materials_volume\": {");
743 CGLTF_WRITE_TEXTURE_INFO("thicknessTexture", params->thickness_texture);
744 cgltf_write_floatprop(context, "thicknessFactor", params->thickness_factor, 0.0f);
745 if (cgltf_check_floatarray(params->attenuation_color, 3, 1.0f))
746 {
747 cgltf_write_floatarrayprop(context, "attenuationColor", params->attenuation_color, 3);
748 }
749 if (params->attenuation_distance < FLT_MAX)
750 {
751 cgltf_write_floatprop(context, "attenuationDistance", params->attenuation_distance, FLT_MAX);
752 }
753 cgltf_write_line(context, "}");
754 }
755 if (material->has_sheen)
756 {
757 const cgltf_sheen* params = &material->sheen;
758 cgltf_write_line(context, "\"KHR_materials_sheen\": {");
759 CGLTF_WRITE_TEXTURE_INFO("sheenColorTexture", params->sheen_color_texture);
760 CGLTF_WRITE_TEXTURE_INFO("sheenRoughnessTexture", params->sheen_roughness_texture);
761 if (cgltf_check_floatarray(params->sheen_color_factor, 3, 0.0f))
762 {
763 cgltf_write_floatarrayprop(context, "sheenColorFactor", params->sheen_color_factor, 3);
764 }
765 cgltf_write_floatprop(context, "sheenRoughnessFactor", params->sheen_roughness_factor, 0.0f);
766 cgltf_write_line(context, "}");
767 }
768 if (material->has_pbr_specular_glossiness)
769 {
771 cgltf_write_line(context, "\"KHR_materials_pbrSpecularGlossiness\": {");
772 CGLTF_WRITE_TEXTURE_INFO("diffuseTexture", params->diffuse_texture);
773 CGLTF_WRITE_TEXTURE_INFO("specularGlossinessTexture", params->specular_glossiness_texture);
774 if (cgltf_check_floatarray(params->diffuse_factor, 4, 1.0f))
775 {
776 cgltf_write_floatarrayprop(context, "diffuseFactor", params->diffuse_factor, 4);
777 }
778 if (cgltf_check_floatarray(params->specular_factor, 3, 1.0f))
779 {
780 cgltf_write_floatarrayprop(context, "specularFactor", params->specular_factor, 3);
781 }
782 cgltf_write_floatprop(context, "glossinessFactor", params->glossiness_factor, 1.0f);
783 cgltf_write_line(context, "}");
784 }
785 if (material->unlit)
786 {
787 cgltf_write_line(context, "\"KHR_materials_unlit\": {}");
788 }
789 if (material->has_emissive_strength)
790 {
791 cgltf_write_line(context, "\"KHR_materials_emissive_strength\": {");
792 const cgltf_emissive_strength* params = &material->emissive_strength;
793 cgltf_write_floatprop(context, "emissiveStrength", params->emissive_strength, 1.f);
794 cgltf_write_line(context, "}");
795 }
796 if (material->has_iridescence)
797 {
798 cgltf_write_line(context, "\"KHR_materials_iridescence\": {");
799 const cgltf_iridescence* params = &material->iridescence;
800 cgltf_write_floatprop(context, "iridescenceFactor", params->iridescence_factor, 0.f);
801 CGLTF_WRITE_TEXTURE_INFO("iridescenceTexture", params->iridescence_texture);
802 cgltf_write_floatprop(context, "iridescenceIor", params->iridescence_ior, 1.3f);
803 cgltf_write_floatprop(context, "iridescenceThicknessMinimum", params->iridescence_thickness_min, 100.f);
804 cgltf_write_floatprop(context, "iridescenceThicknessMaximum", params->iridescence_thickness_max, 400.f);
805 CGLTF_WRITE_TEXTURE_INFO("iridescenceThicknessTexture", params->iridescence_thickness_texture);
806 cgltf_write_line(context, "}");
807 }
808 if (material->has_diffuse_transmission)
809 {
810 const cgltf_diffuse_transmission* params = &material->diffuse_transmission;
811 cgltf_write_line(context, "\"KHR_materials_diffuse_transmission\": {");
812 CGLTF_WRITE_TEXTURE_INFO("diffuseTransmissionTexture", params->diffuse_transmission_texture);
813 cgltf_write_floatprop(context, "diffuseTransmissionFactor", params->diffuse_transmission_factor, 0.f);
814 if (cgltf_check_floatarray(params->diffuse_transmission_color_factor, 3, 1.f))
815 {
816 cgltf_write_floatarrayprop(context, "diffuseTransmissionColorFactor", params->diffuse_transmission_color_factor, 3);
817 }
818 CGLTF_WRITE_TEXTURE_INFO("diffuseTransmissionColorTexture", params->diffuse_transmission_color_texture);
819 cgltf_write_line(context, "}");
820 }
821 if (material->has_subsurface)
822 {
823 const cgltf_subsurface* params = &material->subsurface;
824 cgltf_write_line(context, "\"EXT_materials_subsurface\": {");
825 cgltf_write_strprop(context, "subsurfaceMethod", params->subsurface_method);
826 cgltf_write_floatprop(context, "subsurfaceWeight", params->subsurface_weight, 0.f);
827 if (cgltf_check_floatarray(params->subsurface_radius, 3, 1.f))
828 {
829 cgltf_write_floatarrayprop(context, "subsurfaceRadius", params->subsurface_radius, 3);
830 }
831 cgltf_write_floatprop(context, "subsurfaceScale", params->subsurface_scale, 0.05f);
832 cgltf_write_line(context, "}");
833 }
834 if (material->has_anisotropy)
835 {
836 cgltf_write_line(context, "\"KHR_materials_anisotropy\": {");
837 const cgltf_anisotropy* params = &material->anisotropy;
838 cgltf_write_floatprop(context, "anisotropyStrength", params->anisotropy_strength, 0.f);
839 cgltf_write_floatprop(context, "anisotropyRotation", params->anisotropy_rotation, 0.f);
840 CGLTF_WRITE_TEXTURE_INFO("anisotropyTexture", params->anisotropy_texture);
841 cgltf_write_line(context, "}");
842 }
843 if (material->has_dispersion)
844 {
845 cgltf_write_line(context, "\"KHR_materials_dispersion\": {");
846 const cgltf_dispersion* params = &material->dispersion;
847 cgltf_write_floatprop(context, "dispersion", params->dispersion, 0.f);
848 cgltf_write_line(context, "}");
849 }
850 cgltf_write_line(context, "}");
851 }
852
853 CGLTF_WRITE_NORMAL_TEXTURE_INFO("normalTexture", material->normal_texture);
854 CGLTF_WRITE_OCCLUSION_TEXTURE_INFO("occlusionTexture", material->occlusion_texture);
855 CGLTF_WRITE_TEXTURE_INFO("emissiveTexture", material->emissive_texture);
856 if (cgltf_check_floatarray(material->emissive_factor, 3, 0.0f))
857 {
858 cgltf_write_floatarrayprop(context, "emissiveFactor", material->emissive_factor, 3);
859 }
860 cgltf_write_strprop(context, "alphaMode", cgltf_str_from_alpha_mode(material->alpha_mode));
861 cgltf_write_extras(context, &material->extras);
862 cgltf_write_line(context, "}");
863}
864
865static void cgltf_write_image(cgltf_write_context* context, const cgltf_image* image)
866{
867 cgltf_write_line(context, "{");
868 cgltf_write_strprop(context, "name", image->name);
869 cgltf_write_strprop(context, "uri", image->uri);
870 CGLTF_WRITE_IDXPROP("bufferView", image->buffer_view, context->data->buffer_views);
871 cgltf_write_strprop(context, "mimeType", image->mime_type);
872 cgltf_write_extras(context, &image->extras);
873 cgltf_write_line(context, "}");
874}
875
876static void cgltf_write_texture(cgltf_write_context* context, const cgltf_texture* texture)
877{
878 cgltf_write_line(context, "{");
879 cgltf_write_strprop(context, "name", texture->name);
880 CGLTF_WRITE_IDXPROP("source", texture->image, context->data->images);
881 CGLTF_WRITE_IDXPROP("sampler", texture->sampler, context->data->samplers);
882
883 if (texture->has_basisu || texture->has_webp)
884 {
885 cgltf_write_line(context, "\"extensions\": {");
886 if (texture->has_basisu)
887 {
888 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_BASISU;
889 cgltf_write_line(context, "\"KHR_texture_basisu\": {");
890 CGLTF_WRITE_IDXPROP("source", texture->basisu_image, context->data->images);
891 cgltf_write_line(context, "}");
892 }
893 if (texture->has_webp)
894 {
895 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_WEBP;
896 cgltf_write_line(context, "\"EXT_texture_webp\": {");
897 CGLTF_WRITE_IDXPROP("source", texture->webp_image, context->data->images);
898 cgltf_write_line(context, "}");
899 }
900 cgltf_write_line(context, "}");
901 }
902 cgltf_write_extras(context, &texture->extras);
903 cgltf_write_line(context, "}");
904}
905
906static void cgltf_write_skin(cgltf_write_context* context, const cgltf_skin* skin)
907{
908 cgltf_write_line(context, "{");
909 CGLTF_WRITE_IDXPROP("skeleton", skin->skeleton, context->data->nodes);
910 CGLTF_WRITE_IDXPROP("inverseBindMatrices", skin->inverse_bind_matrices, context->data->accessors);
911 CGLTF_WRITE_IDXARRPROP("joints", skin->joints_count, skin->joints, context->data->nodes);
912 cgltf_write_strprop(context, "name", skin->name);
913 cgltf_write_extras(context, &skin->extras);
914 cgltf_write_line(context, "}");
915}
916
917static const char* cgltf_write_str_path_type(cgltf_animation_path_type path_type)
918{
919 switch (path_type)
920 {
922 return "translation";
924 return "rotation";
926 return "scale";
928 return "weights";
929 default:
930 break;
931 }
932 return "invalid";
933}
934
935static const char* cgltf_write_str_interpolation_type(cgltf_interpolation_type interpolation_type)
936{
937 switch (interpolation_type)
938 {
940 return "LINEAR";
942 return "STEP";
944 return "CUBICSPLINE";
945 default:
946 break;
947 }
948 return "invalid";
949}
950
951static void cgltf_write_path_type(cgltf_write_context* context, const char *label, cgltf_animation_path_type path_type)
952{
953 cgltf_write_strprop(context, label, cgltf_write_str_path_type(path_type));
954}
955
956static void cgltf_write_interpolation_type(cgltf_write_context* context, const char *label, cgltf_interpolation_type interpolation_type)
957{
958 cgltf_write_strprop(context, label, cgltf_write_str_interpolation_type(interpolation_type));
959}
960
961static void cgltf_write_animation_sampler(cgltf_write_context* context, const cgltf_animation_sampler* animation_sampler)
962{
963 cgltf_write_line(context, "{");
964 cgltf_write_interpolation_type(context, "interpolation", animation_sampler->interpolation);
965 CGLTF_WRITE_IDXPROP("input", animation_sampler->input, context->data->accessors);
966 CGLTF_WRITE_IDXPROP("output", animation_sampler->output, context->data->accessors);
967 cgltf_write_extras(context, &animation_sampler->extras);
968 cgltf_write_line(context, "}");
969}
970
971static void cgltf_write_animation_channel(cgltf_write_context* context, const cgltf_animation* animation, const cgltf_animation_channel* animation_channel)
972{
973 cgltf_write_line(context, "{");
974 CGLTF_WRITE_IDXPROP("sampler", animation_channel->sampler, animation->samplers);
975 cgltf_write_line(context, "\"target\": {");
976 CGLTF_WRITE_IDXPROP("node", animation_channel->target_node, context->data->nodes);
977 cgltf_write_path_type(context, "path", animation_channel->target_path);
978 cgltf_write_line(context, "}");
979 cgltf_write_extras(context, &animation_channel->extras);
980 cgltf_write_line(context, "}");
981}
982
983static void cgltf_write_animation(cgltf_write_context* context, const cgltf_animation* animation)
984{
985 cgltf_write_line(context, "{");
986 cgltf_write_strprop(context, "name", animation->name);
987
988 if (animation->samplers_count > 0)
989 {
990 cgltf_write_line(context, "\"samplers\": [");
991 for (cgltf_size i = 0; i < animation->samplers_count; ++i)
992 {
993 cgltf_write_animation_sampler(context, animation->samplers + i);
994 }
995 cgltf_write_line(context, "]");
996 }
997 if (animation->channels_count > 0)
998 {
999 cgltf_write_line(context, "\"channels\": [");
1000 for (cgltf_size i = 0; i < animation->channels_count; ++i)
1001 {
1002 cgltf_write_animation_channel(context, animation, animation->channels + i);
1003 }
1004 cgltf_write_line(context, "]");
1005 }
1006 cgltf_write_extras(context, &animation->extras);
1007 cgltf_write_line(context, "}");
1008}
1009
1010static void cgltf_write_sampler(cgltf_write_context* context, const cgltf_sampler* sampler)
1011{
1012 cgltf_write_line(context, "{");
1013 cgltf_write_strprop(context, "name", sampler->name);
1014 cgltf_write_intprop(context, "magFilter", sampler->mag_filter, 0);
1015 cgltf_write_intprop(context, "minFilter", sampler->min_filter, 0);
1016 cgltf_write_intprop(context, "wrapS", sampler->wrap_s, 10497);
1017 cgltf_write_intprop(context, "wrapT", sampler->wrap_t, 10497);
1018 cgltf_write_extras(context, &sampler->extras);
1019 cgltf_write_line(context, "}");
1020}
1021
1022static void cgltf_write_node(cgltf_write_context* context, const cgltf_node* node)
1023{
1024 cgltf_write_line(context, "{");
1025 CGLTF_WRITE_IDXARRPROP("children", node->children_count, node->children, context->data->nodes);
1026 CGLTF_WRITE_IDXPROP("mesh", node->mesh, context->data->meshes);
1027 cgltf_write_strprop(context, "name", node->name);
1028 if (node->has_matrix)
1029 {
1030 cgltf_write_floatarrayprop(context, "matrix", node->matrix, 16);
1031 }
1032 if (node->has_translation)
1033 {
1034 cgltf_write_floatarrayprop(context, "translation", node->translation, 3);
1035 }
1036 if (node->has_rotation)
1037 {
1038 cgltf_write_floatarrayprop(context, "rotation", node->rotation, 4);
1039 }
1040 if (node->has_scale)
1041 {
1042 cgltf_write_floatarrayprop(context, "scale", node->scale, 3);
1043 }
1044 if (node->skin)
1045 {
1046 CGLTF_WRITE_IDXPROP("skin", node->skin, context->data->skins);
1047 }
1048
1049 bool has_extension = node->light || (node->has_mesh_gpu_instancing && node->mesh_gpu_instancing.attributes_count > 0);
1050 if(has_extension)
1051 cgltf_write_line(context, "\"extensions\": {");
1052
1053 if (node->light)
1054 {
1055 context->extension_flags |= CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL;
1056 cgltf_write_line(context, "\"KHR_lights_punctual\": {");
1057 CGLTF_WRITE_IDXPROP("light", node->light, context->data->lights);
1058 cgltf_write_line(context, "}");
1059 }
1060
1062 {
1063 context->extension_flags |= CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING;
1064 context->required_extension_flags |= CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING;
1065
1066 cgltf_write_line(context, "\"EXT_mesh_gpu_instancing\": {");
1067 {
1068 cgltf_write_line(context, "\"attributes\": {");
1069 {
1070 for (cgltf_size i = 0; i < node->mesh_gpu_instancing.attributes_count; ++i)
1071 {
1072 const cgltf_attribute* attr = node->mesh_gpu_instancing.attributes + i;
1073 CGLTF_WRITE_IDXPROP(attr->name, attr->data, context->data->accessors);
1074 }
1075 }
1076 cgltf_write_line(context, "}");
1077 }
1078 cgltf_write_line(context, "}");
1079 }
1080
1081 if (has_extension)
1082 cgltf_write_line(context, "}");
1083
1084 if (node->weights_count > 0)
1085 {
1086 cgltf_write_floatarrayprop(context, "weights", node->weights, node->weights_count);
1087 }
1088
1089 if (node->camera)
1090 {
1091 CGLTF_WRITE_IDXPROP("camera", node->camera, context->data->cameras);
1092 }
1093
1094 cgltf_write_extras(context, &node->extras);
1095 cgltf_write_line(context, "}");
1096}
1097
1098static void cgltf_write_scene(cgltf_write_context* context, const cgltf_scene* scene)
1099{
1100 cgltf_write_line(context, "{");
1101 cgltf_write_strprop(context, "name", scene->name);
1102 CGLTF_WRITE_IDXARRPROP("nodes", scene->nodes_count, scene->nodes, context->data->nodes);
1103 cgltf_write_extras(context, &scene->extras);
1104 cgltf_write_line(context, "}");
1105}
1106
1107static void cgltf_write_accessor(cgltf_write_context* context, const cgltf_accessor* accessor)
1108{
1109 cgltf_write_line(context, "{");
1110 cgltf_write_strprop(context, "name", accessor->name);
1111 CGLTF_WRITE_IDXPROP("bufferView", accessor->buffer_view, context->data->buffer_views);
1112 cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->component_type), 0);
1113 cgltf_write_strprop(context, "type", cgltf_str_from_type(accessor->type));
1114 cgltf_size dim = cgltf_dim_from_type(accessor->type);
1115 cgltf_write_boolprop_optional(context, "normalized", (bool)accessor->normalized, false);
1116 cgltf_write_sizeprop(context, "byteOffset", (int)accessor->offset, 0);
1117 cgltf_write_intprop(context, "count", (int)accessor->count, -1);
1118 if (accessor->has_min)
1119 {
1120 cgltf_write_floatarrayprop(context, "min", accessor->min, dim);
1121 }
1122 if (accessor->has_max)
1123 {
1124 cgltf_write_floatarrayprop(context, "max", accessor->max, dim);
1125 }
1126 if (accessor->is_sparse)
1127 {
1128 cgltf_write_line(context, "\"sparse\": {");
1129 cgltf_write_intprop(context, "count", (int)accessor->sparse.count, 0);
1130 cgltf_write_line(context, "\"indices\": {");
1131 cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.indices_byte_offset, 0);
1132 CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.indices_buffer_view, context->data->buffer_views);
1133 cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->sparse.indices_component_type), 0);
1134 cgltf_write_line(context, "}");
1135 cgltf_write_line(context, "\"values\": {");
1136 cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.values_byte_offset, 0);
1137 CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.values_buffer_view, context->data->buffer_views);
1138 cgltf_write_line(context, "}");
1139 cgltf_write_line(context, "}");
1140 }
1141 cgltf_write_extras(context, &accessor->extras);
1142 cgltf_write_line(context, "}");
1143}
1144
1145static void cgltf_write_camera(cgltf_write_context* context, const cgltf_camera* camera)
1146{
1147 cgltf_write_line(context, "{");
1148 cgltf_write_strprop(context, "type", cgltf_str_from_camera_type(camera->type));
1149 if (camera->name)
1150 {
1151 cgltf_write_strprop(context, "name", camera->name);
1152 }
1153
1154 if (camera->type == cgltf_camera_type_orthographic)
1155 {
1156 cgltf_write_line(context, "\"orthographic\": {");
1157 cgltf_write_floatprop(context, "xmag", camera->data.orthographic.xmag, -1.0f);
1158 cgltf_write_floatprop(context, "ymag", camera->data.orthographic.ymag, -1.0f);
1159 cgltf_write_floatprop(context, "zfar", camera->data.orthographic.zfar, -1.0f);
1160 cgltf_write_floatprop(context, "znear", camera->data.orthographic.znear, -1.0f);
1161 cgltf_write_extras(context, &camera->data.orthographic.extras);
1162 cgltf_write_line(context, "}");
1163 }
1164 else if (camera->type == cgltf_camera_type_perspective)
1165 {
1166 cgltf_write_line(context, "\"perspective\": {");
1167
1168 if (camera->data.perspective.has_aspect_ratio) {
1169 cgltf_write_floatprop(context, "aspectRatio", camera->data.perspective.aspect_ratio, -1.0f);
1170 }
1171
1172 cgltf_write_floatprop(context, "yfov", camera->data.perspective.yfov, -1.0f);
1173
1174 if (camera->data.perspective.has_zfar) {
1175 cgltf_write_floatprop(context, "zfar", camera->data.perspective.zfar, -1.0f);
1176 }
1177
1178 cgltf_write_floatprop(context, "znear", camera->data.perspective.znear, -1.0f);
1179 cgltf_write_extras(context, &camera->data.perspective.extras);
1180 cgltf_write_line(context, "}");
1181 }
1182 if (camera->has_lens)
1183 {
1184 context->extension_flags |= CGLTF_EXTENSION_FLAG_CAMERA_LENS;
1185 cgltf_write_line(context, "\"extensions\": {");
1186 cgltf_write_line(context, "\"EXT_camera_lens\": {");
1187 cgltf_write_floatprop(context, "sensorSize", camera->lens.sensor_size, -1.0f);
1188 cgltf_write_floatprop(context, "fStop", camera->lens.fstop, -1.0f);
1189 cgltf_write_floatprop(context, "focusDistance", camera->lens.focus_distance, -1.0f);
1190 cgltf_write_intprop(context, "apertureBlades", camera->lens.aperture_blades, -1);
1191 cgltf_write_floatprop(context, "apertureRotation", camera->lens.aperture_rotation, -1.0f);
1192 cgltf_write_floatprop(context, "apertureRatio", camera->lens.aperture_ratio, -1.0f);
1193 cgltf_write_line(context, "}");
1194 cgltf_write_line(context, "}");
1195 }
1196 cgltf_write_extras(context, &camera->extras);
1197 cgltf_write_line(context, "}");
1198}
1199
1200static void cgltf_write_light(cgltf_write_context* context, const cgltf_light* light)
1201{
1202 context->extension_flags |= CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL;
1203
1204 cgltf_write_line(context, "{");
1205 cgltf_write_strprop(context, "type", cgltf_str_from_light_type(light->type));
1206 if (light->name)
1207 {
1208 cgltf_write_strprop(context, "name", light->name);
1209 }
1210 if (cgltf_check_floatarray(light->color, 3, 1.0f))
1211 {
1212 cgltf_write_floatarrayprop(context, "color", light->color, 3);
1213 }
1214 cgltf_write_floatprop(context, "intensity", light->intensity, 1.0f);
1215 cgltf_write_floatprop(context, "range", light->range, 0.0f);
1216
1217 if (light->type == cgltf_light_type_spot)
1218 {
1219 cgltf_write_line(context, "\"spot\": {");
1220 cgltf_write_floatprop(context, "innerConeAngle", light->spot_inner_cone_angle, 0.0f);
1221 cgltf_write_floatprop(context, "outerConeAngle", light->spot_outer_cone_angle, 3.14159265358979323846f/4.0f);
1222 cgltf_write_line(context, "}");
1223 }
1224 cgltf_write_extras( context, &light->extras );
1225 cgltf_write_line(context, "}");
1226}
1227
1228static void cgltf_write_variant(cgltf_write_context* context, const cgltf_material_variant* variant)
1229{
1230 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS;
1231
1232 cgltf_write_line(context, "{");
1233 cgltf_write_strprop(context, "name", variant->name);
1234 cgltf_write_extras(context, &variant->extras);
1235 cgltf_write_line(context, "}");
1236}
1237
1238static void cgltf_write_glb(FILE* file, const void* json_buf, const cgltf_size json_size, const void* bin_buf, const cgltf_size bin_size)
1239{
1240 char header[GlbHeaderSize];
1241 char chunk_header[GlbChunkHeaderSize];
1242 char json_pad[3] = { 0x20, 0x20, 0x20 };
1243 char bin_pad[3] = { 0, 0, 0 };
1244
1245 cgltf_size json_padsize = (json_size % 4 != 0) ? 4 - json_size % 4 : 0;
1246 cgltf_size bin_padsize = (bin_size % 4 != 0) ? 4 - bin_size % 4 : 0;
1247 cgltf_size total_size = GlbHeaderSize + GlbChunkHeaderSize + json_size + json_padsize;
1248 if (bin_buf != NULL && bin_size > 0) {
1249 total_size += GlbChunkHeaderSize + bin_size + bin_padsize;
1250 }
1251
1252 // Write a GLB header
1253 memcpy(header, &GlbMagic, 4);
1254 memcpy(header + 4, &GlbVersion, 4);
1255 memcpy(header + 8, &total_size, 4);
1256 fwrite(header, 1, GlbHeaderSize, file);
1257
1258 // Write a JSON chunk (header & data)
1259 uint32_t json_chunk_size = (uint32_t)(json_size + json_padsize);
1260 memcpy(chunk_header, &json_chunk_size, 4);
1261 memcpy(chunk_header + 4, &GlbMagicJsonChunk, 4);
1262 fwrite(chunk_header, 1, GlbChunkHeaderSize, file);
1263
1264 fwrite(json_buf, 1, json_size, file);
1265 fwrite(json_pad, 1, json_padsize, file);
1266
1267 if (bin_buf != NULL && bin_size > 0) {
1268 // Write a binary chunk (header & data)
1269 uint32_t bin_chunk_size = (uint32_t)(bin_size + bin_padsize);
1270 memcpy(chunk_header, &bin_chunk_size, 4);
1271 memcpy(chunk_header + 4, &GlbMagicBinChunk, 4);
1272 fwrite(chunk_header, 1, GlbChunkHeaderSize, file);
1273
1274 fwrite(bin_buf, 1, bin_size, file);
1275 fwrite(bin_pad, 1, bin_padsize, file);
1276 }
1277}
1278
1279cgltf_result cgltf_write_file(const cgltf_options* options, const char* path, const cgltf_data* data)
1280{
1281 cgltf_size expected = cgltf_write(options, NULL, 0, data);
1282 char* buffer = (char*) malloc(expected);
1283 cgltf_size actual = cgltf_write(options, buffer, expected, data);
1284 if (expected != actual) {
1285 fprintf(stderr, "Error: expected %zu bytes but wrote %zu bytes.\n", expected, actual);
1286 }
1287 FILE* file = fopen(path, "wb");
1288 if (!file)
1289 {
1291 }
1292 // Note that cgltf_write() includes a null terminator, which we omit from the file content.
1293 if (options->type == cgltf_file_type_glb) {
1294 cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size);
1295 } else {
1296 // Write a plain JSON file.
1297 fwrite(buffer, actual - 1, 1, file);
1298 }
1299 fclose(file);
1300 free(buffer);
1301 return cgltf_result_success;
1302}
1303
1304static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extension_flags)
1305{
1306 if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM) {
1307 cgltf_write_stritem(context, "KHR_texture_transform");
1308 }
1309 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) {
1310 cgltf_write_stritem(context, "KHR_materials_unlit");
1311 }
1312 if (extension_flags & CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS) {
1313 cgltf_write_stritem(context, "KHR_materials_pbrSpecularGlossiness");
1314 }
1315 if (extension_flags & CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL) {
1316 cgltf_write_stritem(context, "KHR_lights_punctual");
1317 }
1318 if (extension_flags & CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION) {
1319 cgltf_write_stritem(context, "KHR_draco_mesh_compression");
1320 }
1321 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT) {
1322 cgltf_write_stritem(context, "KHR_materials_clearcoat");
1323 }
1324 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IOR) {
1325 cgltf_write_stritem(context, "KHR_materials_ior");
1326 }
1327 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR) {
1328 cgltf_write_stritem(context, "KHR_materials_specular");
1329 }
1330 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION) {
1331 cgltf_write_stritem(context, "KHR_materials_transmission");
1332 }
1333 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN) {
1334 cgltf_write_stritem(context, "KHR_materials_sheen");
1335 }
1336 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS) {
1337 cgltf_write_stritem(context, "KHR_materials_variants");
1338 }
1339 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME) {
1340 cgltf_write_stritem(context, "KHR_materials_volume");
1341 }
1342 if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_BASISU) {
1343 cgltf_write_stritem(context, "KHR_texture_basisu");
1344 }
1345 if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_WEBP) {
1346 cgltf_write_stritem(context, "EXT_texture_webp");
1347 }
1348 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH) {
1349 cgltf_write_stritem(context, "KHR_materials_emissive_strength");
1350 }
1351 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE) {
1352 cgltf_write_stritem(context, "KHR_materials_iridescence");
1353 }
1354 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION) {
1355 cgltf_write_stritem(context, "KHR_materials_diffuse_transmission");
1356 }
1357 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SUBSURFACE) {
1358 cgltf_write_stritem(context, "EXT_materials_subsurface");
1359 }
1360 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY) {
1361 cgltf_write_stritem(context, "KHR_materials_anisotropy");
1362 }
1363 if (extension_flags & CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING) {
1364 cgltf_write_stritem(context, "EXT_mesh_gpu_instancing");
1365 }
1366 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION) {
1367 cgltf_write_stritem(context, "KHR_materials_dispersion");
1368 }
1369 if (extension_flags & CGLTF_EXTENSION_FLAG_CAMERA_LENS) {
1370 cgltf_write_stritem(context, "EXT_camera_lens");
1371 }
1372}
1373
1374cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data)
1375{
1376 (void)options;
1377 cgltf_write_context ctx;
1378 ctx.buffer = buffer;
1379 ctx.buffer_size = size;
1380 ctx.remaining = size;
1381 ctx.cursor = buffer;
1382 ctx.chars_written = 0;
1383 ctx.data = data;
1384 ctx.depth = 1;
1385 ctx.indent = " ";
1386 ctx.needs_comma = 0;
1387 ctx.extension_flags = 0;
1388 ctx.required_extension_flags = 0;
1389
1390 cgltf_write_context* context = &ctx;
1391
1392 CGLTF_SPRINTF("{");
1393
1394 if (data->accessors_count > 0)
1395 {
1396 cgltf_write_line(context, "\"accessors\": [");
1397 for (cgltf_size i = 0; i < data->accessors_count; ++i)
1398 {
1399 cgltf_write_accessor(context, data->accessors + i);
1400 }
1401 cgltf_write_line(context, "]");
1402 }
1403
1404 cgltf_write_asset(context, &data->asset);
1405
1406 if (data->buffer_views_count > 0)
1407 {
1408 cgltf_write_line(context, "\"bufferViews\": [");
1409 for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
1410 {
1411 cgltf_write_buffer_view(context, data->buffer_views + i);
1412 }
1413 cgltf_write_line(context, "]");
1414 }
1415
1416 if (data->buffers_count > 0)
1417 {
1418 cgltf_write_line(context, "\"buffers\": [");
1419 for (cgltf_size i = 0; i < data->buffers_count; ++i)
1420 {
1421 cgltf_write_buffer(context, data->buffers + i);
1422 }
1423 cgltf_write_line(context, "]");
1424 }
1425
1426 if (data->images_count > 0)
1427 {
1428 cgltf_write_line(context, "\"images\": [");
1429 for (cgltf_size i = 0; i < data->images_count; ++i)
1430 {
1431 cgltf_write_image(context, data->images + i);
1432 }
1433 cgltf_write_line(context, "]");
1434 }
1435
1436 if (data->meshes_count > 0)
1437 {
1438 cgltf_write_line(context, "\"meshes\": [");
1439 for (cgltf_size i = 0; i < data->meshes_count; ++i)
1440 {
1441 cgltf_write_mesh(context, data->meshes + i);
1442 }
1443 cgltf_write_line(context, "]");
1444 }
1445
1446 if (data->materials_count > 0)
1447 {
1448 cgltf_write_line(context, "\"materials\": [");
1449 for (cgltf_size i = 0; i < data->materials_count; ++i)
1450 {
1451 cgltf_write_material(context, data->materials + i);
1452 }
1453 cgltf_write_line(context, "]");
1454 }
1455
1456 if (data->nodes_count > 0)
1457 {
1458 cgltf_write_line(context, "\"nodes\": [");
1459 for (cgltf_size i = 0; i < data->nodes_count; ++i)
1460 {
1461 cgltf_write_node(context, data->nodes + i);
1462 }
1463 cgltf_write_line(context, "]");
1464 }
1465
1466 if (data->samplers_count > 0)
1467 {
1468 cgltf_write_line(context, "\"samplers\": [");
1469 for (cgltf_size i = 0; i < data->samplers_count; ++i)
1470 {
1471 cgltf_write_sampler(context, data->samplers + i);
1472 }
1473 cgltf_write_line(context, "]");
1474 }
1475
1476 CGLTF_WRITE_IDXPROP("scene", data->scene, data->scenes);
1477
1478 if (data->scenes_count > 0)
1479 {
1480 cgltf_write_line(context, "\"scenes\": [");
1481 for (cgltf_size i = 0; i < data->scenes_count; ++i)
1482 {
1483 cgltf_write_scene(context, data->scenes + i);
1484 }
1485 cgltf_write_line(context, "]");
1486 }
1487
1488 if (data->textures_count > 0)
1489 {
1490 cgltf_write_line(context, "\"textures\": [");
1491 for (cgltf_size i = 0; i < data->textures_count; ++i)
1492 {
1493 cgltf_write_texture(context, data->textures + i);
1494 }
1495 cgltf_write_line(context, "]");
1496 }
1497
1498 if (data->skins_count > 0)
1499 {
1500 cgltf_write_line(context, "\"skins\": [");
1501 for (cgltf_size i = 0; i < data->skins_count; ++i)
1502 {
1503 cgltf_write_skin(context, data->skins + i);
1504 }
1505 cgltf_write_line(context, "]");
1506 }
1507
1508 if (data->animations_count > 0)
1509 {
1510 cgltf_write_line(context, "\"animations\": [");
1511 for (cgltf_size i = 0; i < data->animations_count; ++i)
1512 {
1513 cgltf_write_animation(context, data->animations + i);
1514 }
1515 cgltf_write_line(context, "]");
1516 }
1517
1518 if (data->cameras_count > 0)
1519 {
1520 cgltf_write_line(context, "\"cameras\": [");
1521 for (cgltf_size i = 0; i < data->cameras_count; ++i)
1522 {
1523 cgltf_write_camera(context, data->cameras + i);
1524 }
1525 cgltf_write_line(context, "]");
1526 }
1527
1528 if (data->lights_count > 0 || data->variants_count > 0)
1529 {
1530 cgltf_write_line(context, "\"extensions\": {");
1531
1532 if (data->lights_count > 0)
1533 {
1534 cgltf_write_line(context, "\"KHR_lights_punctual\": {");
1535 cgltf_write_line(context, "\"lights\": [");
1536 for (cgltf_size i = 0; i < data->lights_count; ++i)
1537 {
1538 cgltf_write_light(context, data->lights + i);
1539 }
1540 cgltf_write_line(context, "]");
1541 cgltf_write_line(context, "}");
1542 }
1543
1544 if (data->variants_count)
1545 {
1546 cgltf_write_line(context, "\"KHR_materials_variants\": {");
1547 cgltf_write_line(context, "\"variants\": [");
1548 for (cgltf_size i = 0; i < data->variants_count; ++i)
1549 {
1550 cgltf_write_variant(context, data->variants + i);
1551 }
1552 cgltf_write_line(context, "]");
1553 cgltf_write_line(context, "}");
1554 }
1555
1556 cgltf_write_line(context, "}");
1557 }
1558
1559 if (context->extension_flags != 0)
1560 {
1561 cgltf_write_line(context, "\"extensionsUsed\": [");
1562 cgltf_write_extensions(context, context->extension_flags);
1563 cgltf_write_line(context, "]");
1564 }
1565
1566 if (context->required_extension_flags != 0)
1567 {
1568 cgltf_write_line(context, "\"extensionsRequired\": [");
1569 cgltf_write_extensions(context, context->required_extension_flags);
1570 cgltf_write_line(context, "]");
1571 }
1572
1573 cgltf_write_extras(context, &data->extras);
1574
1575 CGLTF_SPRINTF("\n}\n");
1576
1577 // snprintf does not include the null terminator in its return value, so be sure to include it
1578 // in the returned byte count.
1579 return 1 + ctx.chars_written;
1580}
1581
1582#endif /* #ifdef CGLTF_WRITE_IMPLEMENTATION */
1583
1584/* cgltf is distributed under MIT license:
1585 *
1586 * Copyright (c) 2019-2021 Philip Rideout
1587
1588 * Permission is hereby granted, free of charge, to any person obtaining a copy
1589 * of this software and associated documentation files (the "Software"), to deal
1590 * in the Software without restriction, including without limitation the rights
1591 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1592 * copies of the Software, and to permit persons to whom the Software is
1593 * furnished to do so, subject to the following conditions:
1594
1595 * The above copyright notice and this permission notice shall be included in all
1596 * copies or substantial portions of the Software.
1597
1598 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1599 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1600 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1601 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1602 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1603 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1604 * SOFTWARE.
1605 */
size_t cgltf_size
Definition cgltf.h:104
cgltf_animation_path_type
Definition cgltf.h:224
@ cgltf_animation_path_type_weights
Definition cgltf.h:229
@ cgltf_animation_path_type_translation
Definition cgltf.h:226
@ cgltf_animation_path_type_scale
Definition cgltf.h:228
@ cgltf_animation_path_type_rotation
Definition cgltf.h:227
cgltf_primitive_type
Definition cgltf.h:204
@ cgltf_primitive_type_line_strip
Definition cgltf.h:209
@ cgltf_primitive_type_lines
Definition cgltf.h:207
@ cgltf_primitive_type_triangles
Definition cgltf.h:210
@ cgltf_primitive_type_line_loop
Definition cgltf.h:208
@ cgltf_primitive_type_triangle_fan
Definition cgltf.h:212
@ cgltf_primitive_type_points
Definition cgltf.h:206
@ cgltf_primitive_type_triangle_strip
Definition cgltf.h:211
cgltf_interpolation_type
Definition cgltf.h:233
@ cgltf_interpolation_type_cubic_spline
Definition cgltf.h:236
@ cgltf_interpolation_type_linear
Definition cgltf.h:234
@ cgltf_interpolation_type_step
Definition cgltf.h:235
cgltf_light_type
Definition cgltf.h:247
@ cgltf_light_type_spot
Definition cgltf.h:251
@ cgltf_light_type_point
Definition cgltf.h:250
@ cgltf_light_type_directional
Definition cgltf.h:249
float cgltf_float
Definition cgltf.h:106
cgltf_type
Definition cgltf.h:191
@ cgltf_type_vec4
Definition cgltf.h:196
@ cgltf_type_mat2
Definition cgltf.h:197
@ cgltf_type_vec2
Definition cgltf.h:194
@ cgltf_type_vec3
Definition cgltf.h:195
@ cgltf_type_scalar
Definition cgltf.h:193
@ cgltf_type_mat3
Definition cgltf.h:198
@ cgltf_type_mat4
Definition cgltf.h:199
cgltf_component_type
Definition cgltf.h:179
@ cgltf_component_type_r_32f
Definition cgltf.h:186
@ cgltf_component_type_r_8
Definition cgltf.h:181
@ cgltf_component_type_r_8u
Definition cgltf.h:182
@ cgltf_component_type_r_32u
Definition cgltf.h:185
@ cgltf_component_type_r_16u
Definition cgltf.h:184
@ cgltf_component_type_r_16
Definition cgltf.h:183
cgltf_result
Definition cgltf.h:120
@ cgltf_result_success
Definition cgltf.h:121
@ cgltf_result_file_not_found
Definition cgltf.h:127
@ cgltf_file_type_glb
Definition cgltf.h:115
cgltf_camera_type
Definition cgltf.h:240
@ cgltf_camera_type_orthographic
Definition cgltf.h:243
@ cgltf_camera_type_perspective
Definition cgltf.h:242
cgltf_alpha_mode
Definition cgltf.h:217
@ cgltf_alpha_mode_mask
Definition cgltf.h:219
@ cgltf_alpha_mode_blend
Definition cgltf.h:220
cgltf_size cgltf_write(const cgltf_options *options, char *buffer, cgltf_size size, const cgltf_data *data)
cgltf_result cgltf_write_file(const cgltf_options *options, const char *path, const cgltf_data *data)
cgltf_buffer_view * indices_buffer_view
Definition cgltf.h:380
cgltf_component_type indices_component_type
Definition cgltf.h:382
cgltf_size values_byte_offset
Definition cgltf.h:384
cgltf_buffer_view * values_buffer_view
Definition cgltf.h:383
cgltf_size indices_byte_offset
Definition cgltf.h:381
cgltf_size count
Definition cgltf.h:379
Definition cgltf.h:388
char * name
Definition cgltf.h:389
cgltf_bool normalized
Definition cgltf.h:391
cgltf_extras extras
Definition cgltf.h:403
cgltf_bool is_sparse
Definition cgltf.h:401
cgltf_float max[16]
Definition cgltf.h:400
cgltf_size count
Definition cgltf.h:394
cgltf_type type
Definition cgltf.h:392
cgltf_float min[16]
Definition cgltf.h:398
cgltf_size offset
Definition cgltf.h:393
cgltf_bool has_min
Definition cgltf.h:397
cgltf_buffer_view * buffer_view
Definition cgltf.h:396
cgltf_bool has_max
Definition cgltf.h:399
cgltf_component_type component_type
Definition cgltf.h:390
cgltf_accessor_sparse sparse
Definition cgltf.h:402
Definition cgltf.h:860
cgltf_node * target_node
Definition cgltf.h:862
cgltf_extras extras
Definition cgltf.h:864
cgltf_animation_path_type target_path
Definition cgltf.h:863
cgltf_animation_sampler * sampler
Definition cgltf.h:861
Definition cgltf.h:851
cgltf_extras extras
Definition cgltf.h:855
cgltf_accessor * input
Definition cgltf.h:852
cgltf_accessor * output
Definition cgltf.h:853
cgltf_interpolation_type interpolation
Definition cgltf.h:854
Definition cgltf.h:869
cgltf_animation_sampler * samplers
Definition cgltf.h:871
cgltf_animation_channel * channels
Definition cgltf.h:873
cgltf_size channels_count
Definition cgltf.h:874
cgltf_size samplers_count
Definition cgltf.h:872
char * name
Definition cgltf.h:870
cgltf_extras extras
Definition cgltf.h:875
Definition cgltf.h:584
cgltf_texture_view anisotropy_texture
Definition cgltf.h:587
cgltf_float anisotropy_strength
Definition cgltf.h:585
cgltf_float anisotropy_rotation
Definition cgltf.h:586
Definition cgltf.h:886
cgltf_extras extras
Definition cgltf.h:891
char * version
Definition cgltf.h:889
char * min_version
Definition cgltf.h:890
char * copyright
Definition cgltf.h:887
char * generator
Definition cgltf.h:888
Definition cgltf.h:409
char * name
Definition cgltf.h:410
cgltf_accessor * data
Definition cgltf.h:413
Definition cgltf.h:362
cgltf_extras extras
Definition cgltf.h:372
cgltf_size size
Definition cgltf.h:366
cgltf_buffer * buffer
Definition cgltf.h:364
char * name
Definition cgltf.h:363
cgltf_size stride
Definition cgltf.h:367
cgltf_size offset
Definition cgltf.h:365
void * data
Definition cgltf.h:369
Definition cgltf.h:323
char * uri
Definition cgltf.h:326
char * name
Definition cgltf.h:324
cgltf_extras extras
Definition cgltf.h:329
cgltf_size size
Definition cgltf.h:325
void * data
Definition cgltf.h:327
cgltf_float sensor_size
Definition cgltf.h:741
cgltf_uint aperture_blades
Definition cgltf.h:744
cgltf_float aperture_ratio
Definition cgltf.h:746
cgltf_float aperture_rotation
Definition cgltf.h:745
cgltf_float fstop
Definition cgltf.h:742
cgltf_float focus_distance
Definition cgltf.h:743
cgltf_float znear
Definition cgltf.h:736
cgltf_float xmag
Definition cgltf.h:733
cgltf_float ymag
Definition cgltf.h:734
cgltf_float zfar
Definition cgltf.h:735
cgltf_extras extras
Definition cgltf.h:737
cgltf_float yfov
Definition cgltf.h:725
cgltf_bool has_zfar
Definition cgltf.h:726
cgltf_bool has_aspect_ratio
Definition cgltf.h:723
cgltf_float zfar
Definition cgltf.h:727
cgltf_float aspect_ratio
Definition cgltf.h:724
cgltf_float znear
Definition cgltf.h:728
cgltf_extras extras
Definition cgltf.h:729
Definition cgltf.h:749
union cgltf_camera::@0 data
cgltf_extras extras
Definition cgltf.h:758
char * name
Definition cgltf.h:750
cgltf_bool has_lens
Definition cgltf.h:756
cgltf_camera_type type
Definition cgltf.h:751
cgltf_camera_orthographic orthographic
Definition cgltf.h:754
cgltf_camera_perspective perspective
Definition cgltf.h:753
cgltf_camera_lens lens
Definition cgltf.h:757
Definition cgltf.h:508
cgltf_float clearcoat_roughness_factor
Definition cgltf.h:514
cgltf_texture_view clearcoat_roughness_texture
Definition cgltf.h:510
cgltf_texture_view clearcoat_normal_texture
Definition cgltf.h:511
cgltf_float clearcoat_factor
Definition cgltf.h:513
cgltf_texture_view clearcoat_texture
Definition cgltf.h:509
Definition cgltf.h:897
cgltf_size bin_size
Definition cgltf.h:973
cgltf_size variants_count
Definition cgltf.h:954
cgltf_scene * scenes
Definition cgltf.h:945
const void * bin
Definition cgltf.h:972
cgltf_size buffer_views_count
Definition cgltf.h:913
cgltf_asset asset
Definition cgltf.h:901
cgltf_mesh * meshes
Definition cgltf.h:903
cgltf_light * lights
Definition cgltf.h:933
cgltf_size buffers_count
Definition cgltf.h:916
cgltf_buffer_view * buffer_views
Definition cgltf.h:912
cgltf_size cameras_count
Definition cgltf.h:931
cgltf_skin * skins
Definition cgltf.h:927
cgltf_scene * scene
Definition cgltf.h:948
cgltf_size images_count
Definition cgltf.h:919
cgltf_material * materials
Definition cgltf.h:906
cgltf_sampler * samplers
Definition cgltf.h:924
cgltf_size skins_count
Definition cgltf.h:928
cgltf_size textures_count
Definition cgltf.h:922
cgltf_animation * animations
Definition cgltf.h:950
cgltf_node * nodes
Definition cgltf.h:942
cgltf_accessor * accessors
Definition cgltf.h:909
cgltf_camera * cameras
Definition cgltf.h:930
cgltf_size samplers_count
Definition cgltf.h:925
cgltf_size animations_count
Definition cgltf.h:951
cgltf_image * images
Definition cgltf.h:918
cgltf_size nodes_count
Definition cgltf.h:943
cgltf_texture * textures
Definition cgltf.h:921
cgltf_size accessors_count
Definition cgltf.h:910
cgltf_size scenes_count
Definition cgltf.h:946
cgltf_size meshes_count
Definition cgltf.h:904
cgltf_buffer * buffers
Definition cgltf.h:915
cgltf_extras extras
Definition cgltf.h:956
cgltf_size lights_count
Definition cgltf.h:934
cgltf_material_variant * variants
Definition cgltf.h:953
cgltf_size materials_count
Definition cgltf.h:907
Definition cgltf.h:568
cgltf_float diffuse_transmission_color_factor[3]
Definition cgltf.h:571
cgltf_float diffuse_transmission_factor
Definition cgltf.h:570
cgltf_texture_view diffuse_transmission_texture
Definition cgltf.h:569
cgltf_texture_view diffuse_transmission_color_texture
Definition cgltf.h:572
Definition cgltf.h:591
cgltf_float dispersion
Definition cgltf.h:592
cgltf_attribute * attributes
Definition cgltf.h:670
cgltf_size attributes_count
Definition cgltf.h:671
cgltf_buffer_view * buffer_view
Definition cgltf.h:669
Definition cgltf.h:553
cgltf_float emissive_strength
Definition cgltf.h:554
Definition cgltf.h:310
cgltf_size end_offset
Definition cgltf.h:312
cgltf_size start_offset
Definition cgltf.h:311
char * data
Definition cgltf.h:314
Definition cgltf.h:417
char * uri
Definition cgltf.h:419
char * mime_type
Definition cgltf.h:421
cgltf_extras extras
Definition cgltf.h:422
char * name
Definition cgltf.h:418
cgltf_buffer_view * buffer_view
Definition cgltf.h:420
Definition cgltf.h:524
cgltf_float ior
Definition cgltf.h:525
Definition cgltf.h:558
cgltf_float iridescence_thickness_max
Definition cgltf.h:563
cgltf_float iridescence_ior
Definition cgltf.h:561
cgltf_texture_view iridescence_thickness_texture
Definition cgltf.h:564
cgltf_float iridescence_thickness_min
Definition cgltf.h:562
cgltf_texture_view iridescence_texture
Definition cgltf.h:560
cgltf_float iridescence_factor
Definition cgltf.h:559
Definition cgltf.h:763
cgltf_extras extras
Definition cgltf.h:771
cgltf_float range
Definition cgltf.h:768
cgltf_float color[3]
Definition cgltf.h:765
cgltf_light_type type
Definition cgltf.h:767
cgltf_float intensity
Definition cgltf.h:766
cgltf_float spot_outer_cone_angle
Definition cgltf.h:770
char * name
Definition cgltf.h:764
cgltf_float spot_inner_cone_angle
Definition cgltf.h:769
Definition cgltf.h:657
cgltf_extras extras
Definition cgltf.h:660
cgltf_size variant
Definition cgltf.h:658
cgltf_material * material
Definition cgltf.h:659
Definition cgltf.h:881
cgltf_extras extras
Definition cgltf.h:883
char * name
Definition cgltf.h:882
Definition cgltf.h:611
cgltf_bool double_sided
Definition cgltf.h:649
cgltf_pbr_specular_glossiness pbr_specular_glossiness
Definition cgltf.h:629
char * name
Definition cgltf.h:612
cgltf_pbr_metallic_roughness pbr_metallic_roughness
Definition cgltf.h:628
cgltf_dispersion dispersion
Definition cgltf.h:641
cgltf_iridescence iridescence
Definition cgltf.h:637
cgltf_bool has_subsurface
Definition cgltf.h:624
cgltf_extras extras
Definition cgltf.h:651
cgltf_bool has_anisotropy
Definition cgltf.h:625
cgltf_sheen sheen
Definition cgltf.h:633
cgltf_bool has_sheen
Definition cgltf.h:620
cgltf_bool unlit
Definition cgltf.h:650
cgltf_bool has_diffuse_transmission
Definition cgltf.h:623
cgltf_specular specular
Definition cgltf.h:632
cgltf_float emissive_factor[3]
Definition cgltf.h:646
cgltf_emissive_strength emissive_strength
Definition cgltf.h:636
cgltf_bool has_ior
Definition cgltf.h:618
cgltf_anisotropy anisotropy
Definition cgltf.h:640
cgltf_bool has_transmission
Definition cgltf.h:616
cgltf_bool has_pbr_metallic_roughness
Definition cgltf.h:613
cgltf_bool has_iridescence
Definition cgltf.h:622
cgltf_volume volume
Definition cgltf.h:635
cgltf_bool has_volume
Definition cgltf.h:617
cgltf_texture_view emissive_texture
Definition cgltf.h:645
cgltf_bool has_emissive_strength
Definition cgltf.h:621
cgltf_diffuse_transmission diffuse_transmission
Definition cgltf.h:638
cgltf_texture_view occlusion_texture
Definition cgltf.h:644
cgltf_transmission transmission
Definition cgltf.h:634
cgltf_bool has_clearcoat
Definition cgltf.h:615
cgltf_ior ior
Definition cgltf.h:631
cgltf_alpha_mode alpha_mode
Definition cgltf.h:647
cgltf_subsurface subsurface
Definition cgltf.h:639
cgltf_clearcoat clearcoat
Definition cgltf.h:630
cgltf_bool has_pbr_specular_glossiness
Definition cgltf.h:614
cgltf_texture_view normal_texture
Definition cgltf.h:643
cgltf_float alpha_cutoff
Definition cgltf.h:648
cgltf_bool has_specular
Definition cgltf.h:619
cgltf_bool has_dispersion
Definition cgltf.h:626
cgltf_size attributes_count
Definition cgltf.h:676
cgltf_attribute * attributes
Definition cgltf.h:675
Definition cgltf.h:696
cgltf_primitive * primitives
Definition cgltf.h:698
cgltf_size primitives_count
Definition cgltf.h:699
cgltf_extras extras
Definition cgltf.h:704
cgltf_size weights_count
Definition cgltf.h:701
char * name
Definition cgltf.h:697
cgltf_float * weights
Definition cgltf.h:700
cgltf_size attributes_count
Definition cgltf.h:665
cgltf_attribute * attributes
Definition cgltf.h:664
Definition cgltf.h:812
cgltf_mesh_gpu_instancing mesh_gpu_instancing
Definition cgltf.h:835
cgltf_skin * skin
Definition cgltf.h:817
cgltf_extras extras
Definition cgltf.h:833
cgltf_size children_count
Definition cgltf.h:816
char * name
Definition cgltf.h:813
cgltf_size weights_count
Definition cgltf.h:824
cgltf_light * light
Definition cgltf.h:820
cgltf_float rotation[4]
Definition cgltf.h:830
cgltf_bool has_translation
Definition cgltf.h:825
cgltf_mesh * mesh
Definition cgltf.h:818
cgltf_node ** children
Definition cgltf.h:815
cgltf_bool has_rotation
Definition cgltf.h:826
cgltf_float matrix[16]
Definition cgltf.h:832
cgltf_bool has_matrix
Definition cgltf.h:828
cgltf_bool has_scale
Definition cgltf.h:827
cgltf_float scale[3]
Definition cgltf.h:831
cgltf_float * weights
Definition cgltf.h:823
cgltf_bool has_mesh_gpu_instancing
Definition cgltf.h:834
cgltf_camera * camera
Definition cgltf.h:819
cgltf_float translation[3]
Definition cgltf.h:829
Definition cgltf.h:149
cgltf_file_type type
Definition cgltf.h:150
Definition cgltf.h:488
cgltf_float metallic_factor
Definition cgltf.h:493
cgltf_texture_view metallic_roughness_texture
Definition cgltf.h:490
cgltf_texture_view base_color_texture
Definition cgltf.h:489
cgltf_float roughness_factor
Definition cgltf.h:494
cgltf_float base_color_factor[4]
Definition cgltf.h:492
Definition cgltf.h:498
cgltf_texture_view diffuse_texture
Definition cgltf.h:499
cgltf_float specular_factor[3]
Definition cgltf.h:503
cgltf_float diffuse_factor[4]
Definition cgltf.h:502
cgltf_float glossiness_factor
Definition cgltf.h:504
cgltf_texture_view specular_glossiness_texture
Definition cgltf.h:500
Definition cgltf.h:679
cgltf_draco_mesh_compression draco_mesh_compression
Definition cgltf.h:689
cgltf_size attributes_count
Definition cgltf.h:684
cgltf_size targets_count
Definition cgltf.h:686
cgltf_accessor * indices
Definition cgltf.h:681
cgltf_morph_target * targets
Definition cgltf.h:685
cgltf_bool has_draco_mesh_compression
Definition cgltf.h:688
cgltf_size mappings_count
Definition cgltf.h:691
cgltf_extras extras
Definition cgltf.h:687
cgltf_material_mapping * mappings
Definition cgltf.h:690
cgltf_attribute * attributes
Definition cgltf.h:683
cgltf_primitive_type type
Definition cgltf.h:680
cgltf_material * material
Definition cgltf.h:682
Definition cgltf.h:444
cgltf_extras extras
Definition cgltf.h:450
cgltf_wrap_mode wrap_t
Definition cgltf.h:449
cgltf_filter_type mag_filter
Definition cgltf.h:446
cgltf_wrap_mode wrap_s
Definition cgltf.h:448
char * name
Definition cgltf.h:445
cgltf_filter_type min_filter
Definition cgltf.h:447
Definition cgltf.h:840
char * name
Definition cgltf.h:841
cgltf_node ** nodes
Definition cgltf.h:842
cgltf_extras extras
Definition cgltf.h:846
cgltf_size nodes_count
Definition cgltf.h:843
Definition cgltf.h:545
cgltf_texture_view sheen_color_texture
Definition cgltf.h:546
cgltf_float sheen_color_factor[3]
Definition cgltf.h:547
cgltf_float sheen_roughness_factor
Definition cgltf.h:549
cgltf_texture_view sheen_roughness_texture
Definition cgltf.h:548
Definition cgltf.h:711
cgltf_extras extras
Definition cgltf.h:717
cgltf_node * skeleton
Definition cgltf.h:715
cgltf_node ** joints
Definition cgltf.h:713
cgltf_accessor * inverse_bind_matrices
Definition cgltf.h:716
cgltf_size joints_count
Definition cgltf.h:714
char * name
Definition cgltf.h:712
Definition cgltf.h:529
cgltf_float specular_factor
Definition cgltf.h:533
cgltf_float specular_color_factor[3]
Definition cgltf.h:532
cgltf_texture_view specular_color_texture
Definition cgltf.h:531
cgltf_texture_view specular_texture
Definition cgltf.h:530
Definition cgltf.h:576
cgltf_float subsurface_radius[3]
Definition cgltf.h:579
cgltf_float subsurface_scale
Definition cgltf.h:580
char * subsurface_method
Definition cgltf.h:577
cgltf_float subsurface_weight
Definition cgltf.h:578
Definition cgltf.h:470
cgltf_bool has_texcoord
Definition cgltf.h:474
cgltf_float rotation
Definition cgltf.h:472
cgltf_float scale[2]
Definition cgltf.h:473
cgltf_float offset[2]
Definition cgltf.h:471
cgltf_int texcoord
Definition cgltf.h:475
Definition cgltf.h:456
cgltf_bool has_basisu
Definition cgltf.h:460
cgltf_image * basisu_image
Definition cgltf.h:461
cgltf_sampler * sampler
Definition cgltf.h:459
char * name
Definition cgltf.h:457
cgltf_image * image
Definition cgltf.h:458
cgltf_bool has_webp
Definition cgltf.h:462
cgltf_extras extras
Definition cgltf.h:464
cgltf_image * webp_image
Definition cgltf.h:463
Definition cgltf.h:518
cgltf_float transmission_factor
Definition cgltf.h:520
cgltf_texture_view transmission_texture
Definition cgltf.h:519
Definition cgltf.h:537
cgltf_float attenuation_distance
Definition cgltf.h:541
cgltf_float thickness_factor
Definition cgltf.h:539
cgltf_texture_view thickness_texture
Definition cgltf.h:538
cgltf_float attenuation_color[3]
Definition cgltf.h:540