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 Vector3 sphvec(float theta, float phi)
|
nuclear@0
|
11 {
|
nuclear@0
|
12 return Vector3(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 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
31 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
32 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
33 Vector2 *uvarr = (Vector2*)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 = SURAD(u * urange);
|
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 = SVRAD(v * vrange);
|
nuclear@0
|
46
|
nuclear@0
|
47 Vector3 pos = sphvec(theta, phi);
|
nuclear@0
|
48
|
nuclear@0
|
49 *varr++ = pos * rad;
|
nuclear@0
|
50 *narr++ = pos;
|
nuclear@0
|
51 *tarr++ = (sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)).normalized();
|
nuclear@0
|
52 *uvarr++ = Vector2(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
|
nuclear@0
|
72 // -------- cylinder --------
|
nuclear@0
|
73
|
nuclear@0
|
74 static Vector3 cylvec(float theta, float height)
|
nuclear@0
|
75 {
|
nuclear@0
|
76 return Vector3(sin(theta), height, cos(theta));
|
nuclear@0
|
77 }
|
nuclear@0
|
78
|
nuclear@0
|
79 void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
|
nuclear@0
|
80 {
|
nuclear@0
|
81 if(usub < 4) usub = 4;
|
nuclear@0
|
82 if(vsub < 1) vsub = 1;
|
nuclear@0
|
83
|
nuclear@0
|
84 int uverts = usub + 1;
|
nuclear@0
|
85 int vverts = vsub + 1;
|
nuclear@0
|
86
|
nuclear@0
|
87 int num_body_verts = uverts * vverts;
|
nuclear@0
|
88 int num_body_quads = usub * vsub;
|
nuclear@0
|
89 int num_body_tri = num_body_quads * 2;
|
nuclear@0
|
90
|
nuclear@0
|
91 int capvverts = capsub ? capsub + 1 : 0;
|
nuclear@0
|
92 int num_cap_verts = uverts * capvverts;
|
nuclear@0
|
93 int num_cap_quads = usub * capsub;
|
nuclear@0
|
94 int num_cap_tri = num_cap_quads * 2;
|
nuclear@0
|
95
|
nuclear@0
|
96 int num_verts = num_body_verts + num_cap_verts * 2;
|
nuclear@0
|
97 int num_tri = num_body_tri + num_cap_tri * 2;
|
nuclear@0
|
98
|
nuclear@0
|
99 mesh->clear();
|
nuclear@0
|
100 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
101 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
102 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
103 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
104 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
105
|
nuclear@0
|
106 float du = urange / (float)(uverts - 1);
|
nuclear@0
|
107 float dv = vrange / (float)(vverts - 1);
|
nuclear@0
|
108
|
nuclear@0
|
109 float u = 0.0;
|
nuclear@0
|
110 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
111 float theta = SURAD(u);
|
nuclear@0
|
112
|
nuclear@0
|
113 float v = 0.0;
|
nuclear@0
|
114 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
115 float y = (v - 0.5) * height;
|
nuclear@0
|
116 Vector3 pos = cylvec(theta, y);
|
nuclear@0
|
117
|
nuclear@0
|
118 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
|
nuclear@0
|
119 *narr++ = Vector3(pos.x, 0.0, pos.z);
|
nuclear@0
|
120 *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
|
nuclear@0
|
121 *uvarr++ = Vector2(u * urange, v * vrange);
|
nuclear@0
|
122
|
nuclear@0
|
123 if(i < usub && j < vsub) {
|
nuclear@0
|
124 int idx = i * vverts + j;
|
nuclear@0
|
125
|
nuclear@0
|
126 *idxarr++ = idx;
|
nuclear@0
|
127 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
128 *idxarr++ = idx + 1;
|
nuclear@0
|
129
|
nuclear@0
|
130 *idxarr++ = idx;
|
nuclear@0
|
131 *idxarr++ = idx + vverts;
|
nuclear@0
|
132 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
133 }
|
nuclear@0
|
134
|
nuclear@0
|
135 v += dv;
|
nuclear@0
|
136 }
|
nuclear@0
|
137 u += du;
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140
|
nuclear@0
|
141 // now the cap!
|
nuclear@0
|
142 if(!capsub) {
|
nuclear@0
|
143 return;
|
nuclear@0
|
144 }
|
nuclear@0
|
145
|
nuclear@0
|
146 dv = 1.0 / (float)(capvverts - 1);
|
nuclear@0
|
147
|
nuclear@0
|
148 u = 0.0;
|
nuclear@0
|
149 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
150 float theta = SURAD(u);
|
nuclear@0
|
151
|
nuclear@0
|
152 float v = 0.0;
|
nuclear@0
|
153 for(int j=0; j<capvverts; j++) {
|
nuclear@0
|
154 float r = v * rad;
|
nuclear@0
|
155
|
nuclear@0
|
156 Vector3 pos = cylvec(theta, height / 2.0) * r;
|
nuclear@0
|
157 pos.y = height / 2.0;
|
nuclear@0
|
158 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
|
nuclear@0
|
159
|
nuclear@0
|
160 *varr++ = pos;
|
nuclear@0
|
161 *narr++ = Vector3(0, 1, 0);
|
nuclear@0
|
162 *tarr++ = tang;
|
nuclear@0
|
163 *uvarr++ = Vector2(u * urange, v);
|
nuclear@0
|
164
|
nuclear@0
|
165 pos.y = -height / 2.0;
|
nuclear@0
|
166 *varr++ = pos;
|
nuclear@0
|
167 *narr++ = Vector3(0, -1, 0);
|
nuclear@0
|
168 *tarr++ = -tang;
|
nuclear@0
|
169 *uvarr++ = Vector2(u * urange, v);
|
nuclear@0
|
170
|
nuclear@0
|
171 if(i < usub && j < capsub) {
|
nuclear@0
|
172 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
|
nuclear@0
|
173
|
nuclear@0
|
174 unsigned int vidx[4] = {
|
nuclear@0
|
175 idx,
|
nuclear@0
|
176 idx + capvverts * 2,
|
nuclear@0
|
177 idx + (capvverts + 1) * 2,
|
nuclear@0
|
178 idx + 2
|
nuclear@0
|
179 };
|
nuclear@0
|
180
|
nuclear@0
|
181 *idxarr++ = vidx[0];
|
nuclear@0
|
182 *idxarr++ = vidx[2];
|
nuclear@0
|
183 *idxarr++ = vidx[1];
|
nuclear@0
|
184 *idxarr++ = vidx[0];
|
nuclear@0
|
185 *idxarr++ = vidx[3];
|
nuclear@0
|
186 *idxarr++ = vidx[2];
|
nuclear@0
|
187
|
nuclear@0
|
188 *idxarr++ = vidx[0] + 1;
|
nuclear@0
|
189 *idxarr++ = vidx[1] + 1;
|
nuclear@0
|
190 *idxarr++ = vidx[2] + 1;
|
nuclear@0
|
191 *idxarr++ = vidx[0] + 1;
|
nuclear@0
|
192 *idxarr++ = vidx[2] + 1;
|
nuclear@0
|
193 *idxarr++ = vidx[3] + 1;
|
nuclear@0
|
194 }
|
nuclear@0
|
195
|
nuclear@0
|
196 v += dv;
|
nuclear@0
|
197 }
|
nuclear@0
|
198 u += du;
|
nuclear@0
|
199 }
|
nuclear@0
|
200 }
|
nuclear@0
|
201
|
nuclear@0
|
202 // -------- cone --------
|
nuclear@0
|
203
|
nuclear@0
|
204 static Vector3 conevec(float theta, float y, float height)
|
nuclear@0
|
205 {
|
nuclear@0
|
206 float scale = 1.0 - y / height;
|
nuclear@0
|
207 return Vector3(sin(theta) * scale, y, cos(theta) * scale);
|
nuclear@0
|
208 }
|
nuclear@0
|
209
|
nuclear@0
|
210 void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
|
nuclear@0
|
211 {
|
nuclear@0
|
212 if(usub < 4) usub = 4;
|
nuclear@0
|
213 if(vsub < 1) vsub = 1;
|
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_body_verts = uverts * vverts;
|
nuclear@0
|
219 int num_body_quads = usub * vsub;
|
nuclear@0
|
220 int num_body_tri = num_body_quads * 2;
|
nuclear@0
|
221
|
nuclear@0
|
222 int capvverts = capsub ? capsub + 1 : 0;
|
nuclear@0
|
223 int num_cap_verts = uverts * capvverts;
|
nuclear@0
|
224 int num_cap_quads = usub * capsub;
|
nuclear@0
|
225 int num_cap_tri = num_cap_quads * 2;
|
nuclear@0
|
226
|
nuclear@0
|
227 int num_verts = num_body_verts + num_cap_verts;
|
nuclear@0
|
228 int num_tri = num_body_tri + num_cap_tri;
|
nuclear@0
|
229
|
nuclear@0
|
230 mesh->clear();
|
nuclear@0
|
231 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
232 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
233 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
234 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
235 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
236
|
nuclear@0
|
237 float du = urange / (float)(uverts - 1);
|
nuclear@0
|
238 float dv = vrange / (float)(vverts - 1);
|
nuclear@0
|
239
|
nuclear@0
|
240 float u = 0.0;
|
nuclear@0
|
241 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
242 float theta = SURAD(u);
|
nuclear@0
|
243
|
nuclear@0
|
244 float v = 0.0;
|
nuclear@0
|
245 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
246 float y = v * height;
|
nuclear@0
|
247 Vector3 pos = conevec(theta, y, height);
|
nuclear@0
|
248
|
nuclear@0
|
249 Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized();
|
nuclear@0
|
250 Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized();
|
nuclear@0
|
251
|
nuclear@0
|
252 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
|
nuclear@0
|
253 *narr++ = cross_product(tang, bitang);
|
nuclear@0
|
254 *tarr++ = tang;
|
nuclear@0
|
255 *uvarr++ = Vector2(u * urange, v * vrange);
|
nuclear@0
|
256
|
nuclear@0
|
257 if(i < usub && j < vsub) {
|
nuclear@0
|
258 int idx = i * vverts + j;
|
nuclear@0
|
259
|
nuclear@0
|
260 *idxarr++ = idx;
|
nuclear@0
|
261 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
262 *idxarr++ = idx + 1;
|
nuclear@0
|
263
|
nuclear@0
|
264 *idxarr++ = idx;
|
nuclear@0
|
265 *idxarr++ = idx + vverts;
|
nuclear@0
|
266 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
267 }
|
nuclear@0
|
268
|
nuclear@0
|
269 v += dv;
|
nuclear@0
|
270 }
|
nuclear@0
|
271 u += du;
|
nuclear@0
|
272 }
|
nuclear@0
|
273
|
nuclear@0
|
274
|
nuclear@0
|
275 // now the bottom cap!
|
nuclear@0
|
276 if(!capsub) {
|
nuclear@0
|
277 return;
|
nuclear@0
|
278 }
|
nuclear@0
|
279
|
nuclear@0
|
280 dv = 1.0 / (float)(capvverts - 1);
|
nuclear@0
|
281
|
nuclear@0
|
282 u = 0.0;
|
nuclear@0
|
283 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
284 float theta = SURAD(u);
|
nuclear@0
|
285
|
nuclear@0
|
286 float v = 0.0;
|
nuclear@0
|
287 for(int j=0; j<capvverts; j++) {
|
nuclear@0
|
288 float r = v * rad;
|
nuclear@0
|
289
|
nuclear@0
|
290 Vector3 pos = conevec(theta, 0.0, height) * r;
|
nuclear@0
|
291 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
|
nuclear@0
|
292
|
nuclear@0
|
293 *varr++ = pos;
|
nuclear@0
|
294 *narr++ = Vector3(0, -1, 0);
|
nuclear@0
|
295 *tarr++ = tang;
|
nuclear@0
|
296 *uvarr++ = Vector2(u * urange, v);
|
nuclear@0
|
297
|
nuclear@0
|
298 if(i < usub && j < capsub) {
|
nuclear@0
|
299 unsigned int idx = num_body_verts + i * capvverts + j;
|
nuclear@0
|
300
|
nuclear@0
|
301 unsigned int vidx[4] = {
|
nuclear@0
|
302 idx,
|
nuclear@0
|
303 idx + capvverts,
|
nuclear@0
|
304 idx + (capvverts + 1),
|
nuclear@0
|
305 idx + 1
|
nuclear@0
|
306 };
|
nuclear@0
|
307
|
nuclear@0
|
308 *idxarr++ = vidx[0];
|
nuclear@0
|
309 *idxarr++ = vidx[1];
|
nuclear@0
|
310 *idxarr++ = vidx[2];
|
nuclear@0
|
311 *idxarr++ = vidx[0];
|
nuclear@0
|
312 *idxarr++ = vidx[2];
|
nuclear@0
|
313 *idxarr++ = vidx[3];
|
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
|
nuclear@0
|
323 // -------- plane --------
|
nuclear@0
|
324
|
nuclear@0
|
325 void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
|
nuclear@0
|
326 {
|
nuclear@0
|
327 gen_heightmap(mesh, width, height, usub, vsub, 0);
|
nuclear@0
|
328 }
|
nuclear@0
|
329
|
nuclear@0
|
330
|
nuclear@0
|
331 // ----- heightmap ------
|
nuclear@0
|
332
|
nuclear@0
|
333 void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
|
nuclear@0
|
334 {
|
nuclear@0
|
335 if(usub < 1) usub = 1;
|
nuclear@0
|
336 if(vsub < 1) vsub = 1;
|
nuclear@0
|
337
|
nuclear@0
|
338 mesh->clear();
|
nuclear@0
|
339
|
nuclear@0
|
340 int uverts = usub + 1;
|
nuclear@0
|
341 int vverts = vsub + 1;
|
nuclear@0
|
342 int num_verts = uverts * vverts;
|
nuclear@0
|
343
|
nuclear@0
|
344 int num_quads = usub * vsub;
|
nuclear@0
|
345 int num_tri = num_quads * 2;
|
nuclear@0
|
346
|
nuclear@0
|
347 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
348 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
349 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
350 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
351 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
352
|
nuclear@0
|
353 float du = 1.0 / (float)usub;
|
nuclear@0
|
354 float dv = 1.0 / (float)vsub;
|
nuclear@0
|
355
|
nuclear@0
|
356 float u = 0.0;
|
nuclear@0
|
357 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
358 float v = 0.0;
|
nuclear@0
|
359 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
360 float x = (u - 0.5) * width;
|
nuclear@0
|
361 float y = (v - 0.5) * height;
|
nuclear@0
|
362 float z = hf ? hf(u, v, hfdata) : 0.0;
|
nuclear@0
|
363
|
nuclear@0
|
364 Vector3 normal = Vector3(0, 0, 1);
|
nuclear@0
|
365 if(hf) {
|
nuclear@0
|
366 float u1z = hf(u + du, v, hfdata);
|
nuclear@0
|
367 float v1z = hf(u, v + dv, hfdata);
|
nuclear@0
|
368
|
nuclear@0
|
369 Vector3 tang = Vector3(du * width, 0, u1z - z);
|
nuclear@0
|
370 Vector3 bitan = Vector3(0, dv * height, v1z - z);
|
nuclear@0
|
371 normal = cross_product(tang, bitan).normalized();
|
nuclear@0
|
372 }
|
nuclear@0
|
373
|
nuclear@0
|
374 *varr++ = Vector3(x, y, z);
|
nuclear@0
|
375 *narr++ = normal;
|
nuclear@0
|
376 *tarr++ = Vector3(1, 0, 0);
|
nuclear@0
|
377 *uvarr++ = Vector2(u, v);
|
nuclear@0
|
378
|
nuclear@0
|
379 if(i < usub && j < vsub) {
|
nuclear@0
|
380 int idx = i * vverts + j;
|
nuclear@0
|
381
|
nuclear@0
|
382 *idxarr++ = idx;
|
nuclear@0
|
383 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
384 *idxarr++ = idx + 1;
|
nuclear@0
|
385
|
nuclear@0
|
386 *idxarr++ = idx;
|
nuclear@0
|
387 *idxarr++ = idx + vverts;
|
nuclear@0
|
388 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
389 }
|
nuclear@0
|
390
|
nuclear@0
|
391 v += dv;
|
nuclear@0
|
392 }
|
nuclear@0
|
393 u += du;
|
nuclear@0
|
394 }
|
nuclear@0
|
395 }
|
nuclear@0
|
396
|
nuclear@1
|
397 // ----- box ------
|
nuclear@1
|
398 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub)
|
nuclear@1
|
399 {
|
nuclear@1
|
400 static const float face_angles[][2] = {
|
nuclear@1
|
401 {0, 0},
|
nuclear@1
|
402 {M_PI / 2.0, 0},
|
nuclear@1
|
403 {M_PI, 0},
|
nuclear@1
|
404 {3.0 * M_PI / 2.0, 0},
|
nuclear@1
|
405 {0, M_PI / 2.0},
|
nuclear@1
|
406 {0, -M_PI / 2.0}
|
nuclear@1
|
407 };
|
nuclear@0
|
408
|
nuclear@1
|
409 if(usub < 1) usub = 1;
|
nuclear@1
|
410 if(vsub < 1) vsub = 1;
|
nuclear@1
|
411
|
nuclear@1
|
412 mesh->clear();
|
nuclear@1
|
413
|
nuclear@1
|
414 for(int i=0; i<6; i++) {
|
nuclear@2
|
415 Matrix4x4 xform, dir_xform;
|
nuclear@1
|
416 Mesh m;
|
nuclear@1
|
417
|
nuclear@1
|
418 gen_plane(&m, 1, 1, usub, vsub);
|
nuclear@1
|
419 xform.rotate(Vector3(face_angles[i][1], face_angles[i][0], 0));
|
nuclear@2
|
420 dir_xform = xform;
|
nuclear@1
|
421 xform.translate(Vector3(0, 0, 0.5));
|
nuclear@2
|
422 m.apply_xform(xform, dir_xform);
|
nuclear@1
|
423
|
nuclear@1
|
424 mesh->append(m);
|
nuclear@1
|
425 }
|
nuclear@1
|
426
|
nuclear@1
|
427 Matrix4x4 scale;
|
nuclear@1
|
428 scale.set_scaling(Vector3(xsz, ysz, zsz));
|
nuclear@1
|
429 mesh->apply_xform(scale, Matrix4x4::identity);
|
nuclear@1
|
430 }
|
nuclear@1
|
431
|
nuclear@1
|
432 /*
|
nuclear@0
|
433 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
|
nuclear@0
|
434 {
|
nuclear@0
|
435 mesh->clear();
|
nuclear@0
|
436
|
nuclear@0
|
437 const int num_faces = 6;
|
nuclear@0
|
438 int num_verts = num_faces * 4;
|
nuclear@0
|
439 int num_tri = num_faces * 2;
|
nuclear@0
|
440
|
nuclear@0
|
441 float x = xsz / 2.0;
|
nuclear@0
|
442 float y = ysz / 2.0;
|
nuclear@0
|
443 float z = zsz / 2.0;
|
nuclear@0
|
444
|
nuclear@0
|
445 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
446 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
447 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
448 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
449 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
450
|
nuclear@0
|
451 static const Vector2 uv[] = { Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) };
|
nuclear@0
|
452
|
nuclear@0
|
453 // front
|
nuclear@0
|
454 for(int i=0; i<4; i++) {
|
nuclear@0
|
455 *narr++ = Vector3(0, 0, 1);
|
nuclear@0
|
456 *tarr++ = Vector3(1, 0, 0);
|
nuclear@0
|
457 *uvarr++ = uv[i];
|
nuclear@0
|
458 }
|
nuclear@0
|
459 *varr++ = Vector3(-x, -y, z);
|
nuclear@0
|
460 *varr++ = Vector3(x, -y, z);
|
nuclear@0
|
461 *varr++ = Vector3(x, y, z);
|
nuclear@0
|
462 *varr++ = Vector3(-x, y, z);
|
nuclear@0
|
463 // right
|
nuclear@0
|
464 for(int i=0; i<4; i++) {
|
nuclear@0
|
465 *narr++ = Vector3(1, 0, 0);
|
nuclear@0
|
466 *tarr++ = Vector3(0, 0, -1);
|
nuclear@0
|
467 *uvarr++ = uv[i];
|
nuclear@0
|
468 }
|
nuclear@0
|
469 *varr++ = Vector3(x, -y, z);
|
nuclear@0
|
470 *varr++ = Vector3(x, -y, -z);
|
nuclear@0
|
471 *varr++ = Vector3(x, y, -z);
|
nuclear@0
|
472 *varr++ = Vector3(x, y, z);
|
nuclear@0
|
473 // back
|
nuclear@0
|
474 for(int i=0; i<4; i++) {
|
nuclear@0
|
475 *narr++ = Vector3(0, 0, -1);
|
nuclear@0
|
476 *tarr++ = Vector3(-1, 0, 0);
|
nuclear@0
|
477 *uvarr++ = uv[i];
|
nuclear@0
|
478 }
|
nuclear@0
|
479 *varr++ = Vector3(x, -y, -z);
|
nuclear@0
|
480 *varr++ = Vector3(-x, -y, -z);
|
nuclear@0
|
481 *varr++ = Vector3(-x, y, -z);
|
nuclear@0
|
482 *varr++ = Vector3(x, y, -z);
|
nuclear@0
|
483 // left
|
nuclear@0
|
484 for(int i=0; i<4; i++) {
|
nuclear@0
|
485 *narr++ = Vector3(-1, 0, 0);
|
nuclear@0
|
486 *tarr++ = Vector3(0, 0, 1);
|
nuclear@0
|
487 *uvarr++ = uv[i];
|
nuclear@0
|
488 }
|
nuclear@0
|
489 *varr++ = Vector3(-x, -y, -z);
|
nuclear@0
|
490 *varr++ = Vector3(-x, -y, z);
|
nuclear@0
|
491 *varr++ = Vector3(-x, y, z);
|
nuclear@0
|
492 *varr++ = Vector3(-x, y, -z);
|
nuclear@0
|
493 // top
|
nuclear@0
|
494 for(int i=0; i<4; i++) {
|
nuclear@0
|
495 *narr++ = Vector3(0, 1, 0);
|
nuclear@0
|
496 *tarr++ = Vector3(1, 0, 0);
|
nuclear@0
|
497 *uvarr++ = uv[i];
|
nuclear@0
|
498 }
|
nuclear@0
|
499 *varr++ = Vector3(-x, y, z);
|
nuclear@0
|
500 *varr++ = Vector3(x, y, z);
|
nuclear@0
|
501 *varr++ = Vector3(x, y, -z);
|
nuclear@0
|
502 *varr++ = Vector3(-x, y, -z);
|
nuclear@0
|
503 // bottom
|
nuclear@0
|
504 for(int i=0; i<4; i++) {
|
nuclear@0
|
505 *narr++ = Vector3(0, -1, 0);
|
nuclear@0
|
506 *tarr++ = Vector3(1, 0, 0);
|
nuclear@0
|
507 *uvarr++ = uv[i];
|
nuclear@0
|
508 }
|
nuclear@0
|
509 *varr++ = Vector3(-x, -y, -z);
|
nuclear@0
|
510 *varr++ = Vector3(x, -y, -z);
|
nuclear@0
|
511 *varr++ = Vector3(x, -y, z);
|
nuclear@0
|
512 *varr++ = Vector3(-x, -y, z);
|
nuclear@0
|
513
|
nuclear@0
|
514 // index array
|
nuclear@0
|
515 static const int faceidx[] = {0, 1, 2, 0, 2, 3};
|
nuclear@0
|
516 for(int i=0; i<num_faces; i++) {
|
nuclear@0
|
517 for(int j=0; j<6; j++) {
|
nuclear@0
|
518 *idxarr++ = faceidx[j] + i * 4;
|
nuclear@0
|
519 }
|
nuclear@0
|
520 }
|
nuclear@0
|
521 }
|
nuclear@1
|
522 */
|
nuclear@0
|
523
|
nuclear@0
|
524 static inline Vector3 rev_vert(float u, float v, Vector2 (*rf)(float, float, void*), void *cls)
|
nuclear@0
|
525 {
|
nuclear@0
|
526 Vector2 pos = rf(u, v, cls);
|
nuclear@0
|
527
|
nuclear@0
|
528 float angle = u * 2.0 * M_PI;
|
nuclear@0
|
529 float x = pos.x * cos(angle);
|
nuclear@0
|
530 float y = pos.y;
|
nuclear@0
|
531 float z = pos.x * sin(angle);
|
nuclear@0
|
532
|
nuclear@0
|
533 return Vector3(x, y, z);
|
nuclear@0
|
534 }
|
nuclear@0
|
535
|
nuclear@0
|
536 // ------ surface of revolution -------
|
nuclear@0
|
537 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls)
|
nuclear@0
|
538 {
|
nuclear@0
|
539 gen_revol(mesh, usub, vsub, rfunc, 0, cls);
|
nuclear@0
|
540 }
|
nuclear@0
|
541
|
nuclear@0
|
542 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*),
|
nuclear@0
|
543 Vector2 (*nfunc)(float, float, void*), void *cls)
|
nuclear@0
|
544 {
|
nuclear@0
|
545 if(!rfunc) return;
|
nuclear@0
|
546 if(usub < 3) usub = 3;
|
nuclear@0
|
547 if(vsub < 1) vsub = 1;
|
nuclear@0
|
548
|
nuclear@0
|
549 mesh->clear();
|
nuclear@0
|
550
|
nuclear@0
|
551 int uverts = usub + 1;
|
nuclear@0
|
552 int vverts = vsub + 1;
|
nuclear@0
|
553 int num_verts = uverts * vverts;
|
nuclear@0
|
554
|
nuclear@0
|
555 int num_quads = usub * vsub;
|
nuclear@0
|
556 int num_tri = num_quads * 2;
|
nuclear@0
|
557
|
nuclear@0
|
558 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
|
nuclear@0
|
559 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
|
nuclear@0
|
560 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
|
nuclear@0
|
561 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
|
nuclear@0
|
562 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
|
nuclear@0
|
563
|
nuclear@0
|
564 float du = 1.0 / (float)(uverts - 1);
|
nuclear@0
|
565 float dv = 1.0 / (float)(vverts - 1);
|
nuclear@0
|
566
|
nuclear@0
|
567 float u = 0.0;
|
nuclear@0
|
568 for(int i=0; i<uverts; i++) {
|
nuclear@0
|
569 float v = 0.0;
|
nuclear@0
|
570 for(int j=0; j<vverts; j++) {
|
nuclear@0
|
571 Vector3 pos = rev_vert(u, v, rfunc, cls);
|
nuclear@0
|
572
|
nuclear@0
|
573 Vector3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls);
|
nuclear@0
|
574 Vector3 tang = nextu - pos;
|
nuclear@0
|
575 if(tang.length_sq() < 1e-6) {
|
nuclear@0
|
576 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
|
nuclear@0
|
577 nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls);
|
nuclear@0
|
578 tang = nextu - pos;
|
nuclear@0
|
579 }
|
nuclear@0
|
580
|
nuclear@0
|
581 Vector3 normal;
|
nuclear@0
|
582 if(nfunc) {
|
nuclear@0
|
583 normal = rev_vert(u, v, nfunc, cls);
|
nuclear@0
|
584 } else {
|
nuclear@0
|
585 Vector3 nextv = rev_vert(u, v + dv, rfunc, cls);
|
nuclear@0
|
586 Vector3 bitan = nextv - pos;
|
nuclear@0
|
587 if(bitan.length_sq() < 1e-6) {
|
nuclear@0
|
588 nextv = rev_vert(u, v - dv, rfunc, cls);
|
nuclear@0
|
589 bitan = pos - nextv;
|
nuclear@0
|
590 }
|
nuclear@0
|
591
|
nuclear@0
|
592 normal = cross_product(tang, bitan);
|
nuclear@0
|
593 }
|
nuclear@0
|
594
|
nuclear@0
|
595 *varr++ = pos;
|
nuclear@0
|
596 *narr++ = normal.normalized();
|
nuclear@0
|
597 *tarr++ = tang.normalized();
|
nuclear@0
|
598 *uvarr++ = Vector2(u, v);
|
nuclear@0
|
599
|
nuclear@0
|
600 if(i < usub && j < vsub) {
|
nuclear@0
|
601 int idx = i * vverts + j;
|
nuclear@0
|
602
|
nuclear@0
|
603 *idxarr++ = idx;
|
nuclear@0
|
604 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
605 *idxarr++ = idx + 1;
|
nuclear@0
|
606
|
nuclear@0
|
607 *idxarr++ = idx;
|
nuclear@0
|
608 *idxarr++ = idx + vverts;
|
nuclear@0
|
609 *idxarr++ = idx + vverts + 1;
|
nuclear@0
|
610 }
|
nuclear@0
|
611
|
nuclear@0
|
612 v += dv;
|
nuclear@0
|
613 }
|
nuclear@0
|
614 u += du;
|
nuclear@0
|
615 }
|
nuclear@0
|
616 }
|