home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / macraysh.sit / Code / Source / macobject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-13  |  15.2 KB  |  574 lines

  1. /*
  2.  * Macobject.c
  3.  *
  4.  * Purpose: A collection of routines that construct wireframe representations of each object
  5.  * type
  6.  *
  7.  */
  8. #include "common.h"
  9. #include "geom.h"
  10. #include "list.h"
  11. #include "grid.h"
  12. #include "sampling.h"
  13. #include "csg.h"
  14. #include "sphere.h"
  15. #include "box.h"
  16. #include "triangle.h"
  17. #include "disc.h"
  18. #include "blob.h"
  19. #include "torus.h"
  20. #include "plane.h"
  21. #include "cone.h"
  22. #include "cylinder.h"
  23. #include "sampling.h"
  24. #include "hf.h"
  25. #include "csg.h"
  26. #include "instance.h"
  27. #include "poly.h"
  28. #include "surface.h"
  29.  
  30. #include "rotate.h"
  31.  
  32. #include "macobject.h"
  33. #include "maceditor.h"
  34.  
  35. void DisplayWireObject(register char viewdir,register Geom *obj,register Surface *surf);
  36. extern void DisplayHfObject(Hf *hf, char viewdir) ;
  37.  
  38. extern Geom *hiliteobject ;
  39. extern unsigned long FilterFlags ;
  40. extern Float zoom;
  41.  
  42. WireObject *theObject = NULL ;
  43. Trans *transforms[MAXTRANSFORMS] ;
  44. short transdepth ;
  45.  
  46. static Vector zaxis = {0.,0.,1.};
  47. static Geom *objectstack[500] ;
  48. static short objectnum ;
  49.  
  50. /* Now for a recursive routine to magically draw all of the objects in the world */
  51. void DrawObject(register Geom *object, register Surface *surf, register char viewdir)
  52. {
  53.     register Geom *daughter ;
  54.     register char transet ;
  55.     List *list ;
  56.     Grid *grid ;
  57.     Surface *surf2 ;
  58.     
  59.     /* Since transformations are applied to all children, we will alter the value of transform
  60.      * based upon the parents transformation data
  61.      */
  62.  
  63.     if(!object) return ;
  64.     if(object->trans) {
  65.         transforms[transdepth] = object->trans ;
  66.         transdepth++ ;
  67.         transet = 1 ;
  68.     }
  69.     else
  70.         transet = 0 ;
  71.     
  72.     surf2 = (object->surf) ? object->surf : surf;    
  73.     switch(ObjectType(object)) {
  74.     case CSG:
  75.         if(!FILTER_SET(F_CSG)) {
  76.             DrawObject(((Csg *)object->obj)->obj1,surf2,viewdir) ;
  77.             DrawObject(((Csg *)object->obj)->obj2,surf2,viewdir) ;
  78.         }
  79.         break ;
  80.     case LIST:
  81.         if(!FILTER_SET(F_LIST)) {
  82.             list = object->obj ;
  83.             for(daughter = list->list ; daughter ; daughter = daughter->next)
  84.                 DrawObject(daughter,surf2,viewdir) ;
  85.             for(daughter = list->unbounded ; daughter ; daughter = daughter->next)
  86.                 DrawObject(daughter,surf2,viewdir) ;
  87.         }
  88.         break ;
  89.     case GRID:
  90.         if(!FILTER_SET(F_GRID)) {
  91.             grid = object->obj ;
  92.             for(daughter = grid->unbounded ; daughter ; daughter = daughter->next)
  93.                 DrawObject(daughter,surf2,viewdir) ; 
  94.             for(daughter = grid->objects ; daughter ; daughter = daughter->next)
  95.                 DrawObject(daughter,surf2,viewdir) ; 
  96.         }
  97.         break ;
  98.     case INSTANCE:
  99.         if(!FILTER_SET(F_INSTANCE))
  100.             DrawObject(((Instance *)object->obj)->obj,surf2,viewdir) ;
  101.         break ;
  102.     case PLANE:
  103.         if(!FILTER_SET(F_PLANE)) {
  104.             CreateWirePlane((Plane *)object->obj) ;
  105.             DisplayWireObject(viewdir,object,surf2) ;
  106.         }
  107.         break ;
  108.     case SPHERE:
  109.         if(!FILTER_SET(F_SPHERE)) {
  110.             CreateWireSphere((Sphere *)object->obj) ;
  111.             DisplayWireObject(viewdir,object,surf2) ;
  112.         }
  113.         break ;
  114.     case CONE:
  115.         if(!FILTER_SET(F_CONE)) {
  116.             CreateWireCone((Cone *)object->obj) ;
  117.             DisplayWireObject(viewdir,object,surf2) ;
  118.         }
  119.         break ;
  120.     case BOX:
  121.         if(!FILTER_SET(F_BOX)) {
  122.             CreateWireBox((Box *)object->obj) ;
  123.             DisplayWireObject(viewdir,object,surf2) ;
  124.         }
  125.         break ;
  126.     case TORUS:
  127.         if(!FILTER_SET(F_TORUS)) {
  128.             CreateWireTorus((Torus *)object->obj) ;
  129.             DisplayWireObject(viewdir,object,surf2) ;
  130.         }
  131.         break ;
  132.     case BLOB:
  133.         if(!FILTER_SET(F_BLOB)) {
  134.             register short i;
  135.             Blob *blob;
  136.  
  137.             blob = (Blob *) object->obj;
  138.             /* Generate each metaball in turn */
  139.             for(i = 0 ; i < blob->num ; i++) {
  140.                 CreateWireMetaBall(&blob->list[i]) ;
  141.                 DisplayWireObject(viewdir,object,surf2) ;
  142.             }
  143.         }
  144.         break ;
  145.     case DISC:
  146.         if(!FILTER_SET(F_DISC)) {
  147.             CreateWireDisc((Disc *)object->obj) ;
  148.             DisplayWireObject(viewdir,object,surf2) ;
  149.         }
  150.         break ;
  151.     case TRIANGLE:
  152.         if(!FILTER_SET(F_TRIANGLE)) {
  153.             CreateWireTriangle((Triangle *)object->obj) ;
  154.             DisplayWireObject(viewdir,object,surf2) ;
  155.         }
  156.         break ;
  157.     case POLYGON:
  158.         if(!FILTER_SET(F_POLYGON)) {
  159.             CreateWirePolygon((RPolygon *)object->obj) ;
  160.             DisplayWireObject(viewdir,object,surf2) ;
  161.         }
  162.         break ;
  163.     case HF:
  164.         if(!FILTER_SET(F_HF))
  165.             DisplayHfObject((Hf *)object->obj, viewdir) ;
  166.         break ;
  167.     case CYLINDER:
  168.         if(!FILTER_SET(F_CYLINDER)) {
  169.             CreateWireCylinder((Cylinder *)object->obj) ;
  170.             DisplayWireObject(viewdir,object,surf2) ;
  171.         }
  172.         break ;
  173.     }
  174.     if(transet) transdepth-- ;
  175. }
  176.  
  177.  
  178. void InitWireFrame()
  179. {
  180.     theObject = malloc(sizeof(WireObject)) ;
  181. }
  182.  
  183. void RemoveWireFrame()
  184. {
  185.     free((void *)theObject) ;
  186. }
  187.  
  188. void ResetWireObject()
  189. {
  190.     /* Clean the array */
  191.     memset((void *)theObject->edge_array,0,(size_t)MAXPOINTS*MAXPOINTS) ;
  192.     theObject->numpoints = 0 ;
  193. }
  194.  
  195.  
  196. void WireFrameTransform(Trans *trans)
  197. {
  198.     register short loop ;
  199.  
  200.     while(trans) {
  201.         for(loop = 0 ; loop < theObject->numpoints ; loop++)
  202.             PointTransform(&theObject->points[loop],&trans->trans) ;
  203.         trans = trans->next ;    
  204.     }
  205. }
  206.  
  207. void CreateWirePlane(register Plane *plane)
  208. {
  209.     register short loop ;
  210.     Float theta, costheta;
  211.     Vector axis;
  212.     RSMatrix mat;
  213.  
  214.     if(!theObject) InitWireFrame() ;
  215.     ResetWireObject() ;
  216.     theObject->points[0].x = -1000./zoom ;
  217.     theObject->points[0].y = -1000./zoom ;
  218.     theObject->points[0].z = 0 ;
  219.  
  220.     theObject->points[1].x = -1000./zoom ;
  221.     theObject->points[1].y = 1000./zoom;
  222.     theObject->points[1].z = 0 ;
  223.  
  224.     theObject->points[2].x = 1000./zoom ;
  225.     theObject->points[2].y = 1000./zoom ;
  226.     theObject->points[2].z = 0;
  227.  
  228.     theObject->points[3].x = 1000./zoom ;
  229.     theObject->points[3].y = -1000./zoom;
  230.     theObject->points[3].z = 0 ;
  231.  
  232.     EDGE_BETWEEN(0,1) = 1 ;
  233.     EDGE_BETWEEN(1,2) = 1 ;
  234.     EDGE_BETWEEN(2,3) = 1 ;
  235.     EDGE_BETWEEN(3,0) = 1 ;
  236.     EDGE_BETWEEN(0,2) = 1 ;
  237.     EDGE_BETWEEN(1,3) = 1 ;
  238.     theObject->numpoints = 4 ;
  239.     
  240.     VecNormalize(&plane->norm);
  241.     
  242.     costheta = dotp(&plane->norm,&zaxis);
  243.     if(!equal(fabs(costheta),1.)) {
  244.         theta = acos(costheta);
  245.         VecNormCross(&zaxis,&plane->norm,&axis);
  246.         MatrixInit(&mat);
  247.         RotationMatrix(axis.x,axis.y,axis.z,theta,&mat);
  248.         for(loop = 0 ; loop < theObject->numpoints ; loop++) {
  249.             PointTransform(&theObject->points[loop],&mat);
  250.         }
  251.     }
  252.     for(loop = 0 ; loop < theObject->numpoints ; loop++) {
  253.         theObject->points[loop].x += plane->pos.x;
  254.         theObject->points[loop].y += plane->pos.y;
  255.         theObject->points[loop].z += plane->pos.z;
  256.     }
  257. }
  258.  
  259. void CreateWireBox(register Box *box)
  260. {
  261.     if(!theObject) InitWireFrame() ;
  262.     ResetWireObject() ;
  263.  
  264.     theObject->points[0].x = box->bounds[0][0] ;
  265.     theObject->points[0].y = box->bounds[0][1] ;
  266.     theObject->points[0].z = box->bounds[0][2] ;
  267.  
  268.     theObject->points[1].x = box->bounds[1][0] ;
  269.     theObject->points[1].y = box->bounds[0][1] ;
  270.     theObject->points[1].z = box->bounds[0][2] ;
  271.  
  272.     theObject->points[2].x = box->bounds[1][0] ;
  273.     theObject->points[2].y = box->bounds[0][1] ;
  274.     theObject->points[2].z = box->bounds[1][2] ;
  275.  
  276.     theObject->points[3].x = box->bounds[0][0] ;
  277.     theObject->points[3].y = box->bounds[0][1] ;
  278.     theObject->points[3].z = box->bounds[1][2] ;
  279.  
  280.     theObject->points[4].x = box->bounds[0][0] ;
  281.     theObject->points[4].y = box->bounds[1][1] ;
  282.     theObject->points[4].z = box->bounds[0][2] ;
  283.  
  284.     theObject->points[5].x = box->bounds[1][0] ;
  285.     theObject->points[5].y = box->bounds[1][1] ;
  286.     theObject->points[5].z = box->bounds[0][2] ;
  287.  
  288.     theObject->points[6].x = box->bounds[1][0] ;
  289.     theObject->points[6].y = box->bounds[1][1] ;
  290.     theObject->points[6].z = box->bounds[1][2] ;
  291.  
  292.     theObject->points[7].x = box->bounds[0][0] ;
  293.     theObject->points[7].y = box->bounds[1][1] ;
  294.     theObject->points[7].z = box->bounds[1][2] ;
  295.     
  296.     EDGE_BETWEEN(0,1) = 1 ;
  297.     EDGE_BETWEEN(0,3) = 1 ;
  298.     EDGE_BETWEEN(0,4) = 1 ;
  299.     EDGE_BETWEEN(1,2) = 1 ;
  300.     EDGE_BETWEEN(1,5) = 1 ;
  301.     EDGE_BETWEEN(2,3) = 1 ;
  302.     EDGE_BETWEEN(2,6) = 1 ;
  303.     EDGE_BETWEEN(3,7) = 1 ;
  304.     EDGE_BETWEEN(4,5) = 1 ;
  305.     EDGE_BETWEEN(4,7) = 1 ;
  306.     EDGE_BETWEEN(5,6) = 1 ;
  307.     EDGE_BETWEEN(6,7) = 1 ;
  308.     
  309.     theObject->numpoints = 8 ;
  310. }
  311.  
  312. void CreateWireTriangle(register Triangle *tri)
  313. {
  314.     if(!theObject) InitWireFrame() ;
  315.     ResetWireObject() ;
  316.     theObject->points[0] = tri->p[0] ;
  317.     theObject->points[1] = tri->p[1] ;
  318.     theObject->points[2] = tri->p[2] ;
  319.     EDGE_BETWEEN(0,1) = 1 ;
  320.     EDGE_BETWEEN(1,2) = 1 ;
  321.     EDGE_BETWEEN(2,0) = 1 ;
  322.     theObject->numpoints = 3 ;
  323. }
  324.  
  325. void CreateWirePolygon(register RPolygon *poly)
  326. {
  327.     register short loop ;
  328.     
  329.     if(!theObject) InitWireFrame() ;
  330.     ResetWireObject() ;
  331.     for(loop = 0 ; loop < poly->npoints ; loop++) {
  332.         theObject->points[loop] = poly->points[loop] ;
  333.         EDGE_BETWEEN(loop, (loop == poly->npoints-1) ? 0 : loop+1) = 1 ;
  334.     }
  335.     theObject->numpoints = poly->npoints ;
  336. }
  337.  
  338. void CreateWireDisc(register Disc *disc)
  339. {
  340.     register short loop, point ;
  341.     Float theta, costheta;
  342.     Vector axis;
  343.     RSMatrix mat;
  344.     
  345.     if(!theObject) InitWireFrame() ;
  346.     ResetWireObject() ;
  347.     point = 0 ;
  348.     for(loop = 0 ; loop < 360 ; loop += 30) {
  349.         theObject->points[point].x = disc->radius * sin(deg2rad(loop)) ;
  350.         theObject->points[point].y = disc->radius * cos(deg2rad(loop)) ;
  351.         theObject->points[point].z = 0 ;
  352.         EDGE_BETWEEN(point, (point == 11) ? 0 : point+1) = 1 ;
  353.         point++ ;
  354.     }
  355.     theObject->numpoints = point ;
  356.     
  357.     /* We have created a proto disc, nor we must rotate so that it correctly displayed */
  358.     
  359.     VecNormalize(&disc->norm);
  360.     costheta = dotp(&disc->norm,&zaxis);
  361.     if(!equal(fabs(costheta),1.)) {
  362.         theta = acos(costheta);
  363.         VecNormCross(&zaxis,&disc->norm,&axis);
  364.         MatrixInit(&mat);
  365.         RotationMatrix(axis.x,axis.y,axis.z,theta,&mat);
  366.         for(loop = 0 ; loop < point ; loop++) {
  367.             PointTransform(&theObject->points[loop],&mat);
  368.         }
  369.     }
  370.     for(loop = 0 ; loop < point ; loop++) {
  371.         theObject->points[loop].x += disc->pos.x;
  372.         theObject->points[loop].y += disc->pos.y;
  373.         theObject->points[loop].z += disc->pos.z;
  374.     }
  375. }
  376.  
  377. void CreateWireMetaBall(register MetaVector *mv)
  378. {
  379.     register short loop, point ;
  380.     Float radius;
  381.  
  382.     radius = sqrt(mv->rs);
  383.     if(!theObject) InitWireFrame() ;
  384.     ResetWireObject() ;
  385.     point = 0 ;
  386.     for(loop = 0 ; loop < 360 ; loop += 30) {
  387.         theObject->points[point].x = mv->x + radius*sin(deg2rad(loop)) ;
  388.         theObject->points[point].y = mv->y + radius*cos(deg2rad(loop)) ;
  389.         theObject->points[point].z = mv->z ;
  390.         EDGE_BETWEEN(point,(point!=11) ? point+1 : 0) = 1 ;
  391.         point++ ;
  392.     }
  393.     for(loop = 0 ; loop < 360 ; loop += 30) {
  394.         theObject->points[point].x = mv->x + radius*sin(deg2rad(loop)) ;
  395.         theObject->points[point].y = mv->y ;
  396.         theObject->points[point].z = mv->z + radius*cos(deg2rad(loop));
  397.         EDGE_BETWEEN(point,(point!=23) ? point+1 : 12 ) = 1 ;
  398.         point++ ;
  399.     }
  400.     for(loop = 0 ; loop < 360 ; loop += 30) {
  401.         theObject->points[point].x = mv->x ;
  402.         theObject->points[point].y = mv->y + radius*sin(deg2rad(loop)) ;
  403.         theObject->points[point].z = mv->z + radius*cos(deg2rad(loop));
  404.         EDGE_BETWEEN(point,(point!=35) ? point+1 : 24 ) = 1 ;
  405.         point++ ;
  406.     }
  407.     theObject->numpoints = point ;
  408. }
  409.  
  410.  
  411. void CreateWireCone(register Cone *cone)
  412. {
  413.     register short loop, point ;
  414.     register Trans *trans ;
  415.     Float br ;
  416.  
  417.     if(!theObject) InitWireFrame() ;
  418.     ResetWireObject() ;
  419.     point = 0 ;
  420.     /* Generate the base and link it to the apex */
  421.     for(loop = 0 ; loop < 360 ; loop += 30) {
  422.         theObject->points[point].x = sin(deg2rad(loop)) ;
  423.         theObject->points[point].y = cos(deg2rad(loop)) ;
  424.         theObject->points[point].z = 1 ;
  425.         EDGE_BETWEEN(point,(point+1)%12) = 1 ;
  426.         EDGE_BETWEEN(point,point+12) = 1 ;
  427.         point++ ;
  428.     }
  429.     /* Now generate the apex radius */
  430.     br = cone->start_dist ;
  431.     for(loop = 0 ; loop < 360 ; loop += 30) {
  432.         theObject->points[point].x = br*sin(deg2rad(loop)) ;
  433.         theObject->points[point].y = br*cos(deg2rad(loop)) ;
  434.         theObject->points[point].z = cone->start_dist ;
  435.         EDGE_BETWEEN(point,(point != 23) ? point+1 : 12) = 1 ;
  436.         point++ ;
  437.     }
  438.     theObject->numpoints = point ;
  439.  
  440.     /* Now we have to transform the wireframe cone so that it looks ok */
  441.     trans = &cone->trans ;
  442.     if(trans) {
  443.         for(loop = 0 ; loop < theObject->numpoints ; loop++)
  444.             PointTransform(&theObject->points[loop],&trans->trans) ;
  445.     }
  446. }
  447.  
  448.  
  449. void CreateWireCylinder(register Cylinder *cyl)
  450. {
  451.     register short loop, point ;
  452.     Trans *trans ;
  453.  
  454.     if(!theObject) InitWireFrame() ;
  455.     ResetWireObject() ;
  456.     
  457.     point = 0 ;
  458.     /* Generate the bottom and link it to the top */ 
  459.     for(loop = 0 ; loop < 360 ; loop += 30) {
  460.         theObject->points[point].x = sin(deg2rad(loop)) ;
  461.         theObject->points[point].y = cos(deg2rad(loop)) ;
  462.         theObject->points[point].z = 0.0 ;
  463.         EDGE_BETWEEN(point,(point!=11)?point+1:0 ) = 1 ;
  464.         EDGE_BETWEEN(point,point+12) = 1 ;
  465.         point++ ;
  466.     }
  467.     /* Now the top */
  468.     for(loop = 0 ; loop < 360 ; loop += 30) {
  469.         theObject->points[point].x = sin(deg2rad(loop)) ;
  470.         theObject->points[point].y = cos(deg2rad(loop)) ;
  471.         theObject->points[point].z = 1.0 ;
  472.         EDGE_BETWEEN(point,(point != 23)?point+1:12) = 1 ;
  473.         point++ ;
  474.     }
  475.     theObject->numpoints = point ;
  476.     
  477.     /* Now we have to transform the wireframe cylinder so that it looks ok */
  478.     trans = &cyl->trans ;
  479.     if(trans) {
  480.         for(loop = 0 ; loop < theObject->numpoints ; loop++)
  481.             PointTransform(&theObject->points[loop],&trans->trans) ;
  482.     }
  483. }
  484.  
  485. void CreateWireTorus(register Torus *tor)
  486. {
  487.     register short loop, point ;
  488.     register Trans *trans ;
  489.     register Float radius ;
  490.     
  491.     if(!theObject) InitWireFrame() ;
  492.     ResetWireObject() ;
  493.  
  494.     point = 0 ;
  495.     radius = tor->a+tor->b ;
  496.     for(loop = 0 ; loop < 360 ; loop += 30) {
  497.         theObject->points[point].x = radius*sin(deg2rad(loop)) ;
  498.         theObject->points[point].y = radius*cos(deg2rad(loop)) ;
  499.         theObject->points[point].z = 0 ;
  500.         EDGE_BETWEEN(point,(point+1)%12) = 1;
  501.         EDGE_BETWEEN(point,point+24) = 1;
  502.         EDGE_BETWEEN(point,point+36) = 1;
  503.         point++ ;
  504.     }
  505.     radius = tor->a-tor->b ;
  506.     for(loop = 0 ; loop < 360 ; loop += 30) {
  507.         theObject->points[point].x = radius*sin(deg2rad(loop)) ;
  508.         theObject->points[point].y = radius*cos(deg2rad(loop)) ;
  509.         theObject->points[point].z = 0 ;
  510.         EDGE_BETWEEN(point,(point != 23) ? point+1 : 12 ) = 1 ;
  511.         EDGE_BETWEEN(point,point+12) = 1;
  512.         EDGE_BETWEEN(point,point+24) = 1;
  513.         point++ ;
  514.     }
  515.     radius = tor->a ;
  516.     for(loop = 0 ; loop < 360 ; loop += 30) {
  517.         theObject->points[point].x = radius*sin(deg2rad(loop)) ;
  518.         theObject->points[point].y = radius*cos(deg2rad(loop)) ;
  519.         theObject->points[point].z = -tor->b ;
  520.         EDGE_BETWEEN(point,(point != 35) ? point+1:24 ) = 1 ;
  521.         point++ ;
  522.     }
  523.     radius = tor->a ;
  524.     for(loop = 0 ; loop < 360 ; loop += 30) {
  525.         theObject->points[point].x = radius*sin(deg2rad(loop)) ;
  526.         theObject->points[point].y = radius*cos(deg2rad(loop)) ;
  527.         theObject->points[point].z = tor->b ;
  528.         EDGE_BETWEEN(point,(point != 47) ? point+1:36) = 1 ;
  529.         point++ ;
  530.     }
  531.     theObject->numpoints = point ;
  532.  
  533.  
  534.     /* Now we have to transform the wireframe torus so that it looks ok */
  535.     trans = &tor->trans ;
  536.     if(trans) {
  537.         for(loop = 0 ; loop < theObject->numpoints ; loop++)
  538.             PointTransform(&theObject->points[loop],&trans->trans) ;
  539.     }
  540. }
  541.  
  542. void CreateWireSphere(register Sphere *sphere)
  543. {    
  544.  
  545.     register short loop, point ;
  546.  
  547.     if(!theObject) InitWireFrame() ;
  548.     ResetWireObject() ;
  549.     point = 0 ;
  550.     for(loop = 0 ; loop < 360 ; loop += 30) {
  551.         theObject->points[point].x = sphere->x + sphere->r*sin(deg2rad(loop)) ;
  552.         theObject->points[point].y = sphere->y + sphere->r*cos(deg2rad(loop)) ;
  553.         theObject->points[point].z = sphere->z ;
  554.         EDGE_BETWEEN(point,(point != 11) ? point+1 : 0 ) = 1 ;
  555.         point++ ;
  556.     }
  557.     for(loop = 0 ; loop < 360 ; loop += 30) {
  558.         theObject->points[point].x = sphere->x + sphere->r*sin(deg2rad(loop)) ;
  559.         theObject->points[point].y = sphere->y ;
  560.         theObject->points[point].z = sphere->z + sphere->r*cos(deg2rad(loop));
  561.         EDGE_BETWEEN(point,(point != 23) ? point+1 : 12) = 1 ;
  562.         point++ ;
  563.     }
  564.     for(loop = 0 ; loop < 360 ; loop += 30) {
  565.         theObject->points[point].x = sphere->x ;
  566.         theObject->points[point].y = sphere->y + sphere->r*sin(deg2rad(loop)) ;
  567.         theObject->points[point].z = sphere->z + sphere->r*cos(deg2rad(loop));
  568.         EDGE_BETWEEN(point,(point != 35) ? point+1 : 24) = 1 ;
  569.         point++ ;
  570.     }
  571.     theObject->numpoints = point ;
  572. }
  573.  
  574.