home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include <stdio.h>
- #include "art.h"
- #include "objs.h"
- #include "macro.h"
- #include "gram.h"
-
- extern hlist *fhlist;
-
- extern hlist *(*intersects[])();
-
- extern attr *astackp;
- extern mats *mstackp;
-
- extern object *objectinit();
-
- /*
- * getcsgobj
- *
- * instantiate an object, mark it as being in csg and return it
- */
- object *
- getcsgobj(sym, d)
- symbol *sym;
- details *d;
- {
- object *obj;
-
- obj = objectinit(sym, d);
-
- return(obj);
- }
-
- /*
- * makecsgtree
- *
- * set up a csg object from its tree and details list.
- */
- object *
- makecsgtree(tree)
- csgnode *tree;
- {
- register object *o;
- register csg *c;
-
- switch (tree->type) {
- case CSG_SUB:
- o = (object *)smalloc(sizeof(object));
- c = o->obj.csgt = (csg *)smalloc(sizeof(csg));
- o->type = CSG_SUB;
- c->leftb = FALSE;
- c->rightb = TRUE;
- c->left = makecsgtree(tree->u.branch.left);
- c->right = makecsgtree(tree->u.branch.right);
- c->left->incsg = ADDED;
- c->right->incsg = SUBTRACTED;
-
- /* take bounding box of left */
- o->bb = c->left->bb;
- break;
- case CSG_ADD:
- o = (object *)smalloc(sizeof(object));
- c = o->obj.csgt = (csg *)smalloc(sizeof(csg));
- o->type = CSG_ADD;
- c->leftb = TRUE;
- c->rightb = TRUE;
- c->left = makecsgtree(tree->u.branch.left);
- c->right = makecsgtree(tree->u.branch.right);
- c->left->incsg = ADDED;
- c->right->incsg = ADDED;
-
- if (c->left->bb.max[X] > c->right->bb.max[X])
- o->bb.max[X] = c->left->bb.max[X];
- else
- o->bb.max[X] = c->right->bb.max[X];
- if (c->left->bb.max[Y] > c->right->bb.max[Y])
- o->bb.max[Y] = c->left->bb.max[Y];
- else
- o->bb.max[Y] = c->right->bb.max[Y];
- if (c->left->bb.max[Z] > c->right->bb.max[Z])
- o->bb.max[Z] = c->left->bb.max[Z];
- else
- o->bb.max[Z] = c->right->bb.max[Z];
-
- if (c->left->bb.min[X] < c->right->bb.min[X])
- o->bb.min[X] = c->left->bb.min[X];
- else
- o->bb.min[X] = c->right->bb.min[X];
- if (c->left->bb.min[Y] < c->right->bb.min[Y])
- o->bb.min[Y] = c->left->bb.min[Y];
- else
- o->bb.min[Y] = c->right->bb.min[Y];
- if (c->left->bb.min[Z] < c->right->bb.min[Z])
- o->bb.min[Z] = c->left->bb.min[Z];
- else
- o->bb.min[Z] = c->right->bb.min[Z];
- break;
- case CSG_INT:
- o = (object *)smalloc(sizeof(object));
- c = o->obj.csgt = (csg *)smalloc(sizeof(csg));
- o->type = CSG_INT;
- c->leftb = FALSE;
- c->rightb = FALSE;
- c->left = makecsgtree(tree->u.branch.left);
- c->right = makecsgtree(tree->u.branch.right);
- c->left->incsg = ADDED;
- c->right->incsg = ADDED;
-
- /* take overlap */
- if (c->left->bb.max[X] < c->right->bb.max[X])
- o->bb.max[X] = c->left->bb.max[X];
- else
- o->bb.max[X] = c->right->bb.max[X];
- if (c->left->bb.max[Y] < c->right->bb.max[Y])
- o->bb.max[Y] = c->left->bb.max[Y];
- else
- o->bb.max[Y] = c->right->bb.max[Y];
- if (c->left->bb.max[Z] < c->right->bb.max[Z])
- o->bb.max[Z] = c->left->bb.max[Z];
- else
- o->bb.max[Z] = c->right->bb.max[Z];
-
- if (c->left->bb.min[X] > c->right->bb.min[X])
- o->bb.min[X] = c->left->bb.min[X];
- else
- o->bb.min[X] = c->right->bb.min[X];
- if (c->left->bb.min[Y] > c->right->bb.min[Y])
- o->bb.min[Y] = c->left->bb.min[Y];
- else
- o->bb.min[Y] = c->right->bb.min[Y];
- if (c->left->bb.min[Z] > c->right->bb.min[Z])
- o->bb.min[Z] = c->left->bb.min[Z];
- else
- o->bb.min[Z] = c->right->bb.min[Z];
- break;
- case OBJECT:
- o = getcsgobj(tree->u.sym, (details *)NULL);
- break;
- default:
- fatal("art: illegal type in csgtree.\n");
-
- }
-
- o->nxt = (object *)NULL;
-
- return(o);
- }
-
- /*
- * csginit
- *
- * initialise a csg object
- *
- */
- object *
- csginit(sym, d)
- symbol *sym;
- details *d;
- {
- details *dl, *nxtdl, *argdt, *otherdt, *nd;
- object *o;
- surface s;
- int sset;
-
- astackp++;
- *astackp = *(astackp - 1);
-
- mstackp++;
- *mstackp = *(mstackp - 1);
- mident4(mstackp->vm);
-
- s = *astackp->s;
- /* reverse list */
- argdt = (details *)NULL;
- for (dl = d; dl != (details *)NULL; dl = nxtdl) {
- nxtdl = dl->nxt;
- dl->nxt = argdt;
- argdt = dl;
- }
-
- /* copy sym list */
- otherdt = (details *)NULL;
- for (dl = sym->u.det->u.csgobj.det; dl != (details *)NULL; dl = dl->nxt) {
- nd = (details *)smalloc(sizeof(details));
- *nd = *dl;
- nd->nxt = otherdt;
- otherdt = nd;
- }
-
- if (argdt == (details *)NULL) {
- argdt = otherdt;
- otherdt = (details *)NULL;
- }
-
- sset = FALSE;
-
- for (dl = argdt; dl != (details *)NULL; dl = nxtdl) {
- switch (dl->type) {
- case COLOUR:
- s.c.r = dl->u.c.r;
- s.c.g = dl->u.c.g;
- s.c.b = dl->u.c.b;
- sset = TRUE;
- break;
- case AMBIENT:
- s.a.r = dl->u.c.r;
- s.a.g = dl->u.c.g;
- s.a.b = dl->u.c.b;
- sset = TRUE;
- break;
- case TEXTURE:
- dl->u.txt->nxt = astackp->txtlist;
- astackp->txtlist = dl->u.txt;
- break;
- case MATERIAL:
- s.ri = dl->u.mat.ri;
- s.kd = dl->u.mat.kd;
- s.ks = dl->u.mat.ks;
- s.ksexp = dl->u.mat.ksexp;
- sset = TRUE;
- break;
- case REFLECTANCE:
- s.refl = dl->u.f;
- sset = TRUE;
- break;
- case TRANSPARENCY:
- s.trans = dl->u.f;
- sset = TRUE;
- break;
- case ABSORPTION:
- s.falloff = dl->u.f;
- sset = TRUE;
- break;
- case ART_TRANSLATE:
- art_translate(dl->u.v.x, dl->u.v.y, dl->u.v.z);
- break;
- case ART_SCALE:
- art_scale(dl->u.v.x, dl->u.v.y, dl->u.v.z);
- break;
- case ART_ROTATE:
- art_rotate(dl->u.rot.ang, dl->u.rot.axis);
- break;
- case ON:
- astackp->options |= dl->u.i;
- break;
- case OFF:
- astackp->options &= ~dl->u.i;
- break;
- case CSG_OBJ:
- case OBJECT:
- break;
- default:
- warning("art: bad detail in csg ignored.\n");
- }
-
- nxtdl = dl->nxt;
- if (nxtdl == (details *)NULL) {
- nxtdl = otherdt;
- otherdt = (details *)NULL;
- }
-
- free(dl);
- }
-
- if (sset) {
- astackp->s = (surface *)smalloc(sizeof(surface));
- *astackp->s = s;
- }
-
- o = makecsgtree(sym->u.det->u.csgobj.tree);
-
- astackp--;
- mstackp--;
-
- return(o);
- }
-
-