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 }
|