From 7b2946a96196d309c39789804df1c1fff0dd5df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gero=20M=C3=BCller?= Date: Thu, 2 Nov 2017 12:44:44 +1000 Subject: [PATCH] update --- CMakeLists.txt | 16 +- ToDo.txt | 3 +- cmake/FindOpenMesh.cmake | 147 +++++++++++++ shader/skybox.fragment.glsl | 12 + shader/skybox.vertex.glsl | 14 ++ src/AlignedAllocator.h | 206 +++++++++++++++++ src/Application.cpp | 286 ++++++++++++------------ src/Application.h | 19 +- src/Density.h | 4 +- src/MarchingCube.cpp | 394 +++++++++++++++++++++++++++++++++ src/MarchingCube.h | 16 ++ src/Mesh.cpp | 187 ++++++++++++---- src/Mesh.h | 37 ++-- src/Polygoniser.cpp | 285 ++++++++++++++++++------ src/Polygoniser.h | 24 +- src/ProgressMonitor.h | 77 +++++++ src/Shader.cpp | 105 +++++++++ src/Shader.h | 5 + src/SkyBox.cpp | 78 +++++++ src/SkyBox.h | 24 ++ src/TextureMapper.cpp | 62 ++++-- src/TextureMapper.h | 11 +- src/main.cpp | 2 +- src/types.h | 15 ++ vendor/MarchingCube.h | 428 ------------------------------------ vendor/MemoryPool.h | 98 +++++++++ vendor/MemoryPool.tcc | 235 ++++++++++++++++++++ 27 files changed, 2048 insertions(+), 742 deletions(-) create mode 100644 cmake/FindOpenMesh.cmake create mode 100644 shader/skybox.fragment.glsl create mode 100644 shader/skybox.vertex.glsl create mode 100644 src/AlignedAllocator.h create mode 100644 src/MarchingCube.cpp create mode 100644 src/MarchingCube.h create mode 100644 src/ProgressMonitor.h create mode 100644 src/Shader.cpp create mode 100644 src/Shader.h create mode 100644 src/SkyBox.cpp create mode 100644 src/SkyBox.h create mode 100644 src/types.h delete mode 100644 vendor/MarchingCube.h create mode 100644 vendor/MemoryPool.h create mode 100644 vendor/MemoryPool.tcc diff --git a/CMakeLists.txt b/CMakeLists.txt index fd80075..5f65c5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,17 +2,26 @@ project (AsteroGen CXX C) cmake_minimum_required (VERSION 2.6) set (CMAKE_CXX_STANDARD 11) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") +FIND_PACKAGE(OpenMP) if(CMAKE_BUILD_TYPE MATCHES DEBUG) set(CMAKE_CXX_FLAGS "-Wall ${CMAKE_CXX_FLAGS}") endif() +SET(CMAKE_C_FLAGS_RELEASE "-Ofast -msse4 -DNDEBUG") +SET(CMAKE_CXX_FLAGS_RELEASE "-Ofast -msse4 -DNDEBUG") + if(CMAKE_BUILD_TYPE MATCHES RELEASE) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") add_definitions(-DOM_STATIC_BUILD) endif() +IF(OPENMP_CXX_FOUND) + SET(CMAKE_C_FLAGS "${OpenMP_C_FLAGS} ${CMAKE_C_FLAGS}") + SET(CMAKE_CXX_FLAGS "${OpenMP_CXX_FLAGS} ${CMAKE_CXX_FLAGS} ") +ENDIF() + FIND_PACKAGE(OpenMesh REQUIRED) link_directories(${OPENMESH_LIBRARY_DIR}) include_directories(${OPENMESH_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/vendor) @@ -24,6 +33,9 @@ add_executable(asteroidgen src/Polygoniser.cpp src/TextureMapper.cpp src/Mesh.cpp + src/MarchingCube.cpp + src/SkyBox.cpp + src/Shader.cpp # src/TexturePainter.cpp # src/gen.cpp vendor/stb_impl.cpp @@ -35,9 +47,9 @@ add_executable(asteroidgen vendor/imgui_draw.cpp vendor/imgui_impl_glfw_gl3.cpp ) -target_link_libraries(asteroidgen ${OPENMESH_LIBRARIES} dl glfw) +target_link_libraries(asteroidgen ${OPENMESH_LIBRARIES} dl glfw ${OpenMP_CXX_LIBRARIES}) if(CMAKE_BUILD_TYPE MATCHES RELEASE) set_target_properties(asteroidgen PROPERTIES LINK_SEARCH_START_STATIC 1) set_target_properties(asteroidgen PROPERTIES LINK_SEARCH_END_STATIC 1) -endif() \ No newline at end of file +endif() diff --git a/ToDo.txt b/ToDo.txt index 94896da..397062f 100644 --- a/ToDo.txt +++ b/ToDo.txt @@ -1,4 +1,5 @@ LIB: +- fix polygonize - improve marching cube - create patches - use lscm @@ -18,4 +19,4 @@ GUI: - Progress - Arcball - PBR https://learnopengl.com/#!PBR/Lighting -- save \ No newline at end of file +- save diff --git a/cmake/FindOpenMesh.cmake b/cmake/FindOpenMesh.cmake new file mode 100644 index 0000000..307899c --- /dev/null +++ b/cmake/FindOpenMesh.cmake @@ -0,0 +1,147 @@ +# +# Try to find OPENMESH +# Once done this will define +# +# OPENMESH_FOUND - system has OPENMESH +# OPENMESH_INCLUDE_DIRS - the OPENMESH include directories +# OPENMESH_LIBRARIES - Link these to use OPENMESH +# OPENMESH_LIBRARY_DIR - directory where the libraries are included +# +# Copyright 2015 Computer Graphics Group, RWTH Aachen University +# Authors: Jan Möbius +# Hans-Christian Ebke +# +# +#=========================================================================== +# +# OpenMesh +# Copyright (c) 2001-2015, RWTH-Aachen University +# Department of Computer Graphics and Multimedia +# All rights reserved. +# www.openmesh.org +# +#--------------------------------------------------------------------------- +# This file is part of OpenMesh. +#--------------------------------------------------------------------------- +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#=========================================================================== + +cmake_minimum_required(VERSION 2.8.9) + +#if already found via finder or simulated finder in openmesh CMakeLists.txt, skip the search +IF (NOT OPENMESH_FOUND) + SET (SEARCH_PATHS + /usr/local/ + /usr/ + "${CMAKE_SOURCE_DIR}/OpenMesh/src/OpenMesh" + "${CMAKE_SOURCE_DIR}/libs_required/OpenMesh/src/OpenMesh" + "${CMAKE_SOURCE_DIR}/../OpenMesh/src/OpenMesh" + "C:/Program Files/OpenMesh 6.3" + "C:/Program Files/OpenMesh 6.2" + "C:/Program Files/OpenMesh 6.1" + "C:/Program Files/OpenMesh 6.0" + "C:/Program Files/OpenMesh 5.2" + "C:/Program Files/OpenMesh 5.1" + "C:/Program Files/OpenMesh 5.0" + "C:/Program Files/OpenMesh 4.2" + "C:/Program Files/OpenMesh 4.1" + "C:/Program Files/OpenMesh 4.0" + "C:/Program Files/OpenMesh 3.4" + "C:/Program Files/OpenMesh 3.3" + "C:/Program Files/OpenMesh 3.2" + "C:/Program Files/OpenMesh 3.1" + "C:/Program Files/OpenMesh 3.0" + "C:/Program Files/OpenMesh 2.4.1" + "C:/Program Files/OpenMesh 2.4" + "C:/Program Files/OpenMesh 2.0/include" + "C:/libs/OpenMesh 6.3" + "C:/libs/OpenMesh 6.2" + "C:/libs/OpenMesh 6.1" + "C:/libs/OpenMesh 6.0" + "C:/libs/OpenMesh 5.2" + "C:/libs/OpenMesh 5.1" + "C:/libs/OpenMesh 5.0" + "C:/libs/OpenMesh 4.2" + "C:/libs/OpenMesh 4.1" + "C:/libs/OpenMesh 4.0" + "C:/libs/OpenMesh 3.4" + "C:/libs/OpenMesh 3.3" + "C:/libs/OpenMesh 3.2" + "C:/libs/OpenMesh 3.1" + "C:/libs/OpenMesh 3.0" + "C:/libs/OpenMesh 2.4.1" + "C:/libs/OpenMesh 2.4" + "${OPENMESH_LIBRARY_DIR}" + ) + + FIND_PATH (OPENMESH_INCLUDE_DIR OpenMesh/Core/Mesh/PolyMeshT.hh + PATHS ${SEARCH_PATHS} + PATH_SUFFIXES include) + + FIND_LIBRARY(OPENMESH_CORE_LIBRARY_RELEASE NAMES OpenMeshCore + PATHS ${SEARCH_PATHS} + PATH_SUFFIXES lib lib64) + + FIND_LIBRARY(OPENMESH_CORE_LIBRARY_DEBUG NAMES OpenMeshCored + PATHS ${SEARCH_PATHS} + PATH_SUFFIXES lib lib64) + + FIND_LIBRARY(OPENMESH_TOOLS_LIBRARY_RELEASE NAMES OpenMeshTools + PATHS ${SEARCH_PATHS} + PATH_SUFFIXES lib lib64) + + FIND_LIBRARY(OPENMESH_TOOLS_LIBRARY_DEBUG NAMES OpenMeshToolsd + PATHS ${SEARCH_PATHS} + PATH_SUFFIXES lib lib64) + +#select configuration depending on platform (optimized... on windows) + include(SelectLibraryConfigurations) + select_library_configurations( OPENMESH_TOOLS ) + select_library_configurations( OPENMESH_CORE ) + + set(OPENMESH_LIBRARIES ${OPENMESH_CORE_LIBRARY} ${OPENMESH_TOOLS_LIBRARY} ) + set(OPENMESH_INCLUDE_DIRS ${OPENMESH_INCLUDE_DIR} ) + +#checks, if OPENMESH was found and sets OPENMESH_FOUND if so + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(OpenMesh DEFAULT_MSG + OPENMESH_CORE_LIBRARY OPENMESH_TOOLS_LIBRARY OPENMESH_INCLUDE_DIR) + +#sets the library dir + if ( OPENMESH_CORE_LIBRARY_RELEASE ) + get_filename_component(_OPENMESH_LIBRARY_DIR ${OPENMESH_CORE_LIBRARY_RELEASE} PATH) + else( OPENMESH_CORE_LIBRARY_RELEASE ) + get_filename_component(_OPENMESH_LIBRARY_DIR ${OPENMESH_CORE_LIBRARY_DEBUG} PATH) + endif( OPENMESH_CORE_LIBRARY_RELEASE ) + set (OPENMESH_LIBRARY_DIR "${_OPENMESH_LIBRARY_DIR}" CACHE PATH "The directory where the OpenMesh libraries can be found.") + + + mark_as_advanced(OPENMESH_INCLUDE_DIR OPENMESH_CORE_LIBRARY_RELEASE OPENMESH_CORE_LIBRARY_DEBUG OPENMESH_TOOLS_LIBRARY_RELEASE OPENMESH_TOOLS_LIBRARY_DEBUG OPENMESH_LIBRARY_DIR) +endif() diff --git a/shader/skybox.fragment.glsl b/shader/skybox.fragment.glsl new file mode 100644 index 0000000..119d60a --- /dev/null +++ b/shader/skybox.fragment.glsl @@ -0,0 +1,12 @@ +#version 330 + +in vec3 TexCoord0; + +out vec4 FragColor; + +uniform samplerCube gCubemapTexture; + +void main() +{ + FragColor = texture(gCubemapTexture, TexCoord0); +} \ No newline at end of file diff --git a/shader/skybox.vertex.glsl b/shader/skybox.vertex.glsl new file mode 100644 index 0000000..dd2adcf --- /dev/null +++ b/shader/skybox.vertex.glsl @@ -0,0 +1,14 @@ +#version 330 + +in vec3 Position; + +uniform mat4 gWVP; + +out vec3 TexCoord0; + +void main() +{ + vec4 WVP_Pos = gWVP * vec4(Position, 1.0); + gl_Position = WVP_Pos.xyww; + TexCoord0 = Position; +} \ No newline at end of file diff --git a/src/AlignedAllocator.h b/src/AlignedAllocator.h new file mode 100644 index 0000000..23e7684 --- /dev/null +++ b/src/AlignedAllocator.h @@ -0,0 +1,206 @@ +#pragma once + +#include +#include + +#include +#include + +enum class Alignment + : size_t + { + Normal = sizeof(void*), SSE = 16, AVX = 32, +}; + +namespace detail { +void* allocate_aligned_memory(size_t align, size_t size); +void deallocate_aligned_memory(void* ptr) noexcept; +} + +template +class AlignedAllocator; + +template +class AlignedAllocator { +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template struct rebind { + typedef AlignedAllocator other; + }; +}; + +template +class AlignedAllocator { +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef std::true_type propagate_on_container_move_assignment; + + template + struct rebind { + typedef AlignedAllocator other; + }; + +public: + AlignedAllocator() noexcept + { + } + + template + AlignedAllocator(const AlignedAllocator&) noexcept + { + } + + size_type max_size() const noexcept + { + return (size_type(~0) - size_type(Align)) / sizeof(T); + } + + pointer address(reference x) const noexcept + { + return std::addressof(x); + } + + const_pointer address(const_reference x) const noexcept + { + return std::addressof(x); + } + + pointer allocate(size_type n, + typename AlignedAllocator::const_pointer = 0) { + const size_type alignment = static_cast(Align); + void* ptr = detail::allocate_aligned_memory(alignment, n * sizeof(T)); + if (ptr == nullptr) { + throw std::bad_alloc(); + } + + return reinterpret_cast(ptr); + } + + void deallocate(pointer p, size_type) noexcept + { + detail::deallocate_aligned_memory(p); + } + + template + void construct(U* p, Args&&... args) { + ::new (reinterpret_cast(p)) U(std::forward(args)...); + } + + void destroy(pointer p) { + p->~T(); + } +}; + +template +class AlignedAllocator { +public: + typedef T value_type; + typedef const T* pointer; + typedef const T* const_pointer; + typedef const T& reference; + typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef std::true_type propagate_on_container_move_assignment; + + template + struct rebind { + typedef AlignedAllocator other; + }; + +public: + AlignedAllocator() noexcept + { + } + + template + AlignedAllocator(const AlignedAllocator&) noexcept + { + } + + size_type max_size() const noexcept + { + return (size_type(~0) - size_type(Align)) / sizeof(T); + } + + const_pointer address(const_reference x) const noexcept + { + return std::addressof(x); + } + + pointer allocate(size_type n, + typename AlignedAllocator::const_pointer = 0) { + const size_type alignment = static_cast(Align); + void* ptr = detail::allocate_aligned_memory(alignment, n * sizeof(T)); + if (ptr == nullptr) { + throw std::bad_alloc(); + } + + return reinterpret_cast(ptr); + } + + void deallocate(pointer p, size_type) noexcept + { + detail::deallocate_aligned_memory(p); + } + + template + void construct(U* p, Args&&... args) { + ::new (reinterpret_cast(p)) U(std::forward(args)...); + } + + void destroy(pointer p) { + p->~T(); + } +}; + +template +inline +bool operator==(const AlignedAllocator&, + const AlignedAllocator&) noexcept + { + return TAlign == UAlign; +} + +template +inline +bool operator!=(const AlignedAllocator&, + const AlignedAllocator&) noexcept + { + return TAlign != UAlign; +} + +inline void* +detail::allocate_aligned_memory(size_t align, size_t size) { + assert(align >= sizeof(void*)); + //assert(nail::is_power_of_two(align)); + + if (size == 0) { + return nullptr; + } + + void* ptr = nullptr; + int rc = posix_memalign(&ptr, align, size); + + if (rc != 0) { + return nullptr; + } + + return ptr; +} + +inline void detail::deallocate_aligned_memory(void *ptr) noexcept +{ + free(ptr); +} diff --git a/src/Application.cpp b/src/Application.cpp index 242252f..3f0c48f 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -1,5 +1,6 @@ #include "Application.h" #include "Mesh.h" +#include "Shader.h" #include #include @@ -82,7 +83,8 @@ Application::Application() : textureSize), programId(0), vPositionLoc(-1), vTexCoordLoc(-1), vNormalLoc( -1), meteoridCount(1000), meteroidMinRadius(0.005), meteroidMaxRadius( 0.2), meteroidSizeExponent(2048), densityFrequency(2), densityOctave( - 2), densityScale(1.0f), resolution(0.1), viewDistance(3.0f), fpsMode( + 2), densityScale(1.0f), resolution(0.1), smoothMesh(true), viewDistance( + 3.0f), fpsMode(false), meshUploadRequest(false), textureUploadRequest( false) { init(); } @@ -157,7 +159,6 @@ void Application::init() { loadShader(); updateVertexArrayObject(); generateAsteroid(); - uploadMesh(); } void Application::shutdown() { @@ -215,47 +216,98 @@ void Application::toogleFpsMode() { } void Application::generateAsteroid() { - std::srand(123); + if (meshProgress.begin("Random Impacts", 1)) { + //if (density.getImpacts().size() == 0) + density.addRandomImpacts(1000, densityIsolevel, 0.01, 0.005, 0.2, 256); - if (density.getImpacts().size() == 0) - density.addRandomImpacts(1000, 0.2, 0.01, 0.005, 0.2, 4096); - //density.saveCrossSection("density.png", 512); + //density.saveCrossSection("density.png", 512); + } + polygonizer.polygonize(resolution, meshProgress); - polygonizer.polygonize(resolution); + if (smoothMesh && meshProgress.begin("Smooth", 1)) { + smooth(polygonizer.vertices, polygonizer.indices); +// { +// std::ofstream out("stage2.obj"); +// saveAttrib(out, "v ", polygonizer.vertices); +// saveFaces(out, polygonizer.indices, 1); +// } + } + + uvec4v_t edges; + if (meshProgress.begin("Find Edges", 1)) { + findEdges(polygonizer.vertices, polygonizer.indices, edges); + } + uvec3v_t adjacents; + if (meshProgress.begin("Find Adjacent", 1)) { + findAdjacent(edges, polygonizer.indices.size(), adjacents); + } + vec3v_t faceNormals; + calculateFaceNormals(polygonizer.vertices, polygonizer.indices, + faceNormals); + + vec3v_t positions; + uvec3v_t indices; + uintv_t patches; + + createPatches(polygonizer.vertices, polygonizer.indices, faceNormals, + adjacents, positions, indices, patches, 0.9); { std::ofstream out("stage1.obj"); - saveAttrib(out, "v ", polygonizer.vertices); - saveFaces(out, polygonizer.indices, 1); + saveAttrib(out, "v ", positions); + saveFaces(out, indices, 1); } - smooth(polygonizer.vertices, polygonizer.indices); - { - std::ofstream out("stage2.obj"); - saveAttrib(out, "v ", polygonizer.vertices); - saveFaces(out, polygonizer.indices, 1); - } - calculateNormals(polygonizer.vertices, polygonizer.indices, normals); - { - std::ofstream out("stage3.obj"); - saveAttrib(out, "v ", polygonizer.vertices); - saveAttrib(out, "vn ", normals); - saveFaces(out, polygonizer.indices, 2); + if (meshProgress.begin("Calculate Vertex Normals", 1)) { + calculateVertexNormals(polygonizer.vertices, polygonizer.indices, + normals); +// { +// std::ofstream out("stage3.obj"); +// saveAttrib(out, "v ", polygonizer.vertices); +// saveAttrib(out, "vn ", normals); +// saveFaces(out, polygonizer.indices, 2); +// } + } - vector edges; std::cout << "Vertices: " << polygonizer.vertices.size() << std::endl; std::cout << "Triangles: " << polygonizer.indices.size() << std::endl; - texturemapper.map(polygonizer.vertices, normals, polygonizer.indices); - moveToMean(texturemapper.vertices); - - { - std::ofstream out("stage4.obj"); - saveAttrib(out, "v ", texturemapper.vertices); - saveAttrib(out, "vn ", texturemapper.normals); - saveAttrib(out, "vt ", texturemapper.texcoords); - saveFaces(out, texturemapper.indices, 3); + if (meshProgress.begin("Map Textures", 1)) { + texturemapper.map(polygonizer.vertices, normals, polygonizer.indices); } + + if (meshProgress.begin("Move To Mean", 1)) { + moveToMean(texturemapper.vertices); + +// { +// std::ofstream out("stage4.obj"); +// saveAttrib(out, "v ", texturemapper.vertices); +// saveAttrib(out, "vn ", texturemapper.normals); +// saveAttrib(out, "vt ", texturemapper.texcoords); +// saveFaces(out, texturemapper.indices, 3); +// } + + } + + if (meshProgress.begin("Save", 4)) { + std::ofstream out("asteroid.obj"); + saveAttrib(out, "v ", texturemapper.vertices); + meshProgress.advance(); + saveAttrib(out, "vn ", texturemapper.normals); + meshProgress.advance(); + saveAttrib(out, "vt ", texturemapper.texcoords); + meshProgress.advance(); + saveFaces(out, texturemapper.indices, 3); + meshProgress.advance(); + } + + meshProgress.finish(); + + if (!meshProgress.isCanceled()) { + meshUploadRequest = true; + textureUploadRequest = true; + } + } bool Application::bindVertexAttrib(GLuint id, GLint loc, GLuint size) { @@ -267,7 +319,7 @@ bool Application::bindVertexAttrib(GLuint id, GLint loc, GLuint size) { size,// size GL_FLOAT,// type GL_FALSE,// normalized? - 0, // stride + 0,// stride (void* ) 0// array buffer offset )) return true; @@ -290,102 +342,7 @@ void Application::updateVertexArrayObject() { GLCK(glBindVertexArray(0)) } -GLuint Application::loadProgram(const std::string &name) { - // Create the shaders - GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); - GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); - - // Read the Vertex Shader code from the file - std::string VertexShaderCode; - std::string vertex_file_path = "shader/" + name + ".vertex.glsl"; - std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); - if (VertexShaderStream.is_open()) { - std::string Line = ""; - while (getline(VertexShaderStream, Line)) - VertexShaderCode += "\n" + Line; - VertexShaderStream.close(); - } else { - std::cout << "Failed to open " << vertex_file_path << std::endl; - return 0; - } - - // Read the Fragment Shader code from the file - std::string FragmentShaderCode; - std::string fragment_file_path = "shader/" + name + ".fragment.glsl"; - std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); - if (FragmentShaderStream.is_open()) { - std::string Line = ""; - while (getline(FragmentShaderStream, Line)) - FragmentShaderCode += "\n" + Line; - FragmentShaderStream.close(); - } else { - std::cout << "Failed to open " << vertex_file_path << std::endl; - return 0; - } - - GLint Result = GL_FALSE; - int InfoLogLength; - - // Compile Vertex Shader - std::cout << "Compiling vertex shader : " << name << std::endl; - char const * VertexSourcePointer = VertexShaderCode.c_str(); - glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); - glCompileShader(VertexShaderID); - - // Check Vertex Shader - glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); - glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - vector VertexShaderErrorMessage(InfoLogLength + 1); - glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, - &VertexShaderErrorMessage[0]); - printf("%s\n", &VertexShaderErrorMessage[0]); - } - - // Compile Fragment Shader - std::cout << "Compiling fragment shader : " << name << std::endl; - - char const * FragmentSourcePointer = FragmentShaderCode.c_str(); - glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); - glCompileShader(FragmentShaderID); - - // Check Fragment Shader - glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); - glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - vector FragmentShaderErrorMessage(InfoLogLength + 1); - glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, - &FragmentShaderErrorMessage[0]); - printf("%s\n", &FragmentShaderErrorMessage[0]); - } - - // Link the program - std::cout << "Linking program : " << name << std::endl; - - GLuint ProgramID = glCreateProgram(); - glAttachShader(ProgramID, VertexShaderID); - glAttachShader(ProgramID, FragmentShaderID); - glLinkProgram(ProgramID); - - // Check the program - glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); - glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - vector ProgramErrorMessage(InfoLogLength + 1); - glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, - &ProgramErrorMessage[0]); - printf("%s\n", &ProgramErrorMessage[0]); - } - - glDetachShader(ProgramID, VertexShaderID); - glDetachShader(ProgramID, FragmentShaderID); - - glDeleteShader(VertexShaderID); - glDeleteShader(FragmentShaderID); - - return ProgramID; -} void Application::loadShader() { if (programId >= 0) @@ -409,6 +366,7 @@ void Application::loadShader() { } void Application::uploadMesh() { + printf("upload mesh\n"); GLCK(glBindVertexArray(vertexArrayId)) GLCK(glBindBuffer(GL_ARRAY_BUFFER, vPositionId)) @@ -428,10 +386,13 @@ void Application::uploadMesh() { glBufferData(GL_ELEMENT_ARRAY_BUFFER, texturemapper.indices.size() * sizeof(uvec3), texturemapper.indices.data(), GL_STATIC_DRAW)) GLCK(glBindVertexArray(0)) +} +void Application::uploadTexture() { + printf("upload texture\n"); glBindTexture(GL_TEXTURE_2D, tAlbedoId); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texturemapper.getTextureSize(), - texturemapper.getTextureSize(), 0, GL_BGR, GL_UNSIGNED_BYTE, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texturemapper.getTextureSize(), + texturemapper.getTextureSize(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texturemapper.albedo.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -446,9 +407,11 @@ void Application::renderMesh() { } void Application::prepareShader() { - glm::mat4 model(1.0f); glm::mat4 view; + double mouseX, mouseY; + glfwGetCursorPos(window, &mouseX, &mouseY); + if (fpsMode) { glm::mat4 fpsTrafoInv = glm::inverse(fpsTrafo); @@ -458,37 +421,53 @@ void Application::prepareShader() { } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { movement -= glm::vec4(0.0, 0.0, 0.1, 0.0); } - double mouseX, mouseY; - glfwGetCursorPos(window, &mouseX, &mouseY); - glm::vec3 up = fpsTrafoInv * glm::vec4(0.0, 1.0, 0.0, 0.0); - glm::vec3 side = fpsTrafoInv * glm::vec4(1.0, 0.0, 0.0, 0.0); - glm::vec3 front = fpsTrafoInv * glm::vec4(0.0, 0.0, 1.0, 0.0); - fpsTrafo = glm::rotate(fpsTrafo, (float)(mouseX - lastMouseX) * 0.01f, up); - fpsTrafo = glm::rotate(fpsTrafo, (float)(mouseY - lastMouseY) * 0.01f, side); + + if (glfwGetMouseButton(window, 0) == GLFW_PRESS) { + glm::vec3 up = fpsTrafoInv * glm::vec4(0.0, 1.0, 0.0, 0.0); + glm::vec3 side = fpsTrafoInv * glm::vec4(1.0, 0.0, 0.0, 0.0); + glm::vec3 front = fpsTrafoInv * glm::vec4(0.0, 0.0, 1.0, 0.0); + fpsTrafo = glm::rotate(fpsTrafo, + (float) (mouseX - lastMouseX) * 0.01f, up); + fpsTrafo = glm::rotate(fpsTrafo, + (float) (mouseY - lastMouseY) * 0.01f, side); + } //fpsTrafo = glm::rotate(fpsTrafo, mouseX - lastMouseX, up); glm::vec3 absolute = fpsTrafoInv * movement; fpsTrafo = glm::translate(fpsTrafo, absolute); - lastMouseX = mouseX; - lastMouseY = mouseY; + view = fpsTrafo; } else { - model = glm::rotate(model, (float) glfwGetTime(), vec3(0.f, 1.f, 0.f)); + + if (!ImGui::IsMouseHoveringAnyWindow() && glfwGetMouseButton(window, 0) == GLFW_PRESS) { + glm::mat4 modelTrafoInv = glm::inverse(modelTrafo); + modelTrafo = glm::rotate(modelTrafo, + (float) (mouseX - lastMouseX) * 0.01f, + vec3(modelTrafoInv * glm::vec4(0.0, 1.0, 0.0, 0.0))); + modelTrafo = glm::rotate(modelTrafo, + (float) (mouseY - lastMouseY) * 0.01f, + vec3(modelTrafoInv * glm::vec4(1.0, 0.0, 0.0, 0.0))); + } + + //model = glm::rotate(model, (float) glfwGetTime(), vec3(0.f, 1.f, 0.f)); view = glm::lookAt(vec3(0, 0, viewDistance), // Camera is at (4,3,3), in World Space vec3(0, 0, 0), // and looks at the origin vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down) ); } + lastMouseX = mouseX; + lastMouseY = mouseY; + glm::mat4 perspective = glm::perspective(glm::radians(45.0f), (float) width / (float) height, 0.1f, 100.0f); - glm::mat4 mvp = perspective * view * model; + glm::mat4 mvp = perspective * view * modelTrafo; GLCK(glUseProgram(programId)) if (MVPloc >= 0) { GLCK(glUniformMatrix4fv(MVPloc, 1, GL_FALSE, glm::value_ptr(mvp))) } if (Mloc >= 0) { - GLCK(glUniformMatrix4fv(Mloc, 1, GL_FALSE, glm::value_ptr(model))) + GLCK(glUniformMatrix4fv(Mloc, 1, GL_FALSE, glm::value_ptr(modelTrafo))) } if (Vloc >= 0) { GLCK(glUniformMatrix4fv(Vloc, 1, GL_FALSE, glm::value_ptr(view))) @@ -536,6 +515,7 @@ void Application::gui() { density.setFrequency(densityFrequency); if (ImGui::SliderFloat("Octave", &densityOctave, 1, 10, "%.0f", 1)) density.setOctave(densityOctave); + ImGui::Checkbox("Smooth", &smoothMesh); // if (ImGui::InputFloat("Frequency", &densityFrequency)) // if (ImGui::InputFloat("Octave", &densityOctave)) @@ -549,9 +529,17 @@ void Application::gui() { texturemapper.setTextureSize(textureSizes[currentTextureSize]); } - if (ImGui::Button("Generate")) { - generateAsteroid(); - uploadMesh(); + if (meshProgress.isRunning()) { + if (ImGui::Button("Cancel")) + meshProgress.cancel(); + ImGui::Text("Task: %s", meshProgress.getTask().c_str()); + ImGui::ProgressBar(meshProgress.getProgress()); + } else { + if (meshProgress.isFinished() && meshThread.joinable()) + meshThread.join(); + + if (ImGui::Button("Generate")) + meshThread = std::thread(&Application::generateAsteroid, this); } ImGui::End(); @@ -590,6 +578,14 @@ void Application::run() { glDepthFunc(GL_LESS); glEnable(GL_CULL_FACE); + if (meshUploadRequest) { + uploadMesh(); + meshUploadRequest = false; + } + if (textureUploadRequest) { + uploadTexture(); + textureUploadRequest = false; + } prepareShader(); renderMesh(); diff --git a/src/Application.h b/src/Application.h index 5641164..6c8efa7 100644 --- a/src/Application.h +++ b/src/Application.h @@ -3,11 +3,13 @@ #include "Density.h" #include "Polygoniser.h" #include "TextureMapper.h" +#include "ProgressMonitor.h" #include #include #include +#include struct GLFWwindow; @@ -29,10 +31,10 @@ class Application { int vPositionLoc, vTexCoordLoc, vNormalLoc, tAlbedoLoc, tNormalLoc, tRoughnessLoc, tMetalicLoc; - std::vector vertices; - std::vector normals; - std::vector texcoords; - std::vector indices; + vec3v_t vertices; + vec3v_t normals; + vec2v_t texcoords; + uvec3v_t indices; size_t meteoridCount; float meteroidMinRadius; @@ -41,12 +43,18 @@ class Application { float densityFrequency, densityOctave; glm::vec3 densityScale; float resolution; + bool smoothMesh; float viewDistance; glm::mat4 fpsTrafo; bool fpsMode; double lastMouseX, lastMouseY; + glm::mat4 modelTrafo; + + ProgressMonitor meshProgress, textureProgress; + std::thread meshThread, textureThread; + bool meshUploadRequest, textureUploadRequest; void toogleFpsMode(); public: @@ -74,11 +82,10 @@ public: void updateVertexArrayObject(); - unsigned int loadProgram(const std::string &name); - void loadShader(); void uploadMesh(); + void uploadTexture(); void renderMesh(); diff --git a/src/Density.h b/src/Density.h index 950befa..b8df532 100644 --- a/src/Density.h +++ b/src/Density.h @@ -53,6 +53,7 @@ public: void setSeed(uint32_t seed) { noise.reseed(seed); + version++; impacts.clear(); } @@ -77,7 +78,7 @@ public: } float operator()(const glm::vec3 &p, bool includeImpacts = true) const { - if (includeImpacts & impacts.size()) { + if (includeImpacts && impacts.size() > 0) { bool insideImpact = false; impactTree.Search(&p.x, &p.x, [&](int idx) -> bool { if (impacts[idx].contains(p)) { @@ -119,6 +120,7 @@ public: Impact impact; if (intersectIsolevel(start, end, impact.pos, isolevel, resolution)) { + impact.pos -= (impact.r / 1.5f) * normalize(end-start); impact.r = minRadius + pow(glm::linearRand(0.f, 1.f), exponent) * maxRadius; addImpact(impact); diff --git a/src/MarchingCube.cpp b/src/MarchingCube.cpp new file mode 100644 index 0000000..c35a74d --- /dev/null +++ b/src/MarchingCube.cpp @@ -0,0 +1,394 @@ +#include "MarchingCube.h" + +#include + +using namespace glm; + +static const int edgeTable[256] = { 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, + 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, + 0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, + 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33, 0x13a, + 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, + 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac, + 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, + 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, + 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, + 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, + 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c, 0xe5c, 0xf55, + 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, + 0x3c6, 0x2cf, 0x1c5, 0xcc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, + 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, + 0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, + 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55, 0x35f, 0x256, + 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, + 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, + 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, + 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, + 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, + 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, + 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230, 0xe90, 0xf99, + 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, + 0x29a, 0x393, 0x99, 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, + 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 }; +static const int triTable[256][16] = { { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1 }, { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }, { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, + 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 9, + 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 2, + 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, { 3, 11, + 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, + 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, + 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, + 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, { 3, + 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, + 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, { 3, + 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, { 9, 8, + 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 4, 7, + 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + + { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 1, 9, + 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 4, 1, 9, 4, + 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 2, 10, 8, 4, + 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 4, 7, 3, 0, 4, + 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, { 9, 2, 10, 9, 0, 2, 8, + 4, 7, -1, -1, -1, -1, -1, -1, -1 }, { 2, 10, 9, 2, 9, 7, 2, 7, + 3, 7, 9, 4, -1, -1, -1, -1 }, { 8, 4, 7, 3, 11, 2, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1 }, { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, + -1, -1, -1, -1, -1, -1 }, { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, + -1, -1, -1, -1, -1 }, { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, + -1, -1, -1, -1 }, { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, + -1, -1, -1, -1 }, { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, + -1, -1, -1 }, { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, + -1, -1 }, { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, + -1, -1 }, { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, + -1 }, { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1 }, + { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, { 5, 2, 10, + 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, { 2, 10, 5, 3, + 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, { 9, 5, 4, 2, 3, 11, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 11, 2, 0, 8, 11, + 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, { 0, 5, 4, 0, 1, 5, 2, 3, + 11, -1, -1, -1, -1, -1, -1, -1 }, { 2, 1, 5, 2, 5, 8, 2, 8, 11, + 4, 8, 5, -1, -1, -1, -1 }, { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, + -1, -1, -1, -1, -1, -1 }, { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, + 10, -1, -1, -1, -1 }, { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, + -1, -1, -1, -1 }, { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, + -1, -1, -1, -1 }, { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }, { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, + -1, -1, -1 }, { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, + -1, -1 }, { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, + -1 }, { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, { + 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, { 2, 10, + 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, { 7, 9, 5, 7, + 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 7, 9, 7, + 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, { 2, 3, 11, 0, 1, 8, 1, + 7, 8, 1, 5, 7, -1, -1, -1, -1 }, { 11, 2, 1, 11, 1, 7, 7, 1, 5, + -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, + 3, 11, -1, -1, -1, -1 }, { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, + 11, 10, 0, -1 }, { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, + 0, -1 }, { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1 }, { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1 }, { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1 }, { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, + -1, -1 }, { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, + -1 }, { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, { 2, 3, 11, 10, + 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 11, 0, 8, 11, + 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, { 0, 1, 9, 2, 3, + 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, { 5, 10, 6, 1, 9, 2, + 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, { 6, 3, 11, 6, 5, 3, 5, 1, + 3, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 11, 0, 11, 5, 0, 5, 1, + 5, 11, 6, -1, -1, -1, -1 }, { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, + 9, -1, -1, -1, -1 }, { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, + -1, -1, -1, -1 }, { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }, { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, + -1, -1, -1 }, { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, + -1, -1 }, + { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, { 6, 1, 2, 6, + 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, { 1, 2, 5, 5, 2, 6, + 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, { 8, 4, 7, 9, 0, 5, 0, 6, 5, + 0, 2, 6, -1, -1, -1, -1 }, { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, + 2, 6, 9, -1 }, { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, + -1, -1, -1 }, { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, + -1, -1 }, + { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, { 9, 2, 1, 9, + 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, { 8, 4, 7, 3, 11, 5, + 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, { 5, 1, 11, 5, 11, 6, 1, 0, + 11, 7, 11, 4, 0, 4, 11, -1 }, { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, + 6, 3, 8, 4, 7, -1 }, { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, + -1, -1, -1 }, { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1 }, { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, + -1, -1 }, { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, + -1 }, { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, { + 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, { 3, 0, + 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, { 0, 2, 4, 4, 2, + 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 8, 3, 2, 8, 2, 4, + 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, { 10, 4, 9, 10, 6, 4, 11, + 2, 3, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 2, 2, 8, 11, 4, 9, + 10, 4, 10, 6, -1, -1, -1, -1 }, { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, + 1, 10, -1, -1, -1, -1 }, { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, + 8, 11, 1, -1 }, { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, + -1, -1 }, { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, + { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, { 6, 4, 8, + 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 7, 10, 6, + 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, { 0, 7, 3, 0, + 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, { 10, 6, 7, 1, 10, + 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, { 10, 6, 7, 10, 7, 1, 1, + 7, 3, -1, -1, -1, -1, -1, -1, -1 }, { 1, 2, 6, 1, 6, 8, 1, 8, 9, + 8, 6, 7, -1, -1, -1, -1 }, { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, + 7, 3, 9, -1 }, { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, + -1, -1 }, { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1 }, { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, + -1 }, { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, { + 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, { 11, 2, + 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, { 8, 9, 6, 8, + 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, { 0, 9, 1, 11, 6, 7, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 7, 8, 0, 7, 0, 6, 3, 11, + 0, 11, 6, 0, -1, -1, -1, -1 }, { 7, 11, 6, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, { 7, 6, 11, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 0, 8, 11, 7, 6, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 1, 9, 11, 7, 6, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 8, 1, 9, 8, 3, 1, 11, 7, + 6, -1, -1, -1, -1, -1, -1, -1 }, { 10, 1, 2, 6, 11, 7, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 2, 10, 3, 0, 8, 6, 11, 7, + -1, -1, -1, -1, -1, -1, -1 }, { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, + -1, -1, -1, -1, -1, -1 }, { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, + 8, -1, -1, -1, -1 }, { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }, { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, + -1, -1, -1 }, { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, + -1, -1 }, + { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, { 10, 7, 6, 10, + 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, { 10, 7, 6, 1, 7, + 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, { 0, 3, 7, 0, 7, 10, 0, + 10, 9, 6, 10, 7, -1, -1, -1, -1 }, { 7, 6, 10, 7, 10, 8, 8, 10, + 9, -1, -1, -1, -1, -1, -1, -1 }, { 6, 8, 4, 11, 8, 6, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 6, 11, 3, 0, 6, 0, 4, 6, + -1, -1, -1, -1, -1, -1, -1 }, { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, + -1, -1, -1, -1, -1, -1 }, { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, + -1, -1, -1, -1 }, { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, + -1, -1, -1 }, { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, + -1, -1 }, { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, + -1 }, { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, { + 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, { 0, 4, + 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 9, 0, + 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, { 1, 9, 4, 1, 4, 2, + 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, { 8, 1, 3, 8, 6, 1, 8, 4, + 6, 6, 10, 1, -1, -1, -1, -1 }, { 10, 1, 0, 10, 0, 6, 6, 0, 4, + -1, -1, -1, -1, -1, -1, -1 }, { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, + 3, 9, 10, 9, 3, -1 }, { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1 }, { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1 }, { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, + -1, -1, -1, -1 }, { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, + -1, -1, -1 }, { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, + -1 }, + { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, { 6, 11, 7, + 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, { 7, 6, 11, 5, 4, + 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, { 3, 4, 8, 3, 5, 4, 3, + 2, 5, 10, 5, 2, 11, 7, 6, -1 }, { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, + -1, -1, -1, -1, -1, -1 }, { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, + -1, -1, -1, -1 }, { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, + -1, -1 }, { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, { + 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, { 1, 6, + 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, { 4, 0, 10, 4, 10, + 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, { 7, 6, 10, 7, 10, 8, 5, + 4, 10, 4, 8, 10, -1, -1, -1, -1 }, { 6, 9, 5, 6, 11, 9, 11, 8, + 9, -1, -1, -1, -1, -1, -1, -1 }, { 3, 6, 11, 0, 6, 3, 0, 5, 6, + 0, 9, 5, -1, -1, -1, -1 }, { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, + 11, -1, -1, -1, -1 }, { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, + -1, -1, -1, -1 }, { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, + -1, -1, -1 }, { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, + -1 }, { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, { + 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, { 5, 8, + 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, { 9, 5, 6, 9, 6, + 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, { 1, 5, 8, 1, 8, 0, 5, + 6, 8, 3, 8, 2, 6, 2, 8, -1 }, { 1, 5, 6, 2, 1, 6, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1 }, { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, + 6, 9, 8, 9, 6, -1 }, { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, + -1, -1, -1 }, { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1 }, { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }, { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }, { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, + -1, -1, -1, -1 }, { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, + -1, -1, -1, -1 }, { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, + -1, -1, -1 }, { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, + -1, -1 }, + { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, { 9, 7, 5, 9, + 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, { 7, 5, 2, 7, 2, 11, + 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, { 2, 5, 10, 2, 3, 5, 3, 7, 5, + -1, -1, -1, -1, -1, -1, -1 }, { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, + 2, 5, -1, -1, -1, -1 }, { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, + -1, -1, -1, -1 }, { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, + 2, -1 }, { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1 }, { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, { 9, 8, 7, 5, + 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 5, 8, 4, 5, + 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, { 5, 0, 4, 5, + 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, { 0, 1, 9, 8, 4, + 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, { 10, 11, 4, 10, 4, + 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, { 2, 5, 1, 2, 8, 5, 2, 11, + 8, 4, 5, 8, -1, -1, -1, -1 }, { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, + 11, 1, 5, 1, 11, -1 }, { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, + 11, 8, 5, -1 }, { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1 }, { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, + -1 }, + { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, { 3, 10, 2, + 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, { 5, 10, 2, 5, 2, 4, + 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, { 8, 4, 5, 8, 5, 3, 3, 5, 1, + -1, -1, -1, -1, -1, -1, -1 }, { 0, 4, 5, 1, 0, 5, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1 }, { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, + 5, -1, -1, -1, -1 }, { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1 }, { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, + -1, -1, -1, -1, -1 }, { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, + -1, -1, -1, -1 }, { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, + -1, -1, -1 }, { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, + -1 }, { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, + { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, { 11, 7, 4, 11, + 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, { 11, 7, 4, 11, 4, + 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, { 2, 9, 10, 2, 7, 9, 2, + 3, 7, 7, 4, 9, -1, -1, -1, -1 }, { 9, 10, 7, 9, 7, 4, 10, 2, 7, + 8, 7, 0, 2, 0, 7, -1 }, { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, + 0, 4, 0, 10, -1 }, { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1 }, { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, + -1, -1, -1 }, { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, + -1 }, + { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 4, 8, 7, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 9, 10, + 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 0, + 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, { 0, 1, + 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, { 3, 1, + 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 2, + 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, { 3, 0, 9, + 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, { 0, 2, 11, 8, 0, + 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 2, 11, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 2, 3, 8, 2, + 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, { 9, 10, 2, 0, 9, + 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 2, 3, 8, 2, 8, + 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, { 1, 10, 2, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 3, 8, 9, 1, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 9, 1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 3, 8, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }; + +/* + Linearly interpolate the position where an isosurface cuts + an edge between two vertices, each with their own scalar value + */ +XYZ VertexInterp(double isolevel, XYZ p1, XYZ p2, double valp1, double valp2) { + double mu; + XYZ p; + float dx = p2.x - p1.x; + float dy = p2.y - p1.y; + float dz = p2.z - p1.z; + float eps = sqrt(dx*dx+dy*dy+dz*dz) * 0.05; + if (fabs(isolevel - valp1) < eps) + return (p1); + if (fabs(isolevel - valp2) < eps) + return (p2); + if (fabs(valp1 - valp2) < 0.0001) + return (p1); + + mu = (isolevel - valp1) / (valp2 - valp1); + p.x = p1.x + mu * dx; + p.y = p1.y + mu * dy; + p.z = p1.z + mu * dz; + + return (p); +} + +/* + Given a grid cell and an isolevel, calculate the triangular + facets required to represent the isosurface through the cell. + Return the number of triangular facets, the array "triangles" + will be loaded up with the vertices at most 5 triangular facets. + 0 will be returned if the grid cell is either totally above + of totally below the isolevel. + */ +int Polygonise(GRIDCELL &grid, double isolevel, TRIANGLE *triangles) { + int i, ntriang; + int cubeindex; + XYZ vertlist[12]; + + /* + Determine the index into the edge table which + tells us which vertices are inside of the surface + */ + cubeindex = 0; + if (grid.val[0] < isolevel) + cubeindex |= 1; + if (grid.val[1] < isolevel) + cubeindex |= 2; + if (grid.val[2] < isolevel) + cubeindex |= 4; + if (grid.val[3] < isolevel) + cubeindex |= 8; + if (grid.val[4] < isolevel) + cubeindex |= 16; + if (grid.val[5] < isolevel) + cubeindex |= 32; + if (grid.val[6] < isolevel) + cubeindex |= 64; + if (grid.val[7] < isolevel) + cubeindex |= 128; + + /* Cube is entirely in/out of the surface */ + if (edgeTable[cubeindex] == 0) + return (0); + + /* Find the vertices where the surface intersects the cube */ + if (edgeTable[cubeindex] & 1) + vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0], + grid.val[1]); + if (edgeTable[cubeindex] & 2) + vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1], + grid.val[2]); + if (edgeTable[cubeindex] & 4) + vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2], + grid.val[3]); + if (edgeTable[cubeindex] & 8) + vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3], + grid.val[0]); + if (edgeTable[cubeindex] & 16) + vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4], + grid.val[5]); + if (edgeTable[cubeindex] & 32) + vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5], + grid.val[6]); + if (edgeTable[cubeindex] & 64) + vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6], + grid.val[7]); + if (edgeTable[cubeindex] & 128) + vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7], + grid.val[4]); + if (edgeTable[cubeindex] & 256) + vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0], + grid.val[4]); + if (edgeTable[cubeindex] & 512) + vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1], + grid.val[5]); + if (edgeTable[cubeindex] & 1024) + vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2], + grid.val[6]); + if (edgeTable[cubeindex] & 2048) + vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3], + grid.val[7]); + + /* Create the triangle */ + ntriang = 0; + for (i = 0; triTable[cubeindex][i] != -1; i += 3) { + triangles[ntriang].p[0] = vertlist[triTable[cubeindex][i]]; + triangles[ntriang].p[1] = vertlist[triTable[cubeindex][i + 1]]; + triangles[ntriang].p[2] = vertlist[triTable[cubeindex][i + 2]]; + ntriang++; + } + + return (ntriang); +} diff --git a/src/MarchingCube.h b/src/MarchingCube.h new file mode 100644 index 0000000..161e3af --- /dev/null +++ b/src/MarchingCube.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +typedef glm::vec3 XYZ; + +struct TRIANGLE { + XYZ p[3]; +}; + +struct GRIDCELL { + XYZ p[8]; + double val[8]; +} ; + +int Polygonise(GRIDCELL &grid, double isolevel, TRIANGLE *triangles); diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 2ab1e21..5d278f5 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -3,16 +3,25 @@ #include #include +#include +#include using namespace std; using namespace glm; -void calculateNormals(const vec3v_t &vtx, uvec3v_t &tri, vec3v_t &normals) { +static const uvec3::value_type InvalidIndex = + numeric_limits::max(); + +void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices, + vec3v_t &normals) { normals.clear(); - normals.resize(vtx.size(), vec3(0)); - for (size_t i = 0; i < tri.size(); i++) { - int a = tri[i].x, b = tri[i].y, c = tri[i].z; - vec3 faceNormal = normalize(cross(vtx[b] - vtx[a], vtx[c] - vtx[a])); + normals.resize(positions.size(), vec3(0)); + #pragma omp parallel for + for (size_t i = 0; i < indices.size(); i++) { + int a = indices[i].x, b = indices[i].y, c = indices[i].z; + vec3 faceNormal = normalize( + cross(positions[b] - positions[a], + positions[c] - positions[a])); normals[a] += faceNormal; normals[b] += faceNormal; normals[c] += faceNormal; @@ -22,27 +31,40 @@ void calculateNormals(const vec3v_t &vtx, uvec3v_t &tri, vec3v_t &normals) { } -void moveToMean(vec3v_t &vtx) { - vec3 mean(0); - for (size_t i = 0; i < vtx.size(); i++) { - mean += vtx[i]; - } - mean *= vec3(1.f / vtx.size()); - for (size_t i = 0; i < vtx.size(); i++) { - vtx[i] -= mean; +void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices, + vec3v_t &normals) { + normals.clear(); + normals.resize(indices.size(), vec3(uninitialize)); + #pragma omp parallel for + for (size_t i = 0; i < indices.size(); i++) { + int a = indices[i].x, b = indices[i].y, c = indices[i].z; + normals[i] = normalize( + cross(positions[b] - positions[a], + positions[c] - positions[a])); } } -void smooth(vec3v_t &vtx, const uvec3v_t &tri) { - vec3v_t cogs(vtx.size(), vec3(0.f)); - vector valence(vtx.size(), 0); +void moveToMean(vec3v_t &positions) { + vec3 mean(0); + for (size_t i = 0; i < positions.size(); i++) { + mean += positions[i]; + } + mean *= vec3(1.f / positions.size()); + for (size_t i = 0; i < positions.size(); i++) { + positions[i] -= mean; + } +} - for (size_t iTri = 0; iTri < tri.size(); iTri++) { - const uvec3 &idx = tri[iTri]; +void smooth(vec3v_t &positions, const uvec3v_t &indices) { + vec3v_t cogs(positions.size(), vec3(0.f)); + vector valence(positions.size(), 0); + + for (size_t iTri = 0; iTri < indices.size(); iTri++) { + const uvec3 &idx = indices[iTri]; for (size_t iE = 0; iE < 3; iE++) { valence[idx[iE]] += 2; - cogs[idx[iE]] += vtx[idx[(iE + 1) % 3]]; - cogs[idx[iE]] += vtx[idx[(iE + 2) % 3]]; + cogs[idx[iE]] += positions[idx[(iE + 1) % 3]]; + cogs[idx[iE]] += positions[idx[(iE + 2) % 3]]; } } /* @@ -61,10 +83,11 @@ void smooth(vec3v_t &vtx, const uvec3v_t &tri) { mesh.set_point(*v_it, *cog_it); */ - for (size_t i = 0; i < vtx.size(); i++) { + #pragma omp parallel for + for (size_t i = 0; i < positions.size(); i++) { // vtx[i] = vtx[i] * vec3(0.8) // + cogs[i] * vec3(0.2f / valence[i]); - vtx[i] = cogs[i] * vec3(1.f / valence[i]); + positions[i] = cogs[i] * vec3(1.f / valence[i]); } } @@ -81,12 +104,12 @@ void saveAttrib(std::ostream &out, const char *prefix, vec2v_t &elements) { } } -void saveFaces(std::ostream &out, const uvec3v_t &tris, size_t attribs) { - for (size_t i = 0; i < tris.size(); i++) { +void saveFaces(std::ostream &out, const uvec3v_t &incdices, size_t attribs) { + for (size_t i = 0; i < incdices.size(); i++) { out << "f"; for (size_t j = 0; j < 3; j++) { - int v = tris[i][j] + 1; + int v = incdices[i][j] + 1; out << " " << v; if (attribs > 1) out << "/" << v; @@ -99,39 +122,43 @@ void saveFaces(std::ostream &out, const uvec3v_t &tris, size_t attribs) { } } -void findEdges(const vec3v_t &vtx, uvec3v_t &tri, uvec4v_t &edges) { +void findEdges(const vec3v_t &positions, const uvec3v_t &indices, + uvec4v_t &edges) { edges.clear(); map, uint32_t> edgeMap; - for (size_t iTri = 0; iTri < tri.size(); iTri++) { - uvec3 idx = tri[iTri]; + for (size_t iTri = 0; iTri < indices.size(); iTri++) { + uvec3 idx = indices[iTri]; for (size_t k = 0; k < 3; k++) { int a = idx[k]; int b = idx[(k + 1) % 3]; uvec4 edge1(std::min(a, b), std::max(a, b), iTri, 0); - auto it1 = edgeMap.find(std::make_pair(edge1.x, edge1.y)); + auto key = std::make_pair(edge1.x, edge1.y); + auto it1 = edgeMap.find(key); if (it1 != edgeMap.end()) { - edges[it1->second].z = iTri; + edges[it1->second].w = iTri; } else { + size_t idx = edges.size(); edges.push_back(edge1); + edgeMap[key] = idx; } } } } -void computeTangentBasis(vec3v_t & vertices, vec2v_t & uvs, vec3v_t & normals, - vec3v_t & tangents, vec3v_t & bitangents) { +void computeTangentBasis(vec3v_t & positions, vec2v_t & texcoords, + vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents) { - for (size_t i = 0; i < vertices.size(); i += 3) { + for (size_t i = 0; i < positions.size(); i += 3) { // Shortcuts for vertices - vec3 & v0 = vertices[i + 0]; - vec3 & v1 = vertices[i + 1]; - vec3 & v2 = vertices[i + 2]; + vec3 & v0 = positions[i + 0]; + vec3 & v1 = positions[i + 1]; + vec3 & v2 = positions[i + 2]; // Shortcuts for UVs - vec2 & uv0 = uvs[i + 0]; - vec2 & uv1 = uvs[i + 1]; - vec2 & uv2 = uvs[i + 2]; + vec2 & uv0 = texcoords[i + 0]; + vec2 & uv1 = texcoords[i + 1]; + vec2 & uv2 = texcoords[i + 2]; // Edges of the triangle : postion delta vec3 deltaPos1 = v1 - v0; @@ -157,3 +184,85 @@ void computeTangentBasis(vec3v_t & vertices, vec2v_t & uvs, vec3v_t & normals, } } + +void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents) { + printf("findAdjacent: %lu\n", nFaces); + adjacents.resize(nFaces, uvec3(InvalidIndex)); + for (size_t i = 0; i < edges.size(); i++) { + int a = edges[i].z; + int b = edges[i].w; + + uvec3 &aa = adjacents[a]; + for (size_t j = 0; j < 3; j++) { + if (aa[j] == InvalidIndex) { + aa[j] = b; + break; + } + } + uvec3 &ab = adjacents[b]; + for (size_t j = 0; j < 3; j++) { + if (ab[j] == InvalidIndex) { + ab[j] = a; + break; + } + } + } +} + +void createPatches(const vec3v_t &positions, const uvec3v_t &indices, + const vec3v_t &faceNormals, const uvec3v_t &adjacents, + vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches, + float threshold) { + assert(adjacents.size() == indices.size()); + patches.clear(); + oPositions.clear(); + oIndices.clear(); + vector processed(indices.size(), false); + + for (size_t i = 0; i < indices.size(); i++) { + if (processed[i]) + continue; + vector faces; + map vertexMap; + + vec3 normal = faceNormals[i]; + + // check all adjacent faces + stack facesToCheck; + facesToCheck.push(i); + while (facesToCheck.size()) { + uint32_t face = facesToCheck.top(); + facesToCheck.pop(); + if (face == InvalidIndex || processed[face]) + continue; + if (dot(normal, faceNormals[face]) > threshold) { + faces.push_back(face); + //normal = normalize(normal + 0.5f * faceNormals[face]); + processed[face] = true; + facesToCheck.push(adjacents[face].x); + facesToCheck.push(adjacents[face].y); + facesToCheck.push(adjacents[face].z); + } + } + + // fill new arrays + for (size_t j = 0; j < faces.size(); j++) { + uvec3 idx = indices[faces[j]]; + for (size_t k = 0; k < 3; k++) { + auto it = vertexMap.find(idx[k]); + if (it == vertexMap.end()) { + uint32_t newIdx = oPositions.size(); + oPositions.push_back(positions[idx[k]]); + vertexMap[idx[k]] = newIdx; + idx[k] = newIdx; + } else { + idx[k] = it->second; + } + } + oIndices.push_back(idx); + } + printf("\n"); + } + +} + diff --git a/src/Mesh.h b/src/Mesh.h index f21760e..1cc4083 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -1,28 +1,35 @@ #pragma once +#include "types.h" + #include #include -#include -#include +void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices, + vec3v_t &normals); +void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices, + vec3v_t &normals); +void findEdges(const vec3v_t &positions, const uvec3v_t &indices, + uvec4v_t &edges); +//void createPatches(const vec3v_t &positions, const uvec3v_t &indices, +// const uvec4v_t &edges, vec3v_t &oPositions, uvec3v_t &oIndices, +// uvec4v_t &oEdges, uintv_t &patches, float threshold); -typedef std::vector vec3v_t; -typedef std::vector vec2v_t; -typedef std::vector uvec3v_t; -typedef std::vector uvec4v_t; +void moveToMean(vec3v_t &positions); -void calculateNormals(const vec3v_t &vtx, uvec3v_t &tri, vec3v_t &normals); -void findEdges(const vec3v_t &vtx, uvec3v_t &tri, uvec4v_t &edges); - -void moveToMean(vec3v_t &vtx); - -void smooth(vec3v_t &vtx, const uvec3v_t &tri); +void smooth(vec3v_t &positions, const uvec3v_t &indices); void saveAttrib(std::ostream &out, const char *prefix, vec3v_t &elements); void saveAttrib(std::ostream &out, const char *prefix, vec2v_t &elements); -void saveFaces(std::ostream &out, const uvec3v_t &tris, size_t attribs); +void saveFaces(std::ostream &out, const uvec3v_t &indicess, size_t attributes); -void computeTangentBasis(vec3v_t & vertices, vec2v_t & uvs, vec3v_t & normals, - vec3v_t & tangents, vec3v_t & bitangents); +void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents); + +void computeTangentBasis(vec3v_t & vertices, vec2v_t & texcoords, + vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents); +void createPatches(const vec3v_t &positions, const uvec3v_t &indices, + const vec3v_t &faceNormals, const uvec3v_t &adjacents, + vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches, + float threshold); diff --git a/src/Polygoniser.cpp b/src/Polygoniser.cpp index dfe016d..ffe6a47 100644 --- a/src/Polygoniser.cpp +++ b/src/Polygoniser.cpp @@ -5,31 +5,33 @@ #include -#include +#include "MarchingCube.h" -static const int isocells = 32; +using namespace glm; + +#define ISOCELL 0 +static const int isocells = 50; Polygonizer::Polygonizer(Density &density, float isolevel) : - density(density), isolevel(isolevel) { - updateIsocell(); + density(density), isolevel(isolevel), isocellIsolevel(0), isocellVersion( + 0) { } void Polygonizer::setIsoLevel(float isolevel) { - bool needIsocellUpdate = false; - if (this->isolevel != isolevel) { - this->isolevel = isolevel; - needIsocellUpdate = true; - } - needIsocellUpdate |= (isocellVersion != density.getVersion()); - if (needIsocellUpdate) - updateIsocell(); + this->isolevel = isolevel; } +#if ISOCELL void Polygonizer::updateIsocell() { + if (density.getVersion() == isocellVersion && isocellIsolevel == isolevel) + return; isocell.clear(); - isocell.reserve(isocells * isocells * isocells); + isocell.resize(isocells * isocells * isocells); - float step = 1. / isocells; + const float lowerIso = isolevel * 0.7; + const float upperIso = isolevel * 1.3; + const float step = 1. / isocells; +#pragma omp parallel for for (size_t ix = 0; ix < isocells; ix++) { float xmin = ix * step; float xmax = xmin + step; @@ -41,10 +43,10 @@ void Polygonizer::updateIsocell() { float Xyz = density(vec3(xmax, ymin, 0)); float xYz = density(vec3(xmin, ymax, 0)); float XYz = density(vec3(xmax, ymax, 0)); - bool zAllUnder = (xyz < isolevel) && (Xyz < isolevel) - && (xYz < isolevel) && (XYz < isolevel); - bool zAllOver = (xyz > isolevel) && (Xyz > isolevel) - && (xYz > isolevel) && (XYz > isolevel); + bool zAllUnder = (xyz < lowerIso) && (Xyz < lowerIso) + && (xYz < lowerIso) && (XYz < lowerIso); + bool zAllOver = (xyz > upperIso) && (Xyz > upperIso) + && (xYz > upperIso) && (XYz > upperIso); for (size_t iz = 0; iz < isocells; iz++) { float zmin = iz * step; @@ -54,13 +56,13 @@ void Polygonizer::updateIsocell() { float XyZ = density(vec3(xmax, ymin, zmax)); float xYZ = density(vec3(xmin, ymax, zmax)); float XYZ = density(vec3(xmax, ymax, zmax)); - bool ZAllUnder = (xyZ < isolevel) && (XyZ < isolevel) - && (xYZ < isolevel) && (XYZ < isolevel); - bool ZAllOver = (xyZ > isolevel) && (XyZ > isolevel) - && (xYZ > isolevel) && (XYZ > isolevel); + bool ZAllUnder = (xyZ < lowerIso) && (XyZ < lowerIso) + && (xYZ < lowerIso) && (XYZ < lowerIso); + bool ZAllOver = (xyZ > upperIso) && (XyZ > upperIso) + && (xYZ > upperIso) && (XYZ > upperIso); isocell[ix * isocells * isocells + iy * isocells + iz] = - (zAllUnder && ZAllUnder) || (zAllOver && ZAllOver); + !((zAllUnder && ZAllUnder) || (zAllOver && ZAllOver)); xyz = xyZ; Xyz = XyZ; @@ -71,19 +73,25 @@ void Polygonizer::updateIsocell() { } } } + + size_t n = 0; + for(size_t i = 0; i < isocell.size(); i++) + if(isocell[i]) n++; + printf("%lu / %lu", n, isocell.size()); isocellVersion = density.getVersion(); + isocellIsolevel = isolevel; } -void Polygonizer::polygonize(const glm::vec3 lower, const glm::vec3 upper, +void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper, float resolution) { - size_t nSteps = 1.f / resolution - 1; - size_t nT = 0; - for (size_t ix = 0; ix < nSteps; ix++) { + vec3 l = round(lower * vec3(1.f / resolution)); + vec3 u = round(upper * vec3(1.f / resolution)); + for (size_t ix = l.x; ix < u.x; ix++) { double x = (double(ix) + 0.5) * resolution; - for (size_t iy = 0; iy < nSteps; iy++) { + for (size_t iy = l.y; iy < u.y; iy++) { double y = (double(iy) + 0.5) * resolution; - for (size_t iz = 0; iz < nSteps; iz++) { + for (size_t iz = l.z; iz < u.z; iz++) { double z = (double(iz) + 0.5) * resolution; GRIDCELL gridCell; @@ -103,7 +111,6 @@ void Polygonizer::polygonize(const glm::vec3 lower, const glm::vec3 upper, TRIANGLE tris[6]; int nTris = Polygonise(gridCell, isolevel, tris); - nT += nTris; for (int iTri = 0; iTri < nTris; iTri++) { vec3 *ps = tris[iTri].p; @@ -111,13 +118,13 @@ void Polygonizer::polygonize(const glm::vec3 lower, const glm::vec3 upper, if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) || all(epsilonEqual(ps[0], ps[2], 1e-8f)) || all(epsilonEqual(ps[2], ps[1], 1e-8f))) - continue; + continue; - glm::uvec3 idc; + uvec3 idc; for (size_t k = 0; k < 3; k++) { - glm::vec3 &p = tris[iTri].p[k]; - std::map::iterator vit = - vertexLookup.find(p); + vec3 &p = tris[iTri].p[k]; + std::map::iterator vit = vertexLookup.find( + p); if (vit != vertexLookup.end()) { idc[k] = vit->second; } else { @@ -138,36 +145,116 @@ void Polygonizer::polygonize(float resolution) { vertices.clear(); indices.clear(); -// coarse scan - float coarseResolution = resolution * 10; + const float isocellSize = 1.f / isocells; + if (resolution < isocellSize) { + updateIsocell(); - size_t nSteps = 1.f / resolution - 1; - size_t nT = 0; - for (size_t ix = 0; ix < nSteps; ix++) { - double x = (double(ix) + 0.5) * resolution; - for (size_t iy = 0; iy < nSteps; iy++) { - double y = (double(iy) + 0.5) * resolution; - for (size_t iz = 0; iz < nSteps; iz++) { - double z = (double(iz) + 0.5) * resolution; + vec3 lower, upper; + for (size_t ix = 0; ix < isocells - 1; ix++) { + lower.x = double(ix) * isocellSize; + upper.x = lower.x + isocellSize; + for (size_t iy = 0; iy < isocells - 1; iy++) { + lower.y = (double(iy) + 0.5) * isocellSize; + upper.y = lower.y + isocellSize; + for (size_t iz = 0; iz < isocells - 1; iz++) { + if (!isocell[ix * isocells * isocells + iy * isocells + iz]) + continue; + lower.z = (double(iz) + 0.5) * isocellSize; + upper.z = lower.z + isocellSize; - GRIDCELL gridCell; - gridCell.p[0] = vec3(x, y, z); - gridCell.p[1] = vec3(x + resolution, y, z); - gridCell.p[2] = vec3(x + resolution, y + resolution, z); - gridCell.p[3] = vec3(x, y + resolution, z); - gridCell.p[4] = vec3(x, y, z + resolution); - gridCell.p[5] = vec3(x + resolution, y, z + resolution); - gridCell.p[6] = vec3(x + resolution, y + resolution, - z + resolution); - gridCell.p[7] = vec3(x, y + resolution, z + resolution); - - for (size_t iCell = 0; iCell < 8; iCell++) { - gridCell.val[iCell] = density(gridCell.p[iCell]); + polygonize(lower, upper, resolution); } + } + } + } else { + polygonize(vec3(0.f), vec3(1.0f), resolution); + } +} + +#else +void Polygonizer::calculateLayer(std::vector &layer, float resolution, + size_t nSamples, float z) { +#pragma omp parallel for + for (size_t iy = 0; iy < nSamples; iy++) { + float y = iy * resolution; + size_t offset = iy * nSamples; + for (size_t ix = 0; ix < nSamples; ix++) { + float x = ix * resolution; + layer[offset + ix] = density(glm::vec3(x, y, z)); + } + } +} + +void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) { + vertexLookup.clear(); + vertices.clear(); + indices.clear(); + + vertices.reserve(pow(1. / resolution, 2) * 8); + indices.reserve(pow(1. / resolution, 2) * 8); + size_t nSteps = 1.f / resolution; + size_t nSamples = nSteps + 1; + + // precalculate 2 layers + std::vector layers[2]; + layers[0].resize(nSamples * nSamples); + layers[1].resize(nSamples * nSamples); + + calculateLayer(layers[0], resolution, nSamples, 0.0); + + progress.begin("Polygonize", nSteps); + + for (size_t iz = 0; iz < nSteps; iz++) { + std::vector &zLayer = layers[iz % 2]; + std::vector &ZLayer = layers[(iz + 1) % 2]; + float z = iz * resolution; + float Z = z + resolution; + calculateLayer(ZLayer, resolution, nSamples, Z); + + if (!progress.advance()) + break; + + for (size_t iy = 0; iy < nSteps; iy++) { + float y = iy * resolution; + float Y = y + resolution; + size_t yOffset = iy * nSamples; + size_t YOffset = yOffset + nSamples; + + GRIDCELL gridCell; + gridCell.p[0] = vec3(0, y, z); + gridCell.p[1] = vec3(0, y, z); + gridCell.p[2] = vec3(0, Y, z); + gridCell.p[3] = vec3(0, Y, z); + gridCell.p[4] = vec3(0, y, Z); + gridCell.p[5] = vec3(0, y, Z); + gridCell.p[6] = vec3(0, Y, Z); + gridCell.p[7] = vec3(0, Y, Z); + + for (size_t ix = 0; ix < nSteps; ix++) { + float x = ix * resolution; + float X = x + resolution; + + gridCell.p[0].x = x; + gridCell.p[1].x = X; + gridCell.p[2].x = X; + gridCell.p[3].x = x; + gridCell.p[4].x = x; + gridCell.p[5].x = X; + gridCell.p[6].x = X; + gridCell.p[7].x = x; + + gridCell.val[0] = zLayer[yOffset + ix]; + gridCell.val[1] = zLayer[yOffset + ix + 1]; + gridCell.val[2] = zLayer[YOffset + ix + 1]; + gridCell.val[3] = zLayer[YOffset + ix]; + + gridCell.val[4] = ZLayer[yOffset + ix]; + gridCell.val[5] = ZLayer[yOffset + ix + 1]; + gridCell.val[6] = ZLayer[YOffset + ix + 1]; + gridCell.val[7] = ZLayer[YOffset + ix]; TRIANGLE tris[6]; int nTris = Polygonise(gridCell, isolevel, tris); - nT += nTris; for (int iTri = 0; iTri < nTris; iTri++) { vec3 *ps = tris[iTri].p; @@ -177,11 +264,11 @@ void Polygonizer::polygonize(float resolution) { || all(epsilonEqual(ps[2], ps[1], 1e-8f))) continue; - glm::uvec3 idc; + uvec3 idc; for (size_t k = 0; k < 3; k++) { - glm::vec3 &p = tris[iTri].p[k]; - std::map::iterator vit = - vertexLookup.find(p); + vec3 &p = tris[iTri].p[k]; + std::map::iterator vit = vertexLookup.find( + p); if (vit != vertexLookup.end()) { idc[k] = vit->second; } else { @@ -197,3 +284,75 @@ void Polygonizer::polygonize(float resolution) { } } + +//void Polygonizer::polygonize(float resolution) { +// vertexLookup.clear(); +// vertices.clear(); +// indices.clear(); +// +// size_t nSteps = 1.f / resolution; +// size_t nSamples = nSteps + 1; +// +// // precalculate 2 layers +// std::vector layers[2]; +// layers[0].resize(nSamples*nSamples); +// layers[1].resize(nSamples*nSamples); +// +// calculateLayer(layers[0], resolution, nSamples, 0.0); +// +// size_t nT = 0; +// for (size_t ix = 0; ix < nSteps; ix++) { +// double x = (double(ix) + 0.5) * resolution; +// for (size_t iy = 0; iy < nSteps; iy++) { +// double y = (double(iy) + 0.5) * resolution; +// for (size_t iz = 0; iz < nSteps; iz++) { +// double z = (double(iz) + 0.5) * resolution; +// +// GRIDCELL gridCell; +// gridCell.p[0] = vec3(x, y, z); +// gridCell.p[1] = vec3(x + resolution, y, z); +// gridCell.p[2] = vec3(x + resolution, y + resolution, z); +// gridCell.p[3] = vec3(x, y + resolution, z); +// gridCell.p[4] = vec3(x, y, z + resolution); +// gridCell.p[5] = vec3(x + resolution, y, z + resolution); +// gridCell.p[6] = vec3(x + resolution, y + resolution, +// z + resolution); +// gridCell.p[7] = vec3(x, y + resolution, z + resolution); +// +// for (size_t iCell = 0; iCell < 8; iCell++) { +// gridCell.val[iCell] = density(gridCell.p[iCell]); +// } +// +// TRIANGLE tris[6]; +// int nTris = Polygonise(gridCell, isolevel, tris); +// nT += nTris; +// for (int iTri = 0; iTri < nTris; iTri++) { +// vec3 *ps = tris[iTri].p; +// +// // skip degenerate vertices +// if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) +// || all(epsilonEqual(ps[0], ps[2], 1e-8f)) +// || all(epsilonEqual(ps[2], ps[1], 1e-8f))) +// continue; +// +// uvec3 idc; +// for (size_t k = 0; k < 3; k++) { +// vec3 &p = tris[iTri].p[k]; +// std::map::iterator vit = vertexLookup.find( +// p); +// if (vit != vertexLookup.end()) { +// idc[k] = vit->second; +// } else { +// idc[k] = vertices.size(); +// vertices.push_back(p); +// vertexLookup[p] = idc[k]; +// } +// } +// indices.push_back(idc); +// } +// } +// } +// } +// +//} +#endif diff --git a/src/Polygoniser.h b/src/Polygoniser.h index 40789be..de4d98e 100644 --- a/src/Polygoniser.h +++ b/src/Polygoniser.h @@ -3,9 +3,9 @@ #include #include -#include - +#include "types.h" #include "Density.h" +#include "ProgressMonitor.h" struct CompareVec3 { bool operator()(const glm::vec3 &lhs, const glm::vec3 &rhs) { @@ -36,20 +36,26 @@ struct CompareVec3 { class Polygonizer { Density &density; float isolevel; -public: - std::vector vertices; - std::vector indices; - std::map vertexLookup; std::vector isocell; size_t isocellVersion; + float isocellIsolevel; + + void polygonize(const glm::vec3 &lower, const glm::vec3 &upper, + float isolevel); + + void calculateLayer(std::vector &layer, float resolution, size_t nSamples, float z); + +public: + vec3v_t vertices; + uvec3v_t indices; + std::map vertexLookup; + Polygonizer(Density &density, float isolevel); void setIsoLevel(float isolevel); void updateIsocell(); - void polygonize(float resolution); - void polygonize(const glm::vec3 lower, const glm::vec3 upper, - float isolevel); + void polygonize(float resolution, ProgressMonitor &progress); }; diff --git a/src/ProgressMonitor.h b/src/ProgressMonitor.h new file mode 100644 index 0000000..0f1432e --- /dev/null +++ b/src/ProgressMonitor.h @@ -0,0 +1,77 @@ +#pragma once + +#include + +class ProgressMonitor { +public: + ProgressMonitor() : + finished(false), running(false), canceled(false), steps(0), currentStep( + 0) { + + } + + bool begin(std::string task, size_t steps) { + if (canceled) + return false; + this->task = task; + this->steps = steps; + this->running = true; + finished = false; + currentStep = 0; + return true; + } + + bool advance(size_t count = 1) { + currentStep += count; + return !canceled; + } + + size_t getSteps() { + return steps; + } + + size_t getCurrentStep() { + return currentStep; + } + + float getProgress() { + return float(currentStep) / float(steps); + } + + void finish() { + task = "Finished"; + currentStep = 0; + steps = 0; + running = false; + finished = true; + canceled = false; + } + + void cancel() { + canceled = true; + } + + std::string &getTask() { + return task; + } + + bool isFinished() { + return finished; + } + + bool isRunning() { + return running; + } + + bool isCanceled() { + return canceled; + } + +protected: + bool finished; + bool running; + bool canceled; + std::string task; + size_t steps; + size_t currentStep; +}; diff --git a/src/Shader.cpp b/src/Shader.cpp new file mode 100644 index 0000000..56298d7 --- /dev/null +++ b/src/Shader.cpp @@ -0,0 +1,105 @@ +#include "Shader.h" + +#include +#include +#include +#include + +using namespace std; + +GLuint loadProgram(const string &name) { + + // Create the shaders + GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read the Vertex Shader code from the file + string VertexShaderCode; + string vertex_file_path = "shader/" + name + ".vertex.glsl"; + ifstream VertexShaderStream(vertex_file_path, ios::in); + if (VertexShaderStream.is_open()) { + string Line = ""; + while (getline(VertexShaderStream, Line)) + VertexShaderCode += "\n" + Line; + VertexShaderStream.close(); + } else { + cout << "Failed to open " << vertex_file_path << endl; + return 0; + } + + // Read the Fragment Shader code from the file + string FragmentShaderCode; + string fragment_file_path = "shader/" + name + ".fragment.glsl"; + ifstream FragmentShaderStream(fragment_file_path, ios::in); + if (FragmentShaderStream.is_open()) { + string Line = ""; + while (getline(FragmentShaderStream, Line)) + FragmentShaderCode += "\n" + Line; + FragmentShaderStream.close(); + } else { + cout << "Failed to open " << vertex_file_path << endl; + return 0; + } + + GLint Result = GL_FALSE; + int InfoLogLength; + + // Compile Vertex Shader + cout << "Compiling vertex shader : " << name << endl; + char const * VertexSourcePointer = VertexShaderCode.c_str(); + glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); + glCompileShader(VertexShaderID); + + // Check Vertex Shader + glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + vector VertexShaderErrorMessage(InfoLogLength + 1); + glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, + &VertexShaderErrorMessage[0]); + printf("%s\n", &VertexShaderErrorMessage[0]); + } + + // Compile Fragment Shader + cout << "Compiling fragment shader : " << name << endl; + + char const * FragmentSourcePointer = FragmentShaderCode.c_str(); + glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); + glCompileShader(FragmentShaderID); + + // Check Fragment Shader + glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + vector FragmentShaderErrorMessage(InfoLogLength + 1); + glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, + &FragmentShaderErrorMessage[0]); + printf("%s\n", &FragmentShaderErrorMessage[0]); + } + + // Link the program + cout << "Linking program : " << name << endl; + + GLuint ProgramID = glCreateProgram(); + glAttachShader(ProgramID, VertexShaderID); + glAttachShader(ProgramID, FragmentShaderID); + glLinkProgram(ProgramID); + + // Check the program + glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); + glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + vector ProgramErrorMessage(InfoLogLength + 1); + glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, + &ProgramErrorMessage[0]); + printf("%s\n", &ProgramErrorMessage[0]); + } + + glDetachShader(ProgramID, VertexShaderID); + glDetachShader(ProgramID, FragmentShaderID); + + glDeleteShader(VertexShaderID); + glDeleteShader(FragmentShaderID); + + return ProgramID; +} diff --git a/src/Shader.h b/src/Shader.h new file mode 100644 index 0000000..bc9528d --- /dev/null +++ b/src/Shader.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +unsigned int loadProgram(const std::string &name); diff --git a/src/SkyBox.cpp b/src/SkyBox.cpp new file mode 100644 index 0000000..722ba0c --- /dev/null +++ b/src/SkyBox.cpp @@ -0,0 +1,78 @@ +#include "SkyBox.h" +#include "Shader.h" + +#include +#include + +using namespace std; + +SkyBox::SkyBox() { + glGenTextures(1, &textureId); +} + +SkyBox::~SkyBox() { + glDeleteTextures(1, &textureId); +} + +bool SkyBox::Load(const std::string basename) { + glBindTexture(GL_TEXTURE_CUBE_MAP, textureId); + + Load(GL_TEXTURE_CUBE_MAP_POSITIVE_X, basename + "_right1.png"); + Load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, basename + "_left2.png"); + Load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, basename + "_top3.png"); + Load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, basename + "_bottom4.png"); + Load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, basename + "_front5.png"); + Load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, basename + "_back6.png"); + + programId = loadProgram("skybox"); + + return true; +} + +bool SkyBox::Load(GLuint target, const std::string filename) { + int x, y, comp; + unsigned char *data = stbi_load(filename.c_str(), &x, &y, &comp, 4); + + glTexImage2D(target, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, + GL_CLAMP_TO_EDGE); + + stbi_image_free(data); + return true; +} + +void SkyBox::Render() { + GLint OldCullFaceMode; + glGetIntegerv(GL_CULL_FACE_MODE, &OldCullFaceMode); + GLint OldDepthFuncMode; + glGetIntegerv(GL_DEPTH_FUNC, &OldDepthFuncMode); + + glCullFace(GL_FRONT); + glDepthFunc(GL_LEQUAL); +/* + Pipeline p; + p.Scale(20.0f, 20.0f, 20.0f); + p.Rotate(0.0f, 0.0f, 0.0f); + p.WorldPos(m_pCamera->GetPos().x, m_pCamera->GetPos().y, + m_pCamera->GetPos().z); + p.SetCamera(m_pCamera->GetPos(), m_pCamera->GetTarget(), + m_pCamera->GetUp()); + p.SetPerspectiveProj(m_persProjInfo); + m_pSkyboxTechnique->SetWVP(p.GetWVPTrans()); + m_pCubemapTex->Bind(GL_TEXTURE0); + m_pMesh->Render(); +*/ + glCullFace(OldCullFaceMode); + glDepthFunc(OldDepthFuncMode); +} + +void SkyBox::Bind(GLenum unit) { + glActiveTexture(unit); + glBindTexture(GL_TEXTURE_CUBE_MAP, textureId); +} diff --git a/src/SkyBox.h b/src/SkyBox.h new file mode 100644 index 0000000..952d818 --- /dev/null +++ b/src/SkyBox.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include + +class SkyBox { +public: + + SkyBox(); + + ~SkyBox(); + + bool Load(const std::string basename); + bool Load(GLuint target, const std::string filename); + + void Bind(GLenum TextureUnit); + + void Render(); +private: + + std::string fileNames[6]; + GLuint textureId, programId; +}; diff --git a/src/TextureMapper.cpp b/src/TextureMapper.cpp index a2e80a3..26447e2 100644 --- a/src/TextureMapper.cpp +++ b/src/TextureMapper.cpp @@ -9,8 +9,8 @@ TextureMapper::TextureMapper(Density &density, size_t textureSize) : density(density), textureSize(textureSize), albedo( textureSize * textureSize), normal(textureSize * textureSize), roughness( - textureSize * textureSize), darkestColor(0.3, 0.25, 0.2), brightestColor( - 0.9, 0.85, 0.8) { + textureSize * textureSize), darkestColor(0.3, 0.25, 0.2, 1.0), brightestColor( + 0.9, 0.85, 0.8, 1.0) { } void TextureMapper::setTextureSize(size_t size) { @@ -35,9 +35,19 @@ void TextureMapper::map(const vec3v_t &inVertices, const vec3v_t &inNormals, texcoords.clear(); texcoords.reserve(inIndices.size() * 3); + // 2 px margin + size_t marginPixels = 2; + float margin = marginPixels * texf; + + std::fill(albedo.begin(), albedo.end(), 255.f * brightestColor); + std::fill(normal.begin(), normal.end(), ucvec4_t(255, 255, 255, 255)); + std::fill(roughness.begin(), roughness.end(), 255); + int rects = ceil(sqrt(inIndices.size())), rx = 0, ry = 0; - float rectSize = floor(float(textureSize) / rects) / textureSize; - for (size_t i = 0; i != inIndices.size(); i++) { + float rectSizePixel = floor(((float)textureSize - (rects + 1) * marginPixels) / rects); + float rectSize = rectSizePixel / textureSize; + printf("Rects: %d, Size: %f", rects, rectSize); + for (size_t i = 0; i < inIndices.size(); i++) { glm::vec3 p[3], n[3]; glm::uvec3 idx = inIndices[i]; indices.push_back( @@ -62,17 +72,17 @@ void TextureMapper::map(const vec3v_t &inVertices, const vec3v_t &inNormals, t[2] -= lower; glm::vec3 extent = upper - lower; float s = std::max(std::max(extent.x, extent.y), extent.z); - t[0] *= 0.8 * rectSize / s; - t[1] *= 0.8 * rectSize / s; - t[2] *= 0.8 * rectSize / s; - glm::vec3 off(rx * rectSize, 0, ry * rectSize); + t[0] *= 0.9 * rectSize / s; + t[1] *= rectSize / s; + t[2] *= rectSize / s; + glm::vec3 off(margin + rx * (rectSize + margin), 0, margin + ry * (rectSize + margin)); t[0] += off; t[1] += off; t[2] += off; texcoords.push_back(glm::vec2(t[0].x, t[0].z)); texcoords.push_back(glm::vec2(t[1].x, t[1].z)); texcoords.push_back(glm::vec2(t[2].x, t[2].z)); - +#if 0 //if (rx == 0 && ry == 0) { t[0].y = 0; t[1].y = 0; @@ -111,16 +121,22 @@ void TextureMapper::map(const vec3v_t &inVertices, const vec3v_t &inNormals, glm::mat3 faceBase = glm::mat3(db, glm::cross(db, dc), dc); glm::mat3 ifaceBase = glm::inverse(faceBase); - glm::vec3 tmin = max( - floor( - min(min(t[0], t[1]), t[2]) - * glm::vec3((float) textureSize)) - - glm::vec3(1.0f), glm::vec3(0.1)); - glm::vec3 tmax = min( - ceil( - max(max(t[0], t[1]), t[2]) - * glm::vec3((float) textureSize)) - + glm::vec3(1.0f), glm::vec3(textureSize-1)); + glm::vec3 tmin = min(min(t[0], t[1]), t[2]); + tmin = tmin * glm::vec3((float) textureSize); + tmin = floor(tmin) - glm::vec3(2.0f); + //tmin = tmin - glm::vec3(1.0f); + tmin = max(tmin, glm::vec3(0.1)); + +// glm::vec3 tmax = min( +// ceil( +// max(max(t[0], t[1]), t[2]) +// * glm::vec3((float) textureSize)) +// + glm::vec3(1.0f), glm::vec3(textureSize - 1)); + + glm::vec3 tmax = max(max(t[0], t[1]), t[2]); + tmax = tmax * glm::vec3((float) textureSize); + tmax = ceil(tmax) + glm::vec3(2.0f); + tmax = min(tmax, glm::vec3(textureSize)); // TODO: borders! for (int ix = tmin.x; ix < tmax.x; ix++) { @@ -166,9 +182,9 @@ void TextureMapper::map(const vec3v_t &inVertices, const vec3v_t &inNormals, // diff[ix + iy * ntex][2] = 0; //(0.5 + sp.z) * 255; // float rd = 1.f; //0.7 + 0.3 * length(r) * rects; -// albedo[ix + iy * textureSize][0] = rd * (0.5 + sp.x) * 255; -// albedo[ix + iy * textureSize][1] = rd * (0.5 + sp.y) * 255; -// albedo[ix + iy * textureSize][2] = rd * (0.5 + sp.z) * 255; +// albedo[ix + (textureSize - iy) * textureSize][0] = rd * (sp.x) * 255; +// albedo[ix + (textureSize - iy) * textureSize][1] = rd * (sp.y) * 255; +// albedo[ix + (textureSize - iy) * textureSize][2] = rd * (sp.z) * 255; // albedo[ix + iy * textureSize][0] = length(res) * rects * 255; // albedo[ix + iy * textureSize][1] = length(res) * rects * 255; @@ -190,7 +206,7 @@ void TextureMapper::map(const vec3v_t &inVertices, const vec3v_t &inNormals, rx = 0; ry++; } - +#endif } // // for (int ix = 0; ix < ntex; ix++) { diff --git a/src/TextureMapper.h b/src/TextureMapper.h index 75bc0ba..46d21d8 100644 --- a/src/TextureMapper.h +++ b/src/TextureMapper.h @@ -1,19 +1,12 @@ #pragma once #include "Density.h" - -#include -#include +#include "types.h" class TextureMapper { size_t textureSize; public: - typedef std::vector< glm::tvec3 > texture3_t; - typedef std::vector texture1_t; - typedef std::vector vec3v_t; - typedef std::vector vec2v_t; - typedef std::vector uvec3v_t; Density &density; @@ -27,7 +20,7 @@ public: vec2v_t texcoords; uvec3v_t indices; - glm::vec3 darkestColor, brightestColor; + glm::vec4 darkestColor, brightestColor; TextureMapper(Density &density, size_t textureSize); diff --git a/src/main.cpp b/src/main.cpp index aed13b4..f71818c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include "Application.h" int main(void) { - + srand(time(0)); Application::instance().run(); } diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..27cc5b0 --- /dev/null +++ b/src/types.h @@ -0,0 +1,15 @@ +#pragma once + +#include "AlignedAllocator.h" +#include +#include +#include + +typedef glm::tvec4 ucvec4_t; +typedef std::vector > texture3_t; +typedef std::vector> texture1_t; +typedef std::vector > vec3v_t; +typedef std::vector > vec2v_t; +typedef std::vector > uvec3v_t; +typedef std::vector > uvec4v_t; +typedef std::vector uintv_t; diff --git a/vendor/MarchingCube.h b/vendor/MarchingCube.h deleted file mode 100644 index 10153e0..0000000 --- a/vendor/MarchingCube.h +++ /dev/null @@ -1,428 +0,0 @@ -/* - * MarchingCube.h - * - * Created on: 19.10.2017 - * Author: gmueller - */ - -#ifndef MARCHINGCUBE_H_ -#define MARCHINGCUBE_H_ - -#include -#include - -using glm::vec3; - -typedef glm::vec3 XYZ; - -struct TRIANGLE { - XYZ p[3]; -}; - -struct GRIDCELL { - XYZ p[8]; - double val[8]; -} ; - -/* - Linearly interpolate the position where an isosurface cuts - an edge between two vertices, each with their own scalar value - */ -XYZ VertexInterp(double isolevel, XYZ p1, XYZ p2, double valp1, double valp2) { - double mu; - XYZ p; - - if (fabs(isolevel - valp1) < 0.00001) - return (p1); - if (fabs(isolevel - valp2) < 0.00001) - return (p2); - if (fabs(valp1 - valp2) < 0.00001) - return (p1); - - mu = (isolevel - valp1) / (valp2 - valp1); - p.x = p1.x + mu * (p2.x - p1.x); - p.y = p1.y + mu * (p2.y - p1.y); - p.z = p1.z + mu * (p2.z - p1.z); - - return (p); -} - -/* - Given a grid cell and an isolevel, calculate the triangular - facets required to represent the isosurface through the cell. - Return the number of triangular facets, the array "triangles" - will be loaded up with the vertices at most 5 triangular facets. - 0 will be returned if the grid cell is either totally above - of totally below the isolevel. - */ -int Polygonise(GRIDCELL &grid, double isolevel, TRIANGLE *triangles) { - int i, ntriang; - int cubeindex; - XYZ vertlist[12]; - - int edgeTable[256] = { 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, - 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99, - 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, - 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33, 0x13a, 0x636, - 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, - 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac, - 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, - 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, - 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, - 0x1f6, 0xff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, - 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c, - 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, - 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc, 0xfcc, 0xec5, 0xdcf, - 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, - 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, - 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, - 0xe5c, 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, - 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff, - 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, - 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, - 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, - 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0, 0xd30, - 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, - 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, - 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, - 0x393, 0x99, 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, - 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 }; - int triTable[256][16] = { - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - - { - 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 4, - 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, { 1, - 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, { - 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, { - 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, { 8, - 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, { - 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, { - 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, { - 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, { 4, 7, - 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, { 4, 7, - 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, { 9, - 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, - 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, { - 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, { 5, 2, - 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, { 2, 10, - 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, { 9, 5, 4, - 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 11, - 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, { 0, 5, - 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, { 2, 1, - 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, { 10, 3, - 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, { 4, 9, - 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, { 5, 4, - 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, { 5, 4, - 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, { 9, - 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, { - 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, { - 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, { 10, 1, - 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, { 8, 0, 2, - 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, { 2, 10, 5, 2, - 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, { 7, 9, 5, 7, - 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 7, 9, - 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, { 2, 3, 11, 0, 1, - 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, { 11, 2, 1, 11, 1, 7, - 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 8, 8, 5, 7, - 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, { 5, 7, 0, 5, 0, 9, - 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, { 11, 10, 0, 11, 0, 3, - 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, { 11, 10, 5, 7, 11, 5, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 10, 6, 5, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 3, 5, - 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 9, 0, 1, - 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 8, - 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, { 1, 6, - 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, - 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, { 9, - 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, { 5, - 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, { 2, 3, - 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, { 5, - 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, { 6, - 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, { 0, - 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, { 3, - 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, { 6, 5, - 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, { 5, - 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, { - 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, { - 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, { 6, - 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, { 1, - 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, { 8, 4, - 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, { 7, 3, 9, - 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, { 3, 11, 2, 7, 8, - 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, { 5, 10, 6, 4, 7, - 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, { 0, 1, 9, 4, 7, 8, - 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, { 9, 2, 1, 9, 11, 2, - 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, { 8, 4, 7, 3, 11, 5, 3, - 5, 1, 5, 11, 6, -1, -1, -1, -1 }, { 5, 1, 11, 5, 11, 6, 1, - 0, 11, 7, 11, 4, 0, 4, 11, -1 }, { 0, 5, 9, 0, 6, 5, 0, 3, - 6, 11, 6, 3, 8, 4, 7, -1 }, { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, - 11, 9, -1, -1, -1, -1 }, { 10, 4, 9, 6, 4, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1 }, { 4, 10, 6, 4, 9, 10, 0, 8, 3, - -1, -1, -1, -1, -1, -1, -1 }, { 10, 0, 1, 10, 6, 0, 6, 4, 0, - -1, -1, -1, -1, -1, -1, -1 }, { 8, 3, 1, 8, 1, 6, 8, 6, 4, - 6, 1, 10, -1, -1, -1, -1 }, { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, - -1, -1, -1, -1, -1, -1 }, { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, - 4, -1, -1, -1, -1 }, { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1 }, { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, - -1, -1, -1, -1, -1 }, { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, - -1, -1, -1, -1, -1, -1 }, { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, - 10, 6, -1, -1, -1, -1 }, { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, - 10, -1, -1, -1, -1 }, { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, - 11, 8, 11, 1, -1 }, { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, - -1, -1, -1, -1 }, { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, - 4, 1, -1 }, { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, - -1, -1, -1 }, { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1 }, { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, - -1, -1, -1, -1, -1 }, { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, - 10, -1, -1, -1, -1 }, { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, - 0, -1, -1, -1, -1 }, { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, - -1, -1, -1, -1, -1 }, { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, - -1, -1, -1, -1 }, { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, - 3, 9, -1 }, { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, - -1, -1 }, { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1 }, { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, - -1, -1, -1 }, { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, - 7, -1 }, { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, - -1 }, { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, - -1 }, { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, - { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 7, - 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, { 7, - 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 8, - 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, { 10, - 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, { - 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, { - 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, { - 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, { 2, 7, - 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, { 1, 6, - 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, { 10, 7, 6, - 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, { 10, 7, 6, - 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, { 0, 3, 7, 0, - 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, { 7, 6, 10, 7, - 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, { 6, 8, 4, - 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 6, - 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, { 8, 6, - 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, { 9, 4, - 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, { 6, 8, 4, - 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 2, - 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, { 4, 11, - 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, { 10, 9, - 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, { 8, 2, 3, 8, - 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, { 0, 4, 2, 4, - 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 9, 0, - 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, { 1, 9, 4, 1, - 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, { 8, 1, 3, 8, - 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, { 10, 1, 0, 10, - 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, { 4, 6, 3, 4, - 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, { 10, 9, 4, 6, 10, - 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 4, 9, 5, 7, - 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 3, - 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, { 5, 0, 1, - 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, { 11, 7, 6, - 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, { 9, 5, 4, 10, - 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, { 6, 11, 7, 1, - 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, { 7, 6, 11, 5, 4, - 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, { 3, 4, 8, 3, 5, 4, - 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, { 7, 2, 3, 7, 6, 2, 5, 4, - 9, -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 4, 0, 8, 6, 0, 6, - 2, 6, 8, 7, -1, -1, -1, -1 }, { 3, 6, 2, 3, 7, 6, 1, 5, 0, - 5, 4, 0, -1, -1, -1, -1 }, { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, - 8, 5, 1, 5, 8, -1 }, { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, - -1, -1, -1, -1 }, { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, - 5, 4, -1 }, { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, - 10, -1 }, { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, - -1, -1 }, { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, - -1, -1 }, { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, - -1 }, { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, - -1 }, { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, - -1 }, { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, - -1 }, - { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, { 11, 8, 5, - 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, { 6, 11, 3, 6, - 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, { 5, 8, 9, 5, 2, - 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, { 9, 5, 6, 9, 6, 0, - 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, { 1, 5, 8, 1, 8, 0, - 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, { 1, 5, 6, 2, 1, 6, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 3, 6, 1, 6, 10, 3, 8, - 6, 5, 6, 9, 8, 9, 6, -1 }, { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, - 6, 0, -1, -1, -1, -1 }, { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1 }, { 10, 5, 6, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }, { 11, 5, 10, 7, 5, 11, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 11, 5, 10, 11, 7, 5, - 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, { 5, 11, 7, 5, 10, - 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, { 10, 7, 5, 10, - 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, { 11, 1, 2, 11, - 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 3, 1, - 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, { 9, 7, 5, 9, 2, - 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, { 7, 5, 2, 7, 2, 11, - 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, { 2, 5, 10, 2, 3, 5, 3, 7, - 5, -1, -1, -1, -1, -1, -1, -1 }, { 8, 2, 0, 8, 5, 2, 8, 7, - 5, 10, 2, 5, -1, -1, -1, -1 }, { 9, 0, 1, 5, 10, 3, 5, 3, 7, - 3, 10, 2, -1, -1, -1, -1 }, { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, - 2, 5, 7, 5, 2, -1 }, { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1 }, { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, - -1, -1, -1, -1, -1 }, { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, - -1, -1, -1, -1, -1 }, { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1 }, { 5, 8, 4, 5, 10, 8, 10, 11, 8, - -1, -1, -1, -1, -1, -1, -1 }, { 5, 0, 4, 5, 11, 0, 5, 10, - 11, 11, 3, 0, -1, -1, -1, -1 }, { 0, 1, 9, 8, 4, 10, 8, 10, - 11, 10, 4, 5, -1, -1, -1, -1 }, { 10, 11, 4, 10, 4, 5, 11, - 3, 4, 9, 4, 1, 3, 1, 4, -1 }, { 2, 5, 1, 2, 8, 5, 2, 11, 8, - 4, 5, 8, -1, -1, -1, -1 }, { 0, 4, 11, 0, 11, 3, 4, 5, 11, - 2, 11, 1, 5, 1, 11, -1 }, { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, - 5, 8, 11, 8, 5, -1 }, { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1 }, { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, - 8, 4, -1, -1, -1, -1 }, { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, - -1, -1, -1, -1, -1, -1 }, { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, - 5, 8, 0, 1, 9, -1 }, { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, - -1, -1, -1, -1 }, { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, - -1, -1, -1, -1 }, { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1 }, { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, - -1, -1, -1, -1 }, { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1 }, { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, - -1, -1, -1, -1, -1, -1 }, { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, - 10, 11, -1, -1, -1, -1 }, { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, - 4, 11, -1, -1, -1, -1 }, { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, - 11, 10, 11, 4, -1 }, { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, - 2, -1, -1, -1, -1 }, { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, - 1, 0, 8, 3, -1 }, { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, - -1, -1, -1, -1 }, { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, - -1, -1, -1, -1 }, { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, - -1, -1, -1 }, { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, - 7, -1 }, { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, - -1 }, { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1 }, { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, - -1, -1 }, { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, - -1 }, { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1 }, { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1 }, { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1 }, { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, - -1, -1, -1, -1, -1 }, { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, - -1, -1, -1, -1, -1, -1 }, { 3, 1, 10, 11, 3, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1 }, { 1, 2, 11, 1, 11, 9, 9, 11, - 8, -1, -1, -1, -1, -1, -1, -1 }, { 3, 0, 9, 3, 9, 11, 1, 2, - 9, 2, 11, 9, -1, -1, -1, -1 }, { 0, 2, 11, 8, 0, 11, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 2, 11, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 2, 3, 8, 2, 8, - 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, { 9, 10, 2, 0, - 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 2, 3, 8, - 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, { 1, 10, 2, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, - 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, - { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1 } }; - - /* - Determine the index into the edge table which - tells us which vertices are inside of the surface - */ - cubeindex = 0; - if (grid.val[0] < isolevel) - cubeindex |= 1; - if (grid.val[1] < isolevel) - cubeindex |= 2; - if (grid.val[2] < isolevel) - cubeindex |= 4; - if (grid.val[3] < isolevel) - cubeindex |= 8; - if (grid.val[4] < isolevel) - cubeindex |= 16; - if (grid.val[5] < isolevel) - cubeindex |= 32; - if (grid.val[6] < isolevel) - cubeindex |= 64; - if (grid.val[7] < isolevel) - cubeindex |= 128; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[cubeindex] == 0) - return (0); - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[cubeindex] & 1) - vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0], - grid.val[1]); - if (edgeTable[cubeindex] & 2) - vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1], - grid.val[2]); - if (edgeTable[cubeindex] & 4) - vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2], - grid.val[3]); - if (edgeTable[cubeindex] & 8) - vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3], - grid.val[0]); - if (edgeTable[cubeindex] & 16) - vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4], - grid.val[5]); - if (edgeTable[cubeindex] & 32) - vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5], - grid.val[6]); - if (edgeTable[cubeindex] & 64) - vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6], - grid.val[7]); - if (edgeTable[cubeindex] & 128) - vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7], - grid.val[4]); - if (edgeTable[cubeindex] & 256) - vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0], - grid.val[4]); - if (edgeTable[cubeindex] & 512) - vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1], - grid.val[5]); - if (edgeTable[cubeindex] & 1024) - vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2], - grid.val[6]); - if (edgeTable[cubeindex] & 2048) - vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3], - grid.val[7]); - - // std::cout << cubeindex << std::endl; - - /* Create the triangle */ - ntriang = 0; - for (i = 0; triTable[cubeindex][i] != -1; i += 3) { - triangles[ntriang].p[0] = vertlist[triTable[cubeindex][i]]; - triangles[ntriang].p[1] = vertlist[triTable[cubeindex][i + 1]]; - triangles[ntriang].p[2] = vertlist[triTable[cubeindex][i + 2]]; - ntriang++; - } - - return (ntriang); -} - -#endif /* MARCHINGCUBE_H_ */ diff --git a/vendor/MemoryPool.h b/vendor/MemoryPool.h new file mode 100644 index 0000000..bae976e --- /dev/null +++ b/vendor/MemoryPool.h @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2013 Cosku Acay, http://www.coskuacay.com + * + * 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. + */ + +#ifndef MEMORY_POOL_H +#define MEMORY_POOL_H + +#include +#include + +template +class MemoryPool +{ + public: + /* Member types */ + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef const T* const_pointer; + typedef const T& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::false_type propagate_on_container_copy_assignment; + typedef std::true_type propagate_on_container_move_assignment; + typedef std::true_type propagate_on_container_swap; + + template struct rebind { + typedef MemoryPool other; + }; + + /* Member functions */ + MemoryPool() noexcept; + MemoryPool(const MemoryPool& memoryPool) noexcept; + MemoryPool(MemoryPool&& memoryPool) noexcept; + template MemoryPool(const MemoryPool& memoryPool) noexcept; + + ~MemoryPool() noexcept; + + MemoryPool& operator=(const MemoryPool& memoryPool) = delete; + MemoryPool& operator=(MemoryPool&& memoryPool) noexcept; + + pointer address(reference x) const noexcept; + const_pointer address(const_reference x) const noexcept; + + // Can only allocate one object at a time. n and hint are ignored + pointer allocate(size_type n = 1, const_pointer hint = 0); + void deallocate(pointer p, size_type n = 1); + + size_type max_size() const noexcept; + + template void construct(U* p, Args&&... args); + template void destroy(U* p); + + template pointer newElement(Args&&... args); + void deleteElement(pointer p); + + private: + union Slot_ { + value_type element; + Slot_* next; + }; + + typedef char* data_pointer_; + typedef Slot_ slot_type_; + typedef Slot_* slot_pointer_; + + slot_pointer_ currentBlock_; + slot_pointer_ currentSlot_; + slot_pointer_ lastSlot_; + slot_pointer_ freeSlots_; + + size_type padPointer(data_pointer_ p, size_type align) const noexcept; + void allocateBlock(); + + static_assert(BlockSize >= 2 * sizeof(slot_type_), "BlockSize too small."); +}; + +#include "MemoryPool.tcc" + +#endif // MEMORY_POOL_H diff --git a/vendor/MemoryPool.tcc b/vendor/MemoryPool.tcc new file mode 100644 index 0000000..562d958 --- /dev/null +++ b/vendor/MemoryPool.tcc @@ -0,0 +1,235 @@ +/*- + * Copyright (c) 2013 Cosku Acay, http://www.coskuacay.com + * + * 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. + */ + +#ifndef MEMORY_BLOCK_TCC +#define MEMORY_BLOCK_TCC + + + +template +inline typename MemoryPool::size_type +MemoryPool::padPointer(data_pointer_ p, size_type align) +const noexcept +{ + uintptr_t result = reinterpret_cast(p); + return ((align - result) % align); +} + + + +template +MemoryPool::MemoryPool() +noexcept +{ + currentBlock_ = nullptr; + currentSlot_ = nullptr; + lastSlot_ = nullptr; + freeSlots_ = nullptr; +} + + + +template +MemoryPool::MemoryPool(const MemoryPool& memoryPool) +noexcept : +MemoryPool() +{} + + + +template +MemoryPool::MemoryPool(MemoryPool&& memoryPool) +noexcept +{ + currentBlock_ = memoryPool.currentBlock_; + memoryPool.currentBlock_ = nullptr; + currentSlot_ = memoryPool.currentSlot_; + lastSlot_ = memoryPool.lastSlot_; + freeSlots_ = memoryPool.freeSlots; +} + + +template +template +MemoryPool::MemoryPool(const MemoryPool& memoryPool) +noexcept : +MemoryPool() +{} + + + +template +MemoryPool& +MemoryPool::operator=(MemoryPool&& memoryPool) +noexcept +{ + if (this != &memoryPool) + { + std::swap(currentBlock_, memoryPool.currentBlock_); + currentSlot_ = memoryPool.currentSlot_; + lastSlot_ = memoryPool.lastSlot_; + freeSlots_ = memoryPool.freeSlots; + } + return *this; +} + + + +template +MemoryPool::~MemoryPool() +noexcept +{ + slot_pointer_ curr = currentBlock_; + while (curr != nullptr) { + slot_pointer_ prev = curr->next; + operator delete(reinterpret_cast(curr)); + curr = prev; + } +} + + + +template +inline typename MemoryPool::pointer +MemoryPool::address(reference x) +const noexcept +{ + return &x; +} + + + +template +inline typename MemoryPool::const_pointer +MemoryPool::address(const_reference x) +const noexcept +{ + return &x; +} + + + +template +void +MemoryPool::allocateBlock() +{ + // Allocate space for the new block and store a pointer to the previous one + data_pointer_ newBlock = reinterpret_cast + (operator new(BlockSize)); + reinterpret_cast(newBlock)->next = currentBlock_; + currentBlock_ = reinterpret_cast(newBlock); + // Pad block body to staisfy the alignment requirements for elements + data_pointer_ body = newBlock + sizeof(slot_pointer_); + size_type bodyPadding = padPointer(body, alignof(slot_type_)); + currentSlot_ = reinterpret_cast(body + bodyPadding); + lastSlot_ = reinterpret_cast + (newBlock + BlockSize - sizeof(slot_type_) + 1); +} + + + +template +inline typename MemoryPool::pointer +MemoryPool::allocate(size_type n, const_pointer hint) +{ + if (freeSlots_ != nullptr) { + pointer result = reinterpret_cast(freeSlots_); + freeSlots_ = freeSlots_->next; + return result; + } + else { + if (currentSlot_ >= lastSlot_) + allocateBlock(); + return reinterpret_cast(currentSlot_++); + } +} + + + +template +inline void +MemoryPool::deallocate(pointer p, size_type n) +{ + if (p != nullptr) { + reinterpret_cast(p)->next = freeSlots_; + freeSlots_ = reinterpret_cast(p); + } +} + + + +template +inline typename MemoryPool::size_type +MemoryPool::max_size() +const noexcept +{ + size_type maxBlocks = -1 / BlockSize; + return (BlockSize - sizeof(data_pointer_)) / sizeof(slot_type_) * maxBlocks; +} + + + +template +template +inline void +MemoryPool::construct(U* p, Args&&... args) +{ + new (p) U (std::forward(args)...); +} + + + +template +template +inline void +MemoryPool::destroy(U* p) +{ + p->~U(); +} + + + +template +template +inline typename MemoryPool::pointer +MemoryPool::newElement(Args&&... args) +{ + pointer result = allocate(); + construct(result, std::forward(args)...); + return result; +} + + + +template +inline void +MemoryPool::deleteElement(pointer p) +{ + if (p != nullptr) { + p->~value_type(); + deallocate(p); + } +} + + + +#endif // MEMORY_BLOCK_TCC