X-Git-Url: https://eleni.mutantstargoat.com/git/?p=hair;a=blobdiff_plain;f=src%2Fmesh.cc;h=da22d7801b01a5addb67e583fd7936f689877479;hp=c852258949c7c8913b09a87a52401e87e158a744;hb=8f59fd2bda5b48b7cb9137ca5ee141dd8f8382d1;hpb=da5cbacf755273da510c37c819a59c7fe9894c4e diff --git a/src/mesh.cc b/src/mesh.cc index c852258..da22d78 100644 --- a/src/mesh.cc +++ b/src/mesh.cc @@ -1,23 +1,33 @@ #include +#include + #include #include #include #include #include +#include #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; num_vertices = 0; num_indices = 0; + + mtl.tex = 0; + mtl.diffuse = Vec3(1, 1, 1); + mtl.shininess = 50; } Mesh::~Mesh() @@ -26,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) @@ -33,11 +45,36 @@ Mesh::~Mesh() vertices.clear(); normals.clear(); + texcoords.clear(); colors.clear(); } void Mesh::draw() const { + /* set material */ + float diff[4] = { + mtl.diffuse.x, mtl.diffuse.y, mtl.diffuse.z, 1.0 + }; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diff); + + float spec[4] = { + mtl.specular.x, mtl.specular.y, mtl.specular.z, 1.0 + }; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + + 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); glVertexPointer(3, GL_FLOAT, 0, 0); @@ -47,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); @@ -67,12 +110,15 @@ void Mesh::draw() const glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); + + 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); } @@ -87,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); } @@ -104,6 +165,7 @@ void Mesh::update_vbo(unsigned int which) if(which & MESH_VERTEX) { + assert(!vertices.empty()); if(!vbo_vertices) { glGenBuffers(1, &vbo_vertices); } @@ -119,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); } @@ -144,12 +206,14 @@ std::vector load_meshes(const char *fname) for(unsigned int j=0; jmNumMeshes; j++) { aiMesh *amesh = scene->mMeshes[j]; + aiMaterial *amtl = scene->mMaterials[amesh->mMaterialIndex]; if(!amesh->HasPositions() || !amesh->mNumFaces) continue; Mesh *mesh = new Mesh; mesh->name = std::string(amesh->mName.C_Str()); + printf("loading mesh: %s\n", mesh->name.c_str()); for(unsigned int i=0; imNumVertices; i++) { Vec3 vertex = Vec3(amesh->mVertices[i].x, @@ -157,6 +221,7 @@ std::vector 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; imNumVertices; i++) { @@ -167,6 +232,14 @@ std::vector load_meshes(const char *fname) } } + if(amesh->HasTextureCoords(0)) { + for(unsigned int i=0; imNumVertices; 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; imNumVertices; i++) { Vec3 color = Vec3(amesh->mColors[0][i].r, @@ -181,10 +254,49 @@ std::vector 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); + mesh->mtl.diffuse = Vec3(acol.r, acol.g, acol.b); + + float sstr; + aiGetMaterialFloat(amtl, AI_MATKEY_SHININESS_STRENGTH, &sstr); + + aiGetMaterialColor(amtl, AI_MATKEY_COLOR_SPECULAR, &acol); + mesh->mtl.specular = sstr * Vec3(acol.r, acol.g, acol.b) * 0.3; + + float shin; + aiGetMaterialFloat(amtl, AI_MATKEY_SHININESS, &shin); + mesh->mtl.shininess = shin * 6; + + aiString astr; + if(aiGetMaterialTexture(amtl, aiTextureType_DIFFUSE, 0, &astr) == 0) { + char *fname = astr.data; + char *slash; + char *path; + + if((slash = strrchr(fname, '/'))) { + fname = slash + 1; + } + if((slash = strrchr(fname, '\\'))) { + fname = slash + 1; + } + 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", 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; + } meshes.push_back(mesh); } + aiReleaseImport(scene); return meshes; } @@ -209,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