nuclear@8: #include nuclear@8: #include "mesh.h" nuclear@8: #include "opengl.h" nuclear@8: nuclear@8: Mesh::Mesh() nuclear@8: { nuclear@8: set_primitive(GL_TRIANGLES); nuclear@8: nuclear@8: for(int i=0; iprim = GL_TRIANGLES; nuclear@8: } else { nuclear@8: this->prim = prim; nuclear@8: } nuclear@8: nuclear@8: switch(this->prim) { nuclear@8: case GL_TRIANGLES: nuclear@8: prim_verts = 3; nuclear@8: break; nuclear@8: nuclear@8: case GL_QUADS: nuclear@8: prim_verts = 4; nuclear@8: break; nuclear@8: nuclear@8: case GL_LINES: nuclear@8: prim_verts = 2; nuclear@8: break; nuclear@8: nuclear@8: case GL_POINTS: nuclear@8: prim_verts = 1; nuclear@8: break; nuclear@8: nuclear@8: default: nuclear@8: break; nuclear@8: } nuclear@8: } nuclear@8: nuclear@8: void Mesh::set_attrib_location(int attr, int loc) nuclear@8: { nuclear@8: attrib[attr].sdrloc = loc; nuclear@8: } nuclear@8: nuclear@8: float *Mesh::set_vertex_data(int attr, int nelem, int count, float *data) nuclear@8: { nuclear@8: attrib[attr].data.resize(count * nelem); nuclear@8: if(data) { nuclear@8: memcpy(&attrib[attr].data[0], data, nelem * count * sizeof(float)); nuclear@8: } nuclear@8: nuclear@8: attrib[attr].nelems = nelem; nuclear@8: attrib[attr].vbo_valid = false; nuclear@8: nuclear@8: num_verts = count; nuclear@8: nuclear@8: return &attrib[attr].data[0]; nuclear@8: } nuclear@8: nuclear@8: unsigned int *Mesh::set_index_data(int count, unsigned int *data) nuclear@8: { nuclear@8: index.resize(count); nuclear@8: if(data) { nuclear@8: memcpy(&index[0], data, count * sizeof(unsigned int)); nuclear@8: } nuclear@8: nuclear@8: num_idx = count; nuclear@8: ibo_valid = false; nuclear@8: nuclear@8: return &index[0]; nuclear@8: } nuclear@8: nuclear@8: int Mesh::get_vertex_count() const nuclear@8: { nuclear@8: return num_verts; nuclear@8: } nuclear@8: nuclear@8: float *Mesh::get_vertex_data(int attr) nuclear@8: { nuclear@8: if(attrib[attr].data.empty()) { nuclear@8: return 0; nuclear@8: } nuclear@8: return &attrib[attr].data[0]; nuclear@8: } nuclear@8: nuclear@8: const float *Mesh::get_vertex_data(int attr) const nuclear@8: { nuclear@8: if(attrib[attr].data.empty()) { nuclear@8: return 0; nuclear@8: } nuclear@8: return &attrib[attr].data[0]; nuclear@8: } nuclear@8: nuclear@8: int Mesh::get_index_count() const nuclear@8: { nuclear@8: return num_idx; nuclear@8: } nuclear@8: nuclear@8: unsigned int *Mesh::get_index_data() nuclear@8: { nuclear@8: if(index.empty()) { nuclear@8: return 0; nuclear@8: } nuclear@8: return &index[0]; nuclear@8: } nuclear@8: nuclear@8: const unsigned int *Mesh::get_index_data() const nuclear@8: { nuclear@8: if(index.empty()) { nuclear@8: return 0; nuclear@8: } nuclear@8: return &index[0]; nuclear@8: } nuclear@8: nuclear@8: int Mesh::get_face_count() const nuclear@8: { nuclear@8: if(index.empty()) { nuclear@8: return get_vertex_count() / prim_verts; nuclear@8: } nuclear@8: return get_index_count() / prim_verts; nuclear@8: } nuclear@8: nuclear@8: MeshFace Mesh::get_face(int idx) const nuclear@8: { nuclear@8: MeshFace face; nuclear@8: face.vcount = prim_verts; nuclear@8: nuclear@8: int nfaces = get_face_count(); nuclear@8: if(idx < 0 || idx >= nfaces) { nuclear@8: return face; nuclear@8: } nuclear@8: nuclear@8: const Vector3 *verts = (const Vector3*)&attrib[MESH_VERTEX].data[0]; nuclear@8: nuclear@8: if(index.empty()) { nuclear@8: for(int i=0; i<3; i++) { nuclear@8: face.v[i] = verts[idx * 3 + i]; nuclear@8: } nuclear@8: nuclear@8: } else { nuclear@8: for(int i=0; i<3; i++) { nuclear@8: int vidx = index[idx * 3 + i]; nuclear@8: face.v[i] = verts[vidx]; nuclear@8: } nuclear@8: } nuclear@8: nuclear@8: return face; nuclear@8: } nuclear@8: nuclear@8: nuclear@8: void Mesh::begin(int prim) nuclear@8: { nuclear@8: if(prim == -1) { nuclear@8: this->prim = GL_TRIANGLES; nuclear@8: } else { nuclear@8: this->prim = prim; nuclear@8: } nuclear@8: nuclear@8: clear(); nuclear@8: nuclear@8: cur_norm_valid = false; nuclear@8: cur_tc_valid = false; nuclear@8: cur_tang_valid = false; nuclear@8: } nuclear@8: nuclear@8: void Mesh::end() nuclear@8: { nuclear@8: } nuclear@8: nuclear@8: void Mesh::vertex(float x, float y, float z) nuclear@8: { nuclear@8: if(cur_norm_valid) { nuclear@8: attrib[MESH_NORMAL].data.push_back(cur_norm.x); nuclear@8: attrib[MESH_NORMAL].data.push_back(cur_norm.y); nuclear@8: attrib[MESH_NORMAL].data.push_back(cur_norm.z); nuclear@8: } nuclear@8: if(cur_tc_valid) { nuclear@8: attrib[MESH_TEXCOORD].data.push_back(cur_tc.x); nuclear@8: attrib[MESH_TEXCOORD].data.push_back(cur_tc.y); nuclear@8: } nuclear@8: if(cur_tang_valid) { nuclear@8: attrib[MESH_TANGENT].data.push_back(cur_tang.x); nuclear@8: attrib[MESH_TANGENT].data.push_back(cur_tang.y); nuclear@8: attrib[MESH_TANGENT].data.push_back(cur_tang.z); nuclear@8: } nuclear@8: attrib[MESH_VERTEX].data.push_back(x); nuclear@8: attrib[MESH_VERTEX].data.push_back(y); nuclear@8: attrib[MESH_VERTEX].data.push_back(z); nuclear@8: } nuclear@8: nuclear@8: void Mesh::normal(float x, float y, float z) nuclear@8: { nuclear@8: cur_norm = Vector3(x, y, z); nuclear@8: cur_norm_valid = true; nuclear@8: } nuclear@8: nuclear@8: void Mesh::texcoord(float x, float y) nuclear@8: { nuclear@8: cur_tc = Vector2(x, y); nuclear@8: cur_tc_valid = true; nuclear@8: } nuclear@8: nuclear@8: void Mesh::tangent(float x, float y, float z) nuclear@8: { nuclear@8: cur_tang = Vector3(x, y, z); nuclear@8: cur_tang_valid = true; nuclear@8: } nuclear@8: nuclear@14: void Mesh::update_buffers() nuclear@14: { nuclear@14: for(int i=0; iupdate_buffers(); nuclear@14: nuclear@8: bool use_norm = !attrib[MESH_NORMAL].data.empty(); nuclear@8: bool use_tc = !attrib[MESH_TEXCOORD].data.empty(); nuclear@8: bool use_tang = !attrib[MESH_TANGENT].data.empty(); nuclear@8: int norm_loc, tc_loc, tang_loc; nuclear@8: nuclear@14: glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_VERTEX].vbo); nuclear@8: int loc = attrib[MESH_VERTEX].sdrloc; nuclear@8: if(loc == -1) { nuclear@8: glEnableClientState(GL_VERTEX_ARRAY); nuclear@14: glVertexPointer(attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, 0); nuclear@8: } else { nuclear@8: glEnableVertexAttribArray(loc); nuclear@14: glVertexAttribPointer(loc, attrib[MESH_VERTEX].nelems, GL_FLOAT, 0, 0, 0); nuclear@8: } nuclear@8: nuclear@8: if(use_norm) { nuclear@14: glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_NORMAL].vbo); nuclear@8: norm_loc = attrib[MESH_NORMAL].sdrloc; nuclear@8: if(norm_loc == -1) { nuclear@8: glEnableClientState(GL_NORMAL_ARRAY); nuclear@14: glNormalPointer(GL_FLOAT, 0, 0); nuclear@8: } else { nuclear@8: glEnableVertexAttribArray(norm_loc); nuclear@14: glVertexAttribPointer(norm_loc, attrib[MESH_NORMAL].nelems, GL_FLOAT, 0, 0, 0); nuclear@8: } nuclear@8: } nuclear@8: nuclear@8: if(use_tc) { nuclear@14: glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_TEXCOORD].vbo); nuclear@8: tc_loc = attrib[MESH_TEXCOORD].sdrloc; nuclear@8: if(tc_loc == -1) { nuclear@8: glEnableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@14: glTexCoordPointer(attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, 0); nuclear@8: } else { nuclear@8: glEnableVertexAttribArray(tc_loc); nuclear@14: glVertexAttribPointer(tc_loc, attrib[MESH_TEXCOORD].nelems, GL_FLOAT, 0, 0, 0); nuclear@8: } nuclear@8: } nuclear@8: nuclear@8: if(!attrib[MESH_TANGENT].data.empty()) { nuclear@14: glBindBuffer(GL_ARRAY_BUFFER, attrib[MESH_TANGENT].vbo); nuclear@8: tang_loc = attrib[MESH_TANGENT].sdrloc; nuclear@8: if(tang_loc != -1) { nuclear@8: glEnableVertexAttribArray(tang_loc); nuclear@14: glVertexAttribPointer(tang_loc, attrib[MESH_TANGENT].nelems, GL_FLOAT, 0, 0, 0); nuclear@8: } nuclear@8: } nuclear@8: nuclear@14: glBindBuffer(GL_ARRAY_BUFFER, 0); nuclear@14: nuclear@8: if(!index.empty()) { nuclear@14: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); nuclear@14: glDrawElements(prim, num_idx, GL_UNSIGNED_INT, 0); nuclear@14: glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); nuclear@8: } else { nuclear@8: glDrawArrays(prim, 0, num_verts * 3); nuclear@8: } nuclear@8: nuclear@8: if(use_norm) { nuclear@8: if(norm_loc == -1) { nuclear@8: glDisableClientState(GL_NORMAL_ARRAY); nuclear@8: } else { nuclear@8: glDisableVertexAttribArray(norm_loc); nuclear@8: } nuclear@8: } nuclear@8: if(use_tc) { nuclear@8: if(tc_loc == -1) { nuclear@8: glDisableClientState(GL_TEXTURE_COORD_ARRAY); nuclear@8: } else { nuclear@8: glDisableVertexAttribArray(tc_loc); nuclear@8: } nuclear@8: } nuclear@8: if(use_tang) { nuclear@8: if(tang_loc != -1) { nuclear@8: glDisableVertexAttribArray(tang_loc); nuclear@8: } nuclear@8: } nuclear@8: }