ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/m_clip.c
Revision: 2.13
Committed: Sat May 4 03:14:04 2019 UTC (4 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R3
Changes since 2.12: +2 -2 lines
Log Message:
Minor optimization shouldn't affect behavior

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: m_clip.c,v 2.12 2017/04/08 00:09:35 greg Exp $";
3 #endif
4 /*
5 * m_clip.c - routine for clipped (cut) objects.
6 */
7
8 #include "copyright.h"
9
10 #include "ray.h"
11 #include "rtotypes.h"
12
13 /*
14 * Clipping objects permit holes and sections to be taken out
15 * of other objects.
16 *
17 * The argument is the clipped materials;
18 * the first is used to shade upon exit.
19 *
20 * In the simple case of the first argument being "void", we
21 * just add or subtract (depending on whether we're coming or going)
22 * the list of modifiers to the ray's "newcset", which will then
23 * take over for "clipset" on penetration. Any surface modifier
24 * names found in "clipset" will be treated as invisible in raycont().
25 *
26 * In the more complicated case of a non-void material as the
27 * first argument, we have to backtrack up the ray tree to count
28 * the number of times we've penetrated the front side of one of
29 * the surfaces we care about. This relies on outward-facing
30 * surface normals and closed objects, so is somewhat error-prone.
31 */
32
33
34 int
35 m_clip( /* clip objects from ray */
36 OBJREC *m,
37 RAY *r
38 )
39 {
40 OBJECT cset[MAXSET+1], *modset;
41 OBJECT obj, mod;
42 int entering;
43 int i;
44
45 obj = objndx(m);
46 if ((modset = (OBJECT *)m->os) == NULL) {
47 if (m->oargs.nsargs < 1 || m->oargs.nsargs > MAXSET)
48 objerror(m, USER, "bad # arguments");
49 modset = (OBJECT *)malloc((m->oargs.nsargs+1)*sizeof(OBJECT));
50 if (modset == NULL)
51 error(SYSTEM, "out of memory in m_clip");
52 modset[0] = 0;
53 for (i = 0; i < m->oargs.nsargs; i++) {
54 if (!strcmp(m->oargs.sarg[i], VOIDID))
55 continue;
56 if ((mod = lastmod(obj, m->oargs.sarg[i])) == OVOID) {
57 sprintf(errmsg, "unknown modifier \"%s\"",
58 m->oargs.sarg[i]);
59 objerror(m, WARNING, errmsg);
60 continue;
61 }
62 if (inset(modset, mod)) {
63 objerror(m, WARNING, "duplicate modifier");
64 continue;
65 }
66 insertelem(modset, mod);
67 }
68 m->os = (char *)modset;
69 }
70 if (r == NULL)
71 return(0); /* just initializing */
72 if (r->clipset != NULL)
73 setcopy(cset, r->clipset);
74 else
75 cset[0] = 0;
76
77 entering = (r->rod > 0.0); /* entering clipped region? */
78
79 for (i = modset[0]; i > 0; i--)
80 if (entering) {
81 if (!inset(cset, modset[i])) {
82 if (cset[0] >= MAXSET)
83 error(INTERNAL, "set overflow in m_clip");
84 insertelem(cset, modset[i]);
85 }
86 } else if (inset(cset, modset[i]))
87 deletelem(cset, modset[i]);
88
89 /* compute ray value */
90 r->newcset = cset;
91 if (strcmp(m->oargs.sarg[0], VOIDID)) {
92 int inside = 0;
93 const RAY *rp;
94 /* check for penetration */
95 for (rp = r; rp->parent != NULL; rp = rp->parent)
96 if ((rp->rtype == RAYREFL) & (rp->parent->ro != NULL)
97 && inset(modset, rp->parent->ro->omod)) {
98 if (rp->parent->rod > 0.0)
99 inside++;
100 else
101 inside--;
102 }
103 if (inside > 0) { /* we just hit the object */
104 flipsurface(r);
105 return(rayshade(r, lastmod(obj, m->oargs.sarg[0])));
106 }
107 }
108 raytrans(r); /* else transfer ray */
109 return(1);
110 }