home *** CD-ROM | disk | FTP | other *** search
- // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
- // see COPYRIGHT for reuse legalities
- //
-
- #import "RIBTorus.h"
- #import <stdio.h>
-
-
- @implementation RIBTorus
-
- + initialize { return [RIBTorus setVersion:1], self; }
-
- - (BOOL)hasBoundingBox { return YES; }
-
- - init
- {
- [super init];
-
- majorRadius = 1.0;
- minorRadius = 0.5;
- phiMin = 0.0;
- phiMax = 360.0;
-
- return self;
- }
-
- - setMajorRadius:(RtFloat)newMajorRadius minorRadius:(RtFloat)newMinorRadius
- phiMin:(RtFloat)newPhiMin phiMax:(RtFloat)newPhiMax
- thetaMax:(RtFloat)newThetaMax
- n:(int)newN tokens:(RtToken *)newTokens parms:(RtPointer *)newParms archiveVector:(char **)newArchiveVector
- printfTypeVector:(int *)newPrintfTypeVector printfNVector:(int *)newPrintfNVector
- {
- majorRadius = newMajorRadius;
- minorRadius = newMinorRadius;
- phiMin = newPhiMin;
- phiMax = newPhiMax;
- thetaMax = newThetaMax;
- [self setN:newN tokens:newTokens parms:newParms archiveVector:newArchiveVector printfTypeVector:newPrintfTypeVector printfNVector:newPrintfNVector];
-
- dirtyBoundingBox = TRUE;
-
- return self;
- }
-
- - setMajorRadius:(RtFloat)newMajorRadius { majorRadius = newMajorRadius; dirtyBoundingBox = TRUE; return self; }
- - setMinorRadius:(RtFloat)newMinorRadius { minorRadius = newMinorRadius; dirtyBoundingBox = TRUE; return self; }
- - setPhiMin:(RtFloat)newPhiMin { phiMin = newPhiMin; dirtyBoundingBox = TRUE; return self; }
- - setPhiMax:(RtFloat)newPhiMax { phiMax = newPhiMax; dirtyBoundingBox = TRUE; return self; }
-
- - (RtFloat)majorRadius { return majorRadius; }
- - (RtFloat)minorRadius { return minorRadius; }
- - (RtFloat)phiMin { return phiMin; }
- - (RtFloat)phiMax { return phiMax; }
-
- - (BOOL)hasboundingBox { return YES; }
-
- - calculateBoundingBoxStartingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- {
- // WAVE: FILL ME IN CORRECTLY!!!
- boundingBox[0] = -1.0 * (majorRadius + minorRadius);
- boundingBox[1] = majorRadius + minorRadius;
-
- if (thetaMax >= 270.0)
- { boundingBox[2] = -1.0 * (majorRadius + minorRadius);
- boundingBox[3] = majorRadius + minorRadius;
- }
- else
- { if (thetaMax >= 180.0)
- { boundingBox[2] = (majorRadius + minorRadius) * sin((double)(toRadians((thetaMax))));
- boundingBox[3] = (majorRadius + minorRadius);
- }
- else
- { if (thetaMax >= 90.0)
- { boundingBox[2] = 0.0;
- boundingBox[3] = (majorRadius + minorRadius);
- }
- else
- { boundingBox[2] = 0.0;
- boundingBox[3] = (majorRadius + minorRadius) * sin((double)(toRadians((thetaMax))));
- }
- }
- }
-
- boundingBox[4] = -1.0 * minorRadius;
- boundingBox[5] = minorRadius;
- dirtyBoundingBox = FALSE;
-
- return self;
- }
-
- - renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- {
- RiTorusV(majorRadius, minorRadius, phiMin, phiMax, thetaMax, n, tokens, parms);
-
- return self;
- }
-
- - (BOOL)theSameAs:otherRIBCommand
- {
- if (minorRadius != [otherRIBCommand minorRadius])
- { return NO;
- }
- if (majorRadius != [otherRIBCommand majorRadius])
- { return NO;
- }
- if (phiMin != [otherRIBCommand phiMin])
- { return NO;
- }
- if (phiMax != [otherRIBCommand phiMax])
- { return NO;
- }
-
- return [super theSameAs:otherRIBCommand];
- }
-
- - (BOOL)isLerpable { return YES; }
-
- // note: because we've made the WWSampleList "safe" for having
- // multiple samples with the same data, it's perfectly valid to return
- // yourself or b
- - lerpWith:b by:(float)uValue
- {
- id newMe = nil;
- RtFloat minorRadiusA, majorRadiusA, phiMinA, phiMaxA, thetaMaxA;
- RtFloat minorRadiusB, majorRadiusB, phiMinB, phiMaxB, thetaMaxB;
-
-
- if (([self class] != [b class]) || (uValue <= 0.0))
- { return self;
- }
-
- if (uValue >= 1.0)
- { return b;
- }
-
- newMe = [super lerpWith:b by:uValue]; // this makes a copy for us
-
- // okay, now do the specific stuff for this class
- minorRadiusA = [self minorRadius];
- minorRadiusB = [b minorRadius];
- [newMe setMinorRadius:(minorRadiusA + ((minorRadiusB - minorRadiusA) * uValue))];
- majorRadiusA = [self majorRadius];
- majorRadiusB = [b majorRadius];
- [newMe setMajorRadius:(majorRadiusA + ((majorRadiusB - majorRadiusA) * uValue))];
- phiMinA = [self phiMin];
- phiMinB = [b phiMin];
- [newMe setPhiMin:(phiMinA + ((phiMinB - phiMinA) * uValue))];
- phiMaxA = [self phiMax];
- phiMaxB = [b phiMax];
- [newMe setPhiMax:(phiMaxA + ((phiMaxB - phiMaxA) * uValue))];
- thetaMaxA = [self thetaMax];
- thetaMaxB = [b thetaMax];
- [newMe setThetaMax:(thetaMaxA + ((thetaMaxB - thetaMaxA) * uValue))];
-
- return newMe;
- }
-
-
- - lerpSelfWith:b by:(float)uValue
- {
- RtFloat minorRadiusA, majorRadiusA, phiMinA, phiMaxA, thetaMaxA;
- RtFloat minorRadiusB, majorRadiusB, phiMinB, phiMaxB, thetaMaxB;
-
-
- if (([self class] != [b class]) || (uValue <= 0.0))
- { return self;
- }
-
- if (uValue >= 1.0)
- { return b;
- }
-
- [super lerpSelfWith:b by:uValue]; // this makes a copy for us
-
- // okay, now do the specific stuff for this class
- minorRadiusA = [self minorRadius];
- minorRadiusB = [b minorRadius];
- [self setMinorRadius:(minorRadiusA + ((minorRadiusB - minorRadiusA) * uValue))];
- majorRadiusA = [self majorRadius];
- majorRadiusB = [b majorRadius];
- [self setMajorRadius:(majorRadiusA + ((majorRadiusB - majorRadiusA) * uValue))];
- phiMinA = [self phiMin];
- phiMinB = [b phiMin];
- [self setPhiMin:(phiMinA + ((phiMinB - phiMinA) * uValue))];
- phiMaxA = [self phiMax];
- phiMaxB = [b phiMax];
- [self setPhiMax:(phiMaxA + ((phiMaxB - phiMaxA) * uValue))];
- thetaMaxA = [self thetaMax];
- thetaMaxB = [b thetaMax];
- [self setThetaMax:(thetaMaxA + ((thetaMaxB - thetaMaxA) * uValue))];
-
- return self;
- }
-
- - writeEve:(NXStream *)stream atTabLevel:(int)tab
- {
- int i;
-
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "Torus %f %f %f %f %f", majorRadius, minorRadius, phiMin, phiMax, thetaMax);
- [super writeParameterList:stream];
- return self;
- }
-
- - writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
- {
- RtFloat umax;
- RtFloat uknots[12];
- RtFloat vmin, vmax;
- RtFloat vknots[12];
- RtFloat knots[12] = { 0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1.0, 1.0, 1.0};
- RtFloat uspline[9][4] = { {1.0, 0.0, 1.0, 1.0},
- {M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
- {0.0, 1.0, 1.0, 1.0},
- {-M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
- {-1.0, 0.0, 1.0, 1.0},
- {-M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
- {0.0, -1.0, 1.0, 1.0},
- {M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
- {1.0, 0.0, 1.0, 1.0}};
- RtFloat vspline[9][4];
- int i, j, k;
-
-
- umax = [self thetaMax] / 360.0;
- vmin = [self phiMin] / 360.0;
- vmax = [self phiMax] / 360.0;
- for (i=0; i<12; i++)
- { uknots[i] = knots[i] / umax;
- vknots[i] = (knots[i] - vmin) / (vmax - vmin);
- }
-
- vspline[0][0] = [self majorRadius] - [self minorRadius];
- vspline[0][1] = [self majorRadius] - [self minorRadius];
- vspline[0][2] = 0.0;
- vspline[0][3] = 1.0;
- vspline[1][0] = ([self majorRadius] - [self minorRadius]) * M_SQRT1_2;
- vspline[1][1] = ([self majorRadius] - [self minorRadius]) * M_SQRT1_2;
- vspline[1][2] = -[self minorRadius] * M_SQRT1_2;
- vspline[1][3] = M_SQRT1_2;
- vspline[2][0] = [self majorRadius];
- vspline[2][1] = [self majorRadius];
- vspline[2][2] = -[self minorRadius];
- vspline[2][3] = 1.0;
- vspline[3][0] = ([self majorRadius] + [self minorRadius]) * M_SQRT1_2;
- vspline[3][1] = ([self majorRadius] + [self minorRadius]) * M_SQRT1_2;
- vspline[3][2] = -[self minorRadius] * M_SQRT1_2;
- vspline[3][3] = M_SQRT1_2;
- vspline[4][0] = [self majorRadius] + [self minorRadius];
- vspline[4][1] = [self majorRadius] + [self minorRadius];
- vspline[4][2] = 0.0;
- vspline[4][3] = 1.0;
- vspline[5][0] = ([self majorRadius] + [self minorRadius]) * M_SQRT1_2;
- vspline[5][1] = ([self majorRadius] + [self minorRadius]) * M_SQRT1_2;
- vspline[5][2] = [self minorRadius] * M_SQRT1_2;
- vspline[5][3] = M_SQRT1_2;
- vspline[6][0] = [self majorRadius];
- vspline[6][1] = [self majorRadius];
- vspline[6][2] = [self minorRadius];
- vspline[6][3] = 1.0;
- vspline[7][0] = ([self majorRadius] - [self minorRadius]) * M_SQRT1_2;
- vspline[7][1] = ([self majorRadius] - [self minorRadius]) * M_SQRT1_2;
- vspline[7][2] = [self minorRadius] * M_SQRT1_2;
- vspline[7][3] = M_SQRT1_2;
- vspline[8][0] = [self majorRadius] - [self minorRadius];
- vspline[8][1] = [self majorRadius] - [self minorRadius];
- vspline[8][2] = 0.0;
- vspline[8][3] = 1.0;
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "# ");
- [self writeEve:stream atTabLevel:0];
- NXPrintf(stream, "\n");
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "# since Inventor doesn't directly support quadrics in any terribly useful way (sigh), we turn it into a NURBS surface:\n");
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "Separator {\n");
-
- for (i = 0; i < (tab+1); i++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "Complexity {\n");
- for (i = 0; i < (tab+2); i++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "value 1.0\n");
- for (i = 0; i < (tab+1); i++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "}\n");
-
- for (i = 0; i < (tab+1); i++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "Coordinate4 {\n");
- for (i = 0; i < (tab+2); i++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "point [");
-
- for (i=0; i<8; i++)
- { for (j=0; j<9; j++)
- { if (!i && !j)
- { NXPrintf(stream,
- "%f %f %f %f,\n",
- (uspline[j][0] * vspline[i][0]),
- (uspline[j][1] * vspline[i][1]),
- (uspline[j][2] * vspline[i][2]),
- (uspline[j][3] * vspline[i][3]));
- }
- else
- { NXPrintf(stream,
- " %f %f %f %f,\n",
- (uspline[j][0] * vspline[i][0]),
- (uspline[j][1] * vspline[i][1]),
- (uspline[j][2] * vspline[i][2]),
- (uspline[j][3] * vspline[i][3]));
- }
- for (k = 0; k < (tab+2); k++) { NXPrintf(stream, "\t"); }
- }
- }
- for (j=0; j<8; j++)
- { NXPrintf(stream,
- " %f %f %f %f,\n",
- (uspline[j][0] * vspline[i][0]),
- (uspline[j][1] * vspline[i][1]),
- (uspline[j][2] * vspline[i][2]),
- (uspline[j][3] * vspline[i][3]));
- for (k = 0; k < (tab+2); k++) { NXPrintf(stream, "\t"); }
- }
- NXPrintf(stream,
- " %f %f %f %f]\n",
- (uspline[j][0] * vspline[i][0]),
- (uspline[j][1] * vspline[i][1]),
- (uspline[j][2] * vspline[i][2]),
- (uspline[j][3] * vspline[i][3]));
- for (k = 0; k < (tab+1); k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "}\n");
-
- for (k = 0; k < (tab+1); k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "NurbsSurface {\n");
- for (k = 0; k < (tab+2); k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "numUControlPoints 9\n");
- for (k = 0; k < (tab+2); k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "numVControlPoints 2\n");
-
- for (k = 0; k < (tab+2); k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "uKnotVector [");
- for (i=0; i<11; i++)
- { NXPrintf(stream, "%f, ", uknots[i]);
- }
- NXPrintf(stream, "%f]\n", uknots[i]);
-
- for (k = 0; k < (tab+2); k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "vKnotVector [");
- for (i=0; i<3; i++)
- { NXPrintf(stream, "%f, ", vknots[i]);
- }
- NXPrintf(stream, "%f]\n", vknots[i]);
- for (k = 0; k < (tab+1); k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "}\n");
- for (k = 0; k < tab; k++) { NXPrintf(stream, "\t"); }
- NXPrintf(stream, "}\n");
-
- return self;
- }
-
-
- #define typeVector "ffff"
- #define typeValues &majorRadius, &minorRadius, &phiMin, &phiMax
-
- - read:(NXTypedStream *)stream
- {
- int version;
- [super read:stream];
-
- version = NXTypedStreamClassVersion(stream,"RIBTorus");
- if (version == 0) NXReadTypes(stream,"i",&version), version=1;
- if (version == 1)
- { NXReadTypes(stream,typeVector,typeValues);
- }
- else
- {
- }
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
-
- NXWriteTypes(stream,typeVector, typeValues);
-
- return self;
- }
-
-
-
- @end
-