30 #ifndef CGLTF_WRITE_H_INCLUDED__
31 #define CGLTF_WRITE_H_INCLUDED__
58 #if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
60 #define CGLTF_WRITE_IMPLEMENTATION
63 #ifdef CGLTF_WRITE_IMPLEMENTATION
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)
104 uint32_t extension_flags;
105 uint32_t required_extension_flags;
106 } cgltf_write_context;
108 #define CGLTF_MIN(a, b) (a < b ? a : b)
110 #ifdef FLT_DECIMAL_DIG
112 #define CGLTF_DECIMAL_DIG (FLT_DECIMAL_DIG)
114 #define CGLTF_DECIMAL_DIG 9
117 #define CGLTF_SPRINTF(...) { \
118 assert(context->cursor || (!context->cursor && context->remaining == 0)); \
119 context->tmp = snprintf ( context->cursor, context->remaining, __VA_ARGS__ ); \
120 context->chars_written += context->tmp; \
121 if (context->cursor) { \
122 context->cursor += context->tmp; \
123 context->remaining -= context->tmp; \
126 #define CGLTF_SNPRINTF(length, ...) { \
127 assert(context->cursor || (!context->cursor && context->remaining == 0)); \
128 context->tmp = snprintf ( context->cursor, CGLTF_MIN(length + 1, context->remaining), __VA_ARGS__ ); \
129 context->chars_written += length; \
130 if (context->cursor) { \
131 context->cursor += length; \
132 context->remaining -= length; \
135 #define CGLTF_WRITE_IDXPROP(label, val, start) if (val) { \
136 cgltf_write_indent(context); \
137 CGLTF_SPRINTF("\"%s\": %d", label, (int) (val - start)); \
138 context->needs_comma = 1; }
140 #define CGLTF_WRITE_IDXARRPROP(label, dim, vals, start) if (vals) { \
141 cgltf_write_indent(context); \
142 CGLTF_SPRINTF("\"%s\": [", label); \
143 for (int i = 0; i < (int)(dim); ++i) { \
144 int idx = (int) (vals[i] - start); \
145 if (i != 0) CGLTF_SPRINTF(","); \
146 CGLTF_SPRINTF(" %d", idx); \
148 CGLTF_SPRINTF(" ]"); \
149 context->needs_comma = 1; }
151 #define CGLTF_WRITE_TEXTURE_INFO(label, info) if (info.texture) { \
152 cgltf_write_line(context, "\"" label "\": {"); \
153 CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
154 cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
155 if (info.has_transform) { \
156 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
157 cgltf_write_texture_transform(context, &info.transform); \
159 cgltf_write_line(context, "}"); }
161 #define CGLTF_WRITE_NORMAL_TEXTURE_INFO(label, info) if (info.texture) { \
162 cgltf_write_line(context, "\"" label "\": {"); \
163 CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
164 cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
165 cgltf_write_floatprop(context, "scale", info.scale, 1.0f); \
166 if (info.has_transform) { \
167 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
168 cgltf_write_texture_transform(context, &info.transform); \
170 cgltf_write_line(context, "}"); }
172 #define CGLTF_WRITE_OCCLUSION_TEXTURE_INFO(label, info) if (info.texture) { \
173 cgltf_write_line(context, "\"" label "\": {"); \
174 CGLTF_WRITE_IDXPROP("index", info.texture, context->data->textures); \
175 cgltf_write_intprop(context, "texCoord", info.texcoord, 0); \
176 cgltf_write_floatprop(context, "strength", info.scale, 1.0f); \
177 if (info.has_transform) { \
178 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
179 cgltf_write_texture_transform(context, &info.transform); \
181 cgltf_write_line(context, "}"); }
184 #define GlbHeaderSize 12
185 #define GlbChunkHeaderSize 8
186 static const uint32_t GlbVersion = 2;
187 static const uint32_t GlbMagic = 0x46546C67;
188 static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
189 static const uint32_t GlbMagicBinChunk = 0x004E4942;
193 static void cgltf_write_indent(cgltf_write_context* context)
195 if (context->needs_comma)
197 CGLTF_SPRINTF(
",\n");
198 context->needs_comma = 0;
204 for (
int i = 0; i < context->depth; ++i)
206 CGLTF_SPRINTF(
"%s", context->indent);
210 static void cgltf_write_line(cgltf_write_context* context,
const char* line)
212 if (line[0] ==
']' || line[0] ==
'}')
215 context->needs_comma = 0;
217 cgltf_write_indent(context);
218 CGLTF_SPRINTF(
"%s", line);
220 if (line[0] ==
']' || line[0] ==
'}')
222 context->needs_comma = 1;
224 if (line[last] ==
'[' || line[last] ==
'{')
227 context->needs_comma = 0;
231 static void cgltf_write_strprop(cgltf_write_context* context,
const char*
label,
const char*
val)
235 cgltf_write_indent(context);
236 CGLTF_SPRINTF(
"\"%s\": \"%s\"", label, val);
237 context->needs_comma = 1;
241 static void cgltf_write_extras(cgltf_write_context* context,
const cgltf_extras* extras)
245 cgltf_write_indent(context);
246 CGLTF_SPRINTF(
"\"extras\": %s", extras->
data);
247 context->needs_comma = 1;
252 if (length > 0 && context->data->json)
254 char* json_string = ((
char*) context->data->json) + extras->
start_offset;
255 cgltf_write_indent(context);
256 CGLTF_SPRINTF(
"%s",
"\"extras\": ");
258 context->needs_comma = 1;
263 static void cgltf_write_stritem(cgltf_write_context* context,
const char* item)
265 cgltf_write_indent(context);
266 CGLTF_SPRINTF(
"\"%s\"", item);
267 context->needs_comma = 1;
270 static void cgltf_write_intprop(cgltf_write_context* context,
const char* label,
int val,
int def)
274 cgltf_write_indent(context);
275 CGLTF_SPRINTF(
"\"%s\": %d", label, val);
276 context->needs_comma = 1;
280 static void cgltf_write_sizeprop(cgltf_write_context* context,
const char* label,
cgltf_size val,
cgltf_size def)
284 cgltf_write_indent(context);
285 CGLTF_SPRINTF(
"\"%s\": %zu", label, val);
286 context->needs_comma = 1;
290 static void cgltf_write_floatprop(cgltf_write_context* context,
const char* label,
float val,
float def)
294 cgltf_write_indent(context);
295 CGLTF_SPRINTF(
"\"%s\": ", label);
296 CGLTF_SPRINTF(
"%.*g", CGLTF_DECIMAL_DIG, val);
297 context->needs_comma = 1;
301 char *decimal_comma = strchr(context->cursor - context->tmp,
',');
304 *decimal_comma =
'.';
310 static void cgltf_write_boolprop_optional(cgltf_write_context* context,
const char* label,
bool val,
bool def)
314 cgltf_write_indent(context);
315 CGLTF_SPRINTF(
"\"%s\": %s", label, val ?
"true" :
"false");
316 context->needs_comma = 1;
320 static void cgltf_write_floatarrayprop(cgltf_write_context* context,
const char* label,
const cgltf_float* vals,
cgltf_size dim)
322 cgltf_write_indent(context);
323 CGLTF_SPRINTF(
"\"%s\": [", label);
328 CGLTF_SPRINTF(
", %.*g", CGLTF_DECIMAL_DIG, vals[i]);
332 CGLTF_SPRINTF(
"%.*g", CGLTF_DECIMAL_DIG, vals[i]);
336 context->needs_comma = 1;
339 static bool cgltf_check_floatarray(
const float* vals,
int dim,
float val) {
342 if (vals[dim] != val)
385 default:
return NULL;
400 default:
return NULL;
425 default:
return NULL;
436 default:
return NULL;
442 cgltf_write_line(context,
"\"extensions\": {");
443 cgltf_write_line(context,
"\"KHR_texture_transform\": {");
444 if (cgltf_check_floatarray(transform->
offset, 2, 0.0f))
446 cgltf_write_floatarrayprop(context,
"offset", transform->
offset, 2);
448 cgltf_write_floatprop(context,
"rotation", transform->
rotation, 0.0f);
449 if (cgltf_check_floatarray(transform->
scale, 2, 1.0f))
451 cgltf_write_floatarrayprop(context,
"scale", transform->
scale, 2);
455 cgltf_write_intprop(context,
"texCoord", transform->
texcoord, -1);
457 cgltf_write_line(context,
"}");
458 cgltf_write_line(context,
"}");
461 static void cgltf_write_asset(cgltf_write_context* context,
const cgltf_asset* asset)
463 cgltf_write_line(context,
"\"asset\": {");
464 cgltf_write_strprop(context,
"copyright", asset->
copyright);
465 cgltf_write_strprop(context,
"generator", asset->
generator);
466 cgltf_write_strprop(context,
"version", asset->
version);
467 cgltf_write_strprop(context,
"min_version", asset->
min_version);
468 cgltf_write_extras(context, &asset->
extras);
469 cgltf_write_line(context,
"}");
472 static void cgltf_write_primitive(cgltf_write_context* context,
const cgltf_primitive* prim)
474 cgltf_write_intprop(context,
"mode", cgltf_int_from_primitive_type(prim->
type), 4);
475 CGLTF_WRITE_IDXPROP(
"indices", prim->
indices, context->data->accessors);
476 CGLTF_WRITE_IDXPROP(
"material", prim->
material, context->data->materials);
477 cgltf_write_line(context,
"\"attributes\": {");
481 CGLTF_WRITE_IDXPROP(attr->
name, attr->
data, context->data->accessors);
483 cgltf_write_line(context,
"}");
487 cgltf_write_line(context,
"\"targets\": [");
490 cgltf_write_line(context,
"{");
494 CGLTF_WRITE_IDXPROP(attr->
name, attr->
data, context->data->accessors);
496 cgltf_write_line(context,
"}");
498 cgltf_write_line(context,
"]");
500 cgltf_write_extras(context, &prim->
extras);
504 cgltf_write_line(context,
"\"extensions\": {");
508 context->extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION;
511 context->required_extension_flags |= CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION;
514 cgltf_write_line(context,
"\"KHR_draco_mesh_compression\": {");
516 cgltf_write_line(context,
"\"attributes\": {");
520 CGLTF_WRITE_IDXPROP(attr->
name, attr->
data, context->data->accessors);
522 cgltf_write_line(context,
"}");
523 cgltf_write_line(context,
"}");
528 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS;
529 cgltf_write_line(context,
"\"KHR_materials_variants\": {");
530 cgltf_write_line(context,
"\"mappings\": [");
534 cgltf_write_line(context,
"{");
535 CGLTF_WRITE_IDXPROP(
"material", map->
material, context->data->materials);
537 cgltf_write_indent(context);
538 CGLTF_SPRINTF(
"\"variants\": [%d]", (
int)map->
variant);
539 context->needs_comma = 1;
541 cgltf_write_extras(context, &map->
extras);
542 cgltf_write_line(context,
"}");
544 cgltf_write_line(context,
"]");
545 cgltf_write_line(context,
"}");
548 cgltf_write_line(context,
"}");
552 static void cgltf_write_mesh(cgltf_write_context* context,
const cgltf_mesh* mesh)
554 cgltf_write_line(context,
"{");
555 cgltf_write_strprop(context,
"name", mesh->
name);
557 cgltf_write_line(context,
"\"primitives\": [");
560 cgltf_write_line(context,
"{");
561 cgltf_write_primitive(context, mesh->
primitives + i);
562 cgltf_write_line(context,
"}");
564 cgltf_write_line(context,
"]");
571 cgltf_write_extras(context, &mesh->
extras);
572 cgltf_write_line(context,
"}");
575 static void cgltf_write_buffer_view(cgltf_write_context* context,
const cgltf_buffer_view* view)
577 cgltf_write_line(context,
"{");
578 cgltf_write_strprop(context,
"name", view->
name);
579 CGLTF_WRITE_IDXPROP(
"buffer", view->
buffer, context->
data->buffers);
580 cgltf_write_sizeprop(context,
"byteLength", view->
size, (
cgltf_size)-1);
581 cgltf_write_sizeprop(context,
"byteOffset", view->
offset, 0);
582 cgltf_write_sizeprop(context,
"byteStride", view->
stride, 0);
584 cgltf_write_extras(context, &view->
extras);
585 cgltf_write_line(context,
"}");
589 static void cgltf_write_buffer(cgltf_write_context* context,
const cgltf_buffer*
buffer)
591 cgltf_write_line(context,
"{");
592 cgltf_write_strprop(context,
"name", buffer->
name);
593 cgltf_write_strprop(context,
"uri", buffer->
uri);
594 cgltf_write_sizeprop(context,
"byteLength", buffer->
size, (
cgltf_size)-1);
595 cgltf_write_extras(context, &buffer->
extras);
596 cgltf_write_line(context,
"}");
599 static void cgltf_write_material(cgltf_write_context* context,
const cgltf_material* material)
601 cgltf_write_line(context,
"{");
602 cgltf_write_strprop(context,
"name", material->
name);
605 cgltf_write_floatprop(context,
"alphaCutoff", material->
alpha_cutoff, 0.5f);
607 cgltf_write_boolprop_optional(context,
"doubleSided", (
bool)material->
double_sided,
false);
612 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT;
617 context->extension_flags |= CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS;
622 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT;
627 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION;
632 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME;
637 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IOR;
642 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR;
647 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN;
652 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH;
657 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE;
662 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION;
667 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY;
672 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION;
678 cgltf_write_line(context,
"\"pbrMetallicRoughness\": {");
681 cgltf_write_floatprop(context,
"metallicFactor", params->
metallic_factor, 1.0f);
682 cgltf_write_floatprop(context,
"roughnessFactor", params->
roughness_factor, 1.0f);
685 cgltf_write_floatarrayprop(context,
"baseColorFactor", params->
base_color_factor, 4);
687 cgltf_write_line(context,
"}");
692 cgltf_write_line(context,
"\"extensions\": {");
696 cgltf_write_line(context,
"\"KHR_materials_clearcoat\": {");
700 cgltf_write_floatprop(context,
"clearcoatFactor", params->
clearcoat_factor, 0.0f);
702 cgltf_write_line(context,
"}");
707 cgltf_write_line(context,
"\"KHR_materials_ior\": {");
708 cgltf_write_floatprop(context,
"ior", params->
ior, 1.5f);
709 cgltf_write_line(context,
"}");
714 cgltf_write_line(context,
"\"KHR_materials_specular\": {");
717 cgltf_write_floatprop(context,
"specularFactor", params->
specular_factor, 1.0f);
722 cgltf_write_line(context,
"}");
727 cgltf_write_line(context,
"\"KHR_materials_transmission\": {");
730 cgltf_write_line(context,
"}");
735 cgltf_write_line(context,
"\"KHR_materials_volume\": {");
737 cgltf_write_floatprop(context,
"thicknessFactor", params->
thickness_factor, 0.0f);
740 cgltf_write_floatarrayprop(context,
"attenuationColor", params->
attenuation_color, 3);
746 cgltf_write_line(context,
"}");
751 cgltf_write_line(context,
"\"KHR_materials_sheen\": {");
756 cgltf_write_floatarrayprop(context,
"sheenColorFactor", params->
sheen_color_factor, 3);
759 cgltf_write_line(context,
"}");
764 cgltf_write_line(context,
"\"KHR_materials_pbrSpecularGlossiness\": {");
769 cgltf_write_floatarrayprop(context,
"diffuseFactor", params->
diffuse_factor, 4);
773 cgltf_write_floatarrayprop(context,
"specularFactor", params->
specular_factor, 3);
775 cgltf_write_floatprop(context,
"glossinessFactor", params->
glossiness_factor, 1.0f);
776 cgltf_write_line(context,
"}");
780 cgltf_write_line(context,
"\"KHR_materials_unlit\": {}");
784 cgltf_write_line(context,
"\"KHR_materials_emissive_strength\": {");
786 cgltf_write_floatprop(context,
"emissiveStrength", params->
emissive_strength, 1.f);
787 cgltf_write_line(context,
"}");
791 cgltf_write_line(context,
"\"KHR_materials_iridescence\": {");
795 cgltf_write_floatprop(context,
"iridescenceIor", params->
iridescence_ior, 1.3f);
799 cgltf_write_line(context,
"}");
804 cgltf_write_line(context,
"\"KHR_materials_diffuse_transmission\": {");
812 cgltf_write_line(context,
"}");
816 cgltf_write_line(context,
"\"KHR_materials_anisotropy\": {");
821 cgltf_write_line(context,
"}");
825 cgltf_write_line(context,
"\"KHR_materials_dispersion\": {");
827 cgltf_write_floatprop(context,
"dispersion", params->
dispersion, 0.f);
828 cgltf_write_line(context,
"}");
830 cgltf_write_line(context,
"}");
833 CGLTF_WRITE_NORMAL_TEXTURE_INFO(
"normalTexture", material->
normal_texture);
834 CGLTF_WRITE_OCCLUSION_TEXTURE_INFO(
"occlusionTexture", material->
occlusion_texture);
838 cgltf_write_floatarrayprop(context,
"emissiveFactor", material->
emissive_factor, 3);
840 cgltf_write_strprop(context,
"alphaMode", cgltf_str_from_alpha_mode(material->
alpha_mode));
841 cgltf_write_extras(context, &material->
extras);
842 cgltf_write_line(context,
"}");
845 static void cgltf_write_image(cgltf_write_context* context,
const cgltf_image*
image)
847 cgltf_write_line(context,
"{");
848 cgltf_write_strprop(context,
"name", image->
name);
849 cgltf_write_strprop(context,
"uri", image->
uri);
850 CGLTF_WRITE_IDXPROP(
"bufferView", image->
buffer_view, context->
data->buffer_views);
851 cgltf_write_strprop(context,
"mimeType", image->
mime_type);
852 cgltf_write_extras(context, &image->
extras);
853 cgltf_write_line(context,
"}");
858 cgltf_write_line(context,
"{");
859 cgltf_write_strprop(context,
"name", texture->
name);
860 CGLTF_WRITE_IDXPROP(
"source", texture->
image, context->data->images);
861 CGLTF_WRITE_IDXPROP(
"sampler", texture->
sampler, context->data->samplers);
865 cgltf_write_line(context,
"\"extensions\": {");
868 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_BASISU;
869 cgltf_write_line(context,
"\"KHR_texture_basisu\": {");
870 CGLTF_WRITE_IDXPROP(
"source", texture->
basisu_image, context->data->images);
871 cgltf_write_line(context,
"}");
875 context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_WEBP;
876 cgltf_write_line(context,
"\"EXT_texture_webp\": {");
877 CGLTF_WRITE_IDXPROP(
"source", texture->
webp_image, context->data->images);
878 cgltf_write_line(context,
"}");
880 cgltf_write_line(context,
"}");
882 cgltf_write_extras(context, &texture->
extras);
883 cgltf_write_line(context,
"}");
886 static void cgltf_write_skin(cgltf_write_context* context,
const cgltf_skin* skin)
888 cgltf_write_line(context,
"{");
889 CGLTF_WRITE_IDXPROP(
"skeleton", skin->
skeleton, context->data->nodes);
891 CGLTF_WRITE_IDXARRPROP(
"joints", skin->
joints_count, skin->
joints, context->data->nodes);
892 cgltf_write_strprop(context,
"name", skin->
name);
893 cgltf_write_extras(context, &skin->
extras);
894 cgltf_write_line(context,
"}");
902 return "translation";
917 switch (interpolation_type)
924 return "CUBICSPLINE";
933 cgltf_write_strprop(context, label, cgltf_write_str_path_type(path_type));
936 static void cgltf_write_interpolation_type(cgltf_write_context* context,
const char *label,
cgltf_interpolation_type interpolation_type)
938 cgltf_write_strprop(context, label, cgltf_write_str_interpolation_type(interpolation_type));
941 static void cgltf_write_animation_sampler(cgltf_write_context* context,
const cgltf_animation_sampler* animation_sampler)
943 cgltf_write_line(context,
"{");
944 cgltf_write_interpolation_type(context,
"interpolation", animation_sampler->
interpolation);
945 CGLTF_WRITE_IDXPROP(
"input", animation_sampler->
input, context->data->accessors);
946 CGLTF_WRITE_IDXPROP(
"output", animation_sampler->
output, context->data->accessors);
947 cgltf_write_extras(context, &animation_sampler->
extras);
948 cgltf_write_line(context,
"}");
953 cgltf_write_line(context,
"{");
954 CGLTF_WRITE_IDXPROP(
"sampler", animation_channel->
sampler, animation->
samplers);
955 cgltf_write_line(context,
"\"target\": {");
956 CGLTF_WRITE_IDXPROP(
"node", animation_channel->
target_node, context->data->nodes);
957 cgltf_write_path_type(context,
"path", animation_channel->
target_path);
958 cgltf_write_line(context,
"}");
959 cgltf_write_extras(context, &animation_channel->
extras);
960 cgltf_write_line(context,
"}");
963 static void cgltf_write_animation(cgltf_write_context* context,
const cgltf_animation* animation)
965 cgltf_write_line(context,
"{");
966 cgltf_write_strprop(context,
"name", animation->
name);
970 cgltf_write_line(context,
"\"samplers\": [");
973 cgltf_write_animation_sampler(context, animation->
samplers + i);
975 cgltf_write_line(context,
"]");
979 cgltf_write_line(context,
"\"channels\": [");
982 cgltf_write_animation_channel(context, animation, animation->
channels + i);
984 cgltf_write_line(context,
"]");
986 cgltf_write_extras(context, &animation->
extras);
987 cgltf_write_line(context,
"}");
992 cgltf_write_line(context,
"{");
993 cgltf_write_strprop(context,
"name", sampler->
name);
994 cgltf_write_intprop(context,
"magFilter", sampler->
mag_filter, 0);
995 cgltf_write_intprop(context,
"minFilter", sampler->
min_filter, 0);
996 cgltf_write_intprop(context,
"wrapS", sampler->
wrap_s, 10497);
997 cgltf_write_intprop(context,
"wrapT", sampler->
wrap_t, 10497);
998 cgltf_write_extras(context, &sampler->
extras);
999 cgltf_write_line(context,
"}");
1002 static void cgltf_write_node(cgltf_write_context* context,
const cgltf_node* node)
1004 cgltf_write_line(context,
"{");
1006 CGLTF_WRITE_IDXPROP(
"mesh", node->
mesh, context->data->meshes);
1007 cgltf_write_strprop(context,
"name", node->
name);
1010 cgltf_write_floatarrayprop(context,
"matrix", node->
matrix, 16);
1014 cgltf_write_floatarrayprop(context,
"translation", node->
translation, 3);
1018 cgltf_write_floatarrayprop(context,
"rotation", node->
rotation, 4);
1022 cgltf_write_floatarrayprop(context,
"scale", node->
scale, 3);
1026 CGLTF_WRITE_IDXPROP(
"skin", node->
skin, context->data->skins);
1031 cgltf_write_line(context,
"\"extensions\": {");
1035 context->extension_flags |= CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL;
1036 cgltf_write_line(context,
"\"KHR_lights_punctual\": {");
1037 CGLTF_WRITE_IDXPROP(
"light", node->
light, context->data->lights);
1038 cgltf_write_line(context,
"}");
1043 context->extension_flags |= CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING;
1044 context->required_extension_flags |= CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING;
1046 cgltf_write_line(context,
"\"EXT_mesh_gpu_instancing\": {");
1048 cgltf_write_line(context,
"\"attributes\": {");
1053 CGLTF_WRITE_IDXPROP(attr->
name, attr->
data, context->data->accessors);
1056 cgltf_write_line(context,
"}");
1058 cgltf_write_line(context,
"}");
1062 cgltf_write_line(context,
"}");
1071 CGLTF_WRITE_IDXPROP(
"camera", node->
camera, context->
data->cameras);
1074 cgltf_write_extras(context, &node->
extras);
1075 cgltf_write_line(context,
"}");
1078 static void cgltf_write_scene(cgltf_write_context* context,
const cgltf_scene* scene)
1080 cgltf_write_line(context,
"{");
1081 cgltf_write_strprop(context,
"name", scene->
name);
1082 CGLTF_WRITE_IDXARRPROP(
"nodes", scene->
nodes_count, scene->
nodes, context->data->nodes);
1083 cgltf_write_extras(context, &scene->
extras);
1084 cgltf_write_line(context,
"}");
1087 static void cgltf_write_accessor(cgltf_write_context* context,
const cgltf_accessor* accessor)
1089 cgltf_write_line(context,
"{");
1090 cgltf_write_strprop(context,
"name", accessor->
name);
1091 CGLTF_WRITE_IDXPROP(
"bufferView", accessor->
buffer_view, context->
data->buffer_views);
1092 cgltf_write_intprop(context,
"componentType", cgltf_int_from_component_type(accessor->
component_type), 0);
1093 cgltf_write_strprop(context,
"type", cgltf_str_from_type(accessor->
type));
1095 cgltf_write_boolprop_optional(context,
"normalized", (
bool)accessor->
normalized,
false);
1096 cgltf_write_sizeprop(context,
"byteOffset", (
int)accessor->
offset, 0);
1097 cgltf_write_intprop(context,
"count", (
int)accessor->
count, -1);
1100 cgltf_write_floatarrayprop(context,
"min", accessor->
min, dim);
1104 cgltf_write_floatarrayprop(context,
"max", accessor->
max, dim);
1108 cgltf_write_line(context,
"\"sparse\": {");
1109 cgltf_write_intprop(context,
"count", (
int)accessor->
sparse.
count, 0);
1110 cgltf_write_line(context,
"\"indices\": {");
1114 cgltf_write_line(context,
"}");
1115 cgltf_write_line(context,
"\"values\": {");
1118 cgltf_write_line(context,
"}");
1119 cgltf_write_line(context,
"}");
1121 cgltf_write_extras(context, &accessor->
extras);
1122 cgltf_write_line(context,
"}");
1125 static void cgltf_write_camera(cgltf_write_context* context,
const cgltf_camera* camera)
1127 cgltf_write_line(context,
"{");
1128 cgltf_write_strprop(context,
"type", cgltf_str_from_camera_type(camera->
type));
1131 cgltf_write_strprop(context,
"name", camera->
name);
1136 cgltf_write_line(context,
"\"orthographic\": {");
1142 cgltf_write_line(context,
"}");
1146 cgltf_write_line(context,
"\"perspective\": {");
1160 cgltf_write_line(context,
"}");
1162 cgltf_write_extras(context, &camera->
extras);
1163 cgltf_write_line(context,
"}");
1166 static void cgltf_write_light(cgltf_write_context* context,
const cgltf_light* light)
1168 context->extension_flags |= CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL;
1170 cgltf_write_line(context,
"{");
1171 cgltf_write_strprop(context,
"type", cgltf_str_from_light_type(light->
type));
1174 cgltf_write_strprop(context,
"name", light->
name);
1176 if (cgltf_check_floatarray(light->
color, 3, 1.0f))
1178 cgltf_write_floatarrayprop(context,
"color", light->
color, 3);
1180 cgltf_write_floatprop(context,
"intensity", light->
intensity, 1.0f);
1181 cgltf_write_floatprop(context,
"range", light->
range, 0.0f);
1185 cgltf_write_line(context,
"\"spot\": {");
1187 cgltf_write_floatprop(context,
"outerConeAngle", light->
spot_outer_cone_angle, 3.14159265358979323846f/4.0f);
1188 cgltf_write_line(context,
"}");
1190 cgltf_write_extras( context, &light->
extras );
1191 cgltf_write_line(context,
"}");
1196 context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS;
1198 cgltf_write_line(context,
"{");
1199 cgltf_write_strprop(context,
"name", variant->
name);
1200 cgltf_write_extras(context, &variant->
extras);
1201 cgltf_write_line(context,
"}");
1204 static void cgltf_write_glb(FILE* file,
const void* json_buf,
const cgltf_size json_size,
const void* bin_buf,
const cgltf_size bin_size)
1206 char header[GlbHeaderSize];
1207 char chunk_header[GlbChunkHeaderSize];
1208 char json_pad[3] = { 0x20, 0x20, 0x20 };
1209 char bin_pad[3] = { 0, 0, 0 };
1211 cgltf_size json_padsize = (json_size % 4 != 0) ? 4 - json_size % 4 : 0;
1212 cgltf_size bin_padsize = (bin_size % 4 != 0) ? 4 - bin_size % 4 : 0;
1213 cgltf_size total_size = GlbHeaderSize + GlbChunkHeaderSize + json_size + json_padsize;
1214 if (bin_buf != NULL && bin_size > 0) {
1215 total_size += GlbChunkHeaderSize + bin_size + bin_padsize;
1219 memcpy(header, &GlbMagic, 4);
1220 memcpy(header + 4, &GlbVersion, 4);
1221 memcpy(header + 8, &total_size, 4);
1222 fwrite(header, 1, GlbHeaderSize, file);
1225 uint32_t json_chunk_size = (uint32_t)(json_size + json_padsize);
1226 memcpy(chunk_header, &json_chunk_size, 4);
1227 memcpy(chunk_header + 4, &GlbMagicJsonChunk, 4);
1228 fwrite(chunk_header, 1, GlbChunkHeaderSize, file);
1230 fwrite(json_buf, 1, json_size, file);
1231 fwrite(json_pad, 1, json_padsize, file);
1233 if (bin_buf != NULL && bin_size > 0) {
1235 uint32_t bin_chunk_size = (uint32_t)(bin_size + bin_padsize);
1236 memcpy(chunk_header, &bin_chunk_size, 4);
1237 memcpy(chunk_header + 4, &GlbMagicBinChunk, 4);
1238 fwrite(chunk_header, 1, GlbChunkHeaderSize, file);
1240 fwrite(bin_buf, 1, bin_size, file);
1241 fwrite(bin_pad, 1, bin_padsize, file);
1248 char*
buffer = (
char*) malloc(expected);
1250 if (expected != actual) {
1251 fprintf(stderr,
"Error: expected %zu bytes but wrote %zu bytes.\n", expected, actual);
1260 cgltf_write_glb(file, buffer, actual - 1, data->
bin, data->
bin_size);
1263 fwrite(buffer, actual - 1, 1, file);
1270 static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extension_flags)
1272 if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM) {
1273 cgltf_write_stritem(context,
"KHR_texture_transform");
1275 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_UNLIT) {
1276 cgltf_write_stritem(context,
"KHR_materials_unlit");
1278 if (extension_flags & CGLTF_EXTENSION_FLAG_SPECULAR_GLOSSINESS) {
1279 cgltf_write_stritem(context,
"KHR_materials_pbrSpecularGlossiness");
1281 if (extension_flags & CGLTF_EXTENSION_FLAG_LIGHTS_PUNCTUAL) {
1282 cgltf_write_stritem(context,
"KHR_lights_punctual");
1284 if (extension_flags & CGLTF_EXTENSION_FLAG_DRACO_MESH_COMPRESSION) {
1285 cgltf_write_stritem(context,
"KHR_draco_mesh_compression");
1287 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_CLEARCOAT) {
1288 cgltf_write_stritem(context,
"KHR_materials_clearcoat");
1290 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IOR) {
1291 cgltf_write_stritem(context,
"KHR_materials_ior");
1293 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SPECULAR) {
1294 cgltf_write_stritem(context,
"KHR_materials_specular");
1296 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_TRANSMISSION) {
1297 cgltf_write_stritem(context,
"KHR_materials_transmission");
1299 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_SHEEN) {
1300 cgltf_write_stritem(context,
"KHR_materials_sheen");
1302 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_VARIANTS) {
1303 cgltf_write_stritem(context,
"KHR_materials_variants");
1305 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_VOLUME) {
1306 cgltf_write_stritem(context,
"KHR_materials_volume");
1308 if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_BASISU) {
1309 cgltf_write_stritem(context,
"KHR_texture_basisu");
1311 if (extension_flags & CGLTF_EXTENSION_FLAG_TEXTURE_WEBP) {
1312 cgltf_write_stritem(context,
"EXT_texture_webp");
1314 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH) {
1315 cgltf_write_stritem(context,
"KHR_materials_emissive_strength");
1317 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE) {
1318 cgltf_write_stritem(context,
"KHR_materials_iridescence");
1320 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DIFFUSE_TRANSMISSION) {
1321 cgltf_write_stritem(context,
"KHR_materials_diffuse_transmission");
1323 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY) {
1324 cgltf_write_stritem(context,
"KHR_materials_anisotropy");
1326 if (extension_flags & CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING) {
1327 cgltf_write_stritem(context,
"EXT_mesh_gpu_instancing");
1329 if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION) {
1330 cgltf_write_stritem(context,
"KHR_materials_dispersion");
1337 cgltf_write_context ctx;
1339 ctx.buffer_size =
size;
1340 ctx.remaining =
size;
1342 ctx.chars_written = 0;
1346 ctx.needs_comma = 0;
1347 ctx.extension_flags = 0;
1348 ctx.required_extension_flags = 0;
1350 cgltf_write_context* context = &ctx;
1356 cgltf_write_line(context,
"\"accessors\": [");
1359 cgltf_write_accessor(context, data->
accessors + i);
1361 cgltf_write_line(context,
"]");
1364 cgltf_write_asset(context, &data->
asset);
1368 cgltf_write_line(context,
"\"bufferViews\": [");
1371 cgltf_write_buffer_view(context, data->
buffer_views + i);
1373 cgltf_write_line(context,
"]");
1378 cgltf_write_line(context,
"\"buffers\": [");
1381 cgltf_write_buffer(context, data->
buffers + i);
1383 cgltf_write_line(context,
"]");
1388 cgltf_write_line(context,
"\"images\": [");
1391 cgltf_write_image(context, data->
images + i);
1393 cgltf_write_line(context,
"]");
1398 cgltf_write_line(context,
"\"meshes\": [");
1401 cgltf_write_mesh(context, data->
meshes + i);
1403 cgltf_write_line(context,
"]");
1408 cgltf_write_line(context,
"\"materials\": [");
1411 cgltf_write_material(context, data->
materials + i);
1413 cgltf_write_line(context,
"]");
1418 cgltf_write_line(context,
"\"nodes\": [");
1421 cgltf_write_node(context, data->
nodes + i);
1423 cgltf_write_line(context,
"]");
1428 cgltf_write_line(context,
"\"samplers\": [");
1431 cgltf_write_sampler(context, data->
samplers + i);
1433 cgltf_write_line(context,
"]");
1436 CGLTF_WRITE_IDXPROP(
"scene", data->
scene, data->
scenes);
1440 cgltf_write_line(context,
"\"scenes\": [");
1443 cgltf_write_scene(context, data->
scenes + i);
1445 cgltf_write_line(context,
"]");
1450 cgltf_write_line(context,
"\"textures\": [");
1453 cgltf_write_texture(context, data->
textures + i);
1455 cgltf_write_line(context,
"]");
1460 cgltf_write_line(context,
"\"skins\": [");
1463 cgltf_write_skin(context, data->
skins + i);
1465 cgltf_write_line(context,
"]");
1470 cgltf_write_line(context,
"\"animations\": [");
1473 cgltf_write_animation(context, data->
animations + i);
1475 cgltf_write_line(context,
"]");
1480 cgltf_write_line(context,
"\"cameras\": [");
1483 cgltf_write_camera(context, data->
cameras + i);
1485 cgltf_write_line(context,
"]");
1490 cgltf_write_line(context,
"\"extensions\": {");
1494 cgltf_write_line(context,
"\"KHR_lights_punctual\": {");
1495 cgltf_write_line(context,
"\"lights\": [");
1498 cgltf_write_light(context, data->
lights + i);
1500 cgltf_write_line(context,
"]");
1501 cgltf_write_line(context,
"}");
1506 cgltf_write_line(context,
"\"KHR_materials_variants\": {");
1507 cgltf_write_line(context,
"\"variants\": [");
1510 cgltf_write_variant(context, data->
variants + i);
1512 cgltf_write_line(context,
"]");
1513 cgltf_write_line(context,
"}");
1516 cgltf_write_line(context,
"}");
1519 if (context->extension_flags != 0)
1521 cgltf_write_line(context,
"\"extensionsUsed\": [");
1522 cgltf_write_extensions(context, context->extension_flags);
1523 cgltf_write_line(context,
"]");
1526 if (context->required_extension_flags != 0)
1528 cgltf_write_line(context,
"\"extensionsRequired\": [");
1529 cgltf_write_extensions(context, context->required_extension_flags);
1530 cgltf_write_line(context,
"]");
1533 cgltf_write_extras(context, &data->
extras);
1535 CGLTF_SPRINTF(
"\n}\n");
1539 return 1 + ctx.chars_written;
cgltf_material * materials
path_type
CLI enumeration of different file types.
cgltf_texture_view emissive_texture
cgltf_component_type component_type
cgltf_material_mapping * mappings
cgltf_bool has_emissive_strength
GLuint GLsizei const GLchar * label
cgltf_size animations_count
cgltf_bool has_pbr_specular_glossiness
cgltf_texture_view occlusion_texture
cgltf_material_variant * variants
cgltf_camera_perspective perspective
cgltf_attribute * attributes
cgltf_bool has_iridescence
cgltf_result cgltf_write_file(const cgltf_options *options, const char *path, const cgltf_data *data)
cgltf_texture_view specular_color_texture
cgltf_texture_view iridescence_texture
cgltf_texture_view clearcoat_roughness_texture
cgltf_float iridescence_ior
cgltf_float glossiness_factor
cgltf_size channels_count
GLsizei const GLchar *const * path
cgltf_animation_path_type target_path
cgltf_texture_view transmission_texture
cgltf_primitive * primitives
cgltf_buffer_view * values_buffer_view
cgltf_attribute * attributes
GLuint GLsizei GLsizei * length
cgltf_bool has_dispersion
cgltf_component_type indices_component_type
cgltf_float transmission_factor
cgltf_float diffuse_transmission_color_factor[3]
GLenum GLenum GLsizei void * image
GLenum const GLfloat * params
cgltf_float iridescence_thickness_min
cgltf_iridescence iridescence
cgltf_float clearcoat_roughness_factor
cgltf_float anisotropy_rotation
cgltf_texture_view normal_texture
cgltf_size attributes_count
cgltf_float spot_inner_cone_angle
cgltf_texture_view thickness_texture
cgltf_buffer_view * buffer_view
GLint GLint GLsizei GLint GLenum GLenum type
cgltf_float emissive_strength
cgltf_size mappings_count
cgltf_size values_byte_offset
cgltf_size primitives_count
cgltf_float sheen_roughness_factor
cgltf_camera_orthographic orthographic
cgltf_float emissive_factor[3]
cgltf_size attributes_count
cgltf_primitive_type type
OIIO_UTIL_API FILE * fopen(string_view path, string_view mode)
Version of fopen that can handle UTF-8 paths even on Windows.
cgltf_emissive_strength emissive_strength
cgltf_texture_view specular_texture
cgltf_animation * animations
cgltf_float iridescence_thickness_max
cgltf_dispersion dispersion
cgltf_size indices_byte_offset
cgltf_buffer_view * buffer_views
cgltf_accessor_sparse sparse
cgltf_float iridescence_factor
cgltf_size buffer_views_count
union cgltf_camera::@7 data
cgltf_size materials_count
cgltf_size accessors_count
cgltf_morph_target * targets
cgltf_texture_view anisotropy_texture
GA_API const UT_StringHolder transform
cgltf_material * material
cgltf_animation_path_type
cgltf_size samplers_count
cgltf_pbr_specular_glossiness pbr_specular_glossiness
auto fprintf(std::FILE *f, const S &fmt, const T &...args) -> int
cgltf_float attenuation_color[3]
cgltf_buffer_view * indices_buffer_view
cgltf_bool has_transmission
GLint GLint GLsizei GLsizei GLsizei depth
cgltf_alpha_mode alpha_mode
cgltf_size textures_count
__hostdev__ uint64_t last(uint32_t i) const
cgltf_material * material
cgltf_texture_view specular_glossiness_texture
cgltf_texture_view sheen_roughness_texture
cgltf_bool has_mesh_gpu_instancing
cgltf_diffuse_transmission diffuse_transmission
cgltf_anisotropy anisotropy
cgltf_accessor * inverse_bind_matrices
cgltf_float anisotropy_strength
cgltf_filter_type min_filter
cgltf_texture_view diffuse_transmission_texture
cgltf_float clearcoat_factor
cgltf_pbr_metallic_roughness pbr_metallic_roughness
cgltf_size attributes_count
cgltf_bool has_anisotropy
cgltf_texture_view clearcoat_normal_texture
cgltf_attribute * attributes
cgltf_interpolation_type interpolation
cgltf_attribute * attributes
cgltf_animation_sampler * sampler
cgltf_animation_sampler * samplers
cgltf_animation_channel * channels
cgltf_float specular_factor
cgltf_size samplers_count
cgltf_float spot_outer_cone_angle
cgltf_float diffuse_transmission_factor
cgltf_draco_mesh_compression draco_mesh_compression
cgltf_texture_view iridescence_thickness_texture
cgltf_bool has_diffuse_transmission
cgltf_texture_view clearcoat_texture
cgltf_clearcoat clearcoat
cgltf_float diffuse_factor[4]
cgltf_size cgltf_write(const cgltf_options *options, char *buffer, cgltf_size size, const cgltf_data *data)
cgltf_image * basisu_image
cgltf_texture_view diffuse_transmission_color_texture
cgltf_mesh_gpu_instancing mesh_gpu_instancing
cgltf_transmission transmission
cgltf_texture_view diffuse_texture
cgltf_bool has_draco_mesh_compression
cgltf_filter_type mag_filter
cgltf_buffer_view * buffer_view
cgltf_texture_view sheen_color_texture
cgltf_float thickness_factor
cgltf_float translation[3]
cgltf_bool has_pbr_metallic_roughness
cgltf_size attributes_count
cgltf_float specular_color_factor[3]
cgltf_float attenuation_distance
cgltf_float sheen_color_factor[3]
cgltf_bool has_translation
cgltf_size variants_count
cgltf_bool has_aspect_ratio
cgltf_buffer_view * buffer_view
cgltf_accessor * accessors
cgltf_size children_count
cgltf_float specular_factor[3]