home *** CD-ROM | disk | FTP | other *** search
- /*
- * Macobject.c
- *
- * Purpose: A collection of routines that construct wireframe representations of each object
- * type
- *
- */
- #include "common.h"
- #include "geom.h"
- #include "list.h"
- #include "grid.h"
- #include "sampling.h"
- #include "csg.h"
- #include "sphere.h"
- #include "box.h"
- #include "triangle.h"
- #include "disc.h"
- #include "blob.h"
- #include "torus.h"
- #include "plane.h"
- #include "cone.h"
- #include "cylinder.h"
- #include "sampling.h"
- #include "hf.h"
- #include "csg.h"
- #include "instance.h"
- #include "poly.h"
- #include "surface.h"
-
- #include "rotate.h"
-
- #include "macobject.h"
- #include "maceditor.h"
-
- void DisplayWireObject(register char viewdir,register Geom *obj,register Surface *surf);
- extern void DisplayHfObject(Hf *hf, char viewdir) ;
-
- extern Geom *hiliteobject ;
- extern unsigned long FilterFlags ;
- extern Float zoom;
-
- WireObject *theObject = NULL ;
- Trans *transforms[MAXTRANSFORMS] ;
- short transdepth ;
-
- static Vector zaxis = {0.,0.,1.};
- static Geom *objectstack[500] ;
- static short objectnum ;
-
- /* Now for a recursive routine to magically draw all of the objects in the world */
- void DrawObject(register Geom *object, register Surface *surf, register char viewdir)
- {
- register Geom *daughter ;
- register char transet ;
- List *list ;
- Grid *grid ;
- Surface *surf2 ;
-
- /* Since transformations are applied to all children, we will alter the value of transform
- * based upon the parents transformation data
- */
-
- if(!object) return ;
- if(object->trans) {
- transforms[transdepth] = object->trans ;
- transdepth++ ;
- transet = 1 ;
- }
- else
- transet = 0 ;
-
- surf2 = (object->surf) ? object->surf : surf;
- switch(ObjectType(object)) {
- case CSG:
- if(!FILTER_SET(F_CSG)) {
- DrawObject(((Csg *)object->obj)->obj1,surf2,viewdir) ;
- DrawObject(((Csg *)object->obj)->obj2,surf2,viewdir) ;
- }
- break ;
- case LIST:
- if(!FILTER_SET(F_LIST)) {
- list = object->obj ;
- for(daughter = list->list ; daughter ; daughter = daughter->next)
- DrawObject(daughter,surf2,viewdir) ;
- for(daughter = list->unbounded ; daughter ; daughter = daughter->next)
- DrawObject(daughter,surf2,viewdir) ;
- }
- break ;
- case GRID:
- if(!FILTER_SET(F_GRID)) {
- grid = object->obj ;
- for(daughter = grid->unbounded ; daughter ; daughter = daughter->next)
- DrawObject(daughter,surf2,viewdir) ;
- for(daughter = grid->objects ; daughter ; daughter = daughter->next)
- DrawObject(daughter,surf2,viewdir) ;
- }
- break ;
- case INSTANCE:
- if(!FILTER_SET(F_INSTANCE))
- DrawObject(((Instance *)object->obj)->obj,surf2,viewdir) ;
- break ;
- case PLANE:
- if(!FILTER_SET(F_PLANE)) {
- CreateWirePlane((Plane *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case SPHERE:
- if(!FILTER_SET(F_SPHERE)) {
- CreateWireSphere((Sphere *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case CONE:
- if(!FILTER_SET(F_CONE)) {
- CreateWireCone((Cone *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case BOX:
- if(!FILTER_SET(F_BOX)) {
- CreateWireBox((Box *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case TORUS:
- if(!FILTER_SET(F_TORUS)) {
- CreateWireTorus((Torus *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case BLOB:
- if(!FILTER_SET(F_BLOB)) {
- register short i;
- Blob *blob;
-
- blob = (Blob *) object->obj;
- /* Generate each metaball in turn */
- for(i = 0 ; i < blob->num ; i++) {
- CreateWireMetaBall(&blob->list[i]) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- }
- break ;
- case DISC:
- if(!FILTER_SET(F_DISC)) {
- CreateWireDisc((Disc *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case TRIANGLE:
- if(!FILTER_SET(F_TRIANGLE)) {
- CreateWireTriangle((Triangle *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case POLYGON:
- if(!FILTER_SET(F_POLYGON)) {
- CreateWirePolygon((RPolygon *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- case HF:
- if(!FILTER_SET(F_HF))
- DisplayHfObject((Hf *)object->obj, viewdir) ;
- break ;
- case CYLINDER:
- if(!FILTER_SET(F_CYLINDER)) {
- CreateWireCylinder((Cylinder *)object->obj) ;
- DisplayWireObject(viewdir,object,surf2) ;
- }
- break ;
- }
- if(transet) transdepth-- ;
- }
-
-
- void InitWireFrame()
- {
- theObject = malloc(sizeof(WireObject)) ;
- }
-
- void RemoveWireFrame()
- {
- free((void *)theObject) ;
- }
-
- void ResetWireObject()
- {
- /* Clean the array */
- memset((void *)theObject->edge_array,0,(size_t)MAXPOINTS*MAXPOINTS) ;
- theObject->numpoints = 0 ;
- }
-
-
- void WireFrameTransform(Trans *trans)
- {
- register short loop ;
-
- while(trans) {
- for(loop = 0 ; loop < theObject->numpoints ; loop++)
- PointTransform(&theObject->points[loop],&trans->trans) ;
- trans = trans->next ;
- }
- }
-
- void CreateWirePlane(register Plane *plane)
- {
- register short loop ;
- Float theta, costheta;
- Vector axis;
- RSMatrix mat;
-
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
- theObject->points[0].x = -1000./zoom ;
- theObject->points[0].y = -1000./zoom ;
- theObject->points[0].z = 0 ;
-
- theObject->points[1].x = -1000./zoom ;
- theObject->points[1].y = 1000./zoom;
- theObject->points[1].z = 0 ;
-
- theObject->points[2].x = 1000./zoom ;
- theObject->points[2].y = 1000./zoom ;
- theObject->points[2].z = 0;
-
- theObject->points[3].x = 1000./zoom ;
- theObject->points[3].y = -1000./zoom;
- theObject->points[3].z = 0 ;
-
- EDGE_BETWEEN(0,1) = 1 ;
- EDGE_BETWEEN(1,2) = 1 ;
- EDGE_BETWEEN(2,3) = 1 ;
- EDGE_BETWEEN(3,0) = 1 ;
- EDGE_BETWEEN(0,2) = 1 ;
- EDGE_BETWEEN(1,3) = 1 ;
- theObject->numpoints = 4 ;
-
- VecNormalize(&plane->norm);
-
- costheta = dotp(&plane->norm,&zaxis);
- if(!equal(fabs(costheta),1.)) {
- theta = acos(costheta);
- VecNormCross(&zaxis,&plane->norm,&axis);
- MatrixInit(&mat);
- RotationMatrix(axis.x,axis.y,axis.z,theta,&mat);
- for(loop = 0 ; loop < theObject->numpoints ; loop++) {
- PointTransform(&theObject->points[loop],&mat);
- }
- }
- for(loop = 0 ; loop < theObject->numpoints ; loop++) {
- theObject->points[loop].x += plane->pos.x;
- theObject->points[loop].y += plane->pos.y;
- theObject->points[loop].z += plane->pos.z;
- }
- }
-
- void CreateWireBox(register Box *box)
- {
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
-
- theObject->points[0].x = box->bounds[0][0] ;
- theObject->points[0].y = box->bounds[0][1] ;
- theObject->points[0].z = box->bounds[0][2] ;
-
- theObject->points[1].x = box->bounds[1][0] ;
- theObject->points[1].y = box->bounds[0][1] ;
- theObject->points[1].z = box->bounds[0][2] ;
-
- theObject->points[2].x = box->bounds[1][0] ;
- theObject->points[2].y = box->bounds[0][1] ;
- theObject->points[2].z = box->bounds[1][2] ;
-
- theObject->points[3].x = box->bounds[0][0] ;
- theObject->points[3].y = box->bounds[0][1] ;
- theObject->points[3].z = box->bounds[1][2] ;
-
- theObject->points[4].x = box->bounds[0][0] ;
- theObject->points[4].y = box->bounds[1][1] ;
- theObject->points[4].z = box->bounds[0][2] ;
-
- theObject->points[5].x = box->bounds[1][0] ;
- theObject->points[5].y = box->bounds[1][1] ;
- theObject->points[5].z = box->bounds[0][2] ;
-
- theObject->points[6].x = box->bounds[1][0] ;
- theObject->points[6].y = box->bounds[1][1] ;
- theObject->points[6].z = box->bounds[1][2] ;
-
- theObject->points[7].x = box->bounds[0][0] ;
- theObject->points[7].y = box->bounds[1][1] ;
- theObject->points[7].z = box->bounds[1][2] ;
-
- EDGE_BETWEEN(0,1) = 1 ;
- EDGE_BETWEEN(0,3) = 1 ;
- EDGE_BETWEEN(0,4) = 1 ;
- EDGE_BETWEEN(1,2) = 1 ;
- EDGE_BETWEEN(1,5) = 1 ;
- EDGE_BETWEEN(2,3) = 1 ;
- EDGE_BETWEEN(2,6) = 1 ;
- EDGE_BETWEEN(3,7) = 1 ;
- EDGE_BETWEEN(4,5) = 1 ;
- EDGE_BETWEEN(4,7) = 1 ;
- EDGE_BETWEEN(5,6) = 1 ;
- EDGE_BETWEEN(6,7) = 1 ;
-
- theObject->numpoints = 8 ;
- }
-
- void CreateWireTriangle(register Triangle *tri)
- {
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
- theObject->points[0] = tri->p[0] ;
- theObject->points[1] = tri->p[1] ;
- theObject->points[2] = tri->p[2] ;
- EDGE_BETWEEN(0,1) = 1 ;
- EDGE_BETWEEN(1,2) = 1 ;
- EDGE_BETWEEN(2,0) = 1 ;
- theObject->numpoints = 3 ;
- }
-
- void CreateWirePolygon(register RPolygon *poly)
- {
- register short loop ;
-
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
- for(loop = 0 ; loop < poly->npoints ; loop++) {
- theObject->points[loop] = poly->points[loop] ;
- EDGE_BETWEEN(loop, (loop == poly->npoints-1) ? 0 : loop+1) = 1 ;
- }
- theObject->numpoints = poly->npoints ;
- }
-
- void CreateWireDisc(register Disc *disc)
- {
- register short loop, point ;
- Float theta, costheta;
- Vector axis;
- RSMatrix mat;
-
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
- point = 0 ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = disc->radius * sin(deg2rad(loop)) ;
- theObject->points[point].y = disc->radius * cos(deg2rad(loop)) ;
- theObject->points[point].z = 0 ;
- EDGE_BETWEEN(point, (point == 11) ? 0 : point+1) = 1 ;
- point++ ;
- }
- theObject->numpoints = point ;
-
- /* We have created a proto disc, nor we must rotate so that it correctly displayed */
-
- VecNormalize(&disc->norm);
- costheta = dotp(&disc->norm,&zaxis);
- if(!equal(fabs(costheta),1.)) {
- theta = acos(costheta);
- VecNormCross(&zaxis,&disc->norm,&axis);
- MatrixInit(&mat);
- RotationMatrix(axis.x,axis.y,axis.z,theta,&mat);
- for(loop = 0 ; loop < point ; loop++) {
- PointTransform(&theObject->points[loop],&mat);
- }
- }
- for(loop = 0 ; loop < point ; loop++) {
- theObject->points[loop].x += disc->pos.x;
- theObject->points[loop].y += disc->pos.y;
- theObject->points[loop].z += disc->pos.z;
- }
- }
-
- void CreateWireMetaBall(register MetaVector *mv)
- {
- register short loop, point ;
- Float radius;
-
- radius = sqrt(mv->rs);
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
- point = 0 ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = mv->x + radius*sin(deg2rad(loop)) ;
- theObject->points[point].y = mv->y + radius*cos(deg2rad(loop)) ;
- theObject->points[point].z = mv->z ;
- EDGE_BETWEEN(point,(point!=11) ? point+1 : 0) = 1 ;
- point++ ;
- }
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = mv->x + radius*sin(deg2rad(loop)) ;
- theObject->points[point].y = mv->y ;
- theObject->points[point].z = mv->z + radius*cos(deg2rad(loop));
- EDGE_BETWEEN(point,(point!=23) ? point+1 : 12 ) = 1 ;
- point++ ;
- }
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = mv->x ;
- theObject->points[point].y = mv->y + radius*sin(deg2rad(loop)) ;
- theObject->points[point].z = mv->z + radius*cos(deg2rad(loop));
- EDGE_BETWEEN(point,(point!=35) ? point+1 : 24 ) = 1 ;
- point++ ;
- }
- theObject->numpoints = point ;
- }
-
-
- void CreateWireCone(register Cone *cone)
- {
- register short loop, point ;
- register Trans *trans ;
- Float br ;
-
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
- point = 0 ;
- /* Generate the base and link it to the apex */
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = sin(deg2rad(loop)) ;
- theObject->points[point].y = cos(deg2rad(loop)) ;
- theObject->points[point].z = 1 ;
- EDGE_BETWEEN(point,(point+1)%12) = 1 ;
- EDGE_BETWEEN(point,point+12) = 1 ;
- point++ ;
- }
- /* Now generate the apex radius */
- br = cone->start_dist ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = br*sin(deg2rad(loop)) ;
- theObject->points[point].y = br*cos(deg2rad(loop)) ;
- theObject->points[point].z = cone->start_dist ;
- EDGE_BETWEEN(point,(point != 23) ? point+1 : 12) = 1 ;
- point++ ;
- }
- theObject->numpoints = point ;
-
- /* Now we have to transform the wireframe cone so that it looks ok */
- trans = &cone->trans ;
- if(trans) {
- for(loop = 0 ; loop < theObject->numpoints ; loop++)
- PointTransform(&theObject->points[loop],&trans->trans) ;
- }
- }
-
-
- void CreateWireCylinder(register Cylinder *cyl)
- {
- register short loop, point ;
- Trans *trans ;
-
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
-
- point = 0 ;
- /* Generate the bottom and link it to the top */
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = sin(deg2rad(loop)) ;
- theObject->points[point].y = cos(deg2rad(loop)) ;
- theObject->points[point].z = 0.0 ;
- EDGE_BETWEEN(point,(point!=11)?point+1:0 ) = 1 ;
- EDGE_BETWEEN(point,point+12) = 1 ;
- point++ ;
- }
- /* Now the top */
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = sin(deg2rad(loop)) ;
- theObject->points[point].y = cos(deg2rad(loop)) ;
- theObject->points[point].z = 1.0 ;
- EDGE_BETWEEN(point,(point != 23)?point+1:12) = 1 ;
- point++ ;
- }
- theObject->numpoints = point ;
-
- /* Now we have to transform the wireframe cylinder so that it looks ok */
- trans = &cyl->trans ;
- if(trans) {
- for(loop = 0 ; loop < theObject->numpoints ; loop++)
- PointTransform(&theObject->points[loop],&trans->trans) ;
- }
- }
-
- void CreateWireTorus(register Torus *tor)
- {
- register short loop, point ;
- register Trans *trans ;
- register Float radius ;
-
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
-
- point = 0 ;
- radius = tor->a+tor->b ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = radius*sin(deg2rad(loop)) ;
- theObject->points[point].y = radius*cos(deg2rad(loop)) ;
- theObject->points[point].z = 0 ;
- EDGE_BETWEEN(point,(point+1)%12) = 1;
- EDGE_BETWEEN(point,point+24) = 1;
- EDGE_BETWEEN(point,point+36) = 1;
- point++ ;
- }
- radius = tor->a-tor->b ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = radius*sin(deg2rad(loop)) ;
- theObject->points[point].y = radius*cos(deg2rad(loop)) ;
- theObject->points[point].z = 0 ;
- EDGE_BETWEEN(point,(point != 23) ? point+1 : 12 ) = 1 ;
- EDGE_BETWEEN(point,point+12) = 1;
- EDGE_BETWEEN(point,point+24) = 1;
- point++ ;
- }
- radius = tor->a ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = radius*sin(deg2rad(loop)) ;
- theObject->points[point].y = radius*cos(deg2rad(loop)) ;
- theObject->points[point].z = -tor->b ;
- EDGE_BETWEEN(point,(point != 35) ? point+1:24 ) = 1 ;
- point++ ;
- }
- radius = tor->a ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = radius*sin(deg2rad(loop)) ;
- theObject->points[point].y = radius*cos(deg2rad(loop)) ;
- theObject->points[point].z = tor->b ;
- EDGE_BETWEEN(point,(point != 47) ? point+1:36) = 1 ;
- point++ ;
- }
- theObject->numpoints = point ;
-
-
- /* Now we have to transform the wireframe torus so that it looks ok */
- trans = &tor->trans ;
- if(trans) {
- for(loop = 0 ; loop < theObject->numpoints ; loop++)
- PointTransform(&theObject->points[loop],&trans->trans) ;
- }
- }
-
- void CreateWireSphere(register Sphere *sphere)
- {
-
- register short loop, point ;
-
- if(!theObject) InitWireFrame() ;
- ResetWireObject() ;
- point = 0 ;
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = sphere->x + sphere->r*sin(deg2rad(loop)) ;
- theObject->points[point].y = sphere->y + sphere->r*cos(deg2rad(loop)) ;
- theObject->points[point].z = sphere->z ;
- EDGE_BETWEEN(point,(point != 11) ? point+1 : 0 ) = 1 ;
- point++ ;
- }
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = sphere->x + sphere->r*sin(deg2rad(loop)) ;
- theObject->points[point].y = sphere->y ;
- theObject->points[point].z = sphere->z + sphere->r*cos(deg2rad(loop));
- EDGE_BETWEEN(point,(point != 23) ? point+1 : 12) = 1 ;
- point++ ;
- }
- for(loop = 0 ; loop < 360 ; loop += 30) {
- theObject->points[point].x = sphere->x ;
- theObject->points[point].y = sphere->y + sphere->r*sin(deg2rad(loop)) ;
- theObject->points[point].z = sphere->z + sphere->r*cos(deg2rad(loop));
- EDGE_BETWEEN(point,(point != 35) ? point+1 : 24) = 1 ;
- point++ ;
- }
- theObject->numpoints = point ;
- }
-
-