nuclear@10: #include nuclear@10: #include nuclear@2: #include "mesh.h" nuclear@2: #include "opengl.h" nuclear@2: nuclear@10: /* nuclear@10: #define DBG_NORMALS nuclear@10: #define NSZ 0.1 nuclear@10: */ nuclear@10: nuclear@2: Mesh::Mesh() nuclear@2: { nuclear@2: nverts = nfaces = 0; nuclear@2: for(int i=0; iname = name; nuclear@7: } nuclear@7: nuclear@4: const char *Mesh::get_name() const nuclear@4: { nuclear@4: return name.c_str(); nuclear@4: } nuclear@4: nuclear@2: bool Mesh::create(const aiScene *scn, aiMesh *aim) nuclear@2: { nuclear@37: if(aim->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) { nuclear@37: fprintf(stderr, "%s: non-triangle mesh!? primtype mask: %x\n", __func__, aim->mPrimitiveTypes); nuclear@37: return false; nuclear@37: } nuclear@37: nuclear@2: if(vbo[MESH_ATTR_VERTEX]) { nuclear@2: destroy(); nuclear@2: } nuclear@2: nuclear@5: name = aim->mName.data; nuclear@5: nuclear@2: nverts = aim->mNumVertices; nuclear@2: nfaces = aim->mNumFaces; nuclear@2: nuclear@2: glGenBuffers(1, vbo + MESH_ATTR_VERTEX); nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]); nuclear@2: glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mVertices, aim->mVertices, GL_STATIC_DRAW); nuclear@2: nuclear@2: if(aim->mNormals) { nuclear@2: glGenBuffers(1, vbo + MESH_ATTR_NORMAL); nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]); nuclear@2: glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mNormals, aim->mNormals, GL_STATIC_DRAW); nuclear@2: } nuclear@2: if(aim->mTangents) { nuclear@2: glGenBuffers(1, vbo + MESH_ATTR_TANGENT); nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]); nuclear@2: glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTangents, aim->mTangents, GL_STATIC_DRAW); nuclear@2: } nuclear@2: if(aim->mTextureCoords[0]) { nuclear@2: glGenBuffers(1, vbo + MESH_ATTR_TEXCOORD); nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]); nuclear@2: glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTextureCoords[0], aim->mTextureCoords[0], GL_STATIC_DRAW); nuclear@2: } nuclear@2: nuclear@2: glGenBuffers(1, &ibo); nuclear@2: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); nuclear@37: glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), 0, GL_STATIC_DRAW); nuclear@2: nuclear@2: /* map the buffer and fill it up */ nuclear@2: unsigned int *iptr = (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); nuclear@2: nuclear@4: for(int i=0; i<(int)nfaces; i++) { nuclear@2: for(int j=0; j<3; j++) { nuclear@2: *iptr++ = aim->mFaces[i].mIndices[j]; nuclear@2: } nuclear@2: } nuclear@2: glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); nuclear@27: glBindBuffer(GL_ARRAY_BUFFER, 0); nuclear@27: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); nuclear@2: return true; nuclear@2: } nuclear@2: nuclear@2: void Mesh::destroy() nuclear@2: { nuclear@2: for(int i=0; imat = mat; nuclear@11: } nuclear@11: nuclear@11: const Material &Mesh::get_material() const nuclear@11: { nuclear@11: return mat; nuclear@11: } nuclear@11: nuclear@2: void Mesh::set_attrib_location(int attr, int loc) nuclear@2: { nuclear@2: if(attr == MESH_ATTR_TANGENT) { nuclear@2: tang_loc = loc; nuclear@2: } nuclear@2: } nuclear@2: nuclear@2: int Mesh::get_attrib_location(int attr) const nuclear@2: { nuclear@2: return tang_loc; nuclear@2: } nuclear@2: nuclear@2: void Mesh::draw() const nuclear@2: { nuclear@11: mat.setup(); nuclear@11: nuclear@7: glMatrixMode(GL_MODELVIEW); nuclear@7: glPushMatrix(); nuclear@7: mult_matrix(xform); nuclear@7: nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]); nuclear@2: glVertexPointer(3, GL_FLOAT, 0, 0); nuclear@2: glEnableClientState(GL_VERTEX_ARRAY); nuclear@2: nuclear@2: if(vbo[MESH_ATTR_NORMAL]) { nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]); nuclear@2: glNormalPointer(GL_FLOAT, 0, 0); nuclear@2: glEnableClientState(GL_NORMAL_ARRAY); nuclear@2: } nuclear@2: if(vbo[MESH_ATTR_TANGENT] && tang_loc >= 0) { nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]); nuclear@2: glVertexAttribPointer(tang_loc, 3, GL_FLOAT, GL_FALSE, 0, 0); nuclear@2: glEnableVertexAttribArray(tang_loc); nuclear@2: } nuclear@2: if(vbo[MESH_ATTR_TEXCOORD]) { nuclear@2: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]); nuclear@2: glTexCoordPointer(3, GL_FLOAT, 0, 0); nuclear@2: glEnableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@2: } nuclear@2: nuclear@2: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); nuclear@2: glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0); nuclear@2: nuclear@2: glDisableClientState(GL_VERTEX_ARRAY); nuclear@2: glDisableClientState(GL_NORMAL_ARRAY); nuclear@2: glDisableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@2: if(tang_loc >= 0) { nuclear@2: glDisableVertexAttribArray(tang_loc); nuclear@2: } nuclear@7: nuclear@27: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); nuclear@27: nuclear@10: #ifdef DBG_NORMALS nuclear@10: glPushAttrib(GL_ENABLE_BIT); nuclear@10: glDisable(GL_LIGHTING); nuclear@10: nuclear@10: int prog; nuclear@10: glGetIntegerv(GL_CURRENT_PROGRAM, &prog); nuclear@10: glUseProgram(0); nuclear@10: nuclear@35: Vector3 *varr, *narr, *tarr; nuclear@10: nuclear@10: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]); nuclear@10: varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); nuclear@10: nuclear@10: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]); nuclear@10: narr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); nuclear@10: nuclear@35: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]); nuclear@35: tarr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); nuclear@35: nuclear@10: glBegin(GL_LINES); nuclear@10: for(unsigned int i=0; ix, varr->y, varr->z); nuclear@10: glVertex3f(varr->x + narr->x * NSZ, varr->y + narr->y * NSZ, varr->z + narr->z * NSZ); nuclear@35: nuclear@35: glColor3f(1, 1, 0); nuclear@35: glVertex3f(varr->x, varr->y, varr->z); nuclear@35: glVertex3f(varr->x + tarr->x * NSZ, varr->y + tarr->y * NSZ, varr->z + tarr->z * NSZ); nuclear@10: varr++; nuclear@10: narr++; nuclear@35: tarr++; nuclear@10: } nuclear@10: glEnd(); nuclear@10: nuclear@10: glUnmapBuffer(GL_ARRAY_BUFFER); nuclear@35: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]); nuclear@35: glUnmapBuffer(GL_ARRAY_BUFFER); nuclear@10: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]); nuclear@10: glUnmapBuffer(GL_ARRAY_BUFFER); nuclear@10: nuclear@10: glUseProgram(prog); nuclear@10: glPopAttrib(); nuclear@10: #endif nuclear@10: nuclear@27: glBindBuffer(GL_ARRAY_BUFFER, 0); nuclear@27: nuclear@7: glPopMatrix(); nuclear@2: } nuclear@21: nuclear@21: nuclear@21: void Mesh::calc_bsph() nuclear@21: { nuclear@21: glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]); nuclear@21: Vector3 *varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); nuclear@21: nuclear@21: bsph_center = Vector3(0, 0, 0); nuclear@21: nuclear@21: for(unsigned int i=0; icalc_bsph(); nuclear@21: } nuclear@21: return bsph_center; nuclear@21: } nuclear@21: nuclear@21: float Mesh::get_bsph_radius() const nuclear@21: { nuclear@21: if(!bsph_valid) { nuclear@21: ((Mesh*)this)->calc_bsph(); nuclear@21: } nuclear@21: return bsph_rad; nuclear@21: }