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, -