home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Stuff / 3D_Reality / 3D_Reality_API / Examples / Patch.bproj / Patch.m < prev    next >
Encoding:
Text File  |  1992-10-10  |  7.0 KB  |  242 lines

  1.  
  2. /* Patch.m    Peter Wickersham
  3.  *
  4.  * Methods for Patch class.
  5.  *
  6.  */
  7.  
  8. #import "../Stone3DAPI/Stone3D.h"
  9.  
  10. #import "Patch.h"
  11. #import "../ControlPoint.bproj/ControlPoint.h"
  12. #import <ri/ri.h>
  13.  
  14. #define X0     -1.0
  15. #define X1    -0.33
  16. #define X2     0.33
  17. #define X3      1.0
  18. #define Y0     -0.7
  19. #define Y1     -0.1
  20. #define Y2      0.1
  21. #define Y3      0.7
  22. #define Z0     -1.0
  23. #define Z1     -0.33
  24. #define Z2      0.33
  25. #define Z3      1.0
  26.  
  27. #define BEZIER        0
  28. #define HERMITE     1
  29. #define BSPLINE        2
  30. #define CATMULLROM    3
  31.  
  32.  
  33. @implementation Patch
  34.  
  35. // The init method has the same overall implications as it usually does in
  36. // instance initialization with the added bonus of knowing that your shape
  37. // will added into the worldShape hierarchy according to the actions of the
  38. // user.  Therefore, you can create a small little hierarchy of your own with
  39. // the knowledge that it be just fit right in.
  40. // In Patch, I create the standard Patch shape the appears in The RenderMan
  41. // Companion.
  42. - init
  43. {
  44.     RtFloat    pts[16][3] =  {
  45.         { X0, Y0, Z0}, { X1, Y2, Z0}, { X2, Y1, Z0}, { X3, Y3, Z0},
  46.         { X0, Y1, Z1}, { X1, Y2, Z1}, { X2, Y1, Z1}, { X3, Y2, Z1},
  47.         { X0, Y1, Z2}, { X1, Y2, Z2}, { X2, Y1, Z2}, { X3, Y2, Z2},
  48.         { X0, Y0, Z3}, { X1, Y2, Z3}, { X2, Y1, Z3}, { X3, Y3, Z3}};
  49.     id        temp, lastShape;
  50.     int        i;
  51.  
  52.     // First I let Shape perform any inits that it might need to.
  53.     [super init];
  54.     
  55.     // Then I create my List of control points, which are subclassed Shapes
  56.     // as well, and give them their initial translations.  Finally I add them
  57.     // in the hierarchy under Patch.  In order to set up the sub hierarchy
  58.     // correctly, we need to add the first control point as a descendent of
  59.     // self(Patch) and then add all subsequent point shape objects as peers
  60.     // to the last added point.
  61.     controlPts = [[List allocFromZone:[self zone]] initCount:16];
  62.     temp = [[ControlPoint allocFromZone:[self zone]] init];
  63.     [temp translateTo:pts[0][0] :pts[0][1] :pts[0][2]];
  64.     [temp linkAncestor:self];
  65.     [self linkDescendant:temp];
  66.     [controlPts addObject:temp];
  67.     for (i=1; i<16; i++) {
  68.     lastShape = temp;
  69.     temp = [[ControlPoint allocFromZone:[self zone]] init];
  70.     [temp translateTo:pts[i][0] :pts[i][1] :pts[i][2]];
  71.     [lastShape linkPeer:temp];
  72.     [controlPts addObject:temp];
  73.     }
  74.     
  75.     // Finally, I set the default basis matrices and step sizes.
  76.     // The step sizes for a singular patch is always 3 and does not
  77.     // really matter unless it is a mesh.
  78.     uBasis = BEZIER; bcopy(&RiBezierBasis,&theUBasis,sizeof(RtBasis));
  79.     vBasis = BEZIER; bcopy(&RiBezierBasis,&theVBasis,sizeof(RtBasis));
  80.     uStep = 3;
  81.     vStep = 3;
  82.     showCtlPoints = YES;
  83.     showHull = NO;
  84.     
  85.     // The X min and max
  86.     boundingBox[0] = 999;  boundingBox[1] = -999;
  87.     
  88.     // The Y min and max
  89.     boundingBox[2] = 999;  boundingBox[3] = -999;
  90.     
  91.     // The Z min and max
  92.     boundingBox[4] = 999;  boundingBox[5] = -999;
  93.     
  94.     return self;
  95. }
  96.  
  97.  
  98. // The following methods are for querying and setting various instance
  99. // variables.  These variables are generally going to be accessed through
  100. // an inspector panel that is installed concurrently with this class by
  101. // the 3DReality class management facilities.  Therefore, if you want to 
  102. // allow the user to set characteristics of your shape, then you must provide
  103. // an inspector of the name <shapeClassName>Inspector with interface objects
  104. // for tweaking parameters.
  105.  
  106. - (BOOL) hullVisible
  107. {
  108.     return showHull;
  109. }
  110.  
  111. - setHullVisible:(BOOL) flag
  112. {
  113.     showHull = flag;
  114.     return self;
  115. }
  116.  
  117. - (BOOL)controlVisible
  118. {
  119.     return showCtlPoints;
  120. }
  121.  
  122. - setControlVisible:(BOOL)flag
  123. {
  124.     int        i, max;
  125.     id       *clist;
  126.     
  127.     showCtlPoints = flag;
  128.     for (i=0, max = [controlPts count],
  129.     clist=NX_ADDRESS(controlPts);i<max;i++) {
  130.         [clist[i] setVisible:flag];
  131.     }
  132.     return self;
  133. }
  134.  
  135. - (int)uBasis
  136. {
  137.     return uBasis;
  138. }
  139.  
  140. - setUBasis:(int)theU
  141. {
  142.     uBasis = theU;
  143.     switch (uBasis) {
  144.     case BEZIER: bcopy(&RiBezierBasis,&theUBasis,sizeof(RtBasis));
  145.              break;
  146.     case HERMITE: bcopy(&RiHermiteBasis,&theUBasis,sizeof(RtBasis));
  147.              break;
  148.     case BSPLINE: bcopy(&RiBSplineBasis,&theUBasis,sizeof(RtBasis));
  149.              break;
  150.     case CATMULLROM: bcopy(&RiCatmullRomBasis,&theUBasis,sizeof(RtBasis));
  151.              break;
  152.     default: bcopy(&RiBezierBasis,&theUBasis,sizeof(RtBasis));
  153.     }
  154.     return self;
  155. }
  156.  
  157. - (int)vBasis 
  158. {
  159.     return vBasis;
  160. }
  161.  
  162. - setVBasis:(int)theV
  163. {
  164.     vBasis = theV;
  165.     switch (vBasis) {
  166.     case BEZIER: bcopy(&RiBezierBasis,&theVBasis,sizeof(RtBasis));
  167.              break;
  168.     case HERMITE: bcopy(&RiHermiteBasis,&theVBasis,sizeof(RtBasis));
  169.              break;
  170.     case BSPLINE: bcopy(&RiBSplineBasis,&theVBasis,sizeof(RtBasis));
  171.              break;
  172.     case CATMULLROM: bcopy(&RiCatmullRomBasis,&theVBasis,sizeof(RtBasis));
  173.              break;
  174.     default: bcopy(&RiBezierBasis,&theVBasis,sizeof(RtBasis));
  175.     }
  176.     return self;
  177. }
  178.  
  179.  
  180. // In order to provide selection capablity we must override Shapes instance 
  181. // method calcBoundingBox.
  182. - calcBoundingBox
  183. {
  184.     int        i, max;        // index variables
  185.     id       *clist;        // Address of control point list
  186.     RtFloat     pt[3];
  187.     
  188.     for (i=0, max = [controlPts count],
  189.     clist=NX_ADDRESS(controlPts);i<max;i++) {
  190.         [clist[i] trans:&pt[0]];
  191.         if (pt[0] < boundingBox[0]) boundingBox[0] = pt[0];
  192.         if (pt[0] > boundingBox[1]) boundingBox[1] = pt[0];
  193.         if (pt[1] < boundingBox[2]) boundingBox[2] = pt[1];
  194.         if (pt[1] > boundingBox[3]) boundingBox[3] = pt[1];
  195.         if (pt[2] < boundingBox[4]) boundingBox[4] = pt[2];
  196.         if (pt[2] > boundingBox[5]) boundingBox[5] = pt[2];
  197.     }
  198.     return self;
  199. }
  200.  
  201.  
  202. // doRenderSelf is the method where the rendering code is placed.  Here we
  203. // just make normal RenderMan function calls for creating RIB code that gets
  204. // interpreted by either QRMAN or PRMAN depending on whether we are printing
  205. // or drawing the RIB code.  
  206. - doRenderSelf: (Camera *) camera
  207. {
  208.     int        i, max;        // index variables
  209.     id       *clist;        // Address of control point list
  210.     RtFloat    tmppts[16][3];    // The current position of the control points
  211.     
  212.     // verts and nverst are for passing the vertex info to RiPointsPolygon
  213.     // for the control hull.
  214.     static RtInt verts[32] = {0,1,5,4,4,5,9,8,8,9,13,12,13,14,10,6,2,1,5,9,
  215.                   2,3,7,6,6,7,11,10,14,15,11,10};
  216.     static RtInt nverts[7] = {4,4,4,8,4,4,4};
  217.  
  218.     // First let our superclass Shape do its rendering code.  This could 
  219.     // include shading and texturing calls.
  220.     [super doRenderSelf:camera];
  221.     
  222.     // Then we get the current translation information from the control 
  223.     // points.  This gives us their current positions in the Patch space.
  224.     for (i=0, max = [controlPts count],
  225.     clist=NX_ADDRESS(controlPts);i<max;i++) {
  226.         [clist[i] trans:&tmppts[i][0]];
  227.     }
  228.     
  229.     // Draw the control hull polygon if needed using RiPointsPolygon
  230.     if (showHull) {
  231.     RiPointsPolygons((RtInt)7,nverts,verts,RI_P,(RtPointer)tmppts,RI_NULL);
  232.     }
  233.     
  234.     // Set the U and V basis matrices and then draw the patch using 
  235.     // RiPatch with the translations of the control points.
  236.     RiBasis(theUBasis, (RtInt)uStep, theVBasis, (RtInt)vStep);
  237.     RiPatch(RI_BICUBIC, RI_P, (RtPointer)tmppts, RI_NULL);
  238.     
  239.     return self;
  240. }
  241. @end
  242.