ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/genbox.c
(Generate patch)

Comparing ray/src/gen/genbox.c (file contents):
Revision 2.10 by greg, Thu Apr 8 15:13:08 2021 UTC vs.
Revision 2.11 by greg, Fri Apr 9 01:48:20 2021 UTC

# Line 8 | Line 8 | static const char      RCSid[] = "$Id$";
8   */
9  
10   #include  "rtio.h"
11 + #include  "rtmath.h"
12 + #include  "objutil.h"
13   #include  <stdlib.h>
12 #include  <math.h>
14  
15  
16 + char    *progname;
17 +
18 + int     verbose = 0;
19 +
20   char  let[]="0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
21  
22 < char  *cmtype;          /* ppd material type */
22 > char    *cmtype;                /* ppd material type */
23  
24 < char  *cname;           /* ppd name */
24 > char    *cname;         /* ppd name */
25  
26 < double  size[3];        /* ppd size */
26 > double  size[3];        /* ppd size */
27  
28 < double  bevel = 0.0;    /* bevel amount */
28 > int     rounde = 0;     /* round edges? (#segments = 2^rounde) */
29  
30 < int  rounde = 0;        /* boolean true for round edges */
30 > double  bevel = 0.0;    /* bevel amount or round edge radius */
31  
32 < int  reverse = 0;       /* boolean true for reversed normals */
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)
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)^reverse ? size[i]-bevel : bevel);
81 >                        printf("\t%18.12g", (v&01)^rev ? size[i]-bevel : bevel);
82                  else
83 <                        printf("\t%18.12g", (v&01)^reverse ? size[i] : 0.0);
83 >                        printf("\t%18.12g", (v&01)^rev ? size[i] : 0.0);
84                  v >>= 1;
85          }
86          fputc('\n', stdout);
# Line 46 | Line 90 | vertex(int v)
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");
# Line 59 | Line 117 | side(int a, int b, int c, int d)               /* generate a rectan
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");
# Line 69 | Line 137 | corner(int a, int b, int c)                    /* generate a triangular
137  
138  
139   static void
140 < cylinder(int v0, int v1)                /* generate a cylinder */
140 > cylinder(int v0, int v1)                        /* generate a rounded edge */
141   {
142 <        printf("\n%s cylinder %s.%c%c\n", cmtype, cname, v0+'0', v1+'0');
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);
# Line 79 | Line 209 | cylinder(int v0, int v1)               /* generate a cylinder */
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 sphere */
244 > sphere(int v0)                                  /* generate a rounded corner */
245   {
246 <        printf("\n%s sphere %s.%c\n", cmtype, cname, v0+'0');
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);
# Line 92 | Line 274 | sphere(int v0)                 /* generate a sphere */
274   int
275   main(int argc, char *argv[])
276   {
277 +        int  nsegs = 1;
278 +        int  objout = 0;
279          int  i;
280 <        
280 >
281 >        progname = argv[0];
282 >
283          if (argc < 6)
284                  goto userr;
285  
# Line 109 | Line 295 | main(int argc, char *argv[])
295                  if (argv[i][0] != '-')
296                          goto userr;
297                  switch (argv[i][1]) {
298 <                case 'i':
299 <                        reverse = 1;
298 >                case 'o':                       /* requesting .OBJ output */
299 >                        objout = 1;
300                          break;
301 <                case 'r':
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':
307 >                case 'b':                       /* beveled edges */
308                          bevel = atof(argv[++i]);
309 <                        if (bevel > 0.0)
310 <                                break;
311 <                        /* fall through on error */
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 (rounde & reverse)
322 <                fprintf(stderr, "%s: warning - option -i ignored with -r\n",
323 <                                argv[0]);
324 <
325 <        fputs("# ", stdout);
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) {
135 <                                        /* minor faces */
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);
# Line 140 | Line 342 | main(int argc, char *argv[])
342                  side(065, 061, 063, 067);
343                  side(036, 034, 035, 037);
344          }
345 <        if (bevel > 0.0 && !rounde) {
144 <                                        /* bevel faces */
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);
# Line 154 | Line 355 | main(int argc, char *argv[])
355                  side(065, 067, 037, 035);
356                  side(055, 051, 061, 065);
357                  side(034, 054, 055, 035);
358 <                                        /* bevel corners */
358 >                                                /* bevel corners */
359                  corner(030, 050, 060);
360                  corner(051, 031, 061);
361                  corner(032, 062, 052);
# Line 164 | Line 365 | main(int argc, char *argv[])
365                  corner(053, 063, 033);
366                  corner(037, 067, 057);
367          }
368 <        if (bevel > 0.0 && rounde) {
168 <                                        /* round edges */
368 >        if (bevel > 0.0 && rounde) {            /* round edges */
369                  cylinder(070, 071);
370                  cylinder(070, 074);
371                  cylinder(070, 072);
# Line 178 | Line 378 | main(int argc, char *argv[])
378                  cylinder(076, 072);
379                  cylinder(076, 074);
380                  cylinder(076, 077);
381 <                                        /* round corners */
381 >                                                /* round corners */
382                  sphere(070);
383                  sphere(071);
384                  sphere(072);
# Line 188 | Line 388 | main(int argc, char *argv[])
388                  sphere(076);
389                  sphere(077);
390          }
391 <        if (bevel == 0.0) {
192 <                                        /* only need major faces */
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);
# Line 197 | Line 396 | main(int argc, char *argv[])
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 +                        coalesceVertices(obj, 2.*FTINY);
402 +                        if (toOBJ(obj, stdout) <= 0)
403 +                                return(1);
404 +                } else if (toRadiance(obj, stdout, 0, 0) <= 0)
405 +                        return(1);
406 +                /* freeScene(obj);      we're exiting, anyway... */
407 +        }
408          return(0);
409   userr:
410          fprintf(stderr, "Usage: %s ", argv[0]);
411          fprintf(stderr, "material name xsize ysize zsize ");
412 <        fprintf(stderr, "[-i] [-b bevel | -r round]\n");
412 >        fprintf(stderr, "[-i] [-b bevel | -r round [-n nsegs]] [-o]\n");
413          return(1);
414   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines