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