From 2a8997fc4f20f964c5aa759483ae4e6a6a2bb83f Mon Sep 17 00:00:00 2001
From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com>
Date: Wed, 27 Jul 2022 12:51:41 +0200
Subject: [PATCH 01/13] Moved cuda helper libs to seperate directory
---
msvc/vs2022/cuda_voxelizer.vcxproj | 4 ++--
msvc/vs2022/cuda_voxelizer.vcxproj.filters | 19 ++++++++++---------
src/libs/{ => cuda}/helper_cuda.h | 0
src/libs/{ => cuda}/helper_string.h | 0
src/main.cpp | 5 +++--
src/util_cuda.h | 2 +-
6 files changed, 16 insertions(+), 14 deletions(-)
rename src/libs/{ => cuda}/helper_cuda.h (100%)
rename src/libs/{ => cuda}/helper_string.h (100%)
diff --git a/msvc/vs2022/cuda_voxelizer.vcxproj b/msvc/vs2022/cuda_voxelizer.vcxproj
index f926d27..b3f95d1 100644
--- a/msvc/vs2022/cuda_voxelizer.vcxproj
+++ b/msvc/vs2022/cuda_voxelizer.vcxproj
@@ -118,11 +118,11 @@ copy /y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName).exe" "$(BINARY
+
+
-
-
diff --git a/msvc/vs2022/cuda_voxelizer.vcxproj.filters b/msvc/vs2022/cuda_voxelizer.vcxproj.filters
index 6518121..933cae0 100644
--- a/msvc/vs2022/cuda_voxelizer.vcxproj.filters
+++ b/msvc/vs2022/cuda_voxelizer.vcxproj.filters
@@ -16,12 +16,6 @@
-
- cuda
-
-
- cuda
-
@@ -37,9 +31,13 @@
util
-
- util
+
+ libs\cuda
+
+ libs\cuda
+
+
@@ -48,7 +46,10 @@
{a0232da8-2097-49f4-9412-0e4223c7ba4d}
-
+
+ {f8ccb03d-e5cc-438b-96d6-5f9b5fb54160}
+
+
{ea2a8fd1-3d76-496e-9ad4-123e8f208140}
diff --git a/src/libs/helper_cuda.h b/src/libs/cuda/helper_cuda.h
similarity index 100%
rename from src/libs/helper_cuda.h
rename to src/libs/cuda/helper_cuda.h
diff --git a/src/libs/helper_string.h b/src/libs/cuda/helper_string.h
similarity index 100%
rename from src/libs/helper_string.h
rename to src/libs/cuda/helper_string.h
diff --git a/src/main.cpp b/src/main.cpp
index 3e955f8..7a9bfe9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -222,16 +222,17 @@ int main(int argc, char* argv[]) {
fprintf(stdout, "\n## TRIANGLES TO GPU TRANSFER \n");
float* device_triangles;
- // Transfer triangles to GPU using either thrust or managed cuda memory
+
+ // Transfer triangle data to GPU
if (useThrustPath) { device_triangles = meshToGPU_thrust(themesh); }
else { device_triangles = meshToGPU_managed(themesh); }
+ // Allocate memory for voxel grid
if (!useThrustPath) {
fprintf(stdout, "[Voxel Grid] Allocating %s of CUDA-managed UNIFIED memory for Voxel Grid\n", readableSize(vtable_size).c_str());
checkCudaErrors(cudaMallocManaged((void**)&vtable, vtable_size));
}
else {
- // ALLOCATE MEMORY ON HOST
fprintf(stdout, "[Voxel Grid] Allocating %s kB of page-locked HOST memory for Voxel Grid\n", readableSize(vtable_size).c_str());
checkCudaErrors(cudaHostAlloc((void**)&vtable, vtable_size, cudaHostAllocDefault));
}
diff --git a/src/util_cuda.h b/src/util_cuda.h
index 4a20899..7014c15 100644
--- a/src/util_cuda.h
+++ b/src/util_cuda.h
@@ -5,7 +5,7 @@
#include
// Cuda
#include "cuda_runtime.h"
-#include "libs/helper_cuda.h"
+#include "libs/cuda/helper_cuda.h"
// Function to check cuda requirements
bool initCuda();
\ No newline at end of file
From 7f4cdec58ba66a26ed7c63f3f1d61ef4dbe00e07 Mon Sep 17 00:00:00 2001
From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com>
Date: Wed, 27 Jul 2022 12:52:36 +0200
Subject: [PATCH 02/13] Removed VS2019 project
---
msvc/vs2019/cuda_voxelizer.sln | 27 ----
msvc/vs2019/cuda_voxelizer.vcxproj | 138 ---------------------
msvc/vs2019/cuda_voxelizer.vcxproj.filters | 55 --------
msvc/vs2019/custom_includes.props | 30 -----
4 files changed, 250 deletions(-)
delete mode 100644 msvc/vs2019/cuda_voxelizer.sln
delete mode 100644 msvc/vs2019/cuda_voxelizer.vcxproj
delete mode 100644 msvc/vs2019/cuda_voxelizer.vcxproj.filters
delete mode 100644 msvc/vs2019/custom_includes.props
diff --git a/msvc/vs2019/cuda_voxelizer.sln b/msvc/vs2019/cuda_voxelizer.sln
deleted file mode 100644
index a566caa..0000000
--- a/msvc/vs2019/cuda_voxelizer.sln
+++ /dev/null
@@ -1,27 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.271
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cuda_voxelizer", "cuda_voxelizer.vcxproj", "{D4330816-735D-4CC7-AE2A-04A0E998099E}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C52A2702-E60C-4590-9C55-C8C66CCA5BAB}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
- Release|x64 = Release|x64
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {D4330816-735D-4CC7-AE2A-04A0E998099E}.Debug|x64.ActiveCfg = Debug|x64
- {D4330816-735D-4CC7-AE2A-04A0E998099E}.Debug|x64.Build.0 = Debug|x64
- {D4330816-735D-4CC7-AE2A-04A0E998099E}.Release|x64.ActiveCfg = Release|x64
- {D4330816-735D-4CC7-AE2A-04A0E998099E}.Release|x64.Build.0 = Release|x64
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {D7628502-09E5-4B15-AB62-365471E954D4}
- EndGlobalSection
-EndGlobal
diff --git a/msvc/vs2019/cuda_voxelizer.vcxproj b/msvc/vs2019/cuda_voxelizer.vcxproj
deleted file mode 100644
index f926d27..0000000
--- a/msvc/vs2019/cuda_voxelizer.vcxproj
+++ /dev/null
@@ -1,138 +0,0 @@
-
-
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- {D4330816-735D-4CC7-AE2A-04A0E998099E}
- cuda_voxelizer
- 10.0
-
-
-
- Application
- true
- MultiByte
- v143
-
-
- Application
- false
- true
- MultiByte
- v143
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
- C:\libs\trimesh2\include;C:\libs\glm;$(IncludePath)
- C:\libs\trimesh2\lib.Win64;$(LibraryPath)
- xcopy /y "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).exe" "$(BINARY_OUTPUT_DIR)$(ProjectName).exe"
- $(ProjectName)_debug
-
-
- C:\libs\trimesh2\include;C:\libs\glm;$(IncludePath)
- C:\libs\trimesh2\lib.Win64;$(LibraryPath)
- xcopy /y "$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).exe" "$(BINARY_OUTPUT_DIR)$(ProjectName).exe"
-
-
-
- Level3
- Disabled
- WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
-
-
- true
- Console
- trimeshd.lib;cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
-
-
- copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)"
-copy "$(CudaToolkitBinDir)\cudart*.dll" "$(BINARY_OUTPUT_DIR)"
-copy /y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName).exe" "$(BINARY_OUTPUT_DIR)$(TargetName).exe"
-
-
- true
- --source-in-ptx %(AdditionalOptions)
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- Speed
- AnySuitable
- true
- false
- Strict
-
-
- true
- true
- true
- Console
- trimesh.lib;cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
-
-
- copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)"
-copy "$(CudaToolkitBinDir)\cudart*.dll" "$(BINARY_OUTPUT_DIR)"
-copy /y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName).exe" "$(BINARY_OUTPUT_DIR)$(TargetName).exe"
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/msvc/vs2019/cuda_voxelizer.vcxproj.filters b/msvc/vs2019/cuda_voxelizer.vcxproj.filters
deleted file mode 100644
index 6518121..0000000
--- a/msvc/vs2019/cuda_voxelizer.vcxproj.filters
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- util
-
-
- util
-
-
-
-
-
- cuda
-
-
- cuda
-
-
-
-
- util
-
-
-
- util
-
-
- util
-
-
- util
-
-
- util
-
-
-
-
-
-
-
- {a0232da8-2097-49f4-9412-0e4223c7ba4d}
-
-
- {ea2a8fd1-3d76-496e-9ad4-123e8f208140}
-
-
-
\ No newline at end of file
diff --git a/msvc/vs2019/custom_includes.props b/msvc/vs2019/custom_includes.props
deleted file mode 100644
index 0b0440a..0000000
--- a/msvc/vs2019/custom_includes.props
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
- D:\dev\libs\trimesh2\
- D:\dev\libs\glm\
- D:\dev\Binaries\
-
-
- $(GLM_DIR);$(TRIMESH_DIR)\include\;$(IncludePath)
- <_PropertySheetDisplayName>custom_includes
- $(TRIMESH_DIR)\lib.Win$(PlatformArchitecture).vs$(PlatformToolsetVersion);$(LibraryPath)
-
-
-
-
-
- $(BINARY_OUTPUT_DIR)
- true
-
-
- $(TRIMESH_DIR)
- true
-
-
- $(GLM_DIR)
- true
-
-
-
\ No newline at end of file
From da3cd325cd5aecfbb094c74bedf6dafecd7dd8fe Mon Sep 17 00:00:00 2001
From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com>
Date: Wed, 27 Jul 2022 12:53:47 +0200
Subject: [PATCH 03/13] Removed VS2019 mention from Readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e2eb5a8..3c114c0 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@ cmake --build . --parallel number_of_cores
### Build using Visual Studio project (Windows)
-Project solutions for Visual Studio 2019 and 2022 are provided in the `msvc`folder. They are configured for CUDA 11, but you can edit the project file to make it work with lower CUDA versions. You can edit the `custom_includes.props` file to configure the library locations, and specify a place where the resulting binaries should be placed.
+A project solution for Visual Studio 2022 is provided in the `msvc`folder. It is configured for CUDA 11, but you can edit the project file to make it work with lower CUDA versions. You can edit the `custom_includes.props` file to configure the library locations, and specify a place where the resulting binaries should be placed.
```
C:\libs\trimesh2\
From 5ac915fe9fe961770a4e6b439ed3aed61a381766 Mon Sep 17 00:00:00 2001
From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com>
Date: Tue, 16 Aug 2022 12:35:11 +0200
Subject: [PATCH 04/13] Added magicavoxel_file_writer project
---
msvc/vs2022/cuda_voxelizer.vcxproj | 2 +
msvc/vs2022/cuda_voxelizer.vcxproj.filters | 9 +
src/libs/magicavoxel_file_writer/LICENSE | 21 +
.../magicavoxel_file_writer/VoxWriter.cpp | 780 ++++++++++++++++++
src/libs/magicavoxel_file_writer/VoxWriter.h | 397 +++++++++
src/util_io.cpp | 1 +
6 files changed, 1210 insertions(+)
create mode 100644 src/libs/magicavoxel_file_writer/LICENSE
create mode 100644 src/libs/magicavoxel_file_writer/VoxWriter.cpp
create mode 100644 src/libs/magicavoxel_file_writer/VoxWriter.h
diff --git a/msvc/vs2022/cuda_voxelizer.vcxproj b/msvc/vs2022/cuda_voxelizer.vcxproj
index b3f95d1..d5c0bed 100644
--- a/msvc/vs2022/cuda_voxelizer.vcxproj
+++ b/msvc/vs2022/cuda_voxelizer.vcxproj
@@ -112,6 +112,7 @@ copy /y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName).exe" "$(BINARY
+
@@ -120,6 +121,7 @@ copy /y "$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName).exe" "$(BINARY
+
diff --git a/msvc/vs2022/cuda_voxelizer.vcxproj.filters b/msvc/vs2022/cuda_voxelizer.vcxproj.filters
index 933cae0..9c2d88e 100644
--- a/msvc/vs2022/cuda_voxelizer.vcxproj.filters
+++ b/msvc/vs2022/cuda_voxelizer.vcxproj.filters
@@ -14,6 +14,9 @@
util
+
+ libs\magicavoxel_file_writer
+
@@ -38,6 +41,9 @@
libs\cuda
+
+ libs\magicavoxel_file_writer
+
@@ -52,5 +58,8 @@
{ea2a8fd1-3d76-496e-9ad4-123e8f208140}
+
+ {e8008c56-21a7-481c-9d07-a2e13e61a713}
+
\ No newline at end of file
diff --git a/src/libs/magicavoxel_file_writer/LICENSE b/src/libs/magicavoxel_file_writer/LICENSE
new file mode 100644
index 0000000..c896581
--- /dev/null
+++ b/src/libs/magicavoxel_file_writer/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Aiekick
+
+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.
diff --git a/src/libs/magicavoxel_file_writer/VoxWriter.cpp b/src/libs/magicavoxel_file_writer/VoxWriter.cpp
new file mode 100644
index 0000000..775ec10
--- /dev/null
+++ b/src/libs/magicavoxel_file_writer/VoxWriter.cpp
@@ -0,0 +1,780 @@
+// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
+// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+// Copyright 2018 Stephane Cuillerdier @Aiekick
+
+// 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.
+
+// This File is a helper for write a vox file after 0.99 release to support
+// the world mode editor
+// just add all color with the color Index with AddColor
+// And add all voxels with the method AddVoxel with the voxel in world position, and finally save the model
+// that's all, the file was initially created for my Proecedural soft
+// "SdfMesher" cf :https://twitter.com/hashtag/sdfmesher?src=hash
+// it support just my needs for the moment, but i put here because its a basis for more i thinck
+
+#include "VoxWriter.h"
+#include
+
+//#define VERBOSE
+
+namespace vox
+{
+ DICTstring::DICTstring()
+ {
+ bufferSize = 0;
+ }
+
+ void DICTstring::write(FILE *fp)
+ {
+ bufferSize = (int32_t)buffer.size();
+ fwrite(&bufferSize, sizeof(int32_t), 1, fp);
+ fwrite(buffer.data(), sizeof(char), bufferSize, fp);
+ }
+
+ size_t DICTstring::getSize()
+ {
+ bufferSize = (int32_t)buffer.size();
+ return sizeof(int32_t) + sizeof(char) * bufferSize;
+ }
+
+ //////////////////////////////////////////////////////////////////
+
+ DICTitem::DICTitem()
+ {
+
+ }
+
+ DICTitem::DICTitem(std::string vKey, std::string vValue)
+ {
+ key.buffer = vKey;
+ value.buffer = vValue;
+ }
+
+ void DICTitem::write(FILE *fp)
+ {
+ key.write(fp);
+ value.write(fp);
+ }
+
+ size_t DICTitem::getSize()
+ {
+ return key.getSize() + value.getSize();
+ }
+
+ //////////////////////////////////////////////////////////////////
+
+ DICT::DICT()
+ {
+ count = 0;
+ }
+
+ void DICT::write(FILE *fp)
+ {
+ count = (int32_t)keys.size();
+ fwrite(&count, sizeof(int32_t), 1, fp);
+ for (int i=0;iIsOk(vFilePathName);
+
+ if (*vError == 0)
+ {
+ return vox;
+ }
+ else
+ {
+ printf("Vox file creation failed, err : %s", GetErrnoMsg(*vError).c_str());
+
+ SAFE_DELETE(vox);
+ }
+
+ return vox;
+ }
+
+ std::string VoxWriter::GetErrnoMsg(const int32_t& vError)
+ {
+ std::string res;
+
+ switch (vError)
+ {
+ case 1:
+ res = "Operation not permitted"; break;
+ case 2:
+ res = "No such file or directory"; break;
+ case 3:
+ res = "No such process"; break;
+ case 4:
+ res = "Interrupted function"; break;
+ case 5:
+ res = "I / O error"; break;
+ case 6:
+ res = "No such device or address"; break;
+ case 7:
+ res = "Argument list too long"; break;
+ case 8:
+ res = "Exec format error"; break;
+ case 9:
+ res = "Bad file number"; break;
+ case 10:
+ res = "No spawned processes"; break;
+ case 11:
+ res = "No more processes or not enough memory or maximum nesting level reached"; break;
+ case 12:
+ res = "Not enough memory"; break;
+ case 13:
+ res = "Permission denied"; break;
+ case 14:
+ res = "Bad address"; break;
+ case 16:
+ res = "Device or resource busy"; break;
+ case 17:
+ res = "File exists"; break;
+ case 18:
+ res = "Cross - device link"; break;
+ case 19:
+ res = "No such device"; break;
+ case 20:
+ res = "Not a director"; break;
+ case 21:
+ res = "Is a directory"; break;
+ case 22:
+ res = "Invalid argument"; break;
+ case 23:
+ res = "Too many files open in system"; break;
+ case 24:
+ res = "Too many open files"; break;
+ case 25:
+ res = "Inappropriate I / O control operation"; break;
+ case 27:
+ res = "File too large"; break;
+ case 28:
+ res = "No space left on device"; break;
+ case 29:
+ res = "Invalid seek"; break;
+ case 30:
+ res = "Read - only file system"; break;
+ case 31:
+ res = "Too many links"; break;
+ case 32:
+ res = "Broken pipe"; break;
+ case 33:
+ res = "Math argument"; break;
+ case 34:
+ res = "Result too large"; break;
+ case 36:
+ res = "Resource deadlock would occur"; break;
+ case 38:
+ res = "Filename too long"; break;
+ case 39:
+ res = "No locks available"; break;
+ case 40:
+ res = "Function not supported"; break;
+ case 41:
+ res = "Directory not empty"; break;
+ case 42:
+ res = "Illegal byte sequence"; break;
+ case 80:
+ res = "String was truncated"; break;
+ }
+
+ return res;
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // the limit of magicavoxel is 127 for one cube, is 127 voxels (indexs : 0 -> 126)
+ // vMaxVoxelPerCubeX,Y,Z define the limit of one cube
+ VoxWriter::VoxWriter(int32_t vMaxVoxelPerCubeX, int32_t vMaxVoxelPerCubeY, int32_t vMaxVoxelPerCubeZ)
+ {
+ MV_VERSION = 150; // the old version of MV not open another file than if version is 150 (answer by @ephtracy
+
+ ID_VOX = GetID('V', 'O', 'X', ' ');
+ ID_PACK = GetID('P', 'A', 'C', 'K');
+ ID_MAIN = GetID('M', 'A', 'I', 'N');
+ ID_SIZE = GetID('S', 'I', 'Z', 'E');
+ ID_XYZI = GetID('X', 'Y', 'Z', 'I');
+ ID_RGBA = GetID('R', 'G', 'B', 'A');
+ ID_NTRN = GetID('n', 'T', 'R', 'N');
+ ID_NGRP = GetID('n', 'G', 'R', 'P');
+ ID_NSHP = GetID('n', 'S', 'H', 'P');
+
+ maxCubeId = 0;
+
+ minCubeX = (int)1e7;
+ minCubeY = (int)1e7;
+ minCubeZ = (int)1e7;
+
+ // the limit of magicavoxel is 127 because the first is 1 not 0
+ // so this is 0 to 126
+ // index limit, size is 127
+ m_MaxVoxelPerCubeX = ct::clamp(vMaxVoxelPerCubeX, 0, 126);
+ m_MaxVoxelPerCubeY = ct::clamp(vMaxVoxelPerCubeY, 0, 126);
+ m_MaxVoxelPerCubeZ = ct::clamp(vMaxVoxelPerCubeZ, 0, 126);
+
+ maxVolume.lowerBound = 1e7f;
+ maxVolume.upperBound = 0.0f;
+ }
+
+ VoxWriter::~VoxWriter()
+ {
+
+ }
+
+ int32_t VoxWriter::IsOk(const std::string& vFilePathName)
+ {
+ if (OpenFileForWriting(vFilePathName))
+ {
+ CloseFile();
+ }
+ return lastError;
+ }
+
+ void VoxWriter::ClearVoxels()
+ {
+
+ }
+
+ void VoxWriter::ClearColors()
+ {
+
+ }
+
+ void VoxWriter::AddColor(const uint8_t& r, const uint8_t& g, const uint8_t& b, const uint8_t& a, const uint8_t& index)
+ {
+ while (colors.size() <= index)
+ colors.push_back(0);
+ colors[index] = GetID(r, g, b, a);
+ }
+
+ void VoxWriter::AddVoxel(const int32_t& vX, const int32_t& vY, const int32_t& vZ, const uint8_t& vColorIndex)
+ {
+ // cube pos
+ int32_t ox = (int32_t)std::floor((double)vX / (double)m_MaxVoxelPerCubeX);
+ int32_t oy = (int32_t)std::floor((double)vY / (double)m_MaxVoxelPerCubeY);
+ int32_t oz = (int32_t)std::floor((double)vZ / (double)m_MaxVoxelPerCubeZ);
+
+ minCubeX = ct::mini(minCubeX, ox);
+ minCubeY = ct::mini(minCubeX, oy);
+ minCubeZ = ct::mini(minCubeX, oz);
+
+ auto cube = GetCube(ox, oy, oz);
+
+ MergeVoxelInCube(vX, vY, vZ, vColorIndex, cube);
+ }
+
+ void VoxWriter::SaveToFile(const std::string& vFilePathName)
+ {
+ if (OpenFileForWriting(vFilePathName))
+ {
+ int32_t zero = 0;
+
+ fwrite(&ID_VOX, sizeof(int32_t), 1, m_File);
+ fwrite(&MV_VERSION, sizeof(int32_t), 1, m_File);
+
+ // MAIN CHUNCK
+ fwrite(&ID_MAIN, sizeof(int32_t), 1, m_File);
+ fwrite(&zero, sizeof(int32_t), 1, m_File);
+
+ long numBytesMainChunkPos = GetFilePos();
+ fwrite(&zero, sizeof(int32_t), 1, m_File);
+
+ long headerSize = GetFilePos();
+
+ int count = (int)cubes.size();
+
+ int nodeIds = 0;
+ nTRN rootTransform(1);
+ rootTransform.nodeId = nodeIds;
+ rootTransform.childNodeId = ++nodeIds;
+
+ nGRP rootGroup(count);
+ rootGroup.nodeId = nodeIds; //
+ rootGroup.nodeChildrenNodes = count;
+
+ std::vector shapes;
+ std::vector shapeTransforms;
+ for (int i = 0; i < count; i++)
+ {
+ VoxCube *c = &cubes[i];
+
+ c->write(m_File);
+
+ nTRN trans(1);
+ trans.nodeId = ++nodeIds; //
+ rootGroup.childNodes[i] = nodeIds;
+ trans.childNodeId = ++nodeIds;
+ trans.layerId = 0;
+
+ c->tx = (int)std::floor((c->tx - minCubeX + 0.5f) * m_MaxVoxelPerCubeX - maxVolume.lowerBound.x - maxVolume.Size().x * 0.5);
+ c->ty = (int)std::floor((c->ty - minCubeY + 0.5f) * m_MaxVoxelPerCubeY - maxVolume.lowerBound.y - maxVolume.Size().y * 0.5);
+ c->tz = (int)std::floor((c->tz - minCubeZ + 0.5f) * m_MaxVoxelPerCubeZ);
+
+ // not an animation in my case so only first frame frames[0]
+ trans.frames[0].Add("_t", ct::toStr(c->tx) + " " + ct::toStr(c->ty) + " " + ct::toStr(c->tz));
+
+ shapeTransforms.push_back(trans);
+
+ nSHP shape(1);
+ shape.nodeId = nodeIds; //
+ shape.models[0].modelId = i;
+ shapes.push_back(shape);
+ }
+
+ rootTransform.write(m_File);
+ rootGroup.write(m_File);
+
+ // trn & shp
+ for (int i = 0; i < count; i++)
+ {
+ shapeTransforms[i].write(m_File);
+ shapes[i].write(m_File);
+ }
+
+ // no layr in my cases
+
+ // layr
+ /*for (int i = 0; i < 8; i++)
+ {
+ LAYR layr;
+ layr.nodeId = i;
+ layr.nodeAttribs.Add("_name", ct::toStr(i));
+ layr.write(m_File);
+ }*/
+
+ // RGBA Palette
+ if (colors.size() > 0)
+ {
+ RGBA palette;
+ for (int32_t i = 0; i < 255; i++)
+ {
+ if (i < (int32_t)colors.size())
+ {
+ palette.colors[i] = colors[i];
+ }
+ else
+ {
+ palette.colors[i] = 0;
+ }
+ }
+
+ palette.write(m_File);
+ }
+
+ const long mainChildChunkSize = GetFilePos() - headerSize;
+ SetFilePos(numBytesMainChunkPos);
+ uint32_t size = (uint32_t)mainChildChunkSize;
+ fwrite(&size, sizeof(uint32_t), 1, m_File);
+
+ CloseFile();
+ }
+ }
+
+ uint32_t VoxWriter::GetID(const uint8_t& a, const uint8_t& b, const uint8_t& c, const uint8_t& d)
+ {
+ return (a) | (b << 8) | (c << 16) | (d << 24);
+ }
+
+ bool VoxWriter::OpenFileForWriting(const std::string& vFilePathName)
+ {
+#ifdef MSVC
+ lastError = fopen_s(&m_File, vFilePathName.c_str(), "wb");
+#else
+ m_File = fopen(vFilePathName.c_str(), "wb");
+ lastError = m_File ? 0 : errno;
+#endif
+ if (lastError != 0)
+ return false;
+ return true;
+ }
+
+ void VoxWriter::CloseFile()
+ {
+ fclose(m_File);
+ }
+
+ long VoxWriter::GetFilePos()
+ {
+ return ftell(m_File);
+ }
+
+ void VoxWriter::SetFilePos(const long& vPos)
+ {
+ // SEEK_SET Beginning of file
+ // SEEK_CUR Current position of the file pointer
+ // SEEK_END End of file
+ fseek(m_File, vPos, SEEK_SET);
+ }
+
+ int32_t VoxWriter::GetCubeId(const int32_t& vX, const int32_t& vY, const int32_t& vZ)
+ {
+ if (cubesId.find(vX) != cubesId.end())
+ {
+ if (cubesId[vX].find(vY) != cubesId[vX].end())
+ {
+ if (cubesId[vX][vY].find(vZ) != cubesId[vX][vY].end())
+ {
+ return cubesId[vX][vY][vZ];
+ }
+ }
+ }
+
+ cubesId[vX][vY][vZ] = maxCubeId++;
+
+ return cubesId[vX][vY][vZ];
+ }
+
+ void VoxWriter::MergeVoxelInCube(const int32_t& vX, const int32_t& vY, const int32_t& vZ, const uint8_t& vColorIndex, VoxCube *vCube)
+ {
+ maxVolume.Combine(ct::dvec3((double)vX, (double)vY, (double)vZ));
+
+ bool exist = false;
+
+ if (voxelId.find(vX) != voxelId.end())
+ {
+ if (voxelId[vX].find(vY) != voxelId[vX].end())
+ {
+ if (voxelId[vX][vY].find(vZ) != voxelId[vX][vY].end())
+ {
+ exist = true;
+ }
+ }
+ }
+
+ if (exist == false)
+ {
+ vCube->xyzi.voxels.push_back((uint8_t)(vX % m_MaxVoxelPerCubeX)); // x
+ vCube->xyzi.voxels.push_back((uint8_t)(vY % m_MaxVoxelPerCubeY)); // y
+ vCube->xyzi.voxels.push_back((uint8_t)(vZ % m_MaxVoxelPerCubeZ)); // z
+
+ // correspond a la loc de la couleur du voxel en question
+ voxelId[vX][vY][vZ] = vCube->xyzi.voxels.size();
+
+ vCube->xyzi.voxels.push_back(vColorIndex); // color index
+ }
+ }
+
+ VoxCube* VoxWriter::GetCube(const int32_t& vX, const int32_t& vY, const int32_t& vZ)
+ {
+ int32_t id = GetCubeId(vX, vY, vZ);
+
+ if (id == cubes.size())
+ {
+ VoxCube c;
+
+ c.id = id;
+
+ c.tx = vX;
+ c.ty = vY;
+ c.tz = vZ;
+
+ c.size.sizex = m_MaxVoxelPerCubeX + 1;
+ c.size.sizey = m_MaxVoxelPerCubeY + 1;
+ c.size.sizez = m_MaxVoxelPerCubeZ + 1;
+
+ cubes.push_back(c);
+ }
+
+ if (id < (int32_t)cubes.size())
+ {
+ return &cubes[id];
+ }
+
+ return 0;
+ }
+}
+
diff --git a/src/libs/magicavoxel_file_writer/VoxWriter.h b/src/libs/magicavoxel_file_writer/VoxWriter.h
new file mode 100644
index 0000000..d192f5b
--- /dev/null
+++ b/src/libs/magicavoxel_file_writer/VoxWriter.h
@@ -0,0 +1,397 @@
+// Copyright 2018 Stephane Cuillerdier @Aiekick
+
+// 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.
+
+// This File is a helper for write a vox file after 0.99 release to support
+// the world mode editor
+// just add all color with the color Index with AddColor
+// And add all voxels with the method AddVoxel with the voxel in world position, and finally save the model
+// that's all, the file was initially created for my Proecedural soft
+// "SdfMesher" cf :https://twitter.com/hashtag/sdfmesher?src=hash
+// it support just my needs for the moment, but i put here because its a basis for more i thinck
+#ifndef __VOX_WRITER_H__
+#define __VOX_WRITER_H__
+
+#include
+#include
+#include
+#include