dungeon_crawler

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