rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include "meshgen.h"
|
nuclear@0
|
3 #include "mesh.h"
|
nuclear@0
|
4
|
nuclear@0
|
5 // -------- sphere --------
|
nuclear@0
|
6
|
nuclear@0
|
7 #define SURAD(u) ((u) * 2.0 * M_PI)
|
nuclear@0
|
8 #define SVRAD(v) ((v) * M_PI)
|
nuclear@0
|
9
|
nuclear@0
|
10 static Vec3 sphvec(float theta, float phi)
|
nuclear@0
|
11 {
|
nuclear@0
|
12 return Vec3(sin(theta) * sin(phi),
|
nuclear@0
|
13 cos(phi),
|
nuclear@0
|
14 cos(theta) * sin(phi));
|
nuclear@0
|
15 }
|
nuclear@0
|
16
|
nuclear@0
|
17 void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange)
|
nuclear@0
|
18 {
|
nuclear@0
|
19 if(usub < 4) usub = 4;
|
nuclear@0
|
20 if(vsub < 2) vsub = 2;
|
nuclear@0
|
21
|
nuclear@0
|
22 int uverts = usub + 1;
|
nuclear@0
|
23 int vverts = vsub + 1;
|
nuclear@0
|
24
|
nuclear@0
|
25 int num_verts = uverts * vverts;
|
nuclear@0
|
26 int num_quads = usub * vsub;
|
nuclear@0
|
27 int num_tri = num_quads * 2;
|
nuclear@0
|
28
|
nuclear@0
|
29 mesh->clear();
|
nuclear@0
|
30 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
31 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
32 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
33 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
34 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
35
|
nuclear@0
|
36 float du = urange / (float)(uverts - 1);
|
nuclear@0
|
37 float dv = vrange / (float)(vverts - 1);
|
nuclear@0
|
38
|
nuclear@0
|
39 float u = 0.0;
|
nuclear@0
|
40 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
41 float theta = u * 2.0 * M_PI;
|
nuclear@0
|
42
|
nuclear@0
|
43 float v = 0.0;
|
nuclear@0
|
44 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
45 float phi = v * M_PI;
|
nuclear@0
|
46
|
nuclear@0
|
47 Vec3 pos = sphvec(theta, phi);
|
nuclear@0
|
48
|
nuclear@0
|
49 *varr++ = pos * rad;
|
nuclear@0
|
50 *narr++ = pos;
|
nuclear@0
|
51 *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f));
|
nuclear@0
|
52 *uvarr++ = Vec2(u * urange, v * vrange);
|
nuclear@0
|
53
|
nuclear@0
|
54 if(i < usub && j < vsub) {
|
nuclear@0
|
55 int idx = i * vverts + j;
|
nuclear@0
|
56 *idxarr++ = idx;
|
nuclear@0
|
57 *idxarr++ = idx + 1;
|
nuclear@0
|
58 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
59
|
nuclear@0
|
60 *idxarr++ = idx;
|
nuclear@0
|
61 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
62 *idxarr++ = idx + vverts;
|
nuclear@0
|
63 }
|
nuclear@0
|
64
|
nuclear@0
|
65 v += dv;
|
nuclear@0
|
66 }
|
nuclear@0
|
67 u += du;
|
nuclear@0
|
68 }
|
nuclear@0
|
69 }
|
nuclear@0
|
70
|
nuclear@0
|
71 // ------ geosphere ------
|
nuclear@0
|
72 #define PHI 1.618034
|
nuclear@0
|
73
|
nuclear@0
|
74 static Vec3 icosa_pt[] = {
|
nuclear@0
|
75 Vec3(PHI, 1, 0),
|
nuclear@0
|
76 Vec3(-PHI, 1, 0),
|
nuclear@0
|
77 Vec3(PHI, -1, 0),
|
nuclear@0
|
78 Vec3(-PHI, -1, 0),
|
nuclear@0
|
79 Vec3(1, 0, PHI),
|
nuclear@0
|
80 Vec3(1, 0, -PHI),
|
nuclear@0
|
81 Vec3(-1, 0, PHI),
|
nuclear@0
|
82 Vec3(-1, 0, -PHI),
|
nuclear@0
|
83 Vec3(0, PHI, 1),
|
nuclear@0
|
84 Vec3(0, -PHI, 1),
|
nuclear@0
|
85 Vec3(0, PHI, -1),
|
nuclear@0
|
86 Vec3(0, -PHI, -1)
|
nuclear@0
|
87 };
|
nuclear@0
|
88 enum { P11, P12, P13, P14, P21, P22, P23, P24, P31, P32, P33, P34 };
|
nuclear@0
|
89 static int icosa_idx[] = {
|
nuclear@0
|
90 P11, P31, P21,
|
nuclear@0
|
91 P11, P22, P33,
|
nuclear@0
|
92 P13, P21, P32,
|
nuclear@0
|
93 P13, P34, P22,
|
nuclear@0
|
94 P12, P23, P31,
|
nuclear@0
|
95 P12, P33, P24,
|
nuclear@0
|
96 P14, P32, P23,
|
nuclear@0
|
97 P14, P24, P34,
|
nuclear@0
|
98
|
nuclear@0
|
99 P11, P33, P31,
|
nuclear@0
|
100 P12, P31, P33,
|
nuclear@0
|
101 P13, P32, P34,
|
nuclear@0
|
102 P14, P34, P32,
|
nuclear@0
|
103
|
nuclear@0
|
104 P21, P13, P11,
|
nuclear@0
|
105 P22, P11, P13,
|
nuclear@0
|
106 P23, P12, P14,
|
nuclear@0
|
107 P24, P14, P12,
|
nuclear@0
|
108
|
nuclear@0
|
109 P31, P23, P21,
|
nuclear@0
|
110 P32, P21, P23,
|
nuclear@0
|
111 P33, P22, P24,
|
nuclear@0
|
112 P34, P24, P22
|
nuclear@0
|
113 };
|
nuclear@0
|
114
|
nuclear@0
|
115 static void geosphere(std::vector<Vec3> *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter)
|
nuclear@0
|
116 {
|
nuclear@0
|
117 if(!iter) {
|
nuclear@0
|
118 verts->push_back(v1);
|
nuclear@0
|
119 verts->push_back(v2);
|
nuclear@0
|
120 verts->push_back(v3);
|
nuclear@0
|
121 return;
|
nuclear@0
|
122 }
|
nuclear@0
|
123
|
nuclear@0
|
124 Vec3 v12 = normalize(v1 + v2);
|
nuclear@0
|
125 Vec3 v23 = normalize(v2 + v3);
|
nuclear@0
|
126 Vec3 v31 = normalize(v3 + v1);
|
nuclear@0
|
127
|
nuclear@0
|
128 geosphere(verts, v1, v12, v31, iter - 1);
|
nuclear@0
|
129 geosphere(verts, v2, v23, v12, iter - 1);
|
nuclear@0
|
130 geosphere(verts, v3, v31, v23, iter - 1);
|
nuclear@0
|
131 geosphere(verts, v12, v23, v31, iter - 1);
|
nuclear@0
|
132 }
|
nuclear@0
|
133
|
nuclear@0
|
134 void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi)
|
nuclear@0
|
135 {
|
nuclear@0
|
136 int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3;
|
nuclear@0
|
137
|
nuclear@0
|
138 std::vector<Vec3> verts;
|
nuclear@0
|
139 for(int i=0; i<num_tri; i++) {
|
nuclear@0
|
140 Vec3 v[3];
|
nuclear@0
|
141
|
nuclear@0
|
142 for(int j=0; j<3; j++) {
|
nuclear@0
|
143 int vidx = icosa_idx[i * 3 + j];
|
nuclear@0
|
144 v[j] = normalize(icosa_pt[vidx]);
|
nuclear@0
|
145 }
|
nuclear@0
|
146
|
nuclear@0
|
147 if(hemi && (v[0].y < 0.0 || v[1].y < 0.0 || v[2].y < 0.0)) {
|
nuclear@0
|
148 continue;
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 geosphere(&verts, v[0], v[1], v[2], subdiv);
|
nuclear@0
|
152 }
|
nuclear@0
|
153
|
nuclear@0
|
154 int num_verts = (int)verts.size();
|
nuclear@0
|
155
|
nuclear@0
|
156 mesh->clear();
|
nuclear@0
|
157 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
158 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
159 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
160 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
161
|
nuclear@0
|
162 for(int i=0; i<num_verts; i++) {
|
nuclear@0
|
163 *varr++ = verts[i] * rad;
|
nuclear@0
|
164 *narr++ = verts[i];
|
nuclear@0
|
165
|
nuclear@0
|
166 float theta = atan2(verts[i].z, verts[i].x);
|
nuclear@0
|
167 float phi = acos(verts[i].y);
|
nuclear@0
|
168
|
nuclear@0
|
169 *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f));
|
nuclear@0
|
170
|
nuclear@0
|
171 float u = 0.5 * theta / M_PI + 0.5;
|
nuclear@0
|
172 float v = phi / M_PI;
|
nuclear@0
|
173 *uvarr++ = Vec2(u, v);
|
nuclear@0
|
174 }
|
nuclear@0
|
175 }
|
nuclear@0
|
176
|
nuclear@0
|
177 // -------- torus -----------
|
nuclear@0
|
178 static Vec3 torusvec(float theta, float phi, float mr, float rr)
|
nuclear@0
|
179 {
|
nuclear@0
|
180 theta = -theta;
|
nuclear@0
|
181
|
nuclear@0
|
182 float rx = -cos(phi) * rr + mr;
|
nuclear@0
|
183 float ry = sin(phi) * rr;
|
nuclear@0
|
184 float rz = 0.0;
|
nuclear@0
|
185
|
nuclear@0
|
186 float x = rx * sin(theta) + rz * cos(theta);
|
nuclear@0
|
187 float y = ry;
|
nuclear@0
|
188 float z = -rx * cos(theta) + rz * sin(theta);
|
nuclear@0
|
189
|
nuclear@0
|
190 return Vec3(x, y, z);
|
nuclear@0
|
191 }
|
nuclear@0
|
192
|
nuclear@0
|
193 void gen_torus(Mesh *mesh, float mainrad, float ringrad, int usub, int vsub, float urange, float vrange)
|
nuclear@0
|
194 {
|
nuclear@0
|
195 if(usub < 4) usub = 4;
|
nuclear@0
|
196 if(vsub < 2) vsub = 2;
|
nuclear@0
|
197
|
nuclear@0
|
198 int uverts = usub + 1;
|
nuclear@0
|
199 int vverts = vsub + 1;
|
nuclear@0
|
200
|
nuclear@0
|
201 int num_verts = uverts * vverts;
|
nuclear@0
|
202 int num_quads = usub * vsub;
|
nuclear@0
|
203 int num_tri = num_quads * 2;
|
nuclear@0
|
204
|
nuclear@0
|
205 mesh->clear();
|
nuclear@0
|
206 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
207 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
208 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
209 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
210 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
211
|
nuclear@0
|
212 float du = urange / (float)(uverts - 1);
|
nuclear@0
|
213 float dv = vrange / (float)(vverts - 1);
|
nuclear@0
|
214
|
nuclear@0
|
215 float u = 0.0;
|
nuclear@0
|
216 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
217 float theta = u * 2.0 * M_PI;
|
nuclear@0
|
218
|
nuclear@0
|
219 float v = 0.0;
|
nuclear@0
|
220 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
221 float phi = v * 2.0 * M_PI;
|
nuclear@0
|
222
|
nuclear@0
|
223 Vec3 pos = torusvec(theta, phi, mainrad, ringrad);
|
nuclear@0
|
224 Vec3 cent = torusvec(theta, phi, mainrad, 0.0);
|
nuclear@0
|
225
|
nuclear@0
|
226 *varr++ = pos;
|
nuclear@0
|
227 *narr++ = (pos - cent) / ringrad;
|
nuclear@0
|
228
|
nuclear@0
|
229 Vec3 pprev = torusvec(theta - 0.1f, phi, mainrad, ringrad);
|
nuclear@0
|
230 Vec3 pnext = torusvec(theta + 0.1f, phi, mainrad, ringrad);
|
nuclear@0
|
231
|
nuclear@0
|
232 *tarr++ = normalize(pnext - pprev);
|
nuclear@0
|
233 *uvarr++ = Vec2(u * urange, v * vrange);
|
nuclear@0
|
234
|
nuclear@0
|
235 if(i < usub && j < vsub) {
|
nuclear@0
|
236 int idx = i * vverts + j;
|
nuclear@0
|
237 *idxarr++ = idx;
|
nuclear@0
|
238 *idxarr++ = idx + 1;
|
nuclear@0
|
239 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
240
|
nuclear@0
|
241 *idxarr++ = idx;
|
nuclear@0
|
242 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
243 *idxarr++ = idx + vverts;
|
nuclear@0
|
244 }
|
nuclear@0
|
245
|
nuclear@0
|
246 v += dv;
|
nuclear@0
|
247 }
|
nuclear@0
|
248 u += du;
|
nuclear@0
|
249 }
|
nuclear@0
|
250 }
|
nuclear@0
|
251
|
nuclear@0
|
252
|
nuclear@0
|
253 // -------- cylinder --------
|
nuclear@0
|
254
|
nuclear@0
|
255 static Vec3 cylvec(float theta, float height)
|
nuclear@0
|
256 {
|
nuclear@0
|
257 return Vec3(sin(theta), height, cos(theta));
|
nuclear@0
|
258 }
|
nuclear@0
|
259
|
nuclear@0
|
260 void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
|
nuclear@0
|
261 {
|
nuclear@0
|
262 if(usub < 4) usub = 4;
|
nuclear@0
|
263 if(vsub < 1) vsub = 1;
|
nuclear@0
|
264
|
nuclear@0
|
265 int uverts = usub + 1;
|
nuclear@0
|
266 int vverts = vsub + 1;
|
nuclear@0
|
267
|
nuclear@0
|
268 int num_body_verts = uverts * vverts;
|
nuclear@0
|
269 int num_body_quads = usub * vsub;
|
nuclear@0
|
270 int num_body_tri = num_body_quads * 2;
|
nuclear@0
|
271
|
nuclear@0
|
272 int capvverts = capsub ? capsub + 1 : 0;
|
nuclear@0
|
273 int num_cap_verts = uverts * capvverts;
|
nuclear@0
|
274 int num_cap_quads = usub * capsub;
|
nuclear@0
|
275 int num_cap_tri = num_cap_quads * 2;
|
nuclear@0
|
276
|
nuclear@0
|
277 int num_verts = num_body_verts + num_cap_verts * 2;
|
nuclear@0
|
278 int num_tri = num_body_tri + num_cap_tri * 2;
|
nuclear@0
|
279
|
nuclear@0
|
280 mesh->clear();
|
nuclear@0
|
281 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
282 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
283 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
284 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
285 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
286
|
nuclear@0
|
287 float du = urange / (float)(uverts - 1);
|
nuclear@0
|
288 float dv = vrange / (float)(vverts - 1);
|
nuclear@0
|
289
|
nuclear@0
|
290 float u = 0.0;
|
nuclear@0
|
291 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
292 float theta = SURAD(u);
|
nuclear@0
|
293
|
nuclear@0
|
294 float v = 0.0;
|
nuclear@0
|
295 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
296 float y = (v - 0.5) * height;
|
nuclear@0
|
297 Vec3 pos = cylvec(theta, y);
|
nuclear@0
|
298
|
nuclear@0
|
299 *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad);
|
nuclear@0
|
300 *narr++ = Vec3(pos.x, 0.0, pos.z);
|
nuclear@0
|
301 *tarr++ = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
|
nuclear@0
|
302 *uvarr++ = Vec2(u * urange, v * vrange);
|
nuclear@0
|
303
|
nuclear@0
|
304 if(i < usub && j < vsub) {
|
nuclear@0
|
305 int idx = i * vverts + j;
|
nuclear@0
|
306
|
nuclear@0
|
307 *idxarr++ = idx;
|
nuclear@0
|
308 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
309 *idxarr++ = idx + 1;
|
nuclear@0
|
310
|
nuclear@0
|
311 *idxarr++ = idx;
|
nuclear@0
|
312 *idxarr++ = idx + vverts;
|
nuclear@0
|
313 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
314 }
|
nuclear@0
|
315
|
nuclear@0
|
316 v += dv;
|
nuclear@0
|
317 }
|
nuclear@0
|
318 u += du;
|
nuclear@0
|
319 }
|
nuclear@0
|
320
|
nuclear@0
|
321
|
nuclear@0
|
322 // now the cap!
|
nuclear@0
|
323 if(!capsub) {
|
nuclear@0
|
324 return;
|
nuclear@0
|
325 }
|
nuclear@0
|
326
|
nuclear@0
|
327 dv = 1.0 / (float)(capvverts - 1);
|
nuclear@0
|
328
|
nuclear@0
|
329 u = 0.0;
|
nuclear@0
|
330 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
331 float theta = SURAD(u);
|
nuclear@0
|
332
|
nuclear@0
|
333 float v = 0.0;
|
nuclear@0
|
334 for(int j=0; j<capvverts; j++) {
|
nuclear@0
|
335 float r = v * rad;
|
nuclear@0
|
336
|
nuclear@0
|
337 Vec3 pos = cylvec(theta, height / 2.0) * r;
|
nuclear@0
|
338 pos.y = height / 2.0;
|
nuclear@0
|
339 Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
|
nuclear@0
|
340
|
nuclear@0
|
341 *varr++ = pos;
|
nuclear@0
|
342 *narr++ = Vec3(0, 1, 0);
|
nuclear@0
|
343 *tarr++ = tang;
|
nuclear@0
|
344 *uvarr++ = Vec2(u * urange, v);
|
nuclear@0
|
345
|
nuclear@0
|
346 pos.y = -height / 2.0;
|
nuclear@0
|
347 *varr++ = pos;
|
nuclear@0
|
348 *narr++ = Vec3(0, -1, 0);
|
nuclear@0
|
349 *tarr++ = -tang;
|
nuclear@0
|
350 *uvarr++ = Vec2(u * urange, v);
|
nuclear@0
|
351
|
nuclear@0
|
352 if(i < usub && j < capsub) {
|
nuclear@0
|
353 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
|
nuclear@0
|
354
|
nuclear@0
|
355 unsigned int vidx[4] = {
|
nuclear@0
|
356 idx,
|
nuclear@0
|
357 idx + capvverts * 2,
|
nuclear@0
|
358 idx + (capvverts + 1) * 2,
|
nuclear@0
|
359 idx + 2
|
nuclear@0
|
360 };
|
nuclear@0
|
361
|
nuclear@0
|
362 *idxarr++ = vidx[0];
|
nuclear@0
|
363 *idxarr++ = vidx[2];
|
nuclear@0
|
364 *idxarr++ = vidx[1];
|
nuclear@0
|
365 *idxarr++ = vidx[0];
|
nuclear@0
|
366 *idxarr++ = vidx[3];
|
nuclear@0
|
367 *idxarr++ = vidx[2];
|
nuclear@0
|
368
|
nuclear@0
|
369 *idxarr++ = vidx[0] + 1;
|
nuclear@0
|
370 *idxarr++ = vidx[1] + 1;
|
nuclear@0
|
371 *idxarr++ = vidx[2] + 1;
|
nuclear@0
|
372 *idxarr++ = vidx[0] + 1;
|
nuclear@0
|
373 *idxarr++ = vidx[2] + 1;
|
nuclear@0
|
374 *idxarr++ = vidx[3] + 1;
|
nuclear@0
|
375 }
|
nuclear@0
|
376
|
nuclear@0
|
377 v += dv;
|
nuclear@0
|
378 }
|
nuclear@0
|
379 u += du;
|
nuclear@0
|
380 }
|
nuclear@0
|
381 }
|
nuclear@0
|
382
|
nuclear@0
|
383 // -------- cone --------
|
nuclear@0
|
384
|
nuclear@0
|
385 static Vec3 conevec(float theta, float y, float height)
|
nuclear@0
|
386 {
|
nuclear@0
|
387 float scale = 1.0 - y / height;
|
nuclear@0
|
388 return Vec3(sin(theta) * scale, y, cos(theta) * scale);
|
nuclear@0
|
389 }
|
nuclear@0
|
390
|
nuclear@0
|
391 void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
|
nuclear@0
|
392 {
|
nuclear@0
|
393 if(usub < 4) usub = 4;
|
nuclear@0
|
394 if(vsub < 1) vsub = 1;
|
nuclear@0
|
395
|
nuclear@0
|
396 int uverts = usub + 1;
|
nuclear@0
|
397 int vverts = vsub + 1;
|
nuclear@0
|
398
|
nuclear@0
|
399 int num_body_verts = uverts * vverts;
|
nuclear@0
|
400 int num_body_quads = usub * vsub;
|
nuclear@0
|
401 int num_body_tri = num_body_quads * 2;
|
nuclear@0
|
402
|
nuclear@0
|
403 int capvverts = capsub ? capsub + 1 : 0;
|
nuclear@0
|
404 int num_cap_verts = uverts * capvverts;
|
nuclear@0
|
405 int num_cap_quads = usub * capsub;
|
nuclear@0
|
406 int num_cap_tri = num_cap_quads * 2;
|
nuclear@0
|
407
|
nuclear@0
|
408 int num_verts = num_body_verts + num_cap_verts;
|
nuclear@0
|
409 int num_tri = num_body_tri + num_cap_tri;
|
nuclear@0
|
410
|
nuclear@0
|
411 mesh->clear();
|
nuclear@0
|
412 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
413 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
414 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
415 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
416 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
417
|
nuclear@0
|
418 float du = urange / (float)(uverts - 1);
|
nuclear@0
|
419 float dv = vrange / (float)(vverts - 1);
|
nuclear@0
|
420
|
nuclear@0
|
421 float u = 0.0;
|
nuclear@0
|
422 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
423 float theta = SURAD(u);
|
nuclear@0
|
424
|
nuclear@0
|
425 float v = 0.0;
|
nuclear@0
|
426 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
427 float y = v * height;
|
nuclear@0
|
428 Vec3 pos = conevec(theta, y, height);
|
nuclear@0
|
429
|
nuclear@0
|
430 Vec3 tang = normalize(conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height));
|
nuclear@0
|
431 Vec3 bitang = normalize(conevec(theta, y + 0.1, height) - pos);
|
nuclear@0
|
432
|
nuclear@0
|
433 *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad);
|
nuclear@0
|
434 *narr++ = cross(tang, bitang);
|
nuclear@0
|
435 *tarr++ = tang;
|
nuclear@0
|
436 *uvarr++ = Vec2(u * urange, v * vrange);
|
nuclear@0
|
437
|
nuclear@0
|
438 if(i < usub && j < vsub) {
|
nuclear@0
|
439 int idx = i * vverts + j;
|
nuclear@0
|
440
|
nuclear@0
|
441 *idxarr++ = idx;
|
nuclear@0
|
442 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
443 *idxarr++ = idx + 1;
|
nuclear@0
|
444
|
nuclear@0
|
445 *idxarr++ = idx;
|
nuclear@0
|
446 *idxarr++ = idx + vverts;
|
nuclear@0
|
447 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
448 }
|
nuclear@0
|
449
|
nuclear@0
|
450 v += dv;
|
nuclear@0
|
451 }
|
nuclear@0
|
452 u += du;
|
nuclear@0
|
453 }
|
nuclear@0
|
454
|
nuclear@0
|
455
|
nuclear@0
|
456 // now the bottom cap!
|
nuclear@0
|
457 if(!capsub) {
|
nuclear@0
|
458 return;
|
nuclear@0
|
459 }
|
nuclear@0
|
460
|
nuclear@0
|
461 dv = 1.0 / (float)(capvverts - 1);
|
nuclear@0
|
462
|
nuclear@0
|
463 u = 0.0;
|
nuclear@0
|
464 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
465 float theta = SURAD(u);
|
nuclear@0
|
466
|
nuclear@0
|
467 float v = 0.0;
|
nuclear@0
|
468 for(int j=0; j<capvverts; j++) {
|
nuclear@0
|
469 float r = v * rad;
|
nuclear@0
|
470
|
nuclear@0
|
471 Vec3 pos = conevec(theta, 0.0, height) * r;
|
nuclear@0
|
472 Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
|
nuclear@0
|
473
|
nuclear@0
|
474 *varr++ = pos;
|
nuclear@0
|
475 *narr++ = Vec3(0, -1, 0);
|
nuclear@0
|
476 *tarr++ = tang;
|
nuclear@0
|
477 *uvarr++ = Vec2(u * urange, v);
|
nuclear@0
|
478
|
nuclear@0
|
479 if(i < usub && j < capsub) {
|
nuclear@0
|
480 unsigned int idx = num_body_verts + i * capvverts + j;
|
nuclear@0
|
481
|
nuclear@0
|
482 unsigned int vidx[4] = {
|
nuclear@0
|
483 idx,
|
nuclear@0
|
484 idx + capvverts,
|
nuclear@0
|
485 idx + (capvverts + 1),
|
nuclear@0
|
486 idx + 1
|
nuclear@0
|
487 };
|
nuclear@0
|
488
|
nuclear@0
|
489 *idxarr++ = vidx[0];
|
nuclear@0
|
490 *idxarr++ = vidx[1];
|
nuclear@0
|
491 *idxarr++ = vidx[2];
|
nuclear@0
|
492 *idxarr++ = vidx[0];
|
nuclear@0
|
493 *idxarr++ = vidx[2];
|
nuclear@0
|
494 *idxarr++ = vidx[3];
|
nuclear@0
|
495 }
|
nuclear@0
|
496
|
nuclear@0
|
497 v += dv;
|
nuclear@0
|
498 }
|
nuclear@0
|
499 u += du;
|
nuclear@0
|
500 }
|
nuclear@0
|
501 }
|
nuclear@0
|
502
|
nuclear@0
|
503
|
nuclear@0
|
504 // -------- plane --------
|
nuclear@0
|
505
|
nuclear@0
|
506 void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
|
nuclear@0
|
507 {
|
nuclear@0
|
508 gen_heightmap(mesh, width, height, usub, vsub, 0);
|
nuclear@0
|
509 }
|
nuclear@0
|
510
|
nuclear@0
|
511
|
nuclear@0
|
512 // ----- heightmap ------
|
nuclear@0
|
513
|
nuclear@0
|
514 void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
|
nuclear@0
|
515 {
|
nuclear@0
|
516 if(usub < 1) usub = 1;
|
nuclear@0
|
517 if(vsub < 1) vsub = 1;
|
nuclear@0
|
518
|
nuclear@0
|
519 mesh->clear();
|
nuclear@0
|
520
|
nuclear@0
|
521 int uverts = usub + 1;
|
nuclear@0
|
522 int vverts = vsub + 1;
|
nuclear@0
|
523 int num_verts = uverts * vverts;
|
nuclear@0
|
524
|
nuclear@0
|
525 int num_quads = usub * vsub;
|
nuclear@0
|
526 int num_tri = num_quads * 2;
|
nuclear@0
|
527
|
nuclear@0
|
528 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
529 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
530 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
531 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
532 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
533
|
nuclear@0
|
534 float du = 1.0 / (float)usub;
|
nuclear@0
|
535 float dv = 1.0 / (float)vsub;
|
nuclear@0
|
536
|
nuclear@0
|
537 float u = 0.0;
|
nuclear@0
|
538 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
539 float v = 0.0;
|
nuclear@0
|
540 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
541 float x = (u - 0.5) * width;
|
nuclear@0
|
542 float y = (v - 0.5) * height;
|
nuclear@0
|
543 float z = hf ? hf(u, v, hfdata) : 0.0;
|
nuclear@0
|
544
|
nuclear@0
|
545 Vec3 normal = Vec3(0, 0, 1);
|
nuclear@0
|
546 if(hf) {
|
nuclear@0
|
547 float u1z = hf(u + du, v, hfdata);
|
nuclear@0
|
548 float v1z = hf(u, v + dv, hfdata);
|
nuclear@0
|
549
|
nuclear@0
|
550 Vec3 tang = Vec3(du * width, 0, u1z - z);
|
nuclear@0
|
551 Vec3 bitan = Vec3(0, dv * height, v1z - z);
|
nuclear@0
|
552 normal = normalize(cross(tang, bitan));
|
nuclear@0
|
553 }
|
nuclear@0
|
554
|
nuclear@0
|
555 *varr++ = Vec3(x, y, z);
|
nuclear@0
|
556 *narr++ = normal;
|
nuclear@0
|
557 *tarr++ = Vec3(1, 0, 0);
|
nuclear@0
|
558 *uvarr++ = Vec2(u, v);
|
nuclear@0
|
559
|
nuclear@0
|
560 if(i < usub && j < vsub) {
|
nuclear@0
|
561 int idx = i * vverts + j;
|
nuclear@0
|
562
|
nuclear@0
|
563 *idxarr++ = idx;
|
nuclear@0
|
564 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
565 *idxarr++ = idx + 1;
|
nuclear@0
|
566
|
nuclear@0
|
567 *idxarr++ = idx;
|
nuclear@0
|
568 *idxarr++ = idx + vverts;
|
nuclear@0
|
569 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
570 }
|
nuclear@0
|
571
|
nuclear@0
|
572 v += dv;
|
nuclear@0
|
573 }
|
nuclear@0
|
574 u += du;
|
nuclear@0
|
575 }
|
nuclear@0
|
576 }
|
nuclear@0
|
577
|
nuclear@0
|
578 // ----- box ------
|
nuclear@0
|
579 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub)
|
nuclear@0
|
580 {
|
nuclear@0
|
581 static const float face_angles[][2] = {
|
nuclear@0
|
582 {0, 0},
|
nuclear@0
|
583 {M_PI / 2.0, 0},
|
nuclear@0
|
584 {M_PI, 0},
|
nuclear@0
|
585 {3.0 * M_PI / 2.0, 0},
|
nuclear@0
|
586 {0, M_PI / 2.0},
|
nuclear@0
|
587 {0, -M_PI / 2.0}
|
nuclear@0
|
588 };
|
nuclear@0
|
589
|
nuclear@0
|
590 if(usub < 1) usub = 1;
|
nuclear@0
|
591 if(vsub < 1) vsub = 1;
|
nuclear@0
|
592
|
nuclear@0
|
593 mesh->clear();
|
nuclear@0
|
594
|
nuclear@0
|
595 for(int i=0; i<6; i++) {
|
nuclear@0
|
596 Mat4 xform, dir_xform;
|
nuclear@0
|
597 Mesh m;
|
nuclear@0
|
598
|
nuclear@0
|
599 gen_plane(&m, 1, 1, usub, vsub);
|
nuclear@0
|
600 xform.rotate(Vec3(face_angles[i][1], face_angles[i][0], 0));
|
nuclear@0
|
601 dir_xform = xform;
|
nuclear@0
|
602 xform.translate(Vec3(0, 0, 0.5));
|
nuclear@0
|
603 m.apply_xform(xform, dir_xform);
|
nuclear@0
|
604
|
nuclear@0
|
605 mesh->append(m);
|
nuclear@0
|
606 }
|
nuclear@0
|
607
|
nuclear@0
|
608 Mat4 scale;
|
nuclear@0
|
609 scale.scaling(xsz, ysz, zsz);
|
nuclear@0
|
610 mesh->apply_xform(scale, Mat4::identity);
|
nuclear@0
|
611 }
|
nuclear@0
|
612
|
nuclear@0
|
613 /*
|
nuclear@0
|
614 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
|
nuclear@0
|
615 {
|
nuclear@0
|
616 mesh->clear();
|
nuclear@0
|
617
|
nuclear@0
|
618 const int num_faces = 6;
|
nuclear@0
|
619 int num_verts = num_faces * 4;
|
nuclear@0
|
620 int num_tri = num_faces * 2;
|
nuclear@0
|
621
|
nuclear@0
|
622 float x = xsz / 2.0;
|
nuclear@0
|
623 float y = ysz / 2.0;
|
nuclear@0
|
624 float z = zsz / 2.0;
|
nuclear@0
|
625
|
nuclear@0
|
626 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
627 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
628 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
629 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
630 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
631
|
nuclear@0
|
632 static const Vec2 uv[] = { Vec2(0, 0), Vec2(1, 0), Vec2(1, 1), Vec2(0, 1) };
|
nuclear@0
|
633
|
nuclear@0
|
634 // front
|
nuclear@0
|
635 for(int i=0; i<4; i++) {
|
nuclear@0
|
636 *narr++ = Vec3(0, 0, 1);
|
nuclear@0
|
637 *tarr++ = Vec3(1, 0, 0);
|
nuclear@0
|
638 *uvarr++ = uv[i];
|
nuclear@0
|
639 }
|
nuclear@0
|
640 *varr++ = Vec3(-x, -y, z);
|
nuclear@0
|
641 *varr++ = Vec3(x, -y, z);
|
nuclear@0
|
642 *varr++ = Vec3(x, y, z);
|
nuclear@0
|
643 *varr++ = Vec3(-x, y, z);
|
nuclear@0
|
644 // right
|
nuclear@0
|
645 for(int i=0; i<4; i++) {
|
nuclear@0
|
646 *narr++ = Vec3(1, 0, 0);
|
nuclear@0
|
647 *tarr++ = Vec3(0, 0, -1);
|
nuclear@0
|
648 *uvarr++ = uv[i];
|
nuclear@0
|
649 }
|
nuclear@0
|
650 *varr++ = Vec3(x, -y, z);
|
nuclear@0
|
651 *varr++ = Vec3(x, -y, -z);
|
nuclear@0
|
652 *varr++ = Vec3(x, y, -z);
|
nuclear@0
|
653 *varr++ = Vec3(x, y, z);
|
nuclear@0
|
654 // back
|
nuclear@0
|
655 for(int i=0; i<4; i++) {
|
nuclear@0
|
656 *narr++ = Vec3(0, 0, -1);
|
nuclear@0
|
657 *tarr++ = Vec3(-1, 0, 0);
|
nuclear@0
|
658 *uvarr++ = uv[i];
|
nuclear@0
|
659 }
|
nuclear@0
|
660 *varr++ = Vec3(x, -y, -z);
|
nuclear@0
|
661 *varr++ = Vec3(-x, -y, -z);
|
nuclear@0
|
662 *varr++ = Vec3(-x, y, -z);
|
nuclear@0
|
663 *varr++ = Vec3(x, y, -z);
|
nuclear@0
|
664 // left
|
nuclear@0
|
665 for(int i=0; i<4; i++) {
|
nuclear@0
|
666 *narr++ = Vec3(-1, 0, 0);
|
nuclear@0
|
667 *tarr++ = Vec3(0, 0, 1);
|
nuclear@0
|
668 *uvarr++ = uv[i];
|
nuclear@0
|
669 }
|
nuclear@0
|
670 *varr++ = Vec3(-x, -y, -z);
|
nuclear@0
|
671 *varr++ = Vec3(-x, -y, z);
|
nuclear@0
|
672 *varr++ = Vec3(-x, y, z);
|
nuclear@0
|
673 *varr++ = Vec3(-x, y, -z);
|
nuclear@0
|
674 // top
|
nuclear@0
|
675 for(int i=0; i<4; i++) {
|
nuclear@0
|
676 *narr++ = Vec3(0, 1, 0);
|
nuclear@0
|
677 *tarr++ = Vec3(1, 0, 0);
|
nuclear@0
|
678 *uvarr++ = uv[i];
|
nuclear@0
|
679 }
|
nuclear@0
|
680 *varr++ = Vec3(-x, y, z);
|
nuclear@0
|
681 *varr++ = Vec3(x, y, z);
|
nuclear@0
|
682 *varr++ = Vec3(x, y, -z);
|
nuclear@0
|
683 *varr++ = Vec3(-x, y, -z);
|
nuclear@0
|
684 // bottom
|
nuclear@0
|
685 for(int i=0; i<4; i++) {
|
nuclear@0
|
686 *narr++ = Vec3(0, -1, 0);
|
nuclear@0
|
687 *tarr++ = Vec3(1, 0, 0);
|
nuclear@0
|
688 *uvarr++ = uv[i];
|
nuclear@0
|
689 }
|
nuclear@0
|
690 *varr++ = Vec3(-x, -y, -z);
|
nuclear@0
|
691 *varr++ = Vec3(x, -y, -z);
|
nuclear@0
|
692 *varr++ = Vec3(x, -y, z);
|
nuclear@0
|
693 *varr++ = Vec3(-x, -y, z);
|
nuclear@0
|
694
|
nuclear@0
|
695 // index array
|
nuclear@0
|
696 static const int faceidx[] = {0, 1, 2, 0, 2, 3};
|
nuclear@0
|
697 for(int i=0; i<num_faces; i++) {
|
nuclear@0
|
698 for(int j=0; j<6; j++) {
|
nuclear@0
|
699 *idxarr++ = faceidx[j] + i * 4;
|
nuclear@0
|
700 }
|
nuclear@0
|
701 }
|
nuclear@0
|
702 }
|
nuclear@0
|
703 */
|
nuclear@0
|
704
|
nuclear@0
|
705 static inline Vec3 rev_vert(float u, float v, Vec2 (*rf)(float, float, void*), void *cls)
|
nuclear@0
|
706 {
|
nuclear@0
|
707 Vec2 pos = rf(u, v, cls);
|
nuclear@0
|
708
|
nuclear@0
|
709 float angle = u * 2.0 * M_PI;
|
nuclear@0
|
710 float x = pos.x * cos(angle);
|
nuclear@0
|
711 float y = pos.y;
|
nuclear@0
|
712 float z = pos.x * sin(angle);
|
nuclear@0
|
713
|
nuclear@0
|
714 return Vec3(x, y, z);
|
nuclear@0
|
715 }
|
nuclear@0
|
716
|
nuclear@0
|
717 // ------ surface of revolution -------
|
nuclear@0
|
718 void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*), void *cls)
|
nuclear@0
|
719 {
|
nuclear@0
|
720 gen_revol(mesh, usub, vsub, rfunc, 0, cls);
|
nuclear@0
|
721 }
|
nuclear@0
|
722
|
nuclear@0
|
723 void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*),
|
nuclear@0
|
724 Vec2 (*nfunc)(float, float, void*), void *cls)
|
nuclear@0
|
725 {
|
nuclear@0
|
726 if(!rfunc) return;
|
nuclear@0
|
727 if(usub < 3) usub = 3;
|
nuclear@0
|
728 if(vsub < 1) vsub = 1;
|
nuclear@0
|
729
|
nuclear@0
|
730 mesh->clear();
|
nuclear@0
|
731
|
nuclear@0
|
732 int uverts = usub + 1;
|
nuclear@0
|
733 int vverts = vsub + 1;
|
nuclear@0
|
734 int num_verts = uverts * vverts;
|
nuclear@0
|
735
|
nuclear@0
|
736 int num_quads = usub * vsub;
|
nuclear@0
|
737 int num_tri = num_quads * 2;
|
nuclear@0
|
738
|
nuclear@0
|
739 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
740 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
741 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
742 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
743 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
744
|
nuclear@0
|
745 float du = 1.0 / (float)(uverts - 1);
|
nuclear@0
|
746 float dv = 1.0 / (float)(vverts - 1);
|
nuclear@0
|
747
|
nuclear@0
|
748 float u = 0.0;
|
nuclear@0
|
749 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
750 float v = 0.0;
|
nuclear@0
|
751 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
752 Vec3 pos = rev_vert(u, v, rfunc, cls);
|
nuclear@0
|
753
|
nuclear@0
|
754 Vec3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls);
|
nuclear@0
|
755 Vec3 tang = nextu - pos;
|
nuclear@0
|
756 if(length_sq(tang) < 1e-6) {
|
nuclear@0
|
757 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
|
nuclear@0
|
758 nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls);
|
nuclear@0
|
759 tang = nextu - pos;
|
nuclear@0
|
760 }
|
nuclear@0
|
761
|
nuclear@0
|
762 Vec3 normal;
|
nuclear@0
|
763 if(nfunc) {
|
nuclear@0
|
764 normal = rev_vert(u, v, nfunc, cls);
|
nuclear@0
|
765 } else {
|
nuclear@0
|
766 Vec3 nextv = rev_vert(u, v + dv, rfunc, cls);
|
nuclear@0
|
767 Vec3 bitan = nextv - pos;
|
nuclear@0
|
768 if(length_sq(bitan) < 1e-6) {
|
nuclear@0
|
769 nextv = rev_vert(u, v - dv, rfunc, cls);
|
nuclear@0
|
770 bitan = pos - nextv;
|
nuclear@0
|
771 }
|
nuclear@0
|
772
|
nuclear@0
|
773 normal = cross(tang, bitan);
|
nuclear@0
|
774 }
|
nuclear@0
|
775
|
nuclear@0
|
776 *varr++ = pos;
|
nuclear@0
|
777 *narr++ = normalize(normal);
|
nuclear@0
|
778 *tarr++ = normalize(tang);
|
nuclear@0
|
779 *uvarr++ = Vec2(u, v);
|
nuclear@0
|
780
|
nuclear@0
|
781 if(i < usub && j < vsub) {
|
nuclear@0
|
782 int idx = i * vverts + j;
|
nuclear@0
|
783
|
nuclear@0
|
784 *idxarr++ = idx;
|
nuclear@0
|
785 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
786 *idxarr++ = idx + 1;
|
nuclear@0
|
787
|
nuclear@0
|
788 *idxarr++ = idx;
|
nuclear@0
|
789 *idxarr++ = idx + vverts;
|
nuclear@0
|
790 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
791 }
|
nuclear@0
|
792
|
nuclear@0
|
793 v += dv;
|
nuclear@0
|
794 }
|
nuclear@0
|
795 u += du;
|
nuclear@0
|
796 }
|
nuclear@0
|
797 }
|
nuclear@0
|
798
|
nuclear@0
|
799
|
nuclear@0
|
800 static inline Vec3 sweep_vert(float u, float v, float height, Vec2 (*sf)(float, float, void*), void *cls)
|
nuclear@0
|
801 {
|
nuclear@0
|
802 Vec2 pos = sf(u, v, cls);
|
nuclear@0
|
803
|
nuclear@0
|
804 float x = pos.x;
|
nuclear@0
|
805 float y = v * height;
|
nuclear@0
|
806 float z = pos.y;
|
nuclear@0
|
807
|
nuclear@0
|
808 return Vec3(x, y, z);
|
nuclear@0
|
809 }
|
nuclear@0
|
810
|
nuclear@0
|
811 // ---- sweep shape along a path ----
|
nuclear@0
|
812 void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vec2 (*sfunc)(float, float, void*), void *cls)
|
nuclear@0
|
813 {
|
nuclear@0
|
814 if(!sfunc) return;
|
nuclear@0
|
815 if(usub < 3) usub = 3;
|
nuclear@0
|
816 if(vsub < 1) vsub = 1;
|
nuclear@0
|
817
|
nuclear@0
|
818 mesh->clear();
|
nuclear@0
|
819
|
nuclear@0
|
820 int uverts = usub + 1;
|
nuclear@0
|
821 int vverts = vsub + 1;
|
nuclear@0
|
822 int num_verts = uverts * vverts;
|
nuclear@0
|
823
|
nuclear@0
|
824 int num_quads = usub * vsub;
|
nuclear@0
|
825 int num_tri = num_quads * 2;
|
nuclear@0
|
826
|
nuclear@0
|
827 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
828 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
829 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
830 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
831 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
832
|
nuclear@0
|
833 float du = 1.0 / (float)(uverts - 1);
|
nuclear@0
|
834 float dv = 1.0 / (float)(vverts - 1);
|
nuclear@0
|
835
|
nuclear@0
|
836 float u = 0.0;
|
nuclear@0
|
837 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
838 float v = 0.0;
|
nuclear@0
|
839 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
840 Vec3 pos = sweep_vert(u, v, height, sfunc, cls);
|
nuclear@0
|
841
|
nuclear@0
|
842 Vec3 nextu = sweep_vert(fmod(u + du, 1.0), v, height, sfunc, cls);
|
nuclear@0
|
843 Vec3 tang = nextu - pos;
|
nuclear@0
|
844 if(length_sq(tang) < 1e-6) {
|
nuclear@0
|
845 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
|
nuclear@0
|
846 nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls);
|
nuclear@0
|
847 tang = nextu - pos;
|
nuclear@0
|
848 }
|
nuclear@0
|
849
|
nuclear@0
|
850 Vec3 normal;
|
nuclear@0
|
851 Vec3 nextv = sweep_vert(u, v + dv, height, sfunc, cls);
|
nuclear@0
|
852 Vec3 bitan = nextv - pos;
|
nuclear@0
|
853 if(length_sq(bitan) < 1e-6) {
|
nuclear@0
|
854 nextv = sweep_vert(u, v - dv, height, sfunc, cls);
|
nuclear@0
|
855 bitan = pos - nextv;
|
nuclear@0
|
856 }
|
nuclear@0
|
857
|
nuclear@0
|
858 normal = cross(tang, bitan);
|
nuclear@0
|
859
|
nuclear@0
|
860 *varr++ = pos;
|
nuclear@0
|
861 *narr++ = normalize(normal);
|
nuclear@0
|
862 *tarr++ = normalize(tang);
|
nuclear@0
|
863 *uvarr++ = Vec2(u, v);
|
nuclear@0
|
864
|
nuclear@0
|
865 if(i < usub && j < vsub) {
|
nuclear@0
|
866 int idx = i * vverts + j;
|
nuclear@0
|
867
|
nuclear@0
|
868 *idxarr++ = idx;
|
nuclear@0
|
869 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
870 *idxarr++ = idx + 1;
|
nuclear@0
|
871
|
nuclear@0
|
872 *idxarr++ = idx;
|
nuclear@0
|
873 *idxarr++ = idx + vverts;
|
nuclear@0
|
874 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
875 }
|
nuclear@0
|
876
|
nuclear@0
|
877 v += dv;
|
nuclear@0
|
878 }
|
nuclear@0
|
879 u += du;
|
nuclear@0
|
880 }
|
nuclear@0
|
881 }
|