dungeon_crawler

view prototype/src/mesh.cc @ 35:d0e93b4d9ec9

normal mapping
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 28 Aug 2012 06:28:22 +0300
parents cbf86e5198a9
children 84a56fb24850
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;
19 }
21 Mesh::~Mesh()
22 {
23 destroy();
24 }
26 void Mesh::set_name(const char *name)
27 {
28 this->name = name;
29 }
31 const char *Mesh::get_name() const
32 {
33 return name.c_str();
34 }
36 bool Mesh::create(const aiScene *scn, aiMesh *aim)
37 {
38 if(vbo[MESH_ATTR_VERTEX]) {
39 destroy();
40 }
42 name = aim->mName.data;
44 nverts = aim->mNumVertices;
45 nfaces = aim->mNumFaces;
47 glGenBuffers(1, vbo + MESH_ATTR_VERTEX);
48 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
49 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mVertices, aim->mVertices, GL_STATIC_DRAW);
51 if(aim->mNormals) {
52 glGenBuffers(1, vbo + MESH_ATTR_NORMAL);
53 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
54 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mNormals, aim->mNormals, GL_STATIC_DRAW);
55 }
56 if(aim->mTangents) {
57 glGenBuffers(1, vbo + MESH_ATTR_TANGENT);
58 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
59 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTangents, aim->mTangents, GL_STATIC_DRAW);
60 }
61 if(aim->mTextureCoords[0]) {
62 glGenBuffers(1, vbo + MESH_ATTR_TEXCOORD);
63 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
64 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTextureCoords[0], aim->mTextureCoords[0], GL_STATIC_DRAW);
65 }
67 glGenBuffers(1, &ibo);
68 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
69 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof *aim->mFaces[0].mIndices, 0, GL_STATIC_DRAW);
71 /* map the buffer and fill it up */
72 unsigned int *iptr = (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
74 for(int i=0; i<(int)nfaces; i++) {
75 for(int j=0; j<3; j++) {
76 *iptr++ = aim->mFaces[i].mIndices[j];
77 }
78 }
79 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
80 glBindBuffer(GL_ARRAY_BUFFER, 0);
81 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
82 return true;
83 }
85 void Mesh::destroy()
86 {
87 for(int i=0; i<NUM_MESH_ATTR; i++) {
88 if(vbo[i]) {
89 glDeleteBuffers(1, vbo + i);
90 vbo[i] = 0;
91 }
92 }
93 glDeleteBuffers(1, &ibo);
94 ibo = 0;
96 nverts = nfaces = 0;
97 tang_loc = -1;
98 }
100 void Mesh::set_xform(const Matrix4x4 &mat)
101 {
102 xform = mat;
103 }
105 const Matrix4x4 &Mesh::get_xform() const
106 {
107 return xform;
108 }
110 void Mesh::set_material(const Material &mat)
111 {
112 this->mat = mat;
113 }
115 const Material &Mesh::get_material() const
116 {
117 return mat;
118 }
120 void Mesh::set_attrib_location(int attr, int loc)
121 {
122 if(attr == MESH_ATTR_TANGENT) {
123 tang_loc = loc;
124 }
125 }
127 int Mesh::get_attrib_location(int attr) const
128 {
129 return tang_loc;
130 }
132 void Mesh::draw() const
133 {
134 mat.setup();
136 glMatrixMode(GL_MODELVIEW);
137 glPushMatrix();
138 mult_matrix(xform);
140 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
141 glVertexPointer(3, GL_FLOAT, 0, 0);
142 glEnableClientState(GL_VERTEX_ARRAY);
144 if(vbo[MESH_ATTR_NORMAL]) {
145 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
146 glNormalPointer(GL_FLOAT, 0, 0);
147 glEnableClientState(GL_NORMAL_ARRAY);
148 }
149 if(vbo[MESH_ATTR_TANGENT] && tang_loc >= 0) {
150 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
151 glVertexAttribPointer(tang_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
152 glEnableVertexAttribArray(tang_loc);
153 }
154 if(vbo[MESH_ATTR_TEXCOORD]) {
155 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
156 glTexCoordPointer(3, GL_FLOAT, 0, 0);
157 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
158 }
160 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
161 glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0);
163 glDisableClientState(GL_VERTEX_ARRAY);
164 glDisableClientState(GL_NORMAL_ARRAY);
165 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
166 if(tang_loc >= 0) {
167 glDisableVertexAttribArray(tang_loc);
168 }
170 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
172 #ifdef DBG_NORMALS
173 glPushAttrib(GL_ENABLE_BIT);
174 glDisable(GL_LIGHTING);
176 int prog;
177 glGetIntegerv(GL_CURRENT_PROGRAM, &prog);
178 glUseProgram(0);
180 Vector3 *varr, *narr, *tarr;
182 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
183 varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
185 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
186 narr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
188 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
189 tarr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
191 glBegin(GL_LINES);
192 for(unsigned int i=0; i<nverts; i++) {
193 glColor3f(0, 1, 0);
194 glVertex3f(varr->x, varr->y, varr->z);
195 glVertex3f(varr->x + narr->x * NSZ, varr->y + narr->y * NSZ, varr->z + narr->z * NSZ);
197 glColor3f(1, 1, 0);
198 glVertex3f(varr->x, varr->y, varr->z);
199 glVertex3f(varr->x + tarr->x * NSZ, varr->y + tarr->y * NSZ, varr->z + tarr->z * NSZ);
200 varr++;
201 narr++;
202 tarr++;
203 }
204 glEnd();
206 glUnmapBuffer(GL_ARRAY_BUFFER);
207 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
208 glUnmapBuffer(GL_ARRAY_BUFFER);
209 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
210 glUnmapBuffer(GL_ARRAY_BUFFER);
212 glUseProgram(prog);
213 glPopAttrib();
214 #endif
216 glBindBuffer(GL_ARRAY_BUFFER, 0);
218 glPopMatrix();
219 }
222 void Mesh::calc_bsph()
223 {
224 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
225 Vector3 *varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
227 bsph_center = Vector3(0, 0, 0);
229 for(unsigned int i=0; i<nverts; i++) {
230 bsph_center += varr[i];
231 }
232 bsph_center /= (float)nverts;
234 // assume all vertices are equidistant from the center
235 bsph_rad = (varr[0] - bsph_center).length();
237 glUnmapBuffer(GL_ARRAY_BUFFER);
238 bsph_valid = true;
239 }
241 const Vector3 &Mesh::get_bsph_center() const
242 {
243 if(!bsph_valid) {
244 ((Mesh*)this)->calc_bsph();
245 }
246 return bsph_center;
247 }
249 float Mesh::get_bsph_radius() const
250 {
251 if(!bsph_valid) {
252 ((Mesh*)this)->calc_bsph();
253 }
254 return bsph_rad;
255 }