extract Mesh and GLMesh

This commit is contained in:
Gero Müller 2017-11-03 09:22:38 +10:00
parent 07ed96f16d
commit e16915428c
9 changed files with 409 additions and 338 deletions

View File

@ -2,8 +2,7 @@
#include "Mesh.h"
#include "Shader.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "gl.h"
#include <glm/mat4x4.hpp>
#include <glm/mat3x3.hpp>
@ -27,30 +26,6 @@ using glm::uvec3;
using std::map;
using std::vector;
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));}
static void error_callback(int error, const char* description) {
fprintf(stderr, "Error: %s\n", description);
}
@ -80,12 +55,11 @@ static void char_callback(GLFWwindow* window, unsigned int c) {
Application::Application() :
window(0), density(), densityIsolevel(0.2), polygonizer(density,
densityIsolevel), textureSize(512), texturemapper(density,
textureSize), programId(0), vPositionLoc(-1), vTexCoordLoc(-1), vNormalLoc(
-1), meteoridCount(1000), meteroidMinRadius(0.005), meteroidMaxRadius(
0.2), meteroidSizeExponent(2048), densityFrequency(2), densityOctave(
2), densityScale(1.0f), resolution(0.1), smoothMesh(true), viewDistance(
3.0f), fpsMode(false), meshUploadRequest(false), textureUploadRequest(
false) {
textureSize), programId(0), meteoridCount(1000), meteroidMinRadius(
0.005), meteroidMaxRadius(0.2), meteroidSizeExponent(2048), densityFrequency(
2), densityOctave(2), densityScale(1.0f), resolution(0.1), smoothMesh(
true), viewDistance(3.0f), fpsMode(false), meshUploadRequest(
false), textureUploadRequest(false) {
init();
}
@ -145,31 +119,20 @@ void Application::init() {
ImGui_ImplGlfwGL3_Init(window, false);
GLCK(glGenVertexArrays(1, &vertexArrayId))
GLCK(glGenBuffers(1, &vPositionId))
GLCK(glGenBuffers(1, &vTexCoordId))
GLCK(glGenBuffers(1, &vNormalId))
GLCK(glGenBuffers(1, &indexBufferId))
GLCK(glGenTextures(1, &tAlbedoId))
GLCK(glGenTextures(1, &tNormalId))
GLCK(glGenTextures(1, &tRoughnessId))
GLCK(glGenTextures(1, &tMetalicId))
loadShader();
updateVertexArrayObject();
glMesh.create();
glMesh.update(vPositionLoc, vNormalLoc, vTexCoordLoc);
generateAsteroid();
}
void Application::shutdown() {
ImGui_ImplGlfwGL3_Shutdown();
GLCK(glDeleteBuffers(1, &vPositionId))
GLCK(glDeleteBuffers(1, &vTexCoordId))
GLCK(glDeleteBuffers(1, &vNormalId))
GLCK(glDeleteBuffers(1, &indexBufferId))
GLCK(glDeleteVertexArrays(1, &vertexArrayId))
glfwDestroyWindow(window);
glfwTerminate();
}
@ -217,15 +180,16 @@ void Application::toogleFpsMode() {
void Application::generateAsteroid() {
if (meshProgress.begin("Random Impacts", 1)) {
//if (density.getImpacts().size() == 0)
density.addRandomImpacts(1000, densityIsolevel, 0.01, 0.005, 0.2, 256);
if (density.getImpacts().size() == 0)
density.addRandomImpacts(1000, densityIsolevel, 0.01, 0.005, 0.2,
256);
//density.saveCrossSection("density.png", 512);
}
polygonizer.polygonize(resolution, meshProgress);
if (smoothMesh && meshProgress.begin("Smooth", 1)) {
smooth(polygonizer.vertices, polygonizer.indices);
polygonizer.mesh.smooth();
// {
// std::ofstream out("stage2.obj");
// saveAttrib(out, "v ", polygonizer.vertices);
@ -233,72 +197,40 @@ void Application::generateAsteroid() {
// }
}
uvec4v_t edges;
if (meshProgress.begin("Find Edges", 1)) {
findEdges(polygonizer.vertices, polygonizer.indices, edges);
}
uvec3v_t adjacents;
if (meshProgress.begin("Find Adjacent", 1)) {
findAdjacent(edges, polygonizer.indices.size(), adjacents);
}
vec3v_t faceNormals;
calculateFaceNormals(polygonizer.vertices, polygonizer.indices,
faceNormals);
vec3v_t positions;
uvec3v_t indices;
uintv_t patches;
createPatches(polygonizer.vertices, polygonizer.indices, faceNormals,
adjacents, positions, indices, patches, 0.9);
{
std::ofstream out("stage1.obj");
saveAttrib(out, "v ", positions);
saveFaces(out, indices, 1);
if (meshProgress.begin("Generate Edges", 1)) {
polygonizer.mesh.generateEdges();
}
if (meshProgress.begin("Calculate Vertex Normals", 1)) {
calculateVertexNormals(polygonizer.vertices, polygonizer.indices,
normals);
// {
// std::ofstream out("stage3.obj");
// saveAttrib(out, "v ", polygonizer.vertices);
// saveAttrib(out, "vn ", normals);
// saveFaces(out, polygonizer.indices, 2);
// }
if (meshProgress.begin("Generate Adjacent", 1)) {
polygonizer.mesh.generateAdjacent();
}
std::cout << "Vertices: " << polygonizer.vertices.size() << std::endl;
std::cout << "Triangles: " << polygonizer.indices.size() << std::endl;
if (meshProgress.begin("Generate Face Normals", 1)) {
polygonizer.mesh.generateFaceNormals();
}
if (meshProgress.begin("Generate Vertex Normals", 1)) {
polygonizer.mesh.generateNormals();
}
if (meshProgress.begin("Generate Patched", 1)) {
mesh = polygonizer.mesh.createPatched(0.9);
}
if (meshProgress.begin("Save Patched", 1)) {
mesh.save("patched.obj");
}
if (meshProgress.begin("Map Textures", 1)) {
texturemapper.map(polygonizer.vertices, normals, polygonizer.indices);
texturemapper.map(mesh.positions, mesh.normals, mesh.indices);
}
if (meshProgress.begin("Move To Mean", 1)) {
moveToMean(texturemapper.vertices);
// {
// std::ofstream out("stage4.obj");
// saveAttrib(out, "v ", texturemapper.vertices);
// saveAttrib(out, "vn ", texturemapper.normals);
// saveAttrib(out, "vt ", texturemapper.texcoords);
// saveFaces(out, texturemapper.indices, 3);
// }
mesh.moveToMean();
}
if (meshProgress.begin("Save", 4)) {
std::ofstream out("asteroid.obj");
saveAttrib(out, "v ", texturemapper.vertices);
meshProgress.advance();
saveAttrib(out, "vn ", texturemapper.normals);
meshProgress.advance();
saveAttrib(out, "vt ", texturemapper.texcoords);
meshProgress.advance();
saveFaces(out, texturemapper.indices, 3);
meshProgress.advance();
mesh.save("final.obj");
}
meshProgress.finish();
@ -310,40 +242,6 @@ void Application::generateAsteroid() {
}
bool Application::bindVertexAttrib(GLuint id, GLint loc, GLuint size) {
if (loc < 0)
return false;
GLCK(glBindBuffer(GL_ARRAY_BUFFER, id))
GLCK(glEnableVertexAttribArray(loc))
GLCK(glVertexAttribPointer(loc, // attribute
size,// size
GL_FLOAT,// type
GL_FALSE,// normalized?
0,// stride
(void* ) 0// array buffer offset
))
return true;
}
void Application::updateVertexArrayObject() {
GLCK(glBindVertexArray(vertexArrayId))
if (vPositionLoc >= 0)
GLCK(glDisableVertexAttribArray(vPositionLoc))
if (vNormalLoc >= 0)
GLCK(glDisableVertexAttribArray(vNormalLoc))
if (vTexCoordLoc >= 0)
GLCK(glDisableVertexAttribArray(vTexCoordLoc))
bindVertexAttrib(vPositionId, vPositionLoc, 3);
bindVertexAttrib(vNormalId, vNormalLoc, 3);
bindVertexAttrib(vTexCoordId, vTexCoordLoc, 2);
GLCK(glBindVertexArray(0))
}
void Application::loadShader() {
if (programId >= 0)
GLCK(glDeleteProgram(programId))
@ -365,29 +263,6 @@ void Application::loadShader() {
GLCK(tMetalicLoc = glGetAttribLocation(programId, "tMetalic"))
}
void Application::uploadMesh() {
printf("upload mesh\n");
GLCK(glBindVertexArray(vertexArrayId))
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vPositionId))
GLCK(
glBufferData(GL_ARRAY_BUFFER, texturemapper.vertices.size() * sizeof(vec3), texturemapper.vertices.data(), GL_STATIC_DRAW))
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vTexCoordId))
GLCK(
glBufferData(GL_ARRAY_BUFFER, texturemapper.texcoords.size() * sizeof(glm::vec2), texturemapper.texcoords.data(), GL_STATIC_DRAW))
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vNormalId))
GLCK(
glBufferData(GL_ARRAY_BUFFER, texturemapper.normals.size() * sizeof(vec3), texturemapper.normals.data(), GL_STATIC_DRAW))
GLCK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId))
GLCK(
glBufferData(GL_ELEMENT_ARRAY_BUFFER, texturemapper.indices.size() * sizeof(uvec3), texturemapper.indices.data(), GL_STATIC_DRAW))
GLCK(glBindVertexArray(0))
}
void Application::uploadTexture() {
printf("upload texture\n");
glBindTexture(GL_TEXTURE_2D, tAlbedoId);
@ -399,11 +274,11 @@ void Application::uploadTexture() {
}
void Application::renderMesh() {
GLCK(glBindVertexArray(vertexArrayId))
GLCK(
glDrawElements(GL_TRIANGLES, texturemapper.indices.size() * 3, GL_UNSIGNED_INT, (void* ) 0))
GLCK(glBindVertexArray(0))
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glMesh.render();
}
void Application::prepareShader() {
@ -507,8 +382,8 @@ void Application::prepareShader() {
void Application::gui() {
ImGui::Begin("Mesh Generation");
ImGui::Text("Vertices: %lu, Triangles: %lu", polygonizer.vertices.size(),
polygonizer.indices.size());
ImGui::Text("Vertices: %lu, Triangles: %lu", mesh.positions.size(),
mesh.indices.size());
//ImGui::InputFloat("Resolution", &resolution);
ImGui::SliderFloat("Resolution", &resolution, 0.1, 0.001, "%.3f", 0.1);
if (ImGui::SliderFloat("Frequency", &densityFrequency, 1, 10, "%.0f", 1))
@ -546,7 +421,7 @@ void Application::gui() {
ImGui::Begin("Rendering");
if (ImGui::Button("Reload Shader")) {
loadShader();
updateVertexArrayObject();
glMesh.update(vPositionLoc, vNormalLoc, vTexCoordLoc);
}
if (ImGui::Button("Wireframe"))
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
@ -574,12 +449,9 @@ void Application::run() {
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
if (meshUploadRequest) {
uploadMesh();
glMesh.upload(mesh);
meshUploadRequest = false;
}
if (textureUploadRequest) {

View File

@ -4,6 +4,7 @@
#include "Polygoniser.h"
#include "TextureMapper.h"
#include "ProgressMonitor.h"
#include "gl.h"
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
@ -23,18 +24,14 @@ class Application {
float textureSize;
TextureMapper texturemapper;
unsigned int vertexArrayId, vPositionId, vTexCoordId, vNormalId,
indexBufferId, programId, tAlbedoId, tNormalId, tRoughnessId,
tMetalicId;
int vPositionLoc, vTexCoordLoc, vNormalLoc;
unsigned int programId, tAlbedoId, tNormalId, tRoughnessId, tMetalicId;
int MVPloc, Vloc, Mloc, MVloc, LightPosition_worldspaceloc;
int vPositionLoc, vTexCoordLoc, vNormalLoc, tAlbedoLoc, tNormalLoc,
tRoughnessLoc, tMetalicLoc;
int tAlbedoLoc, tNormalLoc, tRoughnessLoc, tMetalicLoc;
vec3v_t vertices;
vec3v_t normals;
vec2v_t texcoords;
uvec3v_t indices;
Mesh mesh;
GLMesh glMesh;
size_t meteoridCount;
float meteroidMinRadius;

View File

@ -1,10 +1,12 @@
#include "Mesh.h"
#include "gl.h"
#include <glm/geometric.hpp>
#include <map>
#include <limits>
#include <stack>
#include <fstream>
using namespace std;
using namespace glm;
@ -12,8 +14,56 @@ using namespace glm;
static const uvec3::value_type InvalidIndex =
numeric_limits<uvec3::value_type>::max();
void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices,
vec3v_t &normals) {
Mesh::Mesh() {
}
Mesh::Mesh(Mesh &other) {
positions = other.positions;
normals = other.normals;
texcoords = other.texcoords;
faceNormals = other.faceNormals;
indices = other.indices;
patches = other.patches;
edges = other.edges;
adjacents = other.adjacents;
tangents = other.tangents;
bitangents = other.bitangents;
}
Mesh::Mesh(Mesh &&other) {
positions.swap(other.positions);
normals.swap(other.normals);
texcoords.swap(other.texcoords);
faceNormals.swap(other.faceNormals);
indices.swap(other.indices);
patches.swap(other.patches);
edges.swap(other.edges);
adjacents.swap(other.adjacents);
tangents.swap(other.tangents);
bitangents.swap(other.bitangents);
}
Mesh& Mesh::operator=(Mesh &&other) {
positions.swap(other.positions);
normals.swap(other.normals);
texcoords.swap(other.texcoords);
faceNormals.swap(other.faceNormals);
indices.swap(other.indices);
patches.swap(other.patches);
edges.swap(other.edges);
adjacents.swap(other.adjacents);
tangents.swap(other.tangents);
bitangents.swap(other.bitangents);
return *this;
}
void Mesh::generateNormals() {
normals.clear();
normals.resize(positions.size(), vec3(0));
#pragma omp parallel for
@ -31,99 +81,19 @@ void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices,
}
void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices,
vec3v_t &normals) {
normals.clear();
normals.resize(indices.size(), vec3(uninitialize));
void Mesh::generateFaceNormals() {
faceNormals.clear();
faceNormals.resize(indices.size(), vec3(uninitialize));
#pragma omp parallel for
for (size_t i = 0; i < indices.size(); i++) {
int a = indices[i].x, b = indices[i].y, c = indices[i].z;
normals[i] = normalize(
faceNormals[i] = normalize(
cross(positions[b] - positions[a],
positions[c] - positions[a]));
}
}
void moveToMean(vec3v_t &positions) {
vec3 mean(0);
for (size_t i = 0; i < positions.size(); i++) {
mean += positions[i];
}
mean *= vec3(1.f / positions.size());
for (size_t i = 0; i < positions.size(); i++) {
positions[i] -= mean;
}
}
void smooth(vec3v_t &positions, const uvec3v_t &indices) {
vec3v_t cogs(positions.size(), vec3(0.f));
vector<int> valence(positions.size(), 0);
for (size_t iTri = 0; iTri < indices.size(); iTri++) {
const uvec3 &idx = indices[iTri];
for (size_t iE = 0; iE < 3; iE++) {
valence[idx[iE]] += 2;
cogs[idx[iE]] += positions[idx[(iE + 1) % 3]];
cogs[idx[iE]] += positions[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);
*/
#pragma omp parallel for
for (size_t i = 0; i < positions.size(); i++) {
// vtx[i] = vtx[i] * vec3(0.8)
// + cogs[i] * vec3(0.2f / valence[i]);
positions[i] = cogs[i] * vec3(1.f / valence[i]);
}
}
void saveAttrib(std::ostream &out, const char *prefix, vec3v_t &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, vec2v_t &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 uvec3v_t &incdices, size_t attribs) {
for (size_t i = 0; i < incdices.size(); i++) {
out << "f";
for (size_t j = 0; j < 3; j++) {
int v = incdices[i][j] + 1;
out << " " << v;
if (attribs > 1)
out << "/" << v;
if (attribs > 2)
out << "/" << v;
out << " ";
}
out << "\n";
}
}
void findEdges(const vec3v_t &positions, const uvec3v_t &indices,
uvec4v_t &edges) {
void Mesh::generateEdges() {
edges.clear();
map<pair<uint32_t, uint32_t>, uint32_t> edgeMap;
for (size_t iTri = 0; iTri < indices.size(); iTri++) {
@ -145,8 +115,7 @@ void findEdges(const vec3v_t &positions, const uvec3v_t &indices,
}
}
void computeTangentBasis(vec3v_t & positions, vec2v_t & texcoords,
vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents) {
void Mesh::generateTangentBasis() {
for (size_t i = 0; i < positions.size(); i += 3) {
@ -185,9 +154,8 @@ void computeTangentBasis(vec3v_t & positions, vec2v_t & texcoords,
}
}
void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents) {
printf("findAdjacent: %lu\n", nFaces);
adjacents.resize(nFaces, uvec3(InvalidIndex));
void Mesh::generateAdjacent() {
adjacents.resize(indices.size(), uvec3(InvalidIndex));
for (size_t i = 0; i < edges.size(); i++) {
int a = edges[i].z;
int b = edges[i].w;
@ -209,14 +177,93 @@ void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents) {
}
}
void createPatches(const vec3v_t &positions, const uvec3v_t &indices,
const vec3v_t &faceNormals, const uvec3v_t &adjacents,
vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches,
float threshold) {
void Mesh::moveToMean() {
vec3 mean(0);
for (size_t i = 0; i < positions.size(); i++) {
mean += positions[i];
}
mean *= vec3(1.f / positions.size());
for (size_t i = 0; i < positions.size(); i++) {
positions[i] -= mean;
}
}
void Mesh::smooth() {
if (positions.size() == 0 || indices.size() == 0)
return;
vec3v_t cogs(positions.size(), vec3(0.f));
vector<int> valence(positions.size(), 0);
for (size_t iTri = 0; iTri < indices.size(); iTri++) {
const uvec3 &idx = indices[iTri];
for (size_t iE = 0; iE < 3; iE++) {
valence[idx[iE]] += 2;
cogs[idx[iE]] += positions[idx[(iE + 1) % 3]];
cogs[idx[iE]] += positions[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);
*/
#pragma omp parallel for
for (size_t i = 0; i < positions.size(); i++) {
// vtx[i] = vtx[i] * vec3(0.8)
// + cogs[i] * vec3(0.2f / valence[i]);
positions[i] = cogs[i] * vec3(1.f / valence[i]);
}
}
void Mesh::saveAttrib(std::ostream &out, const char *prefix,
const vec3v_t &elements) const {
for (size_t i = 0; i < elements.size(); i++) {
out << prefix << elements[i].x << " " << elements[i].y << " "
<< elements[i].z << "\n";
}
}
void Mesh::saveAttrib(std::ostream &out, const char *prefix,
const vec2v_t &elements) const {
for (size_t i = 0; i < elements.size(); i++) {
out << prefix << elements[i].x << " " << elements[i].y << "\n";
}
}
void Mesh::saveFaces(std::ostream &out, const uvec3v_t &incdices,
size_t attribs) const {
for (size_t i = 0; i < incdices.size(); i++) {
out << "f";
for (size_t j = 0; j < 3; j++) {
int v = incdices[i][j] + 1;
out << " " << v;
if (attribs > 1)
out << "/" << v;
if (attribs > 2)
out << "/" << v;
out << " ";
}
out << "\n";
}
}
Mesh Mesh::createPatched(float threshold) const {
assert(adjacents.size() == indices.size());
patches.clear();
oPositions.clear();
oIndices.clear();
Mesh mesh;
vector<bool> processed(indices.size(), false);
for (size_t i = 0; i < indices.size(); i++) {
@ -251,18 +298,39 @@ void createPatches(const vec3v_t &positions, const uvec3v_t &indices,
for (size_t k = 0; k < 3; k++) {
auto it = vertexMap.find(idx[k]);
if (it == vertexMap.end()) {
uint32_t newIdx = oPositions.size();
oPositions.push_back(positions[idx[k]]);
uint32_t newIdx = mesh.positions.size();
mesh.positions.push_back(positions[idx[k]]);
if (normals.size())
mesh.normals.push_back(normals[idx[k]]);
vertexMap[idx[k]] = newIdx;
idx[k] = newIdx;
} else {
idx[k] = it->second;
}
}
oIndices.push_back(idx);
mesh.indices.push_back(idx);
}
printf("\n");
}
return mesh;
}
void Mesh::save(std::ostream &out) const {
size_t nAttribs = 1;
saveAttrib(out, "v ", positions);
if (normals.size()) {
nAttribs++;
saveAttrib(out, "vn ", normals);
}
if (texcoords.size()) {
nAttribs++;
saveAttrib(out, "vt ", texcoords);
}
saveFaces(out, indices, nAttribs);
}
void Mesh::save(std::string filename) const {
std::ofstream out(filename.c_str());
save(out);
}

View File

@ -5,31 +5,43 @@
#include <vector>
#include <ostream>
void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices,
vec3v_t &normals);
void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices,
vec3v_t &normals);
void findEdges(const vec3v_t &positions, const uvec3v_t &indices,
uvec4v_t &edges);
//void createPatches(const vec3v_t &positions, const uvec3v_t &indices,
// const uvec4v_t &edges, vec3v_t &oPositions, uvec3v_t &oIndices,
// uvec4v_t &oEdges, uintv_t &patches, float threshold);
struct Mesh {
vec3v_t positions;
vec3v_t normals;
vec2v_t texcoords;
void moveToMean(vec3v_t &positions);
vec3v_t faceNormals;
uvec3v_t indices;
uintv_t patches;
uvec4v_t edges;
uvec3v_t adjacents;
vec3v_t tangents;
vec3v_t bitangents;
void smooth(vec3v_t &positions, const uvec3v_t &indices);
Mesh();
Mesh(Mesh &other);
Mesh(Mesh &&other);
void saveAttrib(std::ostream &out, const char *prefix, vec3v_t &elements);
Mesh& operator=(Mesh&&);
void saveAttrib(std::ostream &out, const char *prefix, vec2v_t &elements);
void generateNormals();
void generateTangentBasis();
void saveFaces(std::ostream &out, const uvec3v_t &indicess, size_t attributes);
void generateAdjacent();
void generateFaceNormals();
void generateEdges();
void findAdjacent(const uvec4v_t &edges, size_t nFaces, uvec3v_t &adjacents);
void moveToMean();
void smooth();
void computeTangentBasis(vec3v_t & vertices, vec2v_t & texcoords,
vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents);
void createPatches(const vec3v_t &positions, const uvec3v_t &indices,
const vec3v_t &faceNormals, const uvec3v_t &adjacents,
vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches,
float threshold);
Mesh createPatched(float threshold) const;
void saveAttrib(std::ostream &out, const char *prefix,
const vec3v_t &elements) const;
void saveAttrib(std::ostream &out, const char *prefix,
const vec2v_t &elements) const;
void saveFaces(std::ostream &out, const uvec3v_t &indicess,
size_t attributes) const;
void save(std::ostream &out) const;
void save(std::string filename) const;
};

View File

@ -114,7 +114,7 @@ void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper,
for (int iTri = 0; iTri < nTris; iTri++) {
vec3 *ps = tris[iTri].p;
// skip degenerate vertices
// skip degenerate positions
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)))
@ -128,8 +128,8 @@ void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper,
if (vit != vertexLookup.end()) {
idc[k] = vit->second;
} else {
idc[k] = vertices.size();
vertices.push_back(p);
idc[k] = positions.size();
positions.push_back(p);
vertexLookup[p] = idc[k];
}
}
@ -142,7 +142,7 @@ void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper,
void Polygonizer::polygonize(float resolution) {
vertexLookup.clear();
vertices.clear();
positions.clear();
indices.clear();
const float isocellSize = 1.f / isocells;
@ -187,11 +187,11 @@ void Polygonizer::calculateLayer(std::vector<float> &layer, float resolution,
void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
vertexLookup.clear();
vertices.clear();
indices.clear();
mesh.positions.clear();
mesh.indices.clear();
vertices.reserve(pow(1. / resolution, 2) * 8);
indices.reserve(pow(1. / resolution, 2) * 8);
mesh.positions.reserve(pow(1. / resolution, 2) * 8);
mesh.indices.reserve(pow(1. / resolution, 2) * 8);
size_t nSteps = 1.f / resolution;
size_t nSamples = nSteps + 1;
@ -258,7 +258,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
for (int iTri = 0; iTri < nTris; iTri++) {
vec3 *ps = tris[iTri].p;
// skip degenerate vertices
// skip degenerate positions
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)))
@ -272,12 +272,12 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
if (vit != vertexLookup.end()) {
idc[k] = vit->second;
} else {
idc[k] = vertices.size();
vertices.push_back(p);
idc[k] = mesh.positions.size();
mesh.positions.push_back(p);
vertexLookup[p] = idc[k];
}
}
indices.push_back(idc);
mesh.indices.push_back(idc);
}
}
}
@ -287,7 +287,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
//void Polygonizer::polygonize(float resolution) {
// vertexLookup.clear();
// vertices.clear();
// positions.clear();
// indices.clear();
//
// size_t nSteps = 1.f / resolution;
@ -329,7 +329,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
// for (int iTri = 0; iTri < nTris; iTri++) {
// vec3 *ps = tris[iTri].p;
//
// // skip degenerate vertices
// // skip degenerate positions
// 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)))
@ -343,8 +343,8 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
// if (vit != vertexLookup.end()) {
// idc[k] = vit->second;
// } else {
// idc[k] = vertices.size();
// vertices.push_back(p);
// idc[k] = positions.size();
// positions.push_back(p);
// vertexLookup[p] = idc[k];
// }
// }

View File

@ -3,7 +3,7 @@
#include <vector>
#include <map>
#include "types.h"
#include "Mesh.h"
#include "Density.h"
#include "ProgressMonitor.h"
@ -47,8 +47,7 @@ class Polygonizer {
void calculateLayer(std::vector<float> &layer, float resolution, size_t nSamples, float z);
public:
vec3v_t vertices;
uvec3v_t indices;
Mesh mesh;
std::map<glm::vec3, int, CompareVec3> vertexLookup;

View File

@ -6,7 +6,8 @@
using namespace std;
SkyBox::SkyBox() {
SkyBox::SkyBox() :
textureId(GL_INVALID_INDEX), programId(GL_INVALID_INDEX) {
glGenTextures(1, &textureId);
}

121
src/gl.h Normal file
View File

@ -0,0 +1,121 @@
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "types.h"
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));}
class GLMesh {
unsigned int vertexArrayId, vPositionId, vTexCoordId, vNormalId,
indexBufferId;
unsigned int indexCount;
public:
GLMesh() :
vertexArrayId(0), vPositionId(0), vTexCoordId(0), vNormalId(0), indexBufferId(
0), indexCount(0) {
}
~GLMesh() {
GLCK(glDeleteBuffers(1, &vPositionId))
GLCK(glDeleteBuffers(1, &vTexCoordId))
GLCK(glDeleteBuffers(1, &vNormalId))
GLCK(glDeleteBuffers(1, &indexBufferId))
GLCK(glDeleteVertexArrays(1, &vertexArrayId))
}
void create() {
GLCK(glGenVertexArrays(1, &vertexArrayId))
GLCK(glGenBuffers(1, &vPositionId))
GLCK(glGenBuffers(1, &vTexCoordId))
GLCK(glGenBuffers(1, &vNormalId))
GLCK(glGenBuffers(1, &indexBufferId))
}
void upload(const Mesh &mesh) {
printf("upload mesh\n");
GLCK(glBindVertexArray(vertexArrayId))
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vPositionId))
GLCK(
glBufferData(GL_ARRAY_BUFFER, mesh.positions.size() * sizeof(glm::vec3), mesh.positions.data(), GL_STATIC_DRAW))
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vTexCoordId))
GLCK(
glBufferData(GL_ARRAY_BUFFER, mesh.texcoords.size() * sizeof(glm::vec2), mesh.texcoords.data(), GL_STATIC_DRAW))
GLCK(glBindBuffer(GL_ARRAY_BUFFER, vNormalId))
GLCK(
glBufferData(GL_ARRAY_BUFFER, mesh.normals.size() * sizeof(glm::vec3), mesh.normals.data(), GL_STATIC_DRAW))
GLCK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId))
GLCK(
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.indices.size() * sizeof(glm::uvec3), mesh.indices.data(), GL_STATIC_DRAW))
GLCK(glBindVertexArray(0))
indexCount = mesh.indices.size() * 3;
}
void render() {
GLCK(glBindVertexArray(vertexArrayId))
GLCK(
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void* ) 0))
GLCK(glBindVertexArray(0))
}
bool bindVertexAttrib(GLuint id, GLint loc, GLuint size) const {
if (loc < 0) {
GLCK(glDisableVertexAttribArray(loc))
} else {
GLCK(glBindBuffer(GL_ARRAY_BUFFER, id))
GLCK(glEnableVertexAttribArray(loc))
GLCK(glVertexAttribPointer(loc, // attribute
size,// size
GL_FLOAT,// type
GL_FALSE,// normalized?
0,// stride
(void* ) 0// array buffer offset
))
}
return true;
}
void update(int vPositionLoc, int vNormalLoc, int vTexCoordLoc) const {
GLCK(glBindVertexArray(vertexArrayId))
bindVertexAttrib(vPositionId, vPositionLoc, 3);
bindVertexAttrib(vNormalId, vNormalLoc, 3);
bindVertexAttrib(vTexCoordId, vTexCoordLoc, 2);
GLCK(glBindVertexArray(0))
}
};

View File

@ -3,6 +3,7 @@
#include "AlignedAllocator.h"
#include <glm/vec4.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
#include <vector>
typedef glm::tvec4<uint8_t> ucvec4_t;