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

View File

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

View File

@ -1,10 +1,12 @@
#include "Mesh.h" #include "Mesh.h"
#include "gl.h"
#include <glm/geometric.hpp> #include <glm/geometric.hpp>
#include <map> #include <map>
#include <limits> #include <limits>
#include <stack> #include <stack>
#include <fstream>
using namespace std; using namespace std;
using namespace glm; using namespace glm;
@ -12,11 +14,59 @@ using namespace glm;
static const uvec3::value_type InvalidIndex = static const uvec3::value_type InvalidIndex =
numeric_limits<uvec3::value_type>::max(); numeric_limits<uvec3::value_type>::max();
void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices, Mesh::Mesh() {
vec3v_t &normals) {
}
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.clear();
normals.resize(positions.size(), vec3(0)); normals.resize(positions.size(), vec3(0));
#pragma omp parallel for #pragma omp parallel for
for (size_t i = 0; i < indices.size(); i++) { for (size_t i = 0; i < indices.size(); i++) {
int a = indices[i].x, b = indices[i].y, c = indices[i].z; int a = indices[i].x, b = indices[i].y, c = indices[i].z;
vec3 faceNormal = normalize( vec3 faceNormal = normalize(
@ -31,99 +81,19 @@ void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices,
} }
void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices, void Mesh::generateFaceNormals() {
vec3v_t &normals) { faceNormals.clear();
normals.clear(); faceNormals.resize(indices.size(), vec3(uninitialize));
normals.resize(indices.size(), vec3(uninitialize)); #pragma omp parallel for
#pragma omp parallel for
for (size_t i = 0; i < indices.size(); i++) { for (size_t i = 0; i < indices.size(); i++) {
int a = indices[i].x, b = indices[i].y, c = indices[i].z; int a = indices[i].x, b = indices[i].y, c = indices[i].z;
normals[i] = normalize( faceNormals[i] = normalize(
cross(positions[b] - positions[a], cross(positions[b] - positions[a],
positions[c] - positions[a])); positions[c] - positions[a]));
} }
} }
void moveToMean(vec3v_t &positions) { void Mesh::generateEdges() {
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) {
edges.clear(); edges.clear();
map<pair<uint32_t, uint32_t>, uint32_t> edgeMap; map<pair<uint32_t, uint32_t>, uint32_t> edgeMap;
for (size_t iTri = 0; iTri < indices.size(); iTri++) { 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, void Mesh::generateTangentBasis() {
vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents) {
for (size_t i = 0; i < positions.size(); i += 3) { 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) { void Mesh::generateAdjacent() {
printf("findAdjacent: %lu\n", nFaces); adjacents.resize(indices.size(), uvec3(InvalidIndex));
adjacents.resize(nFaces, uvec3(InvalidIndex));
for (size_t i = 0; i < edges.size(); i++) { for (size_t i = 0; i < edges.size(); i++) {
int a = edges[i].z; int a = edges[i].z;
int b = edges[i].w; 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, void Mesh::moveToMean() {
const vec3v_t &faceNormals, const uvec3v_t &adjacents, vec3 mean(0);
vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches, for (size_t i = 0; i < positions.size(); i++) {
float threshold) { 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()); assert(adjacents.size() == indices.size());
patches.clear(); Mesh mesh;
oPositions.clear();
oIndices.clear();
vector<bool> processed(indices.size(), false); vector<bool> processed(indices.size(), false);
for (size_t i = 0; i < indices.size(); i++) { 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++) { for (size_t k = 0; k < 3; k++) {
auto it = vertexMap.find(idx[k]); auto it = vertexMap.find(idx[k]);
if (it == vertexMap.end()) { if (it == vertexMap.end()) {
uint32_t newIdx = oPositions.size(); uint32_t newIdx = mesh.positions.size();
oPositions.push_back(positions[idx[k]]); mesh.positions.push_back(positions[idx[k]]);
if (normals.size())
mesh.normals.push_back(normals[idx[k]]);
vertexMap[idx[k]] = newIdx; vertexMap[idx[k]] = newIdx;
idx[k] = newIdx; idx[k] = newIdx;
} else { } else {
idx[k] = it->second; idx[k] = it->second;
} }
} }
oIndices.push_back(idx); mesh.indices.push_back(idx);
} }
printf("\n"); 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 <vector>
#include <ostream> #include <ostream>
void calculateVertexNormals(const vec3v_t &positions, uvec3v_t &indices, struct Mesh {
vec3v_t &normals); vec3v_t positions;
void calculateFaceNormals(const vec3v_t &positions, uvec3v_t &indices, vec3v_t normals;
vec3v_t &normals); vec2v_t texcoords;
void findEdges(const vec3v_t &positions, const uvec3v_t &indices,
uvec4v_t &edges);
//void createPatches(const vec3v_t &positions, const uvec3v_t &indices,
// const uvec4v_t &edges, vec3v_t &oPositions, uvec3v_t &oIndices,
// uvec4v_t &oEdges, uintv_t &patches, float threshold);
void 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, Mesh createPatched(float threshold) const;
vec3v_t & normals, vec3v_t & tangents, vec3v_t & bitangents);
void createPatches(const vec3v_t &positions, const uvec3v_t &indices, void saveAttrib(std::ostream &out, const char *prefix,
const vec3v_t &faceNormals, const uvec3v_t &adjacents, const vec3v_t &elements) const;
vec3v_t &oPositions, uvec3v_t &oIndices, uintv_t &patches, void saveAttrib(std::ostream &out, const char *prefix,
float threshold); 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++) { for (int iTri = 0; iTri < nTris; iTri++) {
vec3 *ps = tris[iTri].p; vec3 *ps = tris[iTri].p;
// skip degenerate vertices // skip degenerate positions
if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) if (all(epsilonEqual(ps[0], ps[1], 1e-8f))
|| all(epsilonEqual(ps[0], ps[2], 1e-8f)) || all(epsilonEqual(ps[0], ps[2], 1e-8f))
|| all(epsilonEqual(ps[2], ps[1], 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()) { if (vit != vertexLookup.end()) {
idc[k] = vit->second; idc[k] = vit->second;
} else { } else {
idc[k] = vertices.size(); idc[k] = positions.size();
vertices.push_back(p); positions.push_back(p);
vertexLookup[p] = idc[k]; vertexLookup[p] = idc[k];
} }
} }
@ -142,7 +142,7 @@ void Polygonizer::polygonize(const vec3 &lower, const vec3 &upper,
void Polygonizer::polygonize(float resolution) { void Polygonizer::polygonize(float resolution) {
vertexLookup.clear(); vertexLookup.clear();
vertices.clear(); positions.clear();
indices.clear(); indices.clear();
const float isocellSize = 1.f / isocells; 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) { void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
vertexLookup.clear(); vertexLookup.clear();
vertices.clear(); mesh.positions.clear();
indices.clear(); mesh.indices.clear();
vertices.reserve(pow(1. / resolution, 2) * 8); mesh.positions.reserve(pow(1. / resolution, 2) * 8);
indices.reserve(pow(1. / resolution, 2) * 8); mesh.indices.reserve(pow(1. / resolution, 2) * 8);
size_t nSteps = 1.f / resolution; size_t nSteps = 1.f / resolution;
size_t nSamples = nSteps + 1; size_t nSamples = nSteps + 1;
@ -258,7 +258,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
for (int iTri = 0; iTri < nTris; iTri++) { for (int iTri = 0; iTri < nTris; iTri++) {
vec3 *ps = tris[iTri].p; vec3 *ps = tris[iTri].p;
// skip degenerate vertices // skip degenerate positions
if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) if (all(epsilonEqual(ps[0], ps[1], 1e-8f))
|| all(epsilonEqual(ps[0], ps[2], 1e-8f)) || all(epsilonEqual(ps[0], ps[2], 1e-8f))
|| all(epsilonEqual(ps[2], ps[1], 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()) { if (vit != vertexLookup.end()) {
idc[k] = vit->second; idc[k] = vit->second;
} else { } else {
idc[k] = vertices.size(); idc[k] = mesh.positions.size();
vertices.push_back(p); mesh.positions.push_back(p);
vertexLookup[p] = idc[k]; 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) { //void Polygonizer::polygonize(float resolution) {
// vertexLookup.clear(); // vertexLookup.clear();
// vertices.clear(); // positions.clear();
// indices.clear(); // indices.clear();
// //
// size_t nSteps = 1.f / resolution; // size_t nSteps = 1.f / resolution;
@ -329,7 +329,7 @@ void Polygonizer::polygonize(float resolution, ProgressMonitor &progress) {
// for (int iTri = 0; iTri < nTris; iTri++) { // for (int iTri = 0; iTri < nTris; iTri++) {
// vec3 *ps = tris[iTri].p; // vec3 *ps = tris[iTri].p;
// //
// // skip degenerate vertices // // skip degenerate positions
// if (all(epsilonEqual(ps[0], ps[1], 1e-8f)) // if (all(epsilonEqual(ps[0], ps[1], 1e-8f))
// || all(epsilonEqual(ps[0], ps[2], 1e-8f)) // || all(epsilonEqual(ps[0], ps[2], 1e-8f))
// || all(epsilonEqual(ps[2], ps[1], 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()) { // if (vit != vertexLookup.end()) {
// idc[k] = vit->second; // idc[k] = vit->second;
// } else { // } else {
// idc[k] = vertices.size(); // idc[k] = positions.size();
// vertices.push_back(p); // positions.push_back(p);
// vertexLookup[p] = idc[k]; // vertexLookup[p] = idc[k];
// } // }
// } // }

View File

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

View File

@ -6,7 +6,8 @@
using namespace std; using namespace std;
SkyBox::SkyBox() { SkyBox::SkyBox() :
textureId(GL_INVALID_INDEX), programId(GL_INVALID_INDEX) {
glGenTextures(1, &textureId); glGenTextures(1, &textureId);
} }
@ -55,19 +56,19 @@ void SkyBox::Render() {
glCullFace(GL_FRONT); glCullFace(GL_FRONT);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
/* /*
Pipeline p; Pipeline p;
p.Scale(20.0f, 20.0f, 20.0f); p.Scale(20.0f, 20.0f, 20.0f);
p.Rotate(0.0f, 0.0f, 0.0f); p.Rotate(0.0f, 0.0f, 0.0f);
p.WorldPos(m_pCamera->GetPos().x, m_pCamera->GetPos().y, p.WorldPos(m_pCamera->GetPos().x, m_pCamera->GetPos().y,
m_pCamera->GetPos().z); m_pCamera->GetPos().z);
p.SetCamera(m_pCamera->GetPos(), m_pCamera->GetTarget(), p.SetCamera(m_pCamera->GetPos(), m_pCamera->GetTarget(),
m_pCamera->GetUp()); m_pCamera->GetUp());
p.SetPerspectiveProj(m_persProjInfo); p.SetPerspectiveProj(m_persProjInfo);
m_pSkyboxTechnique->SetWVP(p.GetWVPTrans()); m_pSkyboxTechnique->SetWVP(p.GetWVPTrans());
m_pCubemapTex->Bind(GL_TEXTURE0); m_pCubemapTex->Bind(GL_TEXTURE0);
m_pMesh->Render(); m_pMesh->Render();
*/ */
glCullFace(OldCullFaceMode); glCullFace(OldCullFaceMode);
glDepthFunc(OldDepthFuncMode); glDepthFunc(OldDepthFuncMode);
} }

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 "AlignedAllocator.h"
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <glm/vec2.hpp>
#include <vector> #include <vector>
typedef glm::tvec4<uint8_t> ucvec4_t; typedef glm::tvec4<uint8_t> ucvec4_t;