initial commit
This commit is contained in:
commit
dcab466330
37
CMakeLists.txt
Normal file
37
CMakeLists.txt
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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/")
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wall ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
FIND_PACKAGE(OpenMesh REQUIRED)
|
||||||
|
link_directories(${OPENMESH_LIBRARY_DIR})
|
||||||
|
include_directories(${OPENMESH_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/vendor)
|
||||||
|
|
||||||
|
# add executable
|
||||||
|
add_executable(asteroidgen
|
||||||
|
src/main.cpp
|
||||||
|
src/gen.cpp
|
||||||
|
vendor/mersenne-twister.cpp
|
||||||
|
vendor/OpenNL_psm.c
|
||||||
|
vendor/glad.c
|
||||||
|
vendor/logger.cpp
|
||||||
|
vendor/imgui.cpp
|
||||||
|
vendor/imgui_draw.cpp
|
||||||
|
vendor/imgui_impl_glfw_gl3.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(asteroidgen ${OPENMESH_LIBRARIES} dl glfw)
|
||||||
|
|
||||||
|
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()
|
15
src/AsteroidGenerator.h
Normal file
15
src/AsteroidGenerator.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* AsteroidGenerator.h
|
||||||
|
*
|
||||||
|
* Created on: 24.10.2017
|
||||||
|
* Author: gmueller
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_ASTEROIDGENERATOR_H_
|
||||||
|
#define SRC_ASTEROIDGENERATOR_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SRC_ASTEROIDGENERATOR_H_ */
|
126
src/Density.h
Normal file
126
src/Density.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// system
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// external
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
#include <glm/gtc/random.hpp>
|
||||||
|
|
||||||
|
// vendor
|
||||||
|
#include <RTree.h>
|
||||||
|
#include <PerlinNoise.hpp>
|
||||||
|
#include <stb_image_write.h>
|
||||||
|
|
||||||
|
struct Impact {
|
||||||
|
glm::vec3 pos;
|
||||||
|
float r;
|
||||||
|
bool contains(const glm::vec3 &p) const {
|
||||||
|
return (glm::length(pos - p) < r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Density {
|
||||||
|
std::vector<Impact> impacts;
|
||||||
|
RTree<int, float, 3, float> impactTree;
|
||||||
|
siv::PerlinNoise noise;
|
||||||
|
glm::vec3 scale;
|
||||||
|
float scaleFactor;
|
||||||
|
float frequency, octave;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Density() :
|
||||||
|
scale(1), scaleFactor(4), frequency(2), octave(2) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void addImpact(Impact &impact) {
|
||||||
|
size_t idx = impacts.size();
|
||||||
|
impacts.push_back(impact);
|
||||||
|
glm::vec3 l = impact.pos - glm::vec3(impact.r);
|
||||||
|
glm::vec3 u = impact.pos + glm::vec3(impact.r);
|
||||||
|
impactTree.Insert(&l.x, &u.x, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSeed(uint32_t seed) {
|
||||||
|
noise.reseed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setScale(const glm::vec3 &scale) {
|
||||||
|
this->scale = scale;
|
||||||
|
scaleFactor = 4.f / std::min(scale.x, std::min(scale.y, scale.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFrequency(float f) {
|
||||||
|
frequency = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOctave(float o) {
|
||||||
|
octave = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
float operator()(const glm::vec3 &p) const {
|
||||||
|
if (impacts.size()) {
|
||||||
|
bool insideImpact = false;
|
||||||
|
impactTree.Search(&p.x, &p.x, [&](int idx) -> bool {
|
||||||
|
if (impacts[idx].contains(p)) {
|
||||||
|
insideImpact = true;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (insideImpact)
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
float v = (float) noise.octaveNoise0_1(p.x * frequency, p.y * frequency,
|
||||||
|
p.z * frequency, octave);
|
||||||
|
glm::vec3 r = p - glm::vec3(0.5);
|
||||||
|
v *= std::max(1.f - scaleFactor * dot(scale * r, r), 0.f);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersectIsolevel(const glm::vec3 &start, const glm::vec3 &end,
|
||||||
|
glm::vec3 &pos, float isolevel, float resolution) {
|
||||||
|
glm::vec3 step = glm::normalize(end - start) * glm::vec3(resolution);
|
||||||
|
size_t nSteps = ceil(glm::length(end - start) / resolution);
|
||||||
|
pos = start;
|
||||||
|
for (size_t iStep = 0; iStep < nSteps; iStep++) {
|
||||||
|
if ((*this)(pos) > isolevel)
|
||||||
|
return true;
|
||||||
|
pos += step;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addRandomImpacts(size_t count, float isolevel, float resolution,
|
||||||
|
float minRadius, float maxRadius, int exponent) {
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
glm::vec3 start = glm::vec3(0.5f) + glm::sphericalRand(0.6f);
|
||||||
|
glm::vec3 end = glm::vec3(0.5f) + glm::sphericalRand(0.6f);
|
||||||
|
Impact impact;
|
||||||
|
if (intersectIsolevel(start, end, impact.pos, isolevel,
|
||||||
|
resolution)) {
|
||||||
|
impact.r = minRadius
|
||||||
|
+ pow(glm::linearRand(0.f, 1.f), exponent) * maxRadius;
|
||||||
|
addImpact(impact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveCrossSection(const char *filename, size_t pixels) {
|
||||||
|
float step = 1.f / pixels;
|
||||||
|
glm::vec3 pos(step / 2, step / 2, 0.5f);
|
||||||
|
std::vector<uint8_t> img(pixels * pixels);
|
||||||
|
for (size_t ix = 0; ix < pixels; ix++) {
|
||||||
|
for (size_t iy = 0; iy < pixels; iy++) {
|
||||||
|
glm::vec3 pos(step * (0.5f + ix), step * (0.5f + iy), 0.5f);
|
||||||
|
img[iy * pixels + ix] = (*this)(pos) * 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stbi_write_png(filename, pixels, pixels, 1, img.data(), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
117
src/Polygoniser.h
Normal file
117
src/Polygoniser.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
#include <glm/gtc/epsilon.hpp>
|
||||||
|
|
||||||
|
#include <MarchingCube.h>
|
||||||
|
#include <logger.h>
|
||||||
|
|
||||||
|
#include "Density.h"
|
||||||
|
|
||||||
|
struct CompareVec3 {
|
||||||
|
bool operator()(const glm::vec3 &lhs, const glm::vec3 &rhs) {
|
||||||
|
static const float epsilon = 1e-5;
|
||||||
|
if (lhs.x < rhs.x - epsilon)
|
||||||
|
return true;
|
||||||
|
else if (lhs.x > rhs.x + epsilon)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
if (lhs.y < rhs.y - epsilon)
|
||||||
|
return true;
|
||||||
|
else if (lhs.y > rhs.y + epsilon)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
if (lhs.z < rhs.z - epsilon)
|
||||||
|
return true;
|
||||||
|
else if (lhs.z > rhs.z + epsilon)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Polygonizer {
|
||||||
|
public:
|
||||||
|
std::vector<glm::vec3> vertices;
|
||||||
|
std::vector<glm::uvec3> triangles;
|
||||||
|
|
||||||
|
Density &density;
|
||||||
|
|
||||||
|
Polygonizer(Density &density) :
|
||||||
|
density(density) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void polygonize(float isolevel, float resolution) {
|
||||||
|
vertices.clear();
|
||||||
|
triangles.clear();
|
||||||
|
|
||||||
|
std::map<glm::vec3, int, CompareVec3> vertexLookup;
|
||||||
|
|
||||||
|
size_t nSteps = 1.f / resolution - 1;
|
||||||
|
size_t nT = 0;
|
||||||
|
for (size_t ix = 0; ix < nSteps; ix++) {
|
||||||
|
double x = (double(ix) + 0.5) * resolution;
|
||||||
|
for (size_t iy = 0; iy < nSteps; iy++) {
|
||||||
|
double y = (double(iy) + 0.5) * resolution;
|
||||||
|
for (size_t iz = 0; iz < nSteps; iz++) {
|
||||||
|
double z = (double(iz) + 0.5) * resolution;
|
||||||
|
|
||||||
|
GRIDCELL gridCell;
|
||||||
|
gridCell.p[0] = vec3(x, y, z);
|
||||||
|
gridCell.p[1] = vec3(x + resolution, y, z);
|
||||||
|
gridCell.p[2] = vec3(x + resolution, y + resolution, z);
|
||||||
|
gridCell.p[3] = vec3(x, y + resolution, z);
|
||||||
|
gridCell.p[4] = vec3(x, y, z + resolution);
|
||||||
|
gridCell.p[5] = vec3(x + resolution, y, z + resolution);
|
||||||
|
gridCell.p[6] = vec3(x + resolution, y + resolution,
|
||||||
|
z + resolution);
|
||||||
|
gridCell.p[7] = vec3(x, y + resolution, z + resolution);
|
||||||
|
|
||||||
|
for (size_t iCell = 0; iCell < 8; iCell++) {
|
||||||
|
gridCell.val[iCell] = density(gridCell.p[iCell]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRIANGLE tris[6];
|
||||||
|
int nTris = Polygonise(gridCell, isolevel, tris);
|
||||||
|
nT += nTris;
|
||||||
|
for (int iTri = 0; iTri < nTris; iTri++) {
|
||||||
|
vec3 *ps = tris[iTri].p;
|
||||||
|
|
||||||
|
// skip degenerate vertices
|
||||||
|
if (all(epsilonEqual(ps[0], ps[1], 1e-8f))
|
||||||
|
|| all(epsilonEqual(ps[0], ps[2], 1e-8f))
|
||||||
|
|| all(epsilonEqual(ps[2], ps[1], 1e-8f)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
glm::uvec3 idc;
|
||||||
|
for (size_t k = 0; k < 3; k++) {
|
||||||
|
glm::vec3 &p = tris[iTri].p[k];
|
||||||
|
std::map<glm::vec3, int>::iterator vit =
|
||||||
|
vertexLookup.find(p);
|
||||||
|
if (vit != vertexLookup.end()) {
|
||||||
|
idc[k] = vit->second;
|
||||||
|
} else {
|
||||||
|
idc[k] = vertices.size();
|
||||||
|
vertices.push_back(p);
|
||||||
|
vertexLookup[p] = idc[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
triangles.push_back(idc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
201
src/TextureMapper.h
Normal file
201
src/TextureMapper.h
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#ifndef SRC_TEXTUREMAPPER_H_
|
||||||
|
#define SRC_TEXTUREMAPPER_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
|
class TextureMapper {
|
||||||
|
public:
|
||||||
|
typedef std::vector<glm::uint8[3]> texture3_t;
|
||||||
|
typedef std::vector<uint8_t> texture1_t;
|
||||||
|
texture3_t diffuse;
|
||||||
|
texture3_t normal;
|
||||||
|
texture1_t roughness;
|
||||||
|
size_t textureSize;
|
||||||
|
|
||||||
|
TextureMapper(size_t textureSize) :
|
||||||
|
textureSize(textureSize), diffuse(textureSize * textureSize), normal(
|
||||||
|
textureSize * textureSize), roughness(
|
||||||
|
textureSize * textureSize) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void map() {
|
||||||
|
cout << "Stage4: UV map" << endl;
|
||||||
|
TriMesh mappedMesh;
|
||||||
|
float texf = 1. / texture_size;
|
||||||
|
|
||||||
|
mesh.request_vertex_normals();
|
||||||
|
mesh.request_face_normals();
|
||||||
|
mesh.update_face_normals();
|
||||||
|
mesh.update_vertex_normals();
|
||||||
|
int rects = ceil(sqrt(mesh.n_faces())), rx = 0, ry = 0;
|
||||||
|
float rectSize = floor(float(texture_size) / rects) / texture_size;
|
||||||
|
size_t nfaces = mesh.n_faces(), iface = 0;
|
||||||
|
for (auto i = mesh.faces_begin(); i != mesh.faces_end(); i++) {
|
||||||
|
if (show_progress)
|
||||||
|
(cout << "\r " << int(100. * float(iface++) / nfaces) << "%").flush();
|
||||||
|
|
||||||
|
vec3 p[3], n[3];
|
||||||
|
int k = 0;
|
||||||
|
TriMesh::VertexHandle h[3];
|
||||||
|
for (auto j = mesh.fv_begin(*i); j != mesh.fv_end(*i); j++) {
|
||||||
|
if (!j->is_valid())
|
||||||
|
cout << "invalid vertex" << endl;
|
||||||
|
TriMesh::Point pt = mesh.point(*j);
|
||||||
|
p[k] = vec3(pt[0], pt[1], pt[2]);
|
||||||
|
TriMesh::Normal nm = mesh.calc_vertex_normal(*j);
|
||||||
|
n[k] = vec3(nm[0], nm[1], nm[2]);
|
||||||
|
h[k] = mappedMesh.add_vertex(pt);
|
||||||
|
mappedMesh.set_normal(h[k], nm);
|
||||||
|
k++;
|
||||||
|
if (k > 3)
|
||||||
|
cout << "not a triangle!" << endl;
|
||||||
|
}
|
||||||
|
mappedMesh.add_face(h, 3);
|
||||||
|
|
||||||
|
vec3 ex = normalize(p[1] - p[0]);
|
||||||
|
vec3 ey = normalize(cross(ex, p[2] - p[0]));
|
||||||
|
vec3 ez = normalize(cross(ex, ey));
|
||||||
|
mat3 base = mat3(ex, ey, ez);
|
||||||
|
vec3 t[3] = { p[0] * base, p[1] * base, p[2] * base };
|
||||||
|
vec3 lower = min(min(t[0], t[1]), t[2]);
|
||||||
|
vec3 upper = max(max(t[0], t[1]), t[2]);
|
||||||
|
t[0] -= lower;
|
||||||
|
t[1] -= lower;
|
||||||
|
t[2] -= lower;
|
||||||
|
vec3 extent = upper - lower;
|
||||||
|
float s = std::max(std::max(extent.x, extent.y), extent.z);
|
||||||
|
t[0] *= 0.8 * rectSize / s;
|
||||||
|
t[1] *= 0.8 * rectSize / s;
|
||||||
|
t[2] *= 0.8 * rectSize / s;
|
||||||
|
vec3 off(rx * rectSize, 0, ry * rectSize);
|
||||||
|
t[0] += off;
|
||||||
|
t[1] += off;
|
||||||
|
t[2] += off;
|
||||||
|
mappedMesh.set_texcoord2D(h[0],
|
||||||
|
TriMesh::TexCoord2D(t[0].x, t[0].z));
|
||||||
|
mappedMesh.set_texcoord2D(h[1],
|
||||||
|
TriMesh::TexCoord2D(t[1].x, t[1].z));
|
||||||
|
mappedMesh.set_texcoord2D(h[2],
|
||||||
|
TriMesh::TexCoord2D(t[2].x, t[2].z));
|
||||||
|
|
||||||
|
//if (rx == 0 && ry == 0) {
|
||||||
|
t[0].y = 0;
|
||||||
|
t[1].y = 0;
|
||||||
|
t[2].y = 0;
|
||||||
|
// cout << "ftex " << texf << endl;
|
||||||
|
// cout << "t[0] " << t[0].x << " " << t[0].z << endl;
|
||||||
|
// cout << "t[1] " << t[1].x << " " << t[1].z << endl;
|
||||||
|
// cout << "t[2] " << t[2].x << " " << t[2].z << endl;
|
||||||
|
// cout << "t[0]p " << t[0].x * ntex << " " << (1 - t[0].z) * ntex << endl;
|
||||||
|
// cout << "t[1]p " << t[1].x * ntex << " " << (1 - t[1].z) * ntex << endl;
|
||||||
|
// cout << "t[2]p " << t[2].x * ntex << " " << (1 - t[2].z) * ntex << endl;
|
||||||
|
// fill texture
|
||||||
|
// fill whole rect for now
|
||||||
|
int rpix = floor(rectSize * texture_size);
|
||||||
|
|
||||||
|
vec3 eb = t[1] - t[0];
|
||||||
|
float leb = length(eb);
|
||||||
|
vec3 ec = t[2] - t[0];
|
||||||
|
float lec = length(ec);
|
||||||
|
// mat2 textureBase = mat2(vec2(eb.x, eb.z), vec2(ec.x, ec.z));
|
||||||
|
// mat2 itextureBase = inverse(textureBase);
|
||||||
|
mat3 textureBase = mat3(eb, cross(eb, ec), ec);
|
||||||
|
mat3 itextureBase = inverse(textureBase);
|
||||||
|
|
||||||
|
// eb = normalize(eb);
|
||||||
|
// ec = normalize(ec);
|
||||||
|
|
||||||
|
vec3 db = p[1] - p[0];
|
||||||
|
vec3 dc = p[2] - p[0];
|
||||||
|
|
||||||
|
vec3 mb = normalize(p[1] - p[0]);
|
||||||
|
vec3 mc = normalize(p[2] - p[0]);
|
||||||
|
// mat2 faceBase = mat2(vec2(mb.x, mb.z), vec2(mc.x, mc.z));
|
||||||
|
// mat2 ifaceBase = inverse(faceBase);
|
||||||
|
|
||||||
|
mat3 faceBase = mat3(db, cross(db, dc), dc);
|
||||||
|
mat3 ifaceBase = inverse(faceBase);
|
||||||
|
|
||||||
|
// mat2 trafo = ifaceBase * textureBase * faceBase;
|
||||||
|
|
||||||
|
for (int ix = rx * rpix; ix < (rx + 1) * rpix; ix++) {
|
||||||
|
for (int iy = (texture_size - (ry + 1) * rpix);
|
||||||
|
iy < (texture_size - ry * rpix); iy++) {
|
||||||
|
|
||||||
|
// cout << "pix " << ix << " " << iy << endl;
|
||||||
|
// cout << "uv " << float(ix) * texf << " " << 1.f - float(iy) * texf << endl;
|
||||||
|
|
||||||
|
// pixel to uv space
|
||||||
|
vec3 res = vec3(float(ix) * texf, 0.f,
|
||||||
|
1.f - float(iy) * texf) - t[0];
|
||||||
|
// cout << "r = " << r.x << " " << r.y << endl;
|
||||||
|
res = faceBase * itextureBase * res;
|
||||||
|
|
||||||
|
// cout << "res = " << res.x << " " << res.y << endl;
|
||||||
|
// vec2 res = ifaceBase * textureBase * r * faceBase;
|
||||||
|
//
|
||||||
|
// cout << "pix " << ix << " " << res.x << " " << res.y << " " << res.z << endl;
|
||||||
|
// float fb = dot(r, eb) / leb;
|
||||||
|
// float fc = dot(r, ec) / lec;
|
||||||
|
vec3 sp = p[0] + res; //res.x * mb + res.y * mc;
|
||||||
|
float v = (float) noise.octaveNoise0_1(sp.x * frequency * 4,
|
||||||
|
sp.y * frequency * 4, sp.z * frequency * 4, 8);
|
||||||
|
//
|
||||||
|
v = pow(v, 3);
|
||||||
|
// default color
|
||||||
|
float r = 0.12 + v * 0.72, g = 0.1 + 0.7 * v, b = 0.1
|
||||||
|
+ 0.7 * v;
|
||||||
|
|
||||||
|
diff[ix + iy * texture_size][0] = r * 255;
|
||||||
|
diff[ix + iy * texture_size][1] = g * 255;
|
||||||
|
diff[ix + iy * texture_size][2] = b * 255;
|
||||||
|
|
||||||
|
// diff[ix + iy * ntex] = v * 255;
|
||||||
|
// diff[ix + iy * ntex][0] = (32 * rx) % 255;
|
||||||
|
// diff[ix + iy * ntex][1] = (32 * ry) % 255;
|
||||||
|
// diff[ix + iy * ntex][2] = 0; //(0.5 + sp.z) * 255;
|
||||||
|
|
||||||
|
// float rd = 1.f; //0.7 + 0.3 * length(r) * rects;
|
||||||
|
// diff[ix + iy * ntex][0] = rd * (0.5 + sp.x) * 255;
|
||||||
|
// diff[ix + iy * ntex][1] = rd * (0.5 + sp.y) * 255;
|
||||||
|
// diff[ix + iy * ntex][2] = rd * (0.5 + sp.z) * 255;
|
||||||
|
|
||||||
|
// diff[ix + iy * ntex][0] = length(r) * rects * 255;
|
||||||
|
// diff[ix + iy * ntex][1] = length(r) * rects * 255;
|
||||||
|
// diff[ix + iy * ntex][2] = length(r) * rects * 255;
|
||||||
|
|
||||||
|
// diff[ix + iy * ntex][0] = r.x * rects * 200;
|
||||||
|
// diff[ix + iy * ntex][1] = -r.z * rects * 200;
|
||||||
|
// diff[ix + iy * ntex][2] = 0;
|
||||||
|
|
||||||
|
// diff[ix + iy * ntex][0] = 128 + (res.x - 0.5) * 200;
|
||||||
|
// diff[ix + iy * ntex][1] = 128 + (res.y - 0.5) * 200;
|
||||||
|
// diff[ix + iy * ntex][2] = 0; //res.z * 255;
|
||||||
|
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
rx++;
|
||||||
|
if (rx >= rects) {
|
||||||
|
rx = 0;
|
||||||
|
ry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// for (int ix = 0; ix < ntex; ix++) {
|
||||||
|
// for (int iy = 0; iy < ntex; iy++) {
|
||||||
|
//
|
||||||
|
// float v = (float) noise.octaveNoise0_1(ix * texf * frequency,
|
||||||
|
// iy * texf * frequency, 0.5 * frequency, 4);
|
||||||
|
// diff[ix + (ntex - iy) * ntex] = 5 + v * 250;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
stbi_write_bmp("diffuse.bmp", texture_size, texture_size, 3,
|
||||||
|
diff.data());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SRC_TEXTUREMAPPER_H_ */
|
1026
src/gen.cpp
Normal file
1026
src/gen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
385
src/main.cpp
Normal file
385
src/main.cpp
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
#include "Density.h"
|
||||||
|
#include "Polygoniser.h"
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <imgui_impl_glfw_gl3.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
static bool glck(const char* call) {
|
||||||
|
int err = glGetError();
|
||||||
|
if (err == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
switch (err) {
|
||||||
|
case GL_INVALID_VALUE:
|
||||||
|
printf("GL_INVALID_VALUE: %s\n", call);
|
||||||
|
break;
|
||||||
|
case GL_INVALID_ENUM:
|
||||||
|
printf("GL_INVALID_ENUM: %s\n", call);
|
||||||
|
break;
|
||||||
|
case GL_INVALID_OPERATION:
|
||||||
|
printf("GL_INVALID_OPERATION: %s\n", call);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("UNKNOWN Error: %s\n", call);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GLCK(a) {a; assert(glck(#a));}
|
||||||
|
|
||||||
|
// ! https://learnopengl.com/#!PBR/Lighting
|
||||||
|
|
||||||
|
static const char* vertex_shader_text = "#version 130\n"
|
||||||
|
"uniform mat4 MVP;\n"
|
||||||
|
"in vec3 vPos;\n"
|
||||||
|
"in vec3 vNorm;\n"
|
||||||
|
"out vec3 normal;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_Position = MVP * vec4(vPos, 1.0);\n"
|
||||||
|
" normal = normalize(vNorm);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char* fragment_shader_text = "#version 130\n"
|
||||||
|
"in vec3 normal;\n"
|
||||||
|
"out vec4 color;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" color = normal.y * vec4(1.0, 0.95, 0.9, 1.0);\n"
|
||||||
|
"}\n";
|
||||||
|
static void error_callback(int error, const char* description) {
|
||||||
|
fprintf(stderr, "Error: %s\n", description);
|
||||||
|
}
|
||||||
|
static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
||||||
|
int mods) {
|
||||||
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||||
|
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkShader(GLuint vertexShader, const std::string &name) {
|
||||||
|
GLint status;
|
||||||
|
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
|
||||||
|
|
||||||
|
if (status == GL_FALSE) {
|
||||||
|
|
||||||
|
std::cout << "Shader '" << name << "' compiled with an error(s):"
|
||||||
|
<< std::endl;
|
||||||
|
char buffer[512];
|
||||||
|
int l;
|
||||||
|
glGetShaderInfoLog(vertexShader, 512, &l, buffer);
|
||||||
|
buffer[l] = 0;
|
||||||
|
std::cout << buffer << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkProgam(GLuint vertexShader, const std::string &name) {
|
||||||
|
GLint status;
|
||||||
|
glGetProgramiv(vertexShader, GL_LINK_STATUS, &status);
|
||||||
|
|
||||||
|
if (status == GL_FALSE) {
|
||||||
|
|
||||||
|
std::cout << "Program '" << name << "' failed with an error(s):"
|
||||||
|
<< std::endl;
|
||||||
|
char buffer[512];
|
||||||
|
int l;
|
||||||
|
glGetProgramInfoLog(vertexShader, 512, &l, buffer);
|
||||||
|
buffer[l] = 0;
|
||||||
|
std::cout << buffer << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculateNormals(const std::vector<glm::vec3> &vtx,
|
||||||
|
std::vector<glm::uvec3> &tri, std::vector<glm::vec3> &normals) {
|
||||||
|
normals.clear();
|
||||||
|
normals.resize(vtx.size(), glm::vec3(0));
|
||||||
|
for (size_t i = 0; i < tri.size(); i++) {
|
||||||
|
int a = tri[i].x, b = tri[i].y, c = tri[i].z;
|
||||||
|
glm::vec3 faceNormal = normalize(
|
||||||
|
glm::cross(vtx[b] - vtx[a], vtx[c] - vtx[a]));
|
||||||
|
normals[a] += faceNormal;
|
||||||
|
normals[b] += faceNormal;
|
||||||
|
normals[c] += faceNormal;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < normals.size(); i++)
|
||||||
|
normals[i] = glm::normalize(normals[i]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveToMean(std::vector<glm::vec3> &vtx) {
|
||||||
|
glm::vec3 mean(0);
|
||||||
|
for (size_t i = 0; i < vtx.size(); i++) {
|
||||||
|
mean += vtx[i];
|
||||||
|
}
|
||||||
|
mean *= glm::vec3(1.f / vtx.size());
|
||||||
|
for (size_t i = 0; i < vtx.size(); i++) {
|
||||||
|
vtx[i] -= mean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void smooth(std::vector<glm::vec3> &vtx, const std::vector<glm::uvec3> &tri) {
|
||||||
|
std::vector<glm::vec3> cogs(vtx.size(), glm::vec3(0.f));
|
||||||
|
std::vector<int> valence(vtx.size(), 0);
|
||||||
|
|
||||||
|
for (size_t iTri = 0; iTri < tri.size(); iTri++) {
|
||||||
|
const glm::uvec3 &idx = tri[iTri];
|
||||||
|
for (size_t iE = 0; iE < 3; iE++) {
|
||||||
|
valence[idx[iE]] += 2;
|
||||||
|
cogs[idx[iE]] += vtx[idx[(iE + 1) % 3]];
|
||||||
|
cogs[idx[iE]] += vtx[idx[(iE + 2) % 3]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) {
|
||||||
|
cog[0] = cog[1] = cog[2] = valence = 0.0;
|
||||||
|
|
||||||
|
for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) {
|
||||||
|
cog += mesh.point(*vv_it);
|
||||||
|
++valence;
|
||||||
|
}
|
||||||
|
cogs.push_back(cog / valence);
|
||||||
|
}
|
||||||
|
for (v_it = mesh.vertices_begin(), cog_it = cogs.begin(); v_it != v_end;
|
||||||
|
++v_it, ++cog_it)
|
||||||
|
if (!mesh.is_boundary(*v_it))
|
||||||
|
mesh.set_point(*v_it, *cog_it);
|
||||||
|
|
||||||
|
*/
|
||||||
|
for (size_t i = 0; i < vtx.size(); i++) {
|
||||||
|
// vtx[i] = vtx[i] * glm::vec3(0.8)
|
||||||
|
// + cogs[i] * glm::vec3(0.2f / valence[i]);
|
||||||
|
vtx[i] = cogs[i] * glm::vec3(1.f / valence[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveAttrib(std::ostream &out, const char *prefix,
|
||||||
|
std::vector<glm::vec3> &elements) {
|
||||||
|
for (size_t i = 0; i < elements.size(); i++) {
|
||||||
|
out << prefix << elements[i].x << " " << elements[i].y << " " << elements[i].z
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveAttrib(std::ostream &out, const char *prefix,
|
||||||
|
std::vector<glm::vec2> &elements) {
|
||||||
|
for (size_t i = 0; i < elements.size(); i++) {
|
||||||
|
out << prefix << elements[i].x << " " << elements[i].y << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveFaces(std::ostream &out, const std::vector<glm::uvec3> &tris, size_t attribs) {
|
||||||
|
for (size_t i = 0; i < tris.size(); i++) {
|
||||||
|
out << "f";
|
||||||
|
|
||||||
|
for (size_t j = 0; j < 3; j++) {
|
||||||
|
int v = tris[i][j] + 1;
|
||||||
|
out << " " << v;
|
||||||
|
if (attribs > 1)
|
||||||
|
out << "/" << v;
|
||||||
|
if (attribs > 2)
|
||||||
|
out << "/" << v;
|
||||||
|
out << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculateEdges(const std::vector<glm::vec3> &vtx,
|
||||||
|
std::vector<glm::uvec3> &tri, std::vector<glm::vec4> &edges) {
|
||||||
|
edges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
std::srand(123);
|
||||||
|
|
||||||
|
Density density;
|
||||||
|
density.addRandomImpacts(1000, 0.2, 0.01, 0.005, 0.2, 4096);
|
||||||
|
//density.saveCrossSection("density.png", 512);
|
||||||
|
|
||||||
|
Polygonizer polygonizer(density);
|
||||||
|
polygonizer.polygonize(0.2, 1. / 20.);
|
||||||
|
|
||||||
|
moveToMean(polygonizer.vertices);
|
||||||
|
{
|
||||||
|
std::ofstream out("stage1.obj");
|
||||||
|
saveAttrib(out, "v ", polygonizer.vertices);
|
||||||
|
saveFaces(out, polygonizer.triangles, 1);
|
||||||
|
}
|
||||||
|
smooth(polygonizer.vertices, polygonizer.triangles);
|
||||||
|
{
|
||||||
|
std::ofstream out("stage2.obj");
|
||||||
|
saveAttrib(out, "v ", polygonizer.vertices);
|
||||||
|
saveFaces(out, polygonizer.triangles, 1);
|
||||||
|
}
|
||||||
|
std::vector<glm::vec3> normals;
|
||||||
|
calculateNormals(polygonizer.vertices, polygonizer.triangles, normals);
|
||||||
|
{
|
||||||
|
std::ofstream out("stage3.obj");
|
||||||
|
saveAttrib(out, "v ", polygonizer.vertices);
|
||||||
|
saveAttrib(out, "vn ", normals);
|
||||||
|
saveFaces(out, polygonizer.triangles, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<glm::uvec4> edges;
|
||||||
|
std::cout << "Vertices: " << polygonizer.vertices.size() << std::endl;
|
||||||
|
std::cout << "Triangles: " << polygonizer.triangles.size() << std::endl;
|
||||||
|
|
||||||
|
GLFWwindow* window;
|
||||||
|
GLuint vertex_array, vertex_buffer, index_buffer, normal_buffer,
|
||||||
|
vertex_shader, fragment_shader, program;
|
||||||
|
GLint mvp_location, vpos_location, vnorm_location;
|
||||||
|
|
||||||
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
|
if (!glfwInit())
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
|
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
||||||
|
|
||||||
|
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
|
||||||
|
if (!window) {
|
||||||
|
glfwTerminate();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwSetKeyCallback(window, key_callback);
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||||
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
|
std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
|
||||||
|
std::cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION)
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
|
||||||
|
std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
|
||||||
|
|
||||||
|
// NOTE: OpenGL error checks have been omitted for brevity
|
||||||
|
|
||||||
|
// glGenBuffers(1, &vertex_buffer);
|
||||||
|
// glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||||
|
// glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
GLCK(glGenVertexArrays(1, &vertex_array))
|
||||||
|
GLCK(glBindVertexArray(vertex_array))
|
||||||
|
|
||||||
|
GLCK(glGenBuffers(1, &vertex_buffer))
|
||||||
|
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer))
|
||||||
|
GLCK(
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, polygonizer.vertices.size() * sizeof(glm::vec3), polygonizer.vertices.data(), GL_STATIC_DRAW))
|
||||||
|
|
||||||
|
GLCK(glGenBuffers(1, &index_buffer))
|
||||||
|
GLCK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer))
|
||||||
|
GLCK(
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, polygonizer.triangles.size() * sizeof(glm::uvec3), polygonizer.triangles.data(), GL_STATIC_DRAW))
|
||||||
|
|
||||||
|
GLCK(glGenBuffers(1, &normal_buffer))
|
||||||
|
GLCK(glBindBuffer(GL_ARRAY_BUFFER, normal_buffer))
|
||||||
|
GLCK(
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), GL_STATIC_DRAW))
|
||||||
|
|
||||||
|
GLCK(vertex_shader = glCreateShader(GL_VERTEX_SHADER))
|
||||||
|
GLCK(glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL))
|
||||||
|
GLCK(glCompileShader(vertex_shader))
|
||||||
|
checkShader(vertex_shader, "vertex");
|
||||||
|
|
||||||
|
GLCK(fragment_shader = glCreateShader(GL_FRAGMENT_SHADER))
|
||||||
|
GLCK(glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL))
|
||||||
|
GLCK(glCompileShader(fragment_shader))
|
||||||
|
checkShader(fragment_shader, "fragment");
|
||||||
|
|
||||||
|
GLCK(program = glCreateProgram())
|
||||||
|
GLCK(glAttachShader(program, vertex_shader))
|
||||||
|
GLCK(glAttachShader(program, fragment_shader))
|
||||||
|
GLCK(glLinkProgram(program))
|
||||||
|
checkProgam(program, "program");
|
||||||
|
|
||||||
|
GLCK(mvp_location = glGetUniformLocation(program, "MVP"))
|
||||||
|
std::cout << mvp_location << std::endl;
|
||||||
|
|
||||||
|
GLCK(vpos_location = glGetAttribLocation(program, "vPos"))
|
||||||
|
std::cout << vpos_location << std::endl;
|
||||||
|
|
||||||
|
GLCK(vnorm_location = glGetAttribLocation(program, "vNorm"))
|
||||||
|
std::cout << vnorm_location << std::endl;
|
||||||
|
|
||||||
|
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer))
|
||||||
|
glEnableVertexAttribArray(vpos_location);
|
||||||
|
GLCK(
|
||||||
|
glVertexAttribPointer(vpos_location, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0))
|
||||||
|
|
||||||
|
if (vnorm_location >= 0) {
|
||||||
|
GLCK(glBindBuffer(GL_ARRAY_BUFFER, normal_buffer))
|
||||||
|
GLCK(glEnableVertexAttribArray(vnorm_location))
|
||||||
|
GLCK(
|
||||||
|
glVertexAttribPointer(vnorm_location, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplGlfwGL3_Init(window, true);
|
||||||
|
|
||||||
|
while (!glfwWindowShouldClose(window)) {
|
||||||
|
glfwPollEvents();
|
||||||
|
ImGui_ImplGlfwGL3_NewFrame();
|
||||||
|
{
|
||||||
|
static float f = 0.0f;
|
||||||
|
static float resolution = 0.1f;
|
||||||
|
ImGui::Text("Hello, world!");
|
||||||
|
if (ImGui::Button("Wireframe"))
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
if (ImGui::Button("Fill"))
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
ImGui::InputFloat("Resolution", &resolution);
|
||||||
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
|
||||||
|
1000.0f / ImGui::GetIO().Framerate,
|
||||||
|
ImGui::GetIO().Framerate);
|
||||||
|
}
|
||||||
|
int width, height;
|
||||||
|
glm::mat4 m(1.0f), p, mvp(2);
|
||||||
|
|
||||||
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
|
float ratio = width / (float) height;
|
||||||
|
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
m = glm::rotate(m, (float) glfwGetTime(), glm::vec3(0.f, 0.f, 1.f));
|
||||||
|
//m = glm::translate(m, glm::vec3(-1.f));
|
||||||
|
//glm::translate(mvp, glm::vec3((float) glfwGetTime()));
|
||||||
|
p = glm::ortho(-1.f, 1.f, -1.f, 1.f);
|
||||||
|
mvp = p * m;
|
||||||
|
|
||||||
|
GLCK(glUseProgram(program))
|
||||||
|
GLCK(
|
||||||
|
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) &mvp))
|
||||||
|
|
||||||
|
// Draw the triangles !
|
||||||
|
GLCK(glBindVertexArray(vertex_array))
|
||||||
|
glDrawElements( GL_TRIANGLES, polygonizer.triangles.size() * 3,
|
||||||
|
GL_UNSIGNED_INT, (void*) 0);
|
||||||
|
//GLCK(glDrawArrays( GL_TRIANGLES, 0, polygonizer.triangles.size() * 3))
|
||||||
|
ImGui::Render();
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
|
||||||
|
ImGui_ImplGlfwGL3_Shutdown();
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
284
vendor/KHR/khrplatform.h
vendored
Normal file
284
vendor/KHR/khrplatform.h
vendored
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
#ifndef __khrplatform_h_
|
||||||
|
#define __khrplatform_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2008-2009 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
** copy of this software and/or associated documentation files (the
|
||||||
|
** "Materials"), to deal in the Materials without restriction, including
|
||||||
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
** the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included
|
||||||
|
** in all copies or substantial portions of the Materials.
|
||||||
|
**
|
||||||
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Khronos platform-specific types and definitions.
|
||||||
|
*
|
||||||
|
* $Revision: 32517 $ on $Date: 2016-03-11 02:41:19 -0800 (Fri, 11 Mar 2016) $
|
||||||
|
*
|
||||||
|
* Adopters may modify this file to suit their platform. Adopters are
|
||||||
|
* encouraged to submit platform specific modifications to the Khronos
|
||||||
|
* group so that they can be included in future versions of this file.
|
||||||
|
* Please submit changes by sending them to the public Khronos Bugzilla
|
||||||
|
* (http://khronos.org/bugzilla) by filing a bug against product
|
||||||
|
* "Khronos (general)" component "Registry".
|
||||||
|
*
|
||||||
|
* A predefined template which fills in some of the bug fields can be
|
||||||
|
* reached using http://tinyurl.com/khrplatform-h-bugreport, but you
|
||||||
|
* must create a Bugzilla login first.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* See the Implementer's Guidelines for information about where this file
|
||||||
|
* should be located on your system and for more details of its use:
|
||||||
|
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||||
|
*
|
||||||
|
* This file should be included as
|
||||||
|
* #include <KHR/khrplatform.h>
|
||||||
|
* by Khronos client API header files that use its types and defines.
|
||||||
|
*
|
||||||
|
* The types in khrplatform.h should only be used to define API-specific types.
|
||||||
|
*
|
||||||
|
* Types defined in khrplatform.h:
|
||||||
|
* khronos_int8_t signed 8 bit
|
||||||
|
* khronos_uint8_t unsigned 8 bit
|
||||||
|
* khronos_int16_t signed 16 bit
|
||||||
|
* khronos_uint16_t unsigned 16 bit
|
||||||
|
* khronos_int32_t signed 32 bit
|
||||||
|
* khronos_uint32_t unsigned 32 bit
|
||||||
|
* khronos_int64_t signed 64 bit
|
||||||
|
* khronos_uint64_t unsigned 64 bit
|
||||||
|
* khronos_intptr_t signed same number of bits as a pointer
|
||||||
|
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||||
|
* khronos_ssize_t signed size
|
||||||
|
* khronos_usize_t unsigned size
|
||||||
|
* khronos_float_t signed 32 bit floating point
|
||||||
|
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||||
|
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||||
|
* nanoseconds
|
||||||
|
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||||
|
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||||
|
* only be used as a base type when a client API's boolean type is
|
||||||
|
* an enum. Client APIs which use an integer or other type for
|
||||||
|
* booleans cannot use this as the base type for their boolean.
|
||||||
|
*
|
||||||
|
* Tokens defined in khrplatform.h:
|
||||||
|
*
|
||||||
|
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||||
|
*
|
||||||
|
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||||
|
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||||
|
*
|
||||||
|
* Calling convention macros defined in this file:
|
||||||
|
* KHRONOS_APICALL
|
||||||
|
* KHRONOS_APIENTRY
|
||||||
|
* KHRONOS_APIATTRIBUTES
|
||||||
|
*
|
||||||
|
* These may be used in function prototypes as:
|
||||||
|
*
|
||||||
|
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||||
|
* int arg1,
|
||||||
|
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APICALL
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This precedes the return type of the function in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||||
|
# define KHRONOS_APICALL __declspec(dllimport)
|
||||||
|
#elif defined (__SYMBIAN32__)
|
||||||
|
# define KHRONOS_APICALL IMPORT_C
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIENTRY
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the return type of the function and precedes the function
|
||||||
|
* name in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||||
|
/* Win32 but not WinCE */
|
||||||
|
# define KHRONOS_APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIATTRIBUTES
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the closing parenthesis of the function prototype arguments.
|
||||||
|
*/
|
||||||
|
#if defined (__ARMCC_2__)
|
||||||
|
#define KHRONOS_APIATTRIBUTES __softfp
|
||||||
|
#else
|
||||||
|
#define KHRONOS_APIATTRIBUTES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* basic type definitions
|
||||||
|
*-----------------------------------------------------------------------*/
|
||||||
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <stdint.h>
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__VMS ) || defined(__sgi)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <inttypes.h>
|
||||||
|
*/
|
||||||
|
#include <inttypes.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32
|
||||||
|
*/
|
||||||
|
typedef __int32 khronos_int32_t;
|
||||||
|
typedef unsigned __int32 khronos_uint32_t;
|
||||||
|
typedef __int64 khronos_int64_t;
|
||||||
|
typedef unsigned __int64 khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__sun__) || defined(__digital__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sun or Digital
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#if defined(__arch64__) || defined(_LP64)
|
||||||
|
typedef long int khronos_int64_t;
|
||||||
|
typedef unsigned long int khronos_uint64_t;
|
||||||
|
#else
|
||||||
|
typedef long long int khronos_int64_t;
|
||||||
|
typedef unsigned long long int khronos_uint64_t;
|
||||||
|
#endif /* __arch64__ */
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypothetical platform with no float or int64 support
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 0
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic fallback
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that are (so far) the same on all platforms
|
||||||
|
*/
|
||||||
|
typedef signed char khronos_int8_t;
|
||||||
|
typedef unsigned char khronos_uint8_t;
|
||||||
|
typedef signed short int khronos_int16_t;
|
||||||
|
typedef unsigned short int khronos_uint16_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||||
|
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||||
|
* to be the only LLP64 architecture in current use.
|
||||||
|
*/
|
||||||
|
#ifdef _WIN64
|
||||||
|
typedef signed long long int khronos_intptr_t;
|
||||||
|
typedef unsigned long long int khronos_uintptr_t;
|
||||||
|
typedef signed long long int khronos_ssize_t;
|
||||||
|
typedef unsigned long long int khronos_usize_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_intptr_t;
|
||||||
|
typedef unsigned long int khronos_uintptr_t;
|
||||||
|
typedef signed long int khronos_ssize_t;
|
||||||
|
typedef unsigned long int khronos_usize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_FLOAT
|
||||||
|
/*
|
||||||
|
* Float type
|
||||||
|
*/
|
||||||
|
typedef float khronos_float_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_INT64
|
||||||
|
/* Time types
|
||||||
|
*
|
||||||
|
* These types can be used to represent a time interval in nanoseconds or
|
||||||
|
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||||
|
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||||
|
* time the system booted). The Unadjusted System Time is an unsigned
|
||||||
|
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||||
|
* may be either signed or unsigned.
|
||||||
|
*/
|
||||||
|
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||||
|
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy value used to pad enum types to 32 bits.
|
||||||
|
*/
|
||||||
|
#ifndef KHRONOS_MAX_ENUM
|
||||||
|
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerated boolean type
|
||||||
|
*
|
||||||
|
* Values other than zero should be considered to be true. Therefore
|
||||||
|
* comparisons should not be made against KHRONOS_TRUE.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
KHRONOS_FALSE = 0,
|
||||||
|
KHRONOS_TRUE = 1,
|
||||||
|
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||||
|
} khronos_boolean_enum_t;
|
||||||
|
|
||||||
|
#endif /* __khrplatform_h_ */
|
894
vendor/LSCM.h
vendored
Normal file
894
vendor/LSCM.h
vendored
Normal file
@ -0,0 +1,894 @@
|
|||||||
|
/*
|
||||||
|
* To compile under Linux:
|
||||||
|
* g++ -O3 LSCM.cpp OpenNL_psm.c -o LSCM -ldl -lm
|
||||||
|
* To compile under Linux with static linking:
|
||||||
|
* gcc -O3 -DGEO_STATIC_LIBS LSCM.cpp OpenNL_psm.c -o LSCM -lm
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2010, Bruno Levy
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * 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.
|
||||||
|
* * Neither the name of the ALICE Project-Team 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.
|
||||||
|
*
|
||||||
|
* If you modify this software, you should include a notice giving the
|
||||||
|
* name of the person performing the modification, the date of modification,
|
||||||
|
* and the reason for such modification.
|
||||||
|
*
|
||||||
|
* Contact: Bruno Levy
|
||||||
|
*
|
||||||
|
* levy@loria.fr
|
||||||
|
*
|
||||||
|
* ALICE Project
|
||||||
|
* LORIA, INRIA Lorraine,
|
||||||
|
* Campus Scientifique, BP 239
|
||||||
|
* 54506 VANDOEUVRE LES NANCY CEDEX
|
||||||
|
* FRANCE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "OpenNL_psm.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace LSCM {
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* Basic geometric types */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A 2D vector
|
||||||
|
*/
|
||||||
|
class vec2 {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* \brief Constructs a 2D vector from its coordinates.
|
||||||
|
* \param x_in , y_in the coordinates.
|
||||||
|
*/
|
||||||
|
vec2(double x_in, double y_in) :
|
||||||
|
x(x_in), y(y_in) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs the zero vector.
|
||||||
|
*/
|
||||||
|
vec2() :
|
||||||
|
x(0), y(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A 3D vector
|
||||||
|
*/
|
||||||
|
class vec3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs a 3D vector from its coordinates.
|
||||||
|
* \param x_in , y_in , z_in the coordinates.
|
||||||
|
*/
|
||||||
|
vec3(double x_in, double y_in, double z_in) :
|
||||||
|
x(x_in), y(y_in), z(z_in) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs the zero vector.
|
||||||
|
*/
|
||||||
|
vec3() :
|
||||||
|
x(0), y(0), z(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets the length of this vector.
|
||||||
|
* \return the length of this vector.
|
||||||
|
*/
|
||||||
|
double length() const {
|
||||||
|
return sqrt(x * x + y * y + z * z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Normalizes this vector.
|
||||||
|
* \details This makes the norm equal to 1.0
|
||||||
|
*/
|
||||||
|
void normalize() {
|
||||||
|
double l = length();
|
||||||
|
x /= l;
|
||||||
|
y /= l;
|
||||||
|
z /= l;
|
||||||
|
}
|
||||||
|
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Outputs a 2D vector to a stream.
|
||||||
|
* \param[out] out a reference to the stream
|
||||||
|
* \param[in] v a const reference to the vector
|
||||||
|
* \return the new state of the stream
|
||||||
|
* \relates vec2
|
||||||
|
*/
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, const vec2& v) {
|
||||||
|
return out << v.x << " " << v.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Outputs a 3D vector to a stream.
|
||||||
|
* \param[out] out a reference to the stream
|
||||||
|
* \param[in] v a const reference to the vector
|
||||||
|
* \return the new state of the stream
|
||||||
|
* \relates vec3
|
||||||
|
*/
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, const vec3& v) {
|
||||||
|
return out << v.x << " " << v.y << " " << v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Reads a 2D vector from a stream
|
||||||
|
* \param[in] in a reference to the stream
|
||||||
|
* \param[out] v a reference to the vector
|
||||||
|
* \return the new state of the stream
|
||||||
|
* \relates vec2
|
||||||
|
*/
|
||||||
|
inline std::istream& operator>>(std::istream& in, vec2& v) {
|
||||||
|
return in >> v.x >> v.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Reads a 3D vector from a stream
|
||||||
|
* \param[in] in a reference to the stream
|
||||||
|
* \param[out] v a reference to the vector
|
||||||
|
* \return the new state of the stream
|
||||||
|
* \relates vec3
|
||||||
|
*/
|
||||||
|
inline std::istream& operator>>(std::istream& in, vec3& v) {
|
||||||
|
return in >> v.x >> v.y >> v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the dot product between two vectors
|
||||||
|
* \param[in] v1 , v2 const references to the two vectors
|
||||||
|
* \return the dot product between \p v1 and \p v2
|
||||||
|
* \relates vec3
|
||||||
|
*/
|
||||||
|
inline double dot(const vec3& v1, const vec3& v2) {
|
||||||
|
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the cross product between two vectors
|
||||||
|
* \param[in] v1 , v2 const references to the two vectors
|
||||||
|
* \return the cross product between \p v1 and \p v2
|
||||||
|
* \relates vec3
|
||||||
|
*/
|
||||||
|
inline vec3 cross(const vec3& v1, const vec3& v2) {
|
||||||
|
return vec3(v1.y * v2.z - v2.y * v1.z, v1.z * v2.x - v2.z * v1.x,
|
||||||
|
v1.x * v2.y - v2.x * v1.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the sum of two vectors
|
||||||
|
* \param[in] v1 , v2 const references to the two vectors
|
||||||
|
* \return the sum of \p v1 and \p v2
|
||||||
|
* \relates vec3
|
||||||
|
*/
|
||||||
|
inline vec3 operator+(const vec3& v1, const vec3& v2) {
|
||||||
|
return vec3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the difference between two vectors
|
||||||
|
* \param[in] v1 , v2 const references to the two vectors
|
||||||
|
* \return the difference between \p v1 and \p v2
|
||||||
|
* \relates vec3
|
||||||
|
*/
|
||||||
|
inline vec3 operator-(const vec3& v1, const vec3& v2) {
|
||||||
|
return vec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the sum of two vectors
|
||||||
|
* \param[in] v1 , v2 const references to the two vectors
|
||||||
|
* \return the sum of \p v1 and \p v2
|
||||||
|
* \relates vec2
|
||||||
|
*/
|
||||||
|
inline vec2 operator+(const vec2& v1, const vec2& v2) {
|
||||||
|
return vec2(v1.x + v2.x, v1.y + v2.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the difference between two vectors
|
||||||
|
* \param[in] v1 , v2 const references to the two vectors
|
||||||
|
* \return the difference between \p v1 and \p v2
|
||||||
|
* \relates vec2
|
||||||
|
*/
|
||||||
|
inline vec2 operator-(const vec2& v1, const vec2& v2) {
|
||||||
|
return vec2(v1.x - v2.x, v1.y - v2.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* Mesh class */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A vertex in an IndexedMesh
|
||||||
|
* \relates IndexedMesh
|
||||||
|
*/
|
||||||
|
class Vertex {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* \brief Vertex constructor.
|
||||||
|
*/
|
||||||
|
Vertex() :
|
||||||
|
locked(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Vertex constructor from 3D point and texture
|
||||||
|
* coordinates.
|
||||||
|
* \param[in] p the 3D coordinates of the vertex
|
||||||
|
* \param[in] t the texture coordinates associated with the vertex
|
||||||
|
*/
|
||||||
|
Vertex(const vec3& p, const vec2& t) :
|
||||||
|
point(p), tex_coord(t), locked(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The 3D coordinates.
|
||||||
|
*/
|
||||||
|
vec3 point;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The texture coordinates (2D).
|
||||||
|
*/
|
||||||
|
vec2 tex_coord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A boolean flag that indicates whether the vertex is
|
||||||
|
* locked, i.e. considered as constant in the optimizations.
|
||||||
|
*/
|
||||||
|
bool locked;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A minimum mesh class.
|
||||||
|
* \details It does not have facet adjacency information
|
||||||
|
* (we do not need it for LSCM), it just stores for each facet the indices
|
||||||
|
* of its vertices. It has load() and save() functions that use the
|
||||||
|
* Alias Wavefront .obj file format.
|
||||||
|
*/
|
||||||
|
class IndexedMesh {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief IndexedMesh constructor
|
||||||
|
*/
|
||||||
|
IndexedMesh() :
|
||||||
|
in_facet(false) {
|
||||||
|
facet_ptr.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets the number of vertices.
|
||||||
|
* \return the number of vertices in this mesh.
|
||||||
|
*/
|
||||||
|
NLuint nb_vertices() const {
|
||||||
|
return NLuint(vertex.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets the number of facets.
|
||||||
|
* \return the number of facets in this mesh.
|
||||||
|
*/
|
||||||
|
NLuint nb_facets() const {
|
||||||
|
return NLuint(facet_ptr.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets the number of vertices in a facet.
|
||||||
|
* \param[in] f the facet, in 0..nb_facets()-1
|
||||||
|
* \return the number of vertices in facet \p f
|
||||||
|
* \pre f < nb_facets()
|
||||||
|
*/
|
||||||
|
NLuint facet_nb_vertices(NLuint f) {
|
||||||
|
assert(f < nb_facets());
|
||||||
|
return facet_ptr[f + 1] - facet_ptr[f];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets a facet vertex by facet index and
|
||||||
|
* local vertex index in facet.
|
||||||
|
* \param[in] f the facet, in 0..nb_facets()-1
|
||||||
|
* \param[in] lv the local vertex index in the facet,
|
||||||
|
* in 0..facet_nb_vertices(f)-1
|
||||||
|
* \return the global vertex index, in 0..nb_vertices()-1
|
||||||
|
* \pre f<nb_facets() && lv < facet_nb_vertices(f)
|
||||||
|
*/
|
||||||
|
NLuint facet_vertex(NLuint f, NLuint lv) {
|
||||||
|
assert(f < nb_facets());
|
||||||
|
assert(lv < facet_nb_vertices(f));
|
||||||
|
return corner[facet_ptr[f] + lv];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds a new vertex to the mesh.
|
||||||
|
*/
|
||||||
|
void add_vertex() {
|
||||||
|
vertex.push_back(Vertex());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds a new vertex to the mesh.
|
||||||
|
* \param[in] p the 3D coordinates of the vertex
|
||||||
|
* \param[in] t the texture coordinates of the vertex
|
||||||
|
*/
|
||||||
|
void add_vertex(const vec3& p, const vec2& t) {
|
||||||
|
vertex.push_back(Vertex(p, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Stats a new facet.
|
||||||
|
*/
|
||||||
|
void begin_facet() {
|
||||||
|
assert(!in_facet);
|
||||||
|
in_facet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Terminates the current facet.
|
||||||
|
*/
|
||||||
|
void end_facet() {
|
||||||
|
assert(in_facet);
|
||||||
|
in_facet = false;
|
||||||
|
facet_ptr.push_back(NLuint(corner.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds a vertex to the current facet.
|
||||||
|
* \param[in] v the index of the vertex
|
||||||
|
* \pre v < vertex.size()
|
||||||
|
*/
|
||||||
|
void add_vertex_to_facet(NLuint v) {
|
||||||
|
assert(in_facet);
|
||||||
|
assert(v < vertex.size());
|
||||||
|
corner.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Removes all vertices and all facets from
|
||||||
|
* this mesh.
|
||||||
|
*/
|
||||||
|
void clear() {
|
||||||
|
vertex.clear();
|
||||||
|
corner.clear();
|
||||||
|
facet_ptr.clear();
|
||||||
|
facet_ptr.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Loads a file in Alias Wavefront OFF format.
|
||||||
|
* \param[in] file_name the name of the file.
|
||||||
|
*/
|
||||||
|
void load(const std::string& file_name) {
|
||||||
|
std::ifstream input(file_name.c_str());
|
||||||
|
clear();
|
||||||
|
while (input) {
|
||||||
|
std::string line;
|
||||||
|
std::getline(input, line);
|
||||||
|
std::stringstream line_input(line);
|
||||||
|
std::string keyword;
|
||||||
|
line_input >> keyword;
|
||||||
|
if (keyword == "v") {
|
||||||
|
vec3 p;
|
||||||
|
line_input >> p;
|
||||||
|
add_vertex(p, vec2(0.0, 0.0));
|
||||||
|
} else if (keyword == "vt") {
|
||||||
|
// Ignore tex vertices
|
||||||
|
} else if (keyword == "f") {
|
||||||
|
begin_facet();
|
||||||
|
while (line_input) {
|
||||||
|
std::string s;
|
||||||
|
line_input >> s;
|
||||||
|
if (s.length() > 0) {
|
||||||
|
std::stringstream v_input(s.c_str());
|
||||||
|
NLuint index;
|
||||||
|
v_input >> index;
|
||||||
|
add_vertex_to_facet(index - 1);
|
||||||
|
char c;
|
||||||
|
v_input >> c;
|
||||||
|
if (c == '/') {
|
||||||
|
v_input >> index;
|
||||||
|
// Ignore tex vertex index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end_facet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "Loaded " << vertex.size() << " vertices and "
|
||||||
|
<< nb_facets() << " facets" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Saves a file in Alias Wavefront OFF format.
|
||||||
|
* \param[in] file_name the name of the file.
|
||||||
|
*/
|
||||||
|
void save(const std::string& file_name) {
|
||||||
|
std::ofstream out(file_name.c_str());
|
||||||
|
for (NLuint v = 0; v < nb_vertices(); ++v) {
|
||||||
|
out << "v " << vertex[v].point << std::endl;
|
||||||
|
}
|
||||||
|
for (NLuint v = 0; v < nb_vertices(); ++v) {
|
||||||
|
out << "vt " << vertex[v].tex_coord << std::endl;
|
||||||
|
}
|
||||||
|
for (NLuint f = 0; f < nb_facets(); ++f) {
|
||||||
|
NLuint nv = facet_nb_vertices(f);
|
||||||
|
out << "f ";
|
||||||
|
for (NLuint lv = 0; lv < nv; ++lv) {
|
||||||
|
NLuint v = facet_vertex(f, lv);
|
||||||
|
out << (v + 1) << "/" << (v + 1) << " ";
|
||||||
|
}
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
for (NLuint v = 0; v < nb_vertices(); ++v) {
|
||||||
|
if (vertex[v].locked) {
|
||||||
|
out << "# anchor " << v + 1 << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Vertex> vertex;
|
||||||
|
bool in_facet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief All the vertices associated with the facet corners.
|
||||||
|
*/
|
||||||
|
std::vector<NLuint> corner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Indicates where facets start and end within the corner
|
||||||
|
* array (facet indicence matrix is stored in the compressed row
|
||||||
|
* storage format).
|
||||||
|
* \details The corners associated with facet f are in the range
|
||||||
|
* facet_ptr[f] ... facet_ptr[f+1]-1
|
||||||
|
*/
|
||||||
|
std::vector<NLuint> facet_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes Least Squares Conformal Maps in least squares or
|
||||||
|
* spectral mode.
|
||||||
|
* \details The method is described in the following references:
|
||||||
|
* - Least Squares Conformal Maps, Levy, Petitjean, Ray, Maillot, ACM
|
||||||
|
* SIGGRAPH, 2002
|
||||||
|
* - Spectral Conformal Parameterization, Mullen, Tong, Alliez, Desbrun,
|
||||||
|
* Computer Graphics Forum (SGP conf. proc.), 2008
|
||||||
|
*/
|
||||||
|
class LSCM {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief LSCM constructor
|
||||||
|
* \param[in] M a reference to the mesh. It needs to correspond to a
|
||||||
|
* topological disk (open surface with one border and no handle).
|
||||||
|
*/
|
||||||
|
LSCM(IndexedMesh& M) :
|
||||||
|
mesh_(&M) {
|
||||||
|
spectral_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sets whether spectral mode is used.
|
||||||
|
* \details In default mode, the trivial solution (all vertices to zero)
|
||||||
|
* is avoided by locking two vertices (that are as "extremal" as possible).
|
||||||
|
* In spectral mode, the trivial solution is avoided by finding the first
|
||||||
|
* minimizer that is orthogonal to it (more elegant, but more costly).
|
||||||
|
*/
|
||||||
|
void set_spectral(bool x) {
|
||||||
|
spectral_ = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the least squares conformal map and stores it in
|
||||||
|
* the texture coordinates of the mesh.
|
||||||
|
* \details Outline of the algorithm (steps 1,2,3 are not used
|
||||||
|
* in spetral mode):
|
||||||
|
* - 1) Find an initial solution by projecting on a plane
|
||||||
|
* - 2) Lock two vertices of the mesh
|
||||||
|
* - 3) Copy the initial u,v coordinates to OpenNL
|
||||||
|
* - 4) Construct the LSCM equation with OpenNL
|
||||||
|
* - 5) Solve the equation with OpenNL
|
||||||
|
* - 6) Copy OpenNL solution to the u,v coordinates
|
||||||
|
*/
|
||||||
|
|
||||||
|
void apply() {
|
||||||
|
const int nb_eigens = 10;
|
||||||
|
nlNewContext();
|
||||||
|
if (spectral_) {
|
||||||
|
if (nlInitExtension("ARPACK")) {
|
||||||
|
std::cout << "ARPACK extension initialized" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Could not initialize ARPACK extension"
|
||||||
|
<< std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
nlEigenSolverParameteri(NL_EIGEN_SOLVER, NL_ARPACK_EXT);
|
||||||
|
nlEigenSolverParameteri(NL_NB_EIGENS, nb_eigens);
|
||||||
|
nlEnable(NL_VERBOSE);
|
||||||
|
}
|
||||||
|
NLuint nb_vertices = NLuint(mesh_->vertex.size());
|
||||||
|
if (!spectral_) {
|
||||||
|
project();
|
||||||
|
}
|
||||||
|
nlSolverParameteri(NL_NB_VARIABLES, NLint(2 * nb_vertices));
|
||||||
|
nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
|
||||||
|
nlSolverParameteri(NL_MAX_ITERATIONS, NLint(5 * nb_vertices));
|
||||||
|
if (spectral_) {
|
||||||
|
nlSolverParameterd(NL_THRESHOLD, 0.0);
|
||||||
|
} else {
|
||||||
|
nlSolverParameterd(NL_THRESHOLD, 1e-6);
|
||||||
|
}
|
||||||
|
nlBegin(NL_SYSTEM);
|
||||||
|
mesh_to_solver();
|
||||||
|
nlBegin(NL_MATRIX);
|
||||||
|
setup_lscm();
|
||||||
|
nlEnd(NL_MATRIX);
|
||||||
|
nlEnd(NL_SYSTEM);
|
||||||
|
std::cout << "Solving ..." << std::endl;
|
||||||
|
|
||||||
|
if (spectral_) {
|
||||||
|
nlEigenSolve();
|
||||||
|
for (NLuint i = 0; i < nb_eigens; ++i) {
|
||||||
|
std::cerr << "[" << i << "] " << nlGetEigenValue(i)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find first "non-zero" eigenvalue
|
||||||
|
double small_eigen = ::fabs(nlGetEigenValue(0));
|
||||||
|
eigen_ = 1;
|
||||||
|
for (NLuint i = 1; i < nb_eigens; ++i) {
|
||||||
|
if (::fabs(nlGetEigenValue(i)) / small_eigen > 1e3) {
|
||||||
|
eigen_ = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nlSolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
solver_to_mesh();
|
||||||
|
normalize_uv();
|
||||||
|
|
||||||
|
if (!spectral_) {
|
||||||
|
double time;
|
||||||
|
NLint iterations;
|
||||||
|
nlGetDoublev(NL_ELAPSED_TIME, &time);
|
||||||
|
nlGetIntegerv(NL_USED_ITERATIONS, &iterations);
|
||||||
|
std::cout << "Solver time: " << time << std::endl;
|
||||||
|
std::cout << "Used iterations: " << iterations << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlDeleteContext(nlGetCurrent());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates the LSCM equations in OpenNL.
|
||||||
|
*/
|
||||||
|
void setup_lscm() {
|
||||||
|
for (NLuint f = 0; f < mesh_->nb_facets(); ++f) {
|
||||||
|
setup_lscm(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates the LSCM equations in OpenNL, related
|
||||||
|
* with a given facet.
|
||||||
|
* \param[in] f the index of the facet.
|
||||||
|
* \details no-need to triangulate the facet,
|
||||||
|
* we do that "virtually", by creating triangles
|
||||||
|
* radiating around vertex 0 of the facet.
|
||||||
|
* (however, this may be invalid for concave facets)
|
||||||
|
*/
|
||||||
|
void setup_lscm(NLuint f) {
|
||||||
|
NLuint nv = mesh_->facet_nb_vertices(f);
|
||||||
|
for (NLuint i = 1; i < nv - 1; ++i) {
|
||||||
|
setup_conformal_map_relations(mesh_->facet_vertex(f, 0),
|
||||||
|
mesh_->facet_vertex(f, i), mesh_->facet_vertex(f, i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Computes the coordinates of the vertices of a triangle
|
||||||
|
* in a local 2D orthonormal basis of the triangle's plane.
|
||||||
|
* \param[in] p0 , p1 , p2 the 3D coordinates of the vertices of
|
||||||
|
* the triangle
|
||||||
|
* \param[out] z0 , z1 , z2 the 2D coordinates of the vertices of
|
||||||
|
* the triangle
|
||||||
|
*/
|
||||||
|
static void project_triangle(const vec3& p0, const vec3& p1, const vec3& p2,
|
||||||
|
vec2& z0, vec2& z1, vec2& z2) {
|
||||||
|
vec3 X = p1 - p0;
|
||||||
|
X.normalize();
|
||||||
|
vec3 Z = cross(X, (p2 - p0));
|
||||||
|
Z.normalize();
|
||||||
|
vec3 Y = cross(Z, X);
|
||||||
|
const vec3& O = p0;
|
||||||
|
|
||||||
|
double x0 = 0;
|
||||||
|
double y0 = 0;
|
||||||
|
double x1 = (p1 - O).length();
|
||||||
|
double y1 = 0;
|
||||||
|
double x2 = dot((p2 - O), X);
|
||||||
|
double y2 = dot((p2 - O), Y);
|
||||||
|
|
||||||
|
z0 = vec2(x0, y0);
|
||||||
|
z1 = vec2(x1, y1);
|
||||||
|
z2 = vec2(x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates the LSCM equation in OpenNL, related with
|
||||||
|
* a given triangle, specified by vertex indices.
|
||||||
|
* \param[in] v0 , v1 , v2 the indices of the three vertices of
|
||||||
|
* the triangle.
|
||||||
|
* \details Uses the geometric form of LSCM equation:
|
||||||
|
* (Z1 - Z0)(U2 - U0) = (Z2 - Z0)(U1 - U0)
|
||||||
|
* Where Uk = uk + i.vk is the complex number
|
||||||
|
* corresponding to (u,v) coords
|
||||||
|
* Zk = xk + i.yk is the complex number
|
||||||
|
* corresponding to local (x,y) coords
|
||||||
|
* There is no divide with this expression,
|
||||||
|
* this makes it more numerically stable in
|
||||||
|
* the presence of degenerate triangles.
|
||||||
|
*/
|
||||||
|
void setup_conformal_map_relations(NLuint v0, NLuint v1, NLuint v2) {
|
||||||
|
|
||||||
|
const vec3& p0 = mesh_->vertex[v0].point;
|
||||||
|
const vec3& p1 = mesh_->vertex[v1].point;
|
||||||
|
const vec3& p2 = mesh_->vertex[v2].point;
|
||||||
|
|
||||||
|
vec2 z0, z1, z2;
|
||||||
|
project_triangle(p0, p1, p2, z0, z1, z2);
|
||||||
|
vec2 z01 = z1 - z0;
|
||||||
|
vec2 z02 = z2 - z0;
|
||||||
|
double a = z01.x;
|
||||||
|
double b = z01.y;
|
||||||
|
double c = z02.x;
|
||||||
|
double d = z02.y;
|
||||||
|
assert(b == 0.0);
|
||||||
|
|
||||||
|
// Note : 2*id + 0 --> u
|
||||||
|
// 2*id + 1 --> v
|
||||||
|
NLuint u0_id = 2 * v0;
|
||||||
|
NLuint v0_id = 2 * v0 + 1;
|
||||||
|
NLuint u1_id = 2 * v1;
|
||||||
|
NLuint v1_id = 2 * v1 + 1;
|
||||||
|
NLuint u2_id = 2 * v2;
|
||||||
|
NLuint v2_id = 2 * v2 + 1;
|
||||||
|
|
||||||
|
// Note : b = 0
|
||||||
|
|
||||||
|
// Real part
|
||||||
|
nlBegin(NL_ROW);
|
||||||
|
nlCoefficient(u0_id, -a + c);
|
||||||
|
nlCoefficient(v0_id, b - d);
|
||||||
|
nlCoefficient(u1_id, -c);
|
||||||
|
nlCoefficient(v1_id, d);
|
||||||
|
nlCoefficient(u2_id, a);
|
||||||
|
nlEnd(NL_ROW);
|
||||||
|
|
||||||
|
// Imaginary part
|
||||||
|
nlBegin(NL_ROW);
|
||||||
|
nlCoefficient(u0_id, -b + d);
|
||||||
|
nlCoefficient(v0_id, -a + c);
|
||||||
|
nlCoefficient(u1_id, -d);
|
||||||
|
nlCoefficient(v1_id, -c);
|
||||||
|
nlCoefficient(v2_id, a);
|
||||||
|
nlEnd(NL_ROW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copies u,v coordinates from OpenNL solver to the mesh.
|
||||||
|
*/
|
||||||
|
void solver_to_mesh() {
|
||||||
|
for (NLuint i = 0; i < mesh_->vertex.size(); ++i) {
|
||||||
|
Vertex& it = mesh_->vertex[i];
|
||||||
|
double u =
|
||||||
|
spectral_ ?
|
||||||
|
nlMultiGetVariable(2 * i, eigen_) :
|
||||||
|
nlGetVariable(2 * i);
|
||||||
|
double v =
|
||||||
|
spectral_ ?
|
||||||
|
nlMultiGetVariable(2 * i + 1, eigen_) :
|
||||||
|
nlGetVariable(2 * i + 1);
|
||||||
|
it.tex_coord = vec2(u, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Translates and scales tex coords in such a way that they fit
|
||||||
|
* within the unit square.
|
||||||
|
*/
|
||||||
|
void normalize_uv() {
|
||||||
|
double u_min = 1e30, v_min = 1e30, u_max = -1e30, v_max = -1e30;
|
||||||
|
for (NLuint i = 0; i < mesh_->vertex.size(); ++i) {
|
||||||
|
u_min = std::min(u_min, mesh_->vertex[i].tex_coord.x);
|
||||||
|
v_min = std::min(v_min, mesh_->vertex[i].tex_coord.y);
|
||||||
|
u_max = std::max(u_max, mesh_->vertex[i].tex_coord.x);
|
||||||
|
v_max = std::max(v_max, mesh_->vertex[i].tex_coord.y);
|
||||||
|
}
|
||||||
|
double l = std::max(u_max - u_min, v_max - v_min);
|
||||||
|
for (NLuint i = 0; i < mesh_->vertex.size(); ++i) {
|
||||||
|
mesh_->vertex[i].tex_coord.x -= u_min;
|
||||||
|
mesh_->vertex[i].tex_coord.x /= l;
|
||||||
|
mesh_->vertex[i].tex_coord.y -= v_min;
|
||||||
|
mesh_->vertex[i].tex_coord.y /= l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copies u,v coordinates from the mesh to OpenNL solver.
|
||||||
|
*/
|
||||||
|
void mesh_to_solver() {
|
||||||
|
for (NLuint i = 0; i < mesh_->vertex.size(); ++i) {
|
||||||
|
Vertex& it = mesh_->vertex[i];
|
||||||
|
double u = it.tex_coord.x;
|
||||||
|
double v = it.tex_coord.y;
|
||||||
|
nlSetVariable(2 * i, u);
|
||||||
|
nlSetVariable(2 * i + 1, v);
|
||||||
|
if (!spectral_ && it.locked) {
|
||||||
|
nlLockVariable(2 * i);
|
||||||
|
nlLockVariable(2 * i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Chooses an initial solution, and locks two vertices.
|
||||||
|
*/
|
||||||
|
void project() {
|
||||||
|
// Get bbox
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
double xmin = 1e30;
|
||||||
|
double ymin = 1e30;
|
||||||
|
double zmin = 1e30;
|
||||||
|
double xmax = -1e30;
|
||||||
|
double ymax = -1e30;
|
||||||
|
double zmax = -1e30;
|
||||||
|
|
||||||
|
for (i = 0; i < mesh_->vertex.size(); i++) {
|
||||||
|
const Vertex& v = mesh_->vertex[i];
|
||||||
|
xmin = std::min(v.point.x, xmin);
|
||||||
|
ymin = std::min(v.point.y, xmin);
|
||||||
|
zmin = std::min(v.point.z, xmin);
|
||||||
|
|
||||||
|
xmax = std::max(v.point.x, xmin);
|
||||||
|
ymax = std::max(v.point.y, xmin);
|
||||||
|
zmax = std::max(v.point.z, xmin);
|
||||||
|
}
|
||||||
|
|
||||||
|
double dx = xmax - xmin;
|
||||||
|
double dy = ymax - ymin;
|
||||||
|
double dz = zmax - zmin;
|
||||||
|
|
||||||
|
vec3 V1, V2;
|
||||||
|
|
||||||
|
// Find shortest bbox axis
|
||||||
|
if (dx < dy && dx < dz) {
|
||||||
|
if (dy > dz) {
|
||||||
|
V1 = vec3(0, 1, 0);
|
||||||
|
V2 = vec3(0, 0, 1);
|
||||||
|
} else {
|
||||||
|
V2 = vec3(0, 1, 0);
|
||||||
|
V1 = vec3(0, 0, 1);
|
||||||
|
}
|
||||||
|
} else if (dy < dx && dy < dz) {
|
||||||
|
if (dx > dz) {
|
||||||
|
V1 = vec3(1, 0, 0);
|
||||||
|
V2 = vec3(0, 0, 1);
|
||||||
|
} else {
|
||||||
|
V2 = vec3(1, 0, 0);
|
||||||
|
V1 = vec3(0, 0, 1);
|
||||||
|
}
|
||||||
|
} else if (dz < dx && dz < dy) {
|
||||||
|
if (dx > dy) {
|
||||||
|
V1 = vec3(1, 0, 0);
|
||||||
|
V2 = vec3(0, 1, 0);
|
||||||
|
} else {
|
||||||
|
V2 = vec3(1, 0, 0);
|
||||||
|
V1 = vec3(0, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Project onto shortest bbox axis,
|
||||||
|
// and lock extrema vertices
|
||||||
|
|
||||||
|
Vertex* vxmin = NULL;
|
||||||
|
double umin = 1e30;
|
||||||
|
Vertex* vxmax = NULL;
|
||||||
|
double umax = -1e30;
|
||||||
|
|
||||||
|
for (i = 0; i < mesh_->vertex.size(); i++) {
|
||||||
|
Vertex& V = mesh_->vertex[i];
|
||||||
|
double u = dot(V.point, V1);
|
||||||
|
double v = dot(V.point, V2);
|
||||||
|
V.tex_coord = vec2(u, v);
|
||||||
|
if (u < umin) {
|
||||||
|
vxmin = &V;
|
||||||
|
umin = u;
|
||||||
|
}
|
||||||
|
if (u > umax) {
|
||||||
|
vxmax = &V;
|
||||||
|
umax = u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vxmin->locked = true;
|
||||||
|
vxmax->locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexedMesh* mesh_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief true if spectral mode is used,
|
||||||
|
* false if locked least squares mode is used.
|
||||||
|
*/
|
||||||
|
bool spectral_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief In spectral mode, the index of the first
|
||||||
|
* non-zero eigenvalue.
|
||||||
|
*/
|
||||||
|
NLuint eigen_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
nlInitialize(argc, argv);
|
||||||
|
IndexedMesh mesh;
|
||||||
|
std::cout << "Loading " << filenames[0] << " ..." << std::endl;
|
||||||
|
mesh.load(filenames[0]);
|
||||||
|
|
||||||
|
LSCM lscm(mesh);
|
||||||
|
lscm.set_spectral(spectral);
|
||||||
|
lscm.apply();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
1017
vendor/Marching.h
vendored
Normal file
1017
vendor/Marching.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
428
vendor/MarchingCube.h
vendored
Normal file
428
vendor/MarchingCube.h
vendored
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
/*
|
||||||
|
* MarchingCube.h
|
||||||
|
*
|
||||||
|
* Created on: 19.10.2017
|
||||||
|
* Author: gmueller
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MARCHINGCUBE_H_
|
||||||
|
#define MARCHINGCUBE_H_
|
||||||
|
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using glm::vec3;
|
||||||
|
|
||||||
|
typedef glm::vec3 XYZ;
|
||||||
|
|
||||||
|
struct TRIANGLE {
|
||||||
|
XYZ p[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GRIDCELL {
|
||||||
|
XYZ p[8];
|
||||||
|
double val[8];
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Linearly interpolate the position where an isosurface cuts
|
||||||
|
an edge between two vertices, each with their own scalar value
|
||||||
|
*/
|
||||||
|
XYZ VertexInterp(double isolevel, XYZ p1, XYZ p2, double valp1, double valp2) {
|
||||||
|
double mu;
|
||||||
|
XYZ p;
|
||||||
|
|
||||||
|
if (fabs(isolevel - valp1) < 0.00001)
|
||||||
|
return (p1);
|
||||||
|
if (fabs(isolevel - valp2) < 0.00001)
|
||||||
|
return (p2);
|
||||||
|
if (fabs(valp1 - valp2) < 0.00001)
|
||||||
|
return (p1);
|
||||||
|
|
||||||
|
mu = (isolevel - valp1) / (valp2 - valp1);
|
||||||
|
p.x = p1.x + mu * (p2.x - p1.x);
|
||||||
|
p.y = p1.y + mu * (p2.y - p1.y);
|
||||||
|
p.z = p1.z + mu * (p2.z - p1.z);
|
||||||
|
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Given a grid cell and an isolevel, calculate the triangular
|
||||||
|
facets required to represent the isosurface through the cell.
|
||||||
|
Return the number of triangular facets, the array "triangles"
|
||||||
|
will be loaded up with the vertices at most 5 triangular facets.
|
||||||
|
0 will be returned if the grid cell is either totally above
|
||||||
|
of totally below the isolevel.
|
||||||
|
*/
|
||||||
|
int Polygonise(GRIDCELL &grid, double isolevel, TRIANGLE *triangles) {
|
||||||
|
int i, ntriang;
|
||||||
|
int cubeindex;
|
||||||
|
XYZ vertlist[12];
|
||||||
|
|
||||||
|
int edgeTable[256] = { 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
|
||||||
|
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99,
|
||||||
|
0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f,
|
||||||
|
0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33, 0x13a, 0x636,
|
||||||
|
0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33,
|
||||||
|
0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
|
||||||
|
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460,
|
||||||
|
0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f,
|
||||||
|
0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa,
|
||||||
|
0x1f6, 0xff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3,
|
||||||
|
0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,
|
||||||
|
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0,
|
||||||
|
0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc, 0xfcc, 0xec5, 0xdcf,
|
||||||
|
0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca,
|
||||||
|
0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3,
|
||||||
|
0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55,
|
||||||
|
0xe5c, 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0,
|
||||||
|
0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff,
|
||||||
|
0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a,
|
||||||
|
0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663,
|
||||||
|
0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5,
|
||||||
|
0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0, 0xd30,
|
||||||
|
0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435,
|
||||||
|
0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a,
|
||||||
|
0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a,
|
||||||
|
0x393, 0x99, 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905,
|
||||||
|
0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 };
|
||||||
|
int triTable[256][16] = {
|
||||||
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
|
||||||
|
{
|
||||||
|
4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 4,
|
||||||
|
1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, { 1,
|
||||||
|
2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, { 8,
|
||||||
|
4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, {
|
||||||
|
3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, { 4, 7,
|
||||||
|
8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, { 4, 7,
|
||||||
|
11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, { 9,
|
||||||
|
5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0,
|
||||||
|
5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, { 5, 2,
|
||||||
|
10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, { 2, 10,
|
||||||
|
5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, { 9, 5, 4,
|
||||||
|
2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 11,
|
||||||
|
2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, { 0, 5,
|
||||||
|
4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, { 2, 1,
|
||||||
|
5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, { 10, 3,
|
||||||
|
11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, { 4, 9,
|
||||||
|
5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, { 5, 4,
|
||||||
|
0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, { 5, 4,
|
||||||
|
8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, { 9,
|
||||||
|
7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, { 10, 1,
|
||||||
|
2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, { 8, 0, 2,
|
||||||
|
8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, { 2, 10, 5, 2,
|
||||||
|
5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, { 7, 9, 5, 7,
|
||||||
|
8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 7, 9,
|
||||||
|
7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, { 2, 3, 11, 0, 1,
|
||||||
|
8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, { 11, 2, 1, 11, 1, 7,
|
||||||
|
7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 8, 8, 5, 7,
|
||||||
|
10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, { 5, 7, 0, 5, 0, 9,
|
||||||
|
7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, { 11, 10, 0, 11, 0, 3,
|
||||||
|
10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, { 11, 10, 5, 7, 11, 5, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 10, 6, 5, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 3, 5,
|
||||||
|
10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 9, 0, 1,
|
||||||
|
5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 8,
|
||||||
|
3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, { 1, 6,
|
||||||
|
5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1,
|
||||||
|
6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, { 9,
|
||||||
|
6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, { 5,
|
||||||
|
9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, { 2, 3,
|
||||||
|
11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, { 5,
|
||||||
|
10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, { 6,
|
||||||
|
3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, { 0,
|
||||||
|
8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, { 3,
|
||||||
|
11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, { 6, 5,
|
||||||
|
9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, { 5,
|
||||||
|
10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, { 6,
|
||||||
|
1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, { 1,
|
||||||
|
2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, { 8, 4,
|
||||||
|
7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, { 7, 3, 9,
|
||||||
|
7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, { 3, 11, 2, 7, 8,
|
||||||
|
4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, { 5, 10, 6, 4, 7,
|
||||||
|
2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, { 0, 1, 9, 4, 7, 8,
|
||||||
|
2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, { 9, 2, 1, 9, 11, 2,
|
||||||
|
9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, { 8, 4, 7, 3, 11, 5, 3,
|
||||||
|
5, 1, 5, 11, 6, -1, -1, -1, -1 }, { 5, 1, 11, 5, 11, 6, 1,
|
||||||
|
0, 11, 7, 11, 4, 0, 4, 11, -1 }, { 0, 5, 9, 0, 6, 5, 0, 3,
|
||||||
|
6, 11, 6, 3, 8, 4, 7, -1 }, { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7,
|
||||||
|
11, 9, -1, -1, -1, -1 }, { 10, 4, 9, 6, 4, 10, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1 }, { 4, 10, 6, 4, 9, 10, 0, 8, 3,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1 }, { 10, 0, 1, 10, 6, 0, 6, 4, 0,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1 }, { 8, 3, 1, 8, 1, 6, 8, 6, 4,
|
||||||
|
6, 1, 10, -1, -1, -1, -1 }, { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6,
|
||||||
|
4, -1, -1, -1, -1 }, { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4,
|
||||||
|
10, 6, -1, -1, -1, -1 }, { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1,
|
||||||
|
10, -1, -1, -1, -1 }, { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1,
|
||||||
|
11, 8, 11, 1, -1 }, { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3,
|
||||||
|
-1, -1, -1, -1 }, { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6,
|
||||||
|
4, 1, -1 }, { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1 }, { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1 }, { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7,
|
||||||
|
10, -1, -1, -1, -1 }, { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8,
|
||||||
|
0, -1, -1, -1, -1 }, { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7,
|
||||||
|
-1, -1, -1, -1 }, { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7,
|
||||||
|
3, 9, -1 }, { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1 }, { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1 }, { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1,
|
||||||
|
-1, -1, -1 }, { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10,
|
||||||
|
7, -1 }, { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11,
|
||||||
|
-1 }, { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1,
|
||||||
|
-1 }, { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 },
|
||||||
|
{ 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 7,
|
||||||
|
8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, { 7,
|
||||||
|
11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 8,
|
||||||
|
1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, { 10,
|
||||||
|
1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, {
|
||||||
|
7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, { 2, 7,
|
||||||
|
6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, { 1, 6,
|
||||||
|
2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, { 10, 7, 6,
|
||||||
|
10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, { 10, 7, 6,
|
||||||
|
1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, { 0, 3, 7, 0,
|
||||||
|
7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, { 7, 6, 10, 7,
|
||||||
|
10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, { 6, 8, 4,
|
||||||
|
11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 6,
|
||||||
|
11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, { 8, 6,
|
||||||
|
11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, { 9, 4,
|
||||||
|
6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, { 6, 8, 4,
|
||||||
|
6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 2,
|
||||||
|
10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, { 4, 11,
|
||||||
|
8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, { 10, 9,
|
||||||
|
3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, { 8, 2, 3, 8,
|
||||||
|
4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, { 0, 4, 2, 4,
|
||||||
|
6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 9, 0,
|
||||||
|
2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, { 1, 9, 4, 1,
|
||||||
|
4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, { 8, 1, 3, 8,
|
||||||
|
6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, { 10, 1, 0, 10,
|
||||||
|
0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, { 4, 6, 3, 4,
|
||||||
|
3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, { 10, 9, 4, 6, 10,
|
||||||
|
4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 4, 9, 5, 7,
|
||||||
|
6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 3,
|
||||||
|
4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, { 5, 0, 1,
|
||||||
|
5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, { 11, 7, 6,
|
||||||
|
8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, { 9, 5, 4, 10,
|
||||||
|
1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, { 6, 11, 7, 1,
|
||||||
|
2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, { 7, 6, 11, 5, 4,
|
||||||
|
10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, { 3, 4, 8, 3, 5, 4,
|
||||||
|
3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, { 7, 2, 3, 7, 6, 2, 5, 4,
|
||||||
|
9, -1, -1, -1, -1, -1, -1, -1 }, { 9, 5, 4, 0, 8, 6, 0, 6,
|
||||||
|
2, 6, 8, 7, -1, -1, -1, -1 }, { 3, 6, 2, 3, 7, 6, 1, 5, 0,
|
||||||
|
5, 4, 0, -1, -1, -1, -1 }, { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4,
|
||||||
|
8, 5, 1, 5, 8, -1 }, { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7,
|
||||||
|
-1, -1, -1, -1 }, { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9,
|
||||||
|
5, 4, -1 }, { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7,
|
||||||
|
10, -1 }, { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1,
|
||||||
|
-1, -1 }, { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1 }, { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1,
|
||||||
|
-1 }, { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1,
|
||||||
|
-1 }, { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1 }, { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1,
|
||||||
|
-1 },
|
||||||
|
{ 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, { 11, 8, 5,
|
||||||
|
11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, { 6, 11, 3, 6,
|
||||||
|
3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, { 5, 8, 9, 5, 2,
|
||||||
|
8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, { 9, 5, 6, 9, 6, 0,
|
||||||
|
0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, { 1, 5, 8, 1, 8, 0,
|
||||||
|
5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, { 1, 5, 6, 2, 1, 6, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1 }, { 1, 3, 6, 1, 6, 10, 3, 8,
|
||||||
|
6, 5, 6, 9, 8, 9, 6, -1 }, { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5,
|
||||||
|
6, 0, -1, -1, -1, -1 }, { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 10, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1 }, { 11, 5, 10, 7, 5, 11, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 11, 5, 10, 11, 7, 5,
|
||||||
|
8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, { 5, 11, 7, 5, 10,
|
||||||
|
11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, { 10, 7, 5, 10,
|
||||||
|
11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, { 11, 1, 2, 11,
|
||||||
|
7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, { 0, 8, 3, 1,
|
||||||
|
2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, { 9, 7, 5, 9, 2,
|
||||||
|
7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, { 7, 5, 2, 7, 2, 11,
|
||||||
|
5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, { 2, 5, 10, 2, 3, 5, 3, 7,
|
||||||
|
5, -1, -1, -1, -1, -1, -1, -1 }, { 8, 2, 0, 8, 5, 2, 8, 7,
|
||||||
|
5, 10, 2, 5, -1, -1, -1, -1 }, { 9, 0, 1, 5, 10, 3, 5, 3, 7,
|
||||||
|
3, 10, 2, -1, -1, -1, -1 }, { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10,
|
||||||
|
2, 5, 7, 5, 2, -1 }, { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 5, 8, 4, 5, 10, 8, 10, 11, 8,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1 }, { 5, 0, 4, 5, 11, 0, 5, 10,
|
||||||
|
11, 11, 3, 0, -1, -1, -1, -1 }, { 0, 1, 9, 8, 4, 10, 8, 10,
|
||||||
|
11, 10, 4, 5, -1, -1, -1, -1 }, { 10, 11, 4, 10, 4, 5, 11,
|
||||||
|
3, 4, 9, 4, 1, 3, 1, 4, -1 }, { 2, 5, 1, 2, 8, 5, 2, 11, 8,
|
||||||
|
4, 5, 8, -1, -1, -1, -1 }, { 0, 4, 11, 0, 11, 3, 4, 5, 11,
|
||||||
|
2, 11, 1, 5, 1, 11, -1 }, { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4,
|
||||||
|
5, 8, 11, 8, 5, -1 }, { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3,
|
||||||
|
8, 4, -1, -1, -1, -1 }, { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4,
|
||||||
|
5, 8, 0, 1, 9, -1 }, { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2,
|
||||||
|
-1, -1, -1, -1 }, { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1 }, { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5,
|
||||||
|
-1, -1, -1, -1 }, { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9,
|
||||||
|
10, 11, -1, -1, -1, -1 }, { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7,
|
||||||
|
4, 11, -1, -1, -1, -1 }, { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4,
|
||||||
|
11, 10, 11, 4, -1 }, { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1,
|
||||||
|
2, -1, -1, -1, -1 }, { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11,
|
||||||
|
1, 0, 8, 3, -1 }, { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1 }, { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4,
|
||||||
|
-1, -1, -1, -1 }, { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1,
|
||||||
|
-1, -1, -1 }, { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0,
|
||||||
|
7, -1 }, { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10,
|
||||||
|
-1 }, { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1 }, { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1 }, { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1,
|
||||||
|
-1 }, { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1 }, { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1 }, { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1 }, { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1 }, { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1 }, { 3, 1, 10, 11, 3, 10, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1 }, { 1, 2, 11, 1, 11, 9, 9, 11,
|
||||||
|
8, -1, -1, -1, -1, -1, -1, -1 }, { 3, 0, 9, 3, 9, 11, 1, 2,
|
||||||
|
9, 2, 11, 9, -1, -1, -1, -1 }, { 0, 2, 11, 8, 0, 11, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1 }, { 3, 2, 11, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 2, 3, 8, 2, 8,
|
||||||
|
10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, { 9, 10, 2, 0,
|
||||||
|
9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 2, 3, 8,
|
||||||
|
2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, { 1, 10, 2,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { 1,
|
||||||
|
3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||||
|
{ 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, {
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1 } };
|
||||||
|
|
||||||
|
/*
|
||||||
|
Determine the index into the edge table which
|
||||||
|
tells us which vertices are inside of the surface
|
||||||
|
*/
|
||||||
|
cubeindex = 0;
|
||||||
|
if (grid.val[0] < isolevel)
|
||||||
|
cubeindex |= 1;
|
||||||
|
if (grid.val[1] < isolevel)
|
||||||
|
cubeindex |= 2;
|
||||||
|
if (grid.val[2] < isolevel)
|
||||||
|
cubeindex |= 4;
|
||||||
|
if (grid.val[3] < isolevel)
|
||||||
|
cubeindex |= 8;
|
||||||
|
if (grid.val[4] < isolevel)
|
||||||
|
cubeindex |= 16;
|
||||||
|
if (grid.val[5] < isolevel)
|
||||||
|
cubeindex |= 32;
|
||||||
|
if (grid.val[6] < isolevel)
|
||||||
|
cubeindex |= 64;
|
||||||
|
if (grid.val[7] < isolevel)
|
||||||
|
cubeindex |= 128;
|
||||||
|
|
||||||
|
/* Cube is entirely in/out of the surface */
|
||||||
|
if (edgeTable[cubeindex] == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Find the vertices where the surface intersects the cube */
|
||||||
|
if (edgeTable[cubeindex] & 1)
|
||||||
|
vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0],
|
||||||
|
grid.val[1]);
|
||||||
|
if (edgeTable[cubeindex] & 2)
|
||||||
|
vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1],
|
||||||
|
grid.val[2]);
|
||||||
|
if (edgeTable[cubeindex] & 4)
|
||||||
|
vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2],
|
||||||
|
grid.val[3]);
|
||||||
|
if (edgeTable[cubeindex] & 8)
|
||||||
|
vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3],
|
||||||
|
grid.val[0]);
|
||||||
|
if (edgeTable[cubeindex] & 16)
|
||||||
|
vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4],
|
||||||
|
grid.val[5]);
|
||||||
|
if (edgeTable[cubeindex] & 32)
|
||||||
|
vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5],
|
||||||
|
grid.val[6]);
|
||||||
|
if (edgeTable[cubeindex] & 64)
|
||||||
|
vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6],
|
||||||
|
grid.val[7]);
|
||||||
|
if (edgeTable[cubeindex] & 128)
|
||||||
|
vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7],
|
||||||
|
grid.val[4]);
|
||||||
|
if (edgeTable[cubeindex] & 256)
|
||||||
|
vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0],
|
||||||
|
grid.val[4]);
|
||||||
|
if (edgeTable[cubeindex] & 512)
|
||||||
|
vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1],
|
||||||
|
grid.val[5]);
|
||||||
|
if (edgeTable[cubeindex] & 1024)
|
||||||
|
vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2],
|
||||||
|
grid.val[6]);
|
||||||
|
if (edgeTable[cubeindex] & 2048)
|
||||||
|
vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3],
|
||||||
|
grid.val[7]);
|
||||||
|
|
||||||
|
// std::cout << cubeindex << std::endl;
|
||||||
|
|
||||||
|
/* Create the triangle */
|
||||||
|
ntriang = 0;
|
||||||
|
for (i = 0; triTable[cubeindex][i] != -1; i += 3) {
|
||||||
|
triangles[ntriang].p[0] = vertlist[triTable[cubeindex][i]];
|
||||||
|
triangles[ntriang].p[1] = vertlist[triTable[cubeindex][i + 1]];
|
||||||
|
triangles[ntriang].p[2] = vertlist[triTable[cubeindex][i + 2]];
|
||||||
|
ntriang++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ntriang);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MARCHINGCUBE_H_ */
|
796
vendor/MarchingTetrahedon.h
vendored
Normal file
796
vendor/MarchingTetrahedon.h
vendored
Normal file
@ -0,0 +1,796 @@
|
|||||||
|
/*
|
||||||
|
* MarchingTetrahedon.h
|
||||||
|
*
|
||||||
|
* Created on: 20.10.2017
|
||||||
|
* Author: gmueller
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MARCHINGTETRAHEDON_H_
|
||||||
|
#define MARCHINGTETRAHEDON_H_
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct Voxel {
|
||||||
|
Voxel() :
|
||||||
|
density(rand() % 20 + 40), material(0) {
|
||||||
|
}
|
||||||
|
int density; /*1..100*/
|
||||||
|
int material; /*id's will be given*/
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
int width = 1366, height = 768;
|
||||||
|
float moving = 0;
|
||||||
|
float* dispArr;
|
||||||
|
int dispArrSize;
|
||||||
|
int frame = 0;
|
||||||
|
int i = 0, j = 0, k = 0;
|
||||||
|
Voxel*** field;
|
||||||
|
GLuint texture;
|
||||||
|
bool running = true;
|
||||||
|
|
||||||
|
cameraT cam(Vector3D(__MAPSIZE__ - 2, __MAPSIZE__ - 2, __MAPSIZE__ - 2),
|
||||||
|
Vector3D(0, 0, 0));
|
||||||
|
int ghostX, ghostY;
|
||||||
|
|
||||||
|
/*GL_N3F_V3F*/
|
||||||
|
/*[Nx][Ny][Nz][Vx][Vy][Vz]*/
|
||||||
|
float* vertices;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*The coordinates, the nubered tetrahedrons and the description are in the blender file named tetrahedrons.blend*/
|
||||||
|
void marchingTetrahedrons(Voxel v0, Voxel v1, Voxel v2, Voxel v3, float **verts,
|
||||||
|
int size, int* current, int tetrahedron) {
|
||||||
|
/*to be precise: the verts array currently is: [vertices][coordinates] = [n][6]
|
||||||
|
so the size represents the number of vertices*/
|
||||||
|
/*first we find out how many lands are in this tetrahedron(max is 4)*/
|
||||||
|
int count = 0;
|
||||||
|
if (v0.material != 0)
|
||||||
|
count++;
|
||||||
|
if (v1.material != 0)
|
||||||
|
count++;
|
||||||
|
if (v2.material != 0)
|
||||||
|
count++;
|
||||||
|
if (v3.material != 0)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
/*let's decide the density of each material*/
|
||||||
|
float v0d = 1 - (float) v0.density / 100;
|
||||||
|
float v1d = 1 - (float) v1.density / 100;
|
||||||
|
float v2d = 1 - (float) v2.density / 100;
|
||||||
|
float v3d = 1 - (float) v3.density / 100;
|
||||||
|
/*depending on the number we extract the cases*/
|
||||||
|
switch (count) {
|
||||||
|
case 0:
|
||||||
|
case 4:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
/*One voxel has material*/
|
||||||
|
if (v0.material != 0) { /*03,02,01*/
|
||||||
|
if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
/*correct tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
/*wrong tetrahedrons for this winding: 2,5*/
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v1.material != 0) { /*01,13,12*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v2.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v2.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v2.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v2.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v2.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v2.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v2.material != 0) { /*02,12,23*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 3 || tetrahedron == 1 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v3.material != 0) { /*03,32,31*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v2.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v2.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v2.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v1.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v1.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v1.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v1.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v1.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v1.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v2.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v2.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v2.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
/*two voxels have material*/
|
||||||
|
if (v0.material != 0 && v3.material != 0) { /*01,02,31;31,02,32*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v1.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v1.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v1.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v0d) + v0.x * v0d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v0d) + v0.y * v0d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v0d) + v0.z * v0d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v2.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v2.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v2.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 4 || tetrahedron == 1 || tetrahedron == 3
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v1.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v1.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v1.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v2.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v2.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v2.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v0d) + v0.x * v0d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v0d) + v0.y * v0d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v0d) + v0.z * v0d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v1.material != 0 && v2.material != 0) { /*13,32,02;02,01,13*/
|
||||||
|
if (tetrahedron == 1 || tetrahedron == 4 || tetrahedron == 6
|
||||||
|
|| tetrahedron == 3) {
|
||||||
|
/*correct tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
/*wrong tetrahedrons for this winding: 2,5*/
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v3.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v3.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v3.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v3.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v2.material != 0 && v3.material != 0) { /*03,02,13;13,02,12*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v0.material != 0 && v1.material != 0) { /*03,02,13;13,02,12*/
|
||||||
|
if (tetrahedron == 3 || tetrahedron == 6 || tetrahedron == 1
|
||||||
|
|| tetrahedron == 4) {
|
||||||
|
/*correct tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
/*wrong tetrahedrons for this winding: 2,5*/
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v2.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v2.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v2.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v2.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v2.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v2.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v1.material != 0 && v3.material != 0) { /*01,12,32;32,30,01*/
|
||||||
|
if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
/*correct tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
/*wrong tetrahedrons for this winding: 2,5*/
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v2.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v2.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v2.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v0.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v0.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v0.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v2.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v2.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v2.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v3.x * v3d + v0.x * (1 - v3d));
|
||||||
|
verts[(*current)][4] = (v3.y * v3d + v0.y * (1 - v3d));
|
||||||
|
verts[(*current)][5] = (v3.z * v3d + v0.z * (1 - v3d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v0.material != 0 && v2.material != 0) { /*01,03,32;32,12,01*/
|
||||||
|
if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
/*correct tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
/*wrong tetrahedrons for this winding: 2,5*/
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 5 || tetrahedron == 2) {
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
/*three voxels have material*/
|
||||||
|
if (v0.material == 0) { /*03,01,02*/
|
||||||
|
if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
/*correct tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
/*wrong tetrahedrons for this winding: 2,5*/
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v0.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v0.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v1.material == 0) { /*10,12,13*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * (1 - v2d) + v2.x * v2d);
|
||||||
|
verts[(*current)][4] = (v1.y * (1 - v2d) + v2.y * v2d);
|
||||||
|
verts[(*current)][5] = (v1.z * (1 - v2d) + v2.z * v2d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v1.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v1.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v1.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v2.material == 0) { /*20,23,21*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 1 || tetrahedron == 3 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v1d) + v1.x * v1d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v1d) + v1.y * v1d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v1d) + v1.z * v1d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * (1 - v3d) + v3.x * v3d);
|
||||||
|
verts[(*current)][4] = (v2.y * (1 - v3d) + v3.y * v3d);
|
||||||
|
verts[(*current)][5] = (v2.z * (1 - v3d) + v3.z * v3d);
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v2.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v2.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v2.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
} else if (v3.material == 0) { /*30,31,32*/
|
||||||
|
if (tetrahedron == 2 || tetrahedron == 5) {
|
||||||
|
/*correct tetrahedrons for this winding: 2,5*/
|
||||||
|
/*wrong tetrahedrons for this winding: 1,3,4,6*/
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
} else if (tetrahedron == 3 || tetrahedron == 1 || tetrahedron == 4
|
||||||
|
|| tetrahedron == 6) {
|
||||||
|
verts[(*current)][3] = (v2.x * v2d + v3.x * (1 - v2d));
|
||||||
|
verts[(*current)][4] = (v2.y * v2d + v3.y * (1 - v2d));
|
||||||
|
verts[(*current)][5] = (v2.z * v2d + v3.z * (1 - v2d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v1.x * v1d + v3.x * (1 - v1d));
|
||||||
|
verts[(*current)][4] = (v1.y * v1d + v3.y * (1 - v1d));
|
||||||
|
verts[(*current)][5] = (v1.z * v1d + v3.z * (1 - v1d));
|
||||||
|
(*current) = (*current) + 1;
|
||||||
|
verts[(*current)][3] = (v0.x * v0d + v3.x * (1 - v0d));
|
||||||
|
verts[(*current)][4] = (v0.y * v0d + v3.y * (1 - v0d));
|
||||||
|
verts[(*current)][5] = (v0.z * v0d + v3.z * (1 - v0d));
|
||||||
|
(*current) = (*current) + 1;/**/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float** generateVertices(Voxel*** inField, int* size) {
|
||||||
|
/*size means how many vertices are going to be in the array*/
|
||||||
|
/*testdata will be just squares, so there will be n*3*2 vertices */
|
||||||
|
int count = 0;
|
||||||
|
int current = 0;
|
||||||
|
float** verts;
|
||||||
|
float** tverts;
|
||||||
|
|
||||||
|
/*at maximum we have (roughly) __MAPSIZE__*__MAPSIZE__*__MAPSIZE__ cubes, all of which can use
|
||||||
|
(roughly) 6 tetrahedrons, and every tetrahedrons maximum triangle count is 2. every tringle has 3 vertices.
|
||||||
|
Every vertex will have 6 coordinates(3 space coordinates, 3 normal vector coordinates)
|
||||||
|
Considering all this, an estimated maximum we will have __MAPSIZE__*__MAPSIZE__*__MAPSIZE__*6*2*3*6.
|
||||||
|
That's 27000000. Holy shit.
|
||||||
|
Here we will use [__MAPSIZE__*__MAPSIZE__*__MAPSIZE__*6*2*3] elements as vertices, and [6] for coordinates
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*reserve memory for the array*/
|
||||||
|
count = __MAPSIZE__ * __MAPSIZE__ * __MAPSIZE__ * 6 * 2 * 3;
|
||||||
|
tverts = new float*[count];
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
tverts[i] = new float[6];
|
||||||
|
|
||||||
|
/*go through the field cube to cube. A cube will have an edge of 1.*/
|
||||||
|
for (i = 0; i < __MAPSIZE__ - 1; i++)
|
||||||
|
for (j = 0; j < __MAPSIZE__ - 1; j++)
|
||||||
|
for (k = 0; k < __MAPSIZE__ - 1; k++) {
|
||||||
|
/*and we call the tetrahedrons to the 8 vertices of the cube*/
|
||||||
|
/*!Thank you paul Burke! (work needed in the booklet)
|
||||||
|
PolygoniseTri(grid,iso,triangles,0,2,3,7);
|
||||||
|
PolygoniseTri(grid,iso,triangles,0,2,6,7);
|
||||||
|
PolygoniseTri(grid,iso,triangles,0,4,6,7);
|
||||||
|
|
||||||
|
PolygoniseTri(grid,iso,triangles,0,6,1,2);
|
||||||
|
PolygoniseTri(grid,iso,triangles,0,6,1,4);
|
||||||
|
PolygoniseTri(grid,iso,triangles,5,6,1,4);
|
||||||
|
*/
|
||||||
|
/*1*/marchingTetrahedrons(inField[i][j][k + 1],
|
||||||
|
inField[i + 1][j][k], inField[i][j][k],
|
||||||
|
inField[i][j + 1][k], tverts, count, ¤t, 1);/**/
|
||||||
|
/*2*/marchingTetrahedrons(inField[i][j][k + 1],
|
||||||
|
inField[i + 1][j][k], inField[i + 1][j + 1][k],
|
||||||
|
inField[i][j + 1][k], tverts, count, ¤t, 2);/**/
|
||||||
|
/*3*/marchingTetrahedrons(inField[i][j][k + 1],
|
||||||
|
inField[i][j + 1][k + 1], inField[i + 1][j + 1][k],
|
||||||
|
inField[i][j + 1][k], tverts, count, ¤t, 3);/**/
|
||||||
|
/*4*/marchingTetrahedrons(inField[i][j][k + 1],
|
||||||
|
inField[i + 1][j + 1][k], inField[i + 1][j][k + 1],
|
||||||
|
inField[i + 1][j][k], tverts, count, ¤t, 4);/**/
|
||||||
|
/*5*/marchingTetrahedrons(inField[i][j][k + 1],
|
||||||
|
inField[i + 1][j + 1][k], inField[i + 1][j][k + 1],
|
||||||
|
inField[i][j + 1][k + 1], tverts, count, ¤t, 5);/**/
|
||||||
|
/*6*/marchingTetrahedrons(inField[i + 1][j + 1][k + 1],
|
||||||
|
inField[i + 1][j + 1][k], inField[i + 1][j][k + 1],
|
||||||
|
inField[i][j + 1][k + 1], tverts, count, ¤t, 6);/**/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*After the algorithm, I copy every triangle to the appropriate sized result array(verts)*/
|
||||||
|
verts = new float*[current];
|
||||||
|
for (i = 0; i < current; i++)
|
||||||
|
verts[i] = new float[6];
|
||||||
|
|
||||||
|
for (i = 0; i < current; i++) {
|
||||||
|
verts[i][3] = tverts[i][3];
|
||||||
|
verts[i][4] = tverts[i][4];
|
||||||
|
verts[i][5] = tverts[i][5];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] tverts;
|
||||||
|
|
||||||
|
/*and give the algorithm the number of the vertices*/
|
||||||
|
(*size) = current;
|
||||||
|
|
||||||
|
return verts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalizeVertices(float** inverts, int size) {
|
||||||
|
Vector3D tempV[3];
|
||||||
|
Vector3D tNormal;
|
||||||
|
for (i = 0; i < size; i += 3) {
|
||||||
|
|
||||||
|
tempV[0] = Vector3D(inverts[i][3], inverts[i][4], inverts[i][5]);
|
||||||
|
tempV[1] = Vector3D(inverts[i + 1][3], inverts[i + 1][4],
|
||||||
|
inverts[i + 1][5]);
|
||||||
|
tempV[2] = Vector3D(inverts[i + 2][3], inverts[i + 2][4],
|
||||||
|
inverts[i + 2][5]);
|
||||||
|
tNormal = calcNormal(tempV);
|
||||||
|
|
||||||
|
inverts[i][0] = tNormal.x;
|
||||||
|
inverts[i][1] = tNormal.y;
|
||||||
|
inverts[i][2] = tNormal.z;
|
||||||
|
|
||||||
|
inverts[i + 1][0] = tNormal.x;
|
||||||
|
inverts[i + 1][1] = tNormal.y;
|
||||||
|
inverts[i + 1][2] = tNormal.z;
|
||||||
|
|
||||||
|
inverts[i + 2][0] = tNormal.x;
|
||||||
|
inverts[i + 2][1] = tNormal.y;
|
||||||
|
inverts[i + 2][2] = tNormal.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float* arrayizeVertices(float** inverts, int size) {
|
||||||
|
float* verts;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
verts = new float[size * 6];
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
verts[count] = inverts[i][0];
|
||||||
|
verts[count + 1] = inverts[i][1];
|
||||||
|
verts[count + 2] = inverts[i][2];
|
||||||
|
verts[count + 3] = inverts[i][3];
|
||||||
|
verts[count + 4] = inverts[i][4];
|
||||||
|
verts[count + 5] = inverts[i][5];
|
||||||
|
count += 6;
|
||||||
|
}
|
||||||
|
return verts;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MARCHINGTETRAHEDON_H_ */
|
8050
vendor/OpenNL_psm.c
vendored
Normal file
8050
vendor/OpenNL_psm.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
406
vendor/OpenNL_psm.h
vendored
Normal file
406
vendor/OpenNL_psm.h
vendored
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
#define GEOGRAM_PSM
|
||||||
|
#ifndef GEO_STATIC_LIBS
|
||||||
|
#define GEO_DYNAMIC_LIBS
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2010, Bruno Levy
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * 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.
|
||||||
|
* * Neither the name of the ALICE Project-Team 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.
|
||||||
|
*
|
||||||
|
* If you modify this software, you should include a notice giving the
|
||||||
|
* name of the person performing the modification, the date of modification,
|
||||||
|
* and the reason for such modification.
|
||||||
|
*
|
||||||
|
* Contact: Bruno Levy
|
||||||
|
*
|
||||||
|
* levy@loria.fr
|
||||||
|
*
|
||||||
|
* ALICE Project
|
||||||
|
* LORIA, INRIA Lorraine,
|
||||||
|
* Campus Scientifique, BP 239
|
||||||
|
* 54506 VANDOEUVRE LES NANCY CEDEX
|
||||||
|
* FRANCE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is a PSM (pluggable software module)
|
||||||
|
* generated from the distribution of Geogram.
|
||||||
|
*
|
||||||
|
* See Geogram documentation on:
|
||||||
|
* http://alice.loria.fr/software/geogram/doc/html/index.html
|
||||||
|
*
|
||||||
|
* See documentation of the functions bundled in this PSM on:
|
||||||
|
* http://alice.loria.fr/software/geogram/doc/html/nl_8h.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******* extracted from nl_linkage.h *******/
|
||||||
|
|
||||||
|
#ifndef OPENL_LINKAGE_H
|
||||||
|
#define OPENL_LINKAGE_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GEO_DYNAMIC_LIBS
|
||||||
|
#define NL_SHARED_LIBS
|
||||||
|
#ifdef geogram_EXPORTS
|
||||||
|
#define NL_EXPORTS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#ifdef NL_SHARED_LIBS
|
||||||
|
#ifdef NL_EXPORTS
|
||||||
|
#define NLAPIENTRY __declspec( dllexport )
|
||||||
|
#else
|
||||||
|
#define NLAPIENTRY __declspec( dllimport )
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define NLAPIENTRY
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef NL_SHARED_LIBS
|
||||||
|
#define NLAPIENTRY __attribute__ ((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define NLAPIENTRY
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define NL_DEPRECATED(func) func __attribute__ ((deprecated))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define NL_DEPRECATED(func) __declspec(deprecated) func
|
||||||
|
#else
|
||||||
|
#define NL_DEPRECATED(func) func
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/******* extracted from nl.h *******/
|
||||||
|
|
||||||
|
#ifndef OPENNL_H
|
||||||
|
#define OPENNL_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NL_VERSION_4_0 1
|
||||||
|
|
||||||
|
#define NLAPI
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deactivate warnings about documentation
|
||||||
|
* We do that, because CLANG's doxygen parser does not know
|
||||||
|
* some doxygen commands that we use (retval, copydoc) and
|
||||||
|
* generates many warnings for them...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||||
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
||||||
|
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef unsigned int NLenum;
|
||||||
|
|
||||||
|
typedef unsigned char NLboolean;
|
||||||
|
|
||||||
|
typedef unsigned int NLbitfield;
|
||||||
|
|
||||||
|
typedef void NLvoid;
|
||||||
|
|
||||||
|
typedef signed char NLbyte;
|
||||||
|
|
||||||
|
typedef short NLshort;
|
||||||
|
|
||||||
|
typedef int NLint;
|
||||||
|
|
||||||
|
typedef unsigned char NLubyte;
|
||||||
|
|
||||||
|
typedef unsigned short NLushort;
|
||||||
|
|
||||||
|
typedef unsigned int NLuint;
|
||||||
|
|
||||||
|
typedef unsigned long NLulong;
|
||||||
|
|
||||||
|
typedef int NLsizei;
|
||||||
|
|
||||||
|
typedef float NLfloat;
|
||||||
|
|
||||||
|
typedef double NLdouble;
|
||||||
|
|
||||||
|
typedef void(*NLfunc)(void);
|
||||||
|
|
||||||
|
typedef void* NLContext;
|
||||||
|
|
||||||
|
#define NL_FALSE 0x0
|
||||||
|
#define NL_TRUE 0x1
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_SOLVER 0x100
|
||||||
|
|
||||||
|
#define NL_NB_VARIABLES 0x101
|
||||||
|
|
||||||
|
#define NL_LEAST_SQUARES 0x102
|
||||||
|
|
||||||
|
#define NL_MAX_ITERATIONS 0x103
|
||||||
|
|
||||||
|
#define NL_THRESHOLD 0x104
|
||||||
|
|
||||||
|
#define NL_OMEGA 0x105
|
||||||
|
|
||||||
|
#define NL_SYMMETRIC 0x106
|
||||||
|
|
||||||
|
#define NL_USED_ITERATIONS 0x107
|
||||||
|
|
||||||
|
#define NL_ERROR 0x108
|
||||||
|
|
||||||
|
#define NL_INNER_ITERATIONS 0x109
|
||||||
|
|
||||||
|
#define NL_ELAPSED_TIME 0x10a
|
||||||
|
|
||||||
|
#define NL_PRECONDITIONER 0x10b
|
||||||
|
|
||||||
|
#define NL_GFLOPS 0x10c
|
||||||
|
|
||||||
|
#define NL_NNZ 0x10d
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_NB_SYSTEMS 0x10e
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_SOLVER_DEFAULT 0x000
|
||||||
|
|
||||||
|
#define NL_CG 0x200
|
||||||
|
|
||||||
|
#define NL_BICGSTAB 0x201
|
||||||
|
|
||||||
|
#define NL_GMRES 0x202
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_PRECOND_NONE 0x000
|
||||||
|
|
||||||
|
#define NL_PRECOND_JACOBI 0x300
|
||||||
|
|
||||||
|
#define NL_PRECOND_SSOR 0x301
|
||||||
|
|
||||||
|
#define NL_PRECOND_USER 0x303
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_NORMALIZE_ROWS 0x400
|
||||||
|
|
||||||
|
#define NL_VERBOSE 0x401
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI NLContext NLAPIENTRY nlNewContext(void);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlDeleteContext(NLContext context);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlMakeCurrent(NLContext context);
|
||||||
|
|
||||||
|
NLAPI NLContext NLAPIENTRY nlGetCurrent(void);
|
||||||
|
|
||||||
|
NLAPI NLboolean NLAPIENTRY nlInitExtension(const char* extension);
|
||||||
|
|
||||||
|
NLAPI NLboolean NLAPIENTRY nlExtensionIsInitialized(const char* extension);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlInitialize(int argc, char** argv);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlSolverParameterd(NLenum pname, NLdouble param);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlSolverParameteri(NLenum pname, NLint param);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlGetBooleanv(NLenum pname, NLboolean* params);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlGetDoublev(NLenum pname, NLdouble* params);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlGetIntegerv(NLenum pname, NLint* params);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlEnable(NLenum pname);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlDisable(NLenum pname);
|
||||||
|
|
||||||
|
NLAPI NLboolean nlIsEnabled(NLenum pname);
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_FUNC_SOLVER 0x600
|
||||||
|
|
||||||
|
#define NL_FUNC_MATRIX 0x601
|
||||||
|
|
||||||
|
#define NL_FUNC_PRECONDITIONER 0x602
|
||||||
|
|
||||||
|
#define NL_FUNC_PROGRESS 0x603
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlSetFunction(NLenum pname, NLfunc param);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlGetFunction(NLenum pname, NLfunc* param);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlSetVariable(NLuint i, NLdouble value);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlMultiSetVariable(
|
||||||
|
NLuint i, NLuint k, NLdouble value
|
||||||
|
);
|
||||||
|
|
||||||
|
NLAPI NLdouble NLAPIENTRY nlGetVariable(NLuint i);
|
||||||
|
|
||||||
|
NLAPI NLdouble NLAPIENTRY nlMultiGetVariable(NLuint i, NLuint k);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlLockVariable(NLuint index);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlUnlockVariable(NLuint index);
|
||||||
|
|
||||||
|
NLAPI NLboolean NLAPIENTRY nlVariableIsLocked(NLuint index);
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_SYSTEM 0x0
|
||||||
|
|
||||||
|
#define NL_MATRIX 0x1
|
||||||
|
|
||||||
|
#define NL_ROW 0x2
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlBegin(NLenum primitive);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlEnd(NLenum primitive);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlCoefficient(NLuint i, NLdouble value);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlAddIJCoefficient(
|
||||||
|
NLuint i, NLuint j, NLdouble value
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlAddIRightHandSide(NLuint i, NLdouble value);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlMultiAddIRightHandSide(
|
||||||
|
NLuint i, NLuint k, NLdouble value
|
||||||
|
);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlRightHandSide(NLdouble value);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlMultiRightHandSide(NLuint k, NLdouble value);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlRowScaling(NLdouble value);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI NLboolean NLAPIENTRY nlSolve(void);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlUpdateRightHandSide(NLdouble* values);
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_VARIABLES_BUFFER 0x1000
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlBindBuffer(
|
||||||
|
NLenum buffer, NLuint k, void* addr, NLuint stride
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_STIFFNESS_MATRIX 0x3001
|
||||||
|
|
||||||
|
#define NL_MASS_MATRIX 0x3002
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlMatrixMode(NLenum matrix);
|
||||||
|
|
||||||
|
#define NL_NB_EIGENS NL_NB_SYSTEMS
|
||||||
|
|
||||||
|
#define NL_EIGEN_MAX_ITERATIONS NL_MAX_ITERATIONS
|
||||||
|
|
||||||
|
#define NL_EIGEN_THRESHOLD NL_THRESHOLD
|
||||||
|
|
||||||
|
#define NL_EIGEN_SOLVER 0x2000
|
||||||
|
|
||||||
|
#define NL_EIGEN_SHIFT 0x2001
|
||||||
|
|
||||||
|
#define NL_EIGEN_SHIFT_INVERT 0x2002
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlEigenSolverParameterd(
|
||||||
|
NLenum pname, NLdouble val
|
||||||
|
);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlEigenSolverParameteri(
|
||||||
|
NLenum pname, NLint val
|
||||||
|
);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlEigenSolve(void);
|
||||||
|
|
||||||
|
|
||||||
|
NLAPI double NLAPIENTRY nlGetEigenValue(NLuint i);
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (*NLprintfFunc)(const char* format, ...);
|
||||||
|
|
||||||
|
typedef int (*NLfprintfFunc)(FILE* out, const char* format, ...);
|
||||||
|
|
||||||
|
NLAPI void NLAPIENTRY nlPrintfFuncs(NLprintfFunc f1, NLfprintfFunc f2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/******* extracted from nl_ext.h *******/
|
||||||
|
|
||||||
|
#ifndef OPENNL_EXT_H
|
||||||
|
#define OPENNL_EXT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define NL_SUPERLU_EXT 0x210
|
||||||
|
#define NL_PERM_SUPERLU_EXT 0x211
|
||||||
|
#define NL_SYMMETRIC_SUPERLU_EXT 0x212
|
||||||
|
#define NL_SOLVER_USER 0x213
|
||||||
|
#define NL_CHOLMOD_EXT 0x214
|
||||||
|
#define NL_ARPACK_EXT 0x215
|
||||||
|
|
||||||
|
#define NL_CUDA_PRECOND_ILU_EXT 0x220
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
197
vendor/PerlinNoise.hpp
vendored
Normal file
197
vendor/PerlinNoise.hpp
vendored
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// siv::PerlinNoise
|
||||||
|
// Perlin noise library for modern C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2013-2016 Ryo Suzuki <reputeless@gmail.com>
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files(the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions :
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# pragma once
|
||||||
|
# include <cstdint>
|
||||||
|
# include <numeric>
|
||||||
|
# include <algorithm>
|
||||||
|
# include <random>
|
||||||
|
|
||||||
|
namespace siv
|
||||||
|
{
|
||||||
|
class PerlinNoise
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::int32_t p[512];
|
||||||
|
|
||||||
|
double fade(double t) const noexcept
|
||||||
|
{
|
||||||
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
double lerp(double t, double a, double b) const noexcept
|
||||||
|
{
|
||||||
|
return a + t * (b - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
double grad(std::int32_t hash, double x, double y, double z) const noexcept
|
||||||
|
{
|
||||||
|
const std::int32_t h = hash & 15;
|
||||||
|
const double u = h < 8 ? x : y;
|
||||||
|
const double v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
||||||
|
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit PerlinNoise(std::uint32_t seed = std::default_random_engine::default_seed)
|
||||||
|
{
|
||||||
|
reseed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reseed(std::uint32_t seed)
|
||||||
|
{
|
||||||
|
for (std::int32_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
p[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shuffle(std::begin(p), std::begin(p) + 256, std::default_random_engine(seed));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
p[256 + i] = p[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise(double x) const
|
||||||
|
{
|
||||||
|
return noise(x, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise(double x, double y) const
|
||||||
|
{
|
||||||
|
return noise(x, y, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise(double x, double y, double z) const
|
||||||
|
{
|
||||||
|
const std::int32_t X = static_cast<std::int32_t>(std::floor(x)) & 255;
|
||||||
|
const std::int32_t Y = static_cast<std::int32_t>(std::floor(y)) & 255;
|
||||||
|
const std::int32_t Z = static_cast<std::int32_t>(std::floor(z)) & 255;
|
||||||
|
|
||||||
|
x -= std::floor(x);
|
||||||
|
y -= std::floor(y);
|
||||||
|
z -= std::floor(z);
|
||||||
|
|
||||||
|
const double u = fade(x);
|
||||||
|
const double v = fade(y);
|
||||||
|
const double w = fade(z);
|
||||||
|
|
||||||
|
const int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z;
|
||||||
|
const int B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;
|
||||||
|
|
||||||
|
return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),
|
||||||
|
grad(p[BA], x - 1, y, z)),
|
||||||
|
lerp(u, grad(p[AB], x, y - 1, z),
|
||||||
|
grad(p[BB], x - 1, y - 1, z))),
|
||||||
|
lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1),
|
||||||
|
grad(p[BA + 1], x - 1, y, z - 1)),
|
||||||
|
lerp(u, grad(p[AB + 1], x, y - 1, z - 1),
|
||||||
|
grad(p[BB + 1], x - 1, y - 1, z - 1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
double octaveNoise(double x, std::int32_t octaves) const
|
||||||
|
{
|
||||||
|
double result = 0.0;
|
||||||
|
double amp = 1.0;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += noise(x) * amp;
|
||||||
|
x *= 2.0;
|
||||||
|
amp *= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double octaveNoise(double x, double y, std::int32_t octaves) const
|
||||||
|
{
|
||||||
|
double result = 0.0;
|
||||||
|
double amp = 1.0;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += noise(x, y) * amp;
|
||||||
|
x *= 2.0;
|
||||||
|
y *= 2.0;
|
||||||
|
amp *= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double octaveNoise(double x, double y, double z, std::int32_t octaves) const
|
||||||
|
{
|
||||||
|
double result = 0.0;
|
||||||
|
double amp = 1.0;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += noise(x, y, z) * amp;
|
||||||
|
x *= 2.0;
|
||||||
|
y *= 2.0;
|
||||||
|
z *= 2.0;
|
||||||
|
amp *= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise0_1(double x) const
|
||||||
|
{
|
||||||
|
return noise(x) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise0_1(double x, double y) const
|
||||||
|
{
|
||||||
|
return noise(x, y) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise0_1(double x, double y, double z) const
|
||||||
|
{
|
||||||
|
return noise(x, y, z) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
double octaveNoise0_1(double x, std::int32_t octaves) const
|
||||||
|
{
|
||||||
|
return octaveNoise(x, octaves) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
double octaveNoise0_1(double x, double y, std::int32_t octaves) const
|
||||||
|
{
|
||||||
|
return octaveNoise(x, y, octaves) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
double octaveNoise0_1(double x, double y, double z, std::int32_t octaves) const
|
||||||
|
{
|
||||||
|
return octaveNoise(x, y, z, octaves) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
1599
vendor/RTree.h
vendored
Normal file
1599
vendor/RTree.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1219
vendor/cola.hpp
vendored
Normal file
1219
vendor/cola.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1105
vendor/glad.c
vendored
Normal file
1105
vendor/glad.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2185
vendor/glad/glad.h
vendored
Normal file
2185
vendor/glad/glad.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
61
vendor/imconfig.h
vendored
Normal file
61
vendor/imconfig.h
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// USER IMPLEMENTATION
|
||||||
|
// This file contains compile-time options for ImGui.
|
||||||
|
// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO().
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//---- Define assertion handler. Defaults to calling assert().
|
||||||
|
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||||
|
|
||||||
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
|
||||||
|
//#define IMGUI_API __declspec( dllexport )
|
||||||
|
//#define IMGUI_API __declspec( dllimport )
|
||||||
|
|
||||||
|
//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names
|
||||||
|
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
|
||||||
|
//---- Include imgui_user.h at the end of imgui.h
|
||||||
|
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||||
|
|
||||||
|
//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
|
||||||
|
|
||||||
|
//---- Don't implement test window functionality (ShowTestWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
|
||||||
|
//---- It is very strongly recommended to NOT disable the test windows. Please read the comment at the top of imgui_demo.cpp to learn why.
|
||||||
|
//#define IMGUI_DISABLE_TEST_WINDOWS
|
||||||
|
|
||||||
|
//---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself.
|
||||||
|
//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
|
||||||
|
|
||||||
|
//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends)
|
||||||
|
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
|
|
||||||
|
//---- Implement STB libraries in a namespace to avoid linkage conflicts
|
||||||
|
//#define IMGUI_STB_NAMESPACE ImGuiStb
|
||||||
|
|
||||||
|
//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||||
|
/*
|
||||||
|
#define IM_VEC2_CLASS_EXTRA \
|
||||||
|
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||||
|
operator MyVec2() const { return MyVec2(x,y); }
|
||||||
|
|
||||||
|
#define IM_VEC4_CLASS_EXTRA \
|
||||||
|
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
|
||||||
|
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices
|
||||||
|
//#define ImDrawIdx unsigned int
|
||||||
|
|
||||||
|
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||||
|
//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers.
|
||||||
|
/*
|
||||||
|
namespace ImGui
|
||||||
|
{
|
||||||
|
void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
10877
vendor/imgui.cpp
vendored
Normal file
10877
vendor/imgui.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1534
vendor/imgui.h
vendored
Normal file
1534
vendor/imgui.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2873
vendor/imgui_demo.cpp
vendored
Normal file
2873
vendor/imgui_demo.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2710
vendor/imgui_draw.cpp
vendored
Normal file
2710
vendor/imgui_draw.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
417
vendor/imgui_impl_glfw_gl3.cpp
vendored
Normal file
417
vendor/imgui_impl_glfw_gl3.cpp
vendored
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
// ImGui GLFW binding with OpenGL3 + shaders
|
||||||
|
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
|
||||||
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
|
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||||
|
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||||
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include "imgui_impl_glfw_gl3.h"
|
||||||
|
|
||||||
|
// GL3W/GLFW
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#undef APIENTRY
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WGL
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Data
|
||||||
|
static GLFWwindow* g_Window = NULL;
|
||||||
|
static double g_Time = 0.0f;
|
||||||
|
static bool g_MouseJustPressed[3] = { false, false, false };
|
||||||
|
static float g_MouseWheel = 0.0f;
|
||||||
|
static GLuint g_FontTexture = 0;
|
||||||
|
static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||||
|
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||||
|
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||||
|
static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0;
|
||||||
|
|
||||||
|
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure)
|
||||||
|
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||||
|
// If text or lines are blurry when integrating ImGui in your engine: in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
|
||||||
|
void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data)
|
||||||
|
{
|
||||||
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||||
|
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||||
|
if (fb_width == 0 || fb_height == 0)
|
||||||
|
return;
|
||||||
|
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||||
|
|
||||||
|
// Backup GL state
|
||||||
|
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||||
|
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
|
||||||
|
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||||
|
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
|
||||||
|
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||||
|
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
|
||||||
|
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||||
|
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||||
|
GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
|
||||||
|
GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
|
||||||
|
GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
|
||||||
|
GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
|
||||||
|
GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
|
||||||
|
GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
|
||||||
|
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||||
|
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||||
|
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
|
// Setup viewport, orthographic projection matrix
|
||||||
|
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||||
|
const float ortho_projection[4][4] =
|
||||||
|
{
|
||||||
|
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||||
|
{-1.0f, 1.0f, 0.0f, 1.0f },
|
||||||
|
};
|
||||||
|
glUseProgram(g_ShaderHandle);
|
||||||
|
glUniform1i(g_AttribLocationTex, 0);
|
||||||
|
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||||
|
glBindVertexArray(g_VaoHandle);
|
||||||
|
glBindSampler(0, 0); // Rely on combined texture/sampler state.
|
||||||
|
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
const ImDrawIdx* idx_buffer_offset = 0;
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||||
|
{
|
||||||
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||||
|
if (pcmd->UserCallback)
|
||||||
|
{
|
||||||
|
pcmd->UserCallback(cmd_list, pcmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||||
|
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||||
|
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||||
|
}
|
||||||
|
idx_buffer_offset += pcmd->ElemCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore modified GL state
|
||||||
|
glUseProgram(last_program);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
glBindSampler(0, last_sampler);
|
||||||
|
glActiveTexture(last_active_texture);
|
||||||
|
glBindVertexArray(last_vertex_array);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
|
||||||
|
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
||||||
|
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
||||||
|
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
||||||
|
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
||||||
|
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
||||||
|
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]);
|
||||||
|
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||||
|
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* ImGui_ImplGlfwGL3_GetClipboardText(void* user_data)
|
||||||
|
{
|
||||||
|
return glfwGetClipboardString((GLFWwindow*)user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplGlfwGL3_SetClipboardText(void* user_data, const char* text)
|
||||||
|
{
|
||||||
|
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/)
|
||||||
|
{
|
||||||
|
if (action == GLFW_PRESS && button >= 0 && button < 3)
|
||||||
|
g_MouseJustPressed[button] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset)
|
||||||
|
{
|
||||||
|
g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines.
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (action == GLFW_PRESS)
|
||||||
|
io.KeysDown[key] = true;
|
||||||
|
if (action == GLFW_RELEASE)
|
||||||
|
io.KeysDown[key] = false;
|
||||||
|
|
||||||
|
(void)mods; // Modifiers are not reliable across systems
|
||||||
|
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
|
||||||
|
io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
|
||||||
|
io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
|
||||||
|
io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (c > 0 && c < 0x10000)
|
||||||
|
io.AddInputCharacter((unsigned short)c);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplGlfwGL3_CreateFontsTexture()
|
||||||
|
{
|
||||||
|
// Build texture atlas
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
unsigned char* pixels;
|
||||||
|
int width, height;
|
||||||
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||||
|
|
||||||
|
// Upload texture to graphics system
|
||||||
|
GLint last_texture;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGenTextures(1, &g_FontTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||||
|
|
||||||
|
// Store our identifier
|
||||||
|
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||||
|
|
||||||
|
// Restore state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplGlfwGL3_CreateDeviceObjects()
|
||||||
|
{
|
||||||
|
// Backup GL state
|
||||||
|
GLint last_texture, last_array_buffer, last_vertex_array;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||||
|
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||||
|
|
||||||
|
const GLchar *vertex_shader =
|
||||||
|
"#version 330\n"
|
||||||
|
"uniform mat4 ProjMtx;\n"
|
||||||
|
"in vec2 Position;\n"
|
||||||
|
"in vec2 UV;\n"
|
||||||
|
"in vec4 Color;\n"
|
||||||
|
"out vec2 Frag_UV;\n"
|
||||||
|
"out vec4 Frag_Color;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" Frag_UV = UV;\n"
|
||||||
|
" Frag_Color = Color;\n"
|
||||||
|
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
const GLchar* fragment_shader =
|
||||||
|
"#version 330\n"
|
||||||
|
"uniform sampler2D Texture;\n"
|
||||||
|
"in vec2 Frag_UV;\n"
|
||||||
|
"in vec4 Frag_Color;\n"
|
||||||
|
"out vec4 Out_Color;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
g_ShaderHandle = glCreateProgram();
|
||||||
|
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(g_VertHandle, 1, &vertex_shader, 0);
|
||||||
|
glShaderSource(g_FragHandle, 1, &fragment_shader, 0);
|
||||||
|
glCompileShader(g_VertHandle);
|
||||||
|
glCompileShader(g_FragHandle);
|
||||||
|
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||||
|
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||||
|
glLinkProgram(g_ShaderHandle);
|
||||||
|
|
||||||
|
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||||
|
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||||
|
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||||
|
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
||||||
|
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||||
|
|
||||||
|
glGenBuffers(1, &g_VboHandle);
|
||||||
|
glGenBuffers(1, &g_ElementsHandle);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &g_VaoHandle);
|
||||||
|
glBindVertexArray(g_VaoHandle);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||||
|
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||||
|
|
||||||
|
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||||
|
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
|
||||||
|
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
|
||||||
|
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
|
||||||
|
#undef OFFSETOF
|
||||||
|
|
||||||
|
ImGui_ImplGlfwGL3_CreateFontsTexture();
|
||||||
|
|
||||||
|
// Restore modified GL state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||||
|
glBindVertexArray(last_vertex_array);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfwGL3_InvalidateDeviceObjects()
|
||||||
|
{
|
||||||
|
if (g_VaoHandle) glDeleteVertexArrays(1, &g_VaoHandle);
|
||||||
|
if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle);
|
||||||
|
if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
|
||||||
|
g_VaoHandle = g_VboHandle = g_ElementsHandle = 0;
|
||||||
|
|
||||||
|
if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
|
||||||
|
if (g_VertHandle) glDeleteShader(g_VertHandle);
|
||||||
|
g_VertHandle = 0;
|
||||||
|
|
||||||
|
if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
|
||||||
|
if (g_FragHandle) glDeleteShader(g_FragHandle);
|
||||||
|
g_FragHandle = 0;
|
||||||
|
|
||||||
|
if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
|
||||||
|
g_ShaderHandle = 0;
|
||||||
|
|
||||||
|
if (g_FontTexture)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &g_FontTexture);
|
||||||
|
ImGui::GetIO().Fonts->TexID = 0;
|
||||||
|
g_FontTexture = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks)
|
||||||
|
{
|
||||||
|
g_Window = window;
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||||
|
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
||||||
|
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||||
|
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||||
|
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
|
||||||
|
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
|
||||||
|
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
|
||||||
|
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
|
||||||
|
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
|
||||||
|
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
||||||
|
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
|
||||||
|
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
|
||||||
|
io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
|
||||||
|
io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
|
||||||
|
io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
|
||||||
|
io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
|
||||||
|
io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
|
||||||
|
io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
|
||||||
|
io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
|
||||||
|
|
||||||
|
io.RenderDrawListsFn = ImGui_ImplGlfwGL3_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer.
|
||||||
|
io.SetClipboardTextFn = ImGui_ImplGlfwGL3_SetClipboardText;
|
||||||
|
io.GetClipboardTextFn = ImGui_ImplGlfwGL3_GetClipboardText;
|
||||||
|
io.ClipboardUserData = g_Window;
|
||||||
|
#ifdef _WIN32
|
||||||
|
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (install_callbacks)
|
||||||
|
{
|
||||||
|
glfwSetMouseButtonCallback(window, ImGui_ImplGlfwGL3_MouseButtonCallback);
|
||||||
|
glfwSetScrollCallback(window, ImGui_ImplGlfwGL3_ScrollCallback);
|
||||||
|
glfwSetKeyCallback(window, ImGui_ImplGlfwGL3_KeyCallback);
|
||||||
|
glfwSetCharCallback(window, ImGui_ImplGlfwGL3_CharCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfwGL3_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplGlfwGL3_InvalidateDeviceObjects();
|
||||||
|
ImGui::Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGlfwGL3_NewFrame()
|
||||||
|
{
|
||||||
|
if (!g_FontTexture)
|
||||||
|
ImGui_ImplGlfwGL3_CreateDeviceObjects();
|
||||||
|
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
|
int w, h;
|
||||||
|
int display_w, display_h;
|
||||||
|
glfwGetWindowSize(g_Window, &w, &h);
|
||||||
|
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
|
||||||
|
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||||
|
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
|
||||||
|
|
||||||
|
// Setup time step
|
||||||
|
double current_time = glfwGetTime();
|
||||||
|
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
|
||||||
|
g_Time = current_time;
|
||||||
|
|
||||||
|
// Setup inputs
|
||||||
|
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||||
|
if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED))
|
||||||
|
{
|
||||||
|
if (io.WantMoveMouse)
|
||||||
|
{
|
||||||
|
glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double mouse_x, mouse_y;
|
||||||
|
glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
|
||||||
|
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Get mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
// If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||||
|
io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;
|
||||||
|
g_MouseJustPressed[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
io.MouseWheel = g_MouseWheel;
|
||||||
|
g_MouseWheel = 0.0f;
|
||||||
|
|
||||||
|
// Hide OS mouse cursor if ImGui is drawing it
|
||||||
|
glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
|
||||||
|
|
||||||
|
// Start the frame
|
||||||
|
ImGui::NewFrame();
|
||||||
|
}
|
25
vendor/imgui_impl_glfw_gl3.h
vendored
Normal file
25
vendor/imgui_impl_glfw_gl3.h
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// ImGui GLFW binding with OpenGL3 + shaders
|
||||||
|
// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp.
|
||||||
|
|
||||||
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||||
|
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||||
|
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||||
|
// https://github.com/ocornut/imgui
|
||||||
|
|
||||||
|
struct GLFWwindow;
|
||||||
|
|
||||||
|
IMGUI_API bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks);
|
||||||
|
IMGUI_API void ImGui_ImplGlfwGL3_Shutdown();
|
||||||
|
IMGUI_API void ImGui_ImplGlfwGL3_NewFrame();
|
||||||
|
|
||||||
|
// Use if you want to reset your rendering device without losing ImGui state.
|
||||||
|
IMGUI_API void ImGui_ImplGlfwGL3_InvalidateDeviceObjects();
|
||||||
|
IMGUI_API bool ImGui_ImplGlfwGL3_CreateDeviceObjects();
|
||||||
|
|
||||||
|
// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization)
|
||||||
|
// Provided here if you want to chain callbacks.
|
||||||
|
// You can also handle inputs yourself and use those as a reference.
|
||||||
|
IMGUI_API void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||||
|
IMGUI_API void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||||
|
IMGUI_API void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||||
|
IMGUI_API void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c);
|
884
vendor/imgui_internal.h
vendored
Normal file
884
vendor/imgui_internal.h
vendored
Normal file
@ -0,0 +1,884 @@
|
|||||||
|
// dear imgui, v1.52 WIP
|
||||||
|
// (internals)
|
||||||
|
|
||||||
|
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
|
||||||
|
// Implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators)
|
||||||
|
// #define IMGUI_DEFINE_MATH_OPERATORS
|
||||||
|
// Define IM_PLACEMENT_NEW() macro helper.
|
||||||
|
// #define IMGUI_DEFINE_PLACEMENT_NEW
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef IMGUI_VERSION
|
||||||
|
#error Must include imgui.h before imgui_internal.h
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h> // FILE*
|
||||||
|
#include <math.h> // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (push)
|
||||||
|
#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
|
||||||
|
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Forward Declarations
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct ImRect;
|
||||||
|
struct ImGuiColMod;
|
||||||
|
struct ImGuiStyleMod;
|
||||||
|
struct ImGuiGroupData;
|
||||||
|
struct ImGuiSimpleColumns;
|
||||||
|
struct ImGuiDrawContext;
|
||||||
|
struct ImGuiTextEditState;
|
||||||
|
struct ImGuiIniData;
|
||||||
|
struct ImGuiMouseCursorData;
|
||||||
|
struct ImGuiPopupRef;
|
||||||
|
struct ImGuiWindow;
|
||||||
|
|
||||||
|
typedef int ImGuiLayoutType; // enum ImGuiLayoutType_
|
||||||
|
typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_
|
||||||
|
typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_
|
||||||
|
typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_
|
||||||
|
typedef int ImGuiSeparatorFlags; // enum ImGuiSeparatorFlags_
|
||||||
|
typedef int ImGuiItemFlags; // enum ImGuiItemFlags_
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// STB libraries
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace ImGuiStb
|
||||||
|
{
|
||||||
|
|
||||||
|
#undef STB_TEXTEDIT_STRING
|
||||||
|
#undef STB_TEXTEDIT_CHARTYPE
|
||||||
|
#define STB_TEXTEDIT_STRING ImGuiTextEditState
|
||||||
|
#define STB_TEXTEDIT_CHARTYPE ImWchar
|
||||||
|
#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f
|
||||||
|
#include "stb_textedit.h"
|
||||||
|
|
||||||
|
} // namespace ImGuiStb
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Context
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef GImGui
|
||||||
|
extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Helpers
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
|
||||||
|
#define IM_PI 3.14159265358979323846f
|
||||||
|
#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM))
|
||||||
|
|
||||||
|
// Helpers: UTF-8 <> wchar
|
||||||
|
IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
|
||||||
|
IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // return input UTF-8 bytes count
|
||||||
|
IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
|
||||||
|
IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
|
||||||
|
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string as UTF-8 code-points
|
||||||
|
|
||||||
|
// Helpers: Misc
|
||||||
|
IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings
|
||||||
|
IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0);
|
||||||
|
IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode);
|
||||||
|
static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; }
|
||||||
|
static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; }
|
||||||
|
static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
|
||||||
|
|
||||||
|
// Helpers: Geometry
|
||||||
|
IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);
|
||||||
|
IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
|
||||||
|
IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
|
||||||
|
IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);
|
||||||
|
|
||||||
|
// Helpers: String
|
||||||
|
IMGUI_API int ImStricmp(const char* str1, const char* str2);
|
||||||
|
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, int count);
|
||||||
|
IMGUI_API void ImStrncpy(char* dst, const char* src, int count);
|
||||||
|
IMGUI_API char* ImStrdup(const char* str);
|
||||||
|
IMGUI_API int ImStrlenW(const ImWchar* str);
|
||||||
|
IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
|
||||||
|
IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
|
||||||
|
IMGUI_API int ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_FMTARGS(3);
|
||||||
|
IMGUI_API int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) IM_FMTLIST(3);
|
||||||
|
|
||||||
|
// Helpers: Math
|
||||||
|
// We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined)
|
||||||
|
#ifdef IMGUI_DEFINE_MATH_OPERATORS
|
||||||
|
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
|
||||||
|
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); }
|
||||||
|
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
|
||||||
|
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
|
||||||
|
static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }
|
||||||
|
static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }
|
||||||
|
static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
|
||||||
|
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
|
||||||
|
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
||||||
|
static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
||||||
|
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
|
||||||
|
static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||||
|
static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
|
||||||
|
static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||||
|
static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); }
|
||||||
|
static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); }
|
||||||
|
static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
|
||||||
|
static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
|
||||||
|
static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); }
|
||||||
|
static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
|
||||||
|
static inline void ImSwap(int& a, int& b) { int tmp = a; a = b; b = tmp; }
|
||||||
|
static inline void ImSwap(float& a, float& b) { float tmp = a; a = b; b = tmp; }
|
||||||
|
static inline int ImLerp(int a, int b, float t) { return (int)(a + (b - a) * t); }
|
||||||
|
static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; }
|
||||||
|
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); }
|
||||||
|
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
|
||||||
|
static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); }
|
||||||
|
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
|
||||||
|
static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
|
||||||
|
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / sqrtf(d); return fail_value; }
|
||||||
|
static inline float ImFloor(float f) { return (float)(int)f; }
|
||||||
|
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
|
||||||
|
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||||
|
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||||
|
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
|
||||||
|
|
||||||
|
// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
|
||||||
|
// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
|
||||||
|
#ifdef IMGUI_DEFINE_PLACEMENT_NEW
|
||||||
|
struct ImPlacementNewDummy {};
|
||||||
|
inline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; }
|
||||||
|
inline void operator delete(void*, ImPlacementNewDummy, void*) {}
|
||||||
|
#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy(), _PTR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Types
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum ImGuiButtonFlags_
|
||||||
|
{
|
||||||
|
ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat
|
||||||
|
ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // return true on click + release on same item [DEFAULT if no PressedOn* flag is set]
|
||||||
|
ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release)
|
||||||
|
ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release)
|
||||||
|
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release)
|
||||||
|
ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interactions even if a child window is overlapping
|
||||||
|
ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press // [UNUSED]
|
||||||
|
ImGuiButtonFlags_Disabled = 1 << 7, // disable interactions
|
||||||
|
ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline (ButtonEx() only)
|
||||||
|
ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held
|
||||||
|
ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable
|
||||||
|
ImGuiButtonFlags_NoHoldingActiveID = 1 << 11 // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiSliderFlags_
|
||||||
|
{
|
||||||
|
ImGuiSliderFlags_Vertical = 1 << 0
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiColumnsFlags_
|
||||||
|
{
|
||||||
|
// Default: 0
|
||||||
|
ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers
|
||||||
|
ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers
|
||||||
|
ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns
|
||||||
|
ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3 // Disable forcing columns to fit within window
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiSelectableFlagsPrivate_
|
||||||
|
{
|
||||||
|
// NB: need to be in sync with last value of ImGuiSelectableFlags_
|
||||||
|
ImGuiSelectableFlags_Menu = 1 << 3,
|
||||||
|
ImGuiSelectableFlags_MenuItem = 1 << 4,
|
||||||
|
ImGuiSelectableFlags_Disabled = 1 << 5,
|
||||||
|
ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiSeparatorFlags_
|
||||||
|
{
|
||||||
|
ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
|
||||||
|
ImGuiSeparatorFlags_Vertical = 1 << 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: this is in development, not exposed/functional as a generic feature yet.
|
||||||
|
enum ImGuiLayoutType_
|
||||||
|
{
|
||||||
|
ImGuiLayoutType_Vertical,
|
||||||
|
ImGuiLayoutType_Horizontal
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiPlotType
|
||||||
|
{
|
||||||
|
ImGuiPlotType_Lines,
|
||||||
|
ImGuiPlotType_Histogram
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiDataType
|
||||||
|
{
|
||||||
|
ImGuiDataType_Int,
|
||||||
|
ImGuiDataType_Float,
|
||||||
|
ImGuiDataType_Float2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiDir
|
||||||
|
{
|
||||||
|
ImGuiDir_None = -1,
|
||||||
|
ImGuiDir_Left = 0,
|
||||||
|
ImGuiDir_Right = 1,
|
||||||
|
ImGuiDir_Up = 2,
|
||||||
|
ImGuiDir_Down = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGuiCorner
|
||||||
|
{
|
||||||
|
ImGuiCorner_TopLeft = 1 << 0, // 1
|
||||||
|
ImGuiCorner_TopRight = 1 << 1, // 2
|
||||||
|
ImGuiCorner_BotRight = 1 << 2, // 4
|
||||||
|
ImGuiCorner_BotLeft = 1 << 3, // 8
|
||||||
|
ImGuiCorner_All = 0x0F
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2D axis aligned bounding-box
|
||||||
|
// NB: we can't rely on ImVec2 math operators being available here
|
||||||
|
struct IMGUI_API ImRect
|
||||||
|
{
|
||||||
|
ImVec2 Min; // Upper-left
|
||||||
|
ImVec2 Max; // Lower-right
|
||||||
|
|
||||||
|
ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {}
|
||||||
|
ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
|
||||||
|
ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
|
||||||
|
ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
|
||||||
|
|
||||||
|
ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); }
|
||||||
|
ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); }
|
||||||
|
float GetWidth() const { return Max.x-Min.x; }
|
||||||
|
float GetHeight() const { return Max.y-Min.y; }
|
||||||
|
ImVec2 GetTL() const { return Min; } // Top-left
|
||||||
|
ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right
|
||||||
|
ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left
|
||||||
|
ImVec2 GetBR() const { return Max; } // Bottom-right
|
||||||
|
bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
|
||||||
|
bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; }
|
||||||
|
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
|
||||||
|
void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; }
|
||||||
|
void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; }
|
||||||
|
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
|
||||||
|
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
|
||||||
|
void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; }
|
||||||
|
void ClipWith(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; }
|
||||||
|
void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
|
||||||
|
ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const
|
||||||
|
{
|
||||||
|
if (!on_edge && Contains(p))
|
||||||
|
return p;
|
||||||
|
if (p.x > Max.x) p.x = Max.x;
|
||||||
|
else if (p.x < Min.x) p.x = Min.x;
|
||||||
|
if (p.y > Max.y) p.y = Max.y;
|
||||||
|
else if (p.y < Min.y) p.y = Min.y;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stacked color modifier, backup of modified data so we can restore it
|
||||||
|
struct ImGuiColMod
|
||||||
|
{
|
||||||
|
ImGuiCol Col;
|
||||||
|
ImVec4 BackupValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.
|
||||||
|
struct ImGuiStyleMod
|
||||||
|
{
|
||||||
|
ImGuiStyleVar VarIdx;
|
||||||
|
union { int BackupInt[2]; float BackupFloat[2]; };
|
||||||
|
ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; }
|
||||||
|
ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; }
|
||||||
|
ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stacked data for BeginGroup()/EndGroup()
|
||||||
|
struct ImGuiGroupData
|
||||||
|
{
|
||||||
|
ImVec2 BackupCursorPos;
|
||||||
|
ImVec2 BackupCursorMaxPos;
|
||||||
|
float BackupIndentX;
|
||||||
|
float BackupGroupOffsetX;
|
||||||
|
float BackupCurrentLineHeight;
|
||||||
|
float BackupCurrentLineTextBaseOffset;
|
||||||
|
float BackupLogLinePosY;
|
||||||
|
bool BackupActiveIdIsAlive;
|
||||||
|
bool AdvanceCursor;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Per column data for Columns()
|
||||||
|
struct ImGuiColumnData
|
||||||
|
{
|
||||||
|
float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
|
||||||
|
ImRect ClipRect;
|
||||||
|
//float IndentX;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper.
|
||||||
|
struct IMGUI_API ImGuiSimpleColumns
|
||||||
|
{
|
||||||
|
int Count;
|
||||||
|
float Spacing;
|
||||||
|
float Width, NextWidth;
|
||||||
|
float Pos[8], NextWidths[8];
|
||||||
|
|
||||||
|
ImGuiSimpleColumns();
|
||||||
|
void Update(int count, float spacing, bool clear);
|
||||||
|
float DeclColumns(float w0, float w1, float w2);
|
||||||
|
float CalcExtraSpace(float avail_w);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal state of the currently focused/edited text input box
|
||||||
|
struct IMGUI_API ImGuiTextEditState
|
||||||
|
{
|
||||||
|
ImGuiID Id; // widget id owning the text state
|
||||||
|
ImVector<ImWchar> Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
|
||||||
|
ImVector<char> InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
|
||||||
|
ImVector<char> TempTextBuffer;
|
||||||
|
int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
|
||||||
|
int BufSizeA; // end-user buffer size
|
||||||
|
float ScrollX;
|
||||||
|
ImGuiStb::STB_TexteditState StbState;
|
||||||
|
float CursorAnim;
|
||||||
|
bool CursorFollow;
|
||||||
|
bool SelectedAllMouseLock;
|
||||||
|
|
||||||
|
ImGuiTextEditState() { memset(this, 0, sizeof(*this)); }
|
||||||
|
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
|
||||||
|
void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); }
|
||||||
|
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
|
||||||
|
void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; }
|
||||||
|
void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
|
||||||
|
void OnKeyPressed(int key);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Data saved in imgui.ini file
|
||||||
|
struct ImGuiIniData
|
||||||
|
{
|
||||||
|
char* Name;
|
||||||
|
ImGuiID Id;
|
||||||
|
ImVec2 Pos;
|
||||||
|
ImVec2 Size;
|
||||||
|
bool Collapsed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mouse cursor data (used when io.MouseDrawCursor is set)
|
||||||
|
struct ImGuiMouseCursorData
|
||||||
|
{
|
||||||
|
ImGuiMouseCursor Type;
|
||||||
|
ImVec2 HotOffset;
|
||||||
|
ImVec2 Size;
|
||||||
|
ImVec2 TexUvMin[2];
|
||||||
|
ImVec2 TexUvMax[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Storage for current popup stack
|
||||||
|
struct ImGuiPopupRef
|
||||||
|
{
|
||||||
|
ImGuiID PopupId; // Set on OpenPopup()
|
||||||
|
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
|
||||||
|
ImGuiWindow* ParentWindow; // Set on OpenPopup()
|
||||||
|
ImGuiID ParentMenuSet; // Set on OpenPopup()
|
||||||
|
ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup
|
||||||
|
|
||||||
|
ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main state for ImGui
|
||||||
|
struct ImGuiContext
|
||||||
|
{
|
||||||
|
bool Initialized;
|
||||||
|
ImGuiIO IO;
|
||||||
|
ImGuiStyle Style;
|
||||||
|
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
|
||||||
|
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
|
||||||
|
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
|
||||||
|
ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel
|
||||||
|
|
||||||
|
float Time;
|
||||||
|
int FrameCount;
|
||||||
|
int FrameCountEnded;
|
||||||
|
int FrameCountRendered;
|
||||||
|
ImVector<ImGuiWindow*> Windows;
|
||||||
|
ImVector<ImGuiWindow*> WindowsSortBuffer;
|
||||||
|
ImVector<ImGuiWindow*> CurrentWindowStack;
|
||||||
|
ImGuiWindow* CurrentWindow; // Being drawn into
|
||||||
|
ImGuiWindow* NavWindow; // Nav/focused window for navigation
|
||||||
|
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
|
||||||
|
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
|
||||||
|
ImGuiID HoveredId; // Hovered widget
|
||||||
|
bool HoveredIdAllowOverlap;
|
||||||
|
ImGuiID HoveredIdPreviousFrame;
|
||||||
|
ImGuiID ActiveId; // Active widget
|
||||||
|
ImGuiID ActiveIdPreviousFrame;
|
||||||
|
bool ActiveIdIsAlive; // Active widget has been seen this frame
|
||||||
|
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
|
||||||
|
bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
|
||||||
|
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
|
||||||
|
ImGuiWindow* ActiveIdWindow;
|
||||||
|
ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window.
|
||||||
|
ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId
|
||||||
|
ImVector<ImGuiIniData> Settings; // .ini Settings
|
||||||
|
float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero
|
||||||
|
ImVector<ImGuiColMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
|
||||||
|
ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
|
||||||
|
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
|
||||||
|
ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent)
|
||||||
|
ImVector<ImGuiPopupRef> CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame)
|
||||||
|
|
||||||
|
// Storage for SetNexWindow** and SetNextTreeNode*** functions
|
||||||
|
ImVec2 SetNextWindowPosVal;
|
||||||
|
ImVec2 SetNextWindowPosPivot;
|
||||||
|
ImVec2 SetNextWindowSizeVal;
|
||||||
|
ImVec2 SetNextWindowContentSizeVal;
|
||||||
|
bool SetNextWindowCollapsedVal;
|
||||||
|
ImGuiCond SetNextWindowPosCond;
|
||||||
|
ImGuiCond SetNextWindowSizeCond;
|
||||||
|
ImGuiCond SetNextWindowContentSizeCond;
|
||||||
|
ImGuiCond SetNextWindowCollapsedCond;
|
||||||
|
ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true
|
||||||
|
ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback;
|
||||||
|
void* SetNextWindowSizeConstraintCallbackUserData;
|
||||||
|
bool SetNextWindowSizeConstraint;
|
||||||
|
bool SetNextWindowFocus;
|
||||||
|
bool SetNextTreeNodeOpenVal;
|
||||||
|
ImGuiCond SetNextTreeNodeOpenCond;
|
||||||
|
|
||||||
|
// Render
|
||||||
|
ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user
|
||||||
|
ImVector<ImDrawList*> RenderDrawLists[3];
|
||||||
|
float ModalWindowDarkeningRatio;
|
||||||
|
ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays
|
||||||
|
ImGuiMouseCursor MouseCursor;
|
||||||
|
ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_];
|
||||||
|
|
||||||
|
// Widget state
|
||||||
|
ImGuiTextEditState InputTextState;
|
||||||
|
ImFont InputTextPasswordFont;
|
||||||
|
ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
|
||||||
|
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
|
||||||
|
ImVec4 ColorPickerRef;
|
||||||
|
float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings
|
||||||
|
ImVec2 DragLastMouseDelta;
|
||||||
|
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
|
||||||
|
float DragSpeedScaleSlow;
|
||||||
|
float DragSpeedScaleFast;
|
||||||
|
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
|
||||||
|
int TooltipOverrideCount;
|
||||||
|
ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
|
||||||
|
ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
bool LogEnabled;
|
||||||
|
FILE* LogFile; // If != NULL log to stdout/ file
|
||||||
|
ImGuiTextBuffer* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
|
||||||
|
int LogStartDepth;
|
||||||
|
int LogAutoExpandMaxDepth;
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
float FramerateSecPerFrame[120]; // calculate estimate of framerate for user
|
||||||
|
int FramerateSecPerFrameIdx;
|
||||||
|
float FramerateSecPerFrameAccum;
|
||||||
|
int WantCaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags
|
||||||
|
int WantCaptureKeyboardNextFrame;
|
||||||
|
int WantTextInputNextFrame;
|
||||||
|
char TempBuffer[1024*3+1]; // temporary text buffer
|
||||||
|
|
||||||
|
ImGuiContext()
|
||||||
|
{
|
||||||
|
Initialized = false;
|
||||||
|
Font = NULL;
|
||||||
|
FontSize = FontBaseSize = 0.0f;
|
||||||
|
FontTexUvWhitePixel = ImVec2(0.0f, 0.0f);
|
||||||
|
|
||||||
|
Time = 0.0f;
|
||||||
|
FrameCount = 0;
|
||||||
|
FrameCountEnded = FrameCountRendered = -1;
|
||||||
|
CurrentWindow = NULL;
|
||||||
|
NavWindow = NULL;
|
||||||
|
HoveredWindow = NULL;
|
||||||
|
HoveredRootWindow = NULL;
|
||||||
|
HoveredId = 0;
|
||||||
|
HoveredIdAllowOverlap = false;
|
||||||
|
HoveredIdPreviousFrame = 0;
|
||||||
|
ActiveId = 0;
|
||||||
|
ActiveIdPreviousFrame = 0;
|
||||||
|
ActiveIdIsAlive = false;
|
||||||
|
ActiveIdIsJustActivated = false;
|
||||||
|
ActiveIdAllowOverlap = false;
|
||||||
|
ActiveIdClickOffset = ImVec2(-1,-1);
|
||||||
|
ActiveIdWindow = NULL;
|
||||||
|
MovedWindow = NULL;
|
||||||
|
MovedWindowMoveId = 0;
|
||||||
|
SettingsDirtyTimer = 0.0f;
|
||||||
|
|
||||||
|
SetNextWindowPosVal = ImVec2(0.0f, 0.0f);
|
||||||
|
SetNextWindowSizeVal = ImVec2(0.0f, 0.0f);
|
||||||
|
SetNextWindowCollapsedVal = false;
|
||||||
|
SetNextWindowPosCond = 0;
|
||||||
|
SetNextWindowSizeCond = 0;
|
||||||
|
SetNextWindowContentSizeCond = 0;
|
||||||
|
SetNextWindowCollapsedCond = 0;
|
||||||
|
SetNextWindowSizeConstraintRect = ImRect();
|
||||||
|
SetNextWindowSizeConstraintCallback = NULL;
|
||||||
|
SetNextWindowSizeConstraintCallbackUserData = NULL;
|
||||||
|
SetNextWindowSizeConstraint = false;
|
||||||
|
SetNextWindowFocus = false;
|
||||||
|
SetNextTreeNodeOpenVal = false;
|
||||||
|
SetNextTreeNodeOpenCond = 0;
|
||||||
|
|
||||||
|
ScalarAsInputTextId = 0;
|
||||||
|
ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
|
||||||
|
DragCurrentValue = 0.0f;
|
||||||
|
DragLastMouseDelta = ImVec2(0.0f, 0.0f);
|
||||||
|
DragSpeedDefaultRatio = 1.0f / 100.0f;
|
||||||
|
DragSpeedScaleSlow = 1.0f / 100.0f;
|
||||||
|
DragSpeedScaleFast = 10.0f;
|
||||||
|
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
|
||||||
|
TooltipOverrideCount = 0;
|
||||||
|
OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f);
|
||||||
|
|
||||||
|
ModalWindowDarkeningRatio = 0.0f;
|
||||||
|
OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
|
||||||
|
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||||
|
memset(MouseCursorData, 0, sizeof(MouseCursorData));
|
||||||
|
|
||||||
|
LogEnabled = false;
|
||||||
|
LogFile = NULL;
|
||||||
|
LogClipboard = NULL;
|
||||||
|
LogStartDepth = 0;
|
||||||
|
LogAutoExpandMaxDepth = 2;
|
||||||
|
|
||||||
|
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
|
||||||
|
FramerateSecPerFrameIdx = 0;
|
||||||
|
FramerateSecPerFrameAccum = 0.0f;
|
||||||
|
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
|
||||||
|
memset(TempBuffer, 0, sizeof(TempBuffer));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin().
|
||||||
|
enum ImGuiItemFlags_
|
||||||
|
{
|
||||||
|
ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true
|
||||||
|
ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.
|
||||||
|
//ImGuiItemFlags_Disabled = 1 << 2, // false // All widgets appears are disabled
|
||||||
|
//ImGuiItemFlags_AllowNavDefaultFocus = 1 << 3, // true
|
||||||
|
ImGuiItemFlags_SelectableDontClosePopup = 1 << 4, // false // MenuItem/Selectable() automatically closes current Popup window
|
||||||
|
ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transient per-window data, reset at the beginning of the frame
|
||||||
|
// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered.
|
||||||
|
struct IMGUI_API ImGuiDrawContext
|
||||||
|
{
|
||||||
|
ImVec2 CursorPos;
|
||||||
|
ImVec2 CursorPosPrevLine;
|
||||||
|
ImVec2 CursorStartPos;
|
||||||
|
ImVec2 CursorMaxPos; // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at the end of the frame
|
||||||
|
float CurrentLineHeight;
|
||||||
|
float CurrentLineTextBaseOffset;
|
||||||
|
float PrevLineHeight;
|
||||||
|
float PrevLineTextBaseOffset;
|
||||||
|
float LogLinePosY;
|
||||||
|
int TreeDepth;
|
||||||
|
ImGuiID LastItemId;
|
||||||
|
ImRect LastItemRect;
|
||||||
|
bool LastItemRectHoveredRect;
|
||||||
|
bool MenuBarAppending;
|
||||||
|
float MenuBarOffsetX;
|
||||||
|
ImVector<ImGuiWindow*> ChildWindows;
|
||||||
|
ImGuiStorage* StateStorage;
|
||||||
|
ImGuiLayoutType LayoutType;
|
||||||
|
|
||||||
|
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
|
||||||
|
ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
|
||||||
|
float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
|
||||||
|
float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
|
||||||
|
ImVector<ImGuiItemFlags>ItemFlagsStack;
|
||||||
|
ImVector<float> ItemWidthStack;
|
||||||
|
ImVector<float> TextWrapPosStack;
|
||||||
|
ImVector<ImGuiGroupData>GroupStack;
|
||||||
|
int StackSizesBackup[6]; // Store size of various stacks for asserting
|
||||||
|
|
||||||
|
float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
|
||||||
|
float GroupOffsetX;
|
||||||
|
float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
|
||||||
|
int ColumnsCurrent;
|
||||||
|
int ColumnsCount;
|
||||||
|
float ColumnsMinX;
|
||||||
|
float ColumnsMaxX;
|
||||||
|
float ColumnsStartPosY;
|
||||||
|
float ColumnsStartMaxPosX; // Backup of CursorMaxPos
|
||||||
|
float ColumnsCellMinY;
|
||||||
|
float ColumnsCellMaxY;
|
||||||
|
ImGuiColumnsFlags ColumnsFlags;
|
||||||
|
ImGuiID ColumnsSetId;
|
||||||
|
ImVector<ImGuiColumnData> ColumnsData;
|
||||||
|
|
||||||
|
ImGuiDrawContext()
|
||||||
|
{
|
||||||
|
CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f);
|
||||||
|
CurrentLineHeight = PrevLineHeight = 0.0f;
|
||||||
|
CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
|
||||||
|
LogLinePosY = -1.0f;
|
||||||
|
TreeDepth = 0;
|
||||||
|
LastItemId = 0;
|
||||||
|
LastItemRect = ImRect();
|
||||||
|
LastItemRectHoveredRect = false;
|
||||||
|
MenuBarAppending = false;
|
||||||
|
MenuBarOffsetX = 0.0f;
|
||||||
|
StateStorage = NULL;
|
||||||
|
LayoutType = ImGuiLayoutType_Vertical;
|
||||||
|
ItemWidth = 0.0f;
|
||||||
|
ItemFlags = ImGuiItemFlags_Default_;
|
||||||
|
TextWrapPos = -1.0f;
|
||||||
|
memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
|
||||||
|
|
||||||
|
IndentX = 0.0f;
|
||||||
|
GroupOffsetX = 0.0f;
|
||||||
|
ColumnsOffsetX = 0.0f;
|
||||||
|
ColumnsCurrent = 0;
|
||||||
|
ColumnsCount = 1;
|
||||||
|
ColumnsMinX = ColumnsMaxX = 0.0f;
|
||||||
|
ColumnsStartPosY = 0.0f;
|
||||||
|
ColumnsStartMaxPosX = 0.0f;
|
||||||
|
ColumnsCellMinY = ColumnsCellMaxY = 0.0f;
|
||||||
|
ColumnsFlags = 0;
|
||||||
|
ColumnsSetId = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Windows data
|
||||||
|
struct IMGUI_API ImGuiWindow
|
||||||
|
{
|
||||||
|
char* Name;
|
||||||
|
ImGuiID ID; // == ImHash(Name)
|
||||||
|
ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_
|
||||||
|
int OrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0.
|
||||||
|
ImVec2 PosFloat;
|
||||||
|
ImVec2 Pos; // Position rounded-up to nearest pixel
|
||||||
|
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
|
||||||
|
ImVec2 SizeFull; // Size when non collapsed
|
||||||
|
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame
|
||||||
|
ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize()
|
||||||
|
ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis
|
||||||
|
ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect
|
||||||
|
ImGuiID MoveId; // == window->GetID("#MOVE")
|
||||||
|
ImVec2 Scroll;
|
||||||
|
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
|
||||||
|
ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
|
||||||
|
bool ScrollbarX, ScrollbarY;
|
||||||
|
ImVec2 ScrollbarSizes;
|
||||||
|
float BorderSize;
|
||||||
|
bool Active; // Set to true on Begin()
|
||||||
|
bool WasActive;
|
||||||
|
bool Accessed; // Set to true when any widget access the current window
|
||||||
|
bool Collapsed; // Set when collapsing window to become only title-bar
|
||||||
|
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
|
||||||
|
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
|
||||||
|
int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
|
||||||
|
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
|
||||||
|
int AutoFitFramesX, AutoFitFramesY;
|
||||||
|
bool AutoFitOnlyGrows;
|
||||||
|
int AutoFitChildAxises;
|
||||||
|
int AutoPosLastDirection;
|
||||||
|
int HiddenFrames;
|
||||||
|
ImGuiCond SetWindowPosAllowFlags; // store condition flags for next SetWindowPos() call.
|
||||||
|
ImGuiCond SetWindowSizeAllowFlags; // store condition flags for next SetWindowSize() call.
|
||||||
|
ImGuiCond SetWindowCollapsedAllowFlags; // store condition flags for next SetWindowCollapsed() call.
|
||||||
|
ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size)
|
||||||
|
ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right.
|
||||||
|
|
||||||
|
ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame
|
||||||
|
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
|
||||||
|
ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
|
||||||
|
ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window.
|
||||||
|
int LastFrameActive;
|
||||||
|
float ItemWidthDefault;
|
||||||
|
ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items
|
||||||
|
ImGuiStorage StateStorage;
|
||||||
|
float FontWindowScale; // Scale multiplier per-window
|
||||||
|
ImDrawList* DrawList;
|
||||||
|
ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not)
|
||||||
|
ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window.
|
||||||
|
ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
||||||
|
|
||||||
|
// Navigation / Focus
|
||||||
|
int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
|
||||||
|
int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
|
||||||
|
int FocusIdxAllRequestCurrent; // Item being requested for focus
|
||||||
|
int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus
|
||||||
|
int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)
|
||||||
|
int FocusIdxTabRequestNext; // "
|
||||||
|
|
||||||
|
public:
|
||||||
|
ImGuiWindow(const char* name);
|
||||||
|
~ImGuiWindow();
|
||||||
|
|
||||||
|
ImGuiID GetID(const char* str, const char* str_end = NULL);
|
||||||
|
ImGuiID GetID(const void* ptr);
|
||||||
|
ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
|
||||||
|
|
||||||
|
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
|
||||||
|
float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; }
|
||||||
|
float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; }
|
||||||
|
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
|
||||||
|
float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; }
|
||||||
|
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data.
|
||||||
|
struct ImGuiItemHoveredDataBackup
|
||||||
|
{
|
||||||
|
ImGuiID LastItemId;
|
||||||
|
ImRect LastItemRect;
|
||||||
|
bool LastItemRectHoveredRect;
|
||||||
|
|
||||||
|
void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; }
|
||||||
|
void Restore() { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Internal API
|
||||||
|
// No guarantee of forward compatibility here.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace ImGui
|
||||||
|
{
|
||||||
|
// We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
|
||||||
|
// If this ever crash because g.CurrentWindow is NULL it means that either
|
||||||
|
// - ImGui::NewFrame() has never been called, which is illegal.
|
||||||
|
// - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
|
||||||
|
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
|
||||||
|
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }
|
||||||
|
IMGUI_API ImGuiWindow* GetParentWindow();
|
||||||
|
IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
|
||||||
|
IMGUI_API void FocusWindow(ImGuiWindow* window);
|
||||||
|
|
||||||
|
IMGUI_API void Initialize();
|
||||||
|
IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead!
|
||||||
|
|
||||||
|
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
||||||
|
IMGUI_API void ClearActiveID();
|
||||||
|
IMGUI_API void SetHoveredID(ImGuiID id);
|
||||||
|
IMGUI_API void KeepAliveID(ImGuiID id);
|
||||||
|
|
||||||
|
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
|
||||||
|
IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
|
||||||
|
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id);
|
||||||
|
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
|
||||||
|
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
|
||||||
|
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested
|
||||||
|
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
|
||||||
|
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
|
||||||
|
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
|
||||||
|
IMGUI_API void PushMultiItemsWidths(int components, float width_full = 0.0f);
|
||||||
|
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
|
||||||
|
IMGUI_API void PopItemFlag();
|
||||||
|
|
||||||
|
IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing);
|
||||||
|
IMGUI_API void ClosePopup(ImGuiID id);
|
||||||
|
IMGUI_API bool IsPopupOpen(ImGuiID id);
|
||||||
|
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
|
||||||
|
|
||||||
|
IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate);
|
||||||
|
|
||||||
|
IMGUI_API void Scrollbar(ImGuiLayoutType direction);
|
||||||
|
IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout.
|
||||||
|
|
||||||
|
// FIXME-WIP: New Columns API
|
||||||
|
IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
|
||||||
|
IMGUI_API void EndColumns(); // close columns
|
||||||
|
IMGUI_API void PushColumnClipRect(int column_index = -1);
|
||||||
|
|
||||||
|
// FIXME-WIP: New Combo API
|
||||||
|
IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImVec2 popup_size = ImVec2(0.0f,0.0f));
|
||||||
|
IMGUI_API void EndCombo();
|
||||||
|
|
||||||
|
// NB: All position are in absolute pixels coordinates (never using window coordinates internally)
|
||||||
|
// AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT.
|
||||||
|
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
|
||||||
|
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
||||||
|
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);
|
||||||
|
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
|
||||||
|
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||||
|
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0);
|
||||||
|
IMGUI_API void RenderTriangle(ImVec2 pos, ImGuiDir dir, float scale = 1.0f);
|
||||||
|
IMGUI_API void RenderBullet(ImVec2 pos);
|
||||||
|
IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz);
|
||||||
|
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
|
||||||
|
IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
|
||||||
|
|
||||||
|
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
|
||||||
|
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
|
||||||
|
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius);
|
||||||
|
|
||||||
|
IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0);
|
||||||
|
IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power);
|
||||||
|
IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format);
|
||||||
|
|
||||||
|
IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power);
|
||||||
|
IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power);
|
||||||
|
IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format);
|
||||||
|
|
||||||
|
IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL);
|
||||||
|
IMGUI_API bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags);
|
||||||
|
IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags);
|
||||||
|
IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags);
|
||||||
|
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision);
|
||||||
|
|
||||||
|
IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);
|
||||||
|
IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags);
|
||||||
|
|
||||||
|
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
|
||||||
|
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
|
||||||
|
IMGUI_API void TreePushRawID(ImGuiID id);
|
||||||
|
|
||||||
|
IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);
|
||||||
|
|
||||||
|
IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value);
|
||||||
|
IMGUI_API float RoundScalar(float value, int decimal_precision);
|
||||||
|
|
||||||
|
// Shade functions
|
||||||
|
IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1);
|
||||||
|
IMGUI_API void ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x);
|
||||||
|
|
||||||
|
} // namespace ImGui
|
||||||
|
|
||||||
|
// ImFontAtlas internals
|
||||||
|
IMGUI_API bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent);
|
||||||
|
IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc);
|
||||||
|
IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);
|
||||||
|
IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (pop)
|
||||||
|
#endif
|
14705
vendor/json.hpp
vendored
Normal file
14705
vendor/json.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
81
vendor/logger.cpp
vendored
Normal file
81
vendor/logger.cpp
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace kiss {
|
||||||
|
|
||||||
|
std::ostream *Logger::stream = &std::cerr;
|
||||||
|
eLogLevel Logger::level = LOG_LEVEL_WARNING;
|
||||||
|
const char* sLoggerLevel[] = { "ERROR ", "WARNING", "INFO ", "DEBUG " };
|
||||||
|
|
||||||
|
class EnvLogger {
|
||||||
|
public:
|
||||||
|
EnvLogger() {
|
||||||
|
Logger::loadEnvLogLevel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static EnvLogger _env_log_;
|
||||||
|
|
||||||
|
Logger::Logger(eLogLevel level) {
|
||||||
|
time_t rawtime;
|
||||||
|
struct tm * timeinfo;
|
||||||
|
char buffer[80];
|
||||||
|
|
||||||
|
time(&rawtime);
|
||||||
|
timeinfo = localtime(&rawtime);
|
||||||
|
|
||||||
|
strftime(buffer, 80, "%Y-%m-%d %H:%M:%S ", timeinfo);
|
||||||
|
*stream << buffer;
|
||||||
|
*stream << "[" << sLoggerLevel[level] << "] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::~Logger() {
|
||||||
|
*stream << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &Logger::getLogStream() {
|
||||||
|
return (*stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::setLogStream(std::ostream *s) {
|
||||||
|
stream = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::setLogStream(std::ostream &s) {
|
||||||
|
stream = &s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::setLogLevel(eLogLevel l) {
|
||||||
|
level = l;
|
||||||
|
}
|
||||||
|
eLogLevel Logger::getLogLevel() {
|
||||||
|
return (level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::loadEnvLogLevel() {
|
||||||
|
if (::getenv("LOG_LEVEL")) {
|
||||||
|
int level = atoi(::getenv("LOG_LEVEL"));
|
||||||
|
switch (level) {
|
||||||
|
case LOG_LEVEL_ERROR:
|
||||||
|
Logger::setLogLevel(LOG_LEVEL_ERROR);
|
||||||
|
break;
|
||||||
|
case LOG_LEVEL_WARNING:
|
||||||
|
Logger::setLogLevel(LOG_LEVEL_WARNING);
|
||||||
|
break;
|
||||||
|
case LOG_LEVEL_INFO:
|
||||||
|
Logger::setLogLevel(LOG_LEVEL_INFO);
|
||||||
|
break;
|
||||||
|
case LOG_LEVEL_DEBUG:
|
||||||
|
Logger::setLogLevel(LOG_LEVEL_DEBUG);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
std::cerr << "kiss::Logger: unknown log level in LOG_LEVEL '"
|
||||||
|
<< level << " values from 0-3 expected." << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace kiss
|
||||||
|
|
49
vendor/logger.h
vendored
Normal file
49
vendor/logger.h
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef LOG_H_
|
||||||
|
#define LOG_H_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace kiss {
|
||||||
|
|
||||||
|
enum eLogLevel {
|
||||||
|
LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
static std::ostream *stream;
|
||||||
|
static eLogLevel level;
|
||||||
|
public:
|
||||||
|
Logger(eLogLevel level);
|
||||||
|
~Logger();
|
||||||
|
static std::ostream &getLogStream();
|
||||||
|
static void setLogStream(std::ostream *s);
|
||||||
|
static void setLogStream(std::ostream &s);
|
||||||
|
|
||||||
|
static void setLogLevel(eLogLevel level);
|
||||||
|
static eLogLevel getLogLevel();
|
||||||
|
|
||||||
|
static void loadEnvLogLevel();
|
||||||
|
|
||||||
|
operator std::ostream &() {
|
||||||
|
return getLogStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> inline Logger& operator<<(T& data) {
|
||||||
|
getLogStream() << data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Logger& operator<<(std::ostream& (*func)(std::ostream&)) {
|
||||||
|
getLogStream() << func;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace kiss
|
||||||
|
|
||||||
|
#define LOG_ERROR if (kiss::Logger::getLogLevel() < kiss::LOG_LEVEL_ERROR) {} else kiss::Logger(kiss::LOG_LEVEL_ERROR)
|
||||||
|
#define LOG_WARING if (kiss::Logger::getLogLevel() < kiss::LOG_LEVEL_WARNING) {} else kiss::Logger(kiss::LOG_LEVEL_WARNING)
|
||||||
|
#define LOG_INFO if (kiss::Logger::getLogLevel() < kiss::LOG_LEVEL_INFO) {} else kiss::Logger(kiss::LOG_LEVEL_INFO)
|
||||||
|
#define LOG_DEBUG if (kiss::Logger::getLogLevel() < kiss::LOG_LEVEL_DEBUG) {} else kiss::Logger(kiss::LOG_LEVEL_DEBUG)
|
||||||
|
|
||||||
|
#endif /* KISSLOG_H_ */
|
225
vendor/mersenne-twister.cpp
vendored
Normal file
225
vendor/mersenne-twister.cpp
vendored
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* The Mersenne Twister pseudo-random number generator (PRNG)
|
||||||
|
*
|
||||||
|
* This is an implementation of fast PRNG called MT19937,
|
||||||
|
* meaning it has a period of 2^19937-1, which is a Mersenne
|
||||||
|
* prime.
|
||||||
|
*
|
||||||
|
* This PRNG is fast and suitable for non-cryptographic code.
|
||||||
|
* For instance, it would be perfect for Monte Carlo simulations,
|
||||||
|
* etc.
|
||||||
|
*
|
||||||
|
* For all the details on this algorithm, see the original paper:
|
||||||
|
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf
|
||||||
|
*
|
||||||
|
* Written by Christian Stigen Larsen
|
||||||
|
* http://csl.name
|
||||||
|
*
|
||||||
|
* Distributed under the modified BSD license.
|
||||||
|
*
|
||||||
|
* 2015-02-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mersenne-twister.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have an array of 624 32-bit values, and there are
|
||||||
|
* 31 unused bits, so we have a seed value of
|
||||||
|
* 624*32-31 = 19937 bits.
|
||||||
|
*/
|
||||||
|
static const unsigned SIZE = 624;
|
||||||
|
static const unsigned PERIOD = 397;
|
||||||
|
static const unsigned DIFF = SIZE-PERIOD;
|
||||||
|
|
||||||
|
static uint32_t MT[SIZE];
|
||||||
|
static unsigned index = 0;
|
||||||
|
|
||||||
|
#define M32(x) (0x80000000 & x) // 32nd Most Significant Bit
|
||||||
|
#define L31(x) (0x7FFFFFFF & x) // 31 Least Significant Bits
|
||||||
|
#define ODD(x) (x & 1) // Check if number is odd
|
||||||
|
|
||||||
|
#define UNROLL(expr) \
|
||||||
|
y = M32(MT[i]) | L31(MT[i+1]); \
|
||||||
|
MT[i] = MT[expr] ^ (y>>1) ^ MATRIX[ODD(y)]; \
|
||||||
|
++i;
|
||||||
|
|
||||||
|
static inline void generate_numbers()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Originally, we had one loop with i going from [0, SIZE) and
|
||||||
|
* two modulus operations:
|
||||||
|
*
|
||||||
|
* for ( register unsigned i=0; i<SIZE; ++i ) {
|
||||||
|
* register uint32_t y = M32(MT[i]) | L31(MT[(i+1) % SIZE]);
|
||||||
|
* MT[i] = MT[(i + PERIOD) % SIZE] ^ (y>>1);
|
||||||
|
* if ( ODD(y) ) MT[i] ^= 0x9908b0df;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* For performance reasons, we've unrolled the loop three times, thus
|
||||||
|
* mitigating the need for any modulus operations.
|
||||||
|
*
|
||||||
|
* Anyway, it seems this trick is old hat:
|
||||||
|
* http://www.quadibloc.com/crypto/co4814.htm
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const uint32_t MATRIX[2] = {0, 0x9908b0df};
|
||||||
|
register uint32_t y, i=0;
|
||||||
|
|
||||||
|
// i = [0 ... 225]
|
||||||
|
while ( i<(DIFF-1) ) {
|
||||||
|
/*
|
||||||
|
* We're doing 226 = 113*2, an even number of steps, so we can
|
||||||
|
* safely unroll one more step here for speed:
|
||||||
|
*/
|
||||||
|
UNROLL(i+PERIOD);
|
||||||
|
UNROLL(i+PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// i = 226
|
||||||
|
UNROLL((i+PERIOD) % SIZE);
|
||||||
|
|
||||||
|
// i = [227 ... 622]
|
||||||
|
while ( i<(SIZE-1) ) {
|
||||||
|
/*
|
||||||
|
* 623-227 = 396 = 2*2*3*3*11, so we can unroll this loop in any number
|
||||||
|
* that evenly divides 396 (2, 4, 6, etc). Here we'll unroll 11 times.
|
||||||
|
*/
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
UNROLL(i-DIFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// i = 623
|
||||||
|
y = M32(MT[SIZE-1]) | L31(MT[0]); \
|
||||||
|
MT[SIZE-1] = MT[PERIOD-1] ^ (y>>1) ^ MATRIX[ODD(y)]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void seed(uint32_t value)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The equation below is a linear congruential generator (LCG),
|
||||||
|
* one of the oldest known pseudo-random number generator
|
||||||
|
* algorithms, in the form X_(n+1) = = (a*X_n + c) (mod m).
|
||||||
|
*
|
||||||
|
* We've implicitly got m=32 (mask + word size of 32 bits), so
|
||||||
|
* there is no need to explicitly use modulus.
|
||||||
|
*
|
||||||
|
* What is interesting is the multiplier a. The one we have
|
||||||
|
* below is 0x6c07865 --- 1812433253 in decimal, and is called
|
||||||
|
* the Borosh-Niederreiter multiplier for modulus 2^32.
|
||||||
|
*
|
||||||
|
* It is mentioned in passing in Knuth's THE ART OF COMPUTER
|
||||||
|
* PROGRAMMING, Volume 2, page 106, Table 1, line 13. LCGs are
|
||||||
|
* treated in the same book, pp. 10-26
|
||||||
|
*
|
||||||
|
* You can read the original paper by Borosh and Niederreiter
|
||||||
|
* as well. It's called OPTIMAL MULTIPLIERS FOR PSEUDO-RANDOM
|
||||||
|
* NUMBER GENERATION BY THE LINEAR CONGRUENTIAL METHOD (1983) at
|
||||||
|
* http://www.springerlink.com/content/n7765ku70w8857l7/
|
||||||
|
*
|
||||||
|
* You can read about LCGs at:
|
||||||
|
* http://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||||
|
*
|
||||||
|
* From that page, it says:
|
||||||
|
* "A common Mersenne twister implementation, interestingly
|
||||||
|
* enough, uses an LCG to generate seed data.",
|
||||||
|
*
|
||||||
|
* Since we're using 32-bits data types for our MT array, we can skip the
|
||||||
|
* masking with 0xFFFFFFFF below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MT[0] = value;
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
for ( register unsigned i=1; i<SIZE; ++i )
|
||||||
|
MT[i] = 0x6c078965*(MT[i-1] ^ MT[i-1]>>30) + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" uint32_t rand_u32()
|
||||||
|
{
|
||||||
|
if ( !index )
|
||||||
|
generate_numbers();
|
||||||
|
|
||||||
|
register uint32_t y = MT[index];
|
||||||
|
|
||||||
|
// Tempering
|
||||||
|
y ^= y>>11;
|
||||||
|
y ^= y<< 7 & 0x9d2c5680;
|
||||||
|
y ^= y<<15 & 0xefc60000;
|
||||||
|
y ^= y>>18;
|
||||||
|
|
||||||
|
if ( ++index == SIZE )
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int rand()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* PORTABILITY WARNING:
|
||||||
|
*
|
||||||
|
* rand_u32() uses all 32-bits for the pseudo-random number,
|
||||||
|
* but rand() must return a number from 0 ... RAND_MAX.
|
||||||
|
*
|
||||||
|
* We'll just assume that rand() only uses 31 bits worth of
|
||||||
|
* data, and that we're on a two's complement system.
|
||||||
|
*
|
||||||
|
* So, to output an integer compatible with rand(), we have
|
||||||
|
* two options: Either mask off the highest (32nd) bit, or
|
||||||
|
* shift right by one bit. Masking with 0x7FFFFFFF will be
|
||||||
|
* compatible with 64-bit MT[], so we'll just use that here.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
return static_cast<int>(0x7FFFFFFF & rand_u32());
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void srand(unsigned value)
|
||||||
|
{
|
||||||
|
seed(static_cast<uint32_t>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" float randf_cc()
|
||||||
|
{
|
||||||
|
return static_cast<float>(rand_u32())/UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" float randf_co()
|
||||||
|
{
|
||||||
|
return static_cast<float>(rand_u32())/(UINT32_MAX+1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" float randf_oo()
|
||||||
|
{
|
||||||
|
return (static_cast<float>(rand_u32())+0.5f)/(UINT32_MAX+1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" double randd_cc()
|
||||||
|
{
|
||||||
|
return static_cast<double>(rand_u32())/UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" double randd_co()
|
||||||
|
{
|
||||||
|
return static_cast<double>(rand_u32())/(UINT32_MAX+1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" double randd_oo()
|
||||||
|
{
|
||||||
|
return (static_cast<double>(rand_u32())+0.5)/(UINT32_MAX+1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" uint64_t rand_u64()
|
||||||
|
{
|
||||||
|
return static_cast<uint64_t>(rand_u32())<<32 | rand_u32();
|
||||||
|
}
|
107
vendor/mersenne-twister.h
vendored
Normal file
107
vendor/mersenne-twister.h
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* The Mersenne Twister pseudo-random number generator (PRNG)
|
||||||
|
*
|
||||||
|
* This is an implementation of fast PRNG called MT19937,
|
||||||
|
* meaning it has a period of 2^19937-1, which is a Mersenne
|
||||||
|
* prime.
|
||||||
|
*
|
||||||
|
* This PRNG is fast and suitable for non-cryptographic code.
|
||||||
|
* For instance, it would be perfect for Monte Carlo simulations,
|
||||||
|
* etc.
|
||||||
|
*
|
||||||
|
* This code has been designed as a drop-in replacement for libc rand and
|
||||||
|
* srand(). If you need to mix them, you should encapsulate this code in a
|
||||||
|
* namespace.
|
||||||
|
*
|
||||||
|
* Written by Christian Stigen Larsen
|
||||||
|
* http://csl.name
|
||||||
|
*
|
||||||
|
* Distributed under the modified BSD license.
|
||||||
|
*
|
||||||
|
* 2015-02-17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MERSENNE_TWISTER_H
|
||||||
|
#define MERSENNE_TWISTER_H
|
||||||
|
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum number you can get from rand().
|
||||||
|
*/
|
||||||
|
#undef RAND_MAX
|
||||||
|
#define RAND_MAX INT32_MAX
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the number generator with given seed.
|
||||||
|
* (LIBC REPLACEMENT FUNCTION)
|
||||||
|
*/
|
||||||
|
void srand(unsigned seed_value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract a pseudo-random integer in the range 0 ... RAND_MAX.
|
||||||
|
* (LIBC REPLACEMENT FUNCTION)
|
||||||
|
*/
|
||||||
|
int rand();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract a pseudo-random unsigned 32-bit integer in the range 0 ... UINT32_MAX
|
||||||
|
*/
|
||||||
|
uint32_t rand_u32();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Combine two unsigned 32-bit pseudo-random numbers into one 64-bit
|
||||||
|
*/
|
||||||
|
uint64_t rand_u64();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize Mersenne Twister with given seed value.
|
||||||
|
*/
|
||||||
|
void seed(uint32_t seed_value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a random float in the CLOSED range [0, 1]
|
||||||
|
* Mnemonic: randf_co = random float 0=closed 1=closed
|
||||||
|
*/
|
||||||
|
float randf_cc();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a random float in the OPEN range [0, 1>
|
||||||
|
* Mnemonic: randf_co = random float 0=closed 1=open
|
||||||
|
*/
|
||||||
|
float randf_co();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a random float in the OPEN range <0, 1>
|
||||||
|
* Mnemonic: randf_oo = random float 0=open 1=open
|
||||||
|
*/
|
||||||
|
float randf_oo();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a random double in the CLOSED range [0, 1]
|
||||||
|
* Mnemonic: randd_co = random double 0=closed 1=closed
|
||||||
|
*/
|
||||||
|
double randd_cc();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a random double in the OPEN range [0, 1>
|
||||||
|
* Mnemonic: randd_co = random double 0=closed 1=open
|
||||||
|
*/
|
||||||
|
double randd_co();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a random double in the OPEN range <0, 1>
|
||||||
|
* Mnemonic: randd_oo = random double 0=open 1=open
|
||||||
|
*/
|
||||||
|
double randd_oo();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MERSENNE_TWISTER_H
|
1458
vendor/stb_image_write.h
vendored
Normal file
1458
vendor/stb_image_write.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
583
vendor/stb_rect_pack.h
vendored
Normal file
583
vendor/stb_rect_pack.h
vendored
Normal file
@ -0,0 +1,583 @@
|
|||||||
|
// stb_rect_pack.h - v0.10 - public domain - rectangle packing
|
||||||
|
// Sean Barrett 2014
|
||||||
|
//
|
||||||
|
// Useful for e.g. packing rectangular textures into an atlas.
|
||||||
|
// Does not do rotation.
|
||||||
|
//
|
||||||
|
// Not necessarily the awesomest packing method, but better than
|
||||||
|
// the totally naive one in stb_truetype (which is primarily what
|
||||||
|
// this is meant to replace).
|
||||||
|
//
|
||||||
|
// Has only had a few tests run, may have issues.
|
||||||
|
//
|
||||||
|
// More docs to come.
|
||||||
|
//
|
||||||
|
// No memory allocations; uses qsort() and assert() from stdlib.
|
||||||
|
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
|
||||||
|
//
|
||||||
|
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||||
|
//
|
||||||
|
// Please note: better rectangle packers are welcome! Please
|
||||||
|
// implement them to the same API, but with a different init
|
||||||
|
// function.
|
||||||
|
//
|
||||||
|
// Credits
|
||||||
|
//
|
||||||
|
// Library
|
||||||
|
// Sean Barrett
|
||||||
|
// Minor features
|
||||||
|
// Martins Mozeiko
|
||||||
|
// Bugfixes / warning fixes
|
||||||
|
// Jeremy Jaussaud
|
||||||
|
//
|
||||||
|
// Version history:
|
||||||
|
//
|
||||||
|
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||||
|
// 0.09 (2016-08-27) fix compiler warnings
|
||||||
|
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||||
|
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||||
|
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||||
|
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||||
|
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||||
|
// 0.01: initial release
|
||||||
|
//
|
||||||
|
// LICENSE
|
||||||
|
//
|
||||||
|
// This software is dual-licensed to the public domain and under the following
|
||||||
|
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||||
|
// publish, and distribute this file as you see fit.
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// INCLUDE SECTION
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||||
|
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||||
|
|
||||||
|
#define STB_RECT_PACK_VERSION 1
|
||||||
|
|
||||||
|
#ifdef STBRP_STATIC
|
||||||
|
#define STBRP_DEF static
|
||||||
|
#else
|
||||||
|
#define STBRP_DEF extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct stbrp_context stbrp_context;
|
||||||
|
typedef struct stbrp_node stbrp_node;
|
||||||
|
typedef struct stbrp_rect stbrp_rect;
|
||||||
|
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
typedef int stbrp_coord;
|
||||||
|
#else
|
||||||
|
typedef unsigned short stbrp_coord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||||
|
// Assign packed locations to rectangles. The rectangles are of type
|
||||||
|
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||||
|
// are 'num_rects' many of them.
|
||||||
|
//
|
||||||
|
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||||
|
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||||
|
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||||
|
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||||
|
// have the 'was_packed' flag set to 0.
|
||||||
|
//
|
||||||
|
// You should not try to access the 'rects' array from another thread
|
||||||
|
// while this function is running, as the function temporarily reorders
|
||||||
|
// the array while it executes.
|
||||||
|
//
|
||||||
|
// To pack into another rectangle, you need to call stbrp_init_target
|
||||||
|
// again. To continue packing into the same rectangle, you can call
|
||||||
|
// this function again. Calling this multiple times with multiple rect
|
||||||
|
// arrays will probably produce worse packing results than calling it
|
||||||
|
// a single time with the full rectangle array, but the option is
|
||||||
|
// available.
|
||||||
|
|
||||||
|
struct stbrp_rect
|
||||||
|
{
|
||||||
|
// reserved for your use:
|
||||||
|
int id;
|
||||||
|
|
||||||
|
// input:
|
||||||
|
stbrp_coord w, h;
|
||||||
|
|
||||||
|
// output:
|
||||||
|
stbrp_coord x, y;
|
||||||
|
int was_packed; // non-zero if valid packing
|
||||||
|
|
||||||
|
}; // 16 bytes, nominally
|
||||||
|
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||||
|
// Initialize a rectangle packer to:
|
||||||
|
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||||
|
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||||
|
//
|
||||||
|
// You must call this function every time you start packing into a new target.
|
||||||
|
//
|
||||||
|
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||||
|
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||||
|
// the call (or calls) finish.
|
||||||
|
//
|
||||||
|
// Note: to guarantee best results, either:
|
||||||
|
// 1. make sure 'num_nodes' >= 'width'
|
||||||
|
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||||
|
//
|
||||||
|
// If you don't do either of the above things, widths will be quantized to multiples
|
||||||
|
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||||
|
//
|
||||||
|
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||||
|
// may run out of temporary storage and be unable to pack some rectangles.
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||||
|
// Optionally call this function after init but before doing any packing to
|
||||||
|
// change the handling of the out-of-temp-memory scenario, described above.
|
||||||
|
// If you call init again, this will be reset to the default (false).
|
||||||
|
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||||
|
// Optionally select which packing heuristic the library should use. Different
|
||||||
|
// heuristics will produce better/worse results for different data sets.
|
||||||
|
// If you call init again, this will be reset to the default.
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBRP_HEURISTIC_Skyline_default=0,
|
||||||
|
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||||
|
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// the details of the following structures don't matter to you, but they must
|
||||||
|
// be visible so you can handle the memory allocations for them
|
||||||
|
|
||||||
|
struct stbrp_node
|
||||||
|
{
|
||||||
|
stbrp_coord x,y;
|
||||||
|
stbrp_node *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct stbrp_context
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int align;
|
||||||
|
int init_mode;
|
||||||
|
int heuristic;
|
||||||
|
int num_nodes;
|
||||||
|
stbrp_node *active_head;
|
||||||
|
stbrp_node *free_head;
|
||||||
|
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// IMPLEMENTATION SECTION
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
#ifndef STBRP_SORT
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define STBRP_SORT qsort
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STBRP_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#define STBRP_ASSERT assert
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define STBRP__NOTUSED(v) (void)(v)
|
||||||
|
#else
|
||||||
|
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBRP__INIT_skyline = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||||
|
{
|
||||||
|
switch (context->init_mode) {
|
||||||
|
case STBRP__INIT_skyline:
|
||||||
|
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||||
|
context->heuristic = heuristic;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
STBRP_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||||
|
{
|
||||||
|
if (allow_out_of_mem)
|
||||||
|
// if it's ok to run out of memory, then don't bother aligning them;
|
||||||
|
// this gives better packing, but may fail due to OOM (even though
|
||||||
|
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||||
|
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||||
|
context->align = 1;
|
||||||
|
else {
|
||||||
|
// if it's not ok to run out of memory, then quantize the widths
|
||||||
|
// so that num_nodes is always enough nodes.
|
||||||
|
//
|
||||||
|
// I.e. num_nodes * align >= width
|
||||||
|
// align >= width / num_nodes
|
||||||
|
// align = ceil(width/num_nodes)
|
||||||
|
|
||||||
|
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
#ifndef STBRP_LARGE_RECTS
|
||||||
|
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i=0; i < num_nodes-1; ++i)
|
||||||
|
nodes[i].next = &nodes[i+1];
|
||||||
|
nodes[i].next = NULL;
|
||||||
|
context->init_mode = STBRP__INIT_skyline;
|
||||||
|
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||||
|
context->free_head = &nodes[0];
|
||||||
|
context->active_head = &context->extra[0];
|
||||||
|
context->width = width;
|
||||||
|
context->height = height;
|
||||||
|
context->num_nodes = num_nodes;
|
||||||
|
stbrp_setup_allow_out_of_mem(context, 0);
|
||||||
|
|
||||||
|
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||||
|
context->extra[0].x = 0;
|
||||||
|
context->extra[0].y = 0;
|
||||||
|
context->extra[0].next = &context->extra[1];
|
||||||
|
context->extra[1].x = (stbrp_coord) width;
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
context->extra[1].y = (1<<30);
|
||||||
|
#else
|
||||||
|
context->extra[1].y = 65535;
|
||||||
|
#endif
|
||||||
|
context->extra[1].next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find minimum y position if it starts at x1
|
||||||
|
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||||
|
{
|
||||||
|
stbrp_node *node = first;
|
||||||
|
int x1 = x0 + width;
|
||||||
|
int min_y, visited_width, waste_area;
|
||||||
|
|
||||||
|
STBRP__NOTUSED(c);
|
||||||
|
|
||||||
|
STBRP_ASSERT(first->x <= x0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// skip in case we're past the node
|
||||||
|
while (node->next->x <= x0)
|
||||||
|
++node;
|
||||||
|
#else
|
||||||
|
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STBRP_ASSERT(node->x <= x0);
|
||||||
|
|
||||||
|
min_y = 0;
|
||||||
|
waste_area = 0;
|
||||||
|
visited_width = 0;
|
||||||
|
while (node->x < x1) {
|
||||||
|
if (node->y > min_y) {
|
||||||
|
// raise min_y higher.
|
||||||
|
// we've accounted for all waste up to min_y,
|
||||||
|
// but we'll now add more waste for everything we've visted
|
||||||
|
waste_area += visited_width * (node->y - min_y);
|
||||||
|
min_y = node->y;
|
||||||
|
// the first time through, visited_width might be reduced
|
||||||
|
if (node->x < x0)
|
||||||
|
visited_width += node->next->x - x0;
|
||||||
|
else
|
||||||
|
visited_width += node->next->x - node->x;
|
||||||
|
} else {
|
||||||
|
// add waste area
|
||||||
|
int under_width = node->next->x - node->x;
|
||||||
|
if (under_width + visited_width > width)
|
||||||
|
under_width = width - visited_width;
|
||||||
|
waste_area += under_width * (min_y - node->y);
|
||||||
|
visited_width += under_width;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pwaste = waste_area;
|
||||||
|
return min_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int x,y;
|
||||||
|
stbrp_node **prev_link;
|
||||||
|
} stbrp__findresult;
|
||||||
|
|
||||||
|
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||||
|
{
|
||||||
|
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||||
|
stbrp__findresult fr;
|
||||||
|
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||||
|
|
||||||
|
// align to multiple of c->align
|
||||||
|
width = (width + c->align - 1);
|
||||||
|
width -= width % c->align;
|
||||||
|
STBRP_ASSERT(width % c->align == 0);
|
||||||
|
|
||||||
|
node = c->active_head;
|
||||||
|
prev = &c->active_head;
|
||||||
|
while (node->x + width <= c->width) {
|
||||||
|
int y,waste;
|
||||||
|
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||||
|
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||||
|
// bottom left
|
||||||
|
if (y < best_y) {
|
||||||
|
best_y = y;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// best-fit
|
||||||
|
if (y + height <= c->height) {
|
||||||
|
// can only use it if it first vertically
|
||||||
|
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||||
|
best_y = y;
|
||||||
|
best_waste = waste;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = &node->next;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||||
|
|
||||||
|
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||||
|
//
|
||||||
|
// e.g, if fitting
|
||||||
|
//
|
||||||
|
// ____________________
|
||||||
|
// |____________________|
|
||||||
|
//
|
||||||
|
// into
|
||||||
|
//
|
||||||
|
// | |
|
||||||
|
// | ____________|
|
||||||
|
// |____________|
|
||||||
|
//
|
||||||
|
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||||
|
//
|
||||||
|
// This makes BF take about 2x the time
|
||||||
|
|
||||||
|
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||||
|
tail = c->active_head;
|
||||||
|
node = c->active_head;
|
||||||
|
prev = &c->active_head;
|
||||||
|
// find first node that's admissible
|
||||||
|
while (tail->x < width)
|
||||||
|
tail = tail->next;
|
||||||
|
while (tail) {
|
||||||
|
int xpos = tail->x - width;
|
||||||
|
int y,waste;
|
||||||
|
STBRP_ASSERT(xpos >= 0);
|
||||||
|
// find the left position that matches this
|
||||||
|
while (node->next->x <= xpos) {
|
||||||
|
prev = &node->next;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||||
|
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||||
|
if (y + height < c->height) {
|
||||||
|
if (y <= best_y) {
|
||||||
|
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||||
|
best_x = xpos;
|
||||||
|
STBRP_ASSERT(y <= best_y);
|
||||||
|
best_y = y;
|
||||||
|
best_waste = waste;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tail = tail->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fr.prev_link = best;
|
||||||
|
fr.x = best_x;
|
||||||
|
fr.y = best_y;
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||||
|
{
|
||||||
|
// find best position according to heuristic
|
||||||
|
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||||
|
stbrp_node *node, *cur;
|
||||||
|
|
||||||
|
// bail if:
|
||||||
|
// 1. it failed
|
||||||
|
// 2. the best node doesn't fit (we don't always check this)
|
||||||
|
// 3. we're out of memory
|
||||||
|
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||||
|
res.prev_link = NULL;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on success, create new node
|
||||||
|
node = context->free_head;
|
||||||
|
node->x = (stbrp_coord) res.x;
|
||||||
|
node->y = (stbrp_coord) (res.y + height);
|
||||||
|
|
||||||
|
context->free_head = node->next;
|
||||||
|
|
||||||
|
// insert the new node into the right starting point, and
|
||||||
|
// let 'cur' point to the remaining nodes needing to be
|
||||||
|
// stiched back in
|
||||||
|
|
||||||
|
cur = *res.prev_link;
|
||||||
|
if (cur->x < res.x) {
|
||||||
|
// preserve the existing one, so start testing with the next one
|
||||||
|
stbrp_node *next = cur->next;
|
||||||
|
cur->next = node;
|
||||||
|
cur = next;
|
||||||
|
} else {
|
||||||
|
*res.prev_link = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// from here, traverse cur and free the nodes, until we get to one
|
||||||
|
// that shouldn't be freed
|
||||||
|
while (cur->next && cur->next->x <= res.x + width) {
|
||||||
|
stbrp_node *next = cur->next;
|
||||||
|
// move the current node to the free list
|
||||||
|
cur->next = context->free_head;
|
||||||
|
context->free_head = cur;
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stitch the list back in
|
||||||
|
node->next = cur;
|
||||||
|
|
||||||
|
if (cur->x < res.x + width)
|
||||||
|
cur->x = (stbrp_coord) (res.x + width);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
cur = context->active_head;
|
||||||
|
while (cur->x < context->width) {
|
||||||
|
STBRP_ASSERT(cur->x < cur->next->x);
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(cur->next == NULL);
|
||||||
|
|
||||||
|
{
|
||||||
|
stbrp_node *L1 = NULL, *L2 = NULL;
|
||||||
|
int count=0;
|
||||||
|
cur = context->active_head;
|
||||||
|
while (cur) {
|
||||||
|
L1 = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
cur = context->free_head;
|
||||||
|
while (cur) {
|
||||||
|
L2 = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(count == context->num_nodes+2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rect_height_compare(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
if (p->h > q->h)
|
||||||
|
return -1;
|
||||||
|
if (p->h < q->h)
|
||||||
|
return 1;
|
||||||
|
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rect_width_compare(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
if (p->w > q->w)
|
||||||
|
return -1;
|
||||||
|
if (p->w < q->w)
|
||||||
|
return 1;
|
||||||
|
return (p->h > q->h) ? -1 : (p->h < q->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rect_original_order(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
#define STBRP__MAXVAL 0xffffffff
|
||||||
|
#else
|
||||||
|
#define STBRP__MAXVAL 0xffff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
rects[i].was_packed = i;
|
||||||
|
#ifndef STBRP_LARGE_RECTS
|
||||||
|
STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort according to heuristic
|
||||||
|
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||||
|
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||||
|
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||||
|
} else {
|
||||||
|
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||||
|
if (fr.prev_link) {
|
||||||
|
rects[i].x = (stbrp_coord) fr.x;
|
||||||
|
rects[i].y = (stbrp_coord) fr.y;
|
||||||
|
} else {
|
||||||
|
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsort
|
||||||
|
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||||
|
|
||||||
|
// set was_packed flags
|
||||||
|
for (i=0; i < num_rects; ++i)
|
||||||
|
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||||
|
}
|
||||||
|
#endif
|
1322
vendor/stb_textedit.h
vendored
Normal file
1322
vendor/stb_textedit.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4018
vendor/stb_truetype.h
vendored
Normal file
4018
vendor/stb_truetype.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user