eqemu

annotate src/mesh.cc @ 12:2656099aff12

added copyright notices and license
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 18 Jul 2014 07:04:21 +0300
parents 3d3656360a82
children
rev   line source
nuclear@12 1 /*
nuclear@12 2 eqemu - electronic queue system emulator
nuclear@12 3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>,
nuclear@12 4 Eleni-Maria Stea <eleni@mutantstargoat.com>
nuclear@12 5
nuclear@12 6 This program is free software: you can redistribute it and/or modify
nuclear@12 7 it under the terms of the GNU General Public License as published by
nuclear@12 8 the Free Software Foundation, either version 3 of the License, or
nuclear@12 9 (at your option) any later version.
nuclear@12 10
nuclear@12 11 This program is distributed in the hope that it will be useful,
nuclear@12 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@12 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@12 14 GNU General Public License for more details.
nuclear@12 15
nuclear@12 16 You should have received a copy of the GNU General Public License
nuclear@12 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
nuclear@12 18 */
nuclear@3 19 #include <stdio.h>
nuclear@3 20 #include <string.h>
nuclear@4 21 #include <math.h>
nuclear@3 22 #include <GL/glew.h>
nuclear@3 23 #include "mesh.h"
nuclear@3 24
nuclear@3 25 #define ALL_VALID 0xffffffff
nuclear@3 26
nuclear@3 27 Mesh::Mesh()
nuclear@3 28 {
nuclear@3 29 buf_valid = ALL_VALID;
nuclear@4 30 bsph_valid = false;
nuclear@3 31
nuclear@4 32 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
nuclear@3 33 attr[i] = 0;
nuclear@3 34 attr_size[i] = 0;
nuclear@3 35 buf_valid &= ~(1 << i);
nuclear@3 36 }
nuclear@3 37 vcount = 0;
nuclear@3 38 glGenBuffers(NUM_MESH_ATTRIBS, vbo);
nuclear@3 39 }
nuclear@3 40
nuclear@3 41 Mesh::~Mesh()
nuclear@3 42 {
nuclear@4 43 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
nuclear@3 44 delete [] attr[i];
nuclear@3 45 }
nuclear@3 46 glDeleteBuffers(NUM_MESH_ATTRIBS, vbo);
nuclear@3 47 }
nuclear@3 48
nuclear@3 49 float *Mesh::set_attrib(int aidx, int count, int elemsz, float *data)
nuclear@3 50 {
nuclear@4 51 delete [] attr[aidx];
nuclear@3 52 attr[aidx] = new float[count * elemsz];
nuclear@4 53 memcpy(attr[aidx], data, count * elemsz * sizeof *data);
nuclear@4 54 vcount = count;
nuclear@3 55 attr_size[aidx] = elemsz;
nuclear@3 56 buf_valid &= ~(1 << aidx);
nuclear@4 57
nuclear@4 58 if(aidx == MESH_ATTR_VERTEX) {
nuclear@4 59 bsph_valid = false;
nuclear@4 60 }
nuclear@4 61
nuclear@3 62 return attr[aidx];
nuclear@3 63 }
nuclear@3 64
nuclear@3 65 float *Mesh::get_attrib(int aidx)
nuclear@3 66 {
nuclear@3 67 buf_valid &= ~(1 << aidx);
nuclear@4 68 if(aidx == MESH_ATTR_VERTEX) {
nuclear@4 69 bsph_valid = false;
nuclear@4 70 }
nuclear@3 71 return attr[aidx];
nuclear@3 72 }
nuclear@3 73
nuclear@3 74 const float *Mesh::get_attrib(int aidx) const
nuclear@3 75 {
nuclear@3 76 return attr[aidx];
nuclear@3 77 }
nuclear@3 78
nuclear@3 79 void Mesh::draw() const
nuclear@3 80 {
nuclear@4 81 if(!vcount) return;
nuclear@4 82
nuclear@3 83 update_buffers();
nuclear@3 84
nuclear@3 85 if(!vbo[MESH_ATTR_VERTEX]) {
nuclear@3 86 fprintf(stderr, "trying to render without a vertex buffer\n");
nuclear@3 87 return;
nuclear@3 88 }
nuclear@3 89
nuclear@3 90 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
nuclear@3 91 glEnableClientState(GL_VERTEX_ARRAY);
nuclear@3 92 glVertexPointer(attr_size[MESH_ATTR_VERTEX], GL_FLOAT, 0, 0);
nuclear@3 93
nuclear@3 94 if(vbo[MESH_ATTR_NORMAL]) {
nuclear@3 95 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
nuclear@3 96 glEnableClientState(GL_NORMAL_ARRAY);
nuclear@3 97 glNormalPointer(GL_FLOAT, 0, 0);
nuclear@3 98 }
nuclear@3 99 if(vbo[MESH_ATTR_TEXCOORD]) {
nuclear@3 100 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
nuclear@3 101 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@3 102 glTexCoordPointer(attr_size[MESH_ATTR_TEXCOORD], GL_FLOAT, 0, 0);
nuclear@3 103 }
nuclear@3 104 glBindBuffer(GL_ARRAY_BUFFER, 0);
nuclear@3 105
nuclear@3 106 glDrawArrays(GL_TRIANGLES, 0, vcount);
nuclear@3 107
nuclear@3 108 glDisableClientState(GL_VERTEX_ARRAY);
nuclear@3 109 if(vbo[MESH_ATTR_NORMAL]) {
nuclear@3 110 glDisableClientState(GL_NORMAL_ARRAY);
nuclear@3 111 }
nuclear@3 112 if(vbo[MESH_ATTR_TEXCOORD]) {
nuclear@3 113 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@3 114 }
nuclear@3 115 }
nuclear@3 116
nuclear@4 117 BSphere &Mesh::get_bounds()
nuclear@4 118 {
nuclear@4 119 calc_bsph();
nuclear@4 120 return bsph;
nuclear@4 121 }
nuclear@4 122
nuclear@4 123 const BSphere &Mesh::get_bounds() const
nuclear@4 124 {
nuclear@4 125 calc_bsph();
nuclear@4 126 return bsph;
nuclear@4 127 }
nuclear@4 128
nuclear@3 129 void Mesh::update_buffers() const
nuclear@3 130 {
nuclear@3 131 if(buf_valid == ALL_VALID) {
nuclear@3 132 return;
nuclear@3 133 }
nuclear@3 134
nuclear@3 135 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
nuclear@3 136 if((buf_valid & (1 << i)) == 0) {
nuclear@3 137 glBindBuffer(GL_ARRAY_BUFFER, vbo[i]);
nuclear@3 138 glBufferData(GL_ARRAY_BUFFER, vcount * attr_size[i] * sizeof(float),
nuclear@3 139 attr[i], GL_STATIC_DRAW);
nuclear@3 140 buf_valid |= 1 << i;
nuclear@3 141 }
nuclear@3 142 }
nuclear@3 143 }
nuclear@4 144
nuclear@4 145 void Mesh::calc_bsph() const
nuclear@4 146 {
nuclear@4 147 if(bsph_valid || !vcount) {
nuclear@4 148 return;
nuclear@4 149 }
nuclear@4 150
nuclear@4 151 Vector3 center;
nuclear@4 152
nuclear@4 153 float *vptr = attr[MESH_ATTR_VERTEX];
nuclear@4 154 for(int i=0; i<vcount; i++) {
nuclear@4 155 center = center + Vector3(vptr[0], vptr[1], vptr[2]);
nuclear@4 156 vptr += 3;
nuclear@4 157 }
nuclear@4 158 center = center * (1.0f / (float)vcount);
nuclear@4 159
nuclear@4 160 float max_lensq = 0.0f;
nuclear@4 161 vptr = attr[MESH_ATTR_VERTEX];
nuclear@4 162 for(int i=0; i<vcount; i++) {
nuclear@4 163 Vector3 v = Vector3(vptr[0], vptr[1], vptr[2]) - center;
nuclear@4 164 float lensq = dot(v, v);
nuclear@4 165 if(lensq > max_lensq) {
nuclear@4 166 max_lensq = lensq;
nuclear@4 167 }
nuclear@4 168 }
nuclear@4 169
nuclear@4 170 bsph.set_center(center);
nuclear@4 171 bsph.set_radius(sqrt(max_lensq));
nuclear@4 172
nuclear@4 173 bsph_valid = true;
nuclear@4 174 }