Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Sources/GeometrySample.c
/* |
GeometrySample.c |
This is a simple library illustrating trigrid geometries representing a |
Flat 5x5, Torus, Wavey Torus, Splash, Sphere, Cone, Pipe, Steps, and Spring. |
NewLibraryTriGrid returns a trigrid geometry when kGeometryLibraryRange_Simple |
is added to the trigrid number (0 to 8) or a trigrid with shading uv attributes |
when kGeometryLibraryRange_UVGeoAttributes or kGeometryLibraryRange_UVFaceAttributes |
is added to the trigrid number. |
Note: The calculation of uv's may be flipping the texture. |
Robert Dierkes - March 22, 1995 |
© 1995 Apple Computer, Inc. |
Modification History: |
03/22/95 rdd initial version |
*/ |
#include <Memory.h> |
#include "math.h" |
#include "QD3D.h" |
#include "QD3DGeometry.h" |
#include "QD3DMath.h" |
#include "AttributeSet_Lib.h" |
#include "GeometrySample.h" |
#include "MathUtilities.h" |
unsigned long GetLibraryMaxSimpleTriGrid(void) |
{ |
return kGeometryLibrary_TriGridMaxSimple; |
} |
/* |
* NewLibraryTriGrid |
* |
* There are two methods below for creating trigrid vertices. If the trigrid is: |
* |
* 1. planar (relatively) then the vvValue (an x-coordinate) increases from vvMin to vvMax. |
* 2. a cross section revolved about the Y axis then the vvValue (an angle) decreases from |
* vvMax to vvMin in a counter-clockwise manner about the axis. This puts the correct |
* side of the trigrid facing outward for texture uvs. |
* |
* In both cases, uuValue decreases from uuMax to uuMin from postive to negative Y. |
* |
* TriGrid vertex index numbering |
* |
* (i) |
* 8 9 10 11 |
* 4 5 6 7 |
* 0 1 2 3 |
* |
* |
* UVs for an upright texture continuous across the trigrid |
* |
* (U,V) |
* (x,y) |
* |
* ^ + 0.0, 1.0 0.33, 1.0 0.66, 1.0 1.0, 1.0 |
* | 0.0, 0.5 0.33, 0.5 0.66, 0.5 1.0, 0.5 |
* V - 0.0, 0.0 0.33, 0.0 0.66, 0.0 1.0, 0.0 |
* |
* U --> |
* - + |
* |
* UVs for an upright repeated texture |
* |
* (U,V) |
* (x,y) |
* |
* ^ + 0,2 1,2 2,2 3,2 |
* | 0,1 1,1 2,1 3,1 |
* V - 0,0 1,0 2,0 3,0 |
* |
* U --> |
* - + |
*/ |
TQ3GeometryObject NewLibraryTriGrid(unsigned long num) |
{ |
TQ3GeometryObject geometryObject = NULL; |
TQ3TriGridData data; |
TQ3Vertex3D *vertices; |
unsigned long i; |
float uuValue, vvValue, |
uuMin, uuMax, uuStep, |
vvMin, vvMax, vvStep, |
radius; |
TQ3Boolean hasUVAttributes; |
TQ3Param2D param2D; |
hasUVAttributes = (TQ3Boolean) (mHasUVGeoAttributes(num) || mHasUVFaceAttributes(num)); |
switch (num) |
{ |
case kGeometryLibraryRange_Simple+0: // Flat 5x5 |
case kGeometryLibraryRange_UVGeoAttributes+0: |
case kGeometryLibraryRange_UVFaceAttributes+0: |
case kGeometryLibraryRange_Simple+3: // Splash |
case kGeometryLibraryRange_UVGeoAttributes+3: |
case kGeometryLibraryRange_UVFaceAttributes+3: |
case kGeometryLibraryRange_Simple+7: // Steps |
case kGeometryLibraryRange_UVGeoAttributes+7: |
case kGeometryLibraryRange_UVFaceAttributes+7: |
{ |
/* Setup min, max and step values trigrid vertex u & v values */ |
switch (num) |
{ |
/** |
** Flat 5x5 |
**/ |
case kGeometryLibraryRange_Simple+0: |
case kGeometryLibraryRange_UVGeoAttributes+0: |
case kGeometryLibraryRange_UVFaceAttributes+0: |
/* |
* uuValue is an x-coordinate |
* vvValue is a y-coordinate |
*/ |
uuMin = -0.5; |
uuMax = 0.5; |
uuStep = 0.25; |
vvMin = -0.5; |
vvMax = 0.5; |
vvStep = 0.25; |
break; |
/** |
** Splash |
**/ |
case kGeometryLibraryRange_Simple+3: |
case kGeometryLibraryRange_UVGeoAttributes+3: |
case kGeometryLibraryRange_UVFaceAttributes+3: |
/* |
* uuValue is an x-coordinate |
* vvValue is a y-coordinate |
*/ |
uuMin = -3.5; |
uuMax = 3.5; |
vvMin = -3.5; |
vvMax = 3.5; |
if (hasUVAttributes) { |
uuStep = 0.35; |
vvStep = 0.35; |
} else { |
uuStep = 0.25; |
vvStep = 0.25; |
} |
break; |
/** |
** Steps |
**/ |
case kGeometryLibraryRange_Simple+7: |
case kGeometryLibraryRange_UVGeoAttributes+7: |
case kGeometryLibraryRange_UVFaceAttributes+7: |
/* |
* uuValue is an x-coordinate |
* vvValue is a y-coordinate |
*/ |
#define kStepScale 0.2 |
uuMin = -4.5; |
uuMax = 4.5; |
uuStep = 0.5; |
vvMin = -4.5; |
vvMax = 4.5; |
vvStep = 0.5; |
break; |
default: |
DebugStr("\pWarning: NewLibraryTriGrid ; unknown flat trigrid index"); |
return NULL; |
break; |
} |
/* Setup TQ3TriGridData */ |
data.numRows = (unsigned long) ((vvMax - vvMin) / vvStep) + 1; |
data.numColumns = (unsigned long) ((uuMax - uuMin) / uuStep) + 1; |
data.facetAttributeSet = NULL; |
data.triGridAttributeSet= NULL; |
data.vertices = (TQ3Vertex3D *) NewPtr (data.numRows * data.numColumns * sizeof(TQ3Vertex3D)); |
if (data.vertices == NULL) |
{ |
DebugStr("\pError: NewLibraryTriGrid ; Out of memory for triGrid vertices, geometry library number"); |
return NULL; |
} |
/* Set trigrid vertices and shading UVs, if it hasUVAttributes */ |
vertices = data.vertices; |
i = 0; |
for (vvValue = vvMin; vvValue <= vvMax; vvValue += vvStep) |
{ |
for (uuValue = uuMin; uuValue <= uuMax; uuValue += uuStep) |
{ |
switch (num) |
{ |
/* Flat 5x5 */ |
case kGeometryLibraryRange_Simple+0: |
case kGeometryLibraryRange_UVGeoAttributes+0: |
case kGeometryLibraryRange_UVFaceAttributes+0: |
vertices[i].point.x = uuValue; |
vertices[i].point.y = vvValue; |
vertices[i].point.z = 0; |
break; |
/* Splash */ |
case kGeometryLibraryRange_Simple+3: |
case kGeometryLibraryRange_UVGeoAttributes+3: |
case kGeometryLibraryRange_UVFaceAttributes+3: |
vertices[i].point.x = uuValue; |
vertices[i].point.y = vvValue; |
vertices[i].point.z = 1.5 * uMath_Sin_Deg(48.0 * uuValue * vvValue) * |
uMath_Cos_Deg(48.0 * uuValue * vvValue); |
break; |
/* Steps */ |
case kGeometryLibraryRange_Simple+7: |
case kGeometryLibraryRange_UVGeoAttributes+7: |
case kGeometryLibraryRange_UVFaceAttributes+7: |
vertices[i].point.x = uuValue; |
vertices[i].point.y = vvValue; |
vertices[i].point.z = kStepScale * (((long) uuValue) % ((data.numRows-1)/2)) * |
(((long) vvValue) % ((data.numColumns-1)/2)); |
break; |
} |
if (hasUVAttributes) |
{ |
if (mHasUVGeoAttributes(num)) |
{ |
param2D.u = (uuValue - uuMin) / (uuMax - uuMin); |
param2D.v = (vvValue - vvMin) / (vvMax - vvMin); |
} |
else /* mHasUVFaceAttributes */ |
{ |
param2D.u = i % data.numColumns; |
param2D.v = i / data.numColumns; |
} |
vertices[i].attributeSet = Q3AttributeSet_New(); |
Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D); |
} |
else |
vertices[i].attributeSet = NULL; |
i++; |
} |
} |
geometryObject = Q3TriGrid_New (&data); |
if (hasUVAttributes) |
{ |
for (i = 0; i < data.numRows * data.numColumns; i++) |
Q3Object_Dispose(vertices[i].attributeSet); |
} |
DisposePtr ((void *) vertices); |
} |
break; |
case kGeometryLibraryRange_Simple+1: // Torus |
case kGeometryLibraryRange_UVGeoAttributes+1: |
case kGeometryLibraryRange_UVFaceAttributes+1: |
case kGeometryLibraryRange_Simple+2: // Wavey Torus |
case kGeometryLibraryRange_UVGeoAttributes+2: |
case kGeometryLibraryRange_UVFaceAttributes+2: |
case kGeometryLibraryRange_Simple+4: // Sphere |
case kGeometryLibraryRange_UVGeoAttributes+4: |
case kGeometryLibraryRange_UVFaceAttributes+4: |
case kGeometryLibraryRange_Simple+5: // Cone |
case kGeometryLibraryRange_UVGeoAttributes+5: |
case kGeometryLibraryRange_UVFaceAttributes+5: |
case kGeometryLibraryRange_Simple+6: // Pipe |
case kGeometryLibraryRange_UVGeoAttributes+6: |
case kGeometryLibraryRange_UVFaceAttributes+6: |
case kGeometryLibraryRange_Simple+8: // Spring |
case kGeometryLibraryRange_UVGeoAttributes+8: |
case kGeometryLibraryRange_UVFaceAttributes+8: |
{ |
/* Setup min, max and step values trigrid vertex u & v values */ |
switch (num) |
{ |
/** |
** Torus |
**/ |
case kGeometryLibraryRange_Simple+1: |
case kGeometryLibraryRange_UVGeoAttributes+1: |
case kGeometryLibraryRange_UVFaceAttributes+1: |
/** |
** Wavey Torus |
**/ |
case kGeometryLibraryRange_Simple+2: |
case kGeometryLibraryRange_UVGeoAttributes+2: |
case kGeometryLibraryRange_UVFaceAttributes+2: |
/* |
* uuValue is used to generate each circular cross section about the y axis |
* vvValue is used to revolve the circular cross section about the torus' center |
*/ |
#define kTorusCrossRadius 0.5 |
#define kTorusInnerRadius 1.0 |
#define kTorusWaveyAmpRadius 5.0 |
uuMin = 0.0; |
uuMax = 360.0; |
vvMin = -180.0; |
vvMax = 180.0; |
if (hasUVAttributes) { |
uuStep = 12.0; |
vvStep = 12.0; |
} else { |
uuStep = 10.0; |
vvStep = 10.0; |
} |
break; |
/** |
** Sphere |
**/ |
case kGeometryLibraryRange_Simple+4: |
case kGeometryLibraryRange_UVGeoAttributes+4: |
case kGeometryLibraryRange_UVFaceAttributes+4: |
/* |
* uuValue is an angle used to revolve the cross section about the y axis |
* vvValue is an angle used to generate each half circular cross section |
*/ |
uuMin = 0.0; |
uuMax = 360.0; |
vvMin = - 90.0; |
vvMax = 90.0; |
if (hasUVAttributes) { |
uuStep = 12.0; |
vvStep = 12.0; |
} else { |
uuStep = 9.0; |
vvStep = 9.0; |
} |
radius = 1.0; |
break; |
/** |
** Cone |
**/ |
case kGeometryLibraryRange_Simple+5: |
case kGeometryLibraryRange_UVGeoAttributes+5: |
case kGeometryLibraryRange_UVFaceAttributes+5: |
/* |
* vvValue is the length of the cone side from point to the edge |
* uuValue is an angle used to revolve the cross section about the y axis |
*/ |
if (hasUVAttributes) { |
uuStep = 24.0; |
vvStep = 0.25; |
} else { |
uuStep = 10.0; |
vvStep = 0.25; |
} |
uuMin = 0.0; |
uuMax = 360.0; |
vvMin = -vvStep; |
vvMax = 2.0; |
radius = 0.5; |
break; |
/** |
** Pipe |
**/ |
case kGeometryLibraryRange_Simple+6: |
case kGeometryLibraryRange_UVGeoAttributes+6: |
case kGeometryLibraryRange_UVFaceAttributes+6: |
/* |
* uuValue is used to revolve the line cross section about the y axis |
* vvValue is used to generate the length of the pipe |
*/ |
if (hasUVAttributes) { |
uuStep = 20.0; |
vvStep = 0.5; |
} else { |
uuStep = 15.0; |
vvStep = 0.3; |
} |
uuMin = 0.0; |
uuMax = 360.0; |
vvMin = - 1.5; |
vvMax = 1.5; |
#ifdef FINISH_THIS |
vvMin = - 1.5 - vvStep; |
vvMax = 1.5 + vvStep; |
#else /* FINISH_THIS */ |
vvMin = - 1.5; |
vvMax = 1.5; |
#endif /* FINISH_THIS */ |
radius = 1.0; |
break; |
/** |
** Spring |
**/ |
case kGeometryLibraryRange_Simple+8: |
case kGeometryLibraryRange_UVGeoAttributes+8: |
case kGeometryLibraryRange_UVFaceAttributes+8: |
/* |
* uuValue is used to revolve the circular cross section about the springs' axis |
* vvValue is used to generate each circular cross section |
*/ |
#define kSpringCrossRadius 0.25 |
#define kSpringInnerRadius 1.0 |
#define kSpringSpacing 3.5*kSpringCrossRadius |
uuMin = - 90.0; |
uuMax = 810.0; |
vvMin = -180.0; |
vvMax = 180.0; |
if (hasUVAttributes) { |
uuStep = 30.0; |
vvStep = 30.0; |
} else { |
uuStep = 20.0; |
vvStep = 15.0; |
} |
break; |
default: |
DebugStr("\pWarning: NewLibraryTriGrid ; unknown revolved trigrid index"); |
return NULL; |
break; |
} |
/* Setup TQ3TriGridData */ |
data.numRows = (unsigned long) ((vvMax - vvMin) / vvStep) + 1; |
data.numColumns = (unsigned long) ((uuMax - uuMin) / uuStep) + 1; |
data.facetAttributeSet = NULL; |
data.triGridAttributeSet= NULL; |
data.vertices = (TQ3Vertex3D *) NewPtr (data.numRows * data.numColumns * sizeof(TQ3Vertex3D)); |
if (data.vertices == NULL) |
{ |
DebugStr("\pError: NewLibraryTriGrid ; Out of memory for triGrid vertices."); |
return NULL; |
} |
/* Set trigrid vertices and shading UVs, if it hasUVAttributes */ |
vertices = data.vertices; |
i = 0; |
for (vvValue = vvMin; vvValue <= vvMax; vvValue += vvStep) |
{ |
for (uuValue = uuMax; uuValue >= uuMin; uuValue -= uuStep) |
{ |
switch (num) |
{ |
/* Torus */ |
case kGeometryLibraryRange_Simple+1: |
case kGeometryLibraryRange_UVGeoAttributes+1: |
case kGeometryLibraryRange_UVFaceAttributes+1: |
vertices[i].point.x = (uMath_Cos_Deg(vvValue) * kTorusCrossRadius + kTorusInnerRadius) * uMath_Cos_Deg(uuValue); |
vertices[i].point.y = uMath_Sin_Deg(vvValue) * kTorusCrossRadius; |
vertices[i].point.z = (uMath_Cos_Deg(vvValue) * kTorusCrossRadius + kTorusInnerRadius) * uMath_Sin_Deg(uuValue); |
break; |
/* Wavey Torus */ |
case kGeometryLibraryRange_Simple+2: |
case kGeometryLibraryRange_UVGeoAttributes+2: |
case kGeometryLibraryRange_UVFaceAttributes+2: |
radius = kTorusCrossRadius / kTorusWaveyAmpRadius * uMath_Sin_Deg(kTorusWaveyAmpRadius * uuValue) + kTorusCrossRadius; |
vertices[i].point.x = (uMath_Cos_Deg(vvValue) * radius + kTorusInnerRadius) * uMath_Cos_Deg(uuValue); |
vertices[i].point.y = uMath_Sin_Deg(vvValue) * radius; |
vertices[i].point.z = (uMath_Cos_Deg(vvValue) * radius + kTorusInnerRadius) * uMath_Sin_Deg(uuValue); |
break; |
/* Sphere */ |
case kGeometryLibraryRange_Simple+4: |
case kGeometryLibraryRange_UVGeoAttributes+4: |
case kGeometryLibraryRange_UVFaceAttributes+4: |
vertices[i].point.x = uMath_Cos_Deg(vvValue) * uMath_Cos_Deg(uuValue) * radius; |
vertices[i].point.y = uMath_Sin_Deg(vvValue) * radius; |
vertices[i].point.z = uMath_Cos_Deg(vvValue) * uMath_Sin_Deg(uuValue) * radius; |
break; |
/* Cone */ |
case kGeometryLibraryRange_Simple+5: |
case kGeometryLibraryRange_UVGeoAttributes+5: |
case kGeometryLibraryRange_UVFaceAttributes+5: |
if (vvValue < (vvMin + vvStep)) |
{ |
vertices[i].point.x = 0.0; |
vertices[i].point.y = vvMin + vvStep; |
vertices[i].point.z = 0.0; |
} |
else |
{ |
vertices[i].point.x = (vvMax - vvValue) * uMath_Cos_Deg(uuValue) * radius; |
vertices[i].point.y = vvValue; |
vertices[i].point.z = (vvMax - vvValue) * uMath_Sin_Deg(uuValue) * radius; |
} |
break; |
/* Pipe */ |
case kGeometryLibraryRange_Simple+6: |
case kGeometryLibraryRange_UVGeoAttributes+6: |
case kGeometryLibraryRange_UVFaceAttributes+6: |
#ifdef FINISH_THIS |
if (vvValue < (vvMin + vvStep)) |
{ |
vertices[i].point.x = 0.0; |
vertices[i].point.y = vvMin + vvStep; |
vertices[i].point.z = 0.0; |
} |
else |
if (vvValue > (vvMax - vvStep)) |
{ |
vertices[i].point.x = 0.0; |
vertices[i].point.y = vvMax - vvStep; |
vertices[i].point.z = 0.0; |
} |
else |
{ |
vertices[i].point.x = uMath_Cos_Deg(uuValue) * radius; |
vertices[i].point.y = vvValue; |
vertices[i].point.z = uMath_Sin_Deg(uuValue) * radius; |
} |
#else /* FINISH_THIS */ |
vertices[i].point.x = radius * uMath_Cos_Deg(uuValue); |
vertices[i].point.y = vvValue; |
vertices[i].point.z = radius * uMath_Sin_Deg(uuValue); |
#endif /* FINISH_THIS */ |
break; |
/* Spring */ |
case kGeometryLibraryRange_Simple+8: |
case kGeometryLibraryRange_UVGeoAttributes+8: |
case kGeometryLibraryRange_UVFaceAttributes+8: |
vertices[i].point.x = (uMath_Cos_Deg(vvValue) * kSpringCrossRadius + kSpringInnerRadius) * uMath_Cos_Deg(uuValue); |
vertices[i].point.y = uMath_Sin_Deg(vvValue) * kSpringCrossRadius + kSpringSpacing * uuValue/360.0; |
vertices[i].point.z = (uMath_Cos_Deg(vvValue) * kSpringCrossRadius + kSpringInnerRadius) * uMath_Sin_Deg(uuValue); |
break; |
} |
if (hasUVAttributes) |
{ |
if (mHasUVGeoAttributes(num)) |
{ |
param2D.u = 1.0 - ((uuValue - uuMin) / (uuMax - uuMin)); |
param2D.v = (vvValue - vvMin) / (vvMax - vvMin); |
} |
else /* mHasUVFaceAttributes */ |
{ |
param2D.u = i % data.numColumns; |
param2D.v = i / data.numColumns; |
} |
vertices[i].attributeSet = Q3AttributeSet_New(); |
Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D); |
} |
else |
vertices[i].attributeSet = NULL; |
i++; |
} |
} |
geometryObject = Q3TriGrid_New (&data); |
if (hasUVAttributes) |
{ |
for (i = 0; i < data.numRows * data.numColumns; i++) |
Q3Object_Dispose(vertices[i].attributeSet); |
} |
DisposePtr ((void *) vertices); |
} |
break; |
default: |
DebugStr("\pWarning: NewLibraryTriGrid ; index unimplemented "); |
break; |
} |
return geometryObject; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14