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