Many fixes (credits Nuclear)
authorEleni Maria Stea <estea@igalia.com>
Sun, 27 Jan 2019 15:50:45 +0000 (17:50 +0200)
committerEleni Maria Stea <estea@igalia.com>
Sun, 27 Jan 2019 15:52:21 +0000 (17:52 +0200)
1- fixed memory leaks
2- added tex coords
3- fixed empty vbos bug
4- added tex opacity check

Makefile
data/head.blend
data/head.fbx
src/hair.cc
src/main.cc
src/mesh.cc
src/mesh.h

index 8b94f2b..3792df5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,9 @@ dbg = -g
 opt = -O0
 inc = -Isrc -Isrc/shaders -Isrc/math
 CXX = g++
+CC = gcc
 CXXFLAGS = -pedantic -Wall $(dbg) $(opt) $(inc)
+CFLAGS = -pedantic -Wall $(dbg) $(opt) $(inc)
 LDFLAGS = -lGL -lGLU -lglut -lGLEW -limago -lassimp -lgmath
 
 $(bin): $(obj)
index 35f1e1e..6b4efad 100644 (file)
Binary files a/data/head.blend and b/data/head.blend differ
index d1caf71..f7a4fe2 100644 (file)
Binary files a/data/head.fbx and b/data/head.fbx differ
index de31ed8..a369465 100644 (file)
@@ -110,6 +110,7 @@ bool Hair::init(const Mesh *m, int max_num_spawns, float thresh)
                if (res && !kd_res_end(res)) {
                        Vec3 nearest;
                        kd_res_item3f(res, &nearest.x, &nearest.y, &nearest.z);
+                       kd_res_free(res);
                        if(distance_sq(rpoint, nearest) < min_dist * min_dist)
                                continue;
                }
index 9720723..c409322 100644 (file)
@@ -129,6 +129,7 @@ static void cleanup()
        for(size_t i=0; i<meshes.size(); i++) {
                delete meshes[i];
        }
+       glDeleteTextures(1, &grad_tex);
 }
 
 static void display()
@@ -194,7 +195,7 @@ static void display()
        glPopAttrib();
 */
        float plane[4] = {
-               0, 0, 0.5 / 350, 0.5 
+               0, 0, 0.5 / 350, 0.5
        };
 
        glPushMatrix();
index ac18f52..da22d78 100644 (file)
@@ -1,5 +1,7 @@
 #include <GL/glew.h>
 
+#include <assert.h>
+
 #include <assimp/cimport.h>
 #include <assimp/postprocess.h>
 #include <assimp/scene.h>
 
 #include "mesh.h"
 
+static bool check_tex_opaque(unsigned int tex);
+
 Mesh::Mesh()
 {
        vbo_vertices = 0;
        vbo_normals = 0;
+       vbo_texcoords = 0;
        vbo_colors = 0;
        ibo = 0;
 
@@ -31,6 +36,8 @@ Mesh::~Mesh()
                glDeleteBuffers(1, &vbo_vertices);
        if(vbo_normals)
                glDeleteBuffers(1, &vbo_normals);
+       if(vbo_texcoords)
+               glDeleteBuffers(1, &vbo_texcoords);
        if(vbo_colors)
                glDeleteBuffers(1, &vbo_colors);
        if(ibo)
@@ -38,6 +45,7 @@ Mesh::~Mesh()
 
        vertices.clear();
        normals.clear();
+       texcoords.clear();
        colors.clear();
 }
 
@@ -56,9 +64,15 @@ void Mesh::draw() const
 
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mtl.shininess);
 
+       glPushAttrib(GL_ENABLE_BIT);
        if(mtl.tex) {
                glBindTexture(GL_TEXTURE_2D, mtl.tex);
                glEnable(GL_TEXTURE_2D);
+
+               if(!mtl.tex_opaque) {
+                       glEnable(GL_BLEND);
+                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               }
        }
 
        glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
@@ -70,6 +84,12 @@ void Mesh::draw() const
                glEnableClientState(GL_NORMAL_ARRAY);
        }
 
+       if(vbo_texcoords) {
+               glBindBuffer(GL_ARRAY_BUFFER, vbo_texcoords);
+               glTexCoordPointer(2, GL_FLOAT, 0, 0);
+               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+       }
+
        if(vbo_colors) {
                glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
                glColorPointer(3, GL_FLOAT, 0, 0);
@@ -90,16 +110,15 @@ void Mesh::draw() const
 
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
-       
 
-       if(mtl.tex)
-               glDisable(GL_TEXTURE_2D);
+       glPopAttrib();
 }
 
 void Mesh::update_vbo(unsigned int which)
 {
-       if(which & MESH_NORMAL) {
+       if((which & MESH_NORMAL) && !normals.empty()) {
                if(!vbo_normals) {
                        glGenBuffers(1, &vbo_normals);
                }
@@ -114,7 +133,22 @@ void Mesh::update_vbo(unsigned int which)
                }
        }
 
-       if(which & MESH_COLOR) {
+       if((which & MESH_TEXCOORDS) && !texcoords.empty()) {
+               if(!vbo_texcoords) {
+                       glGenBuffers(1, &vbo_texcoords);
+               }
+               glBindBuffer(GL_ARRAY_BUFFER, vbo_texcoords);
+               if(num_vertices != (int)texcoords.size()) {
+                       glBufferData(GL_ARRAY_BUFFER, texcoords.size() * 2 * sizeof(float),
+                                       &texcoords[0], GL_STATIC_DRAW);
+               }
+               else {
+                       glBufferSubData(GL_ARRAY_BUFFER, 0, texcoords.size() * 2 * sizeof(float),
+                                       &texcoords[0]);
+               }
+       }
+
+       if((which & MESH_COLOR) && !colors.empty()) {
                if(!vbo_colors) {
                        glGenBuffers(1, &vbo_colors);
                }
@@ -131,6 +165,7 @@ void Mesh::update_vbo(unsigned int which)
 
 
        if(which & MESH_VERTEX) {
+               assert(!vertices.empty());
                if(!vbo_vertices) {
                        glGenBuffers(1, &vbo_vertices);
                }
@@ -146,7 +181,7 @@ void Mesh::update_vbo(unsigned int which)
                num_vertices = vertices.size();
        }
 
-       if(which & MESH_INDEX) {
+       if((which & MESH_INDEX) && !indices.empty()) {
                if(!ibo) {
                        glGenBuffers(1, &ibo);
                }
@@ -186,6 +221,7 @@ std::vector<Mesh*> load_meshes(const char *fname)
                                        amesh->mVertices[i].z);
                        mesh->vertices.push_back(vertex);
                }
+               printf(" %u vertices\n", amesh->mNumVertices);
 
                if(amesh->HasNormals()) {
                        for(unsigned int i=0; i<amesh->mNumVertices; i++) {
@@ -196,6 +232,14 @@ std::vector<Mesh*> load_meshes(const char *fname)
                        }
                }
 
+               if(amesh->HasTextureCoords(0)) {
+                       for(unsigned int i=0; i<amesh->mNumVertices; i++) {
+                               Vec2 tc = Vec2(amesh->mTextureCoords[0][i].x,
+                                                          1.0f - amesh->mTextureCoords[0][i].y);
+                               mesh->texcoords.push_back(tc);
+                       }
+               }
+
                if(amesh->HasVertexColors(0)) {
                        for(unsigned int i=0; i<amesh->mNumVertices; i++) {
                                Vec3 color = Vec3(amesh->mColors[0][i].r,
@@ -210,6 +254,7 @@ std::vector<Mesh*> load_meshes(const char *fname)
                                mesh->indices.push_back(amesh->mFaces[i].mIndices[j]);
                        }
                }
+               printf(" %d faces\n", amesh->mNumFaces);
 
                aiColor4D acol;
                aiGetMaterialColor(amtl, AI_MATKEY_COLOR_DIFFUSE, &acol);
@@ -220,13 +265,10 @@ std::vector<Mesh*> load_meshes(const char *fname)
 
                aiGetMaterialColor(amtl, AI_MATKEY_COLOR_SPECULAR, &acol);
                mesh->mtl.specular = sstr * Vec3(acol.r, acol.g, acol.b) * 0.3;
-               printf("mtl sstr: %f\n", sstr);
-               printf("mtl spec: %f %f %f\n", acol.r, acol.g, acol.b);
 
                float shin;
                aiGetMaterialFloat(amtl, AI_MATKEY_SHININESS, &shin);
                mesh->mtl.shininess = shin * 6;
-               printf("mtl shin: %f\n", mesh->mtl.shininess);
 
                aiString astr;
                if(aiGetMaterialTexture(amtl, aiTextureType_DIFFUSE, 0, &astr) == 0) {
@@ -243,7 +285,10 @@ std::vector<Mesh*> load_meshes(const char *fname)
                        path = new char[strlen(fname) + 6];
                        sprintf(path, "data/%s", fname);
                        if(!(mesh->mtl.tex = img_gltexture_load(path))) {
-                               fprintf(stderr, "Failed to load texture %s\n", fname);
+                               fprintf(stderr, "Failed to load texture %s\n", path);
+                       } else {
+                               mesh->mtl.tex_opaque = check_tex_opaque(mesh->mtl.tex);
+                               printf(" texture: %s (%s)\n", path, mesh->mtl.tex_opaque ? "opaque" : "transparent");
                        }
                        delete [] path;
                }
@@ -251,6 +296,7 @@ std::vector<Mesh*> load_meshes(const char *fname)
                meshes.push_back(mesh);
        }
 
+       aiReleaseImport(scene);
        return meshes;
 }
 
@@ -275,3 +321,26 @@ void Mesh::calc_bbox()
                }
        }
 }
+
+static bool check_tex_opaque(unsigned int tex)
+{
+       int xsz, ysz;
+       uint32_t *pixels, *pptr;
+
+       glBindTexture(GL_TEXTURE_2D, tex);
+       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &xsz);
+       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &ysz);
+       assert(xsz > 0 && ysz > 0);
+
+       pptr = pixels = new uint32_t[xsz * ysz];
+       glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+       for(int i=0; i<xsz * ysz; i++) {
+               if((*pptr++ & 0xff000000) != 0xff000000) {
+                       delete [] pixels;
+                       return false;
+               }
+       }
+       delete [] pixels;
+       return true;
+}
index ec93ab1..08d01d7 100644 (file)
@@ -10,8 +10,9 @@
 enum {
        MESH_VERTEX = 1,
        MESH_NORMAL = 2,
-       MESH_COLOR = 4,
-       MESH_INDEX = 8
+       MESH_TEXCOORDS = 4,
+       MESH_COLOR = 8,
+       MESH_INDEX = 16
 };
 
 struct Aabb {
@@ -25,12 +26,14 @@ struct Material {
        float shininess;
 
        unsigned int tex;
+       bool tex_opaque;
 };
 
 class Mesh {
 private:
        unsigned int vbo_vertices;
        unsigned int vbo_normals;
+       unsigned int vbo_texcoords;
        unsigned int vbo_colors;
        unsigned int ibo;
 
@@ -47,6 +50,7 @@ public:
        std::string name;
        std::vector<uint16_t> indices;
        std::vector<Vec3> vertices;
+       std::vector<Vec2> texcoords;
        std::vector<Vec3> normals;
        std::vector<Vec3> colors;