dungeon_crawler

annotate prototype/src/mesh.cc @ 21:0588f8a1a351

converting LIGHT meshes to lights
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 21 Aug 2012 06:33:36 +0300
parents e5567ddbf2ef
children cbf86e5198a9
rev   line source
nuclear@10 1 #include <stdio.h>
nuclear@10 2 #include <stdlib.h>
nuclear@2 3 #include "mesh.h"
nuclear@2 4 #include "opengl.h"
nuclear@2 5
nuclear@10 6 /*
nuclear@10 7 #define DBG_NORMALS
nuclear@10 8 #define NSZ 0.1
nuclear@10 9 */
nuclear@10 10
nuclear@2 11 Mesh::Mesh()
nuclear@2 12 {
nuclear@2 13 nverts = nfaces = 0;
nuclear@2 14 for(int i=0; i<NUM_MESH_ATTR; i++) {
nuclear@2 15 vbo[i] = 0;
nuclear@2 16 }
nuclear@2 17 ibo = 0;
nuclear@2 18 tang_loc = -1;
nuclear@2 19 }
nuclear@2 20
nuclear@2 21 Mesh::~Mesh()
nuclear@2 22 {
nuclear@2 23 destroy();
nuclear@2 24 }
nuclear@2 25
nuclear@7 26 void Mesh::set_name(const char *name)
nuclear@7 27 {
nuclear@7 28 this->name = name;
nuclear@7 29 }
nuclear@7 30
nuclear@4 31 const char *Mesh::get_name() const
nuclear@4 32 {
nuclear@4 33 return name.c_str();
nuclear@4 34 }
nuclear@4 35
nuclear@2 36 bool Mesh::create(const aiScene *scn, aiMesh *aim)
nuclear@2 37 {
nuclear@2 38 if(vbo[MESH_ATTR_VERTEX]) {
nuclear@2 39 destroy();
nuclear@2 40 }
nuclear@2 41
nuclear@5 42 name = aim->mName.data;
nuclear@5 43
nuclear@2 44 nverts = aim->mNumVertices;
nuclear@2 45 nfaces = aim->mNumFaces;
nuclear@2 46
nuclear@2 47 glGenBuffers(1, vbo + MESH_ATTR_VERTEX);
nuclear@2 48 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
nuclear@2 49 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mVertices, aim->mVertices, GL_STATIC_DRAW);
nuclear@2 50
nuclear@2 51 if(aim->mNormals) {
nuclear@2 52 glGenBuffers(1, vbo + MESH_ATTR_NORMAL);
nuclear@2 53 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
nuclear@2 54 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mNormals, aim->mNormals, GL_STATIC_DRAW);
nuclear@2 55 }
nuclear@2 56 if(aim->mTangents) {
nuclear@2 57 glGenBuffers(1, vbo + MESH_ATTR_TANGENT);
nuclear@2 58 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
nuclear@2 59 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTangents, aim->mTangents, GL_STATIC_DRAW);
nuclear@2 60 }
nuclear@2 61 if(aim->mTextureCoords[0]) {
nuclear@2 62 glGenBuffers(1, vbo + MESH_ATTR_TEXCOORD);
nuclear@2 63 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
nuclear@2 64 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTextureCoords[0], aim->mTextureCoords[0], GL_STATIC_DRAW);
nuclear@2 65 }
nuclear@2 66
nuclear@2 67 glGenBuffers(1, &ibo);
nuclear@2 68 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
nuclear@2 69 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof *aim->mFaces[0].mIndices, 0, GL_STATIC_DRAW);
nuclear@2 70
nuclear@2 71 /* map the buffer and fill it up */
nuclear@2 72 unsigned int *iptr = (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
nuclear@2 73
nuclear@4 74 for(int i=0; i<(int)nfaces; i++) {
nuclear@2 75 for(int j=0; j<3; j++) {
nuclear@2 76 *iptr++ = aim->mFaces[i].mIndices[j];
nuclear@2 77 }
nuclear@2 78 }
nuclear@2 79 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
nuclear@2 80 return true;
nuclear@2 81 }
nuclear@2 82
nuclear@2 83 void Mesh::destroy()
nuclear@2 84 {
nuclear@2 85 for(int i=0; i<NUM_MESH_ATTR; i++) {
nuclear@2 86 if(vbo[i]) {
nuclear@2 87 glDeleteBuffers(1, vbo + i);
nuclear@2 88 vbo[i] = 0;
nuclear@2 89 }
nuclear@2 90 }
nuclear@2 91 glDeleteBuffers(1, &ibo);
nuclear@2 92 ibo = 0;
nuclear@2 93
nuclear@2 94 nverts = nfaces = 0;
nuclear@2 95 tang_loc = -1;
nuclear@2 96 }
nuclear@2 97
nuclear@7 98 void Mesh::set_xform(const Matrix4x4 &mat)
nuclear@7 99 {
nuclear@7 100 xform = mat;
nuclear@7 101 }
nuclear@7 102
nuclear@7 103 const Matrix4x4 &Mesh::get_xform() const
nuclear@7 104 {
nuclear@7 105 return xform;
nuclear@7 106 }
nuclear@7 107
nuclear@11 108 void Mesh::set_material(const Material &mat)
nuclear@11 109 {
nuclear@11 110 this->mat = mat;
nuclear@11 111 }
nuclear@11 112
nuclear@11 113 const Material &Mesh::get_material() const
nuclear@11 114 {
nuclear@11 115 return mat;
nuclear@11 116 }
nuclear@11 117
nuclear@2 118 void Mesh::set_attrib_location(int attr, int loc)
nuclear@2 119 {
nuclear@2 120 if(attr == MESH_ATTR_TANGENT) {
nuclear@2 121 tang_loc = loc;
nuclear@2 122 }
nuclear@2 123 }
nuclear@2 124
nuclear@2 125 int Mesh::get_attrib_location(int attr) const
nuclear@2 126 {
nuclear@2 127 return tang_loc;
nuclear@2 128 }
nuclear@2 129
nuclear@2 130 void Mesh::draw() const
nuclear@2 131 {
nuclear@11 132 mat.setup();
nuclear@11 133
nuclear@7 134 glMatrixMode(GL_MODELVIEW);
nuclear@7 135 glPushMatrix();
nuclear@7 136 mult_matrix(xform);
nuclear@7 137
nuclear@2 138 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
nuclear@2 139 glVertexPointer(3, GL_FLOAT, 0, 0);
nuclear@2 140 glEnableClientState(GL_VERTEX_ARRAY);
nuclear@2 141
nuclear@2 142 if(vbo[MESH_ATTR_NORMAL]) {
nuclear@2 143 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
nuclear@2 144 glNormalPointer(GL_FLOAT, 0, 0);
nuclear@2 145 glEnableClientState(GL_NORMAL_ARRAY);
nuclear@2 146 }
nuclear@2 147 if(vbo[MESH_ATTR_TANGENT] && tang_loc >= 0) {
nuclear@2 148 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
nuclear@2 149 glVertexAttribPointer(tang_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
nuclear@2 150 glEnableVertexAttribArray(tang_loc);
nuclear@2 151 }
nuclear@2 152 if(vbo[MESH_ATTR_TEXCOORD]) {
nuclear@2 153 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
nuclear@2 154 glTexCoordPointer(3, GL_FLOAT, 0, 0);
nuclear@2 155 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@2 156 }
nuclear@2 157
nuclear@2 158 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
nuclear@2 159 glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0);
nuclear@2 160
nuclear@2 161 glDisableClientState(GL_VERTEX_ARRAY);
nuclear@2 162 glDisableClientState(GL_NORMAL_ARRAY);
nuclear@2 163 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@2 164 if(tang_loc >= 0) {
nuclear@2 165 glDisableVertexAttribArray(tang_loc);
nuclear@2 166 }
nuclear@7 167
nuclear@10 168 #ifdef DBG_NORMALS
nuclear@10 169 glPushAttrib(GL_ENABLE_BIT);
nuclear@10 170 glDisable(GL_LIGHTING);
nuclear@10 171
nuclear@10 172 int prog;
nuclear@10 173 glGetIntegerv(GL_CURRENT_PROGRAM, &prog);
nuclear@10 174 glUseProgram(0);
nuclear@10 175
nuclear@10 176 Vector3 *varr, *narr;
nuclear@10 177
nuclear@10 178 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
nuclear@10 179 varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
nuclear@10 180
nuclear@10 181 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
nuclear@10 182 narr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
nuclear@10 183
nuclear@10 184 glBegin(GL_LINES);
nuclear@10 185 for(unsigned int i=0; i<nverts; i++) {
nuclear@10 186 glColor3f(0, 1, 0);
nuclear@10 187 glVertex3f(varr->x, varr->y, varr->z);
nuclear@10 188 glVertex3f(varr->x + narr->x * NSZ, varr->y + narr->y * NSZ, varr->z + narr->z * NSZ);
nuclear@10 189 varr++;
nuclear@10 190 narr++;
nuclear@10 191 }
nuclear@10 192 glEnd();
nuclear@10 193
nuclear@10 194 glUnmapBuffer(GL_ARRAY_BUFFER);
nuclear@10 195 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
nuclear@10 196 glUnmapBuffer(GL_ARRAY_BUFFER);
nuclear@10 197
nuclear@10 198 glUseProgram(prog);
nuclear@10 199 glPopAttrib();
nuclear@10 200 #endif
nuclear@10 201
nuclear@7 202 glPopMatrix();
nuclear@2 203 }
nuclear@21 204
nuclear@21 205
nuclear@21 206 void Mesh::calc_bsph()
nuclear@21 207 {
nuclear@21 208 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
nuclear@21 209 Vector3 *varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
nuclear@21 210
nuclear@21 211 bsph_center = Vector3(0, 0, 0);
nuclear@21 212
nuclear@21 213 for(unsigned int i=0; i<nverts; i++) {
nuclear@21 214 bsph_center += varr[i];
nuclear@21 215 }
nuclear@21 216 bsph_center /= (float)nverts;
nuclear@21 217
nuclear@21 218 // assume all vertices are equidistant from the center
nuclear@21 219 bsph_rad = (varr[0] - bsph_center).length();
nuclear@21 220
nuclear@21 221 glUnmapBuffer(GL_ARRAY_BUFFER);
nuclear@21 222 bsph_valid = true;
nuclear@21 223 }
nuclear@21 224
nuclear@21 225 const Vector3 &Mesh::get_bsph_center() const
nuclear@21 226 {
nuclear@21 227 if(!bsph_valid) {
nuclear@21 228 ((Mesh*)this)->calc_bsph();
nuclear@21 229 }
nuclear@21 230 return bsph_center;
nuclear@21 231 }
nuclear@21 232
nuclear@21 233 float Mesh::get_bsph_radius() const
nuclear@21 234 {
nuclear@21 235 if(!bsph_valid) {
nuclear@21 236 ((Mesh*)this)->calc_bsph();
nuclear@21 237 }
nuclear@21 238 return bsph_rad;
nuclear@21 239 }