XII Release 0.1.0
Loading...
Searching...
No Matches
ogt_vox.h
1/*
2 opengametools vox file reader/writer - v0.6 - MIT license - Justin Paver, Oct 2019
3
4 This is a single-header-file library that provides easy-to-use
5 support for reading MagicaVoxel .vox files into structures that
6 are easy to dereference and extract information from. It also
7 supports writing back out to .vox file from those structures.
8
9 Please see the MIT license information at the end of this file.
10
11 Also, please consider sharing any improvements you make.
12
13 For more information and more tools, visit:
14 https://github.com/jpaver/opengametools
15
16 HOW TO COMPILE THIS LIBRARY
17
18 1. To compile this library, do this in *one* C or C++ file:
19 #define OGT_VOX_IMPLEMENTATION
20 #include "ogt_vox.h"
21
22 2. From any other module, it is sufficient to just #include this as usual:
23 #include "ogt_vox.h"
24
25 HOW TO READ A VOX SCENE (See demo_vox.cpp)
26
27 1. load a .vox file off disk into a memory buffer.
28
29 2. construct a scene from the memory buffer:
30 ogt_vox_scene* scene = ogt_vox_read_scene(buffer, buffer_size);
31
32 3. use the scene members to extract the information you need. eg.
33 printf("# of layers: %u\n", scene->num_layers );
34
35 4. destroy the scene:
36 ogt_vox_destroy_scene(scene);
37
38 HOW TO MERGE MULTIPLE VOX SCENES (See merge_vox.cpp)
39
40 1. construct multiple scenes from files you want to merge.
41
42 // read buffer1/buffer_size1 from "test1.vox"
43 // read buffer2/buffer_size2 from "test2.vox"
44 // read buffer3/buffer_size3 from "test3.vox"
45 ogt_vox_scene* scene1 = ogt_vox_read_scene(buffer1, buffer_size1);
46 ogt_vox_scene* scene2 = ogt_vox_read_scene(buffer2, buffer_size2);
47 ogt_vox_scene* scene3 = ogt_vox_read_scene(buffer3, buffer_size3);
48
49 2. construct a merged scene
50
51 const ogt_vox_scene* scenes[] = {scene1, scene2, scene3};
52 ogt_vox_scene* merged_scene = ogt_vox_merge_scenes(scenes, 3, NULL, 0);
53
54 3. save out the merged scene
55
56 uint8_t* out_buffer = ogt_vox_write_scene(merged_scene, &out_buffer_size);
57 // save out_buffer to disk as a .vox file (it has length out_buffer_size)
58
59 4. destroy the merged scene:
60
61 ogt_vox_destroy_scene(merged_scene);
62
63 EXPLANATION OF SCENE ELEMENTS:
64
65 A ogt_vox_scene comprises primarily a set of instances, models, layers and a palette.
66
67 A ogt_vox_palette contains a set of 256 colors that is used for the scene.
68 Each color is represented by a 4-tuple called an ogt_vox_rgba which contains red,
69 green, blue and alpha values for the color.
70
71 A ogt_vox_model is a 3-dimensional grid of voxels, where each of those voxels
72 is represented by an 8-bit color index. Voxels are arranged in order of increasing
73 X then increasing Y then increasing Z.
74
75 Given the x,y,z values for a voxel within the model dimensions, the voxels index
76 in the grid can be obtained as follows:
77
78 voxel_index = x + (y * model->size_x) + (z * model->size_x * model->size_y)
79
80 The index is only valid if the coordinate x,y,z satisfy the following conditions:
81 0 <= x < model->size_x -AND-
82 0 <= y < model->size_y -AND-
83 0 <= z < model->size_z
84
85 A voxels color index can be obtained as follows:
86
87 uint8_t color_index = model->voxel_data[voxel_index];
88
89 If color_index == 0, the voxel is not solid and can be skipped,
90 If color_index != 0, the voxel is solid and can be used to lookup the color in the palette:
91
92 ogt_vox_rgba color = scene->palette.color[ color_index]
93
94 A ogt_vox_instance is an individual placement of a voxel model within the scene. Each
95 instance has a transform that determines its position and orientation within the scene,
96 but it also has an index that specifies which model the instance uses for its shape. It
97 is expected that there is a many-to-one mapping of instances to models.
98
99 An ogt_vox_layer is used to conceptually group instances. Each instance indexes the
100 layer that it belongs to, but the layer itself has its own name and hidden/shown state.
101
102 EXPLANATION OF MERGED SCENES:
103
104 A merged scene contains all the models and all the scene instances from
105 each of the scenes that were passed into it.
106
107 The merged scene will have a combined palette of all the source scene
108 palettes by trying to match existing colors exactly, and falling back
109 to an RGB-distance matched color when all 256 colors in the merged
110 scene palette has been allocated.
111
112 You can explicitly control up to 255 merge palette colors by providing
113 those colors to ogt_vox_merge_scenes in the required_colors parameters eg.
114
115 const ogt_vox_palette palette; // load this via .vox or procedurally or whatever
116 const ogt_vox_scene* scenes[] = {scene1, scene2, scene3};
117 // palette.color[0] is always the empty color which is why we pass 255 colors starting from index 1 only:
118 ogt_vox_scene* merged_scene = ogt_vox_merge_scenes(scenes, 3, &palette.color[1], 255);
119*/
120#ifndef OGT_VOX_H__
121# define OGT_VOX_H__
122
123# if _MSC_VER == 1400
124// VS2005 doesn't have inttypes or stdint so we just define what we need here.
125typedef unsigned char uint8_t;
126typedef signed int int32_t;
127typedef unsigned int uint32_t;
128# ifndef UINT32_MAX
129# define UINT32_MAX ((uint32_t)0xFFFFFFFF)
130# endif
131# ifndef INT32_MAX
132# define INT32_MAX ((int32_t)0x7FFFFFFF)
133# endif
134# ifndef UINT8_MAX
135# define UINT8_MAX ((uint8_t)0xFF)
136# endif
137# elif defined(_MSC_VER)
138// general VS*
139# include <inttypes.h>
140# elif __APPLE__
141// general Apple compiler
142# elif defined(__GNUC__)
143// any GCC*
144# include <inttypes.h>
145# include <stdlib.h> // for size_t
146# else
147# error some fixup needed for this platform?
148# endif
149
150// denotes an invalid group index. Usually this is only applicable to the scene's root group's parent.
151static const uint32_t k_invalid_group_index = UINT32_MAX;
152
153// color
154typedef struct ogt_vox_rgba
155{
156 uint8_t r, g, b, a; // red, green, blue and alpha components of a color.
158
159// column-major 4x4 matrix
160typedef struct ogt_vox_transform
161{
162 float m00, m01, m02, m03; // column 0 of 4x4 matrix, 1st three elements = x axis vector, last element always 0.0
163 float m10, m11, m12, m13; // column 1 of 4x4 matrix, 1st three elements = y axis vector, last element always 0.0
164 float m20, m21, m22, m23; // column 2 of 4x4 matrix, 1st three elements = z axis vector, last element always 0.0
165 float m30, m31, m32, m33; // column 3 of 4x4 matrix. 1st three elements = translation vector, last element always 1.0
167
168// a palette of colors
169typedef struct ogt_vox_palette
170{
171 ogt_vox_rgba color[256]; // palette of colors. use the voxel indices to lookup color from the palette.
173
174// a 3-dimensional model of voxels
175typedef struct ogt_vox_model
176{
177 uint32_t size_x; // number of voxels in the local x dimension
178 uint32_t size_y; // number of voxels in the local y dimension
179 uint32_t size_z; // number of voxels in the local z dimension
180 uint32_t voxel_hash; // hash of the content of the grid.
181 const uint8_t* voxel_data; // grid of voxel data comprising color indices in x -> y -> z order. a color index of 0 means empty, all other indices mean solid and can be used to index the scene's palette to obtain the color for the voxel.
183
184// an instance of a model within the scene
185typedef struct ogt_vox_instance
186{
187 const char* name; // name of the instance if there is one, will be NULL otherwise.
188 ogt_vox_transform transform; // orientation and position of this instance within the scene. This is relative to its group local transform if group_index is not 0
189 uint32_t model_index; // index of the model used by this instance. used to lookup the model in the scene's models[] array.
190 uint32_t layer_index; // index of the layer used by this instance. used to lookup the layer in the scene's layers[] array.
191 uint32_t group_index; // this will be the index of the group in the scene's groups[] array. If group is zero it will be the scene root group and the instance transform will be a world-space transform, otherwise the transform is relative to the group.
192 bool hidden; // whether this instance is individually hidden or not. Note: the instance can also be hidden when its layer is hidden, or if it belongs to a group that is hidden.
194
195// describes a layer within the scene
196typedef struct ogt_vox_layer
197{
198 const char* name; // name of this layer if there is one, will be NULL otherwise.
199 bool hidden; // whether this layer is hidden or not.
201
202// describes a group within the scene
203typedef struct ogt_vox_group
204{
205 ogt_vox_transform transform; // transform of this group relative to its parent group (if any), otherwise this will be relative to world-space.
206 uint32_t parent_group_index; // if this group is parented to another group, this will be the index of its parent in the scene's groups[] array, otherwise this group will be the scene root group and this value will be k_invalid_group_index
207 uint32_t layer_index; // which layer this group belongs to. used to lookup the layer in the scene's layers[] array.
208 bool hidden; // whether this group is hidden or not.
210
211// the scene parsed from a .vox file.
212typedef struct ogt_vox_scene
213{
214 uint32_t num_models; // number of models within the scene.
215 uint32_t num_instances; // number of instances in the scene
216 uint32_t num_layers; // number of layers in the scene
217 uint32_t num_groups; // number of groups in the scene
218 const ogt_vox_model** models; // array of models. size is num_models
219 const ogt_vox_instance* instances; // array of instances. size is num_instances
220 const ogt_vox_layer* layers; // array of layers. size is num_layers
221 const ogt_vox_group* groups; // array of groups. size is num_groups
222 ogt_vox_palette palette; // the palette for this scene
224
225// allocate memory function interface. pass in size, and get a pointer to memory with at least that size available.
226typedef void* (*ogt_vox_alloc_func)(size_t size);
227
228// free memory function interface. pass in a pointer previously allocated and it will be released back to the system managing memory.
229typedef void (*ogt_vox_free_func)(void* ptr);
230
231// override the default scene memory allocator if you need to control memory precisely.
232void ogt_vox_set_memory_allocator(ogt_vox_alloc_func alloc_func, ogt_vox_free_func free_func);
233void* ogt_vox_malloc(size_t uiSize);
234void ogt_vox_free(void* pMem);
235
236// flags for ogt_vox_read_scene_with_flags
237static const uint32_t k_read_scene_flags_groups = 1 << 0; // if not specified, all instance transforms will be flattened into world space. If specified, will read group information and keep all transforms as local transform relative to the group they are in.
238
239// creates a scene from a vox file within a memory buffer of a given size.
240// you can destroy the input buffer once you have the scene as this function will allocate separate memory for the scene objecvt.
241const ogt_vox_scene* ogt_vox_read_scene(const uint8_t* pBuffer, uint32_t buffer_size);
242
243// just like ogt_vox_read_scene, but you can additionally pass a union of k_read_scene_flags
244const ogt_vox_scene* ogt_vox_read_scene_with_flags(const uint8_t* pBuffer, uint32_t buffer_size, uint32_t read_flags);
245
246// destroys a scene object to release its memory.
247void ogt_vox_destroy_scene(const ogt_vox_scene* pScene);
248
249// writes the scene to a new buffer and returns the buffer size. free the buffer with ogt_vox_free
250uint8_t* ogt_vox_write_scene(const ogt_vox_scene* pScene, uint32_t* pBuffer_size);
251
252// merges the specified scenes together to create a bigger scene. Merged scene can be destroyed using ogt_vox_destroy_scene
253// If you require specific colors in the merged scene palette, provide up to and including 255 of them via required_colors/required_color_count.
254ogt_vox_scene* ogt_vox_merge_scenes(const ogt_vox_scene** pScenes, uint32_t scene_count, const ogt_vox_rgba* pRequired_colors, const uint32_t required_color_count);
255
256#endif // OGT_VOX_H__
257
258//-----------------------------------------------------------------------------------------------------------------
259//
260// If you're only interested in using this library, everything you need is above this point.
261// If you're interested in how this library works, everything you need is below this point.
262//
263//-----------------------------------------------------------------------------------------------------------------
264#ifdef OGT_VOX_IMPLEMENTATION
265# include <assert.h>
266# include <stdio.h>
267# include <stdlib.h>
268# include <string.h>
269
270// MAKE_VOX_CHUNK_ID: used to construct a literal to describe a chunk in a .vox file.
271# define MAKE_VOX_CHUNK_ID(c0, c1, c2, c3) ((c0 << 0) | (c1 << 8) | (c2 << 16) | (c3 << 24))
272
273static const uint32_t CHUNK_ID_VOX_ = MAKE_VOX_CHUNK_ID('V', 'O', 'X', ' ');
274static const uint32_t CHUNK_ID_MAIN = MAKE_VOX_CHUNK_ID('M', 'A', 'I', 'N');
275static const uint32_t CHUNK_ID_SIZE = MAKE_VOX_CHUNK_ID('S', 'I', 'Z', 'E');
276static const uint32_t CHUNK_ID_XYZI = MAKE_VOX_CHUNK_ID('X', 'Y', 'Z', 'I');
277static const uint32_t CHUNK_ID_RGBA = MAKE_VOX_CHUNK_ID('R', 'G', 'B', 'A');
278static const uint32_t CHUNK_ID_nTRN = MAKE_VOX_CHUNK_ID('n', 'T', 'R', 'N');
279static const uint32_t CHUNK_ID_nGRP = MAKE_VOX_CHUNK_ID('n', 'G', 'R', 'P');
280static const uint32_t CHUNK_ID_nSHP = MAKE_VOX_CHUNK_ID('n', 'S', 'H', 'P');
281static const uint32_t CHUNK_ID_IMAP = MAKE_VOX_CHUNK_ID('I', 'M', 'A', 'P');
282static const uint32_t CHUNK_ID_LAYR = MAKE_VOX_CHUNK_ID('L', 'A', 'Y', 'R');
283static const uint32_t CHUNK_ID_MATL = MAKE_VOX_CHUNK_ID('M', 'A', 'T', 'L');
284static const uint32_t CHUNK_ID_MATT = MAKE_VOX_CHUNK_ID('M', 'A', 'T', 'T');
285static const uint32_t CHUNK_ID_rOBJ = MAKE_VOX_CHUNK_ID('r', 'O', 'B', 'J');
286
287// Some older .vox files will not store a palette, in which case the following palette will be used!
288static const uint8_t k_default_vox_palette[256 * 4] = {
289 0xff,
290 0xff,
291 0xff,
292 0xff,
293 0xff,
294 0xff,
295 0xcc,
296 0xff,
297 0xff,
298 0xff,
299 0x99,
300 0xff,
301 0xff,
302 0xff,
303 0x66,
304 0xff,
305 0xff,
306 0xff,
307 0x33,
308 0xff,
309 0xff,
310 0xff,
311 0x00,
312 0xff,
313 0xff,
314 0xcc,
315 0xff,
316 0xff,
317 0xff,
318 0xcc,
319 0xcc,
320 0xff,
321 0xff,
322 0xcc,
323 0x99,
324 0xff,
325 0xff,
326 0xcc,
327 0x66,
328 0xff,
329 0xff,
330 0xcc,
331 0x33,
332 0xff,
333 0xff,
334 0xcc,
335 0x00,
336 0xff,
337 0xff,
338 0x99,
339 0xff,
340 0xff,
341 0xff,
342 0x99,
343 0xcc,
344 0xff,
345 0xff,
346 0x99,
347 0x99,
348 0xff,
349 0xff,
350 0x99,
351 0x66,
352 0xff,
353 0xff,
354 0x99,
355 0x33,
356 0xff,
357 0xff,
358 0x99,
359 0x00,
360 0xff,
361 0xff,
362 0x66,
363 0xff,
364 0xff,
365 0xff,
366 0x66,
367 0xcc,
368 0xff,
369 0xff,
370 0x66,
371 0x99,
372 0xff,
373 0xff,
374 0x66,
375 0x66,
376 0xff,
377 0xff,
378 0x66,
379 0x33,
380 0xff,
381 0xff,
382 0x66,
383 0x00,
384 0xff,
385 0xff,
386 0x33,
387 0xff,
388 0xff,
389 0xff,
390 0x33,
391 0xcc,
392 0xff,
393 0xff,
394 0x33,
395 0x99,
396 0xff,
397 0xff,
398 0x33,
399 0x66,
400 0xff,
401 0xff,
402 0x33,
403 0x33,
404 0xff,
405 0xff,
406 0x33,
407 0x00,
408 0xff,
409 0xff,
410 0x00,
411 0xff,
412 0xff,
413 0xff,
414 0x00,
415 0xcc,
416 0xff,
417 0xff,
418 0x00,
419 0x99,
420 0xff,
421 0xff,
422 0x00,
423 0x66,
424 0xff,
425 0xff,
426 0x00,
427 0x33,
428 0xff,
429 0xff,
430 0x00,
431 0x00,
432 0xff,
433 0xcc,
434 0xff,
435 0xff,
436 0xff,
437 0xcc,
438 0xff,
439 0xcc,
440 0xff,
441 0xcc,
442 0xff,
443 0x99,
444 0xff,
445 0xcc,
446 0xff,
447 0x66,
448 0xff,
449 0xcc,
450 0xff,
451 0x33,
452 0xff,
453 0xcc,
454 0xff,
455 0x00,
456 0xff,
457 0xcc,
458 0xcc,
459 0xff,
460 0xff,
461 0xcc,
462 0xcc,
463 0xcc,
464 0xff,
465 0xcc,
466 0xcc,
467 0x99,
468 0xff,
469 0xcc,
470 0xcc,
471 0x66,
472 0xff,
473 0xcc,
474 0xcc,
475 0x33,
476 0xff,
477 0xcc,
478 0xcc,
479 0x00,
480 0xff,
481 0xcc,
482 0x99,
483 0xff,
484 0xff,
485 0xcc,
486 0x99,
487 0xcc,
488 0xff,
489 0xcc,
490 0x99,
491 0x99,
492 0xff,
493 0xcc,
494 0x99,
495 0x66,
496 0xff,
497 0xcc,
498 0x99,
499 0x33,
500 0xff,
501 0xcc,
502 0x99,
503 0x00,
504 0xff,
505 0xcc,
506 0x66,
507 0xff,
508 0xff,
509 0xcc,
510 0x66,
511 0xcc,
512 0xff,
513 0xcc,
514 0x66,
515 0x99,
516 0xff,
517 0xcc,
518 0x66,
519 0x66,
520 0xff,
521 0xcc,
522 0x66,
523 0x33,
524 0xff,
525 0xcc,
526 0x66,
527 0x00,
528 0xff,
529 0xcc,
530 0x33,
531 0xff,
532 0xff,
533 0xcc,
534 0x33,
535 0xcc,
536 0xff,
537 0xcc,
538 0x33,
539 0x99,
540 0xff,
541 0xcc,
542 0x33,
543 0x66,
544 0xff,
545 0xcc,
546 0x33,
547 0x33,
548 0xff,
549 0xcc,
550 0x33,
551 0x00,
552 0xff,
553 0xcc,
554 0x00,
555 0xff,
556 0xff,
557 0xcc,
558 0x00,
559 0xcc,
560 0xff,
561 0xcc,
562 0x00,
563 0x99,
564 0xff,
565 0xcc,
566 0x00,
567 0x66,
568 0xff,
569 0xcc,
570 0x00,
571 0x33,
572 0xff,
573 0xcc,
574 0x00,
575 0x00,
576 0xff,
577 0x99,
578 0xff,
579 0xff,
580 0xff,
581 0x99,
582 0xff,
583 0xcc,
584 0xff,
585 0x99,
586 0xff,
587 0x99,
588 0xff,
589 0x99,
590 0xff,
591 0x66,
592 0xff,
593 0x99,
594 0xff,
595 0x33,
596 0xff,
597 0x99,
598 0xff,
599 0x00,
600 0xff,
601 0x99,
602 0xcc,
603 0xff,
604 0xff,
605 0x99,
606 0xcc,
607 0xcc,
608 0xff,
609 0x99,
610 0xcc,
611 0x99,
612 0xff,
613 0x99,
614 0xcc,
615 0x66,
616 0xff,
617 0x99,
618 0xcc,
619 0x33,
620 0xff,
621 0x99,
622 0xcc,
623 0x00,
624 0xff,
625 0x99,
626 0x99,
627 0xff,
628 0xff,
629 0x99,
630 0x99,
631 0xcc,
632 0xff,
633 0x99,
634 0x99,
635 0x99,
636 0xff,
637 0x99,
638 0x99,
639 0x66,
640 0xff,
641 0x99,
642 0x99,
643 0x33,
644 0xff,
645 0x99,
646 0x99,
647 0x00,
648 0xff,
649 0x99,
650 0x66,
651 0xff,
652 0xff,
653 0x99,
654 0x66,
655 0xcc,
656 0xff,
657 0x99,
658 0x66,
659 0x99,
660 0xff,
661 0x99,
662 0x66,
663 0x66,
664 0xff,
665 0x99,
666 0x66,
667 0x33,
668 0xff,
669 0x99,
670 0x66,
671 0x00,
672 0xff,
673 0x99,
674 0x33,
675 0xff,
676 0xff,
677 0x99,
678 0x33,
679 0xcc,
680 0xff,
681 0x99,
682 0x33,
683 0x99,
684 0xff,
685 0x99,
686 0x33,
687 0x66,
688 0xff,
689 0x99,
690 0x33,
691 0x33,
692 0xff,
693 0x99,
694 0x33,
695 0x00,
696 0xff,
697 0x99,
698 0x00,
699 0xff,
700 0xff,
701 0x99,
702 0x00,
703 0xcc,
704 0xff,
705 0x99,
706 0x00,
707 0x99,
708 0xff,
709 0x99,
710 0x00,
711 0x66,
712 0xff,
713 0x99,
714 0x00,
715 0x33,
716 0xff,
717 0x99,
718 0x00,
719 0x00,
720 0xff,
721 0x66,
722 0xff,
723 0xff,
724 0xff,
725 0x66,
726 0xff,
727 0xcc,
728 0xff,
729 0x66,
730 0xff,
731 0x99,
732 0xff,
733 0x66,
734 0xff,
735 0x66,
736 0xff,
737 0x66,
738 0xff,
739 0x33,
740 0xff,
741 0x66,
742 0xff,
743 0x00,
744 0xff,
745 0x66,
746 0xcc,
747 0xff,
748 0xff,
749 0x66,
750 0xcc,
751 0xcc,
752 0xff,
753 0x66,
754 0xcc,
755 0x99,
756 0xff,
757 0x66,
758 0xcc,
759 0x66,
760 0xff,
761 0x66,
762 0xcc,
763 0x33,
764 0xff,
765 0x66,
766 0xcc,
767 0x00,
768 0xff,
769 0x66,
770 0x99,
771 0xff,
772 0xff,
773 0x66,
774 0x99,
775 0xcc,
776 0xff,
777 0x66,
778 0x99,
779 0x99,
780 0xff,
781 0x66,
782 0x99,
783 0x66,
784 0xff,
785 0x66,
786 0x99,
787 0x33,
788 0xff,
789 0x66,
790 0x99,
791 0x00,
792 0xff,
793 0x66,
794 0x66,
795 0xff,
796 0xff,
797 0x66,
798 0x66,
799 0xcc,
800 0xff,
801 0x66,
802 0x66,
803 0x99,
804 0xff,
805 0x66,
806 0x66,
807 0x66,
808 0xff,
809 0x66,
810 0x66,
811 0x33,
812 0xff,
813 0x66,
814 0x66,
815 0x00,
816 0xff,
817 0x66,
818 0x33,
819 0xff,
820 0xff,
821 0x66,
822 0x33,
823 0xcc,
824 0xff,
825 0x66,
826 0x33,
827 0x99,
828 0xff,
829 0x66,
830 0x33,
831 0x66,
832 0xff,
833 0x66,
834 0x33,
835 0x33,
836 0xff,
837 0x66,
838 0x33,
839 0x00,
840 0xff,
841 0x66,
842 0x00,
843 0xff,
844 0xff,
845 0x66,
846 0x00,
847 0xcc,
848 0xff,
849 0x66,
850 0x00,
851 0x99,
852 0xff,
853 0x66,
854 0x00,
855 0x66,
856 0xff,
857 0x66,
858 0x00,
859 0x33,
860 0xff,
861 0x66,
862 0x00,
863 0x00,
864 0xff,
865 0x33,
866 0xff,
867 0xff,
868 0xff,
869 0x33,
870 0xff,
871 0xcc,
872 0xff,
873 0x33,
874 0xff,
875 0x99,
876 0xff,
877 0x33,
878 0xff,
879 0x66,
880 0xff,
881 0x33,
882 0xff,
883 0x33,
884 0xff,
885 0x33,
886 0xff,
887 0x00,
888 0xff,
889 0x33,
890 0xcc,
891 0xff,
892 0xff,
893 0x33,
894 0xcc,
895 0xcc,
896 0xff,
897 0x33,
898 0xcc,
899 0x99,
900 0xff,
901 0x33,
902 0xcc,
903 0x66,
904 0xff,
905 0x33,
906 0xcc,
907 0x33,
908 0xff,
909 0x33,
910 0xcc,
911 0x00,
912 0xff,
913 0x33,
914 0x99,
915 0xff,
916 0xff,
917 0x33,
918 0x99,
919 0xcc,
920 0xff,
921 0x33,
922 0x99,
923 0x99,
924 0xff,
925 0x33,
926 0x99,
927 0x66,
928 0xff,
929 0x33,
930 0x99,
931 0x33,
932 0xff,
933 0x33,
934 0x99,
935 0x00,
936 0xff,
937 0x33,
938 0x66,
939 0xff,
940 0xff,
941 0x33,
942 0x66,
943 0xcc,
944 0xff,
945 0x33,
946 0x66,
947 0x99,
948 0xff,
949 0x33,
950 0x66,
951 0x66,
952 0xff,
953 0x33,
954 0x66,
955 0x33,
956 0xff,
957 0x33,
958 0x66,
959 0x00,
960 0xff,
961 0x33,
962 0x33,
963 0xff,
964 0xff,
965 0x33,
966 0x33,
967 0xcc,
968 0xff,
969 0x33,
970 0x33,
971 0x99,
972 0xff,
973 0x33,
974 0x33,
975 0x66,
976 0xff,
977 0x33,
978 0x33,
979 0x33,
980 0xff,
981 0x33,
982 0x33,
983 0x00,
984 0xff,
985 0x33,
986 0x00,
987 0xff,
988 0xff,
989 0x33,
990 0x00,
991 0xcc,
992 0xff,
993 0x33,
994 0x00,
995 0x99,
996 0xff,
997 0x33,
998 0x00,
999 0x66,
1000 0xff,
1001 0x33,
1002 0x00,
1003 0x33,
1004 0xff,
1005 0x33,
1006 0x00,
1007 0x00,
1008 0xff,
1009 0x00,
1010 0xff,
1011 0xff,
1012 0xff,
1013 0x00,
1014 0xff,
1015 0xcc,
1016 0xff,
1017 0x00,
1018 0xff,
1019 0x99,
1020 0xff,
1021 0x00,
1022 0xff,
1023 0x66,
1024 0xff,
1025 0x00,
1026 0xff,
1027 0x33,
1028 0xff,
1029 0x00,
1030 0xff,
1031 0x00,
1032 0xff,
1033 0x00,
1034 0xcc,
1035 0xff,
1036 0xff,
1037 0x00,
1038 0xcc,
1039 0xcc,
1040 0xff,
1041 0x00,
1042 0xcc,
1043 0x99,
1044 0xff,
1045 0x00,
1046 0xcc,
1047 0x66,
1048 0xff,
1049 0x00,
1050 0xcc,
1051 0x33,
1052 0xff,
1053 0x00,
1054 0xcc,
1055 0x00,
1056 0xff,
1057 0x00,
1058 0x99,
1059 0xff,
1060 0xff,
1061 0x00,
1062 0x99,
1063 0xcc,
1064 0xff,
1065 0x00,
1066 0x99,
1067 0x99,
1068 0xff,
1069 0x00,
1070 0x99,
1071 0x66,
1072 0xff,
1073 0x00,
1074 0x99,
1075 0x33,
1076 0xff,
1077 0x00,
1078 0x99,
1079 0x00,
1080 0xff,
1081 0x00,
1082 0x66,
1083 0xff,
1084 0xff,
1085 0x00,
1086 0x66,
1087 0xcc,
1088 0xff,
1089 0x00,
1090 0x66,
1091 0x99,
1092 0xff,
1093 0x00,
1094 0x66,
1095 0x66,
1096 0xff,
1097 0x00,
1098 0x66,
1099 0x33,
1100 0xff,
1101 0x00,
1102 0x66,
1103 0x00,
1104 0xff,
1105 0x00,
1106 0x33,
1107 0xff,
1108 0xff,
1109 0x00,
1110 0x33,
1111 0xcc,
1112 0xff,
1113 0x00,
1114 0x33,
1115 0x99,
1116 0xff,
1117 0x00,
1118 0x33,
1119 0x66,
1120 0xff,
1121 0x00,
1122 0x33,
1123 0x33,
1124 0xff,
1125 0x00,
1126 0x33,
1127 0x00,
1128 0xff,
1129 0x00,
1130 0x00,
1131 0xff,
1132 0xff,
1133 0x00,
1134 0x00,
1135 0xcc,
1136 0xff,
1137 0x00,
1138 0x00,
1139 0x99,
1140 0xff,
1141 0x00,
1142 0x00,
1143 0x66,
1144 0xff,
1145 0x00,
1146 0x00,
1147 0x33,
1148 0xff,
1149 0xee,
1150 0x00,
1151 0x00,
1152 0xff,
1153 0xdd,
1154 0x00,
1155 0x00,
1156 0xff,
1157 0xbb,
1158 0x00,
1159 0x00,
1160 0xff,
1161 0xaa,
1162 0x00,
1163 0x00,
1164 0xff,
1165 0x88,
1166 0x00,
1167 0x00,
1168 0xff,
1169 0x77,
1170 0x00,
1171 0x00,
1172 0xff,
1173 0x55,
1174 0x00,
1175 0x00,
1176 0xff,
1177 0x44,
1178 0x00,
1179 0x00,
1180 0xff,
1181 0x22,
1182 0x00,
1183 0x00,
1184 0xff,
1185 0x11,
1186 0x00,
1187 0x00,
1188 0xff,
1189 0x00,
1190 0xee,
1191 0x00,
1192 0xff,
1193 0x00,
1194 0xdd,
1195 0x00,
1196 0xff,
1197 0x00,
1198 0xbb,
1199 0x00,
1200 0xff,
1201 0x00,
1202 0xaa,
1203 0x00,
1204 0xff,
1205 0x00,
1206 0x88,
1207 0x00,
1208 0xff,
1209 0x00,
1210 0x77,
1211 0x00,
1212 0xff,
1213 0x00,
1214 0x55,
1215 0x00,
1216 0xff,
1217 0x00,
1218 0x44,
1219 0x00,
1220 0xff,
1221 0x00,
1222 0x22,
1223 0x00,
1224 0xff,
1225 0x00,
1226 0x11,
1227 0x00,
1228 0xff,
1229 0x00,
1230 0x00,
1231 0xee,
1232 0xff,
1233 0x00,
1234 0x00,
1235 0xdd,
1236 0xff,
1237 0x00,
1238 0x00,
1239 0xbb,
1240 0xff,
1241 0x00,
1242 0x00,
1243 0xaa,
1244 0xff,
1245 0x00,
1246 0x00,
1247 0x88,
1248 0xff,
1249 0x00,
1250 0x00,
1251 0x77,
1252 0xff,
1253 0x00,
1254 0x00,
1255 0x55,
1256 0xff,
1257 0x00,
1258 0x00,
1259 0x44,
1260 0xff,
1261 0x00,
1262 0x00,
1263 0x22,
1264 0xff,
1265 0x00,
1266 0x00,
1267 0x11,
1268 0xff,
1269 0xee,
1270 0xee,
1271 0xee,
1272 0xff,
1273 0xdd,
1274 0xdd,
1275 0xdd,
1276 0xff,
1277 0xbb,
1278 0xbb,
1279 0xbb,
1280 0xff,
1281 0xaa,
1282 0xaa,
1283 0xaa,
1284 0xff,
1285 0x88,
1286 0x88,
1287 0x88,
1288 0xff,
1289 0x77,
1290 0x77,
1291 0x77,
1292 0xff,
1293 0x55,
1294 0x55,
1295 0x55,
1296 0xff,
1297 0x44,
1298 0x44,
1299 0x44,
1300 0xff,
1301 0x22,
1302 0x22,
1303 0x22,
1304 0xff,
1305 0x11,
1306 0x11,
1307 0x11,
1308 0xff,
1309 0x00,
1310 0x00,
1311 0x00,
1312 0xff,
1313};
1314
1315// internal math/helper utilities
1316static inline uint32_t _vox_max(uint32_t a, uint32_t b)
1317{
1318 return (a > b) ? a : b;
1319}
1320static inline uint32_t _vox_min(uint32_t a, uint32_t b)
1321{
1322 return (a < b) ? a : b;
1323}
1324
1325// string utilities
1326# ifdef _MSC_VER
1327# define _vox_str_scanf(str, ...) sscanf_s(str, __VA_ARGS__)
1328# define _vox_strcpy_static(dst, src) strcpy_s(dst, src)
1329# define _vox_strcasecmp(a, b) _stricmp(a, b)
1330# define _vox_strcmp(a, b) strcmp(a, b)
1331# define _vox_strlen(a) strlen(a)
1332# define _vox_sprintf(str, str_max, fmt, ...) sprintf_s(str, str_max, fmt, __VA_ARGS__)
1333# else
1334# define _vox_str_scanf(str, ...) sscanf(str, __VA_ARGS__)
1335# define _vox_strcpy_static(dst, src) strcpy(dst, src)
1336# define _vox_strcasecmp(a, b) strcasecmp(a, b)
1337# define _vox_strcmp(a, b) strcmp(a, b)
1338# define _vox_strlen(a) strlen(a)
1339# define _vox_sprintf(str, str_max, fmt, ...) snprintf(str, str_max, fmt, __VA_ARGS__)
1340# endif
1341
1342// 3d vector utilities
1343struct vec3
1344{
1345 float x, y, z;
1346};
1347static inline vec3 vec3_make(float x, float y, float z)
1348{
1349 vec3 v;
1350 v.x = x;
1351 v.y = y;
1352 v.z = z;
1353 return v;
1354}
1355static inline vec3 vec3_negate(const vec3& v)
1356{
1357 vec3 r;
1358 r.x = -v.x;
1359 r.y = -v.y;
1360 r.z = -v.z;
1361 return r;
1362}
1363
1364// API for emulating file transactions on an in-memory buffer of data.
1365struct _vox_file
1366{
1367 const uint8_t* buffer; // source buffer data
1368 const uint32_t buffer_size; // size of the data in the buffer
1369 uint32_t offset; // current offset in the buffer data.
1370};
1371
1372static bool _vox_file_read(_vox_file* pFp, void* pData, uint32_t data_size)
1373{
1374 size_t data_to_read = _vox_min(pFp->buffer_size - pFp->offset, data_size);
1375 memcpy(pData, &pFp->buffer[pFp->offset], data_to_read);
1376 pFp->offset += data_size;
1377 return data_to_read == data_size;
1378}
1379
1380static void _vox_file_seek_forwards(_vox_file* pFp, uint32_t offset)
1381{
1382 pFp->offset += offset;
1383}
1384
1385static bool _vox_file_eof(const _vox_file* pFp)
1386{
1387 return pFp->offset >= pFp->buffer_size;
1388}
1389
1390static const void* _vox_file_data_pointer(const _vox_file* pFp)
1391{
1392 return &pFp->buffer[pFp->offset];
1393}
1394
1395// hash utilities
1396static uint32_t _vox_hash(const uint8_t* pData, uint32_t data_size)
1397{
1398 uint32_t hash = 0;
1399 for (uint32_t i = 0; i < data_size; i++)
1400 hash = pData[i] + (hash * 65559);
1401 return hash;
1402}
1403
1404// memory allocation utils.
1405static void* _ogt_priv_alloc_default(size_t uiSize)
1406{
1407 return malloc(uiSize);
1408}
1409static void _ogt_priv_free_default(void* pPtr)
1410{
1411 free(pPtr);
1412}
1413static ogt_vox_alloc_func g_alloc_func = _ogt_priv_alloc_default; // default function for allocating
1414static ogt_vox_free_func g_free_func = _ogt_priv_free_default; // default function for freeing.
1415
1416// set the provided allocate/free functions if they are non-null, otherwise reset to default allocate/free functions
1417void ogt_vox_set_memory_allocator(ogt_vox_alloc_func alloc_func, ogt_vox_free_func free_func)
1418{
1419 assert((alloc_func && free_func) || // both alloc/free must be non-NULL -OR-
1420 (!alloc_func && !free_func)); // both alloc/free must be NULL. No mixing 'n matching.
1421 if (alloc_func && free_func)
1422 {
1423 g_alloc_func = alloc_func;
1424 g_free_func = free_func;
1425 }
1426 else
1427 {
1428 // reset to default allocate/free functions.
1429 g_alloc_func = _ogt_priv_alloc_default;
1430 g_free_func = _ogt_priv_free_default;
1431 }
1432}
1433
1434static void* _vox_malloc(size_t uiSize)
1435{
1436 return uiSize ? g_alloc_func(uiSize) : NULL;
1437}
1438
1439static void* _vox_calloc(size_t uiSize)
1440{
1441 void* pMem = _vox_malloc(uiSize);
1442 if (pMem)
1443 memset(pMem, 0, uiSize);
1444 return pMem;
1445}
1446
1447static void _vox_free(void* pOld_ptr)
1448{
1449 if (pOld_ptr)
1450 g_free_func(pOld_ptr);
1451}
1452
1453static void* _vox_realloc(void* pOld_ptr, size_t uiOld_size, size_t uiNew_size)
1454{
1455 // early out if new size is non-zero and no resize is required.
1456 if (uiNew_size && uiOld_size >= uiNew_size)
1457 return pOld_ptr;
1458
1459 // memcpy from the old ptr only if both sides are valid.
1460 void* new_ptr = _vox_malloc(uiNew_size);
1461 if (new_ptr)
1462 {
1463 // copy any existing elements over
1464 if (pOld_ptr && uiOld_size)
1465 memcpy(new_ptr, pOld_ptr, uiOld_size);
1466 // zero out any new tail elements
1467 assert(uiNew_size > uiOld_size); // this should be guaranteed by the _vox_realloc early out case above.
1468 uintptr_t new_tail_ptr = (uintptr_t)new_ptr + uiOld_size;
1469 memset((void*)new_tail_ptr, 0, uiNew_size - uiOld_size);
1470 }
1471 if (pOld_ptr)
1472 _vox_free(pOld_ptr);
1473 return new_ptr;
1474}
1475
1476// std::vector-style allocator, which use client-provided allocation functions.
1477template <class T>
1478struct _vox_array
1479{
1480 _vox_array() :
1481 data(NULL), capacity(0), count(0)
1482 {
1483 }
1484 ~_vox_array()
1485 {
1486 _vox_free(data);
1487 data = NULL;
1488 count = 0;
1489 capacity = 0;
1490 }
1491 void reserve(size_t uiNew_capacity)
1492 {
1493 data = (T*)_vox_realloc(data, capacity * sizeof(T), uiNew_capacity * sizeof(T));
1494 capacity = uiNew_capacity;
1495 }
1496 void grow_to_fit_index(size_t uiIndex)
1497 {
1498 if (uiIndex >= count)
1499 resize(uiIndex + 1);
1500 }
1501 void resize(size_t uiNew_count)
1502 {
1503 if (uiNew_count > capacity)
1504 reserve(uiNew_count);
1505 count = uiNew_count;
1506 }
1507 void push_back(const T& new_element)
1508 {
1509 if (count == capacity)
1510 {
1511 size_t new_capacity = capacity ? (capacity * 3) >> 1 : 2; // grow by 50% each time, otherwise start at 2 elements.
1512 reserve(new_capacity);
1513 assert(capacity > count);
1514 }
1515 data[count++] = new_element;
1516 }
1517 void push_back_many(const T* pNew_elements, size_t uiNum_elements)
1518 {
1519 if (count + uiNum_elements > capacity)
1520 {
1521 size_t new_capacity = capacity + uiNum_elements;
1522 new_capacity = new_capacity ? (new_capacity * 3) >> 1 : 2; // grow by 50% each time, otherwise start at 2 elements.
1523 reserve(new_capacity);
1524 assert(capacity >= (count + uiNum_elements));
1525 }
1526 for (size_t i = 0; i < uiNum_elements; i++)
1527 data[count + i] = pNew_elements[i];
1528 count += uiNum_elements;
1529 }
1530 size_t size() const
1531 {
1532 return count;
1533 }
1534 T& operator[](size_t uiIndex)
1535 {
1536 assert(uiIndex < count);
1537 return data[uiIndex];
1538 }
1539 const T& operator[](size_t uiIndex) const
1540 {
1541 assert(uiIndex < count);
1542 return data[uiIndex];
1543 }
1544 T* data; // data for the array
1545 size_t capacity; // capacity of the array
1546 size_t count; // size of the array
1547};
1548
1549// matrix utilities
1550static ogt_vox_transform _vox_transform_identity()
1551{
1553 t.m00 = 1.0f;
1554 t.m01 = 0.0f;
1555 t.m02 = 0.0f;
1556 t.m03 = 0.0f;
1557 t.m10 = 0.0f;
1558 t.m11 = 1.0f;
1559 t.m12 = 0.0f;
1560 t.m13 = 0.0f;
1561 t.m20 = 0.0f;
1562 t.m21 = 0.0f;
1563 t.m22 = 1.0f;
1564 t.m23 = 0.0f;
1565 t.m30 = 0.0f;
1566 t.m31 = 0.0f;
1567 t.m32 = 0.0f;
1568 t.m33 = 1.0f;
1569 return t;
1570}
1571
1572static ogt_vox_transform _vox_transform_multiply(const ogt_vox_transform& a, const ogt_vox_transform& b)
1573{
1575 r.m00 = (a.m00 * b.m00) + (a.m01 * b.m10) + (a.m02 * b.m20) + (a.m03 * b.m30);
1576 r.m01 = (a.m00 * b.m01) + (a.m01 * b.m11) + (a.m02 * b.m21) + (a.m03 * b.m31);
1577 r.m02 = (a.m00 * b.m02) + (a.m01 * b.m12) + (a.m02 * b.m22) + (a.m03 * b.m32);
1578 r.m03 = (a.m00 * b.m03) + (a.m01 * b.m13) + (a.m02 * b.m23) + (a.m03 * b.m33);
1579 r.m10 = (a.m10 * b.m00) + (a.m11 * b.m10) + (a.m12 * b.m20) + (a.m13 * b.m30);
1580 r.m11 = (a.m10 * b.m01) + (a.m11 * b.m11) + (a.m12 * b.m21) + (a.m13 * b.m31);
1581 r.m12 = (a.m10 * b.m02) + (a.m11 * b.m12) + (a.m12 * b.m22) + (a.m13 * b.m32);
1582 r.m13 = (a.m10 * b.m03) + (a.m11 * b.m13) + (a.m12 * b.m23) + (a.m13 * b.m33);
1583 r.m20 = (a.m20 * b.m00) + (a.m21 * b.m10) + (a.m22 * b.m20) + (a.m23 * b.m30);
1584 r.m21 = (a.m20 * b.m01) + (a.m21 * b.m11) + (a.m22 * b.m21) + (a.m23 * b.m31);
1585 r.m22 = (a.m20 * b.m02) + (a.m21 * b.m12) + (a.m22 * b.m22) + (a.m23 * b.m32);
1586 r.m23 = (a.m20 * b.m03) + (a.m21 * b.m13) + (a.m22 * b.m23) + (a.m23 * b.m33);
1587 r.m30 = (a.m30 * b.m00) + (a.m31 * b.m10) + (a.m32 * b.m20) + (a.m33 * b.m30);
1588 r.m31 = (a.m30 * b.m01) + (a.m31 * b.m11) + (a.m32 * b.m21) + (a.m33 * b.m31);
1589 r.m32 = (a.m30 * b.m02) + (a.m31 * b.m12) + (a.m32 * b.m22) + (a.m33 * b.m32);
1590 r.m33 = (a.m30 * b.m03) + (a.m31 * b.m13) + (a.m32 * b.m23) + (a.m33 * b.m33);
1591 return r;
1592}
1593
1594// dictionary utilities
1595static const uint32_t k_vox_max_dict_buffer_size = 4096;
1596static const uint32_t k_vox_max_dict_key_value_pairs = 256;
1597struct _vox_dictionary
1598{
1599 const char* keys[k_vox_max_dict_key_value_pairs];
1600 const char* values[k_vox_max_dict_key_value_pairs];
1601 uint32_t num_key_value_pairs;
1602 char buffer[k_vox_max_dict_buffer_size + 4]; // max 4096, +4 for safety
1603 uint32_t buffer_mem_used;
1604};
1605
1606static bool _vox_file_read_dict(_vox_dictionary* pDict, _vox_file* pFp)
1607{
1608 uint32_t num_pairs_to_read = 0;
1609 _vox_file_read(pFp, &num_pairs_to_read, sizeof(uint32_t));
1610 assert(num_pairs_to_read <= k_vox_max_dict_key_value_pairs);
1611
1612 pDict->buffer_mem_used = 0;
1613 pDict->num_key_value_pairs = 0;
1614 for (uint32_t i = 0; i < num_pairs_to_read; i++)
1615 {
1616 // get the size of the key string
1617 uint32_t key_string_size = 0;
1618 _vox_file_read(pFp, &key_string_size, sizeof(uint32_t));
1619 // allocate space for the key, and read it in.
1620 if (pDict->buffer_mem_used + key_string_size > k_vox_max_dict_buffer_size)
1621 return false;
1622 char* key = &pDict->buffer[pDict->buffer_mem_used];
1623 pDict->buffer_mem_used += key_string_size + 1; // + 1 for zero terminator
1624 _vox_file_read(pFp, key, key_string_size);
1625 key[key_string_size] = 0; // zero-terminate
1626 assert(_vox_strlen(key) == key_string_size); // sanity check
1627
1628 // get the size of the value string
1629 uint32_t value_string_size = 0;
1630 _vox_file_read(pFp, &value_string_size, sizeof(uint32_t));
1631 // allocate space for the value, and read it in.
1632 if (pDict->buffer_mem_used + value_string_size > k_vox_max_dict_buffer_size)
1633 return (false);
1634 char* value = &pDict->buffer[pDict->buffer_mem_used];
1635 pDict->buffer_mem_used += value_string_size + 1; // + 1 for zero terminator
1636 _vox_file_read(pFp, value, value_string_size);
1637 value[value_string_size] = 0; // zero-terminate
1638 assert(_vox_strlen(value) == value_string_size); // sanity check
1639 // now assign it in the dictionary
1640 pDict->keys[pDict->num_key_value_pairs] = key;
1641 pDict->values[pDict->num_key_value_pairs] = value;
1642 pDict->num_key_value_pairs++;
1643 }
1644
1645 return true;
1646}
1647
1648// helper for looking up in the dictionary
1649static const char* _vox_dict_get_value_as_string(const _vox_dictionary* pDict, const char* szKey_to_find, const char* szDefault_value = NULL)
1650{
1651 for (uint32_t i = 0; i < pDict->num_key_value_pairs; i++)
1652 if (_vox_strcasecmp(pDict->keys[i], szKey_to_find) == 0)
1653 return pDict->values[i];
1654 return szDefault_value;
1655}
1656
1657// lookup table for _vox_make_transform_from_dict_strings
1658static const vec3 k_vectors[4] = {
1659 vec3_make(1.0f, 0.0f, 0.0f),
1660 vec3_make(0.0f, 1.0f, 0.0f),
1661 vec3_make(0.0f, 0.0f, 1.0f),
1662 vec3_make(0.0f, 0.0f, 0.0f) // invalid!
1663};
1664
1665// lookup table for _vox_make_transform_from_dict_strings
1666static const uint32_t k_row2_index[] = {UINT32_MAX, UINT32_MAX, UINT32_MAX, 2, UINT32_MAX, 1, 0, UINT32_MAX};
1667
1668
1669static ogt_vox_transform _vox_make_transform_from_dict_strings(const char* szRotation_string, const char* szTranslation_string)
1670{
1671 ogt_vox_transform transform = _vox_transform_identity();
1672
1673 if (szRotation_string != NULL)
1674 {
1675 // compute the per-row indexes into k_vectors[] array.
1676 // unpack rotation bits.
1677 // bits : meaning
1678 // 0 - 1 : index of the non-zero entry in the first row
1679 // 2 - 3 : index of the non-zero entry in the second row
1680 uint32_t packed_rotation_bits = atoi(szRotation_string);
1681 uint32_t row0_vec_index = (packed_rotation_bits >> 0) & 3;
1682 uint32_t row1_vec_index = (packed_rotation_bits >> 2) & 3;
1683 uint32_t row2_vec_index = k_row2_index[(1 << row0_vec_index) | (1 << row1_vec_index)]; // process of elimination to determine row 2 index based on row0/row1 being one of {0,1,2} choose 2.
1684 assert(row2_vec_index != UINT32_MAX); // if you hit this, you probably have invalid indices for row0_vec_index/row1_vec_index.
1685
1686 // unpack rotation bits for vector signs
1687 // bits : meaning
1688 // 4 : the sign in the first row (0 : positive; 1 : negative)
1689 // 5 : the sign in the second row (0 : positive; 1 : negative)
1690 // 6 : the sign in the third row (0 : positive; 1 : negative)
1691 vec3 row0 = k_vectors[row0_vec_index];
1692 vec3 row1 = k_vectors[row1_vec_index];
1693 vec3 row2 = k_vectors[row2_vec_index];
1694 if (packed_rotation_bits & (1 << 4))
1695 row0 = vec3_negate(row0);
1696 if (packed_rotation_bits & (1 << 5))
1697 row1 = vec3_negate(row1);
1698 if (packed_rotation_bits & (1 << 6))
1699 row2 = vec3_negate(row2);
1700
1701 // magicavoxel stores rows, we need columns, so we do the swizzle here into columns
1702 transform.m00 = row0.x;
1703 transform.m01 = row1.x;
1704 transform.m02 = row2.x;
1705 transform.m10 = row0.y;
1706 transform.m11 = row1.y;
1707 transform.m12 = row2.y;
1708 transform.m20 = row0.z;
1709 transform.m21 = row1.z;
1710 transform.m22 = row2.z;
1711 }
1712
1713 if (szTranslation_string != NULL)
1714 {
1715 int32_t x = 0;
1716 int32_t y = 0;
1717 int32_t z = 0;
1718 _vox_str_scanf(szTranslation_string, "%i %i %i", &x, &y, &z);
1719 transform.m30 = (float)x;
1720 transform.m31 = (float)y;
1721 transform.m32 = (float)z;
1722 }
1723 return transform;
1724}
1725
1726enum _vox_scene_node_type
1727{
1728 k_nodetype_invalid = 0, // has not been parsed yet.
1729 k_nodetype_group = 1,
1730 k_nodetype_transform = 2,
1731 k_nodetype_shape = 3,
1732};
1733
1734struct _vox_scene_node_
1735{
1736 _vox_scene_node_type node_type; // only gets assigned when this has been parsed, otherwise will be k_nodetype_invalid
1737 union
1738 {
1739 // used only when node_type == k_nodetype_transform
1740 struct
1741 {
1742 char name[64]; // max name size is 64
1743 ogt_vox_transform transform;
1744 uint32_t child_node_id;
1745 uint32_t layer_id;
1746 bool hidden;
1747 } transform;
1748 // used only when node_type == k_nodetype_group
1749 struct
1750 {
1751 uint32_t first_child_node_id_index; // the index of the first child node ID within the ChildNodeID array
1752 uint32_t num_child_nodes; // number of child node IDs starting at the first index
1753 } group;
1754 // used only when node_type == k_nodetype_shape
1755 struct
1756 {
1757 uint32_t model_id; // will be UINT32_MAX if there is no model. Unlikely, there should always be a model.
1758 } shape;
1759 } u;
1760};
1761
1762static void generate_instances_for_node(
1763 const _vox_array<_vox_scene_node_>& nodes, uint32_t node_index, const _vox_array<uint32_t>& child_id_array, uint32_t layer_index,
1764 const ogt_vox_transform& transform, const _vox_array<ogt_vox_model*>& model_ptrs, const char* szTransform_last_name, bool bTransform_last_hidden,
1765 _vox_array<ogt_vox_instance>& ref_instances, _vox_array<char>& ref_string_data, _vox_array<ogt_vox_group>& ref_groups, uint32_t group_index, bool bGenerate_groups)
1766{
1767 const _vox_scene_node_* node = &nodes[node_index];
1768 assert(node);
1769 switch (node->node_type)
1770 {
1771 case k_nodetype_transform:
1772 {
1773 ogt_vox_transform new_transform = (bGenerate_groups) ? node->u.transform.transform // don't multiply by the parent transform. caller wants the group-relative transform
1774 :
1775 _vox_transform_multiply(node->u.transform.transform, transform); // flatten the transform if we're not generating groups: child transform * parent transform
1776 const char* new_transform_name = node->u.transform.name[0] ? node->u.transform.name : NULL;
1777 szTransform_last_name = new_transform_name ? new_transform_name : szTransform_last_name; // if this node has a name, use it instead of our parent name
1778 generate_instances_for_node(nodes, node->u.transform.child_node_id, child_id_array, node->u.transform.layer_id, new_transform, model_ptrs, szTransform_last_name, node->u.transform.hidden, ref_instances, ref_string_data, ref_groups, group_index, bGenerate_groups);
1779 break;
1780 }
1781 case k_nodetype_group:
1782 {
1783 // create a new group only if we're generating groups.
1784 uint32_t next_group_index = 0;
1785 if (bGenerate_groups)
1786 {
1787 next_group_index = (uint32_t)ref_groups.size();
1788 ogt_vox_group group;
1789 group.parent_group_index = group_index;
1790 group.transform = transform;
1791 group.hidden = bTransform_last_hidden;
1792 group.layer_index = layer_index;
1793 ref_groups.push_back(group);
1794 }
1795 // child nodes will only be hidden if their immediate transform is hidden.
1796 bTransform_last_hidden = false;
1797
1798 const uint32_t* child_node_ids = (const uint32_t*)&child_id_array[node->u.group.first_child_node_id_index];
1799 for (uint32_t i = 0; i < node->u.group.num_child_nodes; i++)
1800 {
1801 generate_instances_for_node(nodes, child_node_ids[i], child_id_array, layer_index, transform, model_ptrs, szTransform_last_name, bTransform_last_hidden, ref_instances, ref_string_data, ref_groups, next_group_index, bGenerate_groups);
1802 }
1803 break;
1804 }
1805 case k_nodetype_shape:
1806 {
1807 assert(node->u.shape.model_id < model_ptrs.size());
1808 if (node->u.shape.model_id < model_ptrs.size() && // model ID is valid
1809 model_ptrs[node->u.shape.model_id] != NULL) // model is non-NULL.
1810 {
1811 assert(bGenerate_groups || group_index == 0); // if we're not generating groups, group_index should be zero to map to the root group.
1812 ogt_vox_instance new_instance;
1813 new_instance.model_index = node->u.shape.model_id;
1814 new_instance.transform = transform;
1815 new_instance.layer_index = layer_index;
1816 new_instance.group_index = group_index;
1817 new_instance.hidden = bTransform_last_hidden;
1818 // if we got a transform name, allocate space in string_data for it and keep track of the index
1819 // within string data. This will be patched to a real pointer at the very end.
1820 new_instance.name = 0;
1821 if (szTransform_last_name && szTransform_last_name[0])
1822 {
1823 new_instance.name = (const char*)(ref_string_data.size());
1824 size_t name_size = _vox_strlen(szTransform_last_name) + 1; // +1 for terminator
1825 ref_string_data.push_back_many(szTransform_last_name, name_size);
1826 }
1827 // create the instance
1828 ref_instances.push_back(new_instance);
1829 }
1830 break;
1831 }
1832 default:
1833 {
1834 assert(0); // unhandled node type!
1835 }
1836 }
1837}
1838
1839// ensure instances are ordered in order of increasing model_index
1840static int _vox_ordered_compare_instance(const void* p_lhs, const void* p_rhs)
1841{
1842 const ogt_vox_instance* lhs = (const ogt_vox_instance*)p_lhs;
1843 const ogt_vox_instance* rhs = (const ogt_vox_instance*)p_rhs;
1844 return lhs->model_index < rhs->model_index ? -1 : lhs->model_index > rhs->model_index ? 1 :
1845 0;
1846}
1847
1848// returns true if the 2 models are content-wise identical.
1849static bool _vox_models_are_equal(const ogt_vox_model* lhs, const ogt_vox_model* rhs)
1850{
1851 // early out: if hashes don't match, they can't be equal
1852 // if hashes match, they might be equal OR there might be a hash collision.
1853 if (lhs->voxel_hash != rhs->voxel_hash)
1854 return false;
1855 // early out: if number of voxels in the model's grid don't match, they can't be equal.
1856 uint32_t num_voxels_lhs = lhs->size_x * lhs->size_y * lhs->size_z;
1857 uint32_t num_voxels_rhs = rhs->size_x * rhs->size_y * rhs->size_z;
1858 if (num_voxels_lhs != num_voxels_rhs)
1859 return false;
1860 // Finally, we know their hashes are the same, and their dimensions are the same
1861 // but they are only equal if they have exactly the same voxel data.
1862 return memcmp(lhs->voxel_data, rhs->voxel_data, num_voxels_lhs) == 0 ? true : false;
1863}
1864
1865const ogt_vox_scene* ogt_vox_read_scene_with_flags(const uint8_t* pBuffer, uint32_t buffer_size, uint32_t read_flags)
1866{
1867 _vox_file file = {pBuffer, buffer_size, 0};
1868 _vox_file* fp = &file;
1869
1870 // parsing state/context
1871 _vox_array<ogt_vox_model*> model_ptrs;
1872 _vox_array<_vox_scene_node_> nodes;
1873 _vox_array<ogt_vox_instance> instances;
1874 _vox_array<char> string_data;
1875 _vox_array<ogt_vox_layer> layers;
1876 _vox_array<ogt_vox_group> groups;
1877 _vox_array<uint32_t> child_ids;
1878 ogt_vox_palette palette;
1879 _vox_dictionary dict;
1880 uint32_t size_x = 0;
1881 uint32_t size_y = 0;
1882 uint32_t size_z = 0;
1883 uint8_t index_map[256];
1884 bool found_index_map_chunk = false;
1885
1886 // size some of our arrays to prevent resizing during the parsing for smallish cases.
1887 model_ptrs.reserve(64);
1888 instances.reserve(256);
1889 child_ids.reserve(256);
1890 nodes.reserve(16);
1891 layers.reserve(8);
1892 groups.reserve(0);
1893 string_data.reserve(256);
1894
1895 // push a sentinel character into these datastructures. This allows us to keep indexes
1896 // rather than pointers into data-structures that grow, and still allow an index of 0
1897 // to means invalid
1898 string_data.push_back('X');
1899 child_ids.push_back(-1);
1900
1901 // copy the default palette into the scene. It may get overwritten by a palette chunk later
1902 memcpy(&palette, k_default_vox_palette, sizeof(ogt_vox_palette));
1903
1904 // load and validate fileheader and file version.
1905 uint32_t file_header;
1906 uint32_t file_version;
1907 _vox_file_read(fp, &file_header, sizeof(uint32_t));
1908 _vox_file_read(fp, &file_version, sizeof(uint32_t));
1909 if (file_header != CHUNK_ID_VOX_ || file_version != 150)
1910 return NULL;
1911
1912 // parse chunks until we reach the end of the file/buffer
1913 while (!_vox_file_eof(fp))
1914 {
1915 // read the fields common to all chunks
1916 uint32_t chunk_id = 0;
1917 uint32_t chunk_size = 0;
1918 uint32_t chunk_child_size = 0;
1919 _vox_file_read(fp, &chunk_id, sizeof(uint32_t));
1920 _vox_file_read(fp, &chunk_size, sizeof(uint32_t));
1921 _vox_file_read(fp, &chunk_child_size, sizeof(uint32_t));
1922
1923 // process the chunk.
1924 switch (chunk_id)
1925 {
1926 case CHUNK_ID_MAIN:
1927 {
1928 assert(chunk_size == 0);
1929 break;
1930 }
1931 case CHUNK_ID_SIZE:
1932 {
1933 assert(chunk_size == 12 && chunk_child_size == 0);
1934 _vox_file_read(fp, &size_x, sizeof(uint32_t));
1935 _vox_file_read(fp, &size_y, sizeof(uint32_t));
1936 _vox_file_read(fp, &size_z, sizeof(uint32_t));
1937 break;
1938 }
1939 case CHUNK_ID_XYZI:
1940 {
1941 assert(chunk_child_size == 0 && size_x && size_y && size_z); // must have read a SIZE chunk prior to XYZI.
1942 // read the number of voxels to process for this moodel
1943 uint32_t num_voxels_in_chunk = 0;
1944 _vox_file_read(fp, &num_voxels_in_chunk, sizeof(uint32_t));
1945 if (num_voxels_in_chunk != 0)
1946 {
1947 uint32_t voxel_count = size_x * size_y * size_z;
1948 ogt_vox_model* model = (ogt_vox_model*)_vox_calloc(sizeof(ogt_vox_model) + voxel_count); // 1 byte for each voxel
1949 if (!model)
1950 return NULL;
1951 uint8_t* voxel_data = (uint8_t*)&model[1];
1952
1953 // insert the model into the model array
1954 model_ptrs.push_back(model);
1955
1956 // now setup the model
1957 model->size_x = size_x;
1958 model->size_y = size_y;
1959 model->size_z = size_z;
1960 model->voxel_data = voxel_data;
1961
1962 // setup some strides for computing voxel index based on x/y/z
1963 const uint32_t k_stride_x = 1;
1964 const uint32_t k_stride_y = size_x;
1965 const uint32_t k_stride_z = size_x * size_y;
1966
1967 // read this many voxels and store it in voxel data.
1968 const uint8_t* packed_voxel_data = (const uint8_t*)_vox_file_data_pointer(fp);
1969 for (uint32_t i = 0; i < num_voxels_in_chunk; i++)
1970 {
1971 uint8_t x = packed_voxel_data[i * 4 + 0];
1972 uint8_t y = packed_voxel_data[i * 4 + 1];
1973 uint8_t z = packed_voxel_data[i * 4 + 2];
1974 uint8_t color_index = packed_voxel_data[i * 4 + 3];
1975 assert(x < size_x && y < size_y && z < size_z);
1976 voxel_data[(x * k_stride_x) + (y * k_stride_y) + (z * k_stride_z)] = color_index;
1977 }
1978 _vox_file_seek_forwards(fp, num_voxels_in_chunk * 4);
1979 // compute the hash of the voxels in this model-- used to accelerate duplicate models checking.
1980 model->voxel_hash = _vox_hash(voxel_data, size_x * size_y * size_z);
1981 }
1982 else
1983 {
1984 model_ptrs.push_back(NULL);
1985 }
1986 break;
1987 }
1988 case CHUNK_ID_RGBA:
1989 {
1990 assert(chunk_size == sizeof(palette));
1991 _vox_file_read(fp, &palette, sizeof(palette));
1992 break;
1993 }
1994 case CHUNK_ID_nTRN:
1995 {
1996 uint32_t node_id;
1997 _vox_file_read(fp, &node_id, sizeof(node_id));
1998
1999 // Parse the node dictionary, which can contain:
2000 // _name: string
2001 // _hidden: 0/1
2002 char node_name[64];
2003 bool hidden = false;
2004 node_name[0] = 0;
2005 {
2006 _vox_file_read_dict(&dict, fp);
2007 const char* name_string = _vox_dict_get_value_as_string(&dict, "_name");
2008 if (name_string)
2009 _vox_strcpy_static(node_name, name_string);
2010 // if we got a hidden attribute - assign it now.
2011 const char* hidden_string = _vox_dict_get_value_as_string(&dict, "_hidden", "0");
2012 if (hidden_string)
2013 hidden = (hidden_string[0] == '1' ? true : false);
2014 }
2015
2016
2017 // get other properties.
2018 uint32_t child_node_id, reserved_id, layer_id, num_frames;
2019 _vox_file_read(fp, &child_node_id, sizeof(child_node_id));
2020 _vox_file_read(fp, &reserved_id, sizeof(reserved_id));
2021 _vox_file_read(fp, &layer_id, sizeof(layer_id));
2022 _vox_file_read(fp, &num_frames, sizeof(num_frames));
2023 assert(reserved_id == UINT32_MAX && num_frames == 1); // must be these values according to the spec
2024
2025 // Parse the frame dictionary that contains:
2026 // _r : int8 ROTATION (c)
2027 // _t : int32x3 translation
2028 // and extract a transform
2029 ogt_vox_transform frame_transform;
2030 {
2031 _vox_file_read_dict(&dict, fp);
2032 const char* rotation_value = _vox_dict_get_value_as_string(&dict, "_r");
2033 const char* translation_value = _vox_dict_get_value_as_string(&dict, "_t");
2034 frame_transform = _vox_make_transform_from_dict_strings(rotation_value, translation_value);
2035 }
2036 // setup the transform node.
2037 {
2038 nodes.grow_to_fit_index(node_id);
2039 _vox_scene_node_* transform_node = &nodes[node_id];
2040 assert(transform_node);
2041 transform_node->node_type = k_nodetype_transform;
2042 transform_node->u.transform.child_node_id = child_node_id;
2043 transform_node->u.transform.layer_id = layer_id;
2044 transform_node->u.transform.transform = frame_transform;
2045 transform_node->u.transform.hidden = hidden;
2046 // assign the name
2047 _vox_strcpy_static(transform_node->u.transform.name, node_name);
2048 }
2049 break;
2050 }
2051 case CHUNK_ID_nGRP:
2052 {
2053 uint32_t node_id;
2054 _vox_file_read(fp, &node_id, sizeof(node_id));
2055
2056 // parse the node dictionary - data is unused.
2057 _vox_file_read_dict(&dict, fp);
2058
2059 // setup the group node
2060 nodes.grow_to_fit_index(node_id);
2061 _vox_scene_node_* group_node = &nodes[node_id];
2062 group_node->node_type = k_nodetype_group;
2063 group_node->u.group.first_child_node_id_index = 0;
2064 group_node->u.group.num_child_nodes = 0;
2065
2066 // setup all child scene nodes to point back to this node.
2067 uint32_t num_child_nodes = 0;
2068 _vox_file_read(fp, &num_child_nodes, sizeof(num_child_nodes));
2069
2070 // allocate space for all the child node IDs
2071 if (num_child_nodes)
2072 {
2073 size_t prior_size = child_ids.size();
2074 assert(prior_size > 0); // should be guaranteed by the sentinel we reserved at the very beginning.
2075 child_ids.resize(prior_size + num_child_nodes);
2076 _vox_file_read(fp, &child_ids[prior_size], sizeof(uint32_t) * num_child_nodes);
2077 group_node->u.group.first_child_node_id_index = (uint32_t)prior_size;
2078 group_node->u.group.num_child_nodes = num_child_nodes;
2079 }
2080 break;
2081 }
2082 case CHUNK_ID_nSHP:
2083 {
2084 uint32_t node_id;
2085 _vox_file_read(fp, &node_id, sizeof(node_id));
2086
2087 // setup the shape node
2088 nodes.grow_to_fit_index(node_id);
2089 _vox_scene_node_* shape_node = &nodes[node_id];
2090 shape_node->node_type = k_nodetype_shape;
2091 shape_node->u.shape.model_id = UINT32_MAX;
2092
2093 // parse the node dictionary - data is unused.
2094 _vox_file_read_dict(&dict, fp);
2095
2096 uint32_t num_models = 0;
2097 _vox_file_read(fp, &num_models, sizeof(num_models));
2098 assert(num_models == 1); // must be 1 according to the spec.
2099
2100 // assign instances
2101 _vox_file_read(fp, &shape_node->u.shape.model_id, sizeof(uint32_t));
2102 assert(shape_node->u.shape.model_id < model_ptrs.size());
2103
2104 // parse the model dictionary - data is unsued.
2105 _vox_file_read_dict(&dict, fp);
2106 break;
2107 }
2108 case CHUNK_ID_IMAP:
2109 {
2110 assert(chunk_size == 256);
2111 _vox_file_read(fp, index_map, 256);
2112 found_index_map_chunk = true;
2113 break;
2114 }
2115 case CHUNK_ID_LAYR:
2116 {
2117 int32_t layer_id = 0;
2118 int32_t reserved_id = 0;
2119 _vox_file_read(fp, &layer_id, sizeof(layer_id));
2120 _vox_file_read_dict(&dict, fp);
2121 _vox_file_read(fp, &reserved_id, sizeof(reserved_id));
2122 assert(reserved_id == -1);
2123
2124 layers.grow_to_fit_index(layer_id);
2125 layers[layer_id].name = NULL;
2126 layers[layer_id].hidden = false;
2127
2128 // if we got a layer name from the LAYR dictionary, allocate space in string_data for it and keep track of the index
2129 // within string data. This will be patched to a real pointer at the very end.
2130 const char* name_string = _vox_dict_get_value_as_string(&dict, "_name", NULL);
2131 if (name_string)
2132 {
2133 layers[layer_id].name = (const char*)(string_data.size());
2134 size_t name_size = _vox_strlen(name_string) + 1; // +1 for terminator
2135 string_data.push_back_many(name_string, name_size);
2136 }
2137 // if we got a hidden attribute - assign it now.
2138 const char* hidden_string = _vox_dict_get_value_as_string(&dict, "_hidden", "0");
2139 if (hidden_string)
2140 layers[layer_id].hidden = (hidden_string[0] == '1' ? true : false);
2141 break;
2142 }
2143 // we don't handle MATL/MATT/rOBJ or any other chunks for now, so we just skip the chunk payload.
2144 case CHUNK_ID_MATL:
2145 case CHUNK_ID_MATT:
2146 case CHUNK_ID_rOBJ:
2147 default:
2148 {
2149 _vox_file_seek_forwards(fp, chunk_size);
2150 break;
2151 }
2152 } // end switch
2153 }
2154
2155 // ok, now that we've parsed all scene nodes - walk the scene hierarchy, and generate instances
2156 // we can't do this while parsing chunks unfortunately because some chunks reference chunks
2157 // that are later in the file than them.
2158 if (nodes.size())
2159 {
2160 bool generate_groups = read_flags & k_read_scene_flags_groups ? true : false;
2161 // if we're not reading scene-embedded groups, we generate only one and then flatten all instance transforms.
2162 if (!generate_groups)
2163 {
2164 ogt_vox_group root_group;
2165 root_group.transform = _vox_transform_identity();
2166 root_group.parent_group_index = k_invalid_group_index;
2167 root_group.layer_index = 0;
2168 root_group.hidden = false;
2169 groups.push_back(root_group);
2170 }
2171 generate_instances_for_node(nodes, 0, child_ids, 0, _vox_transform_identity(), model_ptrs, NULL, false, instances, string_data, groups, k_invalid_group_index, generate_groups);
2172 }
2173 else if (model_ptrs.size() == 1)
2174 {
2175 // add a single instance
2176 ogt_vox_instance new_instance;
2177 new_instance.model_index = 0;
2178 new_instance.group_index = 0;
2179 new_instance.transform = _vox_transform_identity();
2180 new_instance.layer_index = 0;
2181 new_instance.name = 0;
2182 new_instance.hidden = false;
2183 instances.push_back(new_instance);
2184 }
2185
2186 // if we didn't get a layer chunk -- just create a default layer.
2187 if (layers.size() == 0)
2188 {
2189 // go through all instances and ensure they are only mapped to layer 0
2190 for (uint32_t i = 0; i < instances.size(); i++)
2191 instances[i].layer_index = 0;
2192 // add a single layer
2193 ogt_vox_layer new_layer;
2194 new_layer.hidden = false;
2195 new_layer.name = NULL;
2196 layers.push_back(new_layer);
2197 }
2198
2199 // To support index-level assumptions (eg. artists using top 16 colors for color/palette cycling,
2200 // other ranges for emissive etc), we must ensure the order of colors that the artist sees in the
2201 // magicavoxel tool matches the actual index we'll end up using here. Unfortunately, magicavoxel
2202 // does an unexpected thing when remapping colors in the editor using ctrl+drag within the palette.
2203 // Instead of remapping all indices in all models, it just keeps track of a display index to actual
2204 // palette map and uses that to show reordered colors in the palette window. This is how that
2205 // map works:
2206 // displaycolor[k] = paletteColor[imap[k]]
2207 // To ensure our indices are in the same order as displayed by magicavoxel within the palette
2208 // window, we apply the mapping from the IMAP chunk both to the color palette and indices within each
2209 // voxel model.
2210 if (found_index_map_chunk)
2211 {
2212 // the imap chunk maps from display index to actual index.
2213 // generate an inverse index map (maps from actual index to display index)
2214 uint8_t index_map_inverse[256];
2215 for (uint32_t i = 0; i < 256; i++)
2216 {
2217 index_map_inverse[index_map[i]] = (uint8_t)i;
2218 }
2219
2220 // reorder colors in the palette so the palette contains colors in display order
2221 ogt_vox_palette old_palette = palette;
2222 for (uint32_t i = 0; i < 256; i++)
2223 {
2224 uint32_t remapped_index = (index_map[i] + 255) & 0xFF;
2225 palette.color[i] = old_palette.color[remapped_index];
2226 }
2227
2228 // ensure that all models are remapped so they are using display order palette indices.
2229 for (uint32_t i = 0; i < model_ptrs.size(); i++)
2230 {
2231 ogt_vox_model* model = model_ptrs[i];
2232 if (model)
2233 {
2234 uint32_t num_voxels = model->size_x * model->size_y * model->size_z;
2235 uint8_t* voxels = (uint8_t*)&model[1];
2236 for (uint32_t j = 0; j < num_voxels; j++)
2237 voxels[j] = 1 + index_map_inverse[voxels[j]];
2238 }
2239 }
2240 }
2241
2242 // rotate the scene palette now so voxel indices can just map straight into the palette
2243 {
2244 ogt_vox_rgba last_color = palette.color[255];
2245 for (uint32_t i = 255; i > 0; i--)
2246 palette.color[i] = palette.color[i - 1];
2247 palette.color[0] = last_color;
2248 palette.color[0].a = 0; // alpha is zero for the 0th color as that color index represents a transparent voxel.
2249 }
2250
2251 // check for models that are identical by doing a pair-wise compare. If we find identical
2252 // models, we'll end up with NULL gaps in the model_ptrs array, but instances will have
2253 // been remapped to keep the earlier model.
2254 for (uint32_t i = 0; i < model_ptrs.size(); i++)
2255 {
2256 if (!model_ptrs[i])
2257 continue;
2258 for (uint32_t j = i + 1; j < model_ptrs.size(); j++)
2259 {
2260 if (!model_ptrs[j] || !_vox_models_are_equal(model_ptrs[i], model_ptrs[j]))
2261 continue;
2262 // model i and model j are the same, so free model j and keep model i.
2263 _vox_free(model_ptrs[j]);
2264 model_ptrs[j] = NULL;
2265 // remap all instances that were referring to j to now refer to i.
2266 for (uint32_t k = 0; k < instances.size(); k++)
2267 if (instances[k].model_index == j)
2268 instances[k].model_index = i;
2269 }
2270 }
2271
2272 // sometimes a model can be created which has no solid voxels within just due to the
2273 // authoring flow within magicavoxel. We have already have prevented creation of
2274 // instances that refer to empty models, but here we want to compact the model_ptrs
2275 // array such that it contains no more NULL models. This also requires we remap the
2276 // indices for instances so they continue to refer to their correct models.
2277 {
2278 // first, check to see if we find any empty model. No need to do work otherwise.
2279 bool found_empty_model = false;
2280 for (uint32_t i = 0; i < model_ptrs.size() && !found_empty_model; i++)
2281 {
2282 if (model_ptrs[i] == NULL)
2283 found_empty_model = true;
2284 }
2285 if (found_empty_model)
2286 {
2287 // build a remap table for all instances and simultaneously compact the model_ptrs array.
2288 uint32_t* model_remap = (uint32_t*)_vox_malloc(model_ptrs.size() * sizeof(uint32_t));
2289 uint32_t num_output_models = 0;
2290 for (uint32_t i = 0; i < model_ptrs.size(); i++)
2291 {
2292 if (model_ptrs[i] != NULL)
2293 {
2294 model_ptrs[num_output_models] = model_ptrs[i];
2295 model_remap[i] = num_output_models;
2296 num_output_models++;
2297 }
2298 else
2299 {
2300 model_remap[i] = UINT32_MAX;
2301 }
2302 }
2303 model_ptrs.resize(num_output_models);
2304
2305 // remap all instances to point to the compacted model index
2306 for (uint32_t i = 0; i < instances.size(); i++)
2307 {
2308 uint32_t new_model_index = model_remap[instances[i].model_index];
2309 assert(new_model_index != UINT32_MAX); // we should have suppressed instances already that point to NULL models.
2310 instances[i].model_index = new_model_index;
2311 }
2312
2313 // free remap table
2314 _vox_free(model_remap);
2315 model_remap = NULL;
2316 }
2317 }
2318
2319 // finally, construct the output scene..
2320 size_t scene_size = sizeof(ogt_vox_scene) + string_data.size();
2321 ogt_vox_scene* scene = (ogt_vox_scene*)_vox_calloc(scene_size);
2322 {
2323 // copy name data into the scene
2324 char* scene_string_data = (char*)&scene[1];
2325 memcpy(scene_string_data, &string_data[0], sizeof(char) * string_data.size());
2326
2327 // copy instances over to scene, and sort them so that instances with the same model are contiguous.
2328 size_t num_scene_instances = instances.size();
2329 ogt_vox_instance* scene_instances = (ogt_vox_instance*)_vox_malloc(sizeof(ogt_vox_instance) * num_scene_instances);
2330 if (num_scene_instances)
2331 {
2332 memcpy(scene_instances, &instances[0], sizeof(ogt_vox_instance) * num_scene_instances);
2333 qsort(scene_instances, num_scene_instances, sizeof(ogt_vox_instance), _vox_ordered_compare_instance);
2334 }
2335 scene->instances = scene_instances;
2336 scene->num_instances = (uint32_t)instances.size();
2337
2338 // copy model pointers over to the scene,
2339 size_t num_scene_models = model_ptrs.size();
2340 ogt_vox_model** scene_models = (ogt_vox_model**)_vox_malloc(sizeof(ogt_vox_model*) * num_scene_models);
2341 if (num_scene_models)
2342 memcpy(scene_models, &model_ptrs[0], sizeof(ogt_vox_model*) * num_scene_models);
2343 scene->models = (const ogt_vox_model**)scene_models;
2344 scene->num_models = (uint32_t)num_scene_models;
2345
2346 // copy layer pointers over to the scene
2347 size_t num_scene_layers = layers.size();
2348 ogt_vox_layer* scene_layers = (ogt_vox_layer*)_vox_malloc(sizeof(ogt_vox_layer) * num_scene_layers);
2349 memcpy(scene_layers, &layers[0], sizeof(ogt_vox_layer) * num_scene_layers);
2350 scene->layers = scene_layers;
2351 scene->num_layers = (uint32_t)num_scene_layers;
2352
2353 // copy group pointers over to the scene
2354 size_t num_scene_groups = groups.size();
2355 ogt_vox_group* scene_groups = num_scene_groups ? (ogt_vox_group*)_vox_malloc(sizeof(ogt_vox_group) * num_scene_groups) : NULL;
2356 if (num_scene_groups)
2357 memcpy(scene_groups, &groups[0], sizeof(ogt_vox_group) * num_scene_groups);
2358 scene->groups = scene_groups;
2359 scene->num_groups = (uint32_t)num_scene_groups;
2360
2361 // now patch up instance name pointers to point into the scene string area
2362 for (uint32_t i = 0; i < num_scene_instances; i++)
2363 if (scene_instances[i].name)
2364 scene_instances[i].name = scene_string_data + (size_t)scene_instances[i].name;
2365
2366 // now patch up layer name pointers to point into the scene string area
2367 for (uint32_t i = 0; i < num_scene_layers; i++)
2368 if (scene_layers[i].name)
2369 scene_layers[i].name = scene_string_data + (size_t)scene_layers[i].name;
2370
2371 // copy the palette.
2372 scene->palette = palette;
2373 }
2374 return scene;
2375}
2376
2377const ogt_vox_scene* ogt_vox_read_scene(const uint8_t* pBuffer, uint32_t buffer_size)
2378{
2379 return ogt_vox_read_scene_with_flags(pBuffer, buffer_size, 0);
2380}
2381
2382void ogt_vox_destroy_scene(const ogt_vox_scene* p_scene)
2383{
2384 ogt_vox_scene* scene = const_cast<ogt_vox_scene*>(p_scene);
2385 // free models from model array
2386 for (uint32_t i = 0; i < scene->num_models; i++)
2387 _vox_free((void*)scene->models[i]);
2388 // free model array itself
2389 if (scene->models)
2390 {
2391 _vox_free(scene->models);
2392 scene->models = NULL;
2393 }
2394 // free instance array
2395 if (scene->instances)
2396 {
2397 _vox_free(const_cast<ogt_vox_instance*>(scene->instances));
2398 scene->instances = NULL;
2399 }
2400 // free layer array
2401 if (scene->layers)
2402 {
2403 _vox_free(const_cast<ogt_vox_layer*>(scene->layers));
2404 scene->layers = NULL;
2405 }
2406 // free groups array
2407 if (scene->groups)
2408 {
2409 _vox_free(const_cast<ogt_vox_group*>(scene->groups));
2410 scene->groups = NULL;
2411 }
2412 // finally, free the scene.
2413 _vox_free(scene);
2414}
2415
2416// the vector should be a unit vector aligned along one of the cardinal directions exactly. eg. (1,0,0) or (0, 0, -1)
2417// this function returns the non-zero column index in out_index and the returns whether that entry is negative.
2418static bool _vox_get_vec3_rotation_bits(const vec3& vec, uint32_t& out_index)
2419{
2420 const float* f = &vec.x;
2421 out_index = 3;
2422 bool is_negative = false;
2423 for (uint32_t i = 0; i < 3; i++)
2424 {
2425 if (f[i] == 1.0f || f[i] == -1.0f)
2426 {
2427 out_index = i;
2428 is_negative = f[i] < 0.0f ? true : false;
2429 }
2430 else
2431 {
2432 assert(f[i] == 0.0f); // must be zero
2433 }
2434 }
2435 assert(out_index != 3); // if you hit this, you probably have all zeroes in the vector!
2436 return is_negative;
2437}
2438
2439static uint8_t _vox_make_packed_rotation_from_transform(const ogt_vox_transform* pTransform)
2440{
2441 // magicavoxel stores rows, and we have columns, so we do the swizzle here into rows
2442 vec3 row0 = vec3_make(pTransform->m00, pTransform->m10, pTransform->m20);
2443 vec3 row1 = vec3_make(pTransform->m01, pTransform->m11, pTransform->m21);
2444 vec3 row2 = vec3_make(pTransform->m02, pTransform->m12, pTransform->m22);
2445 uint32_t row0_index = 3, row1_index = 3, row2_index = 3;
2446 bool row0_negative = _vox_get_vec3_rotation_bits(row0, row0_index);
2447 bool row1_negative = _vox_get_vec3_rotation_bits(row1, row1_index);
2448 bool row2_negative = _vox_get_vec3_rotation_bits(row2, row2_index);
2449 assert(((1 << row0_index) | (1 << row1_index) | (1 << row2_index)) == 7); // check that rows are orthogonal. There must be a non-zero entry in column 0, 1 and 2 across these 3 rows.
2450 return static_cast<uint8_t>((row0_index) | (row1_index << 2) | (row0_negative ? 1 << 4 : 0) | (row1_negative ? 1 << 5 : 0) | (row2_negative ? 1 << 6 : 0));
2451}
2452
2453struct _vox_file_writeable
2454{
2455 _vox_array<uint8_t> data;
2456};
2457
2458static void _vox_file_writeable_init(_vox_file_writeable* pFp)
2459{
2460 pFp->data.reserve(1024);
2461}
2462static void _vox_file_write(_vox_file_writeable* pFp, const void* pData, uint32_t data_size)
2463{
2464 pFp->data.push_back_many((const uint8_t*)pData, data_size);
2465}
2466static void _vox_file_write_uint32(_vox_file_writeable* pFp, uint32_t data)
2467{
2468 pFp->data.push_back_many((const uint8_t*)&data, sizeof(uint32_t));
2469}
2470static void _vox_file_write_uint8(_vox_file_writeable* pFp, uint8_t data)
2471{
2472 pFp->data.push_back_many((const uint8_t*)&data, sizeof(uint8_t));
2473}
2474static uint32_t _vox_file_get_offset(const _vox_file_writeable* pFp)
2475{
2476 return (uint32_t)pFp->data.count;
2477}
2478static uint8_t* _vox_file_get_data(_vox_file_writeable* pFp)
2479{
2480 return &pFp->data[0];
2481}
2482static void _vox_file_write_dict_key_value(_vox_file_writeable* pFp, const char* szKey, const char* value)
2483{
2484 if (szKey == NULL || value == NULL)
2485 return;
2486 uint32_t key_len = (uint32_t)_vox_strlen(szKey);
2487 uint32_t value_len = (uint32_t)_vox_strlen(value);
2488 _vox_file_write_uint32(pFp, key_len);
2489 _vox_file_write(pFp, szKey, key_len);
2490 _vox_file_write_uint32(pFp, value_len);
2491 _vox_file_write(pFp, value, value_len);
2492}
2493
2494static uint32_t _vox_dict_key_value_size(const char* szKey, const char* value)
2495{
2496 if (szKey == NULL || value == NULL)
2497 return 0;
2498 size_t size = sizeof(uint32_t) + _vox_strlen(szKey) + sizeof(uint32_t) + _vox_strlen(value);
2499 return (uint32_t)size;
2500}
2501
2502static void _vox_file_write_chunk_nTRN(_vox_file_writeable* pFp, uint32_t node_id, uint32_t child_node_id, const char* szName, bool bHidden, const ogt_vox_transform* pTransform, uint32_t layer_id)
2503{
2504 // obtain dictionary string pointers
2505 const char* hidden_string = bHidden ? "1" : NULL;
2506 const char* t_string = NULL;
2507 const char* r_string = NULL;
2508 char t_string_buf[64];
2509 char r_string_buf[64];
2510 t_string_buf[0] = 0;
2511 r_string_buf[0] = 0;
2512 if (pTransform != NULL)
2513 {
2514 uint8_t packed_rotation_bits = _vox_make_packed_rotation_from_transform(pTransform);
2515 _vox_sprintf(t_string_buf, sizeof(t_string_buf), "%i %i %i", (int32_t)pTransform->m30, (int32_t)pTransform->m31, (int32_t)pTransform->m32);
2516 _vox_sprintf(r_string_buf, sizeof(r_string_buf), "%u", packed_rotation_bits);
2517 t_string = t_string_buf;
2518 r_string = r_string_buf;
2519 }
2520
2521 uint32_t node_dict_size =
2522 sizeof(uint32_t) + // num key value pairs
2523 _vox_dict_key_value_size("_name", szName) +
2524 _vox_dict_key_value_size("_hidden", hidden_string);
2525
2526 uint32_t frame_dict_size =
2527 sizeof(uint32_t) + // num key value pairs
2528 _vox_dict_key_value_size("_t", t_string) +
2529 _vox_dict_key_value_size("_r", r_string);
2530
2531 uint32_t chunk_size_ntrn =
2532 sizeof(uint32_t) + // node_id
2533 node_dict_size + // node dictionary
2534 4 * sizeof(uint32_t) + // middle section - 4 uint32s
2535 frame_dict_size;
2536
2537 // write the nTRN header
2538 _vox_file_write_uint32(pFp, CHUNK_ID_nTRN);
2539 _vox_file_write_uint32(pFp, chunk_size_ntrn);
2540 _vox_file_write_uint32(pFp, 0);
2541
2542 // write the nTRN payload
2543 _vox_file_write_uint32(pFp, node_id);
2544
2545 // write the node dictionary
2546 uint32_t node_dict_keyvalue_count = (szName ? 1 : 0) + (hidden_string ? 1 : 0);
2547 _vox_file_write_uint32(pFp, node_dict_keyvalue_count); // num key values
2548 _vox_file_write_dict_key_value(pFp, "_name", szName);
2549 _vox_file_write_dict_key_value(pFp, "_hidden", hidden_string);
2550
2551 // get other properties.
2552 _vox_file_write_uint32(pFp, child_node_id);
2553 _vox_file_write_uint32(pFp, UINT32_MAX); // reserved_id must have all bits set.
2554 _vox_file_write_uint32(pFp, layer_id);
2555 _vox_file_write_uint32(pFp, 1); // num_frames must be 1
2556
2557 // write the frame dictionary
2558 _vox_file_write_uint32(pFp, (r_string ? 1 : 0) + (t_string ? 1 : 0)); // num key values
2559 _vox_file_write_dict_key_value(pFp, "_r", r_string);
2560 _vox_file_write_dict_key_value(pFp, "_t", t_string);
2561}
2562
2563// saves the scene out to a buffer that when saved as a .vox file can be loaded with magicavoxel.
2564uint8_t* ogt_vox_write_scene(const ogt_vox_scene* pScene, uint32_t* pBuffer_size)
2565{
2566 _vox_file_writeable file;
2567 _vox_file_writeable_init(&file);
2568 _vox_file_writeable* fp = &file;
2569
2570 // write file header and file version
2571 _vox_file_write_uint32(fp, CHUNK_ID_VOX_);
2572 _vox_file_write_uint32(fp, 150);
2573
2574 // write the main chunk
2575 _vox_file_write_uint32(fp, CHUNK_ID_MAIN);
2576 _vox_file_write_uint32(fp, 0);
2577 _vox_file_write_uint32(fp, 0); // this main_chunk_child_size will get patched up once everything is written.
2578
2579 // we need to know how to patch up the main chunk size after we've written everything
2580 const uint32_t offset_post_main_chunk = _vox_file_get_offset(fp);
2581
2582 // write out all model chunks
2583 for (uint32_t i = 0; i < pScene->num_models; i++)
2584 {
2585 const ogt_vox_model* model = pScene->models[i];
2586 assert(model->size_x <= 126 && model->size_y <= 126 && model->size_z <= 126);
2587 // count the number of solid voxels in the grid
2588 uint32_t num_voxels_in_grid = model->size_x * model->size_y * model->size_z;
2589 uint32_t num_solid_voxels = 0;
2590 for (uint32_t voxel_index = 0; voxel_index < num_voxels_in_grid; voxel_index++)
2591 if (model->voxel_data[voxel_index] != 0)
2592 num_solid_voxels++;
2593 uint32_t chunk_size_xyzi = sizeof(uint32_t) + 4 * num_solid_voxels;
2594
2595 // write the SIZE chunk header
2596 _vox_file_write_uint32(fp, CHUNK_ID_SIZE);
2597 _vox_file_write_uint32(fp, 12);
2598 _vox_file_write_uint32(fp, 0);
2599
2600 // write the SIZE chunk payload
2601 _vox_file_write_uint32(fp, model->size_x);
2602 _vox_file_write_uint32(fp, model->size_y);
2603 _vox_file_write_uint32(fp, model->size_z);
2604
2605 // write the XYZI chunk header
2606 _vox_file_write_uint32(fp, CHUNK_ID_XYZI);
2607 _vox_file_write_uint32(fp, chunk_size_xyzi);
2608 _vox_file_write_uint32(fp, 0);
2609
2610 // write out XYZI chunk payload
2611 _vox_file_write_uint32(fp, num_solid_voxels);
2612 uint32_t voxel_index = 0;
2613 for (uint32_t z = 0; z < model->size_z; z++)
2614 {
2615 for (uint32_t y = 0; y < model->size_y; y++)
2616 {
2617 for (uint32_t x = 0; x < model->size_x; x++, voxel_index++)
2618 {
2619 uint8_t color_index = model->voxel_data[voxel_index];
2620 if (color_index != 0)
2621 {
2622 _vox_file_write_uint8(fp, (uint8_t)x);
2623 _vox_file_write_uint8(fp, (uint8_t)y);
2624 _vox_file_write_uint8(fp, (uint8_t)z);
2625 _vox_file_write_uint8(fp, color_index);
2626 }
2627 }
2628 }
2629 }
2630 }
2631
2632 // define our node_id ranges.
2633 assert(pScene->num_groups);
2634 uint32_t first_group_transform_node_id = 0;
2635 uint32_t first_group_node_id = first_group_transform_node_id + pScene->num_groups;
2636 uint32_t first_shape_node_id = first_group_node_id + pScene->num_groups;
2637 uint32_t first_instance_transform_node_id = first_shape_node_id + pScene->num_models;
2638
2639 // write the nTRN nodes for each of the groups in the scene.
2640 for (uint32_t group_index = 0; group_index < pScene->num_groups; group_index++)
2641 {
2642 const ogt_vox_group* group = &pScene->groups[group_index];
2643 _vox_file_write_chunk_nTRN(fp, first_group_transform_node_id + group_index, first_group_node_id + group_index, NULL, group->hidden, &group->transform, group->layer_index);
2644 }
2645 // write the group nodes for each of the groups in the scene
2646 for (uint32_t group_index = 0; group_index < pScene->num_groups; group_index++)
2647 {
2648 // count how many childnodes there are. This is simply the sum of all
2649 // groups and instances that have this group as its parent
2650 uint32_t num_child_nodes = 0;
2651 for (uint32_t child_group_index = 0; child_group_index < pScene->num_groups; child_group_index++)
2652 if (pScene->groups[child_group_index].parent_group_index == group_index)
2653 num_child_nodes++;
2654 for (uint32_t child_instance_index = 0; child_instance_index < pScene->num_instances; child_instance_index++)
2655 if (pScene->instances[child_instance_index].group_index == group_index)
2656 num_child_nodes++;
2657
2658 // count number of dictionary items
2659 const char* hidden_string = pScene->groups[group_index].hidden ? "1" : NULL;
2660 uint32_t group_dict_keyvalue_count = (hidden_string ? 1 : 0);
2661
2662 // compute the chunk size.
2663 uint32_t chunk_size_ngrp =
2664 sizeof(uint32_t) + // node_id
2665 sizeof(uint32_t) + // num keyvalue pairs in node dictionary
2666 _vox_dict_key_value_size("_hidden", hidden_string) +
2667 sizeof(uint32_t) + // num_child_nodes field
2668 sizeof(uint32_t) * num_child_nodes; // uint32_t for each child node id.
2669
2670 // write the nGRP header
2671 _vox_file_write_uint32(fp, CHUNK_ID_nGRP);
2672 _vox_file_write_uint32(fp, chunk_size_ngrp);
2673 _vox_file_write_uint32(fp, 0);
2674 // write the nGRP payload
2675 _vox_file_write_uint32(fp, first_group_node_id + group_index); // node_id
2676 _vox_file_write_uint32(fp, group_dict_keyvalue_count); // num keyvalue pairs in node dictionary
2677 _vox_file_write_dict_key_value(fp, "_hidden", hidden_string);
2678 _vox_file_write_uint32(fp, num_child_nodes);
2679 // write the child group transform nodes
2680 for (uint32_t child_group_index = 0; child_group_index < pScene->num_groups; child_group_index++)
2681 if (pScene->groups[child_group_index].parent_group_index == group_index)
2682 _vox_file_write_uint32(fp, first_group_transform_node_id + child_group_index);
2683 // write the child instance transform nodes
2684 for (uint32_t child_instance_index = 0; child_instance_index < pScene->num_instances; child_instance_index++)
2685 if (pScene->instances[child_instance_index].group_index == group_index)
2686 _vox_file_write_uint32(fp, first_instance_transform_node_id + child_instance_index);
2687 }
2688
2689 // write out an nSHP chunk for each of the models
2690 for (uint32_t i = 0; i < pScene->num_models; i++)
2691 {
2692 // compute the size of the nSHP chunk
2693 uint32_t chunk_size_nshp =
2694 sizeof(uint32_t) + // node_id
2695 sizeof(uint32_t) + // num keyvalue pairs in node dictionary
2696 sizeof(uint32_t) + // num_models
2697 sizeof(uint32_t) + // model_id
2698 sizeof(uint32_t); // num keyvalue pairs in model dictionary
2699 // write the nSHP chunk header
2700 _vox_file_write_uint32(fp, CHUNK_ID_nSHP);
2701 _vox_file_write_uint32(fp, chunk_size_nshp);
2702 _vox_file_write_uint32(fp, 0);
2703 // write the nSHP chunk payload
2704 _vox_file_write_uint32(fp, first_shape_node_id + i); // node_id
2705 _vox_file_write_uint32(fp, 0); // num keyvalue pairs in node dictionary
2706 _vox_file_write_uint32(fp, 1); // num_models must be 1
2707 _vox_file_write_uint32(fp, i); // model_id
2708 _vox_file_write_uint32(fp, 0); // num keyvalue pairs in model dictionary
2709 }
2710 // write out an nTRN chunk for all instances - and make them point to the relevant nSHP chunk
2711 for (uint32_t i = 0; i < pScene->num_instances; i++)
2712 {
2713 const ogt_vox_instance* instance = &pScene->instances[i];
2714 uint32_t node_id = first_instance_transform_node_id + i;
2715 uint32_t child_node_id = first_shape_node_id + instance->model_index;
2716 _vox_file_write_chunk_nTRN(fp, node_id, child_node_id, instance->name, instance->hidden, &instance->transform, instance->layer_index);
2717 }
2718
2719 // write out RGBA chunk for the palette
2720 {
2721 // .vox stores palette rotated by 1 color index, so do that now.
2722 ogt_vox_palette rotated_palette;
2723 for (uint32_t i = 0; i < 256; i++)
2724 rotated_palette.color[i] = pScene->palette.color[(i + 1) & 255];
2725
2726 // write the palette chunk header
2727 _vox_file_write_uint32(fp, CHUNK_ID_RGBA);
2728 _vox_file_write_uint32(fp, sizeof(ogt_vox_palette));
2729 _vox_file_write_uint32(fp, 0);
2730 // write the palette chunk payload
2731 _vox_file_write(fp, &rotated_palette, sizeof(ogt_vox_palette));
2732 }
2733
2734 // write all layer chunks out.
2735 for (uint32_t i = 0; i < pScene->num_layers; i++)
2736 {
2737 const char* layer_name_string = pScene->layers[i].name;
2738 const char* hidden_string = pScene->layers[i].hidden ? "1" : NULL;
2739 uint32_t layer_chunk_size =
2740 sizeof(int32_t) + // layer_id
2741 sizeof(uint32_t) + // num key value pairs
2742 _vox_dict_key_value_size("_name", layer_name_string) +
2743 _vox_dict_key_value_size("_hidden", hidden_string) +
2744 sizeof(int32_t); // reserved id, must be -1
2745 uint32_t layer_dict_keyvalue_count = (layer_name_string ? 1 : 0) + (hidden_string ? 1 : 0);
2746 // write the layer chunk header
2747 _vox_file_write_uint32(fp, CHUNK_ID_LAYR);
2748 _vox_file_write_uint32(fp, layer_chunk_size);
2749 _vox_file_write_uint32(fp, 0);
2750 // write the layer chunk payload
2751 _vox_file_write_uint32(fp, i); // layer_id
2752 _vox_file_write_uint32(fp, layer_dict_keyvalue_count); // num keyvalue pairs in layer dictionary
2753 _vox_file_write_dict_key_value(fp, "_name", layer_name_string);
2754 _vox_file_write_dict_key_value(fp, "_hidden", hidden_string);
2755 _vox_file_write_uint32(fp, UINT32_MAX); // reserved id
2756 }
2757
2758 // we deliberately don't free the fp->data field, just pass the buffer pointer and size out to the caller
2759 *pBuffer_size = (uint32_t)fp->data.count;
2760 uint8_t* buffer_data = _vox_file_get_data(fp);
2761 // we deliberately clear this pointer so it doesn't get auto-freed on exiting. The caller will own the memory hereafter.
2762 fp->data.data = NULL;
2763
2764 // patch up the main chunk's child chunk size now that we've written everything we're going to write.
2765 {
2766 uint32_t* main_chunk_child_size = (uint32_t*)&buffer_data[offset_post_main_chunk - sizeof(uint32_t)];
2767 *main_chunk_child_size = *pBuffer_size - offset_post_main_chunk;
2768 }
2769
2770 return buffer_data;
2771}
2772
2773void* ogt_vox_malloc(size_t uiSize)
2774{
2775 return _vox_malloc(uiSize);
2776}
2777
2778void ogt_vox_free(void* pMem)
2779{
2780 _vox_free(pMem);
2781}
2782
2783// compute the minimum and maximum x coordinate within the scene.
2784static void compute_scene_bounding_box_x(const ogt_vox_scene* pScene, int32_t& out_min_x, int32_t& out_max_x)
2785{
2786 if (pScene->num_instances && pScene->num_models)
2787 {
2788 // We don't apply orientation to the model dimensions and compute the exact min/max.
2789 // Instead we just conservatively use the maximum dimension of the model.
2790 int32_t scene_min_x = 0x7ffffff;
2791 int32_t scene_max_x = -0x7ffffff;
2792 for (uint32_t instance_index = 0; instance_index < pScene->num_instances; instance_index++)
2793 {
2794 const ogt_vox_instance* instance = &pScene->instances[instance_index];
2795 // compute the instance transform, taking into account the group hierarchy.
2796 ogt_vox_transform instance_transform = instance->transform;
2797 uint32_t parent_group_index = instance->group_index;
2798 while (parent_group_index != k_invalid_group_index)
2799 {
2800 const ogt_vox_group* group = &pScene->groups[parent_group_index];
2801 instance_transform = _vox_transform_multiply(instance_transform, group->transform);
2802 parent_group_index = group->parent_group_index;
2803 }
2804
2805 const ogt_vox_model* model = pScene->models[instance->model_index];
2806 // the instance_transform can be rotated, so we try to figure out whether the
2807 // model's local x, y or z size is aligned along the world x axis.
2808 // One of the column vectors of the transform must have a non-zero in its
2809 // x field and the dimension associated with that column is the correct choice of rus.
2810 int32_t max_dim = instance_transform.m00 != 0.0f ? model->size_x : instance_transform.m10 != 0.0f ? model->size_y :
2811 instance_transform.m20 != 0.0f ? model->size_z :
2812 model->size_x;
2813 int32_t half_dim = max_dim / 2;
2814 int32_t min_x = (int32_t)instance_transform.m30 - half_dim;
2815 int32_t max_x = (int32_t)instance_transform.m30 + half_dim;
2816 scene_min_x = min_x < scene_min_x ? min_x : scene_min_x;
2817 scene_max_x = max_x > scene_max_x ? max_x : scene_max_x;
2818 }
2819 // pass out the dimensions.
2820 out_min_x = scene_min_x;
2821 out_max_x = scene_max_x;
2822 }
2823 else
2824 {
2825 out_min_x = 0;
2826 out_max_x = 0;
2827 }
2828}
2829
2830// returns a mask of which color indices are used by the specified scene.
2831// used_mask[0] can be false at the end of this if all models 100% fill their voxel grid with solid voxels, so callers
2832// should handle that case properly.
2833static void compute_scene_used_color_index_mask(bool* pUsed_mask, const ogt_vox_scene* pScene)
2834{
2835 memset(pUsed_mask, 0, 256);
2836 for (uint32_t model_index = 0; model_index < pScene->num_models; model_index++)
2837 {
2838 const ogt_vox_model* model = pScene->models[model_index];
2839 uint32_t voxel_count = model->size_x * model->size_y * model->size_z;
2840 for (uint32_t voxel_index = 0; voxel_index < voxel_count; voxel_index++)
2841 {
2842 uint8_t color_index = model->voxel_data[voxel_index];
2843 pUsed_mask[color_index] = true;
2844 }
2845 }
2846}
2847
2848// finds an exact color in the specified palette if it exists, and UINT32_MAX otherwise
2849static uint32_t find_exact_color_in_palette(const ogt_vox_rgba* pPalette, uint32_t palette_count, const ogt_vox_rgba color_to_find)
2850{
2851 for (uint32_t color_index = 1; color_index < palette_count; color_index++)
2852 {
2853 const ogt_vox_rgba color_to_match = pPalette[color_index];
2854 // we only try to match r,g,b components exactly.
2855 if (color_to_match.r == color_to_find.r && color_to_match.g == color_to_find.g && color_to_match.b == color_to_find.b)
2856 return color_index;
2857 }
2858 // no exact color found
2859 return UINT32_MAX;
2860}
2861
2862// finds the index within the specified palette that is closest to the color we want to find
2863static uint32_t find_closest_color_in_palette(const ogt_vox_rgba* pPalette, uint32_t palette_count, const ogt_vox_rgba color_to_find)
2864{
2865 // the lower the score the better, so initialize this to the maximum possible score
2866 int32_t best_score = INT32_MAX;
2867 uint32_t best_index = 1;
2868 // Here we compute a score based on the pythagorean distance between each color in the palette and the color to find.
2869 // The distance is in R,G,B space, and we choose the color with the lowest score.
2870 for (uint32_t color_index = 1; color_index < palette_count; color_index++)
2871 {
2872 int32_t r_diff = (int32_t)color_to_find.r - (int32_t)pPalette[color_index].r;
2873 int32_t g_diff = (int32_t)color_to_find.g - (int32_t)pPalette[color_index].g;
2874 int32_t b_diff = (int32_t)color_to_find.b - (int32_t)pPalette[color_index].b;
2875 // There are 2 aspects of our treatment of color here you may want to experiment with:
2876 // 1. differences in R, differences in G, differences in B are weighted the same rather than perceptually. Different weightings may be better for you.
2877 // 2. We treat R,G,B as if they are in a perceptually linear within each channel. eg. the differences between
2878 // a value of 5 and 8 in any channel is perceptually the same as the difference between 233 and 236 in the same channel.
2879 int32_t score = (r_diff * r_diff) + (g_diff * g_diff) + (b_diff * b_diff);
2880 if (score < best_score)
2881 {
2882 best_score = score;
2883 best_index = color_index;
2884 }
2885 }
2886 assert(best_score < UINT32_MAX); // this might indicate a completely degenerate palette.
2887 return best_index;
2888}
2889
2890static void update_master_palette_from_scene(ogt_vox_rgba* pMaster_palette, uint32_t& ref_master_palette_count, const ogt_vox_scene* pScene, uint32_t* pScene_to_master_map)
2891{
2892 // compute the mask of used colors in the scene.
2893 bool scene_used_mask[256];
2894 compute_scene_used_color_index_mask(scene_used_mask, pScene);
2895
2896 // initialize the map that converts from scene color_index to master color_index
2897 pScene_to_master_map[0] = 0; // zero/empty always maps to zero/empty in the master palette
2898 for (uint32_t i = 1; i < 256; i++)
2899 pScene_to_master_map[i] = UINT32_MAX; // UINT32_MAX means unassigned
2900
2901 // for each used color in the scene, now allocate it into the master palette.
2902 for (uint32_t color_index = 1; color_index < 256; color_index++)
2903 {
2904 if (scene_used_mask[color_index])
2905 {
2906 const ogt_vox_rgba color = pScene->palette.color[color_index];
2907 // find the exact color in the master palette. Will be UINT32_MAX if the color doesn't already exist
2908 uint32_t master_index = find_exact_color_in_palette(pMaster_palette, ref_master_palette_count, color);
2909 if (master_index == UINT32_MAX)
2910 {
2911 if (ref_master_palette_count < 256)
2912 {
2913 // master palette capacity hasn't been exceeded so far, allocate the color to it.
2914 pMaster_palette[ref_master_palette_count] = color;
2915 master_index = ref_master_palette_count++;
2916 }
2917 else
2918 {
2919 // otherwise, find the color that is perceptually closest to the original color.
2920
2921 // TODO(jpaver): It is potentially problematic if we hit this path for a many-scene merge.
2922 // Earlier scenes will reserve their colors exactly into the master palette, whereas later
2923 // scenes will end up having some of their colors remapped to different colors.
2924
2925 // A more holistic approach to color allocation may be necessary here eg.
2926 // we might allow the master palette to grow to more than 256 entries, and then use
2927 // similarity/frequency metrics to reduce the palette from that down to 256 entries. This
2928 // will mean all scenes will have be equally important if they have a high-frequency
2929 // usage of a color.
2930 master_index = find_closest_color_in_palette(pMaster_palette, ref_master_palette_count, color);
2931 }
2932 }
2933 // caller needs to know how to map its original color index into the master palette
2934 pScene_to_master_map[color_index] = master_index;
2935 }
2936 }
2937}
2938
2939ogt_vox_scene* ogt_vox_merge_scenes(const ogt_vox_scene** pScenes, uint32_t scene_count, const ogt_vox_rgba* pRequired_colors, const uint32_t required_color_count)
2940{
2941 assert(required_color_count <= 255); // can't exceed the maximum colors in the master palette plus the empty slot.
2942
2943 // initialize the master palette. If required colors are specified, map them into the master palette now.
2944 ogt_vox_rgba master_palette[256];
2945 uint32_t master_palette_count = 1; // color_index 0 is reserved for empty color!
2946 memset(&master_palette, 0, sizeof(master_palette));
2947 for (uint32_t required_index = 0; required_index < required_color_count; required_index++)
2948 master_palette[master_palette_count++] = pRequired_colors[required_index];
2949
2950 // count the number of required models, instances in the master scene
2951 uint32_t max_layers = 1; // we don't actually merge layers. Every instance will be in layer 0.
2952 uint32_t max_models = 0;
2953 uint32_t max_instances = 0;
2954 uint32_t max_groups = 1; // we add 1 root global group that everything will ultimately be parented to.
2955 for (uint32_t scene_index = 0; scene_index < scene_count; scene_index++)
2956 {
2957 if (!pScenes[scene_index])
2958 continue;
2959 max_instances += pScenes[scene_index]->num_instances;
2960 max_models += pScenes[scene_index]->num_models;
2961 max_groups += pScenes[scene_index]->num_groups;
2962 }
2963
2964 // allocate the master instances array
2965 ogt_vox_instance* instances = (ogt_vox_instance*)_vox_malloc(sizeof(ogt_vox_instance) * max_instances);
2966 ogt_vox_model** models = (ogt_vox_model**)_vox_malloc(sizeof(ogt_vox_model*) * max_models);
2967 ogt_vox_layer* layers = (ogt_vox_layer*)_vox_malloc(sizeof(ogt_vox_layer) * max_layers);
2968 ogt_vox_group* groups = (ogt_vox_group*)_vox_malloc(sizeof(ogt_vox_group) * max_groups);
2969 uint32_t num_instances = 0;
2970 uint32_t num_models = 0;
2971 uint32_t num_layers = 0;
2972 uint32_t num_groups = 0;
2973
2974 // add a single layer.
2975 layers[num_layers].hidden = false;
2976 layers[num_layers].name = "merged";
2977 num_layers++;
2978
2979 // magicavoxel expects exactly 1 root group, so if we have multiple scenes with multiple roots,
2980 // we must ensure all merged scenes are parented to the same root group. Allocate it now for the
2981 // merged scene.
2982 uint32_t global_root_group_index = num_groups;
2983 {
2984 assert(global_root_group_index == 0);
2985 ogt_vox_group root_group;
2986 root_group.hidden = false;
2987 root_group.layer_index = 0;
2988 root_group.parent_group_index = k_invalid_group_index;
2989 root_group.transform = _vox_transform_identity();
2990 groups[num_groups++] = root_group;
2991 }
2992
2993 // go ahead and do the merge now!
2994 size_t string_data_size = 0;
2995 int32_t offset_x = 0;
2996 for (uint32_t scene_index = 0; scene_index < scene_count; scene_index++)
2997 {
2998 const ogt_vox_scene* scene = pScenes[scene_index];
2999 if (!scene)
3000 continue;
3001
3002 // update the master palette, and get the map of this scene's color indices into the master palette.
3003 uint32_t scene_color_index_to_master_map[256];
3004 update_master_palette_from_scene(master_palette, master_palette_count, scene, scene_color_index_to_master_map);
3005
3006 // cache away the base model index for this scene.
3007 uint32_t base_model_index = num_models;
3008 uint32_t base_group_index = num_groups;
3009
3010 // create copies of all models that have color indices remapped.
3011 for (uint32_t model_index = 0; model_index < scene->num_models; model_index++)
3012 {
3013 const ogt_vox_model* model = scene->models[model_index];
3014 uint32_t voxel_count = model->size_x * model->size_y * model->size_z;
3015 // clone the model
3016 ogt_vox_model* override_model = (ogt_vox_model*)_vox_malloc(sizeof(ogt_vox_model) + voxel_count);
3017 uint8_t* override_voxel_data = (uint8_t*)&override_model[1];
3018
3019 // remap all color indices in the cloned model so they reference the master palette now!
3020 for (uint32_t voxel_index = 0; voxel_index < voxel_count; voxel_index++)
3021 {
3022 uint8_t old_color_index = model->voxel_data[voxel_index];
3023 uint32_t new_color_index = scene_color_index_to_master_map[old_color_index];
3024 assert(new_color_index < 256);
3025 override_voxel_data[voxel_index] = (uint8_t)new_color_index;
3026 }
3027 // assign the new model.
3028 *override_model = *model;
3029 override_model->voxel_data = override_voxel_data;
3030 override_model->voxel_hash = _vox_hash(override_voxel_data, voxel_count);
3031
3032 models[num_models++] = override_model;
3033 }
3034
3035 // compute the scene bounding box on x dimension. this is used to offset instances
3036 // and groups in the merged model along X dimension such that they do not overlap
3037 // with instances from another scene in the merged model.
3038 int32_t scene_min_x, scene_max_x;
3039 compute_scene_bounding_box_x(scene, scene_min_x, scene_max_x);
3040 float scene_offset_x = (float)(offset_x - scene_min_x);
3041
3042 // each scene has a root group, and it must the 0th group in its local groups[] array,
3043 assert(scene->groups[0].parent_group_index == k_invalid_group_index);
3044 // create copies of all groups into the merged scene (except the root group from each scene -- which is why we start group_index at 1 here)
3045 for (uint32_t group_index = 1; group_index < scene->num_groups; group_index++)
3046 {
3047 const ogt_vox_group* src_group = &scene->groups[group_index];
3048 assert(src_group->parent_group_index != k_invalid_group_index); // there can be only 1 root group per scene and it must be the 0th group.
3049 ogt_vox_group dst_group = *src_group;
3050 assert(dst_group.parent_group_index < scene->num_groups);
3051 dst_group.layer_index = 0;
3052 dst_group.parent_group_index = (dst_group.parent_group_index == 0) ? global_root_group_index : base_group_index + (dst_group.parent_group_index - 1);
3053 // if this group belongs to the global root group, it must be translated so it doesn't overlap with other scenes.
3054 if (dst_group.parent_group_index == global_root_group_index)
3055 dst_group.transform.m30 += scene_offset_x;
3056 groups[num_groups++] = dst_group;
3057 }
3058
3059 // create copies of all instances (and bias them such that minimum on x starts at zero)
3060 for (uint32_t instance_index = 0; instance_index < scene->num_instances; instance_index++)
3061 {
3062 const ogt_vox_instance* src_instance = &scene->instances[instance_index];
3063 assert(src_instance->group_index < scene->num_groups); // every instance must be mapped to a group.
3064 ogt_vox_instance* dst_instance = &instances[num_instances++];
3065 *dst_instance = *src_instance;
3066 dst_instance->layer_index = 0;
3067 dst_instance->group_index = (dst_instance->group_index == 0) ? global_root_group_index : base_group_index + (dst_instance->group_index - 1);
3068 dst_instance->model_index += base_model_index;
3069 if (dst_instance->name)
3070 string_data_size += _vox_strlen(dst_instance->name) + 1; // + 1 for zero terminator
3071 // if this instance belongs to the global rot group, it must be translated so it doesn't overlap with other scenes.
3072 if (dst_instance->group_index == global_root_group_index)
3073 dst_instance->transform.m30 += scene_offset_x;
3074 }
3075
3076 offset_x += (scene_max_x - scene_min_x); // step the width of the scene in x dimension
3077 offset_x += 4; // a margin of this many voxels between scenes
3078 }
3079
3080 // fill any unused master palette entries with purple/invalid color.
3081 const ogt_vox_rgba k_invalid_color = {255, 0, 255, 255}; // purple = invalid
3082 for (uint32_t color_index = master_palette_count; color_index < 256; color_index++)
3083 master_palette[color_index] = k_invalid_color;
3084
3085 // assign the master scene on output. string_data is part of the scene allocation.
3086 size_t scene_size = sizeof(ogt_vox_scene) + string_data_size;
3087 ogt_vox_scene* merged_scene = (ogt_vox_scene*)_vox_calloc(scene_size);
3088
3089 // copy name data into the string section and make instances point to it. This makes the merged model self-contained.
3090 char* scene_string_data = (char*)&merged_scene[1];
3091 for (uint32_t instance_index = 0; instance_index < num_instances; instance_index++)
3092 {
3093 if (instances[instance_index].name)
3094 {
3095 size_t string_len = _vox_strlen(instances[instance_index].name) + 1; // +1 for zero terminator
3096 memcpy(scene_string_data, instances[instance_index].name, string_len);
3097 instances[instance_index].name = scene_string_data;
3098 scene_string_data += string_len;
3099 }
3100 }
3101
3102 assert(num_groups <= max_groups);
3103
3104 memset(merged_scene, 0, sizeof(ogt_vox_scene));
3105 merged_scene->instances = instances;
3106 merged_scene->num_instances = max_instances;
3107 merged_scene->models = (const ogt_vox_model**)models;
3108 merged_scene->num_models = max_models;
3109 merged_scene->layers = layers;
3110 merged_scene->num_layers = max_layers;
3111 merged_scene->groups = groups;
3112 merged_scene->num_groups = num_groups;
3113 // copy color palette into the merged scene
3114 for (uint32_t color_index = 0; color_index < 256; color_index++)
3115 merged_scene->palette.color[color_index] = master_palette[color_index];
3116
3117 return merged_scene;
3118}
3119
3120#endif // #ifdef OGT_VOX_IMPLEMENTATION
3121
3122/* -------------------------------------------------------------------------------------------------------------------------------------------------
3123
3124 MIT License
3125
3126 Copyright (c) 2019 Justin Paver
3127
3128 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
3129 to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
3130 and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3131
3132 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
3133
3134 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3135 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3136 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
3137 IN THE SOFTWARE.
3138
3139------------------------------------------------------------------------------------------------------------------------------------------------- */
Definition ogt_vox.h:204
Definition ogt_vox.h:186
Definition ogt_vox.h:197
Definition ogt_vox.h:176
Definition ogt_vox.h:170
Definition ogt_vox.h:155
Definition ogt_vox.h:213
Definition ogt_vox.h:161