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.
Txtr_Geometry.c
/* |
* Txtr_Geometry.c |
* |
* This is a simple library illustrating trigrid and box geometries. The trigrids |
* represented are Square, 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 |
* © 1995 Apple Computer, Inc. |
* |
* 03/22/95 RDD Created. |
* 09/20/95 RDD Cleanup. |
* 11/13/95 RDD Changed macro to DebugStr. |
*/ |
/*------------------*/ |
/* Include Files */ |
/*------------------*/ |
#include <Memory.h> |
#include <math.h> |
#include "QD3D.h" |
#include "QD3DGeometry.h" |
#include "QD3DMath.h" |
#include "QD3DSet.h" |
#include "Txtr_Geometry.h" |
#include "Txtr_Math.h" |
#include "Txtr_Error.h" |
/*----------------------*/ |
/* Local Prototypes */ |
/*----------------------*/ |
static |
void AddVertexNormals( |
unsigned long geoNum, |
TQ3TriGridData *pTriData); |
unsigned long GetLibraryMaxSimpleBox(void) |
{ |
return kGeometryLibrary_BoxMaxSimple; |
} |
unsigned long GetLibraryMaxSimpleTriGrid(void) |
{ |
return kGeometryLibrary_TriGridMaxSimple; |
} |
TQ3GeometryObject NewLibraryBox( |
unsigned long num) |
{ |
TQ3GeometryObject geometryObject = NULL; |
TQ3BoxData boxData; |
switch (num) |
{ |
case kGeometryLibraryRange_Simple+0: /* Box */ |
Q3Point3D_Set(&boxData.origin, -0.5,-0.5,-0.5); |
Q3Vector3D_Set(&boxData.orientation, 0.0, 1.0, 0.0); |
Q3Vector3D_Set(&boxData.majorAxis, 0.0, 0.0, 1.0); |
Q3Vector3D_Set(&boxData.minorAxis, 1.0, 0.0, 0.0); |
boxData.boxAttributeSet = NULL; |
boxData.faceAttributeSet = NULL; |
geometryObject = Q3Box_New(&boxData); |
break; |
case kGeometryLibraryRange_Simple+1: /* Skewed Box */ |
Q3Point3D_Set(&boxData.origin, -0.75,-0.5,-0.75); |
Q3Vector3D_Set(&boxData.orientation, 0.5, 1.0, 0.5); |
Q3Vector3D_Set(&boxData.majorAxis, 0.0, 0.0, 1.0); |
Q3Vector3D_Set(&boxData.minorAxis, 1.0, 0.0, 0.0); |
boxData.boxAttributeSet = NULL; |
boxData.faceAttributeSet = NULL; |
geometryObject = Q3Box_New(&boxData); |
break; |
default: |
DebugStr("\pWarning: NewLibraryBox ; unknown box index"); |
return NULL; |
break; |
} |
return geometryObject; |
} |
/* |
* 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; |
TQ3Boolean addNormals; |
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: |
{ |
addNormals = kQ3False; |
/* 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: |
addNormals = kQ3True; |
/* |
* 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 *) NewPtrClear (data.numRows * data.numColumns * sizeof(TQ3Vertex3D)); |
if (data.vertices == NULL) |
{ |
ERROR_DEBUG_STR("Error: 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(); |
if (vertices[i].attributeSet != NULL) |
Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D); |
} |
else |
vertices[i].attributeSet = NULL; |
i++; |
} |
} |
if (addNormals) |
AddVertexNormals(num, &data); |
geometryObject = Q3TriGrid_New (&data); |
if (hasUVAttributes) |
{ |
for (i = 0; i < data.numRows * data.numColumns; i++) |
{ |
if (vertices[i].attributeSet != NULL) |
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: |
addNormals = kQ3True; |
/* |
* 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; /* 10.0; */ |
vvStep = 12.0; /* 10.0; */ |
} else { |
uuStep = 10.0; |
vvStep = 10.0; |
} |
break; |
/** |
** Sphere |
**/ |
case kGeometryLibraryRange_Simple+4: |
case kGeometryLibraryRange_UVGeoAttributes+4: |
case kGeometryLibraryRange_UVFaceAttributes+4: |
addNormals = kQ3True; |
/* |
* 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; /* 10.0; */ |
vvStep = 12.0; /* 10.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: |
addNormals = kQ3True; |
/* |
* 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; /* 15.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: |
addNormals = kQ3True; |
/* |
* 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; /* 10.0; */ |
vvStep = 0.5; |
} else { |
uuStep = 10.0; /* 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: |
addNormals = kQ3True; |
/* |
* 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 = 15.0; /* 30.0; */ |
vvStep = 30.0; |
} else { |
uuStep = 15.0; /* 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 *) NewPtrClear (data.numRows * data.numColumns * sizeof(TQ3Vertex3D)); |
if (data.vertices == NULL) |
{ |
ERROR_DEBUG_STR("Error: 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(); |
if (vertices[i].attributeSet != NULL) |
Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D); |
} |
else |
vertices[i].attributeSet = NULL; |
i++; |
} |
} |
if (addNormals) |
AddVertexNormals(num, &data); |
geometryObject = Q3TriGrid_New (&data); |
if (hasUVAttributes) |
{ |
for (i = 0; i < data.numRows * data.numColumns; i++) |
{ |
if (vertices[i].attributeSet != NULL) |
Q3Object_Dispose(vertices[i].attributeSet); |
} |
} |
DisposePtr ((void *) vertices); |
} |
break; |
default: |
DebugStr("\pWarning: NewLibraryTriGrid ; index unimplemented "); |
break; |
} |
return geometryObject; |
} |
void AddVertexNormals( |
unsigned long geoNum, |
TQ3TriGridData *pTriData) |
{ |
TQ3Vector3D vector3D; |
TQ3Point3D point3D; |
TQ3Vertex3D *pVertices; |
unsigned long i, |
j, |
k; |
pVertices = pTriData->vertices; |
if ( |
/* Torus */ |
geoNum == kGeometryLibraryRange_Simple+1 || |
geoNum == kGeometryLibraryRange_UVGeoAttributes+1 || |
geoNum == kGeometryLibraryRange_UVFaceAttributes+1 || |
/* Wavey Torus */ |
geoNum == kGeometryLibraryRange_Simple+2 || |
geoNum == kGeometryLibraryRange_UVGeoAttributes+2 || |
geoNum == kGeometryLibraryRange_UVFaceAttributes+2 || |
/* Spring */ |
geoNum == kGeometryLibraryRange_Simple+8 || |
geoNum == kGeometryLibraryRange_UVGeoAttributes+8 || |
geoNum == kGeometryLibraryRange_UVFaceAttributes+8 |
) |
{ |
unsigned long i2; |
i2 = pTriData->numColumns * (pTriData->numRows/2); |
#define p1 pVertices[i].point |
#define p2 pVertices[i2].point |
i = 0; |
for (k = 0; k < pTriData->numRows / 2; k++) |
{ |
for (j = 0; j < pTriData->numColumns; j++) |
{ |
/* Create an attribute set for non-textured geometry */ |
if (pVertices[i ].attributeSet == NULL) |
pVertices[i ].attributeSet = Q3AttributeSet_New(); |
if (pVertices[i2].attributeSet == NULL) |
pVertices[i2].attributeSet = Q3AttributeSet_New(); |
switch (geoNum) |
{ |
/* 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: |
/* Spring */ |
case kGeometryLibraryRange_Simple+8: |
case kGeometryLibraryRange_UVGeoAttributes+8: |
case kGeometryLibraryRange_UVFaceAttributes+8: |
/* point3D is midpoint */ |
Q3Point3D_Set (&point3D, |
(uMath_Fabs(p2.x - p1.x) / 2) + uMath_Min(p1.x, p2.x), |
(uMath_Fabs(p2.y - p1.y) / 2) + uMath_Min(p1.y, p2.y), |
(uMath_Fabs(p2.z - p1.z) / 2) + uMath_Min(p1.z, p2.z) |
); |
Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D); |
break; |
} |
if ((i % pTriData->numColumns) != (pTriData->numRows / 2)) |
{ |
Q3Vector3D_Normalize(&vector3D, &vector3D); |
Q3AttributeSet_Add(pVertices[i].attributeSet, kQ3AttributeTypeNormal, &vector3D); |
} |
Q3Vector3D_Negate(&vector3D, &vector3D); |
Q3Vector3D_Normalize(&vector3D, &vector3D); |
Q3AttributeSet_Add(pVertices[i2].attributeSet, kQ3AttributeTypeNormal, &vector3D); |
i++; |
i2++; |
} |
} |
#undef p1 |
#undef p2 |
return; |
} |
else |
if ( |
/* Splash */ |
geoNum == kGeometryLibraryRange_Simple+3 || |
geoNum == kGeometryLibraryRange_UVGeoAttributes+3 || |
geoNum == kGeometryLibraryRange_UVFaceAttributes+3 |
) |
{ |
TQ3Point3D point3Dc, |
point3Dr; |
/* C = numColumns |
* i = vertex index |
* |
* i+C |
* |
* i-1 i i+1 |
* |
* i-C |
*/ |
#define pL pVertices[i-1].point |
#define pR pVertices[i+1].point |
#define pT pVertices[i+pTriData->numColumns].point |
#define pB pVertices[i-pTriData->numColumns].point |
#define pH point3Dc |
#define pV point3Dr |
i = pTriData->numColumns + 1; |
for (k = 1; |
k <= pTriData->numRows - 2; |
k++) |
{ |
for (j = 1; |
j <= pTriData->numColumns - 2; |
j++) |
{ |
/* Create an attribute set for non-textured geometry */ |
if (pVertices[i].attributeSet == NULL) |
pVertices[i].attributeSet = Q3AttributeSet_New(); |
/* point3Dc, point3Dr, point3D are midpoints */ |
/* i-1 and i+1 */ |
Q3Point3D_Set (&point3Dc, |
(uMath_Fabs(pR.x - pL.x) / 2) + uMath_Min(pL.x, pR.x), |
(uMath_Fabs(pR.y - pL.y) / 2) + uMath_Min(pL.y, pR.y), |
(uMath_Fabs(pR.z - pL.z) / 2) + uMath_Min(pL.z, pR.z) |
); |
/* i-C and i+C */ |
Q3Point3D_Set (&point3Dr, |
(uMath_Fabs(pT.x - pB.x) / 2) + uMath_Min(pB.x, pT.x), |
(uMath_Fabs(pT.y - pB.y) / 2) + uMath_Min(pB.y, pT.y), |
(uMath_Fabs(pT.z - pB.z) / 2) + uMath_Min(pB.z, pT.z) |
); |
/* point3Dc and point3Dr */ |
Q3Point3D_Set (&point3D, |
(uMath_Fabs(pH.x - pV.x) / 2) + uMath_Min(pV.x, pH.x), |
(uMath_Fabs(pH.y - pV.y) / 2) + uMath_Min(pV.y, pH.y), |
(uMath_Fabs(pH.z - pV.z) / 2) + uMath_Min(pV.z, pH.z) |
); |
Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D); |
Q3Vector3D_Normalize(&vector3D, &vector3D); |
Q3AttributeSet_Add(pVertices[i].attributeSet, kQ3AttributeTypeNormal, &vector3D); |
i += ((i+2) % pTriData->numColumns == 0) ? 3 : 1; |
} |
} |
#undef pL |
#undef pR |
#undef pT |
#undef pB |
#undef pH |
#undef pV |
return; |
} |
/* |
* Sphere |
* Cone |
* Pipe |
*/ |
i = 0; |
for (k = 0; k < pTriData->numRows; k++) |
{ |
for (j = 0; j < pTriData->numColumns; j++) |
{ |
/* Create an attribute set for non-textured geometry */ |
if (pVertices[i].attributeSet == NULL) |
pVertices[i].attributeSet = Q3AttributeSet_New(); |
switch (geoNum) |
{ |
/* Sphere */ |
case kGeometryLibraryRange_Simple+4: |
case kGeometryLibraryRange_UVGeoAttributes+4: |
case kGeometryLibraryRange_UVFaceAttributes+4: |
Q3Point3D_Set (&point3D, 0.0, 0.0, 0.0); |
Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D); |
break; |
/* Cone */ |
case kGeometryLibraryRange_Simple+5: |
case kGeometryLibraryRange_UVGeoAttributes+5: |
case kGeometryLibraryRange_UVFaceAttributes+5: |
Q3Point3D_Set ( &point3D, |
0.0, |
/**/ ((pVertices[i].point.y > kQ3RealZero) || |
(pVertices[i].point.y == kQ3RealZero && |
Q3Vector3D_Length((TQ3Vector3D *) &pVertices[i].point) == 0.5)) |
? pVertices[i].point.y |
: 100.0, |
0.0); |
Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D); |
break; |
/* Pipe */ |
case kGeometryLibraryRange_Simple+6: |
case kGeometryLibraryRange_UVGeoAttributes+6: |
case kGeometryLibraryRange_UVFaceAttributes+6: |
Q3Point3D_Set (&point3D, 0.0, pVertices[i].point.y, 0.0); |
Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D); |
break; |
} |
Q3Vector3D_Normalize(&vector3D, &vector3D); |
Q3AttributeSet_Add(pVertices[i].attributeSet, kQ3AttributeTypeNormal, &vector3D); |
i++; |
} /* for j */ |
} /* for k */ |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14