Browse Source

update

master
Gero Müller 1 year ago
parent
commit
7b2946a961

+ 14
- 2
CMakeLists.txt 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()

+ 2
- 1
ToDo.txt 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
- 0
cmake/FindOpenMesh.cmake 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()

+ 12
- 0
shader/skybox.fragment.glsl View File

@@ -0,0 +1,12 @@
#version 330

in vec3 TexCoord0;

out vec4 FragColor;

uniform samplerCube gCubemapTexture;

void main()
{
FragColor = texture(gCubemapTexture, TexCoord0);
}

+ 14
- 0
shader/skybox.vertex.glsl 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
- 0
src/AlignedAllocator.h 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);
}

+ 136
- 140
src/Application.cpp 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);

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);
// }
}

polygonizer.polygonize(resolution);
{
std::ofstream out("stage1.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;

smooth(polygonizer.vertices, polygonizer.indices);
createPatches(polygonizer.vertices, polygonizer.indices, faceNormals,
adjacents, positions, indices, patches, 0.9);
{
std::ofstream out("stage2.obj");
saveAttrib(out, "v ", polygonizer.vertices);
saveFaces(out, polygonizer.indices, 1);
std::ofstream out("stage1.obj");
saveAttrib(out, "v ", positions);
saveFaces(out, 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);
if (meshProgress.begin("Map Textures", 1)) {
texturemapper.map(polygonizer.vertices, normals, polygonizer.indices);
}

{
std::ofstream out("stage4.obj");
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();


+ 13
- 6
src/Application.h 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();


+ 3
- 1
src/Density.h 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
- 0
src/MarchingCube.cpp 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
- 0
src/MarchingCube.h 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);

+ 146
- 37
src/Mesh.cpp 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) {
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 moveToMean(vec3v_t &positions) {
vec3 mean(0);
for (size_t i = 0; i < vtx.size(); i++) {
mean += vtx[i];
for (size_t i = 0; i < positions.size(); i++) {
mean += positions[i];
}
mean *= vec3(1.f / vtx.size());
for (size_t i = 0; i < vtx.size(); i++) {
vtx[i] -= mean;
mean *= vec3(1.f / positions.size());
for (size_t i = 0; i < positions.size(); i++) {
positions[i] -= mean;
}
}

void smooth(vec3v_t &vtx, const uvec3v_t &tri) {
vec3v_t cogs(vtx.size(), vec3(0.f));
vector<int> valence(vtx.size(), 0);
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 < tri.size(); iTri++) {
const uvec3 &idx = tri[iTri];
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");
}

}


+ 22
- 15
src/Mesh.h View File

@@ -1,28 +1,35 @@
#pragma once

#include "types.h"

#include <vector>
#include <ostream>

#include <glm/vec3.hpp>
#include <glm/vec4.hpp>

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

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 &positions);

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 findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents);

void computeTangentBasis(vec3v_t & vertices, vec2v_t & uvs, vec3v_t & normals,
vec3v_t & tangents, vec3v_t & bitangents);
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);

+ 221
- 62
src/Polygoniser.cpp 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();

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;

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;

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;
float y = iy * resolution;
float Y = y + resolution;
size_t yOffset = iy * nSamples;
size_t YOffset = yOffset + nSamples;

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);
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 iCell = 0; iCell < 8; iCell++) {
gridCell.val[iCell] = density(gridCell.p[iCell]);
}
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

+ 15
- 9
src/Polygoniser.h 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
- 0
src/ProgressMonitor.h View File

@@ -0,0 +1,77 @@
#pragma once

#include <string>

class ProgressMonitor {
public:
ProgressMonitor() :
finished(false), running(false), canceled(false), steps(0), currentStep(
0) {