eqemu

annotate src/mesh.cc @ 4:3d3656360a82

rendering properly, added picking, almost done...
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 17 Jul 2014 08:51:17 +0300
parents f9274bebe55e
children 2656099aff12
rev   line source
nuclear@3 1 #include <stdio.h>
nuclear@3 2 #include <string.h>
nuclear@4 3 #include <math.h>
nuclear@3 4 #include <GL/glew.h>
nuclear@3 5 #include "mesh.h"
nuclear@3 6
nuclear@3 7 #define ALL_VALID 0xffffffff
nuclear@3 8
nuclear@3 9 Mesh::Mesh()
nuclear@3 10 {
nuclear@3 11 buf_valid = ALL_VALID;
nuclear@4 12 bsph_valid = false;
nuclear@3 13
nuclear@4 14 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
nuclear@3 15 attr[i] = 0;
nuclear@3 16 attr_size[i] = 0;
nuclear@3 17 buf_valid &= ~(1 << i);
nuclear@3 18 }
nuclear@3 19 vcount = 0;
nuclear@3 20 glGenBuffers(NUM_MESH_ATTRIBS, vbo);
nuclear@3 21 }
nuclear@3 22
nuclear@3 23 Mesh::~Mesh()
nuclear@3 24 {
nuclear@4 25 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
nuclear@3 26 delete [] attr[i];
nuclear@3 27 }
nuclear@3 28 glDeleteBuffers(NUM_MESH_ATTRIBS, vbo);
nuclear@3 29 }
nuclear@3 30
nuclear@3 31 float *Mesh::set_attrib(int aidx, int count, int elemsz, float *data)
nuclear@3 32 {
nuclear@4 33 delete [] attr[aidx];
nuclear@3 34 attr[aidx] = new float[count * elemsz];
nuclear@4 35 memcpy(attr[aidx], data, count * elemsz * sizeof *data);
nuclear@4 36 vcount = count;
nuclear@3 37 attr_size[aidx] = elemsz;
nuclear@3 38 buf_valid &= ~(1 << aidx);
nuclear@4 39
nuclear@4 40 if(aidx == MESH_ATTR_VERTEX) {
nuclear@4 41 bsph_valid = false;
nuclear@4 42 }
nuclear@4 43
nuclear@3 44 return attr[aidx];
nuclear@3 45 }
nuclear@3 46
nuclear@3 47 float *Mesh::get_attrib(int aidx)
nuclear@3 48 {
nuclear@3 49 buf_valid &= ~(1 << aidx);
nuclear@4 50 if(aidx == MESH_ATTR_VERTEX) {
nuclear@4 51 bsph_valid = false;
nuclear@4 52 }
nuclear@3 53 return attr[aidx];
nuclear@3 54 }
nuclear@3 55
nuclear@3 56 const float *Mesh::get_attrib(int aidx) const
nuclear@3 57 {
nuclear@3 58 return attr[aidx];
nuclear@3 59 }
nuclear@3 60
nuclear@3 61 void Mesh::draw() const
nuclear@3 62 {
nuclear@4 63 if(!vcount) return;
nuclear@4 64
nuclear@3 65 update_buffers();
nuclear@3 66
nuclear@3 67 if(!vbo[MESH_ATTR_VERTEX]) {
nuclear@3 68 fprintf(stderr, "trying to render without a vertex buffer\n");
nuclear@3 69 return;
nuclear@3 70 }
nuclear@3 71
nuclear@3 72 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
nuclear@3 73 glEnableClientState(GL_VERTEX_ARRAY);
nuclear@3 74 glVertexPointer(attr_size[MESH_ATTR_VERTEX], GL_FLOAT, 0, 0);
nuclear@3 75
nuclear@3 76 if(vbo[MESH_ATTR_NORMAL]) {
nuclear@3 77 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
nuclear@3 78 glEnableClientState(GL_NORMAL_ARRAY);
nuclear@3 79 glNormalPointer(GL_FLOAT, 0, 0);
nuclear@3 80 }
nuclear@3 81 if(vbo[MESH_ATTR_TEXCOORD]) {
nuclear@3 82 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
nuclear@3 83 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@3 84 glTexCoordPointer(attr_size[MESH_ATTR_TEXCOORD], GL_FLOAT, 0, 0);
nuclear@3 85 }
nuclear@3 86 glBindBuffer(GL_ARRAY_BUFFER, 0);
nuclear@3 87
nuclear@3 88 glDrawArrays(GL_TRIANGLES, 0, vcount);
nuclear@3 89
nuclear@3 90 glDisableClientState(GL_VERTEX_ARRAY);
nuclear@3 91 if(vbo[MESH_ATTR_NORMAL]) {
nuclear@3 92 glDisableClientState(GL_NORMAL_ARRAY);
nuclear@3 93 }
nuclear@3 94 if(vbo[MESH_ATTR_TEXCOORD]) {
nuclear@3 95 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@3 96 }
nuclear@3 97 }
nuclear@3 98
nuclear@4 99 BSphere &Mesh::get_bounds()
nuclear@4 100 {
nuclear@4 101 calc_bsph();
nuclear@4 102 return bsph;
nuclear@4 103 }
nuclear@4 104
nuclear@4 105 const BSphere &Mesh::get_bounds() const
nuclear@4 106 {
nuclear@4 107 calc_bsph();
nuclear@4 108 return bsph;
nuclear@4 109 }
nuclear@4 110
nuclear@3 111 void Mesh::update_buffers() const
nuclear@3 112 {
nuclear@3 113 if(buf_valid == ALL_VALID) {
nuclear@3 114 return;
nuclear@3 115 }
nuclear@3 116
nuclear@3 117 for(int i=0; i<NUM_MESH_ATTRIBS; i++) {
nuclear@3 118 if((buf_valid & (1 << i)) == 0) {
nuclear@3 119 glBindBuffer(GL_ARRAY_BUFFER, vbo[i]);
nuclear@3 120 glBufferData(GL_ARRAY_BUFFER, vcount * attr_size[i] * sizeof(float),
nuclear@3 121 attr[i], GL_STATIC_DRAW);
nuclear@3 122 buf_valid |= 1 << i;
nuclear@3 123 }
nuclear@3 124 }
nuclear@3 125 }
nuclear@4 126
nuclear@4 127 void Mesh::calc_bsph() const
nuclear@4 128 {
nuclear@4 129 if(bsph_valid || !vcount) {
nuclear@4 130 return;
nuclear@4 131 }
nuclear@4 132
nuclear@4 133 Vector3 center;
nuclear@4 134
nuclear@4 135 float *vptr = attr[MESH_ATTR_VERTEX];
nuclear@4 136 for(int i=0; i<vcount; i++) {
nuclear@4 137 center = center + Vector3(vptr[0], vptr[1], vptr[2]);
nuclear@4 138 vptr += 3;
nuclear@4 139 }
nuclear@4 140 center = center * (1.0f / (float)vcount);
nuclear@4 141
nuclear@4 142 float max_lensq = 0.0f;
nuclear@4 143 vptr = attr[MESH_ATTR_VERTEX];
nuclear@4 144 for(int i=0; i<vcount; i++) {
nuclear@4 145 Vector3 v = Vector3(vptr[0], vptr[1], vptr[2]) - center;
nuclear@4 146 float lensq = dot(v, v);
nuclear@4 147 if(lensq > max_lensq) {
nuclear@4 148 max_lensq = lensq;
nuclear@4 149 }
nuclear@4 150 }
nuclear@4 151
nuclear@4 152 bsph.set_center(center);
nuclear@4 153 bsph.set_radius(sqrt(max_lensq));
nuclear@4 154
nuclear@4 155 bsph_valid = true;
nuclear@4 156 }