| 1 | #ifndef lint | 
| 2 | static const char       RCSid[] = "$Id: m_clip.c,v 2.8 2004/03/30 16:13:01 schorsch 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.  The method is simple: | 
| 16 | * | 
| 17 | *  The argument is the clipped materials; | 
| 18 | *  the first is used to shade upon exit. | 
| 19 | */ | 
| 20 |  | 
| 21 |  | 
| 22 | extern int | 
| 23 | m_clip(                 /* clip objects from ray */ | 
| 24 | register OBJREC  *m, | 
| 25 | register RAY  *r | 
| 26 | ) | 
| 27 | { | 
| 28 | OBJECT  cset[MAXSET+1], *modset; | 
| 29 | OBJECT  obj, mod; | 
| 30 | int  entering; | 
| 31 | register int  i; | 
| 32 |  | 
| 33 | obj = objndx(m); | 
| 34 | if ((modset = (OBJECT *)m->os) == NULL) { | 
| 35 | if (m->oargs.nsargs < 1 || m->oargs.nsargs > MAXSET) | 
| 36 | objerror(m, USER, "bad # arguments"); | 
| 37 | modset = (OBJECT *)malloc((m->oargs.nsargs+1)*sizeof(OBJECT)); | 
| 38 | if (modset == NULL) | 
| 39 | error(SYSTEM, "out of memory in m_clip"); | 
| 40 | modset[0] = 0; | 
| 41 | for (i = 0; i < m->oargs.nsargs; i++) { | 
| 42 | if (!strcmp(m->oargs.sarg[i], VOIDID)) | 
| 43 | continue; | 
| 44 | if ((mod = lastmod(obj, m->oargs.sarg[i])) == OVOID) { | 
| 45 | sprintf(errmsg, "unknown modifier \"%s\"", | 
| 46 | m->oargs.sarg[i]); | 
| 47 | objerror(m, WARNING, errmsg); | 
| 48 | continue; | 
| 49 | } | 
| 50 | if (inset(modset, mod)) { | 
| 51 | objerror(m, WARNING, "duplicate modifier"); | 
| 52 | continue; | 
| 53 | } | 
| 54 | insertelem(modset, mod); | 
| 55 | } | 
| 56 | m->os = (char *)modset; | 
| 57 | } | 
| 58 | if (r->clipset != NULL) | 
| 59 | setcopy(cset, r->clipset); | 
| 60 | else | 
| 61 | cset[0] = 0; | 
| 62 |  | 
| 63 | entering = r->rod > 0.0;                /* entering clipped region? */ | 
| 64 |  | 
| 65 | for (i = modset[0]; i > 0; i--) { | 
| 66 | if (entering) { | 
| 67 | if (!inset(cset, modset[i])) { | 
| 68 | if (cset[0] >= MAXSET) | 
| 69 | error(INTERNAL, "set overflow in m_clip"); | 
| 70 | insertelem(cset, modset[i]); | 
| 71 | } | 
| 72 | } else { | 
| 73 | if (inset(cset, modset[i])) | 
| 74 | deletelem(cset, modset[i]); | 
| 75 | } | 
| 76 | } | 
| 77 | /* compute ray value */ | 
| 78 | r->newcset = cset; | 
| 79 | if (strcmp(m->oargs.sarg[0], VOIDID)) { | 
| 80 | int  inside = 0; | 
| 81 | register const RAY  *rp; | 
| 82 | /* check for penetration */ | 
| 83 | for (rp = r; rp->parent != NULL; rp = rp->parent) | 
| 84 | if (!(rp->rtype & RAYREFL) && rp->parent->ro != NULL | 
| 85 | && inset(modset, rp->parent->ro->omod)) { | 
| 86 | if (rp->parent->rod > 0.0) | 
| 87 | inside++; | 
| 88 | else | 
| 89 | inside--; | 
| 90 | } | 
| 91 | if (inside > 0) {       /* we just hit the object */ | 
| 92 | flipsurface(r); | 
| 93 | return(rayshade(r, lastmod(obj, m->oargs.sarg[0]))); | 
| 94 | } | 
| 95 | } | 
| 96 | raytrans(r);                    /* else transfer ray */ | 
| 97 | return(1); | 
| 98 | } |