big update

This commit is contained in:
Gero Müller 2017-10-29 14:16:22 +10:00
parent dcab466330
commit 1d22b7a1ab
13 changed files with 1424 additions and 647 deletions

View File

@ -20,7 +20,12 @@ include_directories(${OPENMESH_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/vendor)
# add executable # add executable
add_executable(asteroidgen add_executable(asteroidgen
src/main.cpp src/main.cpp
src/gen.cpp src/Application.cpp
src/Polygoniser.cpp
src/TextureMapper.cpp
# src/TexturePainter.cpp
# src/gen.cpp
vendor/stb_impl.cpp
vendor/mersenne-twister.cpp vendor/mersenne-twister.cpp
vendor/OpenNL_psm.c vendor/OpenNL_psm.c
vendor/glad.c vendor/glad.c

21
ToDo.txt Normal file
View File

@ -0,0 +1,21 @@
LIB:
- improve marching cube
- create patches
- use lscm
- mesh cleanup
- profile texture generation
- improve polygonizer
- use glm::noise or stb noise?
- view dependent progressive mesh
- vertex color?
GUI:
- Skybox: http://ogldev.atspace.co.uk/www/tutorial25/tutorial25.html
- Progress
- Arcball
- PBR https://learnopengl.com/#!PBR/Lighting
- save

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -0,0 +1,64 @@
#version 330 core
// Interpolated values from the vertex shaders
in vec2 UV;
in vec3 Position_worldspace;
in vec3 Normal_cameraspace;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;
// Ouput data
out vec3 color;
// Values that stay constant for the whole mesh.
uniform sampler2D tAlbedo;
uniform mat4 MV;
uniform vec3 LightPosition_worldspace;
void main(){
// Light emission properties
// You probably want to put them as uniforms
vec3 LightColor = vec3(1,1,1);
float LightPower = 400.0f;
// Material properties
vec3 MaterialDiffuseColor = texture( tAlbedo, UV ).rgb;
vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * MaterialDiffuseColor;
vec3 MaterialSpecularColor = vec3(0.03,0.03,0.03);
// Distance to the light
float distance = length( LightPosition_worldspace - Position_worldspace );
// Normal of the computed fragment, in camera space
vec3 n = normalize( Normal_cameraspace );
// Direction of the light (from the fragment to the light)
vec3 l = normalize( LightDirection_cameraspace );
// Cosine of the angle between the normal and the light direction,
// clamped above 0
// - light is at the vertical of the triangle -> 1
// - light is perpendicular to the triangle -> 0
// - light is behind the triangle -> 0
float cosTheta = clamp( dot( n,l ), 0,1 );
// Eye vector (towards the camera)
vec3 E = normalize(EyeDirection_cameraspace);
// Direction in which the triangle reflects the light
vec3 R = reflect(-l,n);
// Cosine of the angle between the Eye vector and the Reflect vector,
// clamped to 0
// - Looking into the reflection -> 1
// - Looking elsewhere -> < 1
float cosAlpha = clamp( dot( E,R ), 0,1 );
color =
// Ambient : simulates indirect lighting
MaterialAmbientColor +
// Diffuse : "color" of the object
MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance)
+
// Specular : reflective highlight, like a mirror
MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance);
}

View File

@ -0,0 +1,44 @@
#version 330 core
// Input vertex data, different for all executions of this shader.
in vec3 vPosition;
in vec2 vTexCoord;
in vec3 vNormal;
// Output data ; will be interpolated for each fragment.
out vec2 UV;
out vec3 Position_worldspace;
out vec3 Normal_cameraspace;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 V;
uniform mat4 M;
uniform vec3 LightPosition_worldspace;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vPosition,1);
// Position of the vertex, in worldspace : M * position
Position_worldspace = (M * vec4(vPosition,1)).xyz;
// Vector that goes from the vertex to the camera, in camera space.
// In camera space, the camera is at the origin (0,0,0).
vec3 vertexPosition_cameraspace = ( V * M * vec4(vPosition,1)).xyz;
EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;
// Vector that goes from the vertex to the light, in camera space. M is ommited because it's identity.
vec3 LightPosition_cameraspace = ( V * vec4(LightPosition_worldspace,1)).xyz;
LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;
// Normal of the the vertex, in camera space
Normal_cameraspace = ( V * M * vec4(vNormal,0)).xyz; // Only correct if ModelMatrix does not scale the model ! Use its inverse transpose if not.
// UV of the vertex. No special space for this one.
UV = vTexCoord;
}

736
src/Application.cpp Normal file
View File

@ -0,0 +1,736 @@
#include "Application.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/mat4x4.hpp>
#include <glm/mat3x3.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <imgui.h>
#include <imgui_impl_glfw_gl3.h>
#include <stb_image.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
using glm::vec3;
using glm::uvec3;
using std::map;
using std::vector;
void calculateNormals(const vector<vec3> &vtx, vector<uvec3> &tri,
vector<vec3> &normals) {
normals.clear();
normals.resize(vtx.size(), vec3(0));
for (size_t i = 0; i < tri.size(); i++) {
int a = tri[i].x, b = tri[i].y, c = tri[i].z;
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(vector<vec3> &vtx) {
vec3 mean(0);
for (size_t i = 0; i < vtx.size(); i++) {
mean += vtx[i];
}
mean *= vec3(1.f / vtx.size());
for (size_t i = 0; i < vtx.size(); i++) {
vtx[i] -= mean;
}
}
void smooth(vector<vec3> &vtx, const vector<uvec3> &tri) {
vector<vec3> cogs(vtx.size(), vec3(0.f));
vector<int> valence(vtx.size(), 0);
for (size_t iTri = 0; iTri < tri.size(); iTri++) {
const 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] * vec3(0.8)
// + cogs[i] * vec3(0.2f / valence[i]);
vtx[i] = cogs[i] * vec3(1.f / valence[i]);
}
}
void saveAttrib(std::ostream &out, const char *prefix, vector<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,
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 vector<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 vector<vec3> &vtx, vector<uvec3> &tri,
vector<glm::uvec4> &edges) {
edges.clear();
map<std::pair<uint32_t, uint32_t>, uint32_t> edgeMap;
for (size_t iTri = 0; iTri < tri.size(); iTri++) {
uvec3 idx = tri[iTri];
for (size_t k = 0; k < 3; k++) {
int a = idx[k];
int b = idx[(k + 1) % 3];
glm::uvec4 edge1(std::min(a, b), std::max(a, b), iTri, 0);
auto it1 = edgeMap.find(std::make_pair(edge1.x, edge1.y));
if (it1 != edgeMap.end()) {
edges[it1->second].z = iTri;
} else {
edges.push_back(edge1);
}
}
}
}
void computeTangentBasis(vector<vec3> & vertices, vector<glm::vec2> & uvs,
vector<vec3> & normals, vector<vec3> & tangents,
vector<vec3> & bitangents) {
for (size_t i = 0; i < vertices.size(); i += 3) {
// Shortcuts for vertices
vec3 & v0 = vertices[i + 0];
vec3 & v1 = vertices[i + 1];
vec3 & v2 = vertices[i + 2];
// Shortcuts for UVs
glm::vec2 & uv0 = uvs[i + 0];
glm::vec2 & uv1 = uvs[i + 1];
glm::vec2 & uv2 = uvs[i + 2];
// Edges of the triangle : postion delta
vec3 deltaPos1 = v1 - v0;
vec3 deltaPos2 = v2 - v0;
// UV delta
glm::vec2 deltaUV1 = uv1 - uv0;
glm::vec2 deltaUV2 = uv2 - uv0;
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
// Set the same tangent for all three vertices of the triangle.
// They will be merged later, in vboindexer.cpp
tangents.push_back(tangent);
tangents.push_back(tangent);
tangents.push_back(tangent);
// Same thing for binormals
bitangents.push_back(bitangent);
bitangents.push_back(bitangent);
bitangents.push_back(bitangent);
}
}
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);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action,
int mods) {
Application::instance().KeyCallback(window, key, scancode, action, mods);
}
static void mouse_button_callback(GLFWwindow* window, int button, int action,
int mods) {
Application::instance().MouseButtonCallback(window, button, action, mods);
}
static void scroll_callback(GLFWwindow* window, double xoffset,
double yoffset) {
Application::instance().ScrollCallback(window, xoffset, yoffset);
}
static void char_callback(GLFWwindow* window, unsigned int c) {
Application::instance().CharCallback(window, 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), viewDistance(3.0f), fpsMode(
false) {
init();
}
Application::~Application() {
shutdown();
}
Application &Application::instance() {
static Application app;
return app;
}
void Application::init() {
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
window = glfwCreateWindow(1200, 800, "Procedural Asteroid Generator", NULL,
NULL);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
GLFWimage icon;
int n;
icon.pixels = stbi_load("icon.png", &icon.width, &icon.height, &n, 4);
if (icon.pixels) {
glfwSetWindowIcon(window, 1, &icon);
stbi_image_free(icon.pixels);
} else
std::cout << "Failed to load icon.png" << std::endl;
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetScrollCallback(window, scroll_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetCharCallback(window, char_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;
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();
generateAsteroid();
uploadMesh();
}
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();
}
void Application::KeyCallback(GLFWwindow* window, int key, int scancode,
int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
glfwSetWindowShouldClose(window, GLFW_TRUE);
if (ImGui::IsMouseHoveringAnyWindow())
ImGui_ImplGlfwGL3_KeyCallback(window, key, scancode, action, mods);
else {
if (key == GLFW_KEY_TAB && action == GLFW_RELEASE) {
toogleFpsMode();
}
}
}
void Application::MouseButtonCallback(GLFWwindow* window, int button,
int action, int mods) {
ImGui_ImplGlfwGL3_MouseButtonCallback(window, button, action, mods);
}
void Application::ScrollCallback(GLFWwindow* window, double xoffset,
double yoffset) {
if (ImGui::IsMouseHoveringAnyWindow())
ImGui_ImplGlfwGL3_ScrollCallback(window, xoffset, yoffset);
else
viewDistance -= yoffset * viewDistance * 0.1;
}
void Application::CharCallback(GLFWwindow* window, unsigned int c) {
ImGui_ImplGlfwGL3_CharCallback(window, c);
}
void Application::toogleFpsMode() {
if (fpsMode) {
fpsMode = false;
} else {
fpsMode = true;
fpsTrafo = glm::lookAt(vec3(0, 0, viewDistance), vec3(0, 0, 0),
vec3(0, 1, 0));
}
}
void Application::generateAsteroid() {
std::srand(123);
if (density.getImpacts().size() == 0)
density.addRandomImpacts(1000, 0.2, 0.01, 0.005, 0.2, 4096);
//density.saveCrossSection("density.png", 512);
polygonizer.polygonize(resolution);
{
std::ofstream out("stage1.obj");
saveAttrib(out, "v ", polygonizer.vertices);
saveFaces(out, polygonizer.indices, 1);
}
smooth(polygonizer.vertices, polygonizer.indices);
{
std::ofstream out("stage2.obj");
saveAttrib(out, "v ", polygonizer.vertices);
saveFaces(out, polygonizer.indices, 1);
}
calculateNormals(polygonizer.vertices, polygonizer.indices, normals);
{
std::ofstream out("stage3.obj");
saveAttrib(out, "v ", polygonizer.vertices);
saveAttrib(out, "vn ", normals);
saveFaces(out, polygonizer.indices, 2);
}
vector<glm::uvec4> edges;
std::cout << "Vertices: " << polygonizer.vertices.size() << std::endl;
std::cout << "Triangles: " << polygonizer.indices.size() << std::endl;
texturemapper.map(polygonizer.vertices, normals, polygonizer.indices);
moveToMean(texturemapper.vertices);
{
std::ofstream out("stage4.obj");
saveAttrib(out, "v ", texturemapper.vertices);
saveAttrib(out, "vn ", texturemapper.normals);
saveAttrib(out, "vt ", texturemapper.texcoords);
saveFaces(out, texturemapper.indices, 3);
}
}
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))
}
GLuint Application::loadProgram(const std::string &name) {
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::string vertex_file_path = "shader/" + name + ".vertex.glsl";
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if (VertexShaderStream.is_open()) {
std::string Line = "";
while (getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
} else {
std::cout << "Failed to open " << vertex_file_path << std::endl;
return 0;
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::string fragment_file_path = "shader/" + name + ".fragment.glsl";
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if (FragmentShaderStream.is_open()) {
std::string Line = "";
while (getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
} else {
std::cout << "Failed to open " << vertex_file_path << std::endl;
return 0;
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
std::cout << "Compiling vertex shader : " << name << std::endl;
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL,
&VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
std::cout << "Compiling fragment shader : " << name << std::endl;
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL,
&FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
std::cout << "Linking program : " << name << std::endl;
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL,
&ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
void Application::loadShader() {
if (programId >= 0)
GLCK(glDeleteProgram(programId))
programId = loadProgram("standard");
GLCK(MVPloc = glGetUniformLocation(programId, "MVP"))
GLCK(Mloc = glGetUniformLocation(programId, "M"))
GLCK(Vloc = glGetUniformLocation(programId, "V"))
GLCK(
LightPosition_worldspaceloc = glGetUniformLocation(programId, "LightPosition_worldspace"))
GLCK(vPositionLoc = glGetAttribLocation(programId, "vPosition"))
GLCK(vTexCoordLoc = glGetAttribLocation(programId, "vTexCoord"))
GLCK(vNormalLoc = glGetAttribLocation(programId, "vNormal"))
GLCK(tAlbedoLoc = glGetAttribLocation(programId, "tAlbedo"))
GLCK(tNormalLoc = glGetAttribLocation(programId, "tNormal"))
GLCK(tRoughnessLoc = glGetAttribLocation(programId, "tRoughness"))
GLCK(tMetalicLoc = glGetAttribLocation(programId, "tMetalic"))
}
void Application::uploadMesh() {
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))
glBindTexture(GL_TEXTURE_2D, tAlbedoId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texturemapper.getTextureSize(),
texturemapper.getTextureSize(), 0, GL_BGR, GL_UNSIGNED_BYTE,
texturemapper.albedo.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
void Application::renderMesh() {
GLCK(glBindVertexArray(vertexArrayId))
GLCK(
glDrawElements(GL_TRIANGLES, texturemapper.indices.size() * 3, GL_UNSIGNED_INT, (void* ) 0))
GLCK(glBindVertexArray(0))
}
void Application::prepareShader() {
glm::mat4 model(1.0f);
glm::mat4 view;
if (fpsMode) {
glm::vec4 movement(0.0);
if (fpsMode) {
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
movement += glm::vec4(0.0, 0.0, 0.1, 0.0);
} else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
movement -= glm::vec4(0.0, 0.0, 0.1, 0.0);
}
}
glm::vec3 absolute = glm::transpose(fpsTrafo) * movement;
fpsTrafo = glm::translate(fpsTrafo, absolute);
view = fpsTrafo;
} else {
model = glm::rotate(model, (float) glfwGetTime(), vec3(0.f, 1.f, 0.f));
view = glm::lookAt(vec3(0, 0, viewDistance), // Camera is at (4,3,3), in World Space
vec3(0, 0, 0), // and looks at the origin
vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
}
glm::mat4 perspective = glm::perspective(glm::radians(45.0f),
(float) width / (float) height, 0.1f, 100.0f);
glm::mat4 mvp = perspective * view * model;
GLCK(glUseProgram(programId))
if (MVPloc >= 0) {
GLCK(glUniformMatrix4fv(MVPloc, 1, GL_FALSE, glm::value_ptr(mvp)))
}
if (Mloc >= 0) {
GLCK(glUniformMatrix4fv(Mloc, 1, GL_FALSE, glm::value_ptr(model)))
}
if (Vloc >= 0) {
GLCK(glUniformMatrix4fv(Vloc, 1, GL_FALSE, glm::value_ptr(view)))
}
if (LightPosition_worldspaceloc >= 0) {
vec3 LightPosition_worldspace(10.0f, 10.0f, 10.0f);
GLCK(
glUniform3fv(LightPosition_worldspaceloc, 1, glm::value_ptr(LightPosition_worldspace)))
}
int idx = 0;
if (tAlbedoLoc >= 0) {
glUniform1i(tAlbedoLoc, idx);
glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(GL_TEXTURE_2D, tAlbedoId);
idx++;
}
if (tNormalLoc >= 0) {
glUniform1i(tNormalLoc, idx);
glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(GL_TEXTURE_2D, tNormalId);
idx++;
}
if (tRoughnessLoc >= 0) {
glUniform1i(tRoughnessLoc, idx);
glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(GL_TEXTURE_2D, tRoughnessId);
idx++;
}
if (tMetalicLoc >= 0) {
glUniform1i(tMetalicLoc, idx);
glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(GL_TEXTURE_2D, tMetalicId);
idx++;
}
}
void Application::gui() {
ImGui::Begin("Mesh Generation");
ImGui::Text("Vertices: %lu, Triangles: %lu", polygonizer.vertices.size(),
polygonizer.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))
density.setFrequency(densityFrequency);
if (ImGui::SliderFloat("Octave", &densityOctave, 1, 10, "%.0f", 1))
density.setOctave(densityOctave);
// if (ImGui::InputFloat("Frequency", &densityFrequency))
// if (ImGui::InputFloat("Octave", &densityOctave))
// density.setOctave(densityOctave);
static const char *textureSizesStrings[] = { "512", "1024", "2048", "4096" };
static const int textureSizes[] = { 512, 1024, 2048, 4096 };
static int currentTextureSize = 0;
if (ImGui::Combo("Texture Size", &currentTextureSize, textureSizesStrings,
4, -1)) {
texturemapper.setTextureSize(textureSizes[currentTextureSize]);
}
if (ImGui::Button("Generate")) {
generateAsteroid();
uploadMesh();
}
ImGui::End();
ImGui::Begin("Rendering");
if (ImGui::Button("Reload Shader")) {
loadShader();
updateVertexArrayObject();
}
if (ImGui::Button("Wireframe"))
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (ImGui::Button("Fill"))
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
ImGui::Begin("Textures");
ImGui::Image((ImTextureID) (intptr_t) tAlbedoId,
ImVec2(ImGui::GetWindowContentRegionMax().x,
ImGui::GetWindowContentRegionMax().x));
ImGui::End();
}
void Application::run() {
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
glfwGetFramebufferSize(window, &width, &height);
ImGui_ImplGlfwGL3_NewFrame();
gui();
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);
prepareShader();
renderMesh();
ImGui::Render();
glfwSwapBuffers(window);
}
}

89
src/Application.h Normal file
View File

@ -0,0 +1,89 @@
#pragma once
#include "Density.h"
#include "Polygoniser.h"
#include "TextureMapper.h"
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <string>
struct GLFWwindow;
class Application {
GLFWwindow* window;
int width, height;
Density density;
float densityIsolevel;
Polygonizer polygonizer;
float textureSize;
TextureMapper texturemapper;
unsigned int vertexArrayId, vPositionId, vTexCoordId, vNormalId,
indexBufferId, programId, tAlbedoId, tNormalId, tRoughnessId,
tMetalicId;
int MVPloc, Vloc, Mloc, MVloc, LightPosition_worldspaceloc;
int vPositionLoc, vTexCoordLoc, vNormalLoc, tAlbedoLoc, tNormalLoc,
tRoughnessLoc, tMetalicLoc;
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<glm::vec2> texcoords;
std::vector<glm::uvec3> indices;
size_t meteoridCount;
float meteroidMinRadius;
float meteroidMaxRadius;
int meteroidSizeExponent;
float densityFrequency, densityOctave;
glm::vec3 densityScale;
float resolution;
float viewDistance;
glm::mat4 fpsTrafo;
bool fpsMode;
void toogleFpsMode();
public:
Application();
~Application();
static Application &instance();
void init();
void shutdown();
void KeyCallback(GLFWwindow* window, int key, int scancode, int action,
int mods);
void MouseButtonCallback(GLFWwindow* window, int button, int action,
int mods);
void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void CharCallback(GLFWwindow* window, unsigned int c);
void generateAsteroid();
bool bindVertexAttrib(unsigned int id, int loc, unsigned int size);
void updateVertexArrayObject();
unsigned int loadProgram(const std::string &name);
void loadShader();
void uploadMesh();
void renderMesh();
void prepareShader();
void gui();
void run();
};

View File

@ -27,40 +27,57 @@ class Density {
glm::vec3 scale; glm::vec3 scale;
float scaleFactor; float scaleFactor;
float frequency, octave; float frequency, octave;
size_t version;
public: public:
Density() : Density() :
scale(1), scaleFactor(4), frequency(2), octave(2) { scale(1.0f), scaleFactor(4), frequency(2), octave(2), version(0) {
} }
const std::vector<Impact> &getImpacts() {
return impacts;
}
size_t getVersion() {
return version;
}
void addImpact(Impact &impact) { void addImpact(Impact &impact) {
size_t idx = impacts.size(); size_t idx = impacts.size();
impacts.push_back(impact); impacts.push_back(impact);
glm::vec3 l = impact.pos - glm::vec3(impact.r); glm::vec3 l = impact.pos - glm::vec3(impact.r);
glm::vec3 u = impact.pos + glm::vec3(impact.r); glm::vec3 u = impact.pos + glm::vec3(impact.r);
impactTree.Insert(&l.x, &u.x, idx); impactTree.Insert(&l.x, &u.x, idx);
version++;
} }
void setSeed(uint32_t seed) { void setSeed(uint32_t seed) {
noise.reseed(seed); noise.reseed(seed);
impacts.clear();
} }
void setScale(const glm::vec3 &scale) { void setScale(const glm::vec3 &scale) {
this->scale = scale; this->scale = scale;
scaleFactor = 4.f / std::min(scale.x, std::min(scale.y, scale.z)); scaleFactor = 4.f / std::min(scale.x, std::min(scale.y, scale.z));
impacts.clear();
version++;
} }
void setFrequency(float f) { void setFrequency(float f) {
frequency = f; frequency = f;
impacts.clear();
version++;
} }
void setOctave(float o) { void setOctave(float o) {
octave = o; octave = o;
impacts.clear();
version++;
} }
float operator()(const glm::vec3 &p) const { float operator()(const glm::vec3 &p, bool includeImpacts = true) const {
if (impacts.size()) { if (includeImpacts & impacts.size()) {
bool insideImpact = false; bool insideImpact = false;
impactTree.Search(&p.x, &p.x, [&](int idx) -> bool { impactTree.Search(&p.x, &p.x, [&](int idx) -> bool {
if (impacts[idx].contains(p)) { if (impacts[idx].contains(p)) {
@ -82,7 +99,7 @@ public:
} }
bool intersectIsolevel(const glm::vec3 &start, const glm::vec3 &end, bool intersectIsolevel(const glm::vec3 &start, const glm::vec3 &end,
glm::vec3 &pos, float isolevel, float resolution) { glm::vec3 &pos, float isolevel, float resolution) const {
glm::vec3 step = glm::normalize(end - start) * glm::vec3(resolution); glm::vec3 step = glm::normalize(end - start) * glm::vec3(resolution);
size_t nSteps = ceil(glm::length(end - start) / resolution); size_t nSteps = ceil(glm::length(end - start) / resolution);
pos = start; pos = start;

199
src/Polygoniser.cpp Normal file
View File

@ -0,0 +1,199 @@
#include "Polygoniser.h"
#include <functional>
#include <map>
#include <glm/gtc/epsilon.hpp>
#include <MarchingCube.h>
static const int isocells = 32;
Polygonizer::Polygonizer(Density &density, float isolevel) :
density(density), isolevel(isolevel) {
updateIsocell();
}
void Polygonizer::setIsoLevel(float isolevel) {
bool needIsocellUpdate = false;
if (this->isolevel != isolevel) {
this->isolevel = isolevel;
needIsocellUpdate = true;
}
needIsocellUpdate |= (isocellVersion != density.getVersion());
if (needIsocellUpdate)
updateIsocell();
}
void Polygonizer::updateIsocell() {
isocell.clear();
isocell.reserve(isocells * isocells * isocells);
float step = 1. / isocells;
for (size_t ix = 0; ix < isocells; ix++) {
float xmin = ix * step;
float xmax = xmin + step;
for (size_t iy = 0; iy < isocells; iy++) {
float ymin = iy * step;
float ymax = ymin + step;
float xyz = density(vec3(xmin, ymin, 0));
float Xyz = density(vec3(xmax, ymin, 0));
float xYz = density(vec3(xmin, ymax, 0));
float XYz = density(vec3(xmax, ymax, 0));
bool zAllUnder = (xyz < isolevel) && (Xyz < isolevel)
&& (xYz < isolevel) && (XYz < isolevel);
bool zAllOver = (xyz > isolevel) && (Xyz > isolevel)
&& (xYz > isolevel) && (XYz > isolevel);
for (size_t iz = 0; iz < isocells; iz++) {
float zmin = iz * step;
float zmax = zmin + step;
float xyZ = density(vec3(xmin, ymin, zmax));
float XyZ = density(vec3(xmax, ymin, zmax));
float xYZ = density(vec3(xmin, ymax, zmax));
float XYZ = density(vec3(xmax, ymax, zmax));
bool ZAllUnder = (xyZ < isolevel) && (XyZ < isolevel)
&& (xYZ < isolevel) && (XYZ < isolevel);
bool ZAllOver = (xyZ > isolevel) && (XyZ > isolevel)
&& (xYZ > isolevel) && (XYZ > isolevel);
isocell[ix * isocells * isocells + iy * isocells + iz] =
(zAllUnder && ZAllUnder) || (zAllOver && ZAllOver);
xyz = xyZ;
Xyz = XyZ;
xYz = xYZ;
XYz = XYZ;
zAllUnder = ZAllUnder;
zAllOver = ZAllOver;
}
}
}
isocellVersion = density.getVersion();
}
void Polygonizer::polygonize(const glm::vec3 lower, const glm::vec3 upper,
float resolution) {
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];
}
}
indices.push_back(idc);
}
}
}
}
}
void Polygonizer::polygonize(float resolution) {
vertexLookup.clear();
vertices.clear();
indices.clear();
// coarse scan
float coarseResolution = resolution * 10;
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];
}
}
indices.push_back(idc);
}
}
}
}
}

View File

@ -1,14 +1,9 @@
#pragma once #pragma once
#include <functional>
#include <vector> #include <vector>
#include <map> #include <map>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <glm/gtc/epsilon.hpp>
#include <MarchingCube.h>
#include <logger.h>
#include "Density.h" #include "Density.h"
@ -39,79 +34,22 @@ struct CompareVec3 {
}; };
class Polygonizer { class Polygonizer {
Density &density;
float isolevel;
public: public:
std::vector<glm::vec3> vertices; std::vector<glm::vec3> vertices;
std::vector<glm::uvec3> triangles; std::vector<glm::uvec3> indices;
Density &density;
Polygonizer(Density &density) :
density(density) {
}
void polygonize(float isolevel, float resolution) {
vertices.clear();
triangles.clear();
std::map<glm::vec3, int, CompareVec3> vertexLookup; std::map<glm::vec3, int, CompareVec3> vertexLookup;
size_t nSteps = 1.f / resolution - 1; std::vector<bool> isocell;
size_t nT = 0; size_t isocellVersion;
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; Polygonizer(Density &density, float isolevel);
gridCell.p[0] = vec3(x, y, z); void setIsoLevel(float isolevel);
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++) { void updateIsocell();
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);
}
}
}
}
}
void polygonize(float resolution);
void polygonize(const glm::vec3 lower, const glm::vec3 upper,
float isolevel);
}; };

205
src/TextureMapper.cpp Normal file
View File

@ -0,0 +1,205 @@
#include "TextureMapper.h"
#include <glm/mat3x3.hpp>
#include "stb_image_write.h"
#include <iostream>
TextureMapper::TextureMapper(Density &density, size_t textureSize) :
density(density), textureSize(textureSize), albedo(
textureSize * textureSize), normal(textureSize * textureSize), roughness(
textureSize * textureSize), darkestColor(0.3, 0.25, 0.2), brightestColor(
0.9, 0.85, 0.8) {
}
void TextureMapper::setTextureSize(size_t size) {
textureSize = size;
albedo.resize(textureSize * textureSize);
normal.resize(textureSize * textureSize);
roughness.resize(textureSize * textureSize);
}
size_t TextureMapper::getTextureSize() {
return textureSize;
}
void TextureMapper::map(const vec3v_t &inVertices, const vec3v_t &inNormals,
const uvec3v_t &inIndices) {
float texf = 1. / textureSize;
vertices.clear();
vertices.reserve(inIndices.size() * 3);
normals.clear();
normals.reserve(inIndices.size() * 3);
texcoords.clear();
texcoords.reserve(inIndices.size() * 3);
int rects = ceil(sqrt(inIndices.size())), rx = 0, ry = 0;
float rectSize = floor(float(textureSize) / rects) / textureSize;
for (size_t i = 0; i != inIndices.size(); i++) {
glm::vec3 p[3], n[3];
glm::uvec3 idx = inIndices[i];
indices.push_back(
glm::uvec3(vertices.size(), vertices.size() + 1,
vertices.size() + 2));
for (size_t j = 0; j < 3; j++) {
p[j] = inVertices[idx[j]];
vertices.push_back(p[j]);
n[j] = inNormals[idx[j]];
normals.push_back(n[j]);
}
glm::vec3 ex = glm::normalize(p[1] - p[0]);
glm::vec3 ey = glm::normalize(glm::cross(ex, p[2] - p[0]));
glm::vec3 ez = glm::normalize(glm::cross(ex, ey));
glm::mat3 base = glm::mat3(ex, ey, ez);
glm::vec3 t[3] = { p[0] * base, p[1] * base, p[2] * base };
glm::vec3 lower = min(min(t[0], t[1]), t[2]);
glm::vec3 upper = max(max(t[0], t[1]), t[2]);
t[0] -= lower;
t[1] -= lower;
t[2] -= lower;
glm::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;
glm::vec3 off(rx * rectSize, 0, ry * rectSize);
t[0] += off;
t[1] += off;
t[2] += off;
texcoords.push_back(glm::vec2(t[0].x, t[0].z));
texcoords.push_back(glm::vec2(t[1].x, t[1].z));
texcoords.push_back(glm::vec2(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 * textureSize);
glm::vec3 eb = t[1] - t[0];
float leb = glm::length(eb);
glm::vec3 ec = t[2] - t[0];
float lec = glm::length(ec);
// mat2 textureBase = mat2(vec2(eb.x, eb.z), vec2(ec.x, ec.z));
// mat2 itextureBase = inverse(textureBase);
glm::mat3 textureBase = glm::mat3(eb, glm::cross(eb, ec), ec);
glm::mat3 itextureBase = glm::inverse(textureBase);
// eb = normalize(eb);
// ec = normalize(ec);
glm::vec3 db = p[1] - p[0];
glm::vec3 dc = p[2] - p[0];
glm::vec3 mb = glm::normalize(p[1] - p[0]);
glm::vec3 mc = glm::normalize(p[2] - p[0]);
// mat2 faceBase = mat2(vec2(mb.x, mb.z), vec2(mc.x, mc.z));
// mat2 ifaceBase = inverse(faceBase);
glm::mat3 faceBase = glm::mat3(db, glm::cross(db, dc), dc);
glm::mat3 ifaceBase = glm::inverse(faceBase);
glm::vec3 tmin = max(
floor(
min(min(t[0], t[1]), t[2])
* glm::vec3((float) textureSize))
- glm::vec3(1.0f), glm::vec3(0.1));
glm::vec3 tmax = min(
ceil(
max(max(t[0], t[1]), t[2])
* glm::vec3((float) textureSize))
+ glm::vec3(1.0f), glm::vec3(textureSize-1));
// TODO: borders!
for (int ix = tmin.x; ix < tmax.x; ix++) {
for (int iy = (textureSize - tmax.z); iy < (textureSize - tmin.z);
iy++) {
// https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle#2049593
// for (int iy = tmin.z; iy < tmax.z; iy++) {
// cout << "pix " << ix << " " << iy << endl;
// cout << "uv " << float(ix) * texf << " " << 1.f - float(iy) * texf << endl;
// pixel to uv space
glm::vec3 res = glm::vec3(float(ix) * texf, 0.f,
1.f - float(iy) * texf) - t[0];
// cout << "r = " << r.x << " " << r.y << endl;
glm::vec3 local = 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;
glm::vec3 sp = p[0] + local; //res.x * mb + res.y * mc;
float v = (float) density(sp, false);
//
//v = pow(v, 3);
// default color
// float r = 0.8 + v * 0.2, g = 0.75 + 0.2 * v, b = 0.7
// + 0.2 * v;
glm::vec3 rgb = glm::vec3(255)
* glm::mix(darkestColor, brightestColor, v);
albedo[ix + (textureSize - iy) * textureSize][0] = rgb.x;
albedo[ix + (textureSize - iy) * textureSize][1] = rgb.y;
albedo[ix + (textureSize - iy) * textureSize][2] = rgb.z;
// 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;
// albedo[ix + iy * textureSize][0] = rd * (0.5 + sp.x) * 255;
// albedo[ix + iy * textureSize][1] = rd * (0.5 + sp.y) * 255;
// albedo[ix + iy * textureSize][2] = rd * (0.5 + sp.z) * 255;
// albedo[ix + iy * textureSize][0] = length(res) * rects * 255;
// albedo[ix + iy * textureSize][1] = length(res) * rects * 255;
// albedo[ix + iy * textureSize][2] = length(res) * 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_png("albedo.png", textureSize, textureSize, 3, albedo.data(), 0);
}

View File

@ -1,201 +1,38 @@
#ifndef SRC_TEXTUREMAPPER_H_ #pragma once
#define SRC_TEXTUREMAPPER_H_
#include "Density.h"
#include <vector> #include <vector>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
class TextureMapper { 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; size_t textureSize;
TextureMapper(size_t textureSize) : public:
textureSize(textureSize), diffuse(textureSize * textureSize), normal( typedef std::vector< glm::tvec3<uint8_t> > texture3_t;
textureSize * textureSize), roughness( typedef std::vector<uint8_t> texture1_t;
textureSize * textureSize) { typedef std::vector<glm::vec3> vec3v_t;
typedef std::vector<glm::vec2> vec2v_t;
typedef std::vector<glm::uvec3> uvec3v_t;
} Density &density;
void map() { texture3_t albedo;
cout << "Stage4: UV map" << endl; texture3_t normal;
TriMesh mappedMesh; texture1_t roughness;
float texf = 1. / texture_size; texture1_t metalness;
mesh.request_vertex_normals(); vec3v_t vertices;
mesh.request_face_normals(); vec3v_t normals;
mesh.update_face_normals(); vec2v_t texcoords;
mesh.update_vertex_normals(); uvec3v_t indices;
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]; glm::vec3 darkestColor, brightestColor;
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]); TextureMapper(Density &density, size_t textureSize);
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) { void setTextureSize(size_t size);
t[0].y = 0; size_t getTextureSize();
t[1].y = 0; void map(const vec3v_t &inVertices, const vec3v_t &inNormals,
t[2].y = 0; const uvec3v_t &inIndices);
// 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_ */

View File

@ -1,385 +1,7 @@
#include "Density.h" #include "Application.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) { int main(void) {
std::srand(123); Application::instance().run();
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();
} }