goat3dgfx

view src/meshgen.cc @ 29:9d581abd0bfb

merged
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 02 Mar 2014 02:18:15 +0200
parents 7d6b667821cf
children
line source
1 #include "meshgen.h"
2 #include "mesh.h"
3 #include "logger.h"
5 using namespace goatgfx;
7 // -------- sphere --------
9 #define SURAD(u) ((u) * 2.0 * M_PI)
10 #define SVRAD(v) ((v) * M_PI)
12 static Vector3 sphvec(float theta, float phi)
13 {
14 return Vector3(sin(theta) * sin(phi),
15 cos(phi),
16 cos(theta) * sin(phi));
17 }
19 void goatgfx::gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange)
20 {
21 if(usub < 4) usub = 4;
22 if(vsub < 2) vsub = 2;
24 int uverts = usub + 1;
25 int vverts = vsub + 1;
27 int num_verts = uverts * vverts;
28 int num_quads = usub * vsub;
29 int num_tri = num_quads * 2;
31 mesh->clear();
32 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
33 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
34 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
35 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
36 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
38 float du = urange / (float)(uverts - 1);
39 float dv = vrange / (float)(vverts - 1);
41 float u = 0.0;
42 for(int i=0; i<uverts; i++) {
43 float theta = SURAD(u * urange);
45 float v = 0.0;
46 for(int j=0; j<vverts; j++) {
47 float phi = SVRAD(v * vrange);
49 Vector3 pos = sphvec(theta, phi);
51 *varr++ = pos * rad;
52 *narr++ = pos;
53 *tarr++ = (sphvec(theta + 0.1, M_PI / 2.0) - sphvec(theta - 0.1, M_PI / 2.0)).normalized();
54 *uvarr++ = Vector2(u * urange, v * vrange);
56 if(i < usub && j < vsub) {
57 int idx = i * vverts + j;
58 *idxarr++ = idx;
59 *idxarr++ = idx + 1;
60 *idxarr++ = idx + vverts + 1;
62 *idxarr++ = idx;
63 *idxarr++ = idx + vverts + 1;
64 *idxarr++ = idx + vverts;
65 }
67 v += dv;
68 }
69 u += du;
70 }
71 }
74 // -------- cylinder --------
76 static Vector3 cylvec(float theta, float height)
77 {
78 return Vector3(sin(theta), height, cos(theta));
79 }
81 void goatgfx::gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
82 {
83 if(usub < 4) usub = 4;
84 if(vsub < 1) vsub = 1;
86 int uverts = usub + 1;
87 int vverts = vsub + 1;
89 int num_body_verts = uverts * vverts;
90 int num_body_quads = usub * vsub;
91 int num_body_tri = num_body_quads * 2;
93 int capvverts = capsub ? capsub + 1 : 0;
94 int num_cap_verts = uverts * capvverts;
95 int num_cap_quads = usub * capsub;
96 int num_cap_tri = num_cap_quads * 2;
98 int num_verts = num_body_verts + num_cap_verts * 2;
99 int num_tri = num_body_tri + num_cap_tri * 2;
101 mesh->clear();
102 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
103 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
104 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
105 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
106 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
108 float du = urange / (float)(uverts - 1);
109 float dv = vrange / (float)(vverts - 1);
111 float u = 0.0;
112 for(int i=0; i<uverts; i++) {
113 float theta = SURAD(u);
115 float v = 0.0;
116 for(int j=0; j<vverts; j++) {
117 float y = (v - 0.5) * height;
118 Vector3 pos = cylvec(theta, y);
120 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
121 *narr++ = Vector3(pos.x, 0.0, pos.z);
122 *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
123 *uvarr++ = Vector2(u * urange, v * vrange);
125 if(i < usub && j < vsub) {
126 int idx = i * vverts + j;
128 *idxarr++ = idx;
129 *idxarr++ = idx + vverts + 1;
130 *idxarr++ = idx + 1;
132 *idxarr++ = idx;
133 *idxarr++ = idx + vverts;
134 *idxarr++ = idx + vverts + 1;
135 }
137 v += dv;
138 }
139 u += du;
140 }
143 // now the cap!
144 if(!capsub) {
145 return;
146 }
148 dv = 1.0 / (float)(capvverts - 1);
150 u = 0.0;
151 for(int i=0; i<uverts; i++) {
152 float theta = SURAD(u);
154 float v = 0.0;
155 for(int j=0; j<capvverts; j++) {
156 float r = v * rad;
158 Vector3 pos = cylvec(theta, height / 2.0) * r;
159 pos.y = height / 2.0;
160 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
162 *varr++ = pos;
163 *narr++ = Vector3(0, 1, 0);
164 *tarr++ = tang;
165 *uvarr++ = Vector2(u * urange, v);
167 pos.y = -height / 2.0;
168 *varr++ = pos;
169 *narr++ = Vector3(0, -1, 0);
170 *tarr++ = -tang;
171 *uvarr++ = Vector2(u * urange, v);
173 if(i < usub && j < capsub) {
174 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
176 unsigned int vidx[4] = {
177 idx,
178 idx + capvverts * 2,
179 idx + (capvverts + 1) * 2,
180 idx + 2
181 };
183 *idxarr++ = vidx[0];
184 *idxarr++ = vidx[2];
185 *idxarr++ = vidx[1];
186 *idxarr++ = vidx[0];
187 *idxarr++ = vidx[3];
188 *idxarr++ = vidx[2];
190 *idxarr++ = vidx[0] + 1;
191 *idxarr++ = vidx[1] + 1;
192 *idxarr++ = vidx[2] + 1;
193 *idxarr++ = vidx[0] + 1;
194 *idxarr++ = vidx[2] + 1;
195 *idxarr++ = vidx[3] + 1;
196 }
198 v += dv;
199 }
200 u += du;
201 }
202 }
204 // -------- cone --------
206 static Vector3 conevec(float theta, float y, float height)
207 {
208 float scale = 1.0 - y / height;
209 return Vector3(sin(theta) * scale, y, cos(theta) * scale);
210 }
212 void goatgfx::gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
213 {
214 if(usub < 4) usub = 4;
215 if(vsub < 1) vsub = 1;
217 int uverts = usub + 1;
218 int vverts = vsub + 1;
220 int num_body_verts = uverts * vverts;
221 int num_body_quads = usub * vsub;
222 int num_body_tri = num_body_quads * 2;
224 int capvverts = capsub ? capsub + 1 : 0;
225 int num_cap_verts = uverts * capvverts;
226 int num_cap_quads = usub * capsub;
227 int num_cap_tri = num_cap_quads * 2;
229 int num_verts = num_body_verts + num_cap_verts;
230 int num_tri = num_body_tri + num_cap_tri;
232 mesh->clear();
233 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
234 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
235 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
236 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
237 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
239 float du = urange / (float)(uverts - 1);
240 float dv = vrange / (float)(vverts - 1);
242 float u = 0.0;
243 for(int i=0; i<uverts; i++) {
244 float theta = SURAD(u);
246 float v = 0.0;
247 for(int j=0; j<vverts; j++) {
248 float y = v * height;
249 Vector3 pos = conevec(theta, y, height);
251 Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized();
252 Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized();
254 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
255 *narr++ = cross_product(tang, bitang);
256 *tarr++ = tang;
257 *uvarr++ = Vector2(u * urange, v * vrange);
259 if(i < usub && j < vsub) {
260 int idx = i * vverts + j;
262 *idxarr++ = idx;
263 *idxarr++ = idx + vverts + 1;
264 *idxarr++ = idx + 1;
266 *idxarr++ = idx;
267 *idxarr++ = idx + vverts;
268 *idxarr++ = idx + vverts + 1;
269 }
271 v += dv;
272 }
273 u += du;
274 }
277 // now the bottom cap!
278 if(!capsub) {
279 return;
280 }
282 dv = 1.0 / (float)(capvverts - 1);
284 u = 0.0;
285 for(int i=0; i<uverts; i++) {
286 float theta = SURAD(u);
288 float v = 0.0;
289 for(int j=0; j<capvverts; j++) {
290 float r = v * rad;
292 Vector3 pos = conevec(theta, 0.0, height) * r;
293 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
295 *varr++ = pos;
296 *narr++ = Vector3(0, -1, 0);
297 *tarr++ = tang;
298 *uvarr++ = Vector2(u * urange, v);
300 if(i < usub && j < capsub) {
301 unsigned int idx = num_body_verts + i * capvverts + j;
303 unsigned int vidx[4] = {
304 idx,
305 idx + capvverts,
306 idx + (capvverts + 1),
307 idx + 1
308 };
310 *idxarr++ = vidx[0];
311 *idxarr++ = vidx[1];
312 *idxarr++ = vidx[2];
313 *idxarr++ = vidx[0];
314 *idxarr++ = vidx[2];
315 *idxarr++ = vidx[3];
316 }
318 v += dv;
319 }
320 u += du;
321 }
322 }
325 // -------- plane --------
327 void goatgfx::gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
328 {
329 if(usub < 1) usub = 1;
330 if(vsub < 1) vsub = 1;
332 mesh->clear();
334 int uverts = usub + 1;
335 int vverts = vsub + 1;
336 int num_verts = uverts * vverts;
338 int num_quads = usub * vsub;
339 int num_tri = num_quads * 2;
341 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
342 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
343 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
344 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
345 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
347 float du = 1.0 / (float)usub;
348 float dv = 1.0 / (float)vsub;
350 float u = 0.0;
351 for(int i=0; i<uverts; i++) {
352 float v = 0.0;
353 for(int j=0; j<vverts; j++) {
354 *varr++ = Vector3((u - 0.5) * width, (v - 0.5) * height, 0.0);
355 *narr++ = Vector3(0, 0, 1);
356 *tarr++ = Vector3(1, 0, 0);
357 *uvarr++ = Vector2(u, v);
359 if(i < usub && j < vsub) {
360 int idx = i * vverts + j;
362 *idxarr++ = idx;
363 *idxarr++ = idx + vverts + 1;
364 *idxarr++ = idx + 1;
366 *idxarr++ = idx;
367 *idxarr++ = idx + vverts;
368 *idxarr++ = idx + vverts + 1;
369 }
371 v += dv;
372 }
373 u += du;
374 }
375 }