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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: genbox.c,v 2.11 2021/04/09 01:48:20 greg Exp $";
3 #endif
4 /*
5 * genbox.c - generate a parallelepiped.
6 *
7 * 1/8/86
8 */
9
10 #include "rtio.h"
11 #include "rtmath.h"
12 #include "objutil.h"
13 #include <stdlib.h>
14
15
16 char *progname;
17
18 int verbose = 0;
19
20 char let[]="0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
21
22 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
39 static int
40 overtex(int v) /* index a .OBJ vertex */
41 {
42 double vpos[3];
43 int i;
44
45 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
54 return(vid[v] = addVertex(obj, vpos[0], vpos[1], vpos[2]));
55 }
56
57
58 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
73
74 static void
75 vertex(int v) /* print a Radiance vertex */
76 {
77 int i;
78
79 for (i = 0; i < 3; i++) {
80 if (v & 010)
81 printf("\t%18.12g", (v&01)^rev ? size[i]-bevel : bevel);
82 else
83 printf("\t%18.12g", (v&01)^rev ? size[i] : 0.0);
84 v >>= 1;
85 }
86 fputc('\n', stdout);
87 }
88
89
90 static void
91 side(int a, int b, int c, int d) /* generate a rectangular face */
92 {
93 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 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 vertex(a);
111 vertex(b);
112 vertex(c);
113 vertex(d);
114 }
115
116
117 static void
118 corner(int a, int b, int c) /* generate a triangular face */
119 {
120 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 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 vertex(a);
134 vertex(b);
135 vertex(c);
136 }
137
138
139 static void
140 cylinder(int v0, int v1) /* generate a rounded edge */
141 {
142 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 printf("0\n0\n7\n");
206 vertex(v0);
207 vertex(v1);
208 printf("\t%18.12g\n", bevel);
209 }
210
211
212 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 static void
244 sphere(int v0) /* generate a rounded corner */
245 {
246 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 printf("0\n0\n4\n");
269 vertex(v0);
270 printf("\t%18.12g\n", bevel);
271 }
272
273
274 int
275 main(int argc, char *argv[])
276 {
277 int nsegs = 1;
278 int objout = 0;
279 int i;
280
281 progname = argv[0];
282
283 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 if ((size[0] <= 0.0) | (size[1] <= 0.0) | (size[2] <= 0.0))
292 goto userr;
293
294 for (i = 6; i < argc; i++) {
295 if (argv[i][0] != '-')
296 goto userr;
297 switch (argv[i][1]) {
298 case 'o': /* requesting .OBJ output */
299 objout = 1;
300 break;
301 case 'i': /* invert surface normals */
302 rev = 1;
303 break;
304 case 'r': /* rounded edges/corners */
305 rounde = 1;
306 /* fall through */
307 case 'b': /* beveled edges */
308 bevel = atof(argv[++i]);
309 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 default:
318 goto userr;
319 }
320 }
321 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 printargs(argc, argv, stdout);
336
337 if (bevel > 0.0) { /* minor faces */
338 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 if (bevel > 0.0 && !rounde) { /* bevel faces */
346 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 /* bevel corners */
359 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 if (bevel > 0.0 && rounde) { /* round edges */
369 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 /* round corners */
382 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 if (bevel == 0.0) { /* only need major faces */
392 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 if (obj != NULL) { /* need to write output? */
400 if (objout) {
401 if (rounde) /* joins corners to edges */
402 coalesceVertices(obj, 2.*FTINY);
403 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 return(0);
410 userr:
411 fprintf(stderr, "Usage: %s ", argv[0]);
412 fprintf(stderr, "material name xsize ysize zsize ");
413 fprintf(stderr, "[-i] [-b bevel | -r round [-n nsegs]] [-o]\n");
414 return(1);
415 }