DualMC
This commit is contained in:
parent
079888cfe8
commit
f3c706013e
9
TODO.md
9
TODO.md
|
@ -3,7 +3,7 @@
|
|||
## Data
|
||||
- [x] Generate noise
|
||||
- [x] Density
|
||||
- [ ] Robin hood map / hopscotch_map
|
||||
- [x] Robin hood map
|
||||
- [ ] Octree world
|
||||
- [ ] Serialize
|
||||
- [ ] In memory RLE
|
||||
|
@ -19,7 +19,7 @@
|
|||
- https://speciesdevblog.files.wordpress.com/2012/11/biomemap.png
|
||||
- [ ] Leak test
|
||||
- Valgrind
|
||||
- Massif
|
||||
- Xtree-memory
|
||||
- [ ] Server
|
||||
- [ ] ZeroMQ
|
||||
|
||||
|
@ -48,10 +48,11 @@
|
|||
- [x] Box contouring
|
||||
- [x] Ignore sides
|
||||
- [ ] LOD
|
||||
- [ ] Dual MC
|
||||
- [x] Dual MC
|
||||
- [ ] Octree
|
||||
- [ ] Collision
|
||||
- [ ] Dynamic index size
|
||||
- [ ] Chunk size performance
|
||||
- [x] Chunk size performance
|
||||
- [ ] Render with glBufferSubData
|
||||
- [x] Frustum Culling
|
||||
- [ ] Occlusion Culling
|
||||
|
|
|
@ -10,9 +10,19 @@ uniform sampler2DArray HOSAtlas;
|
|||
uniform mat4 View;
|
||||
uniform vec3 FogColor;
|
||||
|
||||
in VertexData {
|
||||
#ifdef BLEND
|
||||
in GeometryData
|
||||
#else
|
||||
in VertexData
|
||||
#endif
|
||||
{
|
||||
vec3 Position_worldspace;
|
||||
float Material;
|
||||
#ifdef BLEND
|
||||
flat uint Materials[3];
|
||||
vec3 MaterialRatio;
|
||||
#else
|
||||
flat uint Material;
|
||||
#endif
|
||||
vec3 FaceNormal_modelspace;
|
||||
#ifdef PBR
|
||||
vec3 FaceNormal_worldspace;
|
||||
|
@ -30,9 +40,9 @@ vec3 expand(vec3 v) {
|
|||
|
||||
vec4 getTexture(sampler2DArray sample, vec2 UV) {
|
||||
#ifdef BLEND
|
||||
vec4 colx = texture(sample, vec3(UV, vs.Materials.x));
|
||||
vec4 coly = texture(sample, vec3(UV, vs.Materials.y));
|
||||
vec4 colz = texture(sample, vec3(UV, vs.Materials.z));
|
||||
vec4 colx = texture(sample, vec3(UV, vs.Materials[0]));
|
||||
vec4 coly = texture(sample, vec3(UV, vs.Materials[1]));
|
||||
vec4 colz = texture(sample, vec3(UV, vs.Materials[2]));
|
||||
return colx * vs.MaterialRatio.x + coly * vs.MaterialRatio.y + colz * vs.MaterialRatio.z;
|
||||
#else
|
||||
return texture(sample, vec3(UV, vs.Material));
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
#version 330 core
|
||||
|
||||
|
||||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices = 3) out;
|
||||
|
||||
in VertexData {
|
||||
vec3 Position_worldspace;
|
||||
flat uint Material;
|
||||
vec3 FaceNormal_modelspace;
|
||||
#ifdef PBR
|
||||
vec3 FaceNormal_worldspace;
|
||||
vec3 EyeDirection_cameraspace;
|
||||
vec3 LightDirection_cameraspace;
|
||||
#endif
|
||||
#ifdef FOG
|
||||
float Depth;
|
||||
#endif
|
||||
} vs_in[];
|
||||
|
||||
out GeometryData {
|
||||
vec3 Position_worldspace;
|
||||
flat uint Materials[3];
|
||||
vec3 MaterialRatio;
|
||||
vec3 FaceNormal_modelspace;
|
||||
#ifdef PBR
|
||||
vec3 FaceNormal_worldspace;
|
||||
vec3 EyeDirection_cameraspace;
|
||||
vec3 LightDirection_cameraspace;
|
||||
#endif
|
||||
#ifdef FOG
|
||||
float Depth;
|
||||
#endif
|
||||
} gs;
|
||||
|
||||
void main() {
|
||||
for(int i = 0; i < gl_in.length(); i++) {
|
||||
|
||||
gl_Position = gl_in[i].gl_Position;
|
||||
gs.Position_worldspace = vs_in[i].Position_worldspace;
|
||||
gs.FaceNormal_modelspace = vs_in[i].FaceNormal_modelspace;
|
||||
gs.FaceNormal_worldspace = vs_in[i].FaceNormal_worldspace;
|
||||
|
||||
gs.Materials[i] = vs_in[i].Material;
|
||||
switch(int(mod(i,3))) {
|
||||
case 0:
|
||||
gs.MaterialRatio = vec3(1,0,0);
|
||||
break;
|
||||
case 1:
|
||||
gs.MaterialRatio = vec3(0,1,0);
|
||||
break;
|
||||
case 2:
|
||||
gs.MaterialRatio = vec3(0,0,1);
|
||||
break;
|
||||
default:
|
||||
gs.MaterialRatio = vec3(0);
|
||||
break;
|
||||
};
|
||||
|
||||
gs.EyeDirection_cameraspace = vs_in[i].EyeDirection_cameraspace;
|
||||
gs.LightDirection_cameraspace = vs_in[i].LightDirection_cameraspace;
|
||||
#ifdef SHADOW
|
||||
gs.ShadowCoord = vs_in[i].ShadowCoord;
|
||||
#endif
|
||||
#ifdef FOG
|
||||
gs.Depth = vs_in[i].Depth;
|
||||
#endif
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
|
@ -6,7 +6,7 @@ layout(location = 2) in vec3 Normal_modelspace;
|
|||
|
||||
out VertexData {
|
||||
vec3 Position_worldspace;
|
||||
float Material;
|
||||
flat uint Material;
|
||||
vec3 FaceNormal_modelspace;
|
||||
#ifdef PBR
|
||||
vec3 FaceNormal_worldspace;
|
||||
|
@ -33,7 +33,7 @@ void main(){
|
|||
vs.Depth = length((View * vec4(vs.Position_worldspace,1)).xyz) / FogDepth;
|
||||
#endif
|
||||
|
||||
vs.Material = float(Material_model);
|
||||
vs.Material = Material_model;
|
||||
|
||||
vs.FaceNormal_modelspace = normalize(Normal_modelspace);
|
||||
#ifdef PBR
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,159 @@
|
|||
#include "FlatDualMC.hpp"
|
||||
|
||||
#include "../world/Chunk.hpp"
|
||||
#include "../world/materials.hpp"
|
||||
#include <Remotery.h>
|
||||
#include <imgui.h>
|
||||
#include "dualmc.h"
|
||||
|
||||
namespace contouring {
|
||||
FlatDualMC::FlatDualMC(const std::string &str) : AbstractFlat(str) {
|
||||
auto opt = toml::parse(str);
|
||||
iso = opt["iso"].value_or(iso);
|
||||
manifold = opt["manifold"].value_or(manifold);
|
||||
|
||||
for (size_t i = 1; i <= 2; i++) {
|
||||
workers.push_back(std::thread([&] {
|
||||
while (running) {
|
||||
std::pair<chunk_pos, surrounding::corners> ctx;
|
||||
loadQueue.wait();
|
||||
if (loadQueue.pop(ctx)) {
|
||||
rmt_ScopedCPUSample(ProcessContouring, 0);
|
||||
ShortIndexedBuffer::Data data;
|
||||
render(ctx.second, data);
|
||||
loadedQueue.push({ctx.first, data});
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
FlatDualMC::~FlatDualMC() {
|
||||
running = false;
|
||||
loadQueue.notify();
|
||||
|
||||
for(auto& worker: workers) {
|
||||
if (worker.joinable())
|
||||
worker.join();
|
||||
}
|
||||
}
|
||||
|
||||
std::string FlatDualMC::getOptions() {
|
||||
std::ostringstream ss;
|
||||
ss << toml::table({
|
||||
{"load_distance", loadDistance},
|
||||
{"keep_distance", keepDistance},
|
||||
{"iso", iso},
|
||||
{"manifold", manifold}
|
||||
});
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void FlatDualMC::enqueue(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) {
|
||||
rmt_ScopedCPUSample(EnqueueContouring, RMTSF_Aggregate);
|
||||
const auto dist2 = glm::length2(pos - center);
|
||||
if (dist2 <= loadDistance * loadDistance) {
|
||||
surrounding::corners surrounding;
|
||||
if(surrounding::load(surrounding, pos, data)) {
|
||||
loadQueue.push(pos, surrounding, -dist2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlatDualMC::onUpdate(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data, Faces neighbors) {
|
||||
enqueue(pos, data);
|
||||
if (neighbors && (Faces::Left | Faces::Down | Faces::Backward)) {
|
||||
for (size_t i = 1; i < 8; i++) {
|
||||
enqueue(pos - surrounding::g_corner_offsets[i], data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlatDualMC::onNotify(const chunk_pos &pos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &data) {
|
||||
if (buffers.find(pos) == buffers.end()) {
|
||||
enqueue(pos, data);
|
||||
}
|
||||
}
|
||||
|
||||
void FlatDualMC::update(const camera_pos& pos) {
|
||||
AbstractFlat::update(pos);
|
||||
std::pair<chunk_pos, ShortIndexedBuffer::Data> out;
|
||||
reports.load.push(loadQueue.size());
|
||||
//MAYBE: clear out of range loadQueue.trim(keepDistance * keepDistance)
|
||||
reports.loaded.push(loadedQueue.size());
|
||||
while(loadedQueue.pop(out)) {
|
||||
const auto buffer = new ShortIndexedBuffer(GL_TRIANGLES, out.second);
|
||||
const auto it = buffers.find(out.first);
|
||||
if (it != buffers.end()) {
|
||||
if(it->second != NULL)
|
||||
delete it->second;
|
||||
|
||||
it->second = buffer;
|
||||
} else {
|
||||
buffers.emplace(out.first, buffer);
|
||||
}
|
||||
}
|
||||
reports.count.push(buffers.size());
|
||||
}
|
||||
|
||||
void FlatDualMC::onGui() {
|
||||
ImGui::PlotHistogram("Count", reports.count.buffer.get(), reports.count.size, 0, std::to_string(reports.count.current()).c_str(), 0);
|
||||
ImGui::PlotHistogram("Loading", reports.load.buffer.get(), reports.load.size, 0, std::to_string(reports.load.current()).c_str(), 0);
|
||||
ImGui::PlotHistogram("Waiting", reports.loaded.buffer.get(), reports.loaded.size, 0, std::to_string(reports.loaded.current()).c_str(), 0);
|
||||
ImGui::Separator();
|
||||
AbstractFlat::onGui();
|
||||
ImGui::Separator();
|
||||
ImGui::SliderFloat("Iso", &iso, 0, 1);
|
||||
ImGui::Checkbox("Manifold", &manifold);
|
||||
}
|
||||
|
||||
void FlatDualMC::render(const surrounding::corners &surrounding, ShortIndexedBuffer::Data &out) const {
|
||||
const int SIZE = CHUNK_LENGTH + 3;
|
||||
std::vector<dualmc::DualMC<float>::Point> grid;
|
||||
grid.reserve(SIZE * SIZE * SIZE);
|
||||
{
|
||||
for (int z = 0; z < SIZE; z++) {
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
const auto chunk = surrounding[(z >= CHUNK_LENGTH) + (y >= CHUNK_LENGTH)*2 + (x >= CHUNK_LENGTH)*4];
|
||||
// MAYBE: area copy
|
||||
const auto voxel = chunk->get(Chunk::getIdx(x % CHUNK_LENGTH, y % CHUNK_LENGTH, z % CHUNK_LENGTH));
|
||||
grid.push_back({voxel.Density * 1.f / UCHAR_MAX, voxel.Material});
|
||||
}}}
|
||||
}
|
||||
{
|
||||
std::vector<dualmc::Vertex> dmc_vertices;
|
||||
std::vector<dualmc::Tri> dmc_tris;
|
||||
|
||||
dualmc::DualMC<float> builder;
|
||||
builder.buildTris(&grid.front(), SIZE, SIZE, SIZE, iso, materials::roughness.cbegin(), manifold, dmc_vertices, dmc_tris);
|
||||
|
||||
out.vertices.reserve(dmc_vertices.size());
|
||||
out.materials.reserve(dmc_vertices.size());
|
||||
out.normals.reserve(dmc_vertices.size());
|
||||
for (const auto& v: dmc_vertices) {
|
||||
out.vertices.push_back(glm::vec3(v.x, v.y, v.z));
|
||||
out.materials.push_back(v.w);
|
||||
out.normals.push_back(glm::vec3(0));
|
||||
}
|
||||
|
||||
out.indices.reserve(dmc_tris.size());
|
||||
for (const auto& t: dmc_tris) {
|
||||
out.indices.push_back(t.i0);
|
||||
out.indices.push_back(t.i1);
|
||||
out.indices.push_back(t.i2);
|
||||
|
||||
glm::vec3 edge1 = out.vertices[t.i1] - out.vertices[t.i0];
|
||||
glm::vec3 edge2 = out.vertices[t.i2] - out.vertices[t.i0];
|
||||
glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2));
|
||||
|
||||
out.normals[t.i0] += normal;
|
||||
out.normals[t.i1] += normal;
|
||||
out.normals[t.i2] += normal;
|
||||
}
|
||||
|
||||
for (auto &n : out.normals) {
|
||||
n = glm::normalize(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "AbstractFlat.hpp"
|
||||
#include "surrounding.hpp"
|
||||
|
||||
#include "../data/safe_queue.hpp"
|
||||
#include "../data/safe_priority_queue.hpp"
|
||||
#include "../data/circular_buffer.hpp"
|
||||
#include "../render/buffer/ShortIndexedBuffer.hpp"
|
||||
#include <thread>
|
||||
|
||||
#define REPORT_BUFFER_SIZE 128
|
||||
|
||||
namespace contouring {
|
||||
class FlatDualMC: public AbstractFlat {
|
||||
public:
|
||||
FlatDualMC(const std::string&);
|
||||
virtual ~FlatDualMC();
|
||||
|
||||
void update(const camera_pos&) override;
|
||||
|
||||
void onGui() override;
|
||||
|
||||
std::string getOptions() override;
|
||||
|
||||
/// Chunk data change
|
||||
void onUpdate(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &, Faces) override;
|
||||
/// Chunk existante ping
|
||||
/// @note notify for chunks entering view while moving
|
||||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override;
|
||||
|
||||
protected:
|
||||
safe_priority_queue_map<chunk_pos, surrounding::corners, int> loadQueue;
|
||||
safe_queue<std::pair<chunk_pos, ShortIndexedBuffer::Data>> loadedQueue;
|
||||
|
||||
struct report {
|
||||
circular_buffer<float> count = circular_buffer<float>(REPORT_BUFFER_SIZE, 0); // MAYBE: store int
|
||||
circular_buffer<float> load = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
circular_buffer<float> loaded = circular_buffer<float>(REPORT_BUFFER_SIZE, 0);
|
||||
} reports;
|
||||
|
||||
bool running = true;
|
||||
std::vector<std::thread> workers;
|
||||
|
||||
void enqueue(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &);
|
||||
|
||||
float iso = .1f;
|
||||
bool manifold = true;
|
||||
|
||||
void render(const surrounding::corners &surrounding, ShortIndexedBuffer::Data& out) const;
|
||||
};
|
||||
}
|
|
@ -10,7 +10,7 @@ namespace contouring {
|
|||
for (size_t i = 1; i <= 4; i++) {
|
||||
workers.push_back(std::thread([&] {
|
||||
while (running) {
|
||||
std::pair<chunk_pos, surrounding::chunks> ctx;
|
||||
std::pair<chunk_pos, surrounding::faces> ctx;
|
||||
loadQueue.wait();
|
||||
if (loadQueue.pop(ctx)) {
|
||||
rmt_ScopedCPUSample(ProcessContouring, 0);
|
||||
|
@ -39,7 +39,7 @@ namespace contouring {
|
|||
rmt_ScopedCPUSample(EnqueueContouring, RMTSF_Aggregate);
|
||||
const auto dist2 = glm::length2(pos - center);
|
||||
if (dist2 <= loadDistance * loadDistance) {
|
||||
surrounding::chunks surrounding;
|
||||
surrounding::faces surrounding;
|
||||
if(surrounding::load(surrounding, pos, data)) {
|
||||
loadQueue.push(pos, surrounding, -dist2);
|
||||
}
|
||||
|
@ -102,11 +102,11 @@ namespace contouring {
|
|||
AbstractFlat::onGui();
|
||||
}
|
||||
|
||||
bool FlatSurroundingBox::isTransparent(const surrounding::chunks &surrounding, const std::pair<ushort, ushort> &idx) {
|
||||
bool FlatSurroundingBox::isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx) {
|
||||
return surrounding[idx.first]->begin()[idx.second].Density < UCHAR_MAX; // MAYBE: materials::transparent
|
||||
}
|
||||
|
||||
void FlatSurroundingBox::render(const surrounding::chunks &surrounding, std::vector<VertexData> &vertices) {
|
||||
void FlatSurroundingBox::render(const surrounding::faces &surrounding, std::vector<VertexData> &vertices) {
|
||||
const auto voxels = surrounding[surrounding::CENTER]->begin();
|
||||
vertices.clear();
|
||||
for (ushort i = 0; i < CHUNK_SIZE; i++) {
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace contouring {
|
|||
void onNotify(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &) override;
|
||||
|
||||
protected:
|
||||
safe_priority_queue_map<chunk_pos, surrounding::chunks, int> loadQueue;
|
||||
safe_priority_queue_map<chunk_pos, surrounding::faces, int> loadQueue;
|
||||
safe_queue<std::pair<chunk_pos, ShortIndexedBuffer::Data>> loadedQueue;
|
||||
|
||||
struct report {
|
||||
|
@ -43,7 +43,7 @@ namespace contouring {
|
|||
void enqueue(const chunk_pos &, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &);
|
||||
|
||||
private:
|
||||
static inline bool isTransparent(const surrounding::chunks &surrounding, const std::pair<ushort, ushort> &idx);
|
||||
static void render(const surrounding::chunks &surrounding, std::vector<VertexData> &vertices);
|
||||
static inline bool isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx);
|
||||
static void render(const surrounding::faces &surrounding, std::vector<VertexData> &vertices);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,999 @@
|
|||
// Copyright (C) 2017, Dominik Wodniok
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the BSD 3-Clause license.
|
||||
// See the LICENSE.txt file for details.
|
||||
|
||||
#ifndef DUALMC_H_INCLUDED
|
||||
#define DUALMC_H_INCLUDED
|
||||
|
||||
/// \file dualmc.h
|
||||
/// \author Dominik Wodniok
|
||||
/// \date 2009
|
||||
|
||||
// c includes
|
||||
#include <cstdint>
|
||||
|
||||
// stl includes
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace dualmc {
|
||||
|
||||
|
||||
typedef float VertexComponentsType;
|
||||
typedef uint PropertyType;
|
||||
typedef uint32_t QuadIndexType;
|
||||
typedef uint32_t TriIndexType;
|
||||
|
||||
/// vertex structure for dual points
|
||||
struct Vertex {
|
||||
/// non-initializing constructor
|
||||
Vertex();
|
||||
|
||||
/// initializing constructor
|
||||
Vertex(VertexComponentsType x, VertexComponentsType y, VertexComponentsType z, PropertyType w);
|
||||
|
||||
/// initializing constructor
|
||||
Vertex(Vertex const & v);
|
||||
|
||||
// components
|
||||
VertexComponentsType x,y,z;
|
||||
// material
|
||||
PropertyType w;
|
||||
};
|
||||
|
||||
/// tri indices structure
|
||||
struct Tri {
|
||||
/// non-initializing constructor
|
||||
Tri();
|
||||
|
||||
/// initializing constructor
|
||||
Tri(TriIndexType i0, TriIndexType i1, TriIndexType i2);
|
||||
|
||||
// tri indices
|
||||
TriIndexType i0, i1, i2;
|
||||
|
||||
};
|
||||
|
||||
/// \class DualMC
|
||||
/// \author Dominik Wodniok
|
||||
/// \date 2009
|
||||
/// Class which implements the dual marching cubes algorithm from Gregory M. Nielson.
|
||||
/// Faces and vertices of the standard marching cubes algorithm correspond to
|
||||
/// vertices and faces in the dual algorithm. As a vertex in standard marching cubes
|
||||
/// usually is shared by 4 faces, the dual mesh is entirely made from quadrangles.
|
||||
/// Unfortunately, under rare circumstances the original algorithm can create
|
||||
/// non-manifold meshes. See the remarks of the original paper on this.
|
||||
/// The class optionally can guarantee manifold meshes by taking the Manifold
|
||||
/// Dual Marching Cubes approach from Rephael Wenger as described in
|
||||
/// chapter 3.3.5 of his book "Isosurfaces: Geometry, Topology, and Algorithms".
|
||||
template<class T> class DualMC {
|
||||
public:
|
||||
// typedefs
|
||||
typedef T VolumeDataType;
|
||||
|
||||
/// point structure for input points
|
||||
struct Point {
|
||||
/// non-initializing constructor
|
||||
Point();
|
||||
|
||||
/// initializing constructor
|
||||
Point(VolumeDataType x, PropertyType w);
|
||||
|
||||
/// initializing constructor
|
||||
Point(Point const &v);
|
||||
|
||||
// components
|
||||
VolumeDataType x;
|
||||
// material
|
||||
PropertyType w;
|
||||
|
||||
inline bool operator<(const VolumeDataType& b) const { return x < b; }
|
||||
inline bool operator>=(const VolumeDataType& b) const { return x >= b; }
|
||||
|
||||
inline std::pair<PropertyType, VolumeDataType> pair() const { return std::make_pair(w, x); }
|
||||
};
|
||||
|
||||
/// Extracts the iso surface for a given volume and iso value.
|
||||
/// Output is a list of vertices and a list of indices, which connect
|
||||
/// vertices to tris.
|
||||
void buildTris(
|
||||
Point const *data,
|
||||
int32_t const dimX, int32_t const dimY, int32_t const dimZ,
|
||||
VolumeDataType const iso,
|
||||
float const *roughness,
|
||||
bool const generateManifold,
|
||||
std::vector<Vertex> &vertices,
|
||||
std::vector<Tri> &tris);
|
||||
|
||||
private:
|
||||
/// Extract tris mesh with shared vertex indices.
|
||||
void buildSharedVerticesTris(
|
||||
VolumeDataType const iso,
|
||||
std::vector<Vertex> & vertices,
|
||||
std::vector<Tri> & tris
|
||||
);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/// enum with edge codes for a 12-bit voxel edge mask to indicate
|
||||
/// grid edges which intersect the ISO surface of classic marching cubes
|
||||
enum DMCEdgeCode {
|
||||
EDGE0 = 1,
|
||||
EDGE1 = 1 << 1,
|
||||
EDGE2 = 1 << 2,
|
||||
EDGE3 = 1 << 3,
|
||||
EDGE4 = 1 << 4,
|
||||
EDGE5 = 1 << 5,
|
||||
EDGE6 = 1 << 6,
|
||||
EDGE7 = 1 << 7,
|
||||
EDGE8 = 1 << 8,
|
||||
EDGE9 = 1 << 9,
|
||||
EDGE10 = 1 << 10,
|
||||
EDGE11 = 1 << 11,
|
||||
FORCE_32BIT = 0xffffffff
|
||||
};
|
||||
|
||||
/// get the 8-bit in-out mask for the voxel corners of the cell cube at (cx,cy,cz)
|
||||
/// and the given iso value
|
||||
int getCellCode(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso) const;
|
||||
|
||||
/// Get the 12-bit dual point code mask, which encodes the traditional
|
||||
/// marching cube vertices of the traditional marching cubes face which
|
||||
/// corresponds to the dual point.
|
||||
/// This is also where the manifold dual marching cubes algorithm is
|
||||
/// implemented.
|
||||
int getDualPointCode(int32_t const cx, int32_t const cy, int32_t const cz,
|
||||
VolumeDataType const iso, DMCEdgeCode const edge) const;
|
||||
|
||||
/// Given a dual point code and iso value, compute the dual point.
|
||||
void calculateDualPoint(int32_t const cx, int32_t const cy, int32_t const cz,
|
||||
VolumeDataType const iso, int const pointCode, Vertex &v) const;
|
||||
|
||||
/// Get the shared index of a dual point which is uniquly identified by its
|
||||
/// cell cube index and a cube edge. The dual point is computed,
|
||||
/// if it has not been computed before.
|
||||
QuadIndexType getSharedDualPointIndex(int32_t const cx, int32_t const cy, int32_t const cz,
|
||||
VolumeDataType const iso, DMCEdgeCode const edge,
|
||||
std::vector<Vertex> & vertices);
|
||||
|
||||
/// Compute a linearized cell cube index.
|
||||
int32_t gA(int32_t const x, int32_t const y, int32_t const z) const;
|
||||
|
||||
/// Update material if max.
|
||||
void maxProp(int32_t const x, int32_t const y, int32_t const z, Vertex &vertex, VolumeDataType& max) const;
|
||||
|
||||
protected:
|
||||
// static lookup tables needed for (manifold) dual marching cubes
|
||||
|
||||
/// Dual Marching Cubes table
|
||||
/// Encodes the edge vertices for the 256 marching cubes cases.
|
||||
/// A marching cube case produces up to four faces and ,thus, up to four
|
||||
/// dual points.
|
||||
static int32_t const dualPointsList[256][4];
|
||||
|
||||
/// Table which encodes the ambiguous face of cube configurations, which
|
||||
/// can cause non-manifold meshes.
|
||||
/// Needed for manifold dual marching cubes.
|
||||
static uint8_t const problematicConfigs[256];
|
||||
|
||||
protected:
|
||||
|
||||
/// convenience volume extent array for x-,y-, and z-dimension
|
||||
int32_t dims[3];
|
||||
|
||||
/// convenience volume data point
|
||||
Point const *data;
|
||||
|
||||
/// property roughness table
|
||||
float const *roughness;
|
||||
|
||||
/// store whether the manifold dual marching cubes algorithm should be
|
||||
/// applied.
|
||||
bool generateManifold;
|
||||
|
||||
/// Dual point key structure for hashing of shared vertices
|
||||
struct DualPointKey {
|
||||
// a dual point can be uniquely identified by ite linearized volume cell
|
||||
// id and point code
|
||||
int32_t linearizedCellID;
|
||||
int pointCode;
|
||||
/// Equal operator for unordered map
|
||||
bool operator==(DualPointKey const & other) const;
|
||||
};
|
||||
|
||||
/// Functor for dual point key hash generation
|
||||
struct DualPointKeyHash {
|
||||
size_t operator()(DualPointKey const & k) const {
|
||||
return size_t(k.linearizedCellID) | (size_t(k.pointCode) << 32u);
|
||||
}
|
||||
};
|
||||
|
||||
/// Hash map for shared vertex index computations
|
||||
std::unordered_map<DualPointKey,QuadIndexType,DualPointKeyHash> pointToIndex;
|
||||
};
|
||||
|
||||
// inline function definitions
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
Vertex::Vertex(){}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
Vertex::Vertex(
|
||||
VertexComponentsType x,
|
||||
VertexComponentsType y,
|
||||
VertexComponentsType z,
|
||||
PropertyType w
|
||||
) : x(x), y(y), z(z), w(w) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
Vertex::Vertex(Vertex const & v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
Tri::Tri() {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
Tri::Tri(
|
||||
TriIndexType i0,
|
||||
TriIndexType i1,
|
||||
TriIndexType i2
|
||||
) : i0(i0), i1(i1), i2(i2) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
DualMC<T>::Point::Point() {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
DualMC<T>::Point::Point(VolumeDataType x, PropertyType w): x(x), w(w) { }
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
DualMC<T>::Point::Point(Point const &v): x(v.x), w(v.w) {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
int32_t DualMC<T>::gA(int32_t const x, int32_t const y, int32_t const z) const {
|
||||
return x + dims[0] * (y + dims[1] * z);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
void DualMC<T>::maxProp(int32_t const x, int32_t const y, int32_t const z, Vertex &vertex, VolumeDataType &max) const {
|
||||
if(data[gA(x, y, z)].x > max) {
|
||||
max = data[gA(x, y, z)].x;
|
||||
vertex.w = data[gA(x, y, z)].w;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template<class T> inline
|
||||
bool DualMC<T>::DualPointKey::operator==(typename DualMC<T>::DualPointKey const & other) const {
|
||||
return linearizedCellID == other.linearizedCellID && pointCode == other.pointCode;
|
||||
}
|
||||
|
||||
// Copyright (C) 2017, Dominik Wodniok
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the BSD 3-Clause license. See the LICENSE.txt file for details.
|
||||
|
||||
/// \file dualmc.tpp
|
||||
/// \author Dominik Wodniok
|
||||
/// \date 2009
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
int DualMC<T>::getCellCode(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso) const {
|
||||
// determine for each cube corner if it is outside or inside
|
||||
int code = 0;
|
||||
if (data[gA(cx, cy, cz)] >= iso)
|
||||
code |= 1;
|
||||
if (data[gA(cx + 1, cy, cz)] >= iso)
|
||||
code |= 2;
|
||||
if (data[gA(cx, cy + 1, cz)] >= iso)
|
||||
code |= 4;
|
||||
if (data[gA(cx + 1, cy + 1, cz)] >= iso)
|
||||
code |= 8;
|
||||
if (data[gA(cx, cy, cz + 1)] >= iso)
|
||||
code |= 16;
|
||||
if (data[gA(cx + 1, cy, cz + 1)] >= iso)
|
||||
code |= 32;
|
||||
if (data[gA(cx, cy + 1, cz + 1)] >= iso)
|
||||
code |= 64;
|
||||
if (data[gA(cx + 1, cy + 1, cz + 1)] >= iso)
|
||||
code |= 128;
|
||||
return code;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
int DualMC<T>::getDualPointCode(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso, DMCEdgeCode const edge) const {
|
||||
int cubeCode = getCellCode(cx, cy, cz, iso);
|
||||
|
||||
// is manifold dual marching cubes desired?
|
||||
if (generateManifold) {
|
||||
// The Manifold Dual Marching Cubes approach from Rephael Wenger as described in
|
||||
// chapter 3.3.5 of his book "Isosurfaces: Geometry, Topology, and Algorithms"
|
||||
// is implemente here.
|
||||
// If a problematic C16 or C19 configuration shares the ambiguous face
|
||||
// with another C16 or C19 configuration we simply invert the cube code
|
||||
// before looking up dual points. Doing this for these pairs ensures
|
||||
// manifold meshes.
|
||||
// But this removes the dualism to marching cubes.
|
||||
|
||||
// check if we have a potentially problematic configuration
|
||||
uint8_t const direction = problematicConfigs[uint8_t(cubeCode)];
|
||||
// If the direction code is in {0,...,5} we have a C16 or C19 configuration.
|
||||
if (direction != 255) {
|
||||
// We have to check the neighboring cube, which shares the ambiguous
|
||||
// face. For this we decode the direction. This could also be done
|
||||
// with another lookup table.
|
||||
// copy current cube coordinates into an array.
|
||||
int32_t neighborCoords[] = { cx,cy,cz };
|
||||
// get the dimension of the non-zero coordinate axis
|
||||
unsigned int const component = direction >> 1;
|
||||
// get the sign of the direction
|
||||
int32_t delta = (direction & 1) == 1 ? 1 : -1;
|
||||
// modify the correspong cube coordinate
|
||||
neighborCoords[component] += delta;
|
||||
// have we left the volume in this direction?
|
||||
if (neighborCoords[component] >= 0 && neighborCoords[component] < (dims[component] - 1)) {
|
||||
// get the cube configuration of the relevant neighbor
|
||||
int neighborCubeCode = getCellCode(neighborCoords[0], neighborCoords[1], neighborCoords[2], iso);
|
||||
// Look up the neighbor configuration ambiguous face direction.
|
||||
// If the direction is valid we have a C16 or C19 neighbor.
|
||||
// As C16 and C19 have exactly one ambiguous face this face is
|
||||
// guaranteed to be shared for the pair.
|
||||
if (problematicConfigs[uint8_t(neighborCubeCode)] != 255) {
|
||||
// replace the cube configuration with its inverse.
|
||||
cubeCode ^= 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (dualPointsList[cubeCode][i] & edge) {
|
||||
return dualPointsList[cubeCode][i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
void DualMC<T>::calculateDualPoint(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso, int const pointCode, Vertex & v) const {
|
||||
// initialize the point with lower voxel coordinates
|
||||
v.x = static_cast<VertexComponentsType>(cx);
|
||||
v.y = static_cast<VertexComponentsType>(cy);
|
||||
v.z = static_cast<VertexComponentsType>(cz);
|
||||
|
||||
// compute the dual point as the mean of the face vertices belonging to the
|
||||
// original marching cubes face
|
||||
Vertex p;
|
||||
p.x = 0;
|
||||
p.y = 0;
|
||||
p.z = 0;
|
||||
int points = 0;
|
||||
float max = 0;
|
||||
|
||||
// sum edge intersection vertices using the point code
|
||||
if (pointCode & EDGE0) {
|
||||
p.x += ((float)iso - data[gA(cx, cy, cz)].x) / (data[gA(cx + 1, cy, cz)].x - data[gA(cx, cy, cz)].x);
|
||||
points++;
|
||||
maxProp(cx, cy, cz, v, max);
|
||||
maxProp(cx + 1, cy, cz, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE1) {
|
||||
p.x += 1.0f;
|
||||
p.z += ((float)iso - data[gA(cx + 1, cy, cz)].x) / (data[gA(cx + 1, cy, cz + 1)].x - data[gA(cx + 1, cy, cz)].x);
|
||||
points++;
|
||||
maxProp(cx + 1, cy, cz, v, max);
|
||||
maxProp(cx + 1, cy, cz + 1, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE2) {
|
||||
p.x += ((float)iso - data[gA(cx, cy, cz + 1)].x) / (data[gA(cx + 1, cy, cz + 1)].x - data[gA(cx, cy, cz + 1)].x);
|
||||
p.z += 1.0f;
|
||||
points++;
|
||||
maxProp(cx, cy, cz + 1, v, max);
|
||||
maxProp(cx + 1, cy, cz + 1, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE3) {
|
||||
p.z += ((float)iso - data[gA(cx, cy, cz)].x) / (data[gA(cx, cy, cz + 1)].x - data[gA(cx, cy, cz)].x);
|
||||
points++;
|
||||
maxProp(cx, cy, cz, v, max);
|
||||
maxProp(cx, cy, cz + 1, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE4) {
|
||||
p.x += ((float)iso - data[gA(cx, cy + 1, cz)].x) / (data[gA(cx + 1, cy + 1, cz)].x - data[gA(cx, cy + 1, cz)].x);
|
||||
p.y += 1.0f;
|
||||
points++;
|
||||
maxProp(cx, cy+1, cz, v, max);
|
||||
maxProp(cx + 1, cy+1, cz, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE5) {
|
||||
p.x += 1.0f;
|
||||
p.z += ((float)iso - data[gA(cx + 1, cy + 1, cz)].x) / (data[gA(cx + 1, cy + 1, cz + 1)].x - data[gA(cx + 1, cy + 1, cz)].x);
|
||||
p.y += 1.0f;
|
||||
points++;
|
||||
maxProp(cx+1, cy+1, cz, v, max);
|
||||
maxProp(cx + 1, cy+1, cz+1, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE6) {
|
||||
p.x += ((float)iso - data[gA(cx, cy + 1, cz + 1)].x) / (data[gA(cx + 1, cy + 1, cz + 1)].x - data[gA(cx, cy + 1, cz + 1)].x);
|
||||
p.z += 1.0f;
|
||||
p.y += 1.0f;
|
||||
points++;
|
||||
maxProp(cx, cy+1, cz+1, v, max);
|
||||
maxProp(cx + 1, cy+1, cz+1, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE7) {
|
||||
p.z += ((float)iso - data[gA(cx, cy + 1, cz)].x) / (data[gA(cx, cy + 1, cz + 1)].x - data[gA(cx, cy + 1, cz)].x);
|
||||
p.y += 1.0f;
|
||||
points++;
|
||||
maxProp(cx, cy+1, cz, v, max);
|
||||
maxProp(cx, cy+1, cz+1, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE8) {
|
||||
p.y += ((float)iso - data[gA(cx, cy, cz)].x) / (data[gA(cx, cy + 1, cz)].x - data[gA(cx, cy, cz)].x);
|
||||
points++;
|
||||
maxProp(cx, cy, cz, v, max);
|
||||
maxProp(cx, cy+1, cz, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE9) {
|
||||
p.x += 1.0f;
|
||||
p.y += ((float)iso - data[gA(cx + 1, cy, cz)].x) / (data[gA(cx + 1, cy + 1, cz)].x - data[gA(cx + 1, cy, cz)].x);
|
||||
points++;
|
||||
maxProp(cx+1, cy, cz, v, max);
|
||||
maxProp(cx + 1, cy+1, cz, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE10) {
|
||||
p.x += 1.0f;
|
||||
p.y += ((float)iso - data[gA(cx + 1, cy, cz + 1)].x) / (data[gA(cx + 1, cy + 1, cz + 1)].x - data[gA(cx + 1, cy, cz + 1)].x);
|
||||
p.z += 1.0f;
|
||||
points++;
|
||||
maxProp(cx+1, cy, cz+1, v, max);
|
||||
maxProp(cx + 1, cy+1, cz+1, v, max);
|
||||
}
|
||||
|
||||
if (pointCode & EDGE11) {
|
||||
p.z += 1.0f;
|
||||
p.y += ((float)iso - data[gA(cx, cy, cz + 1)].x) / (data[gA(cx, cy + 1, cz + 1)].x - data[gA(cx, cy, cz + 1)].x);
|
||||
points++;
|
||||
maxProp(cx, cy, cz+1, v, max);
|
||||
maxProp(cx, cy+1, cz+1, v, max);
|
||||
}
|
||||
|
||||
// divide by number of accumulated points
|
||||
float invPoints = (1.f - roughness[v.w]) / (float)points;
|
||||
p.x *= invPoints;
|
||||
p.y *= invPoints;
|
||||
p.z *= invPoints;
|
||||
|
||||
// offset point by voxel coordinates
|
||||
v.x += p.x;
|
||||
v.y += p.y;
|
||||
v.z += p.z;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
QuadIndexType DualMC<T>::getSharedDualPointIndex(
|
||||
int32_t const cx, int32_t const cy, int32_t const cz,
|
||||
VolumeDataType const iso, DMCEdgeCode const edge,
|
||||
std::vector<Vertex> & vertices
|
||||
) {
|
||||
// create a key for the dual point from its linearized cell ID and point code
|
||||
DualPointKey key;
|
||||
key.linearizedCellID = gA(cx, cy, cz);
|
||||
key.pointCode = getDualPointCode(cx, cy, cz, iso, edge);
|
||||
|
||||
// have we already computed the dual point?
|
||||
auto iterator = pointToIndex.find(key);
|
||||
if (iterator != pointToIndex.end()) {
|
||||
// just return the dual point index
|
||||
return iterator->second;
|
||||
}
|
||||
else {
|
||||
// create new vertex and vertex id
|
||||
QuadIndexType newVertexId = static_cast<QuadIndexType>(vertices.size());
|
||||
vertices.emplace_back();
|
||||
calculateDualPoint(cx, cy, cz, iso, key.pointCode, vertices.back());
|
||||
// insert vertex ID into map and also return it
|
||||
pointToIndex[key] = newVertexId;
|
||||
return newVertexId;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T> inline
|
||||
void DualMC<T>::buildTris(
|
||||
Point const * data,
|
||||
int32_t const dimX, int32_t const dimY, int32_t const dimZ,
|
||||
VolumeDataType const iso,
|
||||
float const * roughness,
|
||||
bool const generateManifold,
|
||||
std::vector<Vertex> & vertices,
|
||||
std::vector<Tri> & tris
|
||||
) {
|
||||
|
||||
// set members
|
||||
this->dims[0] = dimX;
|
||||
this->dims[1] = dimY;
|
||||
this->dims[2] = dimZ;
|
||||
this->data = data;
|
||||
this->roughness = roughness;
|
||||
this->generateManifold = generateManifold;
|
||||
|
||||
// clear vertices and quad indices
|
||||
vertices.clear();
|
||||
tris.clear();
|
||||
|
||||
buildSharedVerticesTris(iso, vertices, tris);
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
void DualMC<T>::buildSharedVerticesTris(
|
||||
VolumeDataType const iso,
|
||||
std::vector<Vertex> & vertices,
|
||||
std::vector<Tri> & tris
|
||||
) {
|
||||
int32_t const reducedX = dims[0] - 2;
|
||||
int32_t const reducedY = dims[1] - 2;
|
||||
int32_t const reducedZ = dims[2] - 2;
|
||||
|
||||
TriIndexType i0, i1, i2, i3;
|
||||
|
||||
pointToIndex.clear();
|
||||
|
||||
// iterate voxels
|
||||
for (int32_t z = 0; z < reducedZ; ++z)
|
||||
for (int32_t y = 0; y < reducedY; ++y)
|
||||
for (int32_t x = 0; x < reducedX; ++x) {
|
||||
// construct quads for x edge
|
||||
if (z > 0 && y > 0) {
|
||||
bool const entering = data[gA(x, y, z)] < iso && data[gA(x + 1, y, z)] >= iso;
|
||||
bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x + 1, y, z)] < iso;
|
||||
if (entering || exiting) {
|
||||
// get quad
|
||||
i0 = getSharedDualPointIndex(x, y, z, iso, EDGE0, vertices);
|
||||
i1 = getSharedDualPointIndex(x, y, z - 1, iso, EDGE2, vertices);
|
||||
i2 = getSharedDualPointIndex(x, y - 1, z - 1, iso, EDGE6, vertices);
|
||||
i3 = getSharedDualPointIndex(x, y - 1, z, iso, EDGE4, vertices);
|
||||
|
||||
if (entering) {
|
||||
tris.emplace_back(i0, i1, i2);
|
||||
tris.emplace_back(i2, i3, i0);
|
||||
}
|
||||
else {
|
||||
tris.emplace_back(i2, i1, i0);
|
||||
tris.emplace_back(i0, i3, i2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// construct quads for y edge
|
||||
if (z > 0 && x > 0) {
|
||||
bool const entering = data[gA(x, y, z)] < iso && data[gA(x, y + 1, z)] >= iso;
|
||||
bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x, y + 1, z)] < iso;
|
||||
if (entering || exiting) {
|
||||
// generate quad
|
||||
i0 = getSharedDualPointIndex(x, y, z, iso, EDGE8, vertices);
|
||||
i1 = getSharedDualPointIndex(x, y, z - 1, iso, EDGE11, vertices);
|
||||
i2 = getSharedDualPointIndex(x - 1, y, z - 1, iso, EDGE10, vertices);
|
||||
i3 = getSharedDualPointIndex(x - 1, y, z, iso, EDGE9, vertices);
|
||||
|
||||
if (exiting) {
|
||||
tris.emplace_back(i0, i1, i2);
|
||||
tris.emplace_back(i2, i3, i0);
|
||||
}
|
||||
else {
|
||||
tris.emplace_back(i2, i1, i0);
|
||||
tris.emplace_back(i0, i3, i2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// construct quads for z edge
|
||||
if (x > 0 && y > 0) {
|
||||
bool const entering = data[gA(x, y, z)] < iso && data[gA(x, y, z + 1)] >= iso;
|
||||
bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x, y, z + 1)] < iso;
|
||||
if (entering || exiting) {
|
||||
// generate quad
|
||||
i0 = getSharedDualPointIndex(x, y, z, iso, EDGE3, vertices);
|
||||
i1 = getSharedDualPointIndex(x - 1, y, z, iso, EDGE1, vertices);
|
||||
i2 = getSharedDualPointIndex(x - 1, y - 1, z, iso, EDGE5, vertices);
|
||||
i3 = getSharedDualPointIndex(x, y - 1, z, iso, EDGE7, vertices);
|
||||
|
||||
if (exiting) {
|
||||
tris.emplace_back(i0, i1, i2);
|
||||
tris.emplace_back(i2, i3, i0);
|
||||
}
|
||||
else {
|
||||
tris.emplace_back(i2, i1, i0);
|
||||
tris.emplace_back(i0, i3, i2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (C) 2018, Dominik Wodniok
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the BSD 3-Clause license.
|
||||
// See the LICENSE.txt file for details.
|
||||
|
||||
/// \file dualmc_table.tpp
|
||||
/// \author Dominik Wodniok
|
||||
/// \date 2009
|
||||
|
||||
// TODO: invert y and z
|
||||
// Coordinate system
|
||||
//
|
||||
// y
|
||||
// |
|
||||
// |
|
||||
// |
|
||||
// 0-----x
|
||||
// /
|
||||
// /
|
||||
// z
|
||||
//
|
||||
|
||||
// Cell Corners
|
||||
// (Corners are voxels. Number correspond to Morton codes of corner coordinates)
|
||||
//
|
||||
// 2-------------------3
|
||||
// /| /|
|
||||
// / | / |
|
||||
// / | / |
|
||||
// 6-------------------7 |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | 0---------------|---1
|
||||
// | / | /
|
||||
// | / | /
|
||||
// |/ |/
|
||||
// 4-------------------5
|
||||
//
|
||||
|
||||
|
||||
// Cell Edges
|
||||
//
|
||||
// o--------4----------o
|
||||
// /| /|
|
||||
// 7 | 5 |
|
||||
// / | / |
|
||||
// o--------6----------o |
|
||||
// | 8 | 9
|
||||
// | | | |
|
||||
// | | | |
|
||||
// 11 | 10 |
|
||||
// | o--------0------|---o
|
||||
// | / | /
|
||||
// | 3 | 1
|
||||
// |/ |/
|
||||
// o--------2----------o
|
||||
//
|
||||
|
||||
// Encodes the edge vertices for the 256 marching cubes cases.
|
||||
// A marching cube case produces up to four faces and ,thus, up to four
|
||||
// dual points.
|
||||
template<class T>
|
||||
int32_t const DualMC<T>::dualPointsList[256][4] = {
|
||||
{0, 0, 0, 0}, // 0
|
||||
{EDGE0 | EDGE3 | EDGE8, 0, 0, 0}, // 1
|
||||
{EDGE0 | EDGE1 | EDGE9, 0, 0, 0}, // 2
|
||||
{EDGE1 | EDGE3 | EDGE8 | EDGE9, 0, 0, 0}, // 3
|
||||
{EDGE4 | EDGE7 | EDGE8, 0, 0, 0}, // 4
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE7, 0, 0, 0}, // 5
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE4 | EDGE7 | EDGE8, 0, 0}, // 6
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE7 | EDGE9, 0, 0, 0}, // 7
|
||||
{EDGE4 | EDGE5 | EDGE9, 0, 0, 0}, // 8
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE4 | EDGE5 | EDGE9, 0, 0}, // 9
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE5, 0, 0, 0}, // 10
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE5 | EDGE8, 0, 0, 0}, // 11
|
||||
{EDGE5 | EDGE7 | EDGE8 | EDGE9, 0, 0, 0}, // 12
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE7 | EDGE9, 0, 0, 0}, // 13
|
||||
{EDGE0 | EDGE1 | EDGE5 | EDGE7 | EDGE8, 0, 0, 0}, // 14
|
||||
{EDGE1 | EDGE3 | EDGE5 | EDGE7, 0, 0, 0}, // 15
|
||||
{EDGE2 | EDGE3 | EDGE11, 0, 0, 0}, // 16
|
||||
{EDGE0 | EDGE2 | EDGE8 | EDGE11, 0, 0, 0}, // 17
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 18
|
||||
{EDGE1 | EDGE2 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 19
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 20
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE7 | EDGE11, 0, 0, 0}, // 21
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE4 | EDGE7 | EDGE8, EDGE2 | EDGE3 | EDGE11, 0}, // 22
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE7 | EDGE9 | EDGE11, 0, 0, 0}, // 23
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 24
|
||||
{EDGE0 | EDGE2 | EDGE8 | EDGE11, EDGE4 | EDGE5 | EDGE9, 0, 0}, // 25
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE5, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 26
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE5 | EDGE8 | EDGE11, 0, 0, 0}, // 27
|
||||
{EDGE5 | EDGE7 | EDGE8 | EDGE9, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 28
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE7 | EDGE9 | EDGE11, 0, 0, 0}, // 29
|
||||
{EDGE0 | EDGE1 | EDGE5 | EDGE7 | EDGE8, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 30
|
||||
{EDGE1 | EDGE2 | EDGE5 | EDGE7 | EDGE11, 0, 0, 0}, // 31
|
||||
{EDGE1 | EDGE2 | EDGE10, 0, 0, 0}, // 32
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 33
|
||||
{EDGE0 | EDGE2 | EDGE9 | EDGE10, 0, 0, 0}, // 34
|
||||
{EDGE2 | EDGE3 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 35
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 36
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE7, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 37
|
||||
{EDGE0 | EDGE2 | EDGE9 | EDGE10, EDGE4 | EDGE7 | EDGE8, 0, 0}, // 38
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE7 | EDGE9 | EDGE10, 0, 0, 0}, // 39
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 40
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE4 | EDGE5 | EDGE9, EDGE1 | EDGE2 | EDGE10, 0}, // 41
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE5 | EDGE10, 0, 0, 0}, // 42
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE5 | EDGE8 | EDGE10, 0, 0, 0}, // 43
|
||||
{EDGE5 | EDGE7 | EDGE8 | EDGE9, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 44
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE7 | EDGE9, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 45
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE7 | EDGE8 | EDGE10, 0, 0, 0}, // 46
|
||||
{EDGE2 | EDGE3 | EDGE5 | EDGE7 | EDGE10, 0, 0, 0}, // 47
|
||||
{EDGE1 | EDGE3 | EDGE10 | EDGE11, 0, 0, 0}, // 48
|
||||
{EDGE0 | EDGE1 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 49
|
||||
{EDGE0 | EDGE3 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 50
|
||||
{EDGE8 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 51
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE1 | EDGE3 | EDGE10 | EDGE11, 0, 0}, // 52
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE7 | EDGE10 | EDGE11, 0, 0, 0}, // 53
|
||||
{EDGE0 | EDGE3 | EDGE9 | EDGE10 | EDGE11, EDGE4 | EDGE7 | EDGE8, 0, 0}, // 54
|
||||
{EDGE4 | EDGE7 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 55
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE1 | EDGE3 | EDGE10 | EDGE11, 0, 0}, // 56
|
||||
{EDGE0 | EDGE1 | EDGE8 | EDGE10 | EDGE11, EDGE4 | EDGE5 | EDGE9, 0, 0}, // 57
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE5 | EDGE10 | EDGE11, 0, 0, 0}, // 58
|
||||
{EDGE4 | EDGE5 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 59
|
||||
{EDGE5 | EDGE7 | EDGE8 | EDGE9, EDGE1 | EDGE3 | EDGE10 | EDGE11, 0, 0}, // 60
|
||||
{EDGE0 | EDGE1 | EDGE5 | EDGE7 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 61
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE7 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 62
|
||||
{EDGE5 | EDGE7 | EDGE10 | EDGE11, 0, 0, 0}, // 63
|
||||
{EDGE6 | EDGE7 | EDGE11, 0, 0, 0}, // 64
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 65
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 66
|
||||
{EDGE1 | EDGE3 | EDGE8 | EDGE9, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 67
|
||||
{EDGE4 | EDGE6 | EDGE8 | EDGE11, 0, 0, 0}, // 68
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE6 | EDGE11, 0, 0, 0}, // 69
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE4 | EDGE6 | EDGE8 | EDGE11, 0, 0}, // 70
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE6 | EDGE9 | EDGE11, 0, 0, 0}, // 71
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 72
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE4 | EDGE5 | EDGE9, EDGE6 | EDGE7 | EDGE11, 0}, // 73
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE5, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 74
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE5 | EDGE8, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 75
|
||||
{EDGE5 | EDGE6 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 76
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE6 | EDGE9 | EDGE11, 0, 0, 0}, // 77
|
||||
{EDGE0 | EDGE1 | EDGE5 | EDGE6 | EDGE8 | EDGE11, 0, 0, 0}, // 78
|
||||
{EDGE1 | EDGE3 | EDGE5 | EDGE6 | EDGE11, 0, 0, 0}, // 79
|
||||
{EDGE2 | EDGE3 | EDGE6 | EDGE7, 0, 0, 0}, // 80
|
||||
{EDGE0 | EDGE2 | EDGE6 | EDGE7 | EDGE8, 0, 0, 0}, // 81
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE2 | EDGE3 | EDGE6 | EDGE7, 0, 0}, // 82
|
||||
{EDGE1 | EDGE2 | EDGE6 | EDGE7 | EDGE8 | EDGE9, 0, 0, 0}, // 83
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE6 | EDGE8, 0, 0, 0}, // 84
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE6, 0, 0, 0}, // 85
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE2 | EDGE3 | EDGE4 | EDGE6 | EDGE8, 0, 0}, // 86
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE6 | EDGE9, 0, 0, 0}, // 87
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE2 | EDGE3 | EDGE6 | EDGE7, 0, 0}, // 88
|
||||
{EDGE0 | EDGE2 | EDGE6 | EDGE7 | EDGE8, EDGE4 | EDGE5 | EDGE9, 0, 0}, // 89
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE5, EDGE2 | EDGE3 | EDGE6 | EDGE7, 0, 0}, // 90
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE5 | EDGE6 | EDGE7 | EDGE8, 0, 0, 0}, // 91
|
||||
{EDGE2 | EDGE3 | EDGE5 | EDGE6 | EDGE8 | EDGE9, 0, 0, 0}, // 92
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE6 | EDGE9, 0, 0, 0}, // 93
|
||||
{EDGE0 | EDGE1 | EDGE2 | EDGE3 | EDGE5 | EDGE6 | EDGE8, 0, 0, 0}, // 94
|
||||
{EDGE1 | EDGE2 | EDGE5 | EDGE6, 0, 0, 0}, // 95
|
||||
{EDGE1 | EDGE2 | EDGE10, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 96
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE1 | EDGE2 | EDGE10, EDGE6 | EDGE7 | EDGE11, 0}, // 97
|
||||
{EDGE0 | EDGE2 | EDGE9 | EDGE10, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 98
|
||||
{EDGE2 | EDGE3 | EDGE8 | EDGE9 | EDGE10, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 99
|
||||
{EDGE4 | EDGE6 | EDGE8 | EDGE11, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 100
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE6 | EDGE11, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 101
|
||||
{EDGE0 | EDGE2 | EDGE9 | EDGE10, EDGE4 | EDGE6 | EDGE8 | EDGE11, 0, 0}, // 102
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE6 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 103
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE1 | EDGE2 | EDGE10, EDGE6 | EDGE7 | EDGE11, 0}, // 104
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE4 | EDGE5 | EDGE9, EDGE1 | EDGE2 | EDGE10, EDGE6 | EDGE7 | EDGE11}, // 105
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE5 | EDGE10, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 106
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE5 | EDGE8 | EDGE10, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 107
|
||||
{EDGE5 | EDGE6 | EDGE8 | EDGE9 | EDGE11, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 108
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE6 | EDGE9 | EDGE11, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 109
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE6 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 110
|
||||
{EDGE2 | EDGE3 | EDGE5 | EDGE6 | EDGE10 | EDGE11, 0, 0, 0}, // 111
|
||||
{EDGE1 | EDGE3 | EDGE6 | EDGE7 | EDGE10, 0, 0, 0}, // 112
|
||||
{EDGE0 | EDGE1 | EDGE6 | EDGE7 | EDGE8 | EDGE10, 0, 0, 0}, // 113
|
||||
{EDGE0 | EDGE3 | EDGE6 | EDGE7 | EDGE9 | EDGE10, 0, 0, 0}, // 114
|
||||
{EDGE6 | EDGE7 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 115
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE6 | EDGE8 | EDGE10, 0, 0, 0}, // 116
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE6 | EDGE10, 0, 0, 0}, // 117
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE6 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 118
|
||||
{EDGE4 | EDGE6 | EDGE9 | EDGE10, 0, 0, 0}, // 119
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE1 | EDGE3 | EDGE6 | EDGE7 | EDGE10, 0, 0}, // 120
|
||||
{EDGE0 | EDGE1 | EDGE6 | EDGE7 | EDGE8 | EDGE10, EDGE4 | EDGE5 | EDGE9, 0, 0}, // 121
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE5 | EDGE6 | EDGE7 | EDGE10, 0, 0, 0}, // 122
|
||||
{EDGE4 | EDGE5 | EDGE6 | EDGE7 | EDGE8 | EDGE10, 0, 0, 0}, // 123
|
||||
{EDGE1 | EDGE3 | EDGE5 | EDGE6 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 124
|
||||
{EDGE0 | EDGE1 | EDGE5 | EDGE6 | EDGE9 | EDGE10, 0, 0, 0}, // 125
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 126
|
||||
{EDGE5 | EDGE6 | EDGE10, 0, 0, 0}, // 127
|
||||
{EDGE5 | EDGE6 | EDGE10, 0, 0, 0}, // 128
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 129
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 130
|
||||
{EDGE1 | EDGE3 | EDGE8 | EDGE9, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 131
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 132
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE7, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 133
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE4 | EDGE7 | EDGE8, EDGE5 | EDGE6 | EDGE10, 0}, // 134
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE7 | EDGE9, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 135
|
||||
{EDGE4 | EDGE6 | EDGE9 | EDGE10, 0, 0, 0}, // 136
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE4 | EDGE6 | EDGE9 | EDGE10, 0, 0}, // 137
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE6 | EDGE10, 0, 0, 0}, // 138
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE6 | EDGE8 | EDGE10, 0, 0, 0}, // 139
|
||||
{EDGE6 | EDGE7 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 140
|
||||
{EDGE0 | EDGE3 | EDGE6 | EDGE7 | EDGE9 | EDGE10, 0, 0, 0}, // 141
|
||||
{EDGE0 | EDGE1 | EDGE6 | EDGE7 | EDGE8 | EDGE10, 0, 0, 0}, // 142
|
||||
{EDGE1 | EDGE3 | EDGE6 | EDGE7 | EDGE10, 0, 0, 0}, // 143
|
||||
{EDGE2 | EDGE3 | EDGE11, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 144
|
||||
{EDGE0 | EDGE2 | EDGE8 | EDGE11, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 145
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE2 | EDGE3 | EDGE11, EDGE5 | EDGE6 | EDGE10, 0}, // 146
|
||||
{EDGE1 | EDGE2 | EDGE8 | EDGE9 | EDGE11, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 147
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE2 | EDGE3 | EDGE11, EDGE5 | EDGE6 | EDGE10, 0}, // 148
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE7 | EDGE11, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 149
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE4 | EDGE7 | EDGE8, EDGE2 | EDGE3 | EDGE11, EDGE5 | EDGE6 | EDGE10}, // 150
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE7 | EDGE9 | EDGE11, EDGE5 | EDGE6 | EDGE10, 0, 0}, // 151
|
||||
{EDGE4 | EDGE6 | EDGE9 | EDGE10, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 152
|
||||
{EDGE0 | EDGE2 | EDGE8 | EDGE11, EDGE4 | EDGE6 | EDGE9 | EDGE10, 0, 0}, // 153
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE6 | EDGE10, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 154
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE6 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 155
|
||||
{EDGE6 | EDGE7 | EDGE8 | EDGE9 | EDGE10, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 156
|
||||
{EDGE0 | EDGE2 | EDGE6 | EDGE7 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 157
|
||||
{EDGE0 | EDGE1 | EDGE6 | EDGE7 | EDGE8 | EDGE10, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 158
|
||||
{EDGE1 | EDGE2 | EDGE6 | EDGE7 | EDGE10 | EDGE11, 0, 0, 0}, // 159
|
||||
{EDGE1 | EDGE2 | EDGE5 | EDGE6, 0, 0, 0}, // 160
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE1 | EDGE2 | EDGE5 | EDGE6, 0, 0}, // 161
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE6 | EDGE9, 0, 0, 0}, // 162
|
||||
{EDGE2 | EDGE3 | EDGE5 | EDGE6 | EDGE8 | EDGE9, 0, 0, 0}, // 163
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE1 | EDGE2 | EDGE5 | EDGE6, 0, 0}, // 164
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE7, EDGE1 | EDGE2 | EDGE5 | EDGE6, 0, 0}, // 165
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE6 | EDGE9, EDGE4 | EDGE7 | EDGE8, 0, 0}, // 166
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE5 | EDGE6 | EDGE7 | EDGE9, 0, 0, 0}, // 167
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE6 | EDGE9, 0, 0, 0}, // 168
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE1 | EDGE2 | EDGE4 | EDGE6 | EDGE9, 0, 0}, // 169
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE6, 0, 0, 0}, // 170
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE6 | EDGE8, 0, 0, 0}, // 171
|
||||
{EDGE1 | EDGE2 | EDGE6 | EDGE7 | EDGE8 | EDGE9, 0, 0, 0}, // 172
|
||||
{EDGE0 | EDGE1 | EDGE2 | EDGE3 | EDGE6 | EDGE7 | EDGE9, 0, 0, 0}, // 173
|
||||
{EDGE0 | EDGE2 | EDGE6 | EDGE7 | EDGE8, 0, 0, 0}, // 174
|
||||
{EDGE2 | EDGE3 | EDGE6 | EDGE7, 0, 0, 0}, // 175
|
||||
{EDGE1 | EDGE3 | EDGE5 | EDGE6 | EDGE11, 0, 0, 0}, // 176
|
||||
{EDGE0 | EDGE1 | EDGE5 | EDGE6 | EDGE8 | EDGE11, 0, 0, 0}, // 177
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE6 | EDGE9 | EDGE11, 0, 0, 0}, // 178
|
||||
{EDGE5 | EDGE6 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 179
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE1 | EDGE3 | EDGE5 | EDGE6 | EDGE11, 0, 0}, // 180
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE5 | EDGE6 | EDGE7 | EDGE11, 0, 0, 0}, // 181
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE6 | EDGE9 | EDGE11, EDGE4 | EDGE7 | EDGE8, 0, 0}, // 182
|
||||
{EDGE4 | EDGE5 | EDGE6 | EDGE7 | EDGE9 | EDGE11, 0, 0, 0}, // 183
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE6 | EDGE9 | EDGE11, 0, 0, 0}, // 184
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE6 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 185
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE6 | EDGE11, 0, 0, 0}, // 186
|
||||
{EDGE4 | EDGE6 | EDGE8 | EDGE11, 0, 0, 0}, // 187
|
||||
{EDGE1 | EDGE3 | EDGE6 | EDGE7 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 188
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE6 | EDGE7 | EDGE11, 0, 0}, // 189
|
||||
{EDGE0 | EDGE3 | EDGE6 | EDGE7 | EDGE8 | EDGE11, 0, 0, 0}, // 190
|
||||
{EDGE6 | EDGE7 | EDGE11, 0, 0, 0}, // 191
|
||||
{EDGE5 | EDGE7 | EDGE10 | EDGE11, 0, 0, 0}, // 192
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE5 | EDGE7 | EDGE10 | EDGE11, 0, 0}, // 193
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE5 | EDGE7 | EDGE10 | EDGE11, 0, 0}, // 194
|
||||
{EDGE1 | EDGE3 | EDGE8 | EDGE9, EDGE5 | EDGE7 | EDGE10 | EDGE11, 0, 0}, // 195
|
||||
{EDGE4 | EDGE5 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 196
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE5 | EDGE10 | EDGE11, 0, 0, 0}, // 197
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE4 | EDGE5 | EDGE8 | EDGE10 | EDGE11, 0, 0}, // 198
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE5 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 199
|
||||
{EDGE4 | EDGE7 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 200
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE4 | EDGE7 | EDGE9 | EDGE10 | EDGE11, 0, 0}, // 201
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE7 | EDGE10 | EDGE11, 0, 0, 0}, // 202
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE7 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 203
|
||||
{EDGE8 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 204
|
||||
{EDGE0 | EDGE3 | EDGE9 | EDGE10 | EDGE11, 0, 0, 0}, // 205
|
||||
{EDGE0 | EDGE1 | EDGE8 | EDGE10 | EDGE11, 0, 0, 0}, // 206
|
||||
{EDGE1 | EDGE3 | EDGE10 | EDGE11, 0, 0, 0}, // 207
|
||||
{EDGE2 | EDGE3 | EDGE5 | EDGE7 | EDGE10, 0, 0, 0}, // 208
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE7 | EDGE8 | EDGE10, 0, 0, 0}, // 209
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE2 | EDGE3 | EDGE5 | EDGE7 | EDGE10, 0, 0}, // 210
|
||||
{EDGE1 | EDGE2 | EDGE5 | EDGE7 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 211
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE5 | EDGE8 | EDGE10, 0, 0, 0}, // 212
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE5 | EDGE10, 0, 0, 0}, // 213
|
||||
{EDGE0 | EDGE1 | EDGE9, EDGE2 | EDGE3 | EDGE4 | EDGE5 | EDGE8 | EDGE10, 0, 0}, // 214
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE5 | EDGE9 | EDGE10, 0, 0, 0}, // 215
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE7 | EDGE9 | EDGE10, 0, 0, 0}, // 216
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE7 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 217
|
||||
{EDGE0 | EDGE1 | EDGE2 | EDGE3 | EDGE4 | EDGE7 | EDGE10, 0, 0, 0}, // 218
|
||||
{EDGE4 | EDGE7 | EDGE8, EDGE1 | EDGE2 | EDGE10, 0, 0}, // 219
|
||||
{EDGE2 | EDGE3 | EDGE8 | EDGE9 | EDGE10, 0, 0, 0}, // 220
|
||||
{EDGE0 | EDGE2 | EDGE9 | EDGE10, 0, 0, 0}, // 221
|
||||
{EDGE0 | EDGE1 | EDGE2 | EDGE3 | EDGE8 | EDGE10, 0, 0, 0}, // 222
|
||||
{EDGE1 | EDGE2 | EDGE10, 0, 0, 0}, // 223
|
||||
{EDGE1 | EDGE2 | EDGE5 | EDGE7 | EDGE11, 0, 0, 0}, // 224
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE1 | EDGE2 | EDGE5 | EDGE7 | EDGE11, 0, 0}, // 225
|
||||
{EDGE0 | EDGE2 | EDGE5 | EDGE7 | EDGE9 | EDGE11, 0, 0, 0}, // 226
|
||||
{EDGE2 | EDGE3 | EDGE5 | EDGE7 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 227
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE5 | EDGE8 | EDGE11, 0, 0, 0}, // 228
|
||||
{EDGE0 | EDGE1 | EDGE2 | EDGE3 | EDGE4 | EDGE5 | EDGE11, 0, 0, 0}, // 229
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE5 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 230
|
||||
{EDGE4 | EDGE5 | EDGE9, EDGE2 | EDGE3 | EDGE11, 0, 0}, // 231
|
||||
{EDGE1 | EDGE2 | EDGE4 | EDGE7 | EDGE9 | EDGE11, 0, 0, 0}, // 232
|
||||
{EDGE0 | EDGE3 | EDGE8, EDGE1 | EDGE2 | EDGE4 | EDGE7 | EDGE9 | EDGE11, 0, 0}, // 233
|
||||
{EDGE0 | EDGE2 | EDGE4 | EDGE7 | EDGE11, 0, 0, 0}, // 234
|
||||
{EDGE2 | EDGE3 | EDGE4 | EDGE7 | EDGE8 | EDGE11, 0, 0, 0}, // 235
|
||||
{EDGE1 | EDGE2 | EDGE8 | EDGE9 | EDGE11, 0, 0, 0}, // 236
|
||||
{EDGE0 | EDGE1 | EDGE2 | EDGE3 | EDGE9 | EDGE11, 0, 0, 0}, // 237
|
||||
{EDGE0 | EDGE2 | EDGE8 | EDGE11, 0, 0, 0}, // 238
|
||||
{EDGE2 | EDGE3 | EDGE11, 0, 0, 0}, // 239
|
||||
{EDGE1 | EDGE3 | EDGE5 | EDGE7, 0, 0, 0}, // 240
|
||||
{EDGE0 | EDGE1 | EDGE5 | EDGE7 | EDGE8, 0, 0, 0}, // 241
|
||||
{EDGE0 | EDGE3 | EDGE5 | EDGE7 | EDGE9, 0, 0, 0}, // 242
|
||||
{EDGE5 | EDGE7 | EDGE8 | EDGE9, 0, 0, 0}, // 243
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE5 | EDGE8, 0, 0, 0}, // 244
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE5, 0, 0, 0}, // 245
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE5 | EDGE8 | EDGE9, 0, 0, 0}, // 246
|
||||
{EDGE4 | EDGE5 | EDGE9, 0, 0, 0}, // 247
|
||||
{EDGE1 | EDGE3 | EDGE4 | EDGE7 | EDGE9, 0, 0, 0}, // 248
|
||||
{EDGE0 | EDGE1 | EDGE4 | EDGE7 | EDGE8 | EDGE9, 0, 0, 0}, // 249
|
||||
{EDGE0 | EDGE3 | EDGE4 | EDGE7, 0, 0, 0}, // 250
|
||||
{EDGE4 | EDGE7 | EDGE8, 0, 0, 0}, // 251
|
||||
{EDGE1 | EDGE3 | EDGE8 | EDGE9, 0, 0, 0}, // 252
|
||||
{EDGE0 | EDGE1 | EDGE9, 0, 0, 0}, // 253
|
||||
{EDGE0 | EDGE3 | EDGE8, 0, 0, 0}, // 254
|
||||
{0, 0, 0, 0} // 255
|
||||
};
|
||||
|
||||
/// Encodes the ambiguous face of cube configurations, which
|
||||
/// can cause non-manifold meshes.
|
||||
/// Non-problematic configurations have a value of 255.
|
||||
/// The first bit of each value actually encodes a positive or negative
|
||||
/// direction while the second and third bit enumerate the axis.
|
||||
template<class T>
|
||||
uint8_t const DualMC<T>::problematicConfigs[256] = {
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,1,0,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,3,255,255,2,255,
|
||||
255,255,255,255,255,255,255,5,255,255,255,255,255,255,5,5,
|
||||
255,255,255,255,255,255,4,255,255,255,3,3,1,1,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,5,255,5,255,5,
|
||||
255,255,255,255,255,255,255,3,255,255,255,255,255,2,255,255,
|
||||
255,255,255,255,255,3,255,3,255,4,255,255,0,255,0,255,
|
||||
255,255,255,255,255,255,255,1,255,255,255,0,255,255,255,255,
|
||||
255,255,255,1,255,255,255,1,255,4,2,255,255,255,2,255,
|
||||
255,255,255,0,255,2,4,255,255,255,255,0,255,2,255,255,
|
||||
255,255,255,255,255,255,4,255,255,4,255,255,255,255,255,255
|
||||
};
|
||||
|
||||
|
||||
} // END: namespace dualmc
|
||||
#endif // DUALMC_H_INCLUDED
|
|
@ -1,6 +1,7 @@
|
|||
#include "index.hpp"
|
||||
#include "Dummy.hpp"
|
||||
#include "FlatSurroundingBox.hpp"
|
||||
#include "FlatDualMC.hpp"
|
||||
|
||||
namespace contouring {
|
||||
int idxByName(const std::string& name) {
|
||||
|
@ -13,11 +14,14 @@ namespace contouring {
|
|||
|
||||
std::shared_ptr<Abstract> load(int idx, const std::map<std::string, std::string>& data) {
|
||||
switch (idx) {
|
||||
case 1:
|
||||
case 2:
|
||||
return std::make_shared<Dummy>();
|
||||
|
||||
case 1:
|
||||
return std::make_shared<FlatSurroundingBox>(data.at(names[1]));
|
||||
|
||||
default:
|
||||
return std::make_shared<FlatSurroundingBox>(data.at(names[0]));
|
||||
return std::make_shared<FlatDualMC>(data.at(names[0]));
|
||||
}
|
||||
}
|
||||
void save(int idx, std::shared_ptr<Abstract>& ct, std::map<std::string, std::string>& data) {
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include "Abstract.hpp"
|
||||
|
||||
namespace contouring {
|
||||
static const std::array<std::string, 2> names = {"FlatBox", "Dummy"};
|
||||
static const std::string cnames = "FlatBox\0Dummy\0";
|
||||
static const std::array<std::string, 3> names = {"FlatDualMC", "FlatBox", "Dummy"};
|
||||
static const char* cnames = "FlatDualMC\0FlatBox\0Dummy\0";
|
||||
|
||||
int idxByName(const std::string &name);
|
||||
std::shared_ptr<Abstract> load(int idx, const std::map<std::string, std::string> &data);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "../world/Chunk.hpp"
|
||||
|
||||
namespace contouring::surrounding {
|
||||
bool load(chunks &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks) {
|
||||
bool load(faces &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks) {
|
||||
{
|
||||
const auto it = chunks.find(chunkPos);
|
||||
if (it == chunks.end())
|
||||
|
@ -57,4 +57,15 @@ namespace contouring::surrounding {
|
|||
return {CENTER, idx};
|
||||
}
|
||||
}
|
||||
|
||||
bool load(corners &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks) {
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
const auto it = chunks.find(chunkPos + g_corner_offsets[i]);
|
||||
if (it == chunks.end())
|
||||
return false;
|
||||
|
||||
out[i] = it->second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,23 @@
|
|||
class Chunk;
|
||||
namespace contouring::surrounding {
|
||||
const auto CENTER = 6;
|
||||
typedef std::array<std::shared_ptr<const Chunk>, CENTER+1> chunks;
|
||||
typedef std::array<std::shared_ptr<const Chunk>, CENTER+1> faces;
|
||||
|
||||
bool load(chunks &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks);
|
||||
bool load(faces &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks);
|
||||
|
||||
std::pair<ushort, ushort> getNeighborIdx(ushort idx, Face face);
|
||||
|
||||
typedef std::array<std::shared_ptr<const Chunk>, 8> corners;
|
||||
const glm::ivec3 g_corner_offsets[8] = {
|
||||
glm::ivec3(0, 0, 0),
|
||||
glm::ivec3(0, 0, 1),
|
||||
glm::ivec3(0, 1, 0),
|
||||
glm::ivec3(0, 1, 1),
|
||||
glm::ivec3(1, 0, 0),
|
||||
glm::ivec3(1, 0, 1),
|
||||
glm::ivec3(1, 1, 0),
|
||||
glm::ivec3(1, 1, 1),
|
||||
};
|
||||
|
||||
bool load(corners &out, const chunk_pos &chunkPos, const robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> &chunks);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ struct options {
|
|||
renderer.mipMapLOD = config["render"]["texture_quality"].value_or(renderer.mipMapLOD);
|
||||
renderer.main.pbr = config["render"]["pbr"].value_or(renderer.main.pbr);
|
||||
renderer.main.triplanar = config["render"]["triplanar"].value_or(renderer.main.triplanar);
|
||||
renderer.main.blend = config["render"]["blend"].value_or(renderer.main.blend);
|
||||
renderer.main.fog = config["render"]["fog"].value_or(renderer.main.fog);
|
||||
const std::string fog = config["render"]["fog_color"].value_or(std::string{"#000000"});
|
||||
renderer.clear_color = fromHex(fog);
|
||||
|
@ -83,6 +84,7 @@ struct options {
|
|||
{"texture_quality", renderer.mipMapLOD},
|
||||
{"pbr", renderer.main.pbr},
|
||||
{"triplanar", renderer.main.triplanar},
|
||||
{"blend", renderer.main.blend},
|
||||
{"fog", renderer.main.fog},
|
||||
{"fog_color", toHexa(renderer.clear_color)},
|
||||
{"skybox", renderer.skybox}
|
||||
|
|
|
@ -128,11 +128,11 @@ int main(int, char *[]){
|
|||
pass.start();
|
||||
|
||||
std::vector<std::pair<glm::mat4, Buffer *const>> models;
|
||||
std::optional<Frustum> furstum;
|
||||
std::optional<Frustum> frustum;
|
||||
if(options.culling) {
|
||||
furstum = {camera.getFrustum()};
|
||||
frustum = {camera.getFrustum()};
|
||||
}
|
||||
world.getContouring()->getModels(models, camera.getFrustum(), options.voxel_size);
|
||||
world.getContouring()->getModels(models, frustum, options.voxel_size);
|
||||
reports.main.models_count = 0;
|
||||
reports.main.tris_count = 0;
|
||||
rmt_ScopedOpenGLSample(Render);
|
||||
|
|
|
@ -67,15 +67,14 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
if (ImGui::Checkbox("Fullscreen", &options.fullscreen)){
|
||||
actions = actions | Actions::FullScreen;
|
||||
}
|
||||
if (ImGui::ColorEdit3("Fog color", (float *)&options.renderer.clear_color)) {
|
||||
actions = actions | Actions::ClearColor;
|
||||
}
|
||||
|
||||
{
|
||||
bool changeRenderer = false;
|
||||
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.main.pbr);
|
||||
ImGui::SameLine();
|
||||
changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.main.triplanar);
|
||||
ImGui::SameLine();
|
||||
changeRenderer |= ImGui::Checkbox("Blend", &options.renderer.main.blend);
|
||||
|
||||
changeRenderer |= ImGui::Checkbox("Fog", &options.renderer.main.fog);
|
||||
ImGui::SameLine();
|
||||
|
@ -84,6 +83,9 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
actions = actions | Actions::RendererSharders;
|
||||
}
|
||||
}
|
||||
if (ImGui::ColorEdit3("Fog color", (float *)&options.renderer.clear_color)) {
|
||||
actions = actions | Actions::ClearColor;
|
||||
}
|
||||
if (ImGui::Checkbox("Wireframe", &options.renderer.wireframe))
|
||||
glPolygonMode(GL_FRONT_AND_BACK, options.renderer.wireframe ? GL_LINE : GL_FILL);
|
||||
ImGui::Text("Textures '%s'", options.renderer.textures.c_str()); // MAYBE: select
|
||||
|
@ -115,7 +117,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
if (options.show_debug_contouring) {
|
||||
ImGui::Begin("Debug: Contouring", &options.show_debug_contouring, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
const auto prev_idx = options.contouring_idx;
|
||||
if(ImGui::Combo("Contouring", &options.contouring_idx, contouring::cnames.c_str())) {
|
||||
if(ImGui::Combo("Contouring", &options.contouring_idx, contouring::cnames)) {
|
||||
actions = actions | Actions::ChangeContouring;
|
||||
contouring::save(prev_idx, state.contouring, options.contouring_data);
|
||||
}
|
||||
|
|
|
@ -11,10 +11,14 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
|
|||
flags.push_back("TRIPLANAR");
|
||||
if (opts.fog)
|
||||
flags.push_back("FOG");
|
||||
if (opts.blend)
|
||||
flags.push_back("BLEND");
|
||||
|
||||
std::vector<Shader*> shaders;
|
||||
shaders.push_back(loadShader(GL_VERTEX_SHADER, flags));
|
||||
shaders.push_back(loadShader(GL_FRAGMENT_SHADER, flags));
|
||||
if (opts.blend)
|
||||
shaders.push_back(loadShader(GL_GEOMETRY_SHADER, flags));
|
||||
load(shaders);
|
||||
|
||||
MVPMatrixID = glGetUniformLocation(ProgramID, "MVP");
|
||||
|
|
|
@ -8,7 +8,7 @@ public:
|
|||
struct options {
|
||||
bool pbr = true;
|
||||
bool triplanar = false;
|
||||
//TODO: bool blend = false;
|
||||
bool blend = true;
|
||||
bool fog = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "Voxel.hpp"
|
||||
#include "../data/geometry/Faces.hpp"
|
||||
|
||||
#define CHUNK_LENGTH 16
|
||||
#define CHUNK_LENGTH 32
|
||||
#define CHUNK_LENGTH2 (CHUNK_LENGTH * CHUNK_LENGTH)
|
||||
#define CHUNK_SIZE (CHUNK_LENGTH2 * CHUNK_LENGTH)
|
||||
|
||||
|
@ -18,7 +18,6 @@ public:
|
|||
/// @return true if modified
|
||||
bool update();
|
||||
|
||||
//TODO: get, set
|
||||
const Voxel* begin() const {
|
||||
return voxels.begin();
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ void World::update(const camera_pos& pos, World::report& rep) {
|
|||
// Unload dead chunks
|
||||
{
|
||||
rmt_ScopedCPUSample(Unload, 0);
|
||||
for (size_t i = 0; i < 32 && !unloadQueue.empty(); i++) {
|
||||
for (size_t i = 0; i < 256 && !unloadQueue.empty(); i++) {
|
||||
chunks.erase(unloadQueue.pop());
|
||||
//TODO: save to file
|
||||
}
|
||||
|
|
|
@ -6,4 +6,5 @@
|
|||
namespace materials {
|
||||
static const auto count = 9;
|
||||
static const std::array<std::string, count> textures = {{"Air", "Sand", "Dirt", "Stone_path", "Mapl", "Seaside_rock", "Stone_wall", "Rough_rock", "Alien"}};
|
||||
static const std::array<float, count> roughness = {{0, 0, 0, 0, 0, 0, 0, -1, .8}};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue