minesweeper

A minewseeper implementation to play around with Hare and Raylib
git clone https://git.tronto.net/minesweeper
Download | Log | Files | Refs | README | LICENSE

vox_loader.h (19540B)


      1 /*
      2    The MIT License (MIT)
      3 
      4    Copyright (c) 2021 Johann Nadalutti.
      5 
      6    Permission is hereby granted, free of charge, to any person obtaining a copy
      7    of this software and associated documentation files (the "Software"), to deal
      8    in the Software without restriction, including without limitation the rights
      9    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10    copies of the Software, and to permit persons to whom the Software is
     11    furnished to do so, subject to the following conditions:
     12 
     13    The above copyright notice and this permission notice shall be included in
     14    all copies or substantial portions of the Software.
     15 
     16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22    THE SOFTWARE.
     23 
     24 
     25 	vox_loader - v1.01
     26 			 no warranty implied; use at your own risk
     27 
     28 	Do this:
     29 	#define VOX_LOADER_INCLUDE__H
     30 	before you include this file in* one* C or C++ file to create the implementation.
     31 
     32 	// i.e. it should look like this:
     33 	#include ...
     34 	#include ...
     35 	#include ...
     36 	#define VOX_LOADER_INCLUDE__H
     37 	#include "vox_loader.h"
     38 
     39 revision history:
     40 	1.00  (2021-09-03)	first released version
     41 	1.01  (2021-09-07)	Support custom memory allocators
     42 						Removed Raylib dependencies
     43 						Changed Vox_LoadFileName to Vox_LoadFromMemory
     44     1.02  (2021-09-10)  @raysan5: Reviewed some formating
     45     1.03  (2021-10-02)  @catmanl: Reduce warnings on gcc
     46     1.04  (2021-10-17)  @warzes: Fixing the error of loading VOX models
     47 
     48 */
     49 
     50 #ifndef VOX_LOADER_H
     51 #define VOX_LOADER_H
     52 
     53 // Allow custom memory allocators
     54 #ifndef VOX_MALLOC
     55     #define VOX_MALLOC(sz)     malloc(sz)
     56 #endif
     57 #ifndef VOX_CALLOC
     58     #define VOX_CALLOC(n,sz)   calloc(n,sz)
     59 #endif
     60 #ifndef VOX_REALLOC
     61     #define VOX_REALLOC(n,sz)  realloc(n,sz)
     62 #endif
     63 #ifndef VOX_FREE
     64     #define VOX_FREE(p)        free(p)
     65 #endif
     66 
     67 #define VOX_SUCCESS (0)
     68 #define VOX_ERROR_FILE_NOT_FOUND (-1)
     69 #define VOX_ERROR_INVALID_FORMAT (-2)
     70 #define VOX_ERROR_FILE_VERSION_NOT_MATCH (-3)
     71 
     72 // VoxColor, 4 components, R8G8B8A8 (32bit)
     73 typedef struct {
     74     unsigned char r, g, b, a;
     75 } VoxColor;
     76 
     77 // VoxVector3, 3 components
     78 typedef struct {
     79     float x, y, z;
     80 } VoxVector3;
     81 
     82 typedef struct {
     83     VoxVector3* array;
     84     int used, size;
     85 } ArrayVector3;
     86 
     87 typedef struct {
     88     VoxColor* array;
     89     int used, size;
     90 } ArrayColor;
     91 
     92 typedef struct {
     93     unsigned short* array;
     94     int used, size;
     95 } ArrayUShort;
     96 
     97 // A chunk that contain voxels
     98 typedef struct {
     99     unsigned char* m_array; //If Sparse != null
    100     int arraySize; //Size for m_array in bytes (DEBUG ONLY)
    101 } CubeChunk3D;
    102 
    103 // Array for voxels
    104 // Array is divised into chunks of CHUNKSIZE*CHUNKSIZE*CHUNKSIZE voxels size
    105 typedef struct {
    106     // Array size in voxels
    107     int sizeX;
    108     int sizeY;
    109     int sizeZ;
    110 
    111     // Chunks size into array (array is divised into chunks)
    112     int chunksSizeX;
    113     int chunksSizeY;
    114     int chunksSizeZ;
    115 
    116     // Chunks array
    117     CubeChunk3D* m_arrayChunks;
    118     int arrayChunksSize; // Size for m_arrayChunks in bytes (DEBUG ONLY)
    119 
    120     int ChunkFlattenOffset;
    121     int chunksAllocated;
    122     int chunksTotal;
    123 
    124     // Arrays for mesh build
    125     ArrayVector3 vertices;
    126 	ArrayVector3 normals;
    127     ArrayUShort indices;
    128     ArrayColor colors;
    129 
    130     //Palette for voxels
    131     VoxColor palette[256];
    132 
    133 } VoxArray3D;
    134 
    135 #if defined(__cplusplus)
    136 extern "C" {            // Prevents name mangling of functions
    137 #endif
    138 
    139 // Functions
    140 int Vox_LoadFromMemory(unsigned char* pvoxData, unsigned int voxDataSize, VoxArray3D* pvoxarray);
    141 void Vox_FreeArrays(VoxArray3D* voxarray);
    142 
    143 #ifdef __cplusplus
    144 }
    145 #endif
    146 
    147 #endif // VOX_LOADER_H
    148 ////   end header file   /////////////////////////////////////////////////////
    149 
    150 
    151 /////////////////////////////////////////////////////////////////////////////////////////////
    152 /////////////////////////////////////////////////////////////////////////////////////////////
    153 //									Implementation
    154 ///////////////////////////////////////////////////////////////////////////////////////////// 
    155 /////////////////////////////////////////////////////////////////////////////////////////////
    156 
    157 #ifdef VOX_LOADER_IMPLEMENTATION
    158 
    159 #include <string.h>
    160 #include <stdlib.h>
    161 
    162 /////////////////////////////////////////////////////////////////////////////////////////////
    163 // ArrayUShort helper
    164 /////////////////////////////////////////////////////////////////////////////////////////////
    165 
    166 static void initArrayUShort(ArrayUShort* a, int initialSize)
    167 {
    168 	a->array = VOX_MALLOC(initialSize * sizeof(unsigned short));
    169 	a->used = 0;
    170 	a->size = initialSize;
    171 }
    172 
    173 static void insertArrayUShort(ArrayUShort* a, unsigned short element)
    174 {
    175 	if (a->used == a->size)
    176 	{
    177 		a->size *= 2;
    178 		a->array = VOX_REALLOC(a->array, a->size * sizeof(unsigned short));
    179 	}
    180 	a->array[a->used++] = element;
    181 }
    182 
    183 static void freeArrayUShort(ArrayUShort* a)
    184 {
    185 	VOX_FREE(a->array);
    186 	a->array = NULL;
    187 	a->used = a->size = 0;
    188 }
    189 
    190 
    191 /////////////////////////////////////////////////////////////////////////////////////////////
    192 // ArrayVector3 helper
    193 /////////////////////////////////////////////////////////////////////////////////////////////
    194 
    195 static void initArrayVector3(ArrayVector3* a, int initialSize)
    196 {
    197 	a->array = VOX_MALLOC(initialSize * sizeof(VoxVector3));
    198 	a->used = 0;
    199 	a->size = initialSize;
    200 }
    201 
    202 static void insertArrayVector3(ArrayVector3* a, VoxVector3 element)
    203 {
    204 	if (a->used == a->size)
    205 	{
    206 		a->size *= 2;
    207 		a->array = VOX_REALLOC(a->array, a->size * sizeof(VoxVector3));
    208 	}
    209 	a->array[a->used++] = element;
    210 }
    211 
    212 static void freeArrayVector3(ArrayVector3* a)
    213 {
    214 	VOX_FREE(a->array);
    215 	a->array = NULL;
    216 	a->used = a->size = 0;
    217 }
    218 
    219 /////////////////////////////////////////////////////////////////////////////////////////////
    220 // ArrayColor helper
    221 /////////////////////////////////////////////////////////////////////////////////////////////
    222 
    223 static void initArrayColor(ArrayColor* a, int initialSize)
    224 {
    225 	a->array = VOX_MALLOC(initialSize * sizeof(VoxColor));
    226 	a->used = 0;
    227 	a->size = initialSize;
    228 }
    229 
    230 static void insertArrayColor(ArrayColor* a, VoxColor element)
    231 {
    232 	if (a->used == a->size)
    233 	{
    234 		a->size *= 2;
    235 		a->array = VOX_REALLOC(a->array, a->size * sizeof(VoxColor));
    236 	}
    237 	a->array[a->used++] = element;
    238 }
    239 
    240 static void freeArrayColor(ArrayColor* a)
    241 {
    242 	VOX_FREE(a->array);
    243 	a->array = NULL;
    244 	a->used = a->size = 0;
    245 }
    246 
    247 
    248 /////////////////////////////////////////////////////////////////////////////////////////////
    249 // Vox Loader
    250 /////////////////////////////////////////////////////////////////////////////////////////////
    251 
    252 #define CHUNKSIZE                   16      // chunk size (CHUNKSIZE*CHUNKSIZE*CHUNKSIZE) in voxels 
    253 #define CHUNKSIZE_OPSHIFT            4      // 1<<4=16 -> Warning depend of CHUNKSIZE
    254 #define CHUNK_FLATTENOFFSET_OPSHIFT  8      // Warning depend of CHUNKSIZE
    255 
    256 //
    257 // used right handed system and CCW face
    258 // 
    259 // indexes for voxelcoords, per face orientation
    260 //
    261 
    262 //#      Y
    263 //#      |
    264 //#      o----X
    265 //#     /
    266 //#    Z     2------------3
    267 //#         /|           /|
    268 //#        6------------7 |
    269 //#        | |          | |
    270 //#        |0 ----------|- 1
    271 //#        |/           |/
    272 //#        4------------5
    273 
    274 // 
    275 // CCW
    276 const int fv[6][4] = {
    277 	{0, 2, 6, 4 }, //-X
    278 	{5, 7, 3, 1 }, //+X
    279 	{0, 4, 5, 1 }, //-y
    280 	{6, 2, 3, 7 }, //+y
    281 	{1, 3, 2, 0 }, //-Z
    282 	{4, 6, 7, 5 }  //+Z
    283 };
    284 
    285 const VoxVector3 SolidVertex[] = {
    286 	{0, 0, 0},   //0
    287 	{1, 0, 0},   //1
    288 	{0, 1, 0},   //2
    289 	{1, 1, 0},   //3
    290 	{0, 0, 1},   //4
    291 	{1, 0, 1},   //5
    292 	{0, 1, 1},   //6
    293 	{1, 1, 1}    //7
    294  };
    295 
    296 const VoxVector3 FacesPerSideNormal[] = {
    297 	{ -1, 0, 0 }, //-X
    298 	{1, 0, 0 },   //+X
    299 	{0,-1, 0},    //-Y
    300 	{0, 1, 0},    //+Y
    301 	{0, 0, -1},   //-Z
    302 	{0, 0,  1},  //+Z
    303 };
    304 
    305 
    306 // Allocated VoxArray3D size
    307 static void Vox_AllocArray(VoxArray3D* pvoxarray, int _sx, int _sy, int _sz)
    308 {
    309 	int sx = _sx + ((CHUNKSIZE - (_sx % CHUNKSIZE)) % CHUNKSIZE);
    310 	int sy = _sy + ((CHUNKSIZE - (_sy % CHUNKSIZE)) % CHUNKSIZE);
    311 	int sz = _sz + ((CHUNKSIZE - (_sz % CHUNKSIZE)) % CHUNKSIZE);
    312 
    313 	int chx = sx >> CHUNKSIZE_OPSHIFT; //Chunks Count in X
    314 	int chy = sy >> CHUNKSIZE_OPSHIFT; //Chunks Count in Y
    315 	int chz = sz >> CHUNKSIZE_OPSHIFT; //Chunks Count in Z
    316 
    317 	//VoxArray3D* parray = (VoxArray3D*)VOX_MALLOC(sizeof(VoxArray3D));
    318 	pvoxarray->sizeX = sx;
    319 	pvoxarray->sizeY = sy;
    320 	pvoxarray->sizeZ = sz;
    321 
    322 	pvoxarray->chunksSizeX = chx;
    323 	pvoxarray->chunksSizeY = chy;
    324 	pvoxarray->chunksSizeZ = chz;
    325 
    326 	pvoxarray->ChunkFlattenOffset = (chy * chz); //m_arrayChunks[(x * (sy*sz)) + (z * sy) + y]
    327 
    328 	// Alloc chunks array
    329 	int size = sizeof(CubeChunk3D) * chx * chy * chz;
    330 	pvoxarray->m_arrayChunks = VOX_MALLOC(size);
    331 	pvoxarray->arrayChunksSize = size;
    332 
    333 	// Init chunks array
    334 	size = chx * chy * chz;
    335 	pvoxarray->chunksTotal = size;
    336 	pvoxarray->chunksAllocated = 0;
    337 
    338 	for (int i = 0; i < size; i++)
    339 	{
    340 		pvoxarray->m_arrayChunks[i].m_array = 0;
    341 		pvoxarray->m_arrayChunks[i].arraySize = 0;
    342 	}
    343 }
    344 
    345 // Set voxel ID from its position into VoxArray3D
    346 static void Vox_SetVoxel(VoxArray3D* pvoxarray, int x, int y, int z, unsigned char id)
    347 {
    348 	// Get chunk from array pos
    349 	int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE;
    350 	int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE;
    351 	int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE;
    352 	int offset = (chX * pvoxarray->ChunkFlattenOffset) + (chZ * pvoxarray->chunksSizeY) + chY;
    353 
    354 	//if (offset > voxarray->arrayChunksSize)
    355 	//{
    356 	//	TraceLog(LOG_ERROR, "Out of array");
    357 	//}
    358 
    359 	CubeChunk3D* chunk = &pvoxarray->m_arrayChunks[offset];
    360 
    361 	// Set Chunk
    362 	chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE);
    363 	chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE);
    364 	chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE);
    365 
    366 	if (chunk->m_array == 0)
    367 	{
    368 		int size = CHUNKSIZE * CHUNKSIZE * CHUNKSIZE;
    369 		chunk->m_array = VOX_MALLOC(size);
    370 		chunk->arraySize = size;
    371 		memset(chunk->m_array, 0, size);
    372 
    373 		pvoxarray->chunksAllocated++;
    374 	}
    375 
    376 	offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY;
    377 
    378 	//if (offset > chunk->arraySize)
    379 	//{
    380 	//	TraceLog(LOG_ERROR, "Out of array");
    381 	//}
    382 
    383 	chunk->m_array[offset] = id;
    384 }
    385 
    386 // Get voxel ID from its position into VoxArray3D
    387 static unsigned char Vox_GetVoxel(VoxArray3D* pvoxarray, int x, int y, int z)
    388 {
    389 	if (x < 0 || y < 0 || z < 0) return 0;
    390 
    391 	if (x >= pvoxarray->sizeX || y >= pvoxarray->sizeY || z >= pvoxarray->sizeZ) return 0;
    392 
    393 	// Get chunk from array pos
    394 	int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE;
    395 	int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE;
    396 	int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE;
    397 	int offset = (chX * pvoxarray->ChunkFlattenOffset) + (chZ * pvoxarray->chunksSizeY) + chY;
    398 
    399 	//if (offset > voxarray->arrayChunksSize)
    400 	//{
    401 	//	TraceLog(LOG_ERROR, "Out of array");
    402 	//}
    403 
    404 	CubeChunk3D* chunk = &pvoxarray->m_arrayChunks[offset];
    405 
    406 	// Set Chunk
    407 	chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE);
    408 	chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE);
    409 	chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE);
    410 
    411 	if (chunk->m_array == 0)
    412 	{
    413 		return 0;
    414 	}
    415 
    416 	offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY;
    417 
    418 	//if (offset > chunk->arraySize)
    419 	//{
    420 	//	TraceLog(LOG_ERROR, "Out of array");
    421 	//}
    422 	return chunk->m_array[offset];
    423 
    424 }
    425 
    426 // Calc visibles faces from a voxel position
    427 static unsigned char Vox_CalcFacesVisible(VoxArray3D* pvoxArray, int cx, int cy, int cz)
    428 {
    429 	unsigned char idXm1 = Vox_GetVoxel(pvoxArray, cx - 1, cy, cz);
    430 	unsigned char idXp1 = Vox_GetVoxel(pvoxArray, cx + 1, cy, cz);
    431 
    432 	unsigned char idYm1 = Vox_GetVoxel(pvoxArray, cx, cy - 1, cz);
    433 	unsigned char idYp1 = Vox_GetVoxel(pvoxArray, cx, cy + 1, cz);
    434 
    435 	unsigned char idZm1 = Vox_GetVoxel(pvoxArray, cx, cy, cz - 1);
    436 	unsigned char idZp1 = Vox_GetVoxel(pvoxArray, cx, cy, cz + 1);
    437 
    438 	unsigned char byVFMask = 0;
    439 
    440 	//#-x
    441 	if (idXm1 == 0) byVFMask |= (1 << 0);
    442 
    443 	//#+x
    444 	if (idXp1 == 0) byVFMask |= (1 << 1);
    445 
    446 	//#-y
    447 	if (idYm1 == 0) byVFMask |= (1 << 2);
    448 
    449 	//#+y
    450 	if (idYp1 == 0) byVFMask |= (1 << 3);
    451 
    452 	//#-z
    453 	if (idZm1 == 0) byVFMask |= (1 << 4);
    454 
    455 	//#+z
    456 	if (idZp1 == 0) byVFMask |= (1 << 5);
    457 
    458 	return byVFMask;
    459 }
    460 
    461 // Get a vertex position from a voxel's corner
    462 static VoxVector3 Vox_GetVertexPosition(int _wcx, int _wcy, int _wcz, int _nNumVertex)
    463 {
    464 	float scale = 0.25;
    465     
    466 	VoxVector3 vtx = SolidVertex[_nNumVertex];
    467 	vtx.x = (vtx.x + _wcx) * scale;
    468 	vtx.y = (vtx.y + _wcy) * scale;
    469 	vtx.z = (vtx.z + _wcz) * scale;
    470     
    471 	return vtx;
    472 }
    473 
    474 // Build a voxel vertices/colors/indices
    475 static void Vox_Build_Voxel(VoxArray3D* pvoxArray, int x, int y, int z, int matID)
    476 {
    477 	unsigned char byVFMask = Vox_CalcFacesVisible(pvoxArray, x, y, z);
    478 
    479 	if (byVFMask == 0) return;
    480 
    481 	int i, j;
    482 	VoxVector3 vertComputed[8];
    483 	int bVertexComputed[8];
    484 	memset(vertComputed, 0, sizeof(vertComputed));
    485 	memset(bVertexComputed, 0, sizeof(bVertexComputed));
    486 
    487 	//For each Cube's faces
    488 	for (i = 0; i < 6; i++) // 6 faces
    489 	{
    490 		if ((byVFMask & (1 << i)) != 0)	//If face is visible
    491 		{
    492 			for (j = 0; j < 4; j++)   // 4 corners
    493 			{
    494 				int  nNumVertex = fv[i][j];  //Face,Corner
    495 				if (bVertexComputed[nNumVertex] == 0) //if never calc
    496 				{
    497 					bVertexComputed[nNumVertex] = 1;
    498 					vertComputed[nNumVertex] = Vox_GetVertexPosition(x, y, z, nNumVertex);
    499 				}
    500 			}
    501 		}
    502 	}
    503 
    504 	//Add face
    505 	for (i = 0; i < 6; i++)// 6 faces
    506 	{
    507 		if ((byVFMask & (1 << i)) == 0)
    508 			continue; //Face invisible
    509 
    510 		int v0 = fv[i][0];  //Face, Corner
    511 		int v1 = fv[i][1];  //Face, Corner
    512 		int v2 = fv[i][2];  //Face, Corner
    513 		int v3 = fv[i][3];  //Face, Corner
    514 
    515 		//Arrays
    516 		int idx = pvoxArray->vertices.used;
    517 		insertArrayVector3(&pvoxArray->vertices, vertComputed[v0]);
    518 		insertArrayVector3(&pvoxArray->vertices, vertComputed[v1]);
    519 		insertArrayVector3(&pvoxArray->vertices, vertComputed[v2]);
    520 		insertArrayVector3(&pvoxArray->vertices, vertComputed[v3]);
    521 
    522 		insertArrayVector3(&pvoxArray->normals, FacesPerSideNormal[i]);
    523 		insertArrayVector3(&pvoxArray->normals, FacesPerSideNormal[i]);
    524 		insertArrayVector3(&pvoxArray->normals, FacesPerSideNormal[i]);
    525 		insertArrayVector3(&pvoxArray->normals, FacesPerSideNormal[i]);
    526 
    527 		VoxColor col = pvoxArray->palette[matID];
    528 
    529 		insertArrayColor(&pvoxArray->colors, col);
    530 		insertArrayColor(&pvoxArray->colors, col);
    531 		insertArrayColor(&pvoxArray->colors, col);
    532 		insertArrayColor(&pvoxArray->colors, col);
    533 
    534 
    535 		//v0 - v1 - v2, v0 - v2 - v3
    536 		insertArrayUShort(&pvoxArray->indices, idx + 0);
    537 		insertArrayUShort(&pvoxArray->indices, idx + 2);
    538 		insertArrayUShort(&pvoxArray->indices, idx + 1);
    539 
    540 		insertArrayUShort(&pvoxArray->indices, idx + 0);
    541 		insertArrayUShort(&pvoxArray->indices, idx + 3);
    542 		insertArrayUShort(&pvoxArray->indices, idx + 2);
    543 	}
    544 }
    545 
    546 // MagicaVoxel *.vox file format Loader
    547 int Vox_LoadFromMemory(unsigned char* pvoxData, unsigned int voxDataSize, VoxArray3D* pvoxarray)
    548 {
    549 	//////////////////////////////////////////////////
    550 	// Read VOX file
    551 	// 4 bytes: magic number ('V' 'O' 'X' 'space')
    552 	// 4 bytes: version number (current version is 150)
    553 
    554 	// @raysan5: Reviewed (unsigned long) -> (unsigned int), possible issue with Ubuntu 18.04 64bit
    555 
    556 	// @raysan5: reviewed signature loading
    557 
    558 	unsigned char* fileData = pvoxData;
    559 	unsigned char* fileDataPtr = fileData;
    560 	unsigned char* endfileDataPtr = fileData + voxDataSize;
    561 
    562 	if (strncmp((char*)fileDataPtr, "VOX ", 4) != 0)
    563 	{
    564 		return VOX_ERROR_INVALID_FORMAT; //"Not an MagicaVoxel File format"
    565 	}
    566 
    567 	fileDataPtr += 4;
    568 
    569 	// @raysan5: reviewed version loading
    570 	unsigned int version = 0;
    571 	version = ((unsigned int*)fileDataPtr)[0];
    572 	fileDataPtr += 4;
    573 
    574 	if (version != 150 && version != 200)
    575 	{
    576 		return VOX_ERROR_FILE_VERSION_NOT_MATCH; //"MagicaVoxel version doesn't match"
    577 	}
    578 
    579 
    580 	// header
    581 	//4 bytes: chunk id
    582 	//4 bytes: size of chunk contents (n)
    583 	//4 bytes: total size of children chunks(m)
    584 
    585 	//// chunk content
    586 	//n bytes: chunk contents
    587 
    588 	//// children chunks : m bytes
    589 	//{ child chunk 0 }
    590 	//{ child chunk 1 }
    591 	unsigned int sizeX, sizeY, sizeZ;
    592 	sizeX = sizeY = sizeZ = 0;
    593 	unsigned int numVoxels = 0;
    594 
    595 	while (fileDataPtr < endfileDataPtr)
    596 	{
    597 		char szChunkName[5];
    598 		memcpy(szChunkName, fileDataPtr, 4);
    599 		szChunkName[4] = 0;
    600 		fileDataPtr += 4;
    601 
    602 		unsigned int chunkSize = *((unsigned int*)fileDataPtr);
    603 		fileDataPtr += sizeof(unsigned int);
    604 
    605 		//unsigned long chunkTotalChildSize = *((unsigned long*)fileDataPtr);
    606 		fileDataPtr += sizeof(unsigned int);
    607 
    608 		if (strcmp(szChunkName, "SIZE") == 0)
    609 		{
    610 			//(4 bytes x 3 : x, y, z ) 
    611 			sizeX = *((unsigned int*)fileDataPtr);
    612 			fileDataPtr += sizeof(unsigned int);
    613 
    614 			sizeY = *((unsigned int*)fileDataPtr);
    615 			fileDataPtr += sizeof(unsigned int);
    616 
    617 			sizeZ = *((unsigned int*)fileDataPtr);
    618 			fileDataPtr += sizeof(unsigned int);
    619 
    620 			//Alloc vox array
    621 			Vox_AllocArray(pvoxarray, sizeX, sizeZ, sizeY);	//Reverse Y<>Z for left to right handed system
    622 		}
    623 		else if (strcmp(szChunkName, "XYZI") == 0)
    624 		{
    625 			unsigned char vx, vy, vz, vi;
    626 
    627 			//(numVoxels : 4 bytes )
    628 			//(each voxel: 1 byte x 4 : x, y, z, colorIndex ) x numVoxels
    629 			numVoxels = *((unsigned int*)fileDataPtr);
    630 			fileDataPtr += sizeof(unsigned int);
    631 
    632 			while (numVoxels > 0)
    633 			{
    634 				vx = *((unsigned char*)fileDataPtr++);
    635 				vy = *((unsigned char*)fileDataPtr++);
    636 				vz = *((unsigned char*)fileDataPtr++);
    637 				vi = *((unsigned char*)fileDataPtr++);
    638 
    639 				Vox_SetVoxel(pvoxarray, vx, vz, pvoxarray->sizeZ-vy-1, vi); //Reverse Y<>Z for left to right handed system
    640 
    641 				numVoxels--;
    642 			}
    643 		}
    644 		else if (strcmp(szChunkName, "RGBA") == 0)
    645 		{
    646 			VoxColor col;
    647 
    648 			//(each pixel: 1 byte x 4 : r, g, b, a ) x 256
    649 			for (int i = 0; i < 256 - 1; i++)
    650 			{
    651 				col.r = *((unsigned char*)fileDataPtr++);
    652 				col.g = *((unsigned char*)fileDataPtr++);
    653 				col.b = *((unsigned char*)fileDataPtr++);
    654 				col.a = *((unsigned char*)fileDataPtr++);
    655 
    656 				pvoxarray->palette[i + 1] = col;
    657 			}
    658 
    659 		}
    660 		else
    661 		{
    662 			fileDataPtr += chunkSize;
    663 		}
    664 	}
    665 
    666 	//////////////////////////////////////////////////////////
    667 	// Building Mesh
    668 	//   TODO compute globals indices array
    669 
    670 	// Init Arrays
    671 	initArrayVector3(&pvoxarray->vertices, 3 * 1024);
    672 	initArrayVector3(&pvoxarray->normals, 3 * 1024);
    673 	initArrayUShort(&pvoxarray->indices, 3 * 1024);
    674 	initArrayColor(&pvoxarray->colors, 3 * 1024);
    675 
    676 	// Create vertices and indices buffers
    677 	int x, y, z;
    678 
    679 	for (x = 0; x <= pvoxarray->sizeX; x++)
    680 	{
    681 		for (z = 0; z <= pvoxarray->sizeZ; z++)
    682 		{
    683 			for (y = 0; y <= pvoxarray->sizeY; y++)
    684 			{
    685 				unsigned char matID = Vox_GetVoxel(pvoxarray, x, y, z);
    686 				if (matID != 0)
    687 					Vox_Build_Voxel(pvoxarray, x, y, z, matID);
    688 			}
    689 		}
    690 	}
    691 
    692 	return VOX_SUCCESS;
    693 }
    694 
    695 void Vox_FreeArrays(VoxArray3D* voxarray)
    696 {
    697 	// Free chunks
    698 	if (voxarray->m_arrayChunks != 0)
    699 	{
    700 		for (int i = 0; i < voxarray->chunksTotal; i++)
    701 		{
    702 			CubeChunk3D* chunk = &voxarray->m_arrayChunks[i];
    703 			if (chunk->m_array != 0)
    704 			{
    705 				chunk->arraySize = 0;
    706 				VOX_FREE(chunk->m_array);
    707 			}
    708 		}
    709 
    710 		VOX_FREE(voxarray->m_arrayChunks);
    711 		voxarray->m_arrayChunks = 0;
    712 		voxarray->arrayChunksSize = 0;
    713 
    714 		voxarray->chunksSizeX = voxarray->chunksSizeY = voxarray->chunksSizeZ = 0;
    715 		voxarray->chunksTotal = 0;
    716 		voxarray->chunksAllocated = 0;
    717 		voxarray->ChunkFlattenOffset = 0;
    718 		voxarray->sizeX = voxarray->sizeY = voxarray->sizeZ = 0;
    719 	}
    720 
    721 	// Free arrays
    722 	freeArrayVector3(&voxarray->vertices);
    723 	freeArrayUShort(&voxarray->indices);
    724 	freeArrayColor(&voxarray->colors);
    725 }
    726 
    727 #endif //VOX_LOADER_IMPLEMENTATION