ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/genbox.c
Revision: 2.12
Committed: Fri Apr 9 18:52:57 2021 UTC (3 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.11: +3 -2 lines
Log Message:
perf: removed unnecessary call for non-round edges and .OBJ output

File Contents

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