summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorprocfxgen <[email protected]>2021-09-04 19:55:09 +0200
committerGitHub <[email protected]>2021-09-04 19:55:09 +0200
commitdfc465ca6d5a22abe558c15af97376a955dc1954 (patch)
tree8b2c78b22e4339e2613ff0cac01da8f0233a2a17
parent93168304cd377fabec9dfa88469f2cc635cd6326 (diff)
downloadraylib-dfc465ca6d5a22abe558c15af97376a955dc1954.tar.gz
raylib-dfc465ca6d5a22abe558c15af97376a955dc1954.zip
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
-rw-r--r--examples/CMakeLists.txt2
-rw-r--r--examples/Makefile3
-rw-r--r--examples/models/models_magicavoxel_loading.c153
-rw-r--r--examples/models/resources/vox/chr_knight.voxbin0 -> 31031 bytes
-rw-r--r--examples/models/resources/vox/chr_sword.voxbin0 -> 30775 bytes
-rw-r--r--examples/models/resources/vox/monu9.voxbin0 -> 160767 bytes
-rw-r--r--projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj387
-rw-r--r--projects/VS2019/raylib.sln19
-rw-r--r--src/config.h1
-rw-r--r--src/external/vox_loader.h771
-rw-r--r--src/models.c110
11 files changed, 1445 insertions, 1 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index ad391edd..d102eb4c 100644
--- a/examples/CMakeLists.txt
+++ b/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)
diff --git a/examples/Makefile b/examples/Makefile
index 5abf0c70..f5cb2175 100644
--- a/examples/Makefile
+++ b/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 \
diff --git a/examples/models/models_magicavoxel_loading.c b/examples/models/models_magicavoxel_loading.c
new file mode 100644
index 00000000..bb1389d6
--- /dev/null
+++ b/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;
+}
+
+
diff --git a/examples/models/resources/vox/chr_knight.vox b/examples/models/resources/vox/chr_knight.vox
new file mode 100644
index 00000000..c921bf5c
--- /dev/null
+++ b/examples/models/resources/vox/chr_knight.vox
Binary files differ
diff --git a/examples/models/resources/vox/chr_sword.vox b/examples/models/resources/vox/chr_sword.vox
new file mode 100644
index 00000000..05fc4826
--- /dev/null
+++ b/examples/models/resources/vox/chr_sword.vox
Binary files differ
diff --git a/examples/models/resources/vox/monu9.vox b/examples/models/resources/vox/monu9.vox
new file mode 100644
index 00000000..fd771112
--- /dev/null
+++ b/examples/models/resources/vox/monu9.vox
Binary files differ
diff --git a/projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj b/projects/VS2019/examples/models_mesh_magicavoxel_loading.vcxproj
new file mode 100644
index 00000000..f2e86c8a
--- /dev/null
+++ b/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> \ No newline at end of file
diff --git a/projects/VS2019/raylib.sln b/projects/VS2019/raylib.sln
index 53d2a18a..f5a4180f 100644
--- a/projects/VS2019/raylib.sln
+++ b/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}
diff --git a/src/config.h b/src/config.h
index b7358d7e..b244add6 100644
--- a/src/config.h
+++ b/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
diff --git a/src/external/vox_loader.h b/src/external/vox_loader.h
new file mode 100644
index 00000000..63f2719f
--- /dev/null
+++ b/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
diff --git a/src/models.c b/src/models.c
index b233cf2a..168ac2c3 100644
--- a/src/models.c
+++ b/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 \ No newline at end of file