ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/genbox.c
Revision: 2.14
Committed: Fri Jun 6 19:11:21 2025 UTC (3 days, 11 hours ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.13: +1 -6 lines
Log Message:
refactor: Making use of printargs() more consistent with fixargv0()

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.14 static const char RCSid[] = "$Id: genbox.c,v 2.13 2021/04/15 23:51:04 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * genbox.c - generate a parallelepiped.
6     *
7     * 1/8/86
8     */
9    
10 greg 2.8 #include "rtio.h"
11 greg 2.11 #include "rtmath.h"
12     #include "objutil.h"
13 greg 2.8 #include <stdlib.h>
14 greg 2.3
15 greg 2.11 int verbose = 0;
16    
17 greg 1.1 char let[]="0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
18    
19 greg 2.11 char *cmtype; /* ppd material type */
20    
21     char *cname; /* ppd name */
22    
23     double size[3]; /* ppd size */
24    
25     int rounde = 0; /* round edges? (#segments = 2^rounde) */
26    
27     double bevel = 0.0; /* bevel amount or round edge radius */
28    
29     int rev = 0; /* boolean true for reversed normals */
30    
31     Scene *obj = NULL; /* save as .OBJ scene if not NULL */
32    
33     int vid[0100]; /* vertex ID's for .OBJ scene */
34    
35 greg 1.1
36 greg 2.11 static int
37     overtex(int v) /* index a .OBJ vertex */
38     {
39     double vpos[3];
40     int i;
41 greg 1.1
42 greg 2.11 if (vid[v] >= 0) /* already have this vertex? */
43     return(vid[v]);
44     /* else create new ID */
45     for (i = 0; i < 3; i++)
46     if (v>>i & 010)
47     vpos[i] = (v>>i & 01)^rev ? size[i]-bevel : bevel;
48     else
49     vpos[i] = (v>>i & 01)^rev ? size[i] : 0.0;
50 greg 1.1
51 greg 2.11 return(vid[v] = addVertex(obj, vpos[0], vpos[1], vpos[2]));
52     }
53 greg 1.1
54    
55 greg 2.11 static int
56     onormal(int vid1, int vid2, int vid3) /* index a .OBJ normal */
57     {
58     double *p1 = obj->vert[vid1].p;
59     double *p2 = obj->vert[vid2].p;
60     double *p3 = obj->vert[vid3].p;
61     FVECT sv1, sv2, nrm;
62    
63     VSUB(sv1, p2, p1);
64     VSUB(sv2, p3, p2);
65     VCROSS(nrm, sv1, sv2);
66    
67     return(addNormal(obj, nrm[0], nrm[1], nrm[2]));
68     }
69 greg 1.1
70    
71 schorsch 2.6 static void
72 greg 2.11 vertex(int v) /* print a Radiance vertex */
73 schorsch 2.6 {
74 greg 2.9 int i;
75 schorsch 2.6
76     for (i = 0; i < 3; i++) {
77     if (v & 010)
78 greg 2.11 printf("\t%18.12g", (v&01)^rev ? size[i]-bevel : bevel);
79 schorsch 2.6 else
80 greg 2.11 printf("\t%18.12g", (v&01)^rev ? size[i] : 0.0);
81 schorsch 2.6 v >>= 1;
82     }
83 greg 2.9 fputc('\n', stdout);
84 schorsch 2.6 }
85    
86    
87     static void
88 greg 2.8 side(int a, int b, int c, int d) /* generate a rectangular face */
89 schorsch 2.6 {
90 greg 2.11 if (obj != NULL) { /* working on .OBJ? */
91     VNDX quadv[4];
92     memset(quadv, 0xff, sizeof(quadv));
93     quadv[0][0] = overtex(a);
94     quadv[1][0] = overtex(b);
95     quadv[2][0] = overtex(c);
96     quadv[3][0] = overtex(d);
97     if (rounde) /* add normal if rounded */
98     quadv[0][2] = quadv[1][2] = quadv[2][2] = quadv[3][2]
99     = onormal(quadv[0][0], quadv[1][0], quadv[2][0]);
100     addFace(obj, quadv, 4);
101     return;
102     }
103     /* Radiance output */
104 schorsch 2.6 printf("\n%s polygon %s.%c%c%c%c\n", cmtype, cname,
105     let[a], let[b], let[c], let[d]);
106     printf("0\n0\n12\n");
107 greg 2.10 vertex(a);
108     vertex(b);
109     vertex(c);
110     vertex(d);
111 schorsch 2.6 }
112    
113    
114     static void
115 greg 2.8 corner(int a, int b, int c) /* generate a triangular face */
116 schorsch 2.6 {
117 greg 2.11 if (obj != NULL) { /* working on .OBJ? */
118     VNDX triv[3];
119     memset(triv, 0xff, sizeof(triv));
120     triv[0][0] = overtex(a);
121     triv[1][0] = overtex(b);
122     triv[2][0] = overtex(c);
123     addFace(obj, triv, 3);
124     return;
125     }
126     /* Radiance output */
127 schorsch 2.6 printf("\n%s polygon %s.%c%c%c\n", cmtype, cname,
128     let[a], let[b], let[c]);
129     printf("0\n0\n9\n");
130 greg 2.10 vertex(a);
131     vertex(b);
132     vertex(c);
133 schorsch 2.6 }
134    
135    
136     static void
137 greg 2.11 cylinder(int v0, int v1) /* generate a rounded edge */
138 schorsch 2.6 {
139 greg 2.11 if (obj != NULL) { /* segmenting for .OBJ? */
140     const int nsgn = 1 - 2*rev;
141     const int nseg = 1<<rounde;
142     const double astep = 0.5*PI/(double)nseg;
143     const int vid0 = overtex(v0);
144     const int vid1 = overtex(v1);
145     FVECT p0, p1;
146     FVECT axis[2], voff;
147     int previd[2];
148     int prenid;
149     VNDX quadv[4];
150     double coef[2];
151     int i, j;
152     /* need to copy b/c realloc */
153     VCOPY(p0, obj->vert[vid0].p);
154     VCOPY(p1, obj->vert[vid1].p);
155    
156     memset(axis, 0, sizeof(axis));
157    
158     switch ((v0 ^ v1) & 07) {
159     case 01: /* edge along X-axis */
160     axis[1][1] = bevel*(1. - 2.*(p1[1] < .5*size[1]));
161     axis[0][2] = bevel*(1. - 2.*(p1[2] < .5*size[2]));
162     break;
163     case 02: /* edge along Y-axis */
164     axis[0][0] = bevel*(1. - 2.*(p1[0] < .5*size[0]));
165     axis[1][2] = bevel*(1. - 2.*(p1[2] < .5*size[2]));
166     break;
167     case 04: /* edge along Z-axis */
168     axis[0][1] = bevel*(1. - 2.*(p1[1] < .5*size[1]));
169     axis[1][0] = bevel*(1. - 2.*(p1[0] < .5*size[0]));
170     break;
171     }
172     previd[0] = addVertex(obj, p0[0]+axis[0][0],
173     p0[1]+axis[0][1], p0[2]+axis[0][2]);
174     previd[1] = addVertex(obj, p1[0]+axis[0][0],
175     p1[1]+axis[0][1], p1[2]+axis[0][2]);
176     prenid = addNormal(obj, axis[0][0]*nsgn,
177     axis[0][1]*nsgn, axis[0][2]*nsgn);
178     for (i = 1; i <= nseg; i++) {
179     memset(quadv, 0xff, sizeof(quadv));
180     quadv[0][0] = previd[0];
181     quadv[1][0] = previd[1];
182     quadv[0][2] = quadv[1][2] = prenid;
183     coef[0] = cos(astep*i);
184     coef[1] = sin(astep*i);
185     for (j = 0; j < 3; j++)
186     voff[j] = coef[0]*axis[0][j] + coef[1]*axis[1][j];
187     previd[0] = quadv[3][0]
188     = addVertex(obj, p0[0]+voff[0],
189     p0[1]+voff[1], p0[2]+voff[2]);
190     previd[1] = quadv[2][0]
191     = addVertex(obj, p1[0]+voff[0],
192     p1[1]+voff[1], p1[2]+voff[2]);
193     prenid = quadv[2][2] = quadv[3][2]
194     = addNormal(obj, voff[0]*nsgn,
195     voff[1]*nsgn, voff[2]*nsgn);
196     addFace(obj, quadv, 4);
197     }
198     return;
199     }
200     /* Radiance output */
201     printf("\n%s cylinder %s.%c%c\n", cmtype, cname, let[v0], let[v1]);
202 schorsch 2.6 printf("0\n0\n7\n");
203     vertex(v0);
204     vertex(v1);
205     printf("\t%18.12g\n", bevel);
206     }
207    
208    
209 greg 2.11 static void /* recursive corner subdivision */
210     osubcorner(const FVECT orig, const FVECT c0, const FVECT c1, const FVECT c2, int lvl)
211     {
212     if (lvl-- <= 0) { /* reached terminal depth? */
213     const int nsgn = 1 - 2*rev;
214     FVECT vpos;
215     VNDX triv[3]; /* output smoothed triangle */
216     VSUM(vpos, orig, c0, bevel);
217     triv[0][0] = addVertex(obj, vpos[0], vpos[1], vpos[2]);
218     triv[0][2] = addNormal(obj, c0[0]*nsgn, c0[1]*nsgn, c0[2]*nsgn);
219     VSUM(vpos, orig, c1, bevel);
220     triv[1][0] = addVertex(obj, vpos[0], vpos[1], vpos[2]);
221     triv[1][2] = addNormal(obj, c1[0]*nsgn, c1[1]*nsgn, c1[2]*nsgn);
222     VSUM(vpos, orig, c2, bevel);
223     triv[2][0] = addVertex(obj, vpos[0], vpos[1], vpos[2]);
224     triv[2][2] = addNormal(obj, c2[0]*nsgn, c2[1]*nsgn, c2[2]*nsgn);
225     triv[0][1] = triv[1][1] = triv[2][1] = -1;
226     addFace(obj, triv, 3);
227     } else { /* else subdivide 4 subcorners */
228     FVECT m01, m12, m20;
229     VADD(m01, c0, c1); normalize(m01);
230     VADD(m12, c1, c2); normalize(m12);
231     VADD(m20, c2, c0); normalize(m20);
232     osubcorner(orig, c0, m01, m20, lvl);
233     osubcorner(orig, c1, m12, m01, lvl);
234     osubcorner(orig, c2, m20, m12, lvl);
235     osubcorner(orig, m01, m12, m20, lvl);
236     }
237     }
238    
239    
240 schorsch 2.7 static void
241 greg 2.11 sphere(int v0) /* generate a rounded corner */
242 schorsch 2.6 {
243 greg 2.11 if (obj != NULL) { /* segmenting for .OBJ? */
244     FVECT orig, cdir[3];
245     int i;
246     memset(cdir, 0, sizeof(cdir));
247     for (i = 0; i < 3; i++)
248     cdir[i][i] = 2*((v0>>i & 01)^rev) - 1;
249     switch (v0 & 07) {
250     case 0:
251     case 3:
252     case 5:
253     case 6:
254     VCOPY(orig, cdir[0]);
255     VCOPY(cdir[0], cdir[1]);
256     VCOPY(cdir[1], orig);
257     }
258     i = overtex(v0);
259     VCOPY(orig, obj->vert[i].p); /* realloc remedy */
260     osubcorner(orig, cdir[0], cdir[1], cdir[2], rounde);
261     return;
262     }
263     /* Radiance output */
264     printf("\n%s sphere %s.%c\n", cmtype, cname, let[v0]);
265 schorsch 2.6 printf("0\n0\n4\n");
266     vertex(v0);
267     printf("\t%18.12g\n", bevel);
268     }
269    
270    
271 schorsch 2.7 int
272 greg 2.9 main(int argc, char *argv[])
273 greg 1.1 {
274 greg 2.13 int smooth = 0;
275 greg 2.11 int nsegs = 1;
276     int objout = 0;
277 greg 1.1 int i;
278 greg 2.11
279 greg 1.1 if (argc < 6)
280     goto userr;
281    
282     cmtype = argv[1];
283     cname = argv[2];
284     size[0] = atof(argv[3]);
285     size[1] = atof(argv[4]);
286     size[2] = atof(argv[5]);
287 greg 2.9 if ((size[0] <= 0.0) | (size[1] <= 0.0) | (size[2] <= 0.0))
288     goto userr;
289 greg 1.1
290     for (i = 6; i < argc; i++) {
291     if (argv[i][0] != '-')
292     goto userr;
293     switch (argv[i][1]) {
294 greg 2.11 case 'o': /* requesting .OBJ output */
295     objout = 1;
296 greg 2.9 break;
297 greg 2.11 case 'i': /* invert surface normals */
298     rev = 1;
299     break;
300 greg 2.13 case 's': /* normal smoothing? */
301     smooth = 1;
302     break;
303 greg 2.11 case 'r': /* rounded edges/corners */
304 greg 2.5 rounde = 1;
305 greg 1.1 /* fall through */
306 greg 2.11 case 'b': /* beveled edges */
307 greg 1.1 bevel = atof(argv[++i]);
308 greg 2.11 if (bevel <= 0.0)
309     goto userr;
310     break;
311     case 'n': /* #segments for rounding */
312     nsegs = atoi(argv[++i]);
313     if (nsegs <= 0)
314     goto userr;
315     break;
316 greg 1.1 default:
317     goto userr;
318     }
319     }
320 greg 2.11 if ((objout|rev) & (nsegs==1)) /* default to 32 segments/edge */
321     nsegs = 32;
322     if (rounde) { /* rounding edges/corners? */
323     --nsegs;
324     while ((nsegs >>= 1)) /* segmentation requested? */
325     ++rounde;
326     }
327     if (rounde > 1 || objout) { /* save as .OBJ scene? */
328     obj = newScene();
329     setMaterial(obj, cmtype);
330     setGroup(obj, cname);
331     memset(vid, 0xff, sizeof(vid));
332     }
333     fputs("# ", stdout); /* write command as comment */
334 greg 2.8 printargs(argc, argv, stdout);
335 greg 1.1
336 greg 2.11 if (bevel > 0.0) { /* minor faces */
337 greg 1.1 side(051, 055, 054, 050);
338     side(064, 066, 062, 060);
339     side(032, 033, 031, 030);
340     side(053, 052, 056, 057);
341     side(065, 061, 063, 067);
342     side(036, 034, 035, 037);
343     }
344 greg 2.11 if (bevel > 0.0 && !rounde) { /* bevel faces */
345 greg 1.1 side(031, 051, 050, 030);
346     side(060, 062, 032, 030);
347     side(050, 054, 064, 060);
348     side(034, 036, 066, 064);
349     side(037, 057, 056, 036);
350     side(052, 062, 066, 056);
351     side(052, 053, 033, 032);
352     side(057, 067, 063, 053);
353     side(061, 031, 033, 063);
354     side(065, 067, 037, 035);
355     side(055, 051, 061, 065);
356     side(034, 054, 055, 035);
357 greg 2.11 /* bevel corners */
358 greg 1.1 corner(030, 050, 060);
359     corner(051, 031, 061);
360     corner(032, 062, 052);
361     corner(064, 054, 034);
362     corner(036, 056, 066);
363     corner(065, 035, 055);
364     corner(053, 063, 033);
365     corner(037, 067, 057);
366     }
367 greg 2.11 if (bevel > 0.0 && rounde) { /* round edges */
368 greg 1.1 cylinder(070, 071);
369     cylinder(070, 074);
370     cylinder(070, 072);
371     cylinder(073, 071);
372     cylinder(073, 072);
373     cylinder(073, 077);
374     cylinder(075, 071);
375     cylinder(075, 074);
376     cylinder(075, 077);
377     cylinder(076, 072);
378     cylinder(076, 074);
379     cylinder(076, 077);
380 greg 2.11 /* round corners */
381 greg 1.1 sphere(070);
382     sphere(071);
383     sphere(072);
384     sphere(073);
385     sphere(074);
386     sphere(075);
387     sphere(076);
388     sphere(077);
389     }
390 greg 2.11 if (bevel == 0.0) { /* only need major faces */
391 greg 1.1 side(1, 5, 4, 0);
392     side(4, 6, 2, 0);
393     side(2, 3, 1, 0);
394     side(3, 2, 6, 7);
395     side(5, 1, 3, 7);
396     side(6, 4, 5, 7);
397     }
398 greg 2.11 if (obj != NULL) { /* need to write output? */
399 greg 2.13 if (!smooth)
400     removeNormals(obj, 0, 0);
401 greg 2.11 if (objout) {
402 greg 2.12 if (rounde) /* joins corners to edges */
403     coalesceVertices(obj, 2.*FTINY);
404 greg 2.11 if (toOBJ(obj, stdout) <= 0)
405     return(1);
406     } else if (toRadiance(obj, stdout, 0, 0) <= 0)
407     return(1);
408     /* freeScene(obj); we're exiting, anyway... */
409     }
410 greg 2.8 return(0);
411 greg 1.1 userr:
412     fprintf(stderr, "Usage: %s ", argv[0]);
413     fprintf(stderr, "material name xsize ysize zsize ");
414 greg 2.13 fprintf(stderr, "[-i] [-b bevel | -r round [-n nsegs][-s]] [-o]\n");
415 greg 2.8 return(1);
416 greg 1.1 }