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