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 +#include +#include +// extracted and adapted from https://github.com/aiekick/cTools (LICENSE MIT) +// for make VoxWriter lib free +#define SAFE_DELETE(a) if (a != 0) delete a, a = 0 + +namespace ct +{ + template ::std::string toStr(const T& DOUBLE) + { + ::std::ostringstream os; + os << DOUBLE; + return os.str(); + } + template inline T mini(const T& a, T& b) { return a < b ? a : b; } + template inline T maxi(const T& a, T& b) { return a > b ? a : b; } + template inline T clamp(const T& n) { return n >= T(0) && n <= T(1) ? n : T(n > T(0)); } // clamp n => 0 to 1 + template inline T clamp(const T& n, const T& b) { return n >= T(0) && n <= b ? n : T(n > T(0))*b; } // clamp n => 0 to b + template inline T clamp(const T& n, const T& a, const T& b) { return n >= a && n <= b ? n : n < a ? a : b; } // clamp n => a to b + + // specialized + struct dvec3 + { + double x, y, z; + dvec3() { x = 0.0, y = 0.0, z = 0.0; } + dvec3(const double& vxyz) { x = vxyz, y = vxyz, z = vxyz; } + dvec3(const double& vx, const double& vy, const double& vz) { x = vx, y = vy, z = vz; } + void operator += (const double v) { x += v; y += v; z += v; } + void operator -= (const double v) { x -= v; y -= v; z -= v; } + void operator += (const dvec3 v) { x += v.x; y += v.y; z += v.z; } + void operator -= (const dvec3 v) { x -= v.x; y -= v.y; z -= v.z; } + void operator *= (double v) { x *= v; y *= v; z *= v; } + void operator /= (double v) { x /= v; y /= v; z /= v; } + void operator *= (dvec3 v) { x *= v.x; y *= v.y; z *= v.z; } + void operator /= (dvec3 v) { x /= v.x; y /= v.y; z /= v.z; } + }; + inline dvec3 operator + (const dvec3& v, const double& f) { return dvec3(v.x + f, v.y + f, v.z + f); } + inline dvec3 operator + (const dvec3& v, dvec3 f) { return dvec3(v.x + f.x, v.y + f.y, v.z + f.z); } + inline dvec3 operator - (const dvec3& v, const double& f) { return dvec3(v.x - f, v.y - f, v.z - f); } + inline dvec3 operator - (const dvec3& v, dvec3 f) { return dvec3(v.x - f.x, v.y - f.y, v.z - f.z); } + inline dvec3 operator * (const dvec3& v, const double& f) { return dvec3(v.x * f, v.y * f, v.z * f); } + inline dvec3 operator * (const dvec3& v, dvec3 f) { return dvec3(v.x * f.x, v.y * f.y, v.z * f.z); } + inline dvec3 operator / (const dvec3& v, const double& f) { return dvec3(v.x / f, v.y / f, v.z / f); } + inline dvec3 operator / (dvec3& v, const double& f) { return dvec3(v.x / f, v.y / f, v.z / f); } + inline dvec3 operator / (const double& f, dvec3& v) { return dvec3(f / v.x, f / v.y, f / v.z); } + inline dvec3 operator / (const dvec3& v, dvec3 f) { return dvec3(v.x / f.x, v.y / f.y, v.z / f.z); } + + // specialized + struct dAABBCC // copy of b2AABB struct + { + dvec3 lowerBound; ///< the lower left vertex + dvec3 upperBound; ///< the upper right vertex + + dAABBCC() : lowerBound(0.0), upperBound(0.0) {} + dAABBCC(dvec3 vlowerBound, dvec3 vUpperBound) + { + lowerBound.x = mini(vlowerBound.x, vUpperBound.x); + lowerBound.y = mini(vlowerBound.y, vUpperBound.y); + lowerBound.z = mini(vlowerBound.z, vUpperBound.z); + upperBound.x = maxi(vlowerBound.x, vUpperBound.x); + upperBound.y = maxi(vlowerBound.y, vUpperBound.y); + upperBound.z = maxi(vlowerBound.z, vUpperBound.z); + } + /// Add a vector to this vector. + void operator += (const dvec3& v){lowerBound += v; upperBound += v;} + + /// Subtract a vector from this vector. + void operator -= (const dvec3& v){lowerBound -= v; upperBound -= v;} + + /// Multiply this vector by a scalar. + void operator *= (double a){lowerBound *= a; upperBound *= a;} + + /// Divide this vector by a scalar. + void operator /= (double a){lowerBound /= a; upperBound /= a;} + + /// Get the center of the AABB. + dvec3 GetCenter() const { return (lowerBound + upperBound) * 0.5; } + + /// Get the extents of the AABB (half-widths). + dvec3 GetExtents() const {return (upperBound - lowerBound) * 0.5;} + + /// Get the perimeter length + double GetPerimeter() const + { + double wx = upperBound.x - lowerBound.x; + double wy = upperBound.y - lowerBound.y; + double wz = upperBound.z - lowerBound.z; + return 2.0 * (wx + wy + wz); + } + + /// Combine a point into this one. + void Combine(dvec3 pt) + { + lowerBound.x = mini(lowerBound.x, pt.x); + lowerBound.y = mini(lowerBound.y, pt.y); + lowerBound.z = mini(lowerBound.z, pt.z); + upperBound.x = maxi(upperBound.x, pt.x); + upperBound.y = maxi(upperBound.y, pt.y); + upperBound.z = maxi(upperBound.z, pt.z); + } + + /// Does this aabb contain the provided vec2. + bool ContainsPoint(const dvec3& pt) const + { + bool result = true; + result = result && lowerBound.x <= pt.x; + result = result && lowerBound.y <= pt.y; + result = result && lowerBound.z <= pt.z; + result = result && pt.x <= upperBound.x; + result = result && pt.y <= upperBound.y; + result = result && pt.z <= upperBound.z; + return result; + } + + bool Intersects(const dAABBCC& other) + { + bool result = true; + result = result || lowerBound.x <= other.lowerBound.x; + result = result || lowerBound.y <= other.lowerBound.y; + result = result || lowerBound.z <= other.lowerBound.z; + result = result || other.upperBound.x <= upperBound.x; + result = result || other.upperBound.y <= upperBound.y; + result = result || other.upperBound.z <= upperBound.z; + return result; + } + + const dvec3 Size() + { + return dvec3(upperBound - lowerBound); + } + }; + + /// Add a float to a dAABBCC. + inline dAABBCC operator + (const dAABBCC& v, float f){return dAABBCC(v.lowerBound + f, v.upperBound + f);} + + /// Add a dAABBCC to a dAABBCC. + inline dAABBCC operator + (const dAABBCC& v, dAABBCC f){return dAABBCC(v.lowerBound + f.lowerBound, v.upperBound + f.upperBound);} + + /// Substract a float from a dAABBCC. + inline dAABBCC operator - (const dAABBCC& v, float f){return dAABBCC(v.lowerBound - f, v.upperBound - f);} + + /// Substract a dAABBCC to a dAABBCC. + inline dAABBCC operator - (const dAABBCC& v, dAABBCC f){return dAABBCC(v.lowerBound - f.lowerBound, v.upperBound - f.upperBound);} + + /// Multiply a float with a dAABBCC. + inline dAABBCC operator * (const dAABBCC& v, float f){return dAABBCC(v.lowerBound * f, v.upperBound * f);} + + /// Multiply a dAABBCC with a dAABBCC. + inline dAABBCC operator * (const dAABBCC& v, dAABBCC f){return dAABBCC(v.lowerBound * f.lowerBound, v.upperBound * f.upperBound);} + + /// Divide a dAABBCC by a float. + inline dAABBCC operator / (const dAABBCC& v, float f){return dAABBCC(v.lowerBound / f, v.upperBound / f);} + + /// Divide a dAABBCC by a float. + inline dAABBCC operator / (dAABBCC& v, float f){return dAABBCC(v.lowerBound / f, v.upperBound / f);} + + /// Divide a dAABBCC by a dAABBCC. + inline dAABBCC operator / (const dAABBCC& v, dAABBCC f){return dAABBCC(v.lowerBound / f.lowerBound, v.upperBound / f.upperBound);} +} + +namespace vox +{ + inline uint32_t GetMVID(uint8_t a, uint8_t b, uint8_t c, uint8_t d) + { + return (a) | (b << 8) | (c << 16) | (d << 24); + } + + struct DICTstring + { + int32_t bufferSize; + std::string buffer; + + DICTstring(); + + void write(FILE *fp); + size_t getSize(); + }; + + struct DICTitem + { + DICTstring key; + DICTstring value; + + DICTitem(); + DICTitem(std::string vKey, std::string vValue); + + void write(FILE *fp); + size_t getSize(); + }; + + struct DICT + { + int32_t count; + std::vector keys; + + DICT(); + void write(FILE *fp); + size_t getSize(); + void Add(std::string vKey, std::string vValue); + }; + + struct nTRN + { + int32_t nodeId; + DICT nodeAttribs; + int32_t childNodeId; + int32_t reservedId; + int32_t layerId; + int32_t numFrames; + std::vector frames; + + nTRN(int32_t countFrames); + + void write(FILE *fp); + size_t getSize(); + }; + + struct nGRP + { + int32_t nodeId; + DICT nodeAttribs; + int32_t nodeChildrenNodes; + std::vector childNodes; + + nGRP(int32_t vCount); + + void write(FILE *fp); + size_t getSize(); + }; + + struct MODEL + { + int32_t modelId; + DICT modelAttribs; + + MODEL(); + + void write(FILE *fp); + size_t getSize(); + }; + + struct nSHP + { + int32_t nodeId; + DICT nodeAttribs; + int32_t numModels; + std::vector models; + + nSHP(int32_t vCount); + + void write(FILE *fp); + size_t getSize(); + }; + + struct LAYR + { + int32_t nodeId; + DICT nodeAttribs; + int32_t reservedId; + + LAYR(); + void write(FILE *fp); + size_t getSize(); + }; + + struct SIZE + { + int32_t sizex; + int32_t sizey; + int32_t sizez; + + SIZE(); + + void write(FILE *fp); + size_t getSize(); + }; + + struct XYZI + { + int32_t numVoxels; + std::vector voxels; + + XYZI(); + void write(FILE *fp); + size_t getSize(); + }; + + struct RGBA + { + int32_t colors[256]; + + RGBA(); + void write(FILE *fp); + size_t getSize(); + }; + + struct VoxCube + { + int id; + + // size + SIZE size; + + // translate + int tx; + int ty; + int tz; + + XYZI xyzi; + + VoxCube(); + + void write(FILE *fp); + }; + + class VoxWriter + { + public: + static VoxWriter* Create(const std::string& vFilePathName, const uint32_t& vLimitX, + const uint32_t& vLimitY, const uint32_t& vLimitZ, int32_t *vError); + static std::string GetErrnoMsg(const int32_t& vError); + + private: + int32_t MV_VERSION; + int32_t ID_VOX, ID_PACK, ID_MAIN, ID_SIZE, ID_XYZI, + ID_RGBA, ID_NTRN, ID_NGRP, ID_NSHP; + int32_t m_MaxVoxelPerCubeX; + int32_t m_MaxVoxelPerCubeY; + int32_t m_MaxVoxelPerCubeZ; + FILE * m_File; + ct::dAABBCC maxVolume; + std::vector colors; + std::vector cubes; + int32_t maxCubeId; + int32_t minCubeX; + int32_t minCubeY; + int32_t minCubeZ; + std::map>> cubesId; + std::map>> voxelId; + + int32_t lastError; + + public: + VoxWriter(int32_t vMaxVoxelPerCubeX = 126, int32_t vMaxVoxelPerCubeY = 126, int32_t vMaxVoxelPerCubeZ = 126); + ~VoxWriter(); + int32_t IsOk(const std::string& vFilePathName); + void ClearVoxels(); + void ClearColors(); + void AddColor(const uint8_t& r, const uint8_t& g, const uint8_t& b, const uint8_t& a, const uint8_t& index); + void AddVoxel(const int32_t& vX, const int32_t& vY, const int32_t& vZ, const uint8_t& vColorIndex); + void SaveToFile(const std::string& vFilePathName); + + private: + uint32_t GetID(const uint8_t& a, const uint8_t& b, const uint8_t& c, const uint8_t& d); + bool OpenFileForWriting(const std::string& vFilePathName); + void CloseFile(); + long GetFilePos(); + void SetFilePos(const long& vPos); + int32_t GetCubeId(const int32_t& vX, const int32_t& vY, const int32_t& vZ); + VoxCube* GetCube(const int32_t& vX, const int32_t& vY, const int32_t& vZ); + void MergeVoxelInCube(const int32_t& vX, const int32_t& vY, const int32_t& vZ, const uint8_t& vColorIndex, VoxCube *vCube); + }; +} +#endif //__VOX_WRITER_H__ diff --git a/src/util_io.cpp b/src/util_io.cpp index 73aef36..8d63308 100644 --- a/src/util_io.cpp +++ b/src/util_io.cpp @@ -1,6 +1,7 @@ #include "util.h" #include "util_io.h" #include "TriMesh_algo.h" +#include "libs/magicavoxel_file_writer/VoxWriter.h" using namespace std; From 17e9d3204808fde186178204aac0447271855522 Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Fri, 16 Sep 2022 13:32:55 +0200 Subject: [PATCH 05/13] Removed travis build --- .travis.yml | 51 --------------------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 905a120..0000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -language: cpp - -sudo: enabled - -compiler: - - gcc - -matrix: - include: - - name: CUDA 10 - env: - - CUDA=10.1.105-1 - - CUDA_SHORT=10.1 - - UBUNTU_VERSION=ubuntu1804 - - CUDA_ARCH=30 - dist: bionic - -before_install: -# Get CUDA (based on https://github.com/jeremad/cuda-travis) - - INSTALLER=cuda-repo-${UBUNTU_VERSION}_${CUDA}_amd64.deb - - wget http://developer.download.nvidia.com/compute/cuda/repos/${UBUNTU_VERSION}/x86_64/${INSTALLER} - - sudo dpkg -i ${INSTALLER} - - wget https://developer.download.nvidia.com/compute/cuda/repos/${UBUNTU_VERSION}/x86_64/7fa2af80.pub - - sudo apt-key add 7fa2af80.pub - - sudo apt update -qq - - sudo apt install -y cuda-core-${CUDA_SHORT/./-} cuda-cudart-dev-${CUDA_SHORT/./-} cuda-cufft-dev-${CUDA_SHORT/./-} - - sudo apt clean - - CUDA_HOME=/usr/local/cuda-${CUDA_SHORT} - - LD_LIBRARY_PATH=${CUDA_HOME}/lib64:${LD_LIBRARY_PATH} - - PATH=${CUDA_HOME}/bin:${PATH} - - PATH=${PATH}:${PWD} -# GLM: We can get this from the standard Ubuntu repository, any recent version will do - - sudo apt-get install -y libglm-dev -# TRIMESH: Get dependencies from standard repos, and build project from git using makefile - - sudo apt-get install -y mesa-common-dev libglu1-mesa-dev libxi-dev - - git clone https://github.com/Forceflow/trimesh2.git - - cd trimesh2 && make && cd .. - - wget https://github.com/Kitware/CMake/releases/download/v3.13.0/cmake-3.13.0-Linux-x86_64.sh -q -O ./cmake-install.sh - - chmod u+x ./cmake-install.sh - - mkdir ./cmake - - ./cmake-install.sh --skip-license --prefix=./cmake - - rm ./cmake-install.sh - -script: - - mkdir build - - cd build - - ../cmake/bin/cmake -DTrimesh2_INCLUDE_DIR="../trimesh2/include" -DTrimesh2_LINK_DIR="../trimesh2/lib.Linux64" -DCUDA_ARCH=${CUDA_ARCH} .. - - ../cmake/bin/cmake --build . -j 2 -# Force CPU voxelization to test on Travis (we won't have a GPU here) - - ./cuda_voxelizer -f ../test_models/bunny.OBJ -cpu - - ./cuda_voxelizer -f ../test_models/bunny.OBJ -cpu -solid From e77e2b37b257f5375d7926cb2534bf3e799480af Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Fri, 16 Sep 2022 14:33:07 +0200 Subject: [PATCH 06/13] Added export to magicavoxel format --- src/main.cpp | 10 +++++++--- src/util_io.cpp | 20 ++++++++++++++++++++ src/util_io.h | 1 + 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7a9bfe9..9e8347d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,8 +29,8 @@ void voxelize(const voxinfo & v, float* triangle_data, unsigned int* vtable, boo void voxelize_solid(const voxinfo& v, float* triangle_data, unsigned int* vtable, bool useThrustPath, bool morton_code); // Output formats -enum class OutputFormat { output_binvox = 0, output_morton = 1, output_obj_points = 2, output_obj_cubes = 3}; -char *OutputFormats[] = { "binvox file", "morton encoded blob", "obj file (pointcloud)", "obj file (cubes)"}; +enum class OutputFormat { output_binvox = 0, output_morton = 1, output_obj_points = 2, output_obj_cubes = 3, output_vox = 4}; +char *OutputFormats[] = { "binvox file", "morton encoded blob", "obj file (pointcloud)", "obj file (cubes)", "magicavoxel file"}; // Default options string filename = ""; @@ -56,7 +56,7 @@ void printHelp(){ cout << "Program options: " << endl << endl; cout << " -f (required)" << endl; cout << " -s 512, 1024, ... (default: 256)>" << endl; - cout << " -o " << endl; + cout << " -o " << endl; cout << " -thrust : Force using CUDA Thrust Library (possible speedup / throughput improvement)" << endl; cout << " -cpu : Force CPU-based voxelization (slow, but works if no compatible GPU can be found)" << endl; cout << " -solid : Force solid voxelization (experimental, needs watertight model)" << endl << endl; @@ -143,6 +143,7 @@ void parseProgramParameters(int argc, char* argv[]){ else if (output == "morton"){outputformat = OutputFormat::output_morton;} else if (output == "obj"){outputformat = OutputFormat::output_obj_cubes;} else if (output == "obj_points") { outputformat = OutputFormat::output_obj_points; } + else if (output == "vox") { outputformat = OutputFormat::output_vox; } else { fprintf(stdout, "[Err] Unrecognized output format: %s, valid options are binvox (default), morton, obj or obj_points \n", output.c_str()); exit(1); @@ -276,6 +277,9 @@ int main(int argc, char* argv[]) { else if (outputformat == OutputFormat::output_obj_cubes) { write_obj_cubes(vtable, voxelization_info, filename); } + else if (outputformat == OutputFormat::output_vox) { + write_vox(vtable, voxelization_info, filename); + } if (useThrustPath) { cleanup_thrust(); diff --git a/src/util_io.cpp b/src/util_io.cpp index 8d63308..406ad53 100644 --- a/src/util_io.cpp +++ b/src/util_io.cpp @@ -235,4 +235,24 @@ void write_binvox(const unsigned int* vtable, const voxinfo v_info, const std::s // Write rest output.write((char*)¤t_seen, 1); output.close(); +} + +// Experimental MagicaVoxel file format output +void write_vox(const unsigned int* vtable, const voxinfo v_info, const std::string base_filename) { + string filename_output = base_filename + string("_") + to_string(v_info.gridsize.x) + string(".vox"); + vox::VoxWriter voxwriter; + voxwriter.AddColor(255, 255, 255,0, 0); + + for (size_t x = 0; x < v_info.gridsize.x; x++) { + for (size_t y = 0; y < v_info.gridsize.z; y++) { + for (size_t z = 0; z < v_info.gridsize.y; z++) { + if (checkVoxel(x, y, z, v_info.gridsize, vtable)) { + // Somehow, this makes the vox model come out correct way up. Some axes probably got switched along the way + voxwriter.AddVoxel(x, -z + v_info.gridsize.z, y-1, 1); + } + } + } + } + + voxwriter.SaveToFile(filename_output); } \ No newline at end of file diff --git a/src/util_io.h b/src/util_io.h index b54d0b9..1f98c0b 100644 --- a/src/util_io.h +++ b/src/util_io.h @@ -11,3 +11,4 @@ void write_binary(void* data, const size_t bytes, const std::string base_filenam void write_binvox(const unsigned int* vtable, const voxinfo v_info, const std::string base_filename); void write_obj_pointcloud(const unsigned int* vtable, const voxinfo v_info, const std::string base_filename); void write_obj_cubes(const unsigned int* vtable, const voxinfo v_info, const std::string base_filename); +void write_vox(const unsigned int* vtable, const voxinfo v_info, const std::string base_filename); From f74bb1e63d8859f275e7f0f1540a4b4f8ae7e0bd Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Sat, 24 Sep 2022 13:43:02 +0200 Subject: [PATCH 07/13] Added VoxWriter to Cmake --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9719090..09d167c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ SET(CUDA_VOXELIZER_SRCS ./src/util_cuda.cpp ./src/util_io.cpp ./src/cpu_voxelizer.cpp + ./src/libs/magicavoxel_file_writer/VoxWriter.cpp ) SET(CUDA_VOXELIZER_SRCS_CU ./src/voxelize.cu From 02745fc2ba36a0e80272ccae46f3fa6de3b0f021 Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:51:29 +0200 Subject: [PATCH 08/13] Made vox default output format, version bump --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 9e8347d..bae9996 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,7 @@ #include "cpu_voxelizer.h" using namespace std; -string version_number = "v0.4.14"; +string version_number = "v0.5"; // Forward declaration of CUDA functions float* meshToGPU_thrust(const trimesh::TriMesh *mesh); // METHOD 3 to transfer triangles can be found in thrust_operations.cu(h) @@ -35,7 +35,7 @@ char *OutputFormats[] = { "binvox file", "morton encoded blob", "obj file (point // Default options string filename = ""; string filename_base = ""; -OutputFormat outputformat = OutputFormat::output_binvox; +OutputFormat outputformat = OutputFormat::output_vox; unsigned int gridsize = 256; bool useThrustPath = false; bool forceCPU = false; @@ -56,7 +56,7 @@ void printHelp(){ cout << "Program options: " << endl << endl; cout << " -f (required)" << endl; cout << " -s 512, 1024, ... (default: 256)>" << endl; - cout << " -o " << endl; + cout << " -o " << endl; cout << " -thrust : Force using CUDA Thrust Library (possible speedup / throughput improvement)" << endl; cout << " -cpu : Force CPU-based voxelization (slow, but works if no compatible GPU can be found)" << endl; cout << " -solid : Force solid voxelization (experimental, needs watertight model)" << endl << endl; From 556931baaf14c155ee959b871e5d6c6b064131d5 Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:51:37 +0200 Subject: [PATCH 09/13] Cleanup of silent mode --- src/util_io.cpp | 60 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/util_io.cpp b/src/util_io.cpp index 406ad53..606db37 100644 --- a/src/util_io.cpp +++ b/src/util_io.cpp @@ -94,10 +94,16 @@ void write_cube(const size_t& x, const size_t& y, const size_t& z, ofstream& out void write_obj_cubes(const unsigned int* vtable, const voxinfo v_info, const std::string base_filename) { string filename_output = base_filename + string("_") + to_string(v_info.gridsize.x) + string("_voxels.obj"); + ofstream output(filename_output.c_str(), ios::out); + #ifndef SILENT fprintf(stdout, "[I/O] Writing data in obj voxels format to file %s \n", filename_output.c_str()); + // Write stats + size_t voxels_seen = 0; + const size_t write_stats_25 = (size_t(v_info.gridsize.x) * size_t(v_info.gridsize.y) * size_t(v_info.gridsize.z)) / 4.0f; + fprintf(stdout, "[I/O] Writing to file: 0%%..."); #endif - ofstream output(filename_output.c_str(), ios::out); + // Write vertex normals once //write_vertex_normal(output, glm::ivec3(0, 0, -1)); // forward = 1 @@ -106,22 +112,18 @@ void write_obj_cubes(const unsigned int* vtable, const voxinfo v_info, const std //write_vertex_normal(output, glm::ivec3(1, 0, 0)); // right = 4 //write_vertex_normal(output, glm::ivec3(0, -1, 0)); // bottom = 5 //write_vertex_normal(output, glm::ivec3(0, 1, 0)); // top = 6 - - // Write stats - size_t voxels_seen = 0; - const size_t write_stats_25 = (size_t(v_info.gridsize.x) * size_t(v_info.gridsize.y) * size_t(v_info.gridsize.z)) / 4.0f; - fprintf(stdout, "[I/O] Writing to file: 0%%..."); - //size_t voxels_written = 0; + assert(output); for (size_t x = 0; x < v_info.gridsize.x; x++) { for (size_t y = 0; y < v_info.gridsize.y; y++) { for (size_t z = 0; z < v_info.gridsize.z; z++) { +#ifndef SILENT voxels_seen++; if (voxels_seen == write_stats_25) {fprintf(stdout, "25%%...");} else if (voxels_seen == write_stats_25 * size_t(2)) {fprintf(stdout, "50%%...");} - else if (voxels_seen == write_stats_25 * size_t(3)) {fprintf(stdout, "75%%..."); - } + else if (voxels_seen == write_stats_25 * size_t(3)) {fprintf(stdout, "75%%...");} +#endif if (checkVoxel(x, y, z, v_info.gridsize, vtable)) { //voxels_written += 1; write_cube(x, y, z, output); @@ -129,10 +131,14 @@ void write_obj_cubes(const unsigned int* vtable, const voxinfo v_info, const std } } } +#ifndef SILENT fprintf(stdout, "100%% \n"); +#endif // std::cout << "written " << voxels_written << std::endl; +#ifndef SILENT fprintf(stdout, "[I/O] Reordering / Optimizing mesh with Trimesh2 \n"); +#endif // Load the file using TriMesh2 trimesh::TriMesh* temp_mesh = trimesh::TriMesh::read(filename_output.c_str()); trimesh::reorder_verts(temp_mesh); @@ -140,7 +146,9 @@ void write_obj_cubes(const unsigned int* vtable, const voxinfo v_info, const std //trimesh::edgeflip(temp_mesh); //temp_mesh->clear_normals(); //temp_mesh->need_normals(); +#ifndef SILENT fprintf(stdout, "[I/O] Writing final mesh to file %s \n", filename_output.c_str()); +#endif temp_mesh->write(filename_output.c_str()); output.close(); @@ -148,15 +156,14 @@ void write_obj_cubes(const unsigned int* vtable, const voxinfo v_info, const std void write_obj_pointcloud(const unsigned int* vtable, const voxinfo v_info, const std::string base_filename) { string filename_output = base_filename + string("_") + to_string(v_info.gridsize.x) + string("_pointcloud.obj"); + ofstream output(filename_output.c_str(), ios::out); + #ifndef SILENT fprintf(stdout, "[I/O] Writing data in obj point cloud format to %s \n", filename_output.c_str()); -#endif - ofstream output(filename_output.c_str(), ios::out); - - // Write stats size_t voxels_seen = 0; const size_t write_stats_25 = (size_t(v_info.gridsize.x) * size_t(v_info.gridsize.y) * size_t(v_info.gridsize.z)) / 4.0f; fprintf(stdout, "[I/O] Writing to file: 0%%..."); +#endif // write stats size_t voxels_written = 0; @@ -165,10 +172,12 @@ void write_obj_pointcloud(const unsigned int* vtable, const voxinfo v_info, cons for (size_t x = 0; x < v_info.gridsize.x; x++) { for (size_t y = 0; y < v_info.gridsize.y; y++) { for (size_t z = 0; z < v_info.gridsize.z; z++) { +#ifndef SILENT voxels_seen++; if (voxels_seen == write_stats_25) { fprintf(stdout, "25%%...");} else if (voxels_seen == write_stats_25 * size_t(2)) { fprintf(stdout, "50%%...");} else if (voxels_seen == write_stats_25 * size_t(3)) {fprintf(stdout, "75%%...");} +#endif if (checkVoxel(x, y, z, v_info.gridsize, vtable)) { voxels_written += 1; output << "v " << (x+0.5) << " " << (y + 0.5) << " " << (z + 0.5) << endl; // +0.5 to put vertex in the middle of the voxel @@ -176,7 +185,9 @@ void write_obj_pointcloud(const unsigned int* vtable, const voxinfo v_info, cons } } } +#ifndef SILENT fprintf(stdout, "100%% \n"); +#endif // std::cout << "written " << voxels_written << std::endl; output.close(); } @@ -243,16 +254,35 @@ void write_vox(const unsigned int* vtable, const voxinfo v_info, const std::stri vox::VoxWriter voxwriter; voxwriter.AddColor(255, 255, 255,0, 0); +#ifndef SILENT + fprintf(stdout, "[I/O] Writing data in vox format to %s \n", filename_output.c_str()); + + // Write stats + size_t voxels_seen = 0; + const size_t write_stats_25 = (size_t(v_info.gridsize.x) * size_t(v_info.gridsize.y) * size_t(v_info.gridsize.z)) / 4.0f; + fprintf(stdout, "[I/O] Writing to file: 0%%..."); + size_t voxels_written = 0; +#endif + for (size_t x = 0; x < v_info.gridsize.x; x++) { for (size_t y = 0; y < v_info.gridsize.z; y++) { for (size_t z = 0; z < v_info.gridsize.y; z++) { +#ifndef SILENT + // Progress stats + voxels_seen++; + if (voxels_seen == write_stats_25) { fprintf(stdout, "25%%..."); } + else if (voxels_seen == write_stats_25 * size_t(2)) { fprintf(stdout, "50%%..."); } + else if (voxels_seen == write_stats_25 * size_t(3)) { fprintf(stdout, "75%%..."); } +#endif if (checkVoxel(x, y, z, v_info.gridsize, vtable)) { // Somehow, this makes the vox model come out correct way up. Some axes probably got switched along the way - voxwriter.AddVoxel(x, -z + v_info.gridsize.z, y-1, 1); + voxwriter.AddVoxel(x, -z + v_info.gridsize.z, y, 1); } } } } - +#ifndef SILENT + fprintf(stdout, "100%% \n"); +#endif voxwriter.SaveToFile(filename_output); } \ No newline at end of file From c3a0c6d17556731168d69724a97636349a7c9915 Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:53:37 +0200 Subject: [PATCH 10/13] Updated Readme --- README.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3c114c0..de22211 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ [![Build Status](https://travis-ci.org/Forceflow/cuda_voxelizer.svg?branch=master)](https://travis-ci.org/Forceflow/cuda_voxelizer) ![](https://img.shields.io/github/license/Forceflow/cuda_voxelizer.svg) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/Forceflow) -# cuda_voxelizer v0.4.14 +# cuda_voxelizer v0.5 A command-line tool to convert polygon meshes to (annotated) voxel grids. * Supported input formats: .ply, .off, .obj, .3DS, .SM and RAY - * Supported output formats: .binvox, .obj, morton ordered grid + * Supported output formats: .vox, .binvox, .obj cubes and point cloud, morton ordered grid * Requires a CUDA-compatible video card. Compute Capability 2.0 or higher (Nvidia Fermi or better). * Since v0.4.4, the voxelizer reverts to a (slower) CPU voxelization method when no CUDA device is found @@ -12,18 +12,17 @@ Program options: * `-f `: **(required)** A path to a polygon-based 3D model file. * `-s `: The length of the cubical voxel grid. Default: 256, resulting in a 256 x 256 x 256 voxelization grid. The tool will automatically select the tightest cubical bounding box around the model. * `-o `: The output format for voxelized models, default: *binvox*. Output files are saved in the same folder as the input file. - * `binvox`: A [binvox](http://www.patrickmin.com/binvox/binvox.html) file (default). Can be viewed using [viewvox](http://www.patrickmin.com/viewvox/). + * `vox`: **(default)** A [vox](https://github.com/ephtracy/voxel-model/blob/master/MagicaVoxel-file-format-vox.txt) file, which is the native format of and can be viewed with the excellent [MagicaVoxel](https://ephtracy.github.io/). + * `binvox`: A [binvox](http://www.patrickmin.com/binvox/binvox.html) file. Can be viewed using [viewvox](http://www.patrickmin.com/viewvox/). * `obj`: A mesh containing actual cubes (made up of triangle faces) for each voxel. * `obj_points`: A mesh containing a point cloud, with a vertex for each voxel. Can be viewed using any compatible viewer that can just display vertices, like [Blender](https://www.blender.org/) or [Meshlab](https://www.meshlab.net/). - * `morton`: a binary file containing a Morton-ordered grid. This is a format I personally use for other tools. - * `-cpu`: Force voxelization on the CPU instead of GPU. For when a CUDA device is not detected/compatible, or for very small models where GPU call overhead is not worth it. This is done multi-threaded, but will be slower for large models / grid sizes. + * `morton`: a binary file containing a Morton-ordered grid. This is an internal format I use for other tools. + * `-cpu`: Force multi-threaded voxelization on the CPU instead of GPU. Can be used when a CUDA device is not detected/compatible, or for very small models where GPU call overhead is not worth it. * `-thrust` : Use Thrust library for copying the model data to the GPU, for a possible speed / throughput improvement. I found this to be very system-dependent. Default: disabled. * `-solid` : (Experimental) Use solid voxelization instead of voxelizing the mesh faces. Needs a watertight input mesh. - ## Examples - -`cuda_voxelizer -f bunny.ply -s 256` generates a 256 x 256 x 256 binvox-based voxel model which will be stored in `bunny_256.binvox`. +`cuda_voxelizer -f bunny.ply -s 256` generates a 256 x 256 x 256 vox-based voxel model which will be stored in `bunny_256.vox`. `cuda_voxelizer -f torus.ply -s 64 -o obj -thrust -solid` generates a solid (filled) 64 x 64 x 64 .obj voxel model which will be stored in `torus_64.obj`. During voxelization, the Cuda Thrust library will be used for a possible speedup, but YMMV. @@ -38,7 +37,7 @@ The project has the following build dependencies: * [Nvidia Cuda 8.0 Toolkit (or higher)](https://developer.nvidia.com/cuda-toolkit) for CUDA + Thrust libraries (standard included) * [Trimesh2](https://github.com/Forceflow/trimesh2) for model importing. Latest version recommended. * [GLM](http://glm.g-truc.net/0.9.8/index.html) for vector math. Any recent version will do. - * [OpenMP](https://www.openmp.org/) + * [OpenMP](https://www.openmp.org/) for multi-threading. ### Build using CMake (Windows, Linux) @@ -103,7 +102,6 @@ This is on my list of nice things to add. Don't hesistate to crack one of these * Noncubic grid support * Memory limits test - * Output to more popular voxel formats like MagicaVoxel, Minecraft * Implement partitioning for larger models * Do a pre-pass to categorize triangles * Implement capture of normals / color / texture data From 249ff2c3476017017c4e2bdf26a698ccdf58666f Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:55:48 +0200 Subject: [PATCH 11/13] Updated Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de22211..0ac486e 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ A project solution for Visual Studio 2022 is provided in the `msvc`folder. It is * Nvidia also has a voxel library called [GVDB](https://developer.nvidia.com/gvdb), that does a lot more than just voxelizing. ## Todo / Possible future work -This is on my list of nice things to add. Don't hesistate to crack one of these yourself and make a PR! +This is on my list of "nice things to add". * Noncubic grid support * Memory limits test From 5b32c6df26c08564ab3544ef9db2cf9467369543 Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:56:26 +0200 Subject: [PATCH 12/13] Make repo link clickable --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index bae9996..00d52f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,7 +44,7 @@ bool solidVoxelization = false; void printHeader(){ fprintf(stdout, "## CUDA VOXELIZER \n"); cout << "CUDA Voxelizer " << version_number << " by Jeroen Baert" << endl; - cout << "github.com/Forceflow/cuda_voxelizer - mail (at) jeroen-baert (dot) be" << endl; + cout << "https://github.com/Forceflow/cuda_voxelizer - mail (at) jeroen-baert (dot) be" << endl; } void printExample() { From f76e81409ae5f58c4beb7ec33f77e59884c20c8e Mon Sep 17 00:00:00 2001 From: Jeroen Baert <3607063+Forceflow@users.noreply.github.com> Date: Wed, 28 Sep 2022 12:10:27 +0200 Subject: [PATCH 13/13] Updated Readme --- README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0ac486e..504ff6e 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ A command-line tool to convert polygon meshes to (annotated) voxel grids. ## Usage Program options: * `-f `: **(required)** A path to a polygon-based 3D model file. - * `-s `: The length of the cubical voxel grid. Default: 256, resulting in a 256 x 256 x 256 voxelization grid. The tool will automatically select the tightest cubical bounding box around the model. - * `-o `: The output format for voxelized models, default: *binvox*. Output files are saved in the same folder as the input file. + * `-s `: **(default: 256)** The length of the cubical voxel grid. The process will construct the tightest possible cubical bounding box around the input model. + * `-o `: The output format for voxelized models, default: *binvox*. Output files are saved in the same folder as the input file, in the format `_.extension`. * `vox`: **(default)** A [vox](https://github.com/ephtracy/voxel-model/blob/master/MagicaVoxel-file-format-vox.txt) file, which is the native format of and can be viewed with the excellent [MagicaVoxel](https://ephtracy.github.io/). * `binvox`: A [binvox](http://www.patrickmin.com/binvox/binvox.html) file. Can be viewed using [viewvox](http://www.patrickmin.com/viewvox/). * `obj`: A mesh containing actual cubes (made up of triangle faces) for each voxel. @@ -29,8 +29,8 @@ Program options: ![output_examples](https://raw.githubusercontent.com/Forceflow/cuda_voxelizer/main/img/output_examples.jpg) ## Building -The build process is aimed at 64-bit executables. It's probably possible to build for 32-bit as well, but I'm not actively testing/supporting this. -You can build using CMake, or using the provided Visual Studio project. Since 2022, cuda_voxelizer builds via [Github Actions](https://github.com/Forceflow/cuda_voxelizer/actions) as well, check the .[yml config file](https://github.com/Forceflow/cuda_voxelizer/blob/main/.github/workflows/autobuild.yml) for more info. +The build process is aimed at 64-bit executables. It's possible to build for 32-bit as well, but I'm not actively testing/supporting this. +You can build using CMake or using the provided Visual Studio project. Since 2022, cuda_voxelizer builds via [Github Actions](https://github.com/Forceflow/cuda_voxelizer/actions) as well, check the .[yml config file](https://github.com/Forceflow/cuda_voxelizer/blob/main/.github/workflows/autobuild.yml) for more info. ### Dependencies The project has the following build dependencies: @@ -62,7 +62,7 @@ cmake --build . --parallel number_of_cores ### Build using Visual Studio project (Windows) -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. +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 other 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\ @@ -85,13 +85,17 @@ A project solution for Visual Studio 2022 is provided in the `msvc`folder. It is | 1024³ | 8.6 ms | 1047.5 ms | | 2048³ | 44.6 ms | 4147.4 ms | -## Notes / See Also +## Thanks + * The [MagicaVoxel](https://ephtracy.github.io/) I/O was implemented using [MagicaVoxel File Writer](https://github.com/aiekick/MagicaVoxel_File_Writer) by [aiekick](https://github.com/aiekick). +* Thanks to [conceptclear](https://github.com/conceptclear) for implementing solid voxelization. + +## See also + * The [.binvox file format](https://www.patrickmin.com/binvox/binvox.html) was created by Michael Kazhdan. * [Patrick Min](https://www.patrickmin.com/binvox/) wrote some interesting tools to work with it: * [viewvox](https://www.patrickmin.com/viewvox/): Visualization of voxel grids (a copy of this tool is included in cuda_voxelizer releases) * [thinvox](https://www.patrickmin.com/thinvox/): Thinning of voxel grids * [binvox-rw-py](https://github.com/dimatura/binvox-rw-py) is a Python module to interact with .binvox files - * Thanks to [conceptclear](https://github.com/conceptclear) for implementing solid voxelization * [Zarbuz](https://github.com/zarbuz)'s [FileToVox](https://github.com/Zarbuz/FileToVox) looks interesting as well * If you want a good customizable CPU-based voxelizer, I can recommend [VoxSurf](https://github.com/sylefeb/VoxSurf). * Another hackable voxel viewer is Sean Barrett's excellent [stb_voxel_render.h](https://github.com/nothings/stb/blob/master/stb_voxel_render.h).