ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/genbox.c
Revision: 2.15
Committed: Sat Jun 7 05:09:45 2025 UTC (18 hours, 35 minutes ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.14: +2 -2 lines
Log Message:
refactor: Put some declarations into "paths.h" and included in "platform.h"

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: genbox.c,v 2.14 2025/06/06 19:11:21 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 "paths.h"
14
15 int verbose = 0;
16
17 char let[]="0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
18
19 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
36 static int
37 overtex(int v) /* index a .OBJ vertex */
38 {
39 double vpos[3];
40 int i;
41
42 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
51 return(vid[v] = addVertex(obj, vpos[0], vpos[1], vpos[2]));
52 }
53
54
55 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
70
71 static void
72 vertex(int v) /* print a Radiance vertex */
73 {
74 int i;
75
76 for (i = 0; i < 3; i++) {
77 if (v & 010)
78 printf("\t%18.12g", (v&01)^rev ? size[i]-bevel : bevel);
79 else
80 printf("\t%18.12g", (v&01)^rev ? size[i] : 0.0);
81 v >>= 1;
82 }
83 fputc('\n', stdout);
84 }
85
86
87 static void
88 side(int a, int b, int c, int d) /* generate a rectangular face */
89 {
90 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 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 vertex(a);
108 vertex(b);
109 vertex(c);
110 vertex(d);
111 }
112
113
114 static void
115 corner(int a, int b, int c) /* generate a triangular face */
116 {
117 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 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 vertex(a);
131 vertex(b);
132 vertex(c);
133 }
134
135
136 static void
137 cylinder(int v0, int v1) /* generate a rounded edge */
138 {
139 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 printf("0\n0\n7\n");
203 vertex(v0);
204 vertex(v1);
205 printf("\t%18.12g\n", bevel);
206 }
207
208
209 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 static void
241 sphere(int v0) /* generate a rounded corner */
242 {
243 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 printf("0\n0\n4\n");
266 vertex(v0);
267 printf("\t%18.12g\n", bevel);
268 }
269
270
271 int
272 main(int argc, char *argv[])
273 {
274 int smooth = 0;
275 int nsegs = 1;
276 int objout = 0;
277 int i;
278
279 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 if ((size[0] <= 0.0) | (size[1] <= 0.0) | (size[2] <= 0.0))
288 goto userr;
289
290 for (i = 6; i < argc; i++) {
291 if (argv[i][0] != '-')
292 goto userr;
293 switch (argv[i][1]) {
294 case 'o': /* requesting .OBJ output */
295 objout = 1;
296 break;
297 case 'i': /* invert surface normals */
298 rev = 1;
299 break;
300 case 's': /* normal smoothing? */
301 smooth = 1;
302 break;
303 case 'r': /* rounded edges/corners */
304 rounde = 1;
305 /* fall through */
306 case 'b': /* beveled edges */
307 bevel = atof(argv[++i]);
308 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 default:
317 goto userr;
318 }
319 }
320 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 printargs(argc, argv, stdout);
335
336 if (bevel > 0.0) { /* minor faces */
337 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 if (bevel > 0.0 && !rounde) { /* bevel faces */
345 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 /* bevel corners */
358 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 if (bevel > 0.0 && rounde) { /* round edges */
368 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 /* round corners */
381 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 if (bevel == 0.0) { /* only need major faces */
391 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 if (obj != NULL) { /* need to write output? */
399 if (!smooth)
400 removeNormals(obj, 0, 0);
401 if (objout) {
402 if (rounde) /* joins corners to edges */
403 coalesceVertices(obj, 2.*FTINY);
404 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 return(0);
411 userr:
412 fprintf(stderr, "Usage: %s ", argv[0]);
413 fprintf(stderr, "material name xsize ysize zsize ");
414 fprintf(stderr, "[-i] [-b bevel | -r round [-n nsegs][-s]] [-o]\n");
415 return(1);
416 }