浏览代码

new models_magicavoxel_loading example (#1940)

* new models_magicavoxel_loading example

* Portable header-only file "magicavoxel_loader.h" for MagicaVoxel loader example.

* models_magicavoxel_loading example added to CMakeLists.txt and Makefile

* fix models_magicavoxel_loading example for linux.

* * vox_loader into "src/external/vox_loader.h"
 * vox file support for "models.c"
 * updated example "models/models_magicavoxel_loading.c"

* * Fix Vox_FreeArrays (removed memory leak)

* * removed magicavoxel_loader.h

* * Revert vs2019 solution
procfxgen 4 年之前
父节点
当前提交
dfc465ca6d

+ 2 - 0
examples/CMakeLists.txt

@@ -86,7 +86,9 @@ if (${PLATFORM} MATCHES "Android")
     list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_obj_viewer.c)
     list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_animation.c)
     list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_first_person_maze.c)
+	list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_magicavoxel_loading.c)
     
+	
     list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_custom_uniform.c)
     list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_model_shader.c)
     list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_postprocessing.c)

+ 2 - 1
examples/Makefile

@@ -466,7 +466,8 @@ MODELS = \
     models/models_skybox \
     models/models_yaw_pitch_roll \
     models/models_heightmap \
-    models/models_waving_cubes
+    models/models_waving_cubes \
+	models/models_magicavoxel_loading
 
 SHADERS = \
     shaders/shaders_model_shader \

+ 153 - 0
examples/models/models_magicavoxel_loading.c

@@ -0,0 +1,153 @@
+/*******************************************************************************************
+*
+*   raylib [models] example - magicavoxel loader and viewer
+*
+*   This example has been created using raylib 3.8 (www.raylib.com)
+*   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+*   Example contributed by Johann Nadalutti 
+*
+*   Copyright (c) 2021 Johann Nadalutti 
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "raymath.h"
+
+#include <string.h>
+
+
+// VOX Files to load and view
+
+#define NUM_VOX_FILES  3
+
+const char* szVoxFiles[] = {
+	"resources/vox/chr_knight.vox",
+	"resources/vox/chr_sword.vox",
+	"resources/vox/monu9.vox"
+};
+
+
+int main(void)
+{
+	// Initialization
+	//--------------------------------------------------------------------------------------
+	const int screenWidth = 800;
+	const int screenHeight = 450;
+
+	InitWindow(screenWidth, screenHeight, "raylib [models] example - magicavoxel loading");
+
+	// Load MagicaVoxel files
+	Model models[NUM_VOX_FILES] = { 0 };
+
+	for (int i = 0; i < NUM_VOX_FILES; i++)
+	{
+		// Load MagicaVoxel File and build model
+		double t0, t1;
+		t0 = GetTime() * 1000.0;
+
+		models[i] = LoadModel(szVoxFiles[i]);
+
+		t1 = GetTime() * 1000.0;
+		TraceLog(LOG_INFO, TextFormat("Vox <%s> loaded in %f ms", GetFileName(szVoxFiles[i]), t1 - t0));
+
+		//Compute model matrix
+		BoundingBox  bb = GetModelBoundingBox(models[i]);
+		Vector3 center;
+		center.x = -(((bb.max.x - bb.min.x) / 2));
+		center.y = -(((bb.max.y - bb.min.y) / 2));
+		center.z = -(((bb.max.z - bb.min.z) / 2));
+
+		Matrix matP = MatrixTranslate(center.x, center.z, 0);
+		Matrix matR = MatrixRotateX(90 * DEG2RAD);
+		models[i].transform = MatrixMultiply(matP, matR);
+
+
+	}
+
+
+	// Define the camera to look into our 3d world
+	Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
+
+	// Model drawing position
+	Vector3 position = { 0.0f, 0.0f, 0.0f };
+
+	int currentModel = 0;
+
+
+
+	SetCameraMode(camera, CAMERA_ORBITAL);  // Set a orbital camera mode
+
+	SetTargetFPS(60);               // Set our game to run at 60 frames-per-second
+
+	//--------------------------------------------------------------------------------------
+	// Main game loop
+	//--------------------------------------------------------------------------------------
+	while (!WindowShouldClose())    // Detect window close button or ESC key
+	{
+		//--------------------------------------------------------------------------------------
+		// Update
+		//----------------------------------------------------------------------------------
+		UpdateCamera(&camera);      // Update internal camera and our camera
+
+		if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
+		{
+			currentModel = (currentModel + 1) % NUM_VOX_FILES; // Cycle between models
+		}
+
+		if (IsKeyPressed(KEY_RIGHT))
+		{
+			currentModel++;
+			if (currentModel >= NUM_VOX_FILES) currentModel = 0;
+		}
+		else if (IsKeyPressed(KEY_LEFT))
+		{
+			currentModel--;
+			if (currentModel < 0) currentModel = NUM_VOX_FILES - 1;
+		}
+
+		//----------------------------------------------------------------------------------
+		// Draw
+		//----------------------------------------------------------------------------------
+		BeginDrawing();
+
+		ClearBackground(RAYWHITE);
+
+		//Display model
+		BeginMode3D(camera);
+
+		Vector3 rotAxis = { 1,0,0 };
+		Vector3 scale = { 1,1,1 };
+
+
+		DrawModelEx(models[currentModel], position, rotAxis, 0, scale, WHITE);
+		//DrawModelWiresEx(models[currentModel], position, rotAxis, -90.0f, scale, BLACK);
+
+		DrawGrid(10, 1.0);
+
+		EndMode3D();
+
+		//Display debug infos
+		DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f));
+		DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f));
+		DrawText("MOUSE LEFT BUTTON to CYCLE VOX MODELS", 40, 410, 10, BLUE);
+
+		DrawText(GetFileName(szVoxFiles[currentModel]), 100, 10, 20, DARKBLUE);
+
+		EndDrawing();
+		//----------------------------------------------------------------------------------
+	}
+
+	// De-Initialization
+	//--------------------------------------------------------------------------------------
+
+	// Unload models data (GPU VRAM)
+	for (int i = 0; i < NUM_VOX_FILES; i++) UnloadModel(models[i]);
+
+	CloseWindow();          // Close window and OpenGL context
+	//--------------------------------------------------------------------------------------
+
+	return 0;
+}
+
+

二进制
examples/models/resources/vox/chr_knight.vox


二进制
examples/models/resources/vox/chr_sword.vox


二进制
examples/models/resources/vox/monu9.vox


+ 387 - 0
projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj

@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug.DLL|Win32">
+      <Configuration>Debug.DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug.DLL|x64">
+      <Configuration>Debug.DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release.DLL|Win32">
+      <Configuration>Release.DLL</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release.DLL|x64">
+      <Configuration>Release.DLL</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{2F1B955B-275E-4D8E-8864-06FEC44D7912}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>models_mesh_magicavoxel_loading</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+    <ProjectName>models_mesh_magicavoxel_loading</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
+    <LocalDebuggerWorkingDirectory>$(SolutionDir)..\..\examples\models</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PostBuildEvent>
+      <Command>xcopy /y /d  "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
+      <Message>Copy Debug DLL to output directory</Message>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <CompileAs>CompileAsC</CompileAs>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <PostBuildEvent>
+      <Command>xcopy /y /d  "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
+      <Message>Copy Debug DLL to output directory</Message>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+      <RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+      <RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+      <RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+    </Link>
+    <PostBuildEvent>
+      <Command>xcopy /y /d  "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
+    </PostBuildEvent>
+    <PostBuildEvent>
+      <Message>Copy Release DLL to output directory</Message>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <CompileAs>CompileAsC</CompileAs>
+      <RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
+    </Link>
+    <PostBuildEvent>
+      <Command>xcopy /y /d  "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"</Command>
+    </PostBuildEvent>
+    <PostBuildEvent>
+      <Message>Copy Release DLL to output directory</Message>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\raylib\raylib.vcxproj">
+      <Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\examples\models\models_magicavoxel_loading.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 19 - 0
projects/VS2019/raylib.sln

@@ -275,6 +275,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rlgl_standalone", "examples
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_split_screen", "examples\core_split_screen.vcxproj", "{946A1700-C7AA-46F0-AEF2-67C98B5722AC}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_mesh_magicavoxel_loading", "examples\models_mesh_magicavoxel_loading.vcxproj", "{2F1B955B-275E-4D8E-8864-06FEC44D7912}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug.DLL|x64 = Debug.DLL|x64
@@ -2283,6 +2285,22 @@ Global
 		{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x64.Build.0 = Release|x64
 		{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.ActiveCfg = Release|Win32
 		{946A1700-C7AA-46F0-AEF2-67C98B5722AC}.Release|x86.Build.0 = Release|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x64.ActiveCfg = Debug|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x64.Build.0 = Debug|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x86.ActiveCfg = Debug|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Debug|x86.Build.0 = Debug|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x64.Build.0 = Release.DLL|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x64.ActiveCfg = Release|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x64.Build.0 = Release|x64
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.ActiveCfg = Release|Win32
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912}.Release|x86.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -2422,6 +2440,7 @@ Global
 		{6237BEDE-BAAA-4A06-9C5E-8089BAA14C8B} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
 		{C8765523-58F8-4C8E-9914-693396F6F0FF} = {E9D708A5-9C1F-4B84-A795-C5F191801762}
 		{946A1700-C7AA-46F0-AEF2-67C98B5722AC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
+		{2F1B955B-275E-4D8E-8864-06FEC44D7912} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}

+ 1 - 0
src/config.h

@@ -182,6 +182,7 @@
 #define SUPPORT_FILEFORMAT_MTL      1
 #define SUPPORT_FILEFORMAT_IQM      1
 #define SUPPORT_FILEFORMAT_GLTF     1
+#define SUPPORT_FILEFORMAT_VOX      1
 // Support procedural mesh generation functions, uses external par_shapes.h library
 // NOTE: Some generated meshes DO NOT include generated texture coordinates
 #define SUPPORT_MESH_GENERATION     1

+ 771 - 0
src/external/vox_loader.h

@@ -0,0 +1,771 @@
+/*
+   The MIT License (MIT)
+
+   Copyright (c) 2021 Johann Nadalutti.
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy
+   of this software and associated documentation files (the "Software"), to deal
+   in the Software without restriction, including without limitation the rights
+   to use, copy, modify, merge, publish, distribute, sublicense, 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:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   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 IN
+   THE SOFTWARE.
+
+
+	vox_loader - v1.00
+			 no warranty implied; use at your own risk
+
+	Do this:
+	#define VOX_LOADER_INCLUDE__H
+	before you include this file in* one* C or C++ file to create the implementation.
+
+	// i.e. it should look like this:
+	#include ...
+	#include ...
+	#include ...
+	#define VOX_LOADER_INCLUDE__H
+	#include "magicavoxel_loader.h"
+
+revision history:
+	1.00  (2021-09-03)	first released version
+
+*/
+
+
+#ifndef VOX_LOADER_H
+#define VOX_LOADER_H
+
+
+#include <string.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VOX_SUCCESS (0)
+#define VOX_ERROR_FILE_NOT_FOUND (-1)
+#define VOX_ERROR_INVALID_FORMAT (-2)
+#define VOX_ERROR_FILE_VERSION_TOO_OLD (-3)
+
+	typedef struct
+	{
+		int* array;
+		int used, size;
+	} ArrayInt;
+
+	typedef struct
+	{
+		Vector3* array;
+		int used, size;
+	} ArrayVector3;
+
+	typedef struct
+	{
+		Color* array;
+		int used, size;
+	} ArrayColor;
+
+	typedef struct
+	{
+		unsigned short* array;
+		int used, size;
+	} ArrayUShort;
+
+
+	// A chunk that contain voxels
+	typedef struct
+	{
+		unsigned char* m_array; //If Sparse != null
+		int arraySize; //Size for m_array in bytes (DEBUG ONLY)
+	} CubeChunk3D;
+
+	// Array for voxels
+	// Array is divised into chunks of CHUNKSIZE*CHUNKSIZE*CHUNKSIZE voxels size
+	typedef struct
+	{
+		//Array size in voxels
+		int sizeX;
+		int sizeY;
+		int sizeZ;
+
+		//Chunks size into array (array is divised into chunks)
+		int chunksSizeX;
+		int chunksSizeY;
+		int chunksSizeZ;
+
+		//Chunks array
+		CubeChunk3D* m_arrayChunks;
+		int arrayChunksSize; //Size for m_arrayChunks in bytes (DEBUG ONLY)
+
+		int ChunkFlattenOffset;
+		int chunksAllocated;
+		int chunksTotal;
+
+		//Arrays for mesh build
+		ArrayVector3 vertices;
+		ArrayUShort indices;
+		ArrayColor colors;
+
+		//Palette for voxels
+		Color palette[256];
+
+	} VoxArray3D;
+
+
+	// Functions
+	extern int Vox_LoadFileName(const char* pszfileName, VoxArray3D* voxarray);
+	extern void Vox_FreeArrays(VoxArray3D* voxarray);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+////   end header file   /////////////////////////////////////////////////////
+#endif // VOX_LOADER_H
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////
+//									Implementation
+///////////////////////////////////////////////////////////////////////////////////////////// 
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef VOX_LOADER_IMPLEMENTATION
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// ArrayInt helper
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void initArrayInt(ArrayInt* a, int initialSize)
+{
+	a->array = MemAlloc(initialSize * sizeof(int));
+	a->used = 0;
+	a->size = initialSize;
+}
+
+void insertArrayInt(ArrayInt* a, int element)
+{
+	if (a->used == a->size)
+	{
+		a->size *= 2;
+		a->array = MemRealloc(a->array, a->size * sizeof(int));
+	}
+	a->array[a->used++] = element;
+}
+
+void freeArrayInt(ArrayInt* a)
+{
+	MemFree(a->array);
+	a->array = NULL;
+	a->used = a->size = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// ArrayUShort helper
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void initArrayUShort(ArrayUShort* a, int initialSize)
+{
+	a->array = MemAlloc(initialSize * sizeof(unsigned short));
+	a->used = 0;
+	a->size = initialSize;
+}
+
+void insertArrayUShort(ArrayUShort* a, unsigned short element)
+{
+	if (a->used == a->size)
+	{
+		a->size *= 2;
+		a->array = MemRealloc(a->array, a->size * sizeof(unsigned short));
+	}
+	a->array[a->used++] = element;
+}
+
+void freeArrayUShort(ArrayUShort* a)
+{
+	MemFree(a->array);
+	a->array = NULL;
+	a->used = a->size = 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// ArrayVector3 helper
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void initArrayVector3(ArrayVector3* a, int initialSize)
+{
+	a->array = MemAlloc(initialSize * sizeof(Vector3));
+	a->used = 0;
+	a->size = initialSize;
+}
+
+void insertArrayVector3(ArrayVector3* a, Vector3 element)
+{
+	if (a->used == a->size)
+	{
+		a->size *= 2;
+		a->array = MemRealloc(a->array, a->size * sizeof(Vector3));
+	}
+	a->array[a->used++] = element;
+}
+
+void freeArrayVector3(ArrayVector3* a)
+{
+	MemFree(a->array);
+	a->array = NULL;
+	a->used = a->size = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// ArrayColor helper
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void initArrayColor(ArrayColor* a, int initialSize)
+{
+	a->array = MemAlloc(initialSize * sizeof(Color));
+	a->used = 0;
+	a->size = initialSize;
+}
+
+void insertArrayColor(ArrayColor* a, Color element)
+{
+	if (a->used == a->size)
+	{
+		a->size *= 2;
+		a->array = MemRealloc(a->array, a->size * sizeof(Color));
+	}
+	a->array[a->used++] = element;
+}
+
+void freeArrayColor(ArrayColor* a)
+{
+	MemFree(a->array);
+	a->array = NULL;
+	a->used = a->size = 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Vox Loader
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+#define CHUNKSIZE 16 // chunk size (CHUNKSIZE*CHUNKSIZE*CHUNKSIZE) in voxels 
+#define CHUNKSIZE_OPSHIFT 4 // 1<<4=16 -> Warning depend of CHUNKSIZE
+#define CHUNK_FLATTENOFFSET_OPSHIFT 8  //Warning depend of CHUNKSIZE
+
+//
+// used right handed system and CCW face
+// 
+// indexes for voxelcoords, per face orientation
+//
+
+//#      Y
+//#      |
+//#      o----X
+//#     /
+//#    Z     2------------3
+//#         /|           /|
+//#        6------------7 |
+//#        | |          | |
+//#        |0 ----------|- 1
+//#        |/           |/
+//#        4------------5
+
+// 
+// CCW
+const int fv[6][4] = {
+	{0, 2, 6, 4 }, //-X
+	{5, 7, 3, 1 }, //+X
+	{0, 4, 5, 1 }, //-y
+	{6, 2, 3, 7 }, //+y
+	{1, 3, 2, 0 }, //-Z
+	{4, 6, 7, 5 } };//+Z
+
+
+const Vector3 SolidVertex[] = {
+	{0, 0, 0},   //0
+	{1, 0, 0},   //1
+	{0, 1, 0},   //2
+	{1, 1, 0},   //3
+	{0, 0, 1},   //4
+	{1, 0, 1},   //5
+	{0, 1, 1},   //6
+	{1, 1, 1} }; //7
+
+
+
+
+
+// Allocated VoxArray3D size
+void Vox_AllocArray(VoxArray3D* voxarray, int _sx, int _sy, int _sz)
+{
+	int sx = _sx + ((CHUNKSIZE - (_sx % CHUNKSIZE)) % CHUNKSIZE);
+	int sy = _sy + ((CHUNKSIZE - (_sy % CHUNKSIZE)) % CHUNKSIZE);
+	int sz = _sz + ((CHUNKSIZE - (_sz % CHUNKSIZE)) % CHUNKSIZE);
+
+	int chx = sx >> CHUNKSIZE_OPSHIFT; //Chunks Count in X
+	int chy = sy >> CHUNKSIZE_OPSHIFT; //Chunks Count in Y
+	int chz = sz >> CHUNKSIZE_OPSHIFT; //Chunks Count in Z
+
+	//VoxArray3D* parray = (VoxArray3D*)MemAlloc(sizeof(VoxArray3D));
+	voxarray->sizeX = sx;
+	voxarray->sizeY = sy;
+	voxarray->sizeZ = sz;
+
+	voxarray->chunksSizeX = chx;
+	voxarray->chunksSizeY = chy;
+	voxarray->chunksSizeZ = chz;
+
+	voxarray->ChunkFlattenOffset = (chy * chz); //m_arrayChunks[(x * (sy*sz)) + (z * sy) + y]
+
+	//Alloc chunks array
+	int size = sizeof(CubeChunk3D) * chx * chy * chz;
+	voxarray->m_arrayChunks = MemAlloc(size);
+	voxarray->arrayChunksSize = size;
+
+
+	//Init chunks array
+	size = chx * chy * chz;
+	voxarray->chunksTotal = size;
+	voxarray->chunksAllocated = 0;
+
+	for (int i = 0; i < size; i++)
+	{
+		voxarray->m_arrayChunks[i].m_array = 0;
+		voxarray->m_arrayChunks[i].arraySize = 0;
+	}
+
+	return voxarray;
+}
+
+// Set voxel ID from its position into VoxArray3D
+void Vox_SetVoxel(VoxArray3D* voxarray, int x, int y, int z, unsigned char id)
+{
+	//Get chunk from array pos
+	int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE;
+	int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE;
+	int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE;
+	int offset = (chX * voxarray->ChunkFlattenOffset) + (chZ * voxarray->chunksSizeY) + chY;
+
+	//if (offset > voxarray->arrayChunksSize)
+	//{
+	//	TraceLog(LOG_ERROR, "Out of array");
+	//}
+
+	CubeChunk3D* chunk = &voxarray->m_arrayChunks[offset];
+
+	//Set Chunk
+	chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE);
+	chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE);
+	chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE);
+
+	if (chunk->m_array == 0)
+	{
+		int size = CHUNKSIZE * CHUNKSIZE * CHUNKSIZE;
+		chunk->m_array = MemAlloc(size);
+		chunk->arraySize = size;
+		//memset(chunk->m_array, 0, size);
+
+		voxarray->chunksAllocated++;
+	}
+
+	offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY;
+
+	//if (offset > chunk->arraySize)
+	//{
+	//	TraceLog(LOG_ERROR, "Out of array");
+	//}
+
+	chunk->m_array[offset] = id;
+
+}
+
+// Get voxel ID from its position into VoxArray3D
+unsigned char Vox_GetVoxel(VoxArray3D* voxarray, int x, int y, int z)
+{
+	if (x < 0 || y < 0 || z < 0)
+		return 0;
+
+	if (x >= voxarray->sizeX || y >= voxarray->sizeY || z >= voxarray->sizeZ)
+		return 0;
+
+
+	//Get chunk from array pos
+	int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE;
+	int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE;
+	int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE;
+	int offset = (chX * voxarray->ChunkFlattenOffset) + (chZ * voxarray->chunksSizeY) + chY;
+
+	//if (offset > voxarray->arrayChunksSize)
+	//{
+	//	TraceLog(LOG_ERROR, "Out of array");
+	//}
+
+	CubeChunk3D* chunk = &voxarray->m_arrayChunks[offset];
+
+	//Set Chunk
+	chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE);
+	chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE);
+	chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE);
+
+	if (chunk->m_array == 0)
+	{
+		return 0;
+	}
+
+	offset = (chX << CHUNK_FLATTENOFFSET_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY;
+
+	//if (offset > chunk->arraySize)
+	//{
+	//	TraceLog(LOG_ERROR, "Out of array");
+	//}
+	return chunk->m_array[offset];
+
+}
+
+// Calc visibles faces from a voxel position
+unsigned char Vox_CalcFacesVisible(VoxArray3D* pvoxArray, int cx, int cy, int cz)
+{
+	unsigned char idXm1 = Vox_GetVoxel(pvoxArray, cx - 1, cy, cz);
+	unsigned char idXp1 = Vox_GetVoxel(pvoxArray, cx + 1, cy, cz);
+
+	unsigned char idYm1 = Vox_GetVoxel(pvoxArray, cx, cy - 1, cz);
+	unsigned char idYp1 = Vox_GetVoxel(pvoxArray, cx, cy + 1, cz);
+
+	unsigned char idZm1 = Vox_GetVoxel(pvoxArray, cx, cy, cz - 1);
+	unsigned char idZp1 = Vox_GetVoxel(pvoxArray, cx, cy, cz + 1);
+
+	unsigned char byVFMask = 0;
+
+	//#-x
+	if (idXm1 == 0)
+		byVFMask |= (1 << 0);
+
+	//#+x
+	if (idXp1 == 0)
+		byVFMask |= (1 << 1);
+
+	//#-y
+	if (idYm1 == 0)
+		byVFMask |= (1 << 2);
+
+	//#+y
+	if (idYp1 == 0)
+		byVFMask |= (1 << 3);
+
+	//#-z
+	if (idZm1 == 0)
+		byVFMask |= (1 << 4);
+
+	//#+z
+	if (idZp1 == 0)
+		byVFMask |= (1 << 5);
+
+	return byVFMask;
+}
+
+// Get a vertex position from a voxel's corner
+Vector3 Vox_GetVertexPosition(int _wcx, int _wcy, int _wcz, int _nNumVertex)
+{
+	float scale = 0.25;
+	Vector3 vtx = SolidVertex[_nNumVertex];
+	vtx.x = (vtx.x + _wcx) * scale;
+	vtx.y = (vtx.y + _wcy) * scale;
+	vtx.z = (vtx.z + _wcz) * scale;
+	return vtx;
+}
+
+// Build a voxel vertices/colors/indices
+void Vox_Build_Voxel(VoxArray3D* pvoxArray, int x, int y, int z, int matID)
+{
+
+	unsigned char byVFMask = Vox_CalcFacesVisible(pvoxArray, x, y, z);
+
+	if (byVFMask == 0)
+		return;
+
+	int i, j;
+	Vector3 vertComputed[8];
+	int bVertexComputed[8];
+	memset(vertComputed, 0, sizeof(vertComputed));
+	memset(bVertexComputed, 0, sizeof(bVertexComputed));
+
+
+	//For each Cube's faces
+	for (i = 0; i < 6; i++) // 6 faces
+	{
+		if ((byVFMask & (1 << i)) != 0)	//If face is visible
+		{
+			for (j = 0; j < 4; j++)   // 4 corners
+			{
+				int  nNumVertex = fv[i][j];  //Face,Corner
+				if (bVertexComputed[nNumVertex] == 0) //if never calc
+				{
+					bVertexComputed[nNumVertex] = 1;
+					vertComputed[nNumVertex] = Vox_GetVertexPosition(x, y, z, nNumVertex);
+				}
+			}
+		}
+	}
+
+	//Add face
+	for (i = 0; i < 6; i++)// 6 faces
+	{
+		if ((byVFMask & (1 << i)) == 0)
+			continue; //Face invisible
+
+		int v0 = fv[i][0];  //Face, Corner
+		int v1 = fv[i][1];  //Face, Corner
+		int v2 = fv[i][2];  //Face, Corner
+		int v3 = fv[i][3];  //Face, Corner
+
+		//Arrays
+		int idx = pvoxArray->vertices.used;
+		insertArrayVector3(&pvoxArray->vertices, vertComputed[v0]);
+		insertArrayVector3(&pvoxArray->vertices, vertComputed[v1]);
+		insertArrayVector3(&pvoxArray->vertices, vertComputed[v2]);
+		insertArrayVector3(&pvoxArray->vertices, vertComputed[v3]);
+
+		Color col = pvoxArray->palette[matID];
+
+		insertArrayColor(&pvoxArray->colors, col);
+		insertArrayColor(&pvoxArray->colors, col);
+		insertArrayColor(&pvoxArray->colors, col);
+		insertArrayColor(&pvoxArray->colors, col);
+
+
+		//v0 - v1 - v2, v0 - v2 - v3
+		insertArrayUShort(&pvoxArray->indices, idx + 0);
+		insertArrayUShort(&pvoxArray->indices, idx + 2);
+		insertArrayUShort(&pvoxArray->indices, idx + 1);
+
+		insertArrayUShort(&pvoxArray->indices, idx + 0);
+		insertArrayUShort(&pvoxArray->indices, idx + 3);
+		insertArrayUShort(&pvoxArray->indices, idx + 2);
+
+
+
+	}
+
+}
+
+// MagicaVoxel *.vox file format Loader
+int Vox_LoadFileName(const char* pszfileName, VoxArray3D* voxarray)
+{
+
+	//////////////////////////////////////////////////
+	//Read VOX file
+	//4 bytes: magic number ('V' 'O' 'X' 'space' )
+	//4 bytes: version number (current version is 150 )
+
+	unsigned long signature;
+
+	unsigned long readed = 0;
+	unsigned char* fileData;
+	fileData = LoadFileData(pszfileName, &readed);
+	if (fileData == 0)
+	{
+		return VOX_ERROR_FILE_NOT_FOUND;
+	}
+
+	unsigned char* fileDataPtr = fileData;
+	unsigned char* endfileDataPtr = fileData + readed;
+
+	signature = *((unsigned long*)fileDataPtr);
+	fileDataPtr += sizeof(unsigned long);
+
+	if (signature != 0x20584F56) //56 4F 58 20
+	{
+		//TraceLog(LOG_ERROR, "Not an MagicaVoxel File format");
+		return VOX_ERROR_INVALID_FORMAT;
+	}
+
+	unsigned long version;
+
+	version = *((unsigned long*)fileDataPtr);
+	fileDataPtr += sizeof(unsigned long);
+
+	if (version < 150)
+	{
+		//TraceLog(LOG_ERROR, "MagicaVoxel version too old");
+		return VOX_ERROR_FILE_VERSION_TOO_OLD;
+	}
+
+
+	// header
+	//4 bytes: chunk id
+	//4 bytes: size of chunk contents (n)
+	//4 bytes: total size of children chunks(m)
+
+	//// chunk content
+	//n bytes: chunk contents
+
+	//// children chunks : m bytes
+	//{ child chunk 0 }
+	//{ child chunk 1 }
+	unsigned long sizeX, sizeY, sizeZ;
+	sizeX = sizeY = sizeZ = 0;
+	unsigned long numVoxels = 0;
+	int offsetX, offsetY, offsetZ;
+	offsetX = offsetY = offsetZ = 0;
+
+	while (fileDataPtr < endfileDataPtr)
+	{
+		char szChunkName[5];
+		memcpy(szChunkName, fileDataPtr, 4);
+		szChunkName[4] = 0;
+		fileDataPtr += 4;
+
+		unsigned long chunkSize = *((unsigned long*)fileDataPtr);
+		fileDataPtr += sizeof(unsigned long);
+
+		unsigned long chunkTotalChildSize = *((unsigned long*)fileDataPtr);
+		fileDataPtr += sizeof(unsigned long);
+
+
+		if (strcmp(szChunkName, "SIZE") == 0)
+		{
+			//(4 bytes x 3 : x, y, z ) 
+			sizeX = *((unsigned long*)fileDataPtr);
+			fileDataPtr += sizeof(unsigned long);
+
+			sizeY = *((unsigned long*)fileDataPtr);
+			fileDataPtr += sizeof(unsigned long);
+
+			sizeZ = *((unsigned long*)fileDataPtr);
+			fileDataPtr += sizeof(unsigned long);
+
+			//Alloc vox array
+			Vox_AllocArray(voxarray, sizeX, sizeY, sizeZ);
+		}
+		else if (strcmp(szChunkName, "XYZI") == 0)
+		{
+			unsigned char vx, vy, vz, vi;
+
+			//(numVoxels : 4 bytes )
+			//(each voxel: 1 byte x 4 : x, y, z, colorIndex ) x numVoxels
+			numVoxels = *((unsigned long*)fileDataPtr);
+			fileDataPtr += sizeof(unsigned long);
+
+			while (numVoxels > 0)
+			{
+				vx = *((unsigned char*)fileDataPtr++);
+				vy = *((unsigned char*)fileDataPtr++);
+				vz = *((unsigned char*)fileDataPtr++);
+				vi = *((unsigned char*)fileDataPtr++);
+
+				Vox_SetVoxel(voxarray, vx, vy, vz, vi);
+
+				numVoxels--;
+			}
+		}
+		else if (strcmp(szChunkName, "RGBA") == 0)
+		{
+			Color col;
+
+			//(each pixel: 1 byte x 4 : r, g, b, a ) x 256
+			for (int i = 0; i < 256 - 1; i++)
+			{
+				col.r = *((unsigned char*)fileDataPtr++);
+				col.g = *((unsigned char*)fileDataPtr++);
+				col.b = *((unsigned char*)fileDataPtr++);
+				col.a = *((unsigned char*)fileDataPtr++);
+
+				voxarray->palette[i + 1] = col;
+			}
+
+		}
+		else
+		{
+			fileDataPtr += chunkSize;
+		}
+	}
+
+	//TraceLog(LOG_INFO, TextFormat("Vox Size : %dx%dx%d", sizeX, sizeY, sizeZ));
+
+	//TraceLog(LOG_INFO, TextFormat("Vox Chunks Count : %d/%d", pvoxArray->chunksAllocated, pvoxArray->chunksTotal));
+
+
+	//////////////////////////////////////////////////////////
+	// Building Mesh
+	//   TODO compute globals indices array
+
+	//TraceLog(LOG_INFO, TextFormat("Building VOX Mesh : %s", pszfileName));
+
+	// Init Arrays
+	initArrayVector3(&voxarray->vertices, 3 * 1024);
+	initArrayUShort(&voxarray->indices, 3 * 1024);
+	initArrayColor(&voxarray->colors, 3 * 1024);
+
+	// Create vertices and indices buffers
+	int x, y, z;
+
+	for (x = 0; x <= voxarray->sizeX; x++)
+	{
+		for (z = 0; z <= voxarray->sizeZ; z++)
+		{
+			for (y = 0; y <= voxarray->sizeY; y++)
+			{
+				unsigned char matID = Vox_GetVoxel(voxarray, x, y, z);
+				if (matID != 0)
+					Vox_Build_Voxel(voxarray, x, y, z, matID);
+			}
+		}
+	}
+
+
+
+	return VOX_SUCCESS;
+}
+
+void Vox_FreeArrays(VoxArray3D* voxarray)
+{
+	//Free chunks
+	if (voxarray->m_arrayChunks != 0)
+	{
+		for (int i = 0; i < voxarray->chunksTotal; i++)
+		{
+			CubeChunk3D* chunk = &voxarray->m_arrayChunks[i];
+			if (chunk->m_array != 0)
+			{
+				chunk->arraySize = 0;
+				MemFree(chunk->m_array);
+			}
+		}
+
+		MemFree(voxarray->m_arrayChunks);
+		voxarray->m_arrayChunks = 0;
+		voxarray->arrayChunksSize = 0;
+
+		voxarray->chunksSizeX = voxarray->chunksSizeY = voxarray->chunksSizeZ = 0;
+		voxarray->chunksTotal = 0;
+		voxarray->chunksAllocated = 0;
+		voxarray->ChunkFlattenOffset = 0;
+		voxarray->sizeX = voxarray->sizeY = voxarray->sizeZ = 0;
+	}
+
+	//Free arrays
+	freeArrayVector3(&voxarray->vertices);
+	freeArrayUShort(&voxarray->indices);
+	freeArrayColor(&voxarray->colors);
+}
+
+#endif //VOX_LOADER_IMPLEMENTATION

+ 110 - 0
src/models.c

@@ -8,6 +8,8 @@
 *   #define SUPPORT_FILEFORMAT_MTL
 *   #define SUPPORT_FILEFORMAT_IQM
 *   #define SUPPORT_FILEFORMAT_GLTF
+*   #define SUPPORT_FILEFORMAT_VOX
+* 
 *       Selected desired fileformats to be supported for model data loading.
 *
 *   #define SUPPORT_MESH_GENERATION
@@ -71,6 +73,11 @@
     #include "external/stb_image.h"     // glTF texture images loading
 #endif
 
+#if defined(SUPPORT_FILEFORMAT_VOX)
+    #define VOX_LOADER_IMPLEMENTATION
+    #include "external/vox_loader.h"        // vox file format loading
+#endif
+
 #if defined(SUPPORT_MESH_GENERATION)
     #define PAR_MALLOC(T, N) ((T*)RL_MALLOC(N*sizeof(T)))
     #define PAR_CALLOC(T, N) ((T*)RL_CALLOC(N*sizeof(T), 1))
@@ -131,6 +138,9 @@ static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount);
 static bool ReadGLTFValue(cgltf_accessor *acc, unsigned int index, void *variable);
 static void *ReadGLTFValuesAs(cgltf_accessor *acc, cgltf_component_type type, bool adjustOnDownCasting);
 #endif
+#if defined(SUPPORT_FILEFORMAT_VOX)
+static Model LoadVOX(const char* filename);     //Load VOX mesh data
+#endif
 
 //----------------------------------------------------------------------------------
 // Module Functions Definition
@@ -718,6 +728,9 @@ Model LoadModel(const char *fileName)
 #if defined(SUPPORT_FILEFORMAT_GLTF)
     if (IsFileExtension(fileName, ".gltf;.glb")) model = LoadGLTF(fileName);
 #endif
+#if defined(SUPPORT_FILEFORMAT_VOX)
+    if (IsFileExtension(fileName, ".vox")) model = LoadVOX(fileName);
+#endif
 
     // Make sure model transform is set to identity matrix!
     model.transform = MatrixIdentity();
@@ -5469,3 +5482,100 @@ static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount)
 }
 
 #endif
+
+#if defined(SUPPORT_FILEFORMAT_VOX)
+// Load OBJ mesh data
+static Model LoadVOX(const char* fileName)
+{
+    Model model = { 0 };
+    int nbvertices = 0;
+    int meshescount = 0;
+
+    //////////////////////////////////
+    // Load MagicaVoxel fileformat
+    
+    VoxArray3D voxarray;
+    int ret = Vox_LoadFileName(fileName, &voxarray);
+
+    if (ret != VOX_SUCCESS)
+    {
+        TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX data", fileName);
+        return model;
+    }
+    else
+    {
+        // Compute meshes count
+        nbvertices = voxarray.vertices.used;
+        meshescount = 1 + (nbvertices / 65536);
+
+        TRACELOG(LOG_INFO, "MODEL: [%s] VOX data loaded successfully : %i vertices/%i meshes", fileName, nbvertices, meshescount);
+    }
+
+    //////////////////////////////////
+    // Build model
+
+    // Build Models from meshes
+    model.transform = MatrixIdentity();
+
+    model.meshCount = meshescount;
+    model.meshes = (Mesh*)MemAlloc(model.meshCount * sizeof(Mesh));
+
+    model.meshMaterial = (int*)MemAlloc(model.meshCount * sizeof(int));
+
+    model.materialCount = 1;
+    model.materials = (Material*)MemAlloc(model.materialCount * sizeof(Material));
+    model.materials[0] = LoadMaterialDefault();
+
+
+    // Init model's meshes
+    int verticesRemain = voxarray.vertices.used;
+    int verticesMax = 65532; //5461 voxels x 12 vertices per voxel -> 65532 (must be inf 65536)
+
+    Vector3* pvertices = voxarray.vertices.array;	//6*4=12 vertices per voxel
+    Color* pcolors = voxarray.colors.array;
+    unsigned short* pindices = voxarray.indices.array;	//5461 * 6 * 6 -> 196596 indices max per mesh
+
+    int size;
+
+    for (int idxMesh = 0; idxMesh < meshescount; idxMesh++)
+    {
+        Mesh* pmesh = &model.meshes[idxMesh];
+        memset(pmesh, 0, sizeof(Mesh));
+
+        // Copy Vertices
+        pmesh->vertexCount = (int)fmin(verticesMax, verticesRemain);
+
+        size = pmesh->vertexCount * sizeof(float) * 3;
+        pmesh->vertices = MemAlloc(size);
+        memcpy(pmesh->vertices, pvertices, size);
+
+        //Copy Indices TODO compute globals indices array
+        size = voxarray.indices.used * sizeof(unsigned short);
+        pmesh->indices = MemAlloc(size);
+        memcpy(pmesh->indices, pindices, size);
+
+        pmesh->triangleCount = (pmesh->vertexCount / 4) * 2;
+
+        // Copy Colors
+        size = pmesh->vertexCount * sizeof(Color);
+        pmesh->colors = MemAlloc(size);
+        memcpy(pmesh->colors, pcolors, size);
+
+        // First material index
+        model.meshMaterial[idxMesh] = 0;
+
+        // Build GPU mesh
+        UploadMesh(pmesh, false);
+
+        //Next
+        verticesRemain -= verticesMax;
+        pvertices += verticesMax;
+        pcolors += verticesMax;
+    }
+
+    //Free arrays
+    Vox_FreeArrays(&voxarray);
+
+    return model;
+}
+#endif