rev |
line source |
nuclear@10
|
1 #include <stdio.h>
|
nuclear@10
|
2 #include <stdlib.h>
|
nuclear@2
|
3 #include "mesh.h"
|
nuclear@2
|
4 #include "opengl.h"
|
nuclear@2
|
5
|
nuclear@10
|
6 /*
|
nuclear@10
|
7 #define DBG_NORMALS
|
nuclear@10
|
8 #define NSZ 0.1
|
nuclear@10
|
9 */
|
nuclear@10
|
10
|
nuclear@2
|
11 Mesh::Mesh()
|
nuclear@2
|
12 {
|
nuclear@2
|
13 nverts = nfaces = 0;
|
nuclear@2
|
14 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@2
|
15 vbo[i] = 0;
|
nuclear@2
|
16 }
|
nuclear@2
|
17 ibo = 0;
|
nuclear@2
|
18 tang_loc = -1;
|
nuclear@37
|
19
|
nuclear@37
|
20 bsph_valid = false;
|
nuclear@2
|
21 }
|
nuclear@2
|
22
|
nuclear@2
|
23 Mesh::~Mesh()
|
nuclear@2
|
24 {
|
nuclear@2
|
25 destroy();
|
nuclear@2
|
26 }
|
nuclear@2
|
27
|
nuclear@7
|
28 void Mesh::set_name(const char *name)
|
nuclear@7
|
29 {
|
nuclear@7
|
30 this->name = name;
|
nuclear@7
|
31 }
|
nuclear@7
|
32
|
nuclear@4
|
33 const char *Mesh::get_name() const
|
nuclear@4
|
34 {
|
nuclear@4
|
35 return name.c_str();
|
nuclear@4
|
36 }
|
nuclear@4
|
37
|
nuclear@2
|
38 bool Mesh::create(const aiScene *scn, aiMesh *aim)
|
nuclear@2
|
39 {
|
nuclear@37
|
40 if(aim->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) {
|
nuclear@66
|
41 fprintf(stderr, "%s: non-triangle mesh!? primtype mask: %x\n", __FUNCTION__, aim->mPrimitiveTypes);
|
nuclear@37
|
42 return false;
|
nuclear@37
|
43 }
|
nuclear@37
|
44
|
nuclear@2
|
45 if(vbo[MESH_ATTR_VERTEX]) {
|
nuclear@2
|
46 destroy();
|
nuclear@2
|
47 }
|
nuclear@2
|
48
|
nuclear@5
|
49 name = aim->mName.data;
|
nuclear@5
|
50
|
nuclear@2
|
51 nverts = aim->mNumVertices;
|
nuclear@2
|
52 nfaces = aim->mNumFaces;
|
nuclear@2
|
53
|
nuclear@2
|
54 glGenBuffers(1, vbo + MESH_ATTR_VERTEX);
|
nuclear@2
|
55 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
|
nuclear@2
|
56 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mVertices, aim->mVertices, GL_STATIC_DRAW);
|
nuclear@2
|
57
|
nuclear@2
|
58 if(aim->mNormals) {
|
nuclear@2
|
59 glGenBuffers(1, vbo + MESH_ATTR_NORMAL);
|
nuclear@2
|
60 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
|
nuclear@2
|
61 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mNormals, aim->mNormals, GL_STATIC_DRAW);
|
nuclear@2
|
62 }
|
nuclear@2
|
63 if(aim->mTangents) {
|
nuclear@2
|
64 glGenBuffers(1, vbo + MESH_ATTR_TANGENT);
|
nuclear@2
|
65 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
|
nuclear@2
|
66 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTangents, aim->mTangents, GL_STATIC_DRAW);
|
nuclear@2
|
67 }
|
nuclear@2
|
68 if(aim->mTextureCoords[0]) {
|
nuclear@2
|
69 glGenBuffers(1, vbo + MESH_ATTR_TEXCOORD);
|
nuclear@2
|
70 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
|
nuclear@2
|
71 glBufferData(GL_ARRAY_BUFFER, nverts * sizeof *aim->mTextureCoords[0], aim->mTextureCoords[0], GL_STATIC_DRAW);
|
nuclear@2
|
72 }
|
nuclear@2
|
73
|
nuclear@2
|
74 glGenBuffers(1, &ibo);
|
nuclear@2
|
75 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@37
|
76 glBufferData(GL_ELEMENT_ARRAY_BUFFER, nfaces * 3 * sizeof(unsigned int), 0, GL_STATIC_DRAW);
|
nuclear@2
|
77
|
nuclear@2
|
78 /* map the buffer and fill it up */
|
nuclear@2
|
79 unsigned int *iptr = (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
|
nuclear@2
|
80
|
nuclear@4
|
81 for(int i=0; i<(int)nfaces; i++) {
|
nuclear@2
|
82 for(int j=0; j<3; j++) {
|
nuclear@2
|
83 *iptr++ = aim->mFaces[i].mIndices[j];
|
nuclear@2
|
84 }
|
nuclear@2
|
85 }
|
nuclear@2
|
86 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
nuclear@27
|
87 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@27
|
88 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@2
|
89 return true;
|
nuclear@2
|
90 }
|
nuclear@2
|
91
|
nuclear@2
|
92 void Mesh::destroy()
|
nuclear@2
|
93 {
|
nuclear@2
|
94 for(int i=0; i<NUM_MESH_ATTR; i++) {
|
nuclear@2
|
95 if(vbo[i]) {
|
nuclear@2
|
96 glDeleteBuffers(1, vbo + i);
|
nuclear@2
|
97 vbo[i] = 0;
|
nuclear@2
|
98 }
|
nuclear@2
|
99 }
|
nuclear@2
|
100 glDeleteBuffers(1, &ibo);
|
nuclear@2
|
101 ibo = 0;
|
nuclear@2
|
102
|
nuclear@2
|
103 nverts = nfaces = 0;
|
nuclear@2
|
104 tang_loc = -1;
|
nuclear@2
|
105 }
|
nuclear@2
|
106
|
nuclear@7
|
107 void Mesh::set_xform(const Matrix4x4 &mat)
|
nuclear@7
|
108 {
|
nuclear@7
|
109 xform = mat;
|
nuclear@71
|
110 bsph_valid = false;
|
nuclear@7
|
111 }
|
nuclear@7
|
112
|
nuclear@7
|
113 const Matrix4x4 &Mesh::get_xform() const
|
nuclear@7
|
114 {
|
nuclear@7
|
115 return xform;
|
nuclear@7
|
116 }
|
nuclear@7
|
117
|
nuclear@11
|
118 void Mesh::set_material(const Material &mat)
|
nuclear@11
|
119 {
|
nuclear@11
|
120 this->mat = mat;
|
nuclear@11
|
121 }
|
nuclear@11
|
122
|
nuclear@11
|
123 const Material &Mesh::get_material() const
|
nuclear@11
|
124 {
|
nuclear@11
|
125 return mat;
|
nuclear@11
|
126 }
|
nuclear@11
|
127
|
nuclear@2
|
128 void Mesh::set_attrib_location(int attr, int loc)
|
nuclear@2
|
129 {
|
nuclear@2
|
130 if(attr == MESH_ATTR_TANGENT) {
|
nuclear@2
|
131 tang_loc = loc;
|
nuclear@2
|
132 }
|
nuclear@2
|
133 }
|
nuclear@2
|
134
|
nuclear@2
|
135 int Mesh::get_attrib_location(int attr) const
|
nuclear@2
|
136 {
|
nuclear@2
|
137 return tang_loc;
|
nuclear@2
|
138 }
|
nuclear@2
|
139
|
nuclear@2
|
140 void Mesh::draw() const
|
nuclear@2
|
141 {
|
nuclear@11
|
142 mat.setup();
|
nuclear@11
|
143
|
nuclear@7
|
144 glMatrixMode(GL_MODELVIEW);
|
nuclear@7
|
145 glPushMatrix();
|
nuclear@7
|
146 mult_matrix(xform);
|
nuclear@7
|
147
|
nuclear@2
|
148 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
|
nuclear@2
|
149 glVertexPointer(3, GL_FLOAT, 0, 0);
|
nuclear@2
|
150 glEnableClientState(GL_VERTEX_ARRAY);
|
nuclear@2
|
151
|
nuclear@2
|
152 if(vbo[MESH_ATTR_NORMAL]) {
|
nuclear@2
|
153 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
|
nuclear@2
|
154 glNormalPointer(GL_FLOAT, 0, 0);
|
nuclear@2
|
155 glEnableClientState(GL_NORMAL_ARRAY);
|
nuclear@2
|
156 }
|
nuclear@2
|
157 if(vbo[MESH_ATTR_TANGENT] && tang_loc >= 0) {
|
nuclear@2
|
158 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
|
nuclear@2
|
159 glVertexAttribPointer(tang_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
nuclear@2
|
160 glEnableVertexAttribArray(tang_loc);
|
nuclear@2
|
161 }
|
nuclear@2
|
162 if(vbo[MESH_ATTR_TEXCOORD]) {
|
nuclear@2
|
163 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TEXCOORD]);
|
nuclear@2
|
164 glTexCoordPointer(3, GL_FLOAT, 0, 0);
|
nuclear@2
|
165 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@2
|
166 }
|
nuclear@2
|
167
|
nuclear@2
|
168 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
nuclear@2
|
169 glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, 0);
|
nuclear@2
|
170
|
nuclear@2
|
171 glDisableClientState(GL_VERTEX_ARRAY);
|
nuclear@2
|
172 glDisableClientState(GL_NORMAL_ARRAY);
|
nuclear@2
|
173 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
nuclear@2
|
174 if(tang_loc >= 0) {
|
nuclear@2
|
175 glDisableVertexAttribArray(tang_loc);
|
nuclear@2
|
176 }
|
nuclear@7
|
177
|
nuclear@27
|
178 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
nuclear@27
|
179
|
nuclear@10
|
180 #ifdef DBG_NORMALS
|
nuclear@10
|
181 glPushAttrib(GL_ENABLE_BIT);
|
nuclear@10
|
182 glDisable(GL_LIGHTING);
|
nuclear@10
|
183
|
nuclear@10
|
184 int prog;
|
nuclear@10
|
185 glGetIntegerv(GL_CURRENT_PROGRAM, &prog);
|
nuclear@10
|
186 glUseProgram(0);
|
nuclear@10
|
187
|
nuclear@35
|
188 Vector3 *varr, *narr, *tarr;
|
nuclear@10
|
189
|
nuclear@10
|
190 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
|
nuclear@10
|
191 varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@10
|
192
|
nuclear@10
|
193 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
|
nuclear@10
|
194 narr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@10
|
195
|
nuclear@35
|
196 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_TANGENT]);
|
nuclear@35
|
197 tarr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@35
|
198
|
nuclear@10
|
199 glBegin(GL_LINES);
|
nuclear@10
|
200 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@10
|
201 glColor3f(0, 1, 0);
|
nuclear@10
|
202 glVertex3f(varr->x, varr->y, varr->z);
|
nuclear@10
|
203 glVertex3f(varr->x + narr->x * NSZ, varr->y + narr->y * NSZ, varr->z + narr->z * NSZ);
|
nuclear@35
|
204
|
nuclear@35
|
205 glColor3f(1, 1, 0);
|
nuclear@35
|
206 glVertex3f(varr->x, varr->y, varr->z);
|
nuclear@35
|
207 glVertex3f(varr->x + tarr->x * NSZ, varr->y + tarr->y * NSZ, varr->z + tarr->z * NSZ);
|
nuclear@10
|
208 varr++;
|
nuclear@10
|
209 narr++;
|
nuclear@35
|
210 tarr++;
|
nuclear@10
|
211 }
|
nuclear@10
|
212 glEnd();
|
nuclear@10
|
213
|
nuclear@10
|
214 glUnmapBuffer(GL_ARRAY_BUFFER);
|
nuclear@35
|
215 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_NORMAL]);
|
nuclear@35
|
216 glUnmapBuffer(GL_ARRAY_BUFFER);
|
nuclear@10
|
217 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
|
nuclear@10
|
218 glUnmapBuffer(GL_ARRAY_BUFFER);
|
nuclear@10
|
219
|
nuclear@10
|
220 glUseProgram(prog);
|
nuclear@10
|
221 glPopAttrib();
|
nuclear@10
|
222 #endif
|
nuclear@10
|
223
|
nuclear@27
|
224 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@27
|
225
|
nuclear@7
|
226 glPopMatrix();
|
nuclear@2
|
227 }
|
nuclear@21
|
228
|
nuclear@21
|
229
|
nuclear@21
|
230 void Mesh::calc_bsph()
|
nuclear@21
|
231 {
|
nuclear@21
|
232 glBindBuffer(GL_ARRAY_BUFFER, vbo[MESH_ATTR_VERTEX]);
|
nuclear@21
|
233 Vector3 *varr = (Vector3*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
nuclear@21
|
234
|
nuclear@21
|
235 bsph_center = Vector3(0, 0, 0);
|
nuclear@21
|
236
|
nuclear@21
|
237 for(unsigned int i=0; i<nverts; i++) {
|
nuclear@71
|
238 bsph_center += varr[i].transformed(xform);
|
nuclear@21
|
239 }
|
nuclear@21
|
240 bsph_center /= (float)nverts;
|
nuclear@21
|
241
|
nuclear@71
|
242 // XXX assume all vertices are equidistant from the center
|
nuclear@71
|
243 bsph_rad = (varr[0].transformed(xform) - bsph_center).length();
|
nuclear@21
|
244
|
nuclear@21
|
245 glUnmapBuffer(GL_ARRAY_BUFFER);
|
nuclear@21
|
246 bsph_valid = true;
|
nuclear@71
|
247
|
nuclear@71
|
248 printf("calculated center: %f %f %f, rad: %f\n", bsph_center.x, bsph_center.y, bsph_center.z, bsph_rad);
|
nuclear@21
|
249 }
|
nuclear@21
|
250
|
nuclear@21
|
251 const Vector3 &Mesh::get_bsph_center() const
|
nuclear@21
|
252 {
|
nuclear@21
|
253 if(!bsph_valid) {
|
nuclear@21
|
254 ((Mesh*)this)->calc_bsph();
|
nuclear@21
|
255 }
|
nuclear@21
|
256 return bsph_center;
|
nuclear@21
|
257 }
|
nuclear@21
|
258
|
nuclear@21
|
259 float Mesh::get_bsph_radius() const
|
nuclear@21
|
260 {
|
nuclear@21
|
261 if(!bsph_valid) {
|
nuclear@21
|
262 ((Mesh*)this)->calc_bsph();
|
nuclear@21
|
263 }
|
nuclear@21
|
264 return bsph_rad;
|
nuclear@21
|
265 }
|