home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 April: Mac OS SDK / Dev.CD Apr 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / TriGrids / Sources / GeometrySample.c next >
Encoding:
C/C++ Source or Header  |  1996-05-21  |  16.3 KB  |  598 lines  |  [TEXT/MPCC]

  1. /*
  2.     GeometrySample.c
  3.  
  4.     This is a simple library illustrating trigrid geometries representing a
  5.     Flat 5x5, Torus, Wavey Torus, Splash, Sphere, Cone, Pipe, Steps, and Spring.
  6.  
  7.     NewLibraryTriGrid returns a trigrid geometry when kGeometryLibraryRange_Simple
  8.     is added to the trigrid number (0 to 8) or a trigrid with shading uv attributes
  9.     when kGeometryLibraryRange_UVGeoAttributes or kGeometryLibraryRange_UVFaceAttributes
  10.     is added to the trigrid number.
  11.  
  12.     Note: The calculation of uv's may be flipping the texture.
  13.  
  14.  
  15.     Robert Dierkes - March 22, 1995
  16.     © 1995 Apple Computer, Inc.
  17.  
  18.     Modification History:
  19.  
  20.     03/22/95    rdd        initial version
  21. */
  22.  
  23. #include <Memory.h>
  24. #include "math.h"
  25.  
  26. #include "QD3D.h"
  27. #include "QD3DGeometry.h"
  28. #include "QD3DMath.h"
  29. #include "AttributeSet_Lib.h"
  30.  
  31. #include "GeometrySample.h"
  32. #include "MathUtilities.h"
  33.  
  34.  
  35. unsigned long GetLibraryMaxSimpleTriGrid(void)
  36. {
  37.     return kGeometryLibrary_TriGridMaxSimple;
  38. }
  39.  
  40.  
  41.  
  42. /*
  43.  *    NewLibraryTriGrid
  44.  *
  45.  * There are two methods below for creating trigrid vertices. If the trigrid is:
  46.  *
  47.  *    1. planar (relatively) then the vvValue (an x-coordinate) increases from vvMin to vvMax.
  48.  *    2. a cross section revolved about the Y axis then the vvValue (an angle) decreases from
  49.  *        vvMax to vvMin in a counter-clockwise manner about the axis. This puts the correct
  50.  *        side of the trigrid facing outward for texture uvs.
  51.  *
  52.  * In both cases, uuValue decreases from uuMax to uuMin from postive to negative Y.
  53.  *
  54.  *    TriGrid vertex index numbering
  55.  *
  56.  *       (i)
  57.  *        8        9        10        11
  58.  *        4        5        6        7
  59.  *        0        1        2        3
  60.  *
  61.  *
  62.  *    UVs for an upright texture continuous across the trigrid
  63.  *
  64.  *       (U,V)
  65.  *       (x,y)
  66.  *
  67.  *        ^ +        0.0, 1.0    0.33, 1.0    0.66, 1.0    1.0, 1.0
  68.  *        |        0.0, 0.5    0.33, 0.5    0.66, 0.5    1.0, 0.5
  69.  *        V -        0.0, 0.0    0.33, 0.0    0.66, 0.0    1.0, 0.0
  70.  *
  71.  *                   U -->
  72.  *                   -   +
  73.  *
  74.  *    UVs for an upright repeated texture
  75.  *
  76.  *       (U,V)
  77.  *       (x,y)
  78.  *
  79.  *        ^ +        0,2        1,2        2,2        3,2
  80.  *        |        0,1        1,1        2,1        3,1
  81.  *        V -        0,0        1,0        2,0        3,0
  82.  *
  83.  *                   U -->
  84.  *                   -   +
  85.  */
  86. TQ3GeometryObject    NewLibraryTriGrid(unsigned long num)
  87. {
  88.     TQ3GeometryObject    geometryObject = NULL;
  89.     TQ3TriGridData        data;
  90.     TQ3Vertex3D            *vertices;
  91.     unsigned long        i;
  92.     float                uuValue, vvValue,
  93.                         uuMin, uuMax, uuStep,
  94.                         vvMin, vvMax, vvStep,
  95.                         radius;
  96.     TQ3Boolean            hasUVAttributes;
  97.     TQ3Param2D            param2D;
  98.  
  99.     hasUVAttributes = (TQ3Boolean) (mHasUVGeoAttributes(num)  ||  mHasUVFaceAttributes(num));
  100.  
  101.     switch (num)
  102.     {
  103.         case kGeometryLibraryRange_Simple+0:        //    Flat 5x5
  104.         case kGeometryLibraryRange_UVGeoAttributes+0:
  105.         case kGeometryLibraryRange_UVFaceAttributes+0:
  106.         case kGeometryLibraryRange_Simple+3:        //    Splash
  107.         case kGeometryLibraryRange_UVGeoAttributes+3:
  108.         case kGeometryLibraryRange_UVFaceAttributes+3:
  109.         case kGeometryLibraryRange_Simple+7:        //    Steps
  110.         case kGeometryLibraryRange_UVGeoAttributes+7:
  111.         case kGeometryLibraryRange_UVFaceAttributes+7:
  112.         {
  113.             /* Setup min, max and step values trigrid vertex u & v values */
  114.             switch (num)
  115.             {
  116.             /**
  117.              ** Flat 5x5
  118.              **/
  119.             case kGeometryLibraryRange_Simple+0:
  120.             case kGeometryLibraryRange_UVGeoAttributes+0:
  121.             case kGeometryLibraryRange_UVFaceAttributes+0:
  122.  
  123.                 /*
  124.                  * uuValue is an x-coordinate
  125.                  * vvValue is a  y-coordinate
  126.                  */
  127.                 uuMin = -0.5;
  128.                 uuMax =  0.5;
  129.                 uuStep = 0.25;
  130.  
  131.                 vvMin = -0.5;
  132.                 vvMax =  0.5;
  133.                 vvStep = 0.25;
  134.             break;
  135.  
  136.             /**
  137.              ** Splash
  138.              **/
  139.             case kGeometryLibraryRange_Simple+3:
  140.             case kGeometryLibraryRange_UVGeoAttributes+3:
  141.             case kGeometryLibraryRange_UVFaceAttributes+3:
  142.  
  143.                 /*
  144.                  * uuValue is an x-coordinate
  145.                  * vvValue is a  y-coordinate
  146.                  */
  147.                 uuMin = -3.5;
  148.                 uuMax =  3.5;
  149.                 vvMin = -3.5;
  150.                 vvMax =  3.5;
  151.                 if (hasUVAttributes) {
  152.                     uuStep = 0.35;
  153.                     vvStep = 0.35;
  154.                 } else {
  155.                     uuStep = 0.25;
  156.                     vvStep = 0.25;
  157.                 }
  158.                 break;
  159.  
  160.             /**
  161.              ** Steps
  162.              **/
  163.             case kGeometryLibraryRange_Simple+7:
  164.             case kGeometryLibraryRange_UVGeoAttributes+7:
  165.             case kGeometryLibraryRange_UVFaceAttributes+7:
  166.  
  167.                 /*
  168.                  * uuValue is an x-coordinate
  169.                  * vvValue is a  y-coordinate
  170.                  */
  171.                 #define    kStepScale     0.2
  172.  
  173.                 uuMin = -4.5;
  174.                 uuMax =  4.5;
  175.                 uuStep = 0.5;
  176.  
  177.                 vvMin = -4.5;
  178.                 vvMax =  4.5;
  179.                 vvStep = 0.5;
  180.                 break;
  181.  
  182.             default:
  183.                 DebugStr("\pWarning:  NewLibraryTriGrid ; unknown flat trigrid index");
  184.                 return NULL;
  185.                 break;
  186.             }
  187.  
  188.  
  189.             /* Setup TQ3TriGridData */
  190.             data.numRows        = (unsigned long) ((vvMax - vvMin) / vvStep) + 1;
  191.             data.numColumns        = (unsigned long) ((uuMax - uuMin) / uuStep) + 1;
  192.             data.facetAttributeSet    = NULL;
  193.             data.triGridAttributeSet= NULL;
  194.  
  195.             data.vertices = (TQ3Vertex3D *) NewPtr (data.numRows * data.numColumns * sizeof(TQ3Vertex3D));
  196.             if (data.vertices == NULL)
  197.             {
  198.                 DebugStr("\pError:  NewLibraryTriGrid ; Out of memory for triGrid vertices, geometry library number");
  199.                 return NULL;
  200.             }
  201.  
  202.             /* Set trigrid vertices and shading UVs, if it hasUVAttributes */
  203.             vertices = data.vertices;
  204.             i = 0;
  205.             for (vvValue = vvMin; vvValue <= vvMax; vvValue += vvStep)
  206.             {
  207.                 for (uuValue = uuMin; uuValue <= uuMax; uuValue += uuStep)
  208.                 {
  209.                     switch (num)
  210.                     {
  211.                         /* Flat 5x5 */
  212.                         case kGeometryLibraryRange_Simple+0:
  213.                         case kGeometryLibraryRange_UVGeoAttributes+0:
  214.                         case kGeometryLibraryRange_UVFaceAttributes+0:
  215.                             vertices[i].point.x = uuValue;
  216.                             vertices[i].point.y = vvValue;
  217.                             vertices[i].point.z = 0;
  218.                         break;
  219.  
  220.                         /* Splash */
  221.                         case kGeometryLibraryRange_Simple+3:
  222.                         case kGeometryLibraryRange_UVGeoAttributes+3:
  223.                         case kGeometryLibraryRange_UVFaceAttributes+3:
  224.                             vertices[i].point.x = uuValue;
  225.                             vertices[i].point.y = vvValue;
  226.                             vertices[i].point.z = 1.5 * uMath_Sin_Deg(48.0 * uuValue * vvValue) *
  227.                                                         uMath_Cos_Deg(48.0 * uuValue * vvValue);
  228.                         break;
  229.  
  230.                         /* Steps */
  231.                         case kGeometryLibraryRange_Simple+7:
  232.                         case kGeometryLibraryRange_UVGeoAttributes+7:
  233.                         case kGeometryLibraryRange_UVFaceAttributes+7:
  234.                             vertices[i].point.x = uuValue;
  235.                             vertices[i].point.y = vvValue;
  236.                             vertices[i].point.z = kStepScale * (((long) uuValue) % ((data.numRows-1)/2)) *
  237.                                                                (((long) vvValue) % ((data.numColumns-1)/2));
  238.                         break;
  239.                     }
  240.  
  241.                     if (hasUVAttributes)
  242.                     {
  243.                         if (mHasUVGeoAttributes(num))
  244.                         {
  245.                             param2D.u = (uuValue - uuMin) / (uuMax - uuMin);
  246.                             param2D.v = (vvValue - vvMin) / (vvMax - vvMin);
  247.                         }
  248.                         else /* mHasUVFaceAttributes */
  249.                         {
  250.                             param2D.u = i % data.numColumns;
  251.                             param2D.v = i / data.numColumns;
  252.                         }
  253.  
  254.                         vertices[i].attributeSet = Q3AttributeSet_New();
  255.                         Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D);
  256.                     }
  257.                     else
  258.                         vertices[i].attributeSet = NULL;
  259.  
  260.                     i++;
  261.                 }
  262.             }
  263.  
  264.             geometryObject = Q3TriGrid_New (&data);
  265.  
  266.             if (hasUVAttributes)
  267.             {
  268.                 for (i = 0; i < data.numRows * data.numColumns; i++)
  269.                     Q3Object_Dispose(vertices[i].attributeSet);
  270.             }
  271.             DisposePtr ((void *) vertices);
  272.         }
  273.         break;
  274.  
  275.         case kGeometryLibraryRange_Simple+1:        //    Torus
  276.         case kGeometryLibraryRange_UVGeoAttributes+1:
  277.         case kGeometryLibraryRange_UVFaceAttributes+1:
  278.         case kGeometryLibraryRange_Simple+2:        //    Wavey Torus
  279.         case kGeometryLibraryRange_UVGeoAttributes+2:
  280.         case kGeometryLibraryRange_UVFaceAttributes+2:
  281.         case kGeometryLibraryRange_Simple+4:        //    Sphere
  282.         case kGeometryLibraryRange_UVGeoAttributes+4:
  283.         case kGeometryLibraryRange_UVFaceAttributes+4:
  284.         case kGeometryLibraryRange_Simple+5:        //    Cone
  285.         case kGeometryLibraryRange_UVGeoAttributes+5:
  286.         case kGeometryLibraryRange_UVFaceAttributes+5:
  287.         case kGeometryLibraryRange_Simple+6:        //    Pipe
  288.         case kGeometryLibraryRange_UVGeoAttributes+6:
  289.         case kGeometryLibraryRange_UVFaceAttributes+6:
  290.         case kGeometryLibraryRange_Simple+8:        //    Spring
  291.         case kGeometryLibraryRange_UVGeoAttributes+8:
  292.         case kGeometryLibraryRange_UVFaceAttributes+8:
  293.         {
  294.             /* Setup min, max and step values trigrid vertex u & v values */
  295.             switch (num)
  296.             {
  297.             /**
  298.              ** Torus
  299.              **/
  300.             case kGeometryLibraryRange_Simple+1:
  301.             case kGeometryLibraryRange_UVGeoAttributes+1:
  302.             case kGeometryLibraryRange_UVFaceAttributes+1:
  303.             /**
  304.              ** Wavey Torus
  305.              **/
  306.             case kGeometryLibraryRange_Simple+2:
  307.             case kGeometryLibraryRange_UVGeoAttributes+2:
  308.             case kGeometryLibraryRange_UVFaceAttributes+2:
  309.  
  310.                 /*
  311.                  * uuValue is used to generate each circular cross section about the y axis
  312.                  * vvValue is used to revolve the circular cross section about the torus' center
  313.                  */
  314.                 #define    kTorusCrossRadius     0.5
  315.                 #define    kTorusInnerRadius     1.0
  316.                 #define    kTorusWaveyAmpRadius 5.0
  317.  
  318.                 uuMin =    0.0;
  319.                 uuMax =  360.0;
  320.                 vvMin = -180.0;
  321.                 vvMax =  180.0;
  322.                 if (hasUVAttributes) {
  323.                     uuStep = 12.0;
  324.                     vvStep = 12.0;
  325.                 } else {
  326.                     uuStep = 10.0;
  327.                     vvStep = 10.0;
  328.                 }
  329.                 break;
  330.  
  331.             /**
  332.              ** Sphere
  333.              **/
  334.             case kGeometryLibraryRange_Simple+4:
  335.             case kGeometryLibraryRange_UVGeoAttributes+4:
  336.             case kGeometryLibraryRange_UVFaceAttributes+4:
  337.  
  338.                 /*
  339.                  * uuValue is an angle used to revolve the cross section about the y axis
  340.                  * vvValue is an angle used to generate each half circular cross section
  341.                  */
  342.                 uuMin =    0.0;
  343.                 uuMax =  360.0;
  344.                 vvMin = - 90.0;
  345.                 vvMax =   90.0;
  346.                 if (hasUVAttributes) {
  347.                     uuStep =  12.0;
  348.                     vvStep =  12.0;
  349.                 } else {
  350.                     uuStep =   9.0;
  351.                     vvStep =   9.0;
  352.                 }
  353.                 radius = 1.0;
  354.                 break;
  355.  
  356.             /**
  357.              ** Cone
  358.              **/
  359.             case kGeometryLibraryRange_Simple+5:
  360.             case kGeometryLibraryRange_UVGeoAttributes+5:
  361.             case kGeometryLibraryRange_UVFaceAttributes+5:
  362.  
  363.                 /*
  364.                  * vvValue is the length of the cone side from point to the edge
  365.                  * uuValue is an angle used to revolve the cross section about the y axis
  366.                  */
  367.                 if (hasUVAttributes) {
  368.                     uuStep = 24.0;
  369.                     vvStep =  0.25;
  370.                 } else {
  371.                     uuStep = 10.0;
  372.                     vvStep =  0.25;
  373.                 }
  374.                 uuMin =   0.0;
  375.                 uuMax = 360.0;
  376.                 vvMin = -vvStep;
  377.                 vvMax =   2.0;
  378.  
  379.                 radius =  0.5;
  380.                 break;
  381.  
  382.             /**
  383.              ** Pipe
  384.              **/
  385.             case kGeometryLibraryRange_Simple+6:
  386.             case kGeometryLibraryRange_UVGeoAttributes+6:
  387.             case kGeometryLibraryRange_UVFaceAttributes+6:
  388.  
  389.                 /*
  390.                  * uuValue is used to revolve the line cross section about the y axis
  391.                  * vvValue is used to generate the length of the pipe
  392.                  */
  393.                 if (hasUVAttributes) {
  394.                     uuStep = 20.0;
  395.                     vvStep =  0.5;
  396.                 } else {
  397.                     uuStep = 15.0;
  398.                     vvStep =  0.3;
  399.                 }
  400.                 uuMin =   0.0;
  401.                 uuMax = 360.0;
  402.                 vvMin = - 1.5;
  403.                 vvMax =   1.5;
  404. #ifdef    FINISH_THIS
  405.                 vvMin = - 1.5 - vvStep;
  406.                 vvMax =   1.5 + vvStep;
  407. #else    /* FINISH_THIS */
  408.                 vvMin = - 1.5;
  409.                 vvMax =   1.5;
  410. #endif    /* FINISH_THIS */
  411.                 radius =  1.0;
  412.                 break;
  413.  
  414.             /**
  415.              ** Spring
  416.              **/
  417.             case kGeometryLibraryRange_Simple+8:
  418.             case kGeometryLibraryRange_UVGeoAttributes+8:
  419.             case kGeometryLibraryRange_UVFaceAttributes+8:
  420.  
  421.                 /*
  422.                  * uuValue is used to revolve the circular cross section about the springs' axis
  423.                  * vvValue is used to generate each circular cross section
  424.                  */
  425.                 #define    kSpringCrossRadius     0.25
  426.                 #define    kSpringInnerRadius     1.0
  427.                 #define    kSpringSpacing         3.5*kSpringCrossRadius
  428.  
  429.                 uuMin = - 90.0;
  430.                 uuMax =  810.0;
  431.                 vvMin = -180.0;
  432.                 vvMax =  180.0;
  433.                 if (hasUVAttributes) {
  434.                     uuStep = 30.0;
  435.                     vvStep = 30.0;
  436.                 } else {
  437.                     uuStep = 20.0;
  438.                     vvStep = 15.0;
  439.                 }
  440.                 break;
  441.  
  442.             default:
  443.                 DebugStr("\pWarning:  NewLibraryTriGrid ; unknown revolved trigrid index");
  444.                 return NULL;
  445.                 break;
  446.             }
  447.  
  448.  
  449.             /* Setup TQ3TriGridData */
  450.             data.numRows        = (unsigned long) ((vvMax - vvMin) / vvStep) + 1;
  451.             data.numColumns        = (unsigned long) ((uuMax - uuMin) / uuStep) + 1;
  452.             data.facetAttributeSet    = NULL;
  453.             data.triGridAttributeSet= NULL;
  454.  
  455.             data.vertices = (TQ3Vertex3D *) NewPtr (data.numRows * data.numColumns * sizeof(TQ3Vertex3D));
  456.             if (data.vertices == NULL)
  457.             {
  458.                 DebugStr("\pError:  NewLibraryTriGrid ; Out of memory for triGrid vertices.");
  459.                 return NULL;
  460.             }
  461.  
  462.             /* Set trigrid vertices and shading UVs, if it hasUVAttributes */
  463.             vertices = data.vertices;
  464.             i = 0;
  465.             for (vvValue = vvMin; vvValue <= vvMax; vvValue += vvStep)
  466.             {
  467.                 for (uuValue = uuMax; uuValue >= uuMin; uuValue -= uuStep)
  468.                 {
  469.                     switch (num)
  470.                     {
  471.                         /* Torus */
  472.                         case kGeometryLibraryRange_Simple+1:
  473.                         case kGeometryLibraryRange_UVGeoAttributes+1:
  474.                         case kGeometryLibraryRange_UVFaceAttributes+1:
  475.                             vertices[i].point.x = (uMath_Cos_Deg(vvValue) * kTorusCrossRadius + kTorusInnerRadius) * uMath_Cos_Deg(uuValue);
  476.                             vertices[i].point.y =  uMath_Sin_Deg(vvValue) * kTorusCrossRadius;
  477.                             vertices[i].point.z = (uMath_Cos_Deg(vvValue) * kTorusCrossRadius + kTorusInnerRadius) * uMath_Sin_Deg(uuValue);
  478.                         break;
  479.  
  480.                         /* Wavey Torus */
  481.                         case kGeometryLibraryRange_Simple+2:
  482.                         case kGeometryLibraryRange_UVGeoAttributes+2:
  483.                         case kGeometryLibraryRange_UVFaceAttributes+2:
  484.                             radius = kTorusCrossRadius / kTorusWaveyAmpRadius * uMath_Sin_Deg(kTorusWaveyAmpRadius * uuValue) + kTorusCrossRadius;
  485.                             vertices[i].point.x = (uMath_Cos_Deg(vvValue) * radius + kTorusInnerRadius) * uMath_Cos_Deg(uuValue);
  486.                             vertices[i].point.y =  uMath_Sin_Deg(vvValue) * radius;
  487.                             vertices[i].point.z = (uMath_Cos_Deg(vvValue) * radius + kTorusInnerRadius) * uMath_Sin_Deg(uuValue);
  488.                         break;
  489.  
  490.                         /* Sphere */
  491.                         case kGeometryLibraryRange_Simple+4:
  492.                         case kGeometryLibraryRange_UVGeoAttributes+4:
  493.                         case kGeometryLibraryRange_UVFaceAttributes+4:
  494.                             vertices[i].point.x = uMath_Cos_Deg(vvValue) * uMath_Cos_Deg(uuValue) * radius;
  495.                             vertices[i].point.y = uMath_Sin_Deg(vvValue) * radius;
  496.                             vertices[i].point.z = uMath_Cos_Deg(vvValue) * uMath_Sin_Deg(uuValue) * radius;
  497.                         break;
  498.  
  499.                         /* Cone */
  500.                         case kGeometryLibraryRange_Simple+5:
  501.                         case kGeometryLibraryRange_UVGeoAttributes+5:
  502.                         case kGeometryLibraryRange_UVFaceAttributes+5:
  503.                             if (vvValue < (vvMin + vvStep))
  504.                             {
  505.                                 vertices[i].point.x = 0.0;
  506.                                 vertices[i].point.y = vvMin + vvStep;
  507.                                 vertices[i].point.z = 0.0;
  508.                             }
  509.                             else
  510.                             {
  511.                                 vertices[i].point.x = (vvMax - vvValue) * uMath_Cos_Deg(uuValue) * radius;
  512.                                 vertices[i].point.y =  vvValue;
  513.                                 vertices[i].point.z = (vvMax - vvValue) * uMath_Sin_Deg(uuValue) * radius;
  514.                             }
  515.                         break;
  516.  
  517.                         /* Pipe */
  518.                         case kGeometryLibraryRange_Simple+6:
  519.                         case kGeometryLibraryRange_UVGeoAttributes+6:
  520.                         case kGeometryLibraryRange_UVFaceAttributes+6:
  521. #ifdef    FINISH_THIS
  522.                             if (vvValue < (vvMin + vvStep))
  523.                             {
  524.                                 vertices[i].point.x = 0.0;
  525.                                 vertices[i].point.y = vvMin + vvStep;
  526.                                 vertices[i].point.z = 0.0;
  527.                             }
  528.                             else
  529.                             if (vvValue > (vvMax - vvStep))
  530.                             {
  531.                                 vertices[i].point.x = 0.0;
  532.                                 vertices[i].point.y = vvMax - vvStep;
  533.                                 vertices[i].point.z = 0.0;
  534.                             }
  535.                             else
  536.                             {
  537.                                 vertices[i].point.x = uMath_Cos_Deg(uuValue) * radius;
  538.                                 vertices[i].point.y = vvValue;
  539.                                 vertices[i].point.z = uMath_Sin_Deg(uuValue) * radius;
  540.                             }
  541. #else    /* FINISH_THIS */
  542.                             vertices[i].point.x = radius * uMath_Cos_Deg(uuValue);
  543.                             vertices[i].point.y = vvValue;
  544.                             vertices[i].point.z = radius * uMath_Sin_Deg(uuValue);
  545. #endif    /* FINISH_THIS */
  546.                         break;
  547.  
  548.                         /* Spring */
  549.                         case kGeometryLibraryRange_Simple+8:
  550.                         case kGeometryLibraryRange_UVGeoAttributes+8:
  551.                         case kGeometryLibraryRange_UVFaceAttributes+8:
  552.                             vertices[i].point.x = (uMath_Cos_Deg(vvValue) * kSpringCrossRadius + kSpringInnerRadius) * uMath_Cos_Deg(uuValue);
  553.                             vertices[i].point.y =  uMath_Sin_Deg(vvValue) * kSpringCrossRadius + kSpringSpacing * uuValue/360.0;
  554.                             vertices[i].point.z = (uMath_Cos_Deg(vvValue) * kSpringCrossRadius + kSpringInnerRadius) * uMath_Sin_Deg(uuValue);
  555.                         break;
  556.                     }
  557.  
  558.                     if (hasUVAttributes)
  559.                     {
  560.                         if (mHasUVGeoAttributes(num))
  561.                         {
  562.                             param2D.u = 1.0 - ((uuValue - uuMin) / (uuMax - uuMin));
  563.                             param2D.v = (vvValue - vvMin) / (vvMax - vvMin);
  564.                         }
  565.                         else /* mHasUVFaceAttributes */
  566.                         {
  567.                             param2D.u = i % data.numColumns;
  568.                             param2D.v = i / data.numColumns;
  569.                         }
  570.  
  571.                         vertices[i].attributeSet = Q3AttributeSet_New();
  572.                         Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D);
  573.                     }
  574.                     else
  575.                         vertices[i].attributeSet = NULL;
  576.  
  577.                     i++;
  578.                 }
  579.             }
  580.  
  581.             geometryObject = Q3TriGrid_New (&data);
  582.  
  583.             if (hasUVAttributes)
  584.             {
  585.                 for (i = 0; i < data.numRows * data.numColumns; i++)
  586.                     Q3Object_Dispose(vertices[i].attributeSet);
  587.             }
  588.             DisposePtr ((void *) vertices);
  589.         }
  590.         break;
  591.  
  592.         default:
  593.             DebugStr("\pWarning:  NewLibraryTriGrid ; index unimplemented ");
  594.             break;
  595.     }
  596.     return    geometryObject;
  597. }
  598.