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