fixed materials etc (not all), improvements
[hair] / src / mesh.cc
1 #include <GL/glew.h>
2
3 #include <assimp/cimport.h>
4 #include <assimp/postprocess.h>
5 #include <assimp/scene.h>
6 #include <assimp/mesh.h>
7
8 #include <float.h>
9 #include <imago2.h>
10
11 #include "mesh.h"
12
13 Mesh::Mesh()
14 {
15         vbo_vertices = 0;
16         vbo_normals = 0;
17         vbo_colors = 0;
18         ibo = 0;
19
20         num_vertices = 0;
21         num_indices = 0;
22
23         mtl.tex = 0;
24         mtl.diffuse = Vec3(1, 1, 1);
25         mtl.shininess = 50;
26 }
27
28 Mesh::~Mesh()
29 {
30         if(vbo_vertices)
31                 glDeleteBuffers(1, &vbo_vertices);
32         if(vbo_normals)
33                 glDeleteBuffers(1, &vbo_normals);
34         if(vbo_colors)
35                 glDeleteBuffers(1, &vbo_colors);
36         if(ibo)
37                 glDeleteBuffers(1, &ibo);
38
39         vertices.clear();
40         normals.clear();
41         colors.clear();
42 }
43
44 void Mesh::draw() const
45 {
46         /* set material */
47         float diff[4] = {
48                 mtl.diffuse.x, mtl.diffuse.y, mtl.diffuse.z, 1.0
49         };
50         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diff);
51
52         float spec[4] = {
53                 mtl.specular.x, mtl.specular.y, mtl.specular.z, 1.0
54         };
55         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
56
57         glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mtl.shininess);
58
59         if(mtl.tex) {
60                 glBindTexture(GL_TEXTURE_2D, mtl.tex);
61                 glEnable(GL_TEXTURE_2D);
62         }
63
64         glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
65         glVertexPointer(3, GL_FLOAT, 0, 0);
66
67         if(vbo_normals) {
68                 glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
69                 glNormalPointer(GL_FLOAT, 0, 0);
70                 glEnableClientState(GL_NORMAL_ARRAY);
71         }
72
73         if(vbo_colors) {
74                 glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
75                 glColorPointer(3, GL_FLOAT, 0, 0);
76                 glEnableClientState(GL_COLOR_ARRAY);
77         }
78
79         glBindBuffer(GL_ARRAY_BUFFER, 0);
80
81         glEnableClientState(GL_VERTEX_ARRAY);
82
83         if(ibo) {
84                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
85                 glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
86                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
87         } else {
88                 glDrawArrays(GL_TRIANGLES, 0, num_vertices);
89         }
90
91         glDisableClientState(GL_VERTEX_ARRAY);
92         glDisableClientState(GL_NORMAL_ARRAY);
93         glDisableClientState(GL_COLOR_ARRAY);
94         
95
96         if(mtl.tex)
97                 glDisable(GL_TEXTURE_2D);
98 }
99
100 void Mesh::update_vbo(unsigned int which)
101 {
102         if(which & MESH_NORMAL) {
103                 if(!vbo_normals) {
104                         glGenBuffers(1, &vbo_normals);
105                 }
106                 glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
107                 if(num_vertices != (int)normals.size()) {
108                         glBufferData(GL_ARRAY_BUFFER, normals.size() * 3 * sizeof(float),
109                                         &normals[0], GL_STATIC_DRAW);
110                 }
111                 else {
112                         glBufferSubData(GL_ARRAY_BUFFER, 0, normals.size() * 3 * sizeof(float),
113                                         &normals[0]);
114                 }
115         }
116
117         if(which & MESH_COLOR) {
118                 if(!vbo_colors) {
119                         glGenBuffers(1, &vbo_colors);
120                 }
121                 glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
122                 if(num_vertices != (int)colors.size()) {
123                         glBufferData(GL_ARRAY_BUFFER, colors.size() * 3 * sizeof(float),
124                                         &colors[0], GL_STATIC_DRAW);
125                 }
126                 else {
127                         glBufferSubData(GL_ARRAY_BUFFER, 0, colors.size() * 3 * sizeof(float),
128                                         &colors[0]);
129                 }
130         }
131
132
133         if(which & MESH_VERTEX) {
134                 if(!vbo_vertices) {
135                         glGenBuffers(1, &vbo_vertices);
136                 }
137                 glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
138                 if(num_vertices != (int)vertices.size()) {
139                         glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float),
140                                         &vertices[0], GL_STATIC_DRAW);
141                 }
142                 else {
143                         glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * 3 * sizeof(float),
144                                         &vertices[0]);
145                 }
146                 num_vertices = vertices.size();
147         }
148
149         if(which & MESH_INDEX) {
150                 if(!ibo) {
151                         glGenBuffers(1, &ibo);
152                 }
153                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
154                 if(num_indices != (int)indices.size()) {
155                         glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * 2,
156                                         &indices[0], GL_STATIC_DRAW);
157                 }
158                 else {
159                         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * 2,
160                                         &indices[0]);
161                 }
162                 num_indices = indices.size();
163         }
164 }
165
166 std::vector<Mesh*> load_meshes(const char *fname)
167 {
168         std::vector<Mesh*> meshes;
169         unsigned int ai_flags = aiProcessPreset_TargetRealtime_Quality;
170         const aiScene *scene = aiImportFile(fname, ai_flags);
171
172         for(unsigned int j=0; j<scene->mNumMeshes; j++) {
173                 aiMesh *amesh = scene->mMeshes[j];
174                 aiMaterial *amtl = scene->mMaterials[amesh->mMaterialIndex];
175
176                 if(!amesh->HasPositions() || !amesh->mNumFaces)
177                         continue;
178
179                 Mesh *mesh = new Mesh;
180                 mesh->name = std::string(amesh->mName.C_Str());
181                 printf("loading mesh: %s\n", mesh->name.c_str());
182
183                 for(unsigned int i=0; i<amesh->mNumVertices; i++) {
184                         Vec3 vertex = Vec3(amesh->mVertices[i].x,
185                                         amesh->mVertices[i].y,
186                                         amesh->mVertices[i].z);
187                         mesh->vertices.push_back(vertex);
188                 }
189
190                 if(amesh->HasNormals()) {
191                         for(unsigned int i=0; i<amesh->mNumVertices; i++) {
192                                 Vec3 normal = Vec3(amesh->mNormals[i].x,
193                                                            amesh->mNormals[i].y,
194                                                                    amesh->mNormals[i].z);
195                                 mesh->normals.push_back(normal);
196                         }
197                 }
198
199                 if(amesh->HasVertexColors(0)) {
200                         for(unsigned int i=0; i<amesh->mNumVertices; i++) {
201                                 Vec3 color = Vec3(amesh->mColors[0][i].r,
202                                                                   amesh->mColors[0][i].g,
203                                                                   amesh->mColors[0][i].b);
204                                 mesh->colors.push_back(color);
205                         }
206                 }
207
208                 for(unsigned int i=0; i<amesh->mNumFaces; i++) {
209                         for(int j=0; j<3; j++) {
210                                 mesh->indices.push_back(amesh->mFaces[i].mIndices[j]);
211                         }
212                 }
213
214                 aiColor4D acol;
215                 aiGetMaterialColor(amtl, AI_MATKEY_COLOR_DIFFUSE, &acol);
216                 mesh->mtl.diffuse = Vec3(acol.r, acol.g, acol.b);
217
218                 float sstr;
219                 aiGetMaterialFloat(amtl, AI_MATKEY_SHININESS_STRENGTH, &sstr);
220
221                 aiGetMaterialColor(amtl, AI_MATKEY_COLOR_SPECULAR, &acol);
222                 mesh->mtl.specular = sstr * Vec3(acol.r, acol.g, acol.b) * 0.3;
223                 printf("mtl sstr: %f\n", sstr);
224                 printf("mtl spec: %f %f %f\n", acol.r, acol.g, acol.b);
225
226                 float shin;
227                 aiGetMaterialFloat(amtl, AI_MATKEY_SHININESS, &shin);
228                 mesh->mtl.shininess = shin * 6;
229                 printf("mtl shin: %f\n", mesh->mtl.shininess);
230
231                 aiString astr;
232                 if(aiGetMaterialTexture(amtl, aiTextureType_DIFFUSE, 0, &astr) == 0) {
233                         char *fname = astr.data;
234                         char *slash;
235                         char *path;
236
237                         if((slash = strrchr(fname, '/'))) {
238                                 fname = slash + 1;
239                         }
240                         if((slash = strrchr(fname, '\\'))) {
241                                 fname = slash + 1;
242                         }
243                         path = new char[strlen(fname) + 6];
244                         sprintf(path, "data/%s", fname);
245                         if(!(mesh->mtl.tex = img_gltexture_load(path))) {
246                                 fprintf(stderr, "Failed to load texture %s\n", fname);
247                         }
248                         delete [] path;
249                 }
250
251                 meshes.push_back(mesh);
252         }
253
254         return meshes;
255 }
256
257 void Mesh::calc_bbox()
258 {
259         if (vertices.empty()) {
260                 bbox.v0 = Vec3(0, 0, 0);
261                 bbox.v1 = Vec3(0, 0, 0);
262
263                 return;
264         }
265
266         bbox.v0 = Vec3(FLT_MAX, FLT_MAX, FLT_MAX);
267         bbox.v1 = -bbox.v0;
268
269         for(size_t i=0; i<vertices.size(); i++) {
270                 for(int j=0; j<3; j++) {
271                         if(vertices[i][j] < bbox.v0[j])
272                                 bbox.v0[j] = vertices[i][j];
273                         if(vertices[i][j] > bbox.v1[j])
274                                 bbox.v1[j] = vertices[i][j];
275                 }
276         }
277 }