dungeon_crawler

view prototype/src/mesh.cc @ 80:a373b36ffc17

better
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 27 Oct 2012 01:59:39 +0300
parents 6a471c87f9ca
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "mesh.h"
4 #include "opengl.h"
6 /*
7 #define DBG_NORMALS
8 #define NSZ 0.1
9 */
11 Mesh::Mesh()
12 {
13 nverts = nfaces = 0;
14 for(int i=0; i<NUM_MESH_ATTR; i++) {
15 vbo[i] = 0;
16 }
17 ibo = 0;
18 tang_loc = -1;
20 bsph_valid = false;
21 }
23 Mesh::~Mesh()
24 {
25 destroy();
26 }
28 void Mesh::set_name(const char *name)
29 {
30 this->name = name;
31 }
33 const char *Mesh::get_name() const
34 {
35 return name.c_str();
36 }
38 bool Mesh::create(const aiScene *scn, aiMesh *aim)
39 {
40 if(aim->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) {
41 fprintf(stderr, "%s: non-triangle mesh!? primtype mask: %x\n", __FUNCTION__, aim->mPrimitiveTypes);
42 return false;
43 }
45 if(vbo[MESH_ATTR_VERTEX]) {
46 destroy();
47 }
49 name = aim->mName.data;
51 nverts = aim->mNumVertices;
52 nfaces = aim->mNumFaces;
54 glGenBuffers(1, vbo + MESH_ATTR_VERTEX);
55 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
56 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mVertices, aim->mVertices, GL_STATIC_DRAW);
58 if(aim->mNormals) {
59 glGenBuffers(1, vbo + MESH_ATTR_NORMAL);
60 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
61 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mNormals, aim->mNormals, GL_STATIC_DRAW);
62 }
63 if(aim->mTangents) {
64 glGenBuffers(1, vbo + MESH_ATTR_TANGENT);
65 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
66 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTangents, aim->mTangents, GL_STATIC_DRAW);
67 }
68 if(aim->mTextureCoords[0]) {
69 glGenBuffers(1, vbo + MESH_ATTR_TEXCOORD);
70 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
71 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTextureCoords[0], aim->mTextureCoords[0], GL_STATIC_DRAW);
72 }
74 glGenBuffers(1, &ibo);
75 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
76 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), 0, GL_STATIC_DRAW);
78 /* map the buffer and fill it up */
79 unsigned int *iptr = (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
81 for(int i=0; i<(int)nfaces; i++) {
82 for(int j=0; j<3; j++) {
83 *iptr++ = aim->mFaces[i].mIndices[j];
84 }
85 }
86 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
87 glBindBuffer(GL_ARRAY_BUFFER, 0);
88 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
89 return true;
90 }
92 void Mesh::destroy()
93 {
94 for(int i=0; i<NUM_MESH_ATTR; i++) {
95 if(vbo[i]) {
96 glDeleteBuffers(1, vbo + i);
97 vbo[i] = 0;
98 }
99 }
100 glDeleteBuffers(1, &ibo);
101 ibo = 0;
103 nverts = nfaces = 0;
104 tang_loc = -1;
105 }
107 void Mesh::set_xform(const Matrix4x4 &mat)
108 {
109 xform = mat;
110 bsph_valid = false;
111 }
113 const Matrix4x4 &Mesh::get_xform() const
114 {
115 return xform;
116 }
118 void Mesh::set_material(const Material &mat)
119 {
120 this->mat = mat;
121 }
123 const Material &Mesh::get_material() const
124 {
125 return mat;
126 }
128 void Mesh::set_attrib_location(int attr, int loc)
129 {
130 if(attr == MESH_ATTR_TANGENT) {
131 tang_loc = loc;
132 }
133 }
135 int Mesh::get_attrib_location(int attr) const
136 {
137 return tang_loc;
138 }
140 void Mesh::draw() const
141 {
142 mat.setup();
144 glMatrixMode(GL_MODELVIEW);
145 glPushMatrix();
146 mult_matrix(xform);
148 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
149 glVertexPointer(3, GL_FLOAT, 0, 0);
150 glEnableClientState(GL_VERTEX_ARRAY);
152 if(vbo[MESH_ATTR_NORMAL]) {
153 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
154 glNormalPointer(GL_FLOAT, 0, 0);
155 glEnableClientState(GL_NORMAL_ARRAY);
156 }
157 if(vbo[MESH_ATTR_TANGENT] && tang_loc >= 0) {
158 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
159 glVertexAttribPointer(tang_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
160 glEnableVertexAttribArray(tang_loc);
161 }
162 if(vbo[MESH_ATTR_TEXCOORD]) {
163 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
164 glTexCoordPointer(3, GL_FLOAT, 0, 0);
165 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
166 }
168 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
169 glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0);
171 glDisableClientState(GL_VERTEX_ARRAY);
172 glDisableClientState(GL_NORMAL_ARRAY);
173 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
174 if(tang_loc >= 0) {
175 glDisableVertexAttribArray(tang_loc);
176 }
178 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
180 #ifdef DBG_NORMALS
181 glPushAttrib(GL_ENABLE_BIT);
182 glDisable(GL_LIGHTING);
184 int prog;
185 glGetIntegerv(GL_CURRENT_PROGRAM, &prog);
186 glUseProgram(0);
188 Vector3 *varr, *narr, *tarr;
190 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
191 varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
193 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
194 narr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
196 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
197 tarr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
199 glBegin(GL_LINES);
200 for(unsigned int i=0; i<nverts; i++) {
201 glColor3f(0, 1, 0);
202 glVertex3f(varr->x, varr->y, varr->z);
203 glVertex3f(varr->x + narr->x * NSZ, varr->y + narr->y * NSZ, varr->z + narr->z * NSZ);
205 glColor3f(1, 1, 0);
206 glVertex3f(varr->x, varr->y, varr->z);
207 glVertex3f(varr->x + tarr->x * NSZ, varr->y + tarr->y * NSZ, varr->z + tarr->z * NSZ);
208 varr++;
209 narr++;
210 tarr++;
211 }
212 glEnd();
214 glUnmapBuffer(GL_ARRAY_BUFFER);
215 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
216 glUnmapBuffer(GL_ARRAY_BUFFER);
217 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
218 glUnmapBuffer(GL_ARRAY_BUFFER);
220 glUseProgram(prog);
221 glPopAttrib();
222 #endif
224 glBindBuffer(GL_ARRAY_BUFFER, 0);
226 glPopMatrix();
227 }
230 void Mesh::calc_bsph()
231 {
232 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
233 Vector3 *varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
235 bsph_center = Vector3(0, 0, 0);
237 for(unsigned int i=0; i<nverts; i++) {
238 bsph_center += varr[i].transformed(xform);
239 }
240 bsph_center /= (float)nverts;
242 // XXX assume all vertices are equidistant from the center
243 bsph_rad = (varr[0].transformed(xform) - bsph_center).length();
245 glUnmapBuffer(GL_ARRAY_BUFFER);
246 bsph_valid = true;
248 printf("calculated center: %f %f %f, rad: %f\n", bsph_center.x, bsph_center.y, bsph_center.z, bsph_rad);
249 }
251 const Vector3 &Mesh::get_bsph_center() const
252 {
253 if(!bsph_valid) {
254 ((Mesh*)this)->calc_bsph();
255 }
256 return bsph_center;
257 }
259 float Mesh::get_bsph_radius() const
260 {
261 if(!bsph_valid) {
262 ((Mesh*)this)->calc_bsph();
263 }
264 return bsph_rad;
265 }