This commit is contained in:
Gero Müller 2017-11-02 12:44:44 +10:00
parent f2815b796a
commit 7b2946a961
27 changed files with 2048 additions and 742 deletions

View File

@ -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()
endif()

View File

@ -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
- save

147
cmake/FindOpenMesh.cmake Normal file
View File

@ -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 <moebius@cs.rwth-aachen.de>
# Hans-Christian Ebke <ebke@cs.rwth-aachen.de>
#
#
#===========================================================================
#
# 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()

View File

@ -0,0 +1,12 @@
#version 330
in vec3 TexCoord0;
out vec4 FragColor;
uniform samplerCube gCubemapTexture;
void main()
{
FragColor = texture(gCubemapTexture, TexCoord0);
}

14
shader/skybox.vertex.glsl Normal file
View File

@ -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;
}

206
src/AlignedAllocator.h Normal file
View File

@ -0,0 +1,206 @@
#pragma once
#include <malloc.h>
#include <assert.h>
#include <type_traits>
#include <memory>
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<typename T, Alignment Align = Alignment::SSE>
class AlignedAllocator;
template<Alignment Align>
class AlignedAllocator<void, Align> {
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template<class U> struct rebind {
typedef AlignedAllocator<U, Align> other;
};
};
template<typename T, Alignment Align>
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<class U>
struct rebind {
typedef AlignedAllocator<U, Align> other;
};
public:
AlignedAllocator() noexcept
{
}
template<class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) 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<void, Align>::const_pointer = 0) {
const size_type alignment = static_cast<size_type>(Align);
void* ptr = detail::allocate_aligned_memory(alignment, n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void deallocate(pointer p, size_type) noexcept
{
detail::deallocate_aligned_memory(p);
}
template<class U, class ...Args>
void construct(U* p, Args&&... args) {
::new (reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...);
}
void destroy(pointer p) {
p->~T();
}
};
template<typename T, Alignment Align>
class AlignedAllocator<const T, Align> {
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<class U>
struct rebind {
typedef AlignedAllocator<U, Align> other;
};
public:
AlignedAllocator() noexcept
{
}
template<class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) 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<void, Align>::const_pointer = 0) {
const size_type alignment = static_cast<size_type>(Align);
void* ptr = detail::allocate_aligned_memory(alignment, n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void deallocate(pointer p, size_type) noexcept
{
detail::deallocate_aligned_memory(p);
}
template<class U, class ...Args>
void construct(U* p, Args&&... args) {
::new (reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...);
}
void destroy(pointer p) {
p->~T();
}
};
template<typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool operator==(const AlignedAllocator<T, TAlign>&,
const AlignedAllocator<U, UAlign>&) noexcept
{
return TAlign == UAlign;
}
template<typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool operator!=(const AlignedAllocator<T, TAlign>&,
const AlignedAllocator<U, UAlign>&) 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);
}

View File

@ -1,5 +1,6 @@
#include "Application.h"
#include "Mesh.h"
#include "Shader.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
@ -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<glm::uvec4> 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<char> 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<char> 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<char> 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();

View File

@ -3,11 +3,13 @@
#include "Density.h"
#include "Polygoniser.h"
#include "TextureMapper.h"
#include "ProgressMonitor.h"
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <string>
#include <thread>
struct GLFWwindow;
@ -29,10 +31,10 @@ class Application {
int vPositionLoc, vTexCoordLoc, vNormalLoc, tAlbedoLoc, tNormalLoc,
tRoughnessLoc, tMetalicLoc;
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<glm::vec2> texcoords;
std::vector<glm::uvec3> 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();

View File

@ -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);

394
src/MarchingCube.cpp Normal file
View File

@ -0,0 +1,394 @@
#include "MarchingCube.h"
#include <math.h>
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);
}

16
src/MarchingCube.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <glm/vec3.hpp>
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);

View File

@ -3,16 +3,25 @@
#include <glm/geometric.hpp>
#include <map>
#include <limits>
#include <stack>
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<uvec3::value_type>::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<int> 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<int> 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<pair<uint32_t, uint32_t>, 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<bool> processed(indices.size(), false);
for (size_t i = 0; i < indices.size(); i++) {
if (processed[i])
continue;
vector<uint32_t> faces;
map<uint32_t, uint32_t> vertexMap;
vec3 normal = faceNormals[i];
// check all adjacent faces
stack<uint32_t> 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");
}
}

View File

@ -1,28 +1,35 @@
#pragma once
#include "types.h"
#include <vector>
#include <ostream>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
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<glm::vec3> vec3v_t;
typedef std::vector<glm::vec2> vec2v_t;
typedef std::vector<glm::uvec3> uvec3v_t;
typedef std::vector<glm::uvec4> 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);

View File

@ -5,31 +5,33 @@
#include <glm/gtc/epsilon.hpp>
#include <MarchingCube.h>
#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<glm::vec3, int>::iterator vit =
vertexLookup.find(p);
vec3 &p = tris[iTri].p[k];
std::map<vec3, int>::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<float> &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<float> 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<float> &zLayer = layers[iz % 2];
std::vector<float> &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<glm::vec3, int>::iterator vit =
vertexLookup.find(p);
vec3 &p = tris[iTri].p[k];
std::map<vec3, int>::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<float> 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<vec3, int>::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

View File

@ -3,9 +3,9 @@
#include <vector>
#include <map>
#include <glm/vec3.hpp>
#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<glm::vec3> vertices;
std::vector<glm::uvec3> indices;
std::map<glm::vec3, int, CompareVec3> vertexLookup;
std::vector<bool> isocell;
size_t isocellVersion;
float isocellIsolevel;
void polygonize(const glm::vec3 &lower, const glm::vec3 &upper,
float isolevel);
void calculateLayer(std::vector<float> &layer, float resolution, size_t nSamples, float z);
public:
vec3v_t vertices;
uvec3v_t indices;
std::map<glm::vec3, int, CompareVec3> 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);
};

77
src/ProgressMonitor.h Normal file
View File

@ -0,0 +1,77 @@
#pragma once
#include <string>
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;
};

105
src/Shader.cpp Normal file
View File

@ -0,0 +1,105 @@
#include "Shader.h"
#include <glad/glad.h>
#include <fstream>
#include <iostream>
#include <vector>
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<char> 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<char> 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<char> 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;
}

5
src/Shader.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <string>
unsigned int loadProgram(const std::string &name);

78
src/SkyBox.cpp Normal file
View File

@ -0,0 +1,78 @@
#include "SkyBox.h"
#include "Shader.h"
#include <glad/glad.h>
#include <stb_image.h>
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);
}

24
src/SkyBox.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include <glad/glad.h>
#include <string>
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;
};

View File

@ -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++) {

View File

@ -1,19 +1,12 @@
#pragma once
#include "Density.h"
#include <vector>
#include <glm/vec3.hpp>
#include "types.h"
class TextureMapper {
size_t textureSize;
public:
typedef std::vector< glm::tvec3<uint8_t> > texture3_t;
typedef std::vector<uint8_t> texture1_t;
typedef std::vector<glm::vec3> vec3v_t;
typedef std::vector<glm::vec2> vec2v_t;
typedef std::vector<glm::uvec3> 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);

View File

@ -1,7 +1,7 @@
#include "Application.h"
int main(void) {
srand(time(0));
Application::instance().run();
}

15
src/types.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include "AlignedAllocator.h"
#include <glm/vec4.hpp>
#include <glm/vec3.hpp>
#include <vector>
typedef glm::tvec4<uint8_t> ucvec4_t;
typedef std::vector<ucvec4_t, AlignedAllocator<ucvec4_t> > texture3_t;
typedef std::vector<uint8_t, AlignedAllocator<uint8_t>> texture1_t;
typedef std::vector<glm::vec3, AlignedAllocator<glm::vec3> > vec3v_t;
typedef std::vector<glm::vec2, AlignedAllocator<glm::vec2> > vec2v_t;
typedef std::vector<glm::uvec3, AlignedAllocator<glm::uvec3> > uvec3v_t;
typedef std::vector<glm::uvec4, AlignedAllocator<glm::uvec4> > uvec4v_t;
typedef std::vector<uint32_t> uintv_t;

428
vendor/MarchingCube.h vendored
View File

@ -1,428 +0,0 @@
/*
* MarchingCube.h
*
* Created on: 19.10.2017
* Author: gmueller
*/
#ifndef MARCHINGCUBE_H_
#define MARCHINGCUBE_H_
#include <glm/vec3.hpp>
#include <iostream>
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_ */

98
vendor/MemoryPool.h vendored Normal file
View File

@ -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 <climits>
#include <cstddef>
template <typename T, size_t BlockSize = 4096>
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 <typename U> struct rebind {
typedef MemoryPool<U> other;
};
/* Member functions */
MemoryPool() noexcept;
MemoryPool(const MemoryPool& memoryPool) noexcept;
MemoryPool(MemoryPool&& memoryPool) noexcept;
template <class U> MemoryPool(const MemoryPool<U>& 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 <class U, class... Args> void construct(U* p, Args&&... args);
template <class U> void destroy(U* p);
template <class... Args> 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

235
vendor/MemoryPool.tcc vendored Normal file
View File

@ -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 <typename T, size_t BlockSize>
inline typename MemoryPool<T, BlockSize>::size_type
MemoryPool<T, BlockSize>::padPointer(data_pointer_ p, size_type align)
const noexcept
{
uintptr_t result = reinterpret_cast<uintptr_t>(p);
return ((align - result) % align);
}
template <typename T, size_t BlockSize>
MemoryPool<T, BlockSize>::MemoryPool()
noexcept
{
currentBlock_ = nullptr;
currentSlot_ = nullptr;
lastSlot_ = nullptr;
freeSlots_ = nullptr;
}
template <typename T, size_t BlockSize>
MemoryPool<T, BlockSize>::MemoryPool(const MemoryPool& memoryPool)
noexcept :
MemoryPool()
{}
template <typename T, size_t BlockSize>
MemoryPool<T, BlockSize>::MemoryPool(MemoryPool&& memoryPool)
noexcept
{
currentBlock_ = memoryPool.currentBlock_;
memoryPool.currentBlock_ = nullptr;
currentSlot_ = memoryPool.currentSlot_;
lastSlot_ = memoryPool.lastSlot_;
freeSlots_ = memoryPool.freeSlots;
}
template <typename T, size_t BlockSize>
template<class U>
MemoryPool<T, BlockSize>::MemoryPool(const MemoryPool<U>& memoryPool)
noexcept :
MemoryPool()
{}
template <typename T, size_t BlockSize>
MemoryPool<T, BlockSize>&
MemoryPool<T, BlockSize>::operator=(MemoryPool&& memoryPool)
noexcept
{
if (this != &memoryPool)
{
std::swap(currentBlock_, memoryPool.currentBlock_);
currentSlot_ = memoryPool.currentSlot_;
lastSlot_ = memoryPool.lastSlot_;
freeSlots_ = memoryPool.freeSlots;
}
return *this;
}
template <typename T, size_t BlockSize>
MemoryPool<T, BlockSize>::~MemoryPool()
noexcept
{
slot_pointer_ curr = currentBlock_;
while (curr != nullptr) {
slot_pointer_ prev = curr->next;
operator delete(reinterpret_cast<void*>(curr));
curr = prev;
}
}
template <typename T, size_t BlockSize>
inline typename MemoryPool<T, BlockSize>::pointer
MemoryPool<T, BlockSize>::address(reference x)
const noexcept
{
return &x;
}
template <typename T, size_t BlockSize>
inline typename MemoryPool<T, BlockSize>::const_pointer
MemoryPool<T, BlockSize>::address(const_reference x)
const noexcept
{
return &x;
}
template <typename T, size_t BlockSize>
void
MemoryPool<T, BlockSize>::allocateBlock()
{
// Allocate space for the new block and store a pointer to the previous one
data_pointer_ newBlock = reinterpret_cast<data_pointer_>
(operator new(BlockSize));
reinterpret_cast<slot_pointer_>(newBlock)->next = currentBlock_;
currentBlock_ = reinterpret_cast<slot_pointer_>(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<slot_pointer_>(body + bodyPadding);
lastSlot_ = reinterpret_cast<slot_pointer_>
(newBlock + BlockSize - sizeof(slot_type_) + 1);
}
template <typename T, size_t BlockSize>
inline typename MemoryPool<T, BlockSize>::pointer
MemoryPool<T, BlockSize>::allocate(size_type n, const_pointer hint)
{
if (freeSlots_ != nullptr) {
pointer result = reinterpret_cast<pointer>(freeSlots_);
freeSlots_ = freeSlots_->next;
return result;
}
else {
if (currentSlot_ >= lastSlot_)
allocateBlock();
return reinterpret_cast<pointer>(currentSlot_++);
}
}
template <typename T, size_t BlockSize>
inline void
MemoryPool<T, BlockSize>::deallocate(pointer p, size_type n)
{
if (p != nullptr) {
reinterpret_cast<slot_pointer_>(p)->next = freeSlots_;
freeSlots_ = reinterpret_cast<slot_pointer_>(p);
}
}
template <typename T, size_t BlockSize>
inline typename MemoryPool<T, BlockSize>::size_type
MemoryPool<T, BlockSize>::max_size()
const noexcept
{
size_type maxBlocks = -1 / BlockSize;
return (BlockSize - sizeof(data_pointer_)) / sizeof(slot_type_) * maxBlocks;
}
template <typename T, size_t BlockSize>
template <class U, class... Args>
inline void
MemoryPool<T, BlockSize>::construct(U* p, Args&&... args)
{
new (p) U (std::forward<Args>(args)...);
}
template <typename T, size_t BlockSize>
template <class U>
inline void
MemoryPool<T, BlockSize>::destroy(U* p)
{
p->~U();
}
template <typename T, size_t BlockSize>
template <class... Args>
inline typename MemoryPool<T, BlockSize>::pointer
MemoryPool<T, BlockSize>::newElement(Args&&... args)
{
pointer result = allocate();
construct<value_type>(result, std::forward<Args>(args)...);
return result;
}
template <typename T, size_t BlockSize>
inline void
MemoryPool<T, BlockSize>::deleteElement(pointer p)
{
if (p != nullptr) {
p->~value_type();
deallocate(p);
}
}
#endif // MEMORY_BLOCK_TCC