5 #include <assimp/cimport.h>
6 #include <assimp/postprocess.h>
7 #include <assimp/scene.h>
8 #include <assimp/mesh.h>
15 static bool check_tex_opaque(unsigned int tex);
29 mtl.diffuse = Vec3(1, 1, 1);
36 glDeleteBuffers(1, &vbo_vertices);
38 glDeleteBuffers(1, &vbo_normals);
40 glDeleteBuffers(1, &vbo_texcoords);
42 glDeleteBuffers(1, &vbo_colors);
44 glDeleteBuffers(1, &ibo);
52 void Mesh::draw() const
56 mtl.diffuse.x, mtl.diffuse.y, mtl.diffuse.z, 1.0
58 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diff);
61 mtl.specular.x, mtl.specular.y, mtl.specular.z, 1.0
63 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
65 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mtl.shininess);
67 glPushAttrib(GL_ENABLE_BIT);
69 glBindTexture(GL_TEXTURE_2D, mtl.tex);
70 glEnable(GL_TEXTURE_2D);
74 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
78 glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
79 glVertexPointer(3, GL_FLOAT, 0, 0);
82 glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
83 glNormalPointer(GL_FLOAT, 0, 0);
84 glEnableClientState(GL_NORMAL_ARRAY);
88 glBindBuffer(GL_ARRAY_BUFFER, vbo_texcoords);
89 glTexCoordPointer(2, GL_FLOAT, 0, 0);
90 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
94 glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
95 glColorPointer(3, GL_FLOAT, 0, 0);
96 glEnableClientState(GL_COLOR_ARRAY);
99 glBindBuffer(GL_ARRAY_BUFFER, 0);
101 glEnableClientState(GL_VERTEX_ARRAY);
104 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
105 glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
106 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
108 glDrawArrays(GL_TRIANGLES, 0, num_vertices);
111 glDisableClientState(GL_VERTEX_ARRAY);
112 glDisableClientState(GL_NORMAL_ARRAY);
113 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
114 glDisableClientState(GL_COLOR_ARRAY);
119 void Mesh::update_vbo(unsigned int which)
121 if((which & MESH_NORMAL) && !normals.empty()) {
123 glGenBuffers(1, &vbo_normals);
125 glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
126 if(num_vertices != (int)normals.size()) {
127 glBufferData(GL_ARRAY_BUFFER, normals.size() * 3 * sizeof(float),
128 &normals[0], GL_STATIC_DRAW);
131 glBufferSubData(GL_ARRAY_BUFFER, 0, normals.size() * 3 * sizeof(float),
136 if((which & MESH_TEXCOORDS) && !texcoords.empty()) {
138 glGenBuffers(1, &vbo_texcoords);
140 glBindBuffer(GL_ARRAY_BUFFER, vbo_texcoords);
141 if(num_vertices != (int)texcoords.size()) {
142 glBufferData(GL_ARRAY_BUFFER, texcoords.size() * 2 * sizeof(float),
143 &texcoords[0], GL_STATIC_DRAW);
146 glBufferSubData(GL_ARRAY_BUFFER, 0, texcoords.size() * 2 * sizeof(float),
151 if((which & MESH_COLOR) && !colors.empty()) {
153 glGenBuffers(1, &vbo_colors);
155 glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
156 if(num_vertices != (int)colors.size()) {
157 glBufferData(GL_ARRAY_BUFFER, colors.size() * 3 * sizeof(float),
158 &colors[0], GL_STATIC_DRAW);
161 glBufferSubData(GL_ARRAY_BUFFER, 0, colors.size() * 3 * sizeof(float),
167 if(which & MESH_VERTEX) {
168 assert(!vertices.empty());
170 glGenBuffers(1, &vbo_vertices);
172 glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
173 if(num_vertices != (int)vertices.size()) {
174 glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float),
175 &vertices[0], GL_STATIC_DRAW);
178 glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * 3 * sizeof(float),
181 num_vertices = vertices.size();
184 if((which & MESH_INDEX) && !indices.empty()) {
186 glGenBuffers(1, &ibo);
188 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
189 if(num_indices != (int)indices.size()) {
190 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * 2,
191 &indices[0], GL_STATIC_DRAW);
194 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * 2,
197 num_indices = indices.size();
201 std::vector<Mesh*> load_meshes(const char *fname)
203 std::vector<Mesh*> meshes;
204 unsigned int ai_flags = aiProcessPreset_TargetRealtime_Quality;
205 const aiScene *scene = aiImportFile(fname, ai_flags);
207 for(unsigned int j=0; j<scene->mNumMeshes; j++) {
208 aiMesh *amesh = scene->mMeshes[j];
209 aiMaterial *amtl = scene->mMaterials[amesh->mMaterialIndex];
211 if(!amesh->HasPositions() || !amesh->mNumFaces)
214 Mesh *mesh = new Mesh;
215 mesh->name = std::string(amesh->mName.C_Str());
216 printf("loading mesh: %s\n", mesh->name.c_str());
218 for(unsigned int i=0; i<amesh->mNumVertices; i++) {
219 Vec3 vertex = Vec3(amesh->mVertices[i].x,
220 amesh->mVertices[i].y,
221 amesh->mVertices[i].z);
222 mesh->vertices.push_back(vertex);
224 printf(" %u vertices\n", amesh->mNumVertices);
226 if(amesh->HasNormals()) {
227 for(unsigned int i=0; i<amesh->mNumVertices; i++) {
228 Vec3 normal = Vec3(amesh->mNormals[i].x,
229 amesh->mNormals[i].y,
230 amesh->mNormals[i].z);
231 mesh->normals.push_back(normal);
235 if(amesh->HasTextureCoords(0)) {
236 for(unsigned int i=0; i<amesh->mNumVertices; i++) {
237 Vec2 tc = Vec2(amesh->mTextureCoords[0][i].x,
238 1.0f - amesh->mTextureCoords[0][i].y);
239 mesh->texcoords.push_back(tc);
243 if(amesh->HasVertexColors(0)) {
244 for(unsigned int i=0; i<amesh->mNumVertices; i++) {
245 Vec3 color = Vec3(amesh->mColors[0][i].r,
246 amesh->mColors[0][i].g,
247 amesh->mColors[0][i].b);
248 mesh->colors.push_back(color);
252 for(unsigned int i=0; i<amesh->mNumFaces; i++) {
253 for(int j=0; j<3; j++) {
254 mesh->indices.push_back(amesh->mFaces[i].mIndices[j]);
257 printf(" %d faces\n", amesh->mNumFaces);
260 aiGetMaterialColor(amtl, AI_MATKEY_COLOR_DIFFUSE, &acol);
261 mesh->mtl.diffuse = Vec3(acol.r, acol.g, acol.b);
264 aiGetMaterialFloat(amtl, AI_MATKEY_SHININESS_STRENGTH, &sstr);
266 aiGetMaterialColor(amtl, AI_MATKEY_COLOR_SPECULAR, &acol);
267 mesh->mtl.specular = sstr * Vec3(acol.r, acol.g, acol.b) * 0.3;
270 aiGetMaterialFloat(amtl, AI_MATKEY_SHININESS, &shin);
271 mesh->mtl.shininess = shin * 6;
274 if(aiGetMaterialTexture(amtl, aiTextureType_DIFFUSE, 0, &astr) == 0) {
275 char *fname = astr.data;
279 if((slash = strrchr(fname, '/'))) {
282 if((slash = strrchr(fname, '\\'))) {
285 path = new char[strlen(fname) + 6];
286 sprintf(path, "data/%s", fname);
287 if(!(mesh->mtl.tex = img_gltexture_load(path))) {
288 fprintf(stderr, "Failed to load texture %s\n", path);
290 mesh->mtl.tex_opaque = check_tex_opaque(mesh->mtl.tex);
291 printf(" texture: %s (%s)\n", path, mesh->mtl.tex_opaque ? "opaque" : "transparent");
296 meshes.push_back(mesh);
299 aiReleaseImport(scene);
303 void Mesh::calc_bbox()
305 if (vertices.empty()) {
306 bbox.v0 = Vec3(0, 0, 0);
307 bbox.v1 = Vec3(0, 0, 0);
312 bbox.v0 = Vec3(FLT_MAX, FLT_MAX, FLT_MAX);
315 for(size_t i=0; i<vertices.size(); i++) {
316 for(int j=0; j<3; j++) {
317 if(vertices[i][j] < bbox.v0[j])
318 bbox.v0[j] = vertices[i][j];
319 if(vertices[i][j] > bbox.v1[j])
320 bbox.v1[j] = vertices[i][j];
325 static bool check_tex_opaque(unsigned int tex)
328 uint32_t *pixels, *pptr;
330 glBindTexture(GL_TEXTURE_2D, tex);
331 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &xsz);
332 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &ysz);
333 assert(xsz > 0 && ysz > 0);
335 pptr = pixels = new uint32_t[xsz * ysz];
336 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
338 for(int i=0; i<xsz * ysz; i++) {
339 if((*pptr++ & 0xff000000) != 0xff000000) {