rev |
line source |
nuclear@16
|
1 #include <stdio.h>
|
nuclear@17
|
2 #include <stdlib.h>
|
nuclear@17
|
3 #include <string.h>
|
nuclear@17
|
4 #include <math.h>
|
nuclear@16
|
5 #include "goat3d.h"
|
nuclear@16
|
6
|
nuclear@18
|
7 #define DEF_USUB 16
|
nuclear@18
|
8 #define DEF_VSUB 8
|
nuclear@18
|
9 #define DEF_SIZE 1.0
|
nuclear@18
|
10 #define DEF_OUTER 0.25
|
nuclear@18
|
11 #define DEF_DIFFUSE_R 0.6
|
nuclear@18
|
12 #define DEF_DIFFUSE_G 0.6
|
nuclear@18
|
13 #define DEF_DIFFUSE_B 0.6
|
nuclear@18
|
14 #define DEF_SPECULAR_R 0.8
|
nuclear@18
|
15 #define DEF_SPECULAR_G 0.8
|
nuclear@18
|
16 #define DEF_SPECULAR_B 0.8
|
nuclear@18
|
17 #define DEF_SHININESS 60.0
|
nuclear@16
|
18
|
nuclear@17
|
19 enum { BOX, SPHERE, TORUS };
|
nuclear@17
|
20
|
nuclear@17
|
21 void gen_box(struct goat3d_mesh *mesh, float size);
|
nuclear@17
|
22 void gen_sphere(struct goat3d_mesh *mesh, float rad, int usub, int vsub);
|
nuclear@17
|
23 void gen_sphere_part(struct goat3d_mesh *mesh, float rad, int usub, int vsub, float umax, float vmax);
|
nuclear@17
|
24 void gen_torus(struct goat3d_mesh *mesh, float inner, float outer, int usub, int vsub);
|
nuclear@17
|
25 void gen_torus_part(struct goat3d_mesh *mesh, float inner, float outer,
|
nuclear@17
|
26 int usub, int vsub, float umax, float vmin, float vmax);
|
nuclear@17
|
27
|
nuclear@17
|
28
|
nuclear@17
|
29 int main(int argc, char **argv)
|
nuclear@16
|
30 {
|
nuclear@17
|
31 int i, prim = BOX;
|
nuclear@17
|
32 int usub = DEF_USUB;
|
nuclear@17
|
33 int vsub = DEF_VSUB;
|
nuclear@17
|
34 float size = DEF_SIZE;
|
nuclear@17
|
35 float outer = DEF_OUTER;
|
nuclear@18
|
36 float diffuse[] = {DEF_DIFFUSE_R, DEF_DIFFUSE_G, DEF_DIFFUSE_B, 1.0};
|
nuclear@18
|
37 float specular[] = {DEF_SPECULAR_R, DEF_SPECULAR_G, DEF_SPECULAR_B, 1.0};
|
nuclear@18
|
38 float shininess = DEF_SHININESS;
|
nuclear@16
|
39 struct goat3d *goat;
|
nuclear@16
|
40 struct goat3d_material *mtl;
|
nuclear@16
|
41 struct goat3d_mesh *mesh;
|
nuclear@17
|
42 const char *fname = 0;
|
nuclear@17
|
43
|
nuclear@17
|
44 for(i=1; i<argc; i++) {
|
nuclear@17
|
45 if(strcmp(argv[i], "-box") == 0) {
|
nuclear@17
|
46 prim = BOX;
|
nuclear@17
|
47
|
nuclear@17
|
48 } else if(strcmp(argv[i], "-sphere") == 0) {
|
nuclear@17
|
49 prim = SPHERE;
|
nuclear@17
|
50
|
nuclear@17
|
51 } else if(strcmp(argv[i], "-torus") == 0) {
|
nuclear@17
|
52 prim = TORUS;
|
nuclear@17
|
53
|
nuclear@17
|
54 } else if(strcmp(argv[i], "-rad") == 0 || strcmp(argv[i], "-size") == 0
|
nuclear@17
|
55 || strcmp(argv[i], "-inner") == 0) {
|
nuclear@17
|
56 if((size = atof(argv[++i])) == 0.0) {
|
nuclear@17
|
57 fprintf(stderr, "invalid size\n");
|
nuclear@17
|
58 return 1;
|
nuclear@17
|
59 }
|
nuclear@17
|
60
|
nuclear@17
|
61 } else if(strcmp(argv[i], "-outer") == 0) {
|
nuclear@17
|
62 if((outer = atof(argv[++i])) == 0.0) {
|
nuclear@17
|
63 fprintf(stderr, "invalid outer radius\n");
|
nuclear@17
|
64 return 1;
|
nuclear@17
|
65 }
|
nuclear@17
|
66
|
nuclear@17
|
67 } else if(strcmp(argv[i], "-usub") == 0) {
|
nuclear@17
|
68 if(!(usub = atoi(argv[++i]))) {
|
nuclear@17
|
69 fprintf(stderr, "invalid usub\n");
|
nuclear@17
|
70 return 1;
|
nuclear@17
|
71 }
|
nuclear@17
|
72
|
nuclear@17
|
73 } else if(strcmp(argv[i], "-vsub") == 0) {
|
nuclear@17
|
74 if(!(vsub = atoi(argv[++i]))) {
|
nuclear@17
|
75 fprintf(stderr, "invalid vsub\n");
|
nuclear@17
|
76 return 1;
|
nuclear@17
|
77 }
|
nuclear@17
|
78
|
nuclear@18
|
79 } else if(strcmp(argv[i], "-diffuse") == 0) {
|
nuclear@18
|
80 if(!argv[i + 1] || !argv[i + 2] || !argv[i + 3]) {
|
nuclear@18
|
81 fprintf(stderr, "-diffuse must be followed by 3 numbers (r, g, b)\n");
|
nuclear@18
|
82 return 1;
|
nuclear@18
|
83 }
|
nuclear@18
|
84 diffuse[0] = atof(argv[++i]);
|
nuclear@18
|
85 diffuse[1] = atof(argv[++i]);
|
nuclear@18
|
86 diffuse[2] = atof(argv[++i]);
|
nuclear@18
|
87
|
nuclear@18
|
88 } else if(strcmp(argv[i], "-specular") == 0) {
|
nuclear@18
|
89 if(!argv[i + 1] || !argv[i + 2] || !argv[i + 3]) {
|
nuclear@18
|
90 fprintf(stderr, "-specular must be followed by 3 numbers (r, g, b)\n");
|
nuclear@18
|
91 return 1;
|
nuclear@18
|
92 }
|
nuclear@18
|
93 specular[0] = atof(argv[++i]);
|
nuclear@18
|
94 specular[1] = atof(argv[++i]);
|
nuclear@18
|
95 specular[2] = atof(argv[++i]);
|
nuclear@18
|
96
|
nuclear@18
|
97 } else if(strcmp(argv[i], "-shininess") == 0) {
|
nuclear@18
|
98 if(!argv[i + 1]) {
|
nuclear@18
|
99 fprintf(stderr, "-shininess must be followed by a number\n");
|
nuclear@18
|
100 return 1;
|
nuclear@18
|
101 }
|
nuclear@18
|
102 shininess = atof(argv[++i]);
|
nuclear@18
|
103
|
nuclear@17
|
104 } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
|
nuclear@17
|
105 printf("Usage: %s [filename] [options]\n", argv[0]);
|
nuclear@17
|
106 printf("Options:\n");
|
nuclear@17
|
107 printf(" -box create box (default)\n");
|
nuclear@17
|
108 printf(" -sphere create sphere\n");
|
nuclear@17
|
109 printf(" -torus create torus\n");
|
nuclear@17
|
110 printf(" -size <n>, -rad <n>, -inner <n> (default: %g)\n", DEF_SIZE);
|
nuclear@17
|
111 printf(" -outer <n> torus outer radius (default: %g)\n", DEF_OUTER);
|
nuclear@17
|
112 printf(" -usub <n> subdivisions along the horizontal direction (default: %d)\n", DEF_USUB);
|
nuclear@17
|
113 printf(" -vsub <n> subdivisions along the vertical direction (default: %d)\n", DEF_VSUB);
|
nuclear@18
|
114 printf(" -diffuse <r> <g> <b> material diffuse color (default: %g %g %g)\n", DEF_DIFFUSE_R, DEF_DIFFUSE_G, DEF_DIFFUSE_B);
|
nuclear@18
|
115 printf(" -specular <r> <g> <b> material specular color (default: %g %g %g)\n", DEF_SPECULAR_R, DEF_SPECULAR_G, DEF_SPECULAR_B);
|
nuclear@18
|
116 printf(" -shininess <n> material shininess (default: %g)\n", DEF_SHININESS);
|
nuclear@17
|
117 printf(" -h, -help print usage information and exit\n");
|
nuclear@17
|
118 return 0;
|
nuclear@17
|
119
|
nuclear@17
|
120 } else {
|
nuclear@17
|
121 if(fname) {
|
nuclear@17
|
122 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
|
nuclear@17
|
123 return 1;
|
nuclear@17
|
124 }
|
nuclear@17
|
125 fname = argv[i];
|
nuclear@17
|
126 }
|
nuclear@17
|
127 }
|
nuclear@17
|
128
|
nuclear@17
|
129 if(!fname) {
|
nuclear@17
|
130 fname = "out.xml";
|
nuclear@17
|
131 }
|
nuclear@16
|
132
|
nuclear@16
|
133 goat = goat3d_create();
|
nuclear@17
|
134 goat3d_set_name(goat, fname);
|
nuclear@16
|
135
|
nuclear@16
|
136 mtl = goat3d_create_mtl();
|
nuclear@16
|
137 goat3d_set_mtl_name(mtl, "mat");
|
nuclear@18
|
138 goat3d_set_mtl_attrib(mtl, GOAT3D_MAT_ATTR_DIFFUSE, diffuse);
|
nuclear@18
|
139 goat3d_set_mtl_attrib(mtl, GOAT3D_MAT_ATTR_SPECULAR, specular);
|
nuclear@18
|
140 goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_SHININESS, shininess);
|
nuclear@16
|
141 goat3d_add_mtl(goat, mtl);
|
nuclear@16
|
142
|
nuclear@17
|
143 mesh = goat3d_create_mesh();
|
nuclear@17
|
144
|
nuclear@17
|
145 switch(prim) {
|
nuclear@17
|
146 case BOX:
|
nuclear@17
|
147 gen_box(mesh, size);
|
nuclear@17
|
148 break;
|
nuclear@17
|
149
|
nuclear@17
|
150 case SPHERE:
|
nuclear@17
|
151 gen_sphere(mesh, size, usub, vsub);
|
nuclear@17
|
152 break;
|
nuclear@17
|
153
|
nuclear@17
|
154 case TORUS:
|
nuclear@17
|
155 gen_torus(mesh, size, outer, usub, vsub);
|
nuclear@17
|
156 break;
|
nuclear@17
|
157
|
nuclear@17
|
158 default:
|
nuclear@17
|
159 return 1;
|
nuclear@17
|
160 }
|
nuclear@17
|
161 goat3d_set_mesh_mtl(mesh, mtl);
|
nuclear@16
|
162 goat3d_add_mesh(goat, mesh);
|
nuclear@16
|
163
|
nuclear@16
|
164 goat3d_setopt(goat, GOAT3D_OPT_SAVEXML, 1);
|
nuclear@17
|
165 goat3d_save(goat, fname);
|
nuclear@16
|
166
|
nuclear@16
|
167 goat3d_free(goat);
|
nuclear@16
|
168 return 0;
|
nuclear@16
|
169 }
|
nuclear@16
|
170
|
nuclear@17
|
171 void gen_box(struct goat3d_mesh *mesh, float size)
|
nuclear@16
|
172 {
|
nuclear@17
|
173 float hsz = size / 2.0;
|
nuclear@16
|
174
|
nuclear@16
|
175 goat3d_begin(mesh, GOAT3D_QUADS);
|
nuclear@16
|
176 // +X
|
nuclear@16
|
177 goat3d_normal3f(1, 0, 0);
|
nuclear@17
|
178 goat3d_texcoord2f(0, 0);
|
nuclear@17
|
179 goat3d_vertex3f(hsz, -hsz, hsz);
|
nuclear@17
|
180 goat3d_texcoord2f(1, 0);
|
nuclear@17
|
181 goat3d_vertex3f(hsz, -hsz, -hsz);
|
nuclear@17
|
182 goat3d_texcoord2f(1, 1);
|
nuclear@17
|
183 goat3d_vertex3f(hsz, hsz, -hsz);
|
nuclear@17
|
184 goat3d_texcoord2f(0, 1);
|
nuclear@17
|
185 goat3d_vertex3f(hsz, hsz, hsz);
|
nuclear@16
|
186
|
nuclear@16
|
187 // -X
|
nuclear@16
|
188 goat3d_normal3f(-1, 0, 0);
|
nuclear@17
|
189 goat3d_texcoord2f(0, 0);
|
nuclear@17
|
190 goat3d_vertex3f(-hsz, -hsz, -hsz);
|
nuclear@17
|
191 goat3d_texcoord2f(1, 0);
|
nuclear@17
|
192 goat3d_vertex3f(-hsz, -hsz, hsz);
|
nuclear@17
|
193 goat3d_texcoord2f(1, 1);
|
nuclear@17
|
194 goat3d_vertex3f(-hsz, hsz, hsz);
|
nuclear@17
|
195 goat3d_texcoord2f(0, 1);
|
nuclear@17
|
196 goat3d_vertex3f(-hsz, hsz, -hsz);
|
nuclear@16
|
197
|
nuclear@16
|
198 // +Y
|
nuclear@16
|
199 goat3d_normal3f(0, 1, 0);
|
nuclear@17
|
200 goat3d_texcoord2f(0, 0);
|
nuclear@17
|
201 goat3d_vertex3f(-hsz, hsz, hsz);
|
nuclear@17
|
202 goat3d_texcoord2f(1, 0);
|
nuclear@17
|
203 goat3d_vertex3f(hsz, hsz, hsz);
|
nuclear@17
|
204 goat3d_texcoord2f(1, 1);
|
nuclear@17
|
205 goat3d_vertex3f(hsz, hsz, -hsz);
|
nuclear@17
|
206 goat3d_texcoord2f(0, 1);
|
nuclear@17
|
207 goat3d_vertex3f(-hsz, hsz, -hsz);
|
nuclear@16
|
208
|
nuclear@16
|
209 // -Y
|
nuclear@16
|
210 goat3d_normal3f(0, -1, 0);
|
nuclear@17
|
211 goat3d_texcoord2f(0, 0);
|
nuclear@17
|
212 goat3d_vertex3f(-hsz, -hsz, -hsz);
|
nuclear@17
|
213 goat3d_texcoord2f(1, 0);
|
nuclear@17
|
214 goat3d_vertex3f(hsz, -hsz, -hsz);
|
nuclear@17
|
215 goat3d_texcoord2f(1, 1);
|
nuclear@17
|
216 goat3d_vertex3f(hsz, -hsz, hsz);
|
nuclear@17
|
217 goat3d_texcoord2f(0, 1);
|
nuclear@17
|
218 goat3d_vertex3f(-hsz, -hsz, hsz);
|
nuclear@16
|
219
|
nuclear@16
|
220 // +Z
|
nuclear@16
|
221 goat3d_normal3f(0, 0, 1);
|
nuclear@17
|
222 goat3d_texcoord2f(0, 0);
|
nuclear@17
|
223 goat3d_vertex3f(-hsz, -hsz, hsz);
|
nuclear@17
|
224 goat3d_texcoord2f(1, 0);
|
nuclear@17
|
225 goat3d_vertex3f(hsz, -hsz, hsz);
|
nuclear@17
|
226 goat3d_texcoord2f(1, 1);
|
nuclear@17
|
227 goat3d_vertex3f(hsz, hsz, hsz);
|
nuclear@17
|
228 goat3d_texcoord2f(0, 1);
|
nuclear@17
|
229 goat3d_vertex3f(-hsz, hsz, hsz);
|
nuclear@16
|
230
|
nuclear@16
|
231 // -Z
|
nuclear@16
|
232 goat3d_normal3f(0, 0, -1);
|
nuclear@17
|
233 goat3d_texcoord2f(0, 0);
|
nuclear@17
|
234 goat3d_vertex3f(hsz, -hsz, -hsz);
|
nuclear@17
|
235 goat3d_texcoord2f(1, 0);
|
nuclear@17
|
236 goat3d_vertex3f(-hsz, -hsz, -hsz);
|
nuclear@17
|
237 goat3d_texcoord2f(1, 1);
|
nuclear@17
|
238 goat3d_vertex3f(-hsz, hsz, -hsz);
|
nuclear@17
|
239 goat3d_texcoord2f(0, 1);
|
nuclear@17
|
240 goat3d_vertex3f(hsz, hsz, -hsz);
|
nuclear@16
|
241 goat3d_end();
|
nuclear@17
|
242 }
|
nuclear@16
|
243
|
nuclear@17
|
244 void gen_sphere(struct goat3d_mesh *mesh, float rad, int usub, int vsub)
|
nuclear@17
|
245 {
|
nuclear@17
|
246 gen_sphere_part(mesh, rad, usub, vsub, 1.0, 1.0);
|
nuclear@16
|
247 }
|
nuclear@17
|
248
|
nuclear@17
|
249 #define sphere_vertex(u, v) \
|
nuclear@17
|
250 do { \
|
nuclear@17
|
251 float x, y, z, theta, phi; \
|
nuclear@17
|
252 float costheta, sinphi; \
|
nuclear@17
|
253 theta = (u) * 2.0 * M_PI; \
|
nuclear@17
|
254 phi = (v) * M_PI; \
|
nuclear@17
|
255 costheta = cos(theta); \
|
nuclear@17
|
256 sinphi = sin(phi); \
|
nuclear@17
|
257 x = costheta * sinphi; \
|
nuclear@17
|
258 y = cos(phi); \
|
nuclear@17
|
259 z = sin(theta) * sinphi; \
|
nuclear@17
|
260 goat3d_normal3f(x, y, z); \
|
nuclear@17
|
261 goat3d_texcoord2f(u, v); \
|
nuclear@17
|
262 goat3d_vertex3f(rad * x, rad * y, rad * z); \
|
nuclear@17
|
263 } while(0)
|
nuclear@17
|
264
|
nuclear@17
|
265 void gen_sphere_part(struct goat3d_mesh *mesh, float rad, int usub, int vsub, float umax, float vmax)
|
nuclear@17
|
266 {
|
nuclear@17
|
267 int i, j;
|
nuclear@17
|
268 float u, v, du, dv;
|
nuclear@17
|
269
|
nuclear@17
|
270 if(usub < 3) usub = 3;
|
nuclear@17
|
271 if(vsub < 3) vsub = 3;
|
nuclear@17
|
272
|
nuclear@17
|
273 du = umax / (float)usub;
|
nuclear@17
|
274 dv = vmax / (float)vsub;
|
nuclear@17
|
275
|
nuclear@17
|
276 goat3d_begin(mesh, GOAT3D_QUADS);
|
nuclear@17
|
277
|
nuclear@17
|
278 u = 0.0;
|
nuclear@17
|
279 for(i=0; i<usub; i++) {
|
nuclear@17
|
280 v = 0.0;
|
nuclear@17
|
281 for(j=0; j<vsub; j++) {
|
nuclear@17
|
282 sphere_vertex(u, v);
|
nuclear@17
|
283 sphere_vertex(u + du, v);
|
nuclear@17
|
284 sphere_vertex(u + du, v + dv);
|
nuclear@17
|
285 sphere_vertex(u, v + dv);
|
nuclear@17
|
286 v += dv;
|
nuclear@17
|
287 }
|
nuclear@17
|
288 u += du;
|
nuclear@17
|
289 }
|
nuclear@17
|
290 goat3d_end();
|
nuclear@17
|
291 }
|
nuclear@17
|
292
|
nuclear@17
|
293
|
nuclear@17
|
294 void gen_torus(struct goat3d_mesh *mesh, float inner, float outer, int usub, int vsub)
|
nuclear@17
|
295 {
|
nuclear@17
|
296 gen_torus_part(mesh, inner, outer, usub, vsub, 1.0, 0.0, 1.0);
|
nuclear@17
|
297 }
|
nuclear@17
|
298
|
nuclear@17
|
299 #define torus_vertex(u, v) \
|
nuclear@17
|
300 do { \
|
nuclear@17
|
301 float rx, ry, rz, cx, cy, cz, theta, phi; \
|
nuclear@17
|
302 float costheta, sintheta, sinphi; \
|
nuclear@17
|
303 theta = (u) * 2.0 * M_PI; \
|
nuclear@17
|
304 phi = (v) * 2.0 * M_PI; \
|
nuclear@17
|
305 costheta = cos(theta); \
|
nuclear@17
|
306 sintheta = sin(theta); \
|
nuclear@17
|
307 sinphi = sin(phi); \
|
nuclear@17
|
308 cx = costheta * inner; \
|
nuclear@17
|
309 cy = 0.0f; \
|
nuclear@17
|
310 cz = sintheta * inner; \
|
nuclear@17
|
311 rx = costheta * sinphi; \
|
nuclear@17
|
312 ry = cos(phi); \
|
nuclear@17
|
313 rz = sintheta * sinphi; \
|
nuclear@17
|
314 goat3d_normal3f(rx, ry, rz); \
|
nuclear@17
|
315 goat3d_texcoord2f(u, v); \
|
nuclear@17
|
316 goat3d_vertex3f(outer * rx + cx, outer * ry + cy, outer * rz + cz); \
|
nuclear@17
|
317 } while(0)
|
nuclear@17
|
318
|
nuclear@17
|
319 void gen_torus_part(struct goat3d_mesh *mesh, float inner, float outer,
|
nuclear@17
|
320 int usub, int vsub, float umax, float vmin, float vmax)
|
nuclear@17
|
321 {
|
nuclear@17
|
322 int i, j;
|
nuclear@17
|
323 float u, v, du, dv;
|
nuclear@17
|
324
|
nuclear@17
|
325 if(usub < 3) usub = 3;
|
nuclear@17
|
326 if(vsub < 3) vsub = 3;
|
nuclear@17
|
327
|
nuclear@17
|
328 du = umax / (float)usub;
|
nuclear@17
|
329 dv = (vmax - vmin) / (float)vsub;
|
nuclear@17
|
330
|
nuclear@17
|
331 goat3d_begin(mesh, GOAT3D_QUADS);
|
nuclear@17
|
332
|
nuclear@17
|
333 u = 0.0;
|
nuclear@17
|
334 for(i=0; i<usub; i++) {
|
nuclear@17
|
335 v = vmin;
|
nuclear@17
|
336 for(j=0; j<vsub; j++) {
|
nuclear@17
|
337 torus_vertex(u, v);
|
nuclear@17
|
338 torus_vertex(u + du, v);
|
nuclear@17
|
339 torus_vertex(u + du, v + dv);
|
nuclear@17
|
340 torus_vertex(u, v + dv);
|
nuclear@17
|
341 v += dv;
|
nuclear@17
|
342 }
|
nuclear@17
|
343 u += du;
|
nuclear@17
|
344 }
|
nuclear@17
|
345 goat3d_end();
|
nuclear@17
|
346 }
|