/*********************************************************** * * * camera2.c * * * * * LPGE 1997 * * * * Copyright (C) 1996 Sony Computer Entertainment Inc. * * All Rights Reserved * * * ***********************************************************/ /**************************************************************************** includes ****************************************************************************/ #include "sys_libs.h" #include "pad.h" #include "sound.h" #include "object.h" #include "tunnel.h" #include "tunnel2.h" #include "flying.h" #include "main.h" #include "menu_mod.h" #include "tracks.h" #include "drawproc.h" #include "camera.h" /**************************************************************************** local constants ****************************************************************************/ #define ZOOM_IN 1 #define ZOOM_OUT 2 #define ZOOM_CHANGE_FREQUENCY 3 #define LOWEST_PROJECTION 65 #define MEDIUM_PROJECTION (FIXED_PROJECTION_DISTANCE) #define HIGHEST_PROJECTION 512 #define PROJECTION_CHANGE_FREQUENCY 3 #define INCREASE_PROJECTION 1001 #define REDUCE_PROJECTION 1002 /**************************************************************************** globals ****************************************************************************/ int CardinalFlybyDistanceOffSplinePath; int FramesWithinThirdHelicalViewer, ThirdHelicalViewerPeriod; int ThirdHelicalViewerDistanceOffSplinePath; int ThirdHelicalViewerTotalThetaZRevolutionAngle; int ThirdHelicalViewerTotalThetaZCirclingDirection; int ThirdHelicalViewerInitialAngle; int ThirdHelicalViewerCylinderLength; int ThirdHelicalViewerMinDistanceOffSplinePath; int ThirdHelicalViewerMaxDistanceOffSplinePath; int FramesWithinFourthHelicalViewer, FourthHelicalViewerPeriod; int FourthHelicalViewerDistanceOffSplinePath; int FourthHelicalViewerTotalThetaZRevolutionAngle; int FourthHelicalViewerTotalThetaZCirclingDirection; int FourthHelicalViewerInitialAngle; int FourthHelicalViewerCylinderLength; int FourthHelicalViewerMinDistanceOffSplinePath; int FourthHelicalViewerMaxDistanceOffSplinePath; int FirstLazyRotationViewerPeriod; int FirstLazyRotationViewerSubPeriod; int FramesWithinFirstLazyRotationViewer; int FirstLazyRotationViewerDistance; int FirstLazyRotationAngularSpeed; int LazyRotationEffect1, LazyRotationEffect2; int *SmallerEffect, *LargerEffect; int SecondLazyRotationViewerPeriod; int SecondLazyRotationViewerSubPeriod; int FramesWithinSecondLazyRotationViewer; int SecondLazyRotationViewerDistance; int SecondLazyRotationAngularSpeed; int LazyRotationProjectionChangeFlag; int LazyRotationProjectionStateFlag; int ThirdLazyRotationViewerPeriod; int ThirdLazyRotationViewerSubPeriod; int FramesWithinThirdLazyRotationViewer; int ThirdLazyRotationViewerDistance; int ThirdLazyRotationAngularSpeed; /**************************************************************************** externed globals from camera.c ****************************************************************************/ extern int FramesSinceViewLastSet; extern int FlybyFrames, FlybyDistanceOffSplinePath, FlybyXYAngle; extern VECTOR FlybyViewpoint; extern int FlybyShipSpeed, FlybySection, FlybyOffsetRatio; extern int FlybyZTwistDirection; extern int PointOnSphere, FramesSinceLastSphericalMove; extern int SphericalMovePeriod, SphericalMoveId; extern int SphericalCameraMinRadius, SphericalCameraMaxRadius; extern SphericalCameraZoomFlag; extern GsCOORDINATE2 CameraCoord; /**************************************************************************** macros ****************************************************************************/ #define ValidID(id) ( (id >= 0) && (id < NumberTunnelSections) ) /**************************************************************************** local prototypes ****************************************************************************/ int GetNewProjectionMove (int state); void UpdateProjectionState (int *state, int move); /**************************************************************************** functions ****************************************************************************/ void InitFourthSphericalViewer (void) { int point, orientation, startDistance; ViewTypeFlag = REFERENCE_VIEW; orientation = rand() % 4; point = ABOVE + (rand() % 6); GsInitCoordinate2(WORLD, &CameraCoord); SetMatrixByPointAndOrientation( &CameraCoord.coord, point, orientation); CameraCoord.super = &TheViewShip->coord; SphericalMoveId = TILT_LEFT + (rand() % 4); TheView.super = &CameraCoord; TheView.rz = 0; TheView.vpx = 0; TheView.vpy = 0; startDistance = rand() % 2; if (startDistance == 0) { TheView.vpz = -SphericalCameraMinRadius; } else { TheView.vpz = -SphericalCameraMaxRadius; } TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; FramesSinceLastSphericalMove = 1; if ((rand() % ZOOM_CHANGE_FREQUENCY) == 0) { if (startDistance == 0) SphericalCameraZoomFlag = ZOOM_OUT; else SphericalCameraZoomFlag = ZOOM_IN; } else { SphericalCameraZoomFlag = FALSE; } } void UpdateFourthSphericalViewer (void) { int cycleRatio; assert(FramesSinceLastSphericalMove >= 0); assert(FramesSinceLastSphericalMove <= SphericalMovePeriod); ViewTypeFlag = REFERENCE_VIEW; if (FramesSinceLastSphericalMove == SphericalMovePeriod) { switch(SphericalMoveId) { case TILT_LEFT: case TILT_RIGHT: if ((rand() % 2) == 0) SphericalMoveId = TILT_UP; else SphericalMoveId = TILT_DOWN; break; case TILT_UP: case TILT_DOWN: if ((rand() % 2) == 0) SphericalMoveId = TILT_LEFT; else SphericalMoveId = TILT_RIGHT; break; default: assert(FALSE); } FramesSinceLastSphericalMove = 1; if ((rand() % ZOOM_CHANGE_FREQUENCY) == 0) { if (abs(TheView.vpz + SphericalCameraMaxRadius) < 50) { SphericalCameraZoomFlag = ZOOM_IN; } else { int distance; distance = abs(TheView.vpz + SphericalCameraMinRadius); assert(distance < 50); SphericalCameraZoomFlag = ZOOM_OUT; } } else SphericalCameraZoomFlag = FALSE; } else { int smallAngle; SVECTOR twistVector; MATRIX twistMatrix; assert(SphericalMovePeriod > 0); smallAngle = 1024 / SphericalMovePeriod; cycleRatio = (FramesSinceLastSphericalMove * ONE) / SphericalMovePeriod; switch(SphericalCameraZoomFlag) { case ZOOM_IN: TheView.vpz = -(SphericalCameraMaxRadius - (((SphericalCameraMaxRadius - SphericalCameraMinRadius) * cycleRatio) >> 12)); break; case ZOOM_OUT: TheView.vpz = -(SphericalCameraMinRadius + (((SphericalCameraMaxRadius - SphericalCameraMinRadius) * cycleRatio) >> 12)); break; case FALSE: // do nowt break; default: assert(FALSE); } switch(SphericalMoveId) { case TILT_LEFT: setVECTOR( &twistVector, 0, -smallAngle, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); break; case TILT_RIGHT: setVECTOR( &twistVector, 0, smallAngle, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); break; case TILT_UP: setVECTOR( &twistVector, -smallAngle, 0, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); break; case TILT_DOWN: setVECTOR( &twistVector, smallAngle, 0, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); break; default: assert(FALSE); } TheView.rz = 0; FramesSinceLastSphericalMove++; } } void InitCardinalFlyby (void) { int distanceCovered, distanceInSections, distanceOffset; int aheadSections, aheadOffset, sectionID, offsetRatio; int newSectionID, newOffsetRatio; VECTOR relativePoint; int x, y, z; ViewTypeFlag = REFERENCE_VIEW; FlybyShipSpeed = GetSpeedOfViewShip(); distanceCovered = FlybyShipSpeed * FlybyFrames; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; if ((distanceInSections % 2) == 0) { aheadSections = distanceInSections / 4; aheadOffset = distanceOffset / 4; } else { aheadSections = (distanceInSections-1) / 4; aheadOffset = ((distanceOffset / 2) + 2048) / 2; } sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); GetNewSectionAndOffset (sectionID, offsetRatio, aheadSections, aheadOffset, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); FlybySection = newSectionID; FlybyOffsetRatio = newOffsetRatio; FlybyXYAngle = (rand() % 4) * 1024; x = (CardinalFlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (CardinalFlybyDistanceOffSplinePath * rsin(FlybyXYAngle)) >> 12; z = (newOffsetRatio * TunnelSectionLength) >> 12; setVECTOR( &relativePoint, x, y, z); ExpressSubPointInSuper( &relativePoint, &TheTunnel[newSectionID].coordinateData, &FlybyViewpoint); FlybyViewpoint.vx += TheTunnel[newSectionID].splinePoint.vx; FlybyViewpoint.vy += TheTunnel[newSectionID].splinePoint.vy; FlybyViewpoint.vz += TheTunnel[newSectionID].splinePoint.vz; TheView.vpx = FlybyViewpoint.vx; TheView.vpy = FlybyViewpoint.vy; TheView.vpz = FlybyViewpoint.vz; TheView.super = WORLD; } void UpdateCardinalFlyby (void) { int framesSinceThisModeSet, framesWithinFlyby; int sectionID, offsetRatio; int newSectionID, newOffsetRatio; int aheadSections, aheadOffset, movePerFrame; int offsetPerFrame, offsetSoFar, sectionOffsetSoFar; VECTOR relativePoint; int distanceCovered, distanceInSections, distanceOffset; int x, y, z; framesSinceThisModeSet = frameNumber - FramesSinceViewLastSet; framesWithinFlyby = framesSinceThisModeSet % FlybyFrames; if (framesWithinFlyby == 0) { FlybyShipSpeed = GetSpeedOfViewShip(); distanceCovered = FlybyShipSpeed * FlybyFrames; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; if ((distanceInSections % 2) == 0) { aheadSections = distanceInSections / 4; aheadOffset = distanceOffset / 4; } else { aheadSections = (distanceInSections-1) / 4; aheadOffset = ((distanceOffset / 2) + 2048) / 2; } sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); GetNewSectionAndOffset (sectionID, offsetRatio, aheadSections, aheadOffset, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); FlybySection = newSectionID; FlybyOffsetRatio = newOffsetRatio; FlybyXYAngle = (rand() % 4) * 1024; x = (CardinalFlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (CardinalFlybyDistanceOffSplinePath * rsin(FlybyXYAngle)) >> 12; z = (newOffsetRatio * TunnelSectionLength) >> 12; setVECTOR( &relativePoint, x, y, z); ExpressSubPointInSuper( &relativePoint, &TheTunnel[newSectionID].coordinateData, &FlybyViewpoint); FlybyViewpoint.vx += TheTunnel[newSectionID].splinePoint.vx; FlybyViewpoint.vy += TheTunnel[newSectionID].splinePoint.vy; FlybyViewpoint.vz += TheTunnel[newSectionID].splinePoint.vz; TheView.vpx = FlybyViewpoint.vx; TheView.vpy = FlybyViewpoint.vy; TheView.vpz = FlybyViewpoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; TheView.super = WORLD; } else { TheView.super = WORLD; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; movePerFrame = FlybyShipSpeed / 2; offsetPerFrame = (movePerFrame << 12) / TunnelSectionLength; offsetSoFar = framesWithinFlyby * offsetPerFrame; sectionOffsetSoFar = 0; while (offsetSoFar >= ONE) { sectionOffsetSoFar++; offsetSoFar -= ONE; } assert(ValidID(FlybySection)); GetNewSectionAndOffset (FlybySection, FlybyOffsetRatio, sectionOffsetSoFar, offsetSoFar, &newSectionID, &newOffsetRatio); x = (CardinalFlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (CardinalFlybyDistanceOffSplinePath * rsin(FlybyXYAngle)) >> 12; z = (newOffsetRatio * TunnelSectionLength) >> 12; setVECTOR( &relativePoint, x, y, z); ExpressSubPointInSuper( &relativePoint, &TheTunnel[newSectionID].coordinateData, &FlybyViewpoint); FlybyViewpoint.vx += TheTunnel[newSectionID].splinePoint.vx; FlybyViewpoint.vy += TheTunnel[newSectionID].splinePoint.vy; FlybyViewpoint.vz += TheTunnel[newSectionID].splinePoint.vz; TheView.vpx = FlybyViewpoint.vx; TheView.vpy = FlybyViewpoint.vy; TheView.vpz = FlybyViewpoint.vz; TheView.rz = 0; } } void InitThirdHelicalViewer (void) { FramesWithinThirdHelicalViewer = 0; ThirdHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); ThirdHelicalViewerInitialAngle = rand() % ONE; ThirdHelicalViewerDistanceOffSplinePath = ThirdHelicalViewerMaxDistanceOffSplinePath; ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; TheView.rz = 0; } void UpdateThirdHelicalViewer (void) { int cycleRatio, theta; TheView.super = &TheViewShip->coord; FramesWithinThirdHelicalViewer++; assert(FramesWithinThirdHelicalViewer <= ThirdHelicalViewerPeriod); if (FramesWithinThirdHelicalViewer == ThirdHelicalViewerPeriod) { FramesWithinThirdHelicalViewer = 0; ThirdHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); ThirdHelicalViewerInitialAngle = rand() % ONE; ThirdHelicalViewerDistanceOffSplinePath = ThirdHelicalViewerMaxDistanceOffSplinePath; } assert(ThirdHelicalViewerPeriod > 0); cycleRatio = (FramesWithinThirdHelicalViewer * ONE) / ThirdHelicalViewerPeriod; assert(cycleRatio >= 0); assert(cycleRatio < ONE); TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; theta = ThirdHelicalViewerInitialAngle; switch(ThirdHelicalViewerTotalThetaZCirclingDirection) { case CLOCKWISE: theta += (ThirdHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; case ANTICLOCKWISE: theta -= (ThirdHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; default: assert(FALSE); } if (cycleRatio < 2048) { ThirdHelicalViewerDistanceOffSplinePath = ThirdHelicalViewerMaxDistanceOffSplinePath - (( (ThirdHelicalViewerMaxDistanceOffSplinePath - ThirdHelicalViewerMinDistanceOffSplinePath) * cycleRatio) / 2048); } else { ThirdHelicalViewerDistanceOffSplinePath = ThirdHelicalViewerMinDistanceOffSplinePath + (( (ThirdHelicalViewerMaxDistanceOffSplinePath - ThirdHelicalViewerMinDistanceOffSplinePath) * (cycleRatio-2048)) / 2048); } TheView.vpx = (ThirdHelicalViewerDistanceOffSplinePath * rcos(theta)) >> 12; TheView.vpy = (ThirdHelicalViewerDistanceOffSplinePath * rsin(theta)) >> 12; TheView.vpz = (ThirdHelicalViewerCylinderLength/2) - ((ThirdHelicalViewerCylinderLength * cycleRatio) >> 12); TheView.rz = 0; } void InitFourthHelicalViewer (void) { FramesWithinFourthHelicalViewer = 0; FourthHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); FourthHelicalViewerInitialAngle = rand() % ONE; FourthHelicalViewerDistanceOffSplinePath = FourthHelicalViewerMaxDistanceOffSplinePath; ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; TheView.rz = 0; } void UpdateFourthHelicalViewer (void) { int cycleRatio, theta; ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; FramesWithinFourthHelicalViewer++; assert(FramesWithinFourthHelicalViewer <= FourthHelicalViewerPeriod); if (FramesWithinFourthHelicalViewer == FourthHelicalViewerPeriod) { FramesWithinFourthHelicalViewer = 0; FourthHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); FourthHelicalViewerInitialAngle = rand() % ONE; FourthHelicalViewerDistanceOffSplinePath = FourthHelicalViewerMaxDistanceOffSplinePath; } assert(FourthHelicalViewerPeriod > 0); cycleRatio = (FramesWithinFourthHelicalViewer * ONE) / FourthHelicalViewerPeriod; assert(cycleRatio >= 0); assert(cycleRatio < ONE); TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; theta = FourthHelicalViewerInitialAngle; switch(FourthHelicalViewerTotalThetaZCirclingDirection) { case CLOCKWISE: theta += (FourthHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; case ANTICLOCKWISE: theta -= (FourthHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; default: assert(FALSE); } if (cycleRatio < 2048) { FourthHelicalViewerDistanceOffSplinePath = FourthHelicalViewerMaxDistanceOffSplinePath - (( (FourthHelicalViewerMaxDistanceOffSplinePath - FourthHelicalViewerMinDistanceOffSplinePath) * cycleRatio) / 2048); } else { FourthHelicalViewerDistanceOffSplinePath = FourthHelicalViewerMinDistanceOffSplinePath + (( (FourthHelicalViewerMaxDistanceOffSplinePath - FourthHelicalViewerMinDistanceOffSplinePath) * (cycleRatio-2048)) / 2048); } TheView.vpx = (FourthHelicalViewerDistanceOffSplinePath * rcos(theta)) >> 12; TheView.vpy = (FourthHelicalViewerDistanceOffSplinePath * rsin(theta)) >> 12; TheView.vpz = (FourthHelicalViewerCylinderLength/2) - ((FourthHelicalViewerCylinderLength * cycleRatio) >> 12); TheView.rz = 0; } void InitFirstSpiralViewer (void) { assert(FALSE); // not used } void UpdateFirstSpiralViewer (void) { assert(FALSE); // not used } int GetDifferentLazyRotationMove (int move) { int result; assert(move >= 0 && move < 6); for (;;) { result = rand() % 6; if (result != move && (result/2) != (move/2)) break; } return result; } void InitFirstLazyRotationViewer (void) { FramesWithinFirstLazyRotationViewer = 0; LazyRotationEffect1 = rand() % 6; LazyRotationEffect2 = GetDifferentLazyRotationMove(LazyRotationEffect1); SmallerEffect = &LazyRotationEffect1; LargerEffect = &LazyRotationEffect2; ViewTypeFlag = REFERENCE_VIEW; GsInitCoordinate2(WORLD, &CameraCoord); assert(TheViewShip != NULL); CameraCoord.super = &TheViewShip->coord; TheView.super = &CameraCoord; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -FirstLazyRotationViewerDistance; } void UpdateFirstLazyRotationViewer (void) { int time, angle, crossoverValue; SVECTOR twistVector; MATRIX twistMatrix; int largerEffectRatio, smallerEffectRatio; FramesWithinFirstLazyRotationViewer++; assert(FirstLazyRotationViewerPeriod > 0); assert(FirstLazyRotationViewerSubPeriod > 0); time = FramesWithinFirstLazyRotationViewer % FirstLazyRotationViewerPeriod; crossoverValue = (ONE * FirstLazyRotationViewerSubPeriod) / ((FirstLazyRotationViewerPeriod/2) + FirstLazyRotationViewerSubPeriod); if (time == 0) { int *temp; temp = LargerEffect; LargerEffect = SmallerEffect; SmallerEffect = temp; } else if (time == (FirstLazyRotationViewerPeriod) - FirstLazyRotationViewerSubPeriod) { int newID; newID = GetDifferentLazyRotationMove(*LargerEffect); *SmallerEffect = newID; } if (time < FirstLazyRotationViewerPeriod/2) { largerEffectRatio = (ONE * (time + FirstLazyRotationViewerSubPeriod)) / ((FirstLazyRotationViewerPeriod/2) + FirstLazyRotationViewerSubPeriod); } else { largerEffectRatio = (ONE * (FirstLazyRotationViewerPeriod + FirstLazyRotationViewerSubPeriod - time)) / ((FirstLazyRotationViewerPeriod/2) + FirstLazyRotationViewerSubPeriod); } assert(largerEffectRatio >= 0); if (largerEffectRatio > ONE) largerEffectRatio = ONE; smallerEffectRatio = (2 * crossoverValue) - largerEffectRatio; if (smallerEffectRatio < 0) smallerEffectRatio = 0; setVECTOR( &twistVector, 0, 0, 0); angle = (FirstLazyRotationAngularSpeed * largerEffectRatio) >> 12; switch(*LargerEffect) { case 0: twistVector.vx -= angle; break; case 1: twistVector.vx += angle; break; case 2: twistVector.vy -= angle; break; case 3: twistVector.vy += angle; break; case 4: twistVector.vz -= angle; break; case 5: twistVector.vz += angle; break; default: assert(FALSE); } angle = (FirstLazyRotationAngularSpeed * smallerEffectRatio) >> 12; switch(*SmallerEffect) { case 0: twistVector.vx -= angle; break; case 1: twistVector.vx += angle; break; case 2: twistVector.vy -= angle; break; case 3: twistVector.vy += angle; break; case 4: twistVector.vz -= angle; break; case 5: twistVector.vz += angle; break; default: assert(FALSE); } RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); CameraCoord.flg = 0; } void InitSecondLazyRotationViewer (void) { FramesWithinSecondLazyRotationViewer = 1; LazyRotationEffect1 = rand() % 6; LazyRotationEffect2 = GetDifferentLazyRotationMove(LazyRotationEffect1); SmallerEffect = &LazyRotationEffect1; LargerEffect = &LazyRotationEffect2; ViewTypeFlag = REFERENCE_VIEW; GsInitCoordinate2(WORLD, &CameraCoord); assert(TheViewShip != NULL); CameraCoord.super = &TheViewShip->coord; TheView.super = &CameraCoord; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -SecondLazyRotationViewerDistance; LazyRotationProjectionStateFlag = MEDIUM_PROJECTION; if ((rand() % PROJECTION_CHANGE_FREQUENCY) == 0) { LazyRotationProjectionChangeFlag = GetNewProjectionMove( LazyRotationProjectionStateFlag); } else LazyRotationProjectionChangeFlag = FALSE; } int GetNewProjectionMove (int state) { int move; switch(state) { case LOWEST_PROJECTION: move = INCREASE_PROJECTION; break; case MEDIUM_PROJECTION: move = INCREASE_PROJECTION + (rand() % 2); break; case HIGHEST_PROJECTION: move = REDUCE_PROJECTION; break; default: assert(FALSE); } return move; } void UpdateProjectionState (int *state, int move) { switch(*state) { case LOWEST_PROJECTION: assert(move == INCREASE_PROJECTION); *state = MEDIUM_PROJECTION; break; case MEDIUM_PROJECTION: switch(move) { case INCREASE_PROJECTION: *state = HIGHEST_PROJECTION; break; case REDUCE_PROJECTION: *state = LOWEST_PROJECTION; break; default: assert(FALSE); } break; case HIGHEST_PROJECTION: assert(move == REDUCE_PROJECTION); *state = MEDIUM_PROJECTION; break; default: assert(FALSE); } } void UpdateSecondLazyRotationViewer (void) { int time, cycleRatio, angle, crossoverValue; SVECTOR twistVector; MATRIX twistMatrix; int largerEffectRatio, smallerEffectRatio; int projectionDistance; FramesWithinSecondLazyRotationViewer++; assert(SecondLazyRotationViewerPeriod > 0); assert(SecondLazyRotationViewerSubPeriod > 0); time = FramesWithinSecondLazyRotationViewer % SecondLazyRotationViewerPeriod; cycleRatio = (time * ONE) / SecondLazyRotationViewerPeriod; crossoverValue = (ONE * SecondLazyRotationViewerSubPeriod) / ((SecondLazyRotationViewerPeriod/2) + SecondLazyRotationViewerSubPeriod); if (time == 0) { int *temp; temp = LargerEffect; LargerEffect = SmallerEffect; SmallerEffect = temp; if (LazyRotationProjectionChangeFlag != FALSE) { UpdateProjectionState( &LazyRotationProjectionStateFlag, LazyRotationProjectionChangeFlag); LazyRotationProjectionChangeFlag = FALSE; } else { if ((rand() % PROJECTION_CHANGE_FREQUENCY) == 0) { LazyRotationProjectionChangeFlag = GetNewProjectionMove( LazyRotationProjectionStateFlag); } else { LazyRotationProjectionChangeFlag = FALSE; } } } else if (time == (SecondLazyRotationViewerPeriod/2) - SecondLazyRotationViewerSubPeriod) { int newID; newID = GetDifferentLazyRotationMove(*SmallerEffect); *SmallerEffect = newID; } if (time < SecondLazyRotationViewerPeriod/2) { largerEffectRatio = (ONE * (time + SecondLazyRotationViewerSubPeriod)) / ((SecondLazyRotationViewerPeriod/2) + SecondLazyRotationViewerSubPeriod); } else { largerEffectRatio = (ONE * (SecondLazyRotationViewerPeriod + SecondLazyRotationViewerSubPeriod - time)) / ((SecondLazyRotationViewerPeriod/2) + SecondLazyRotationViewerSubPeriod); } assert(largerEffectRatio >= 0); assert(largerEffectRatio <= ONE); smallerEffectRatio = (2 * crossoverValue) - largerEffectRatio; if (smallerEffectRatio < 0) smallerEffectRatio = 0; setVECTOR( &twistVector, 0, 0, 0); angle = (SecondLazyRotationAngularSpeed * largerEffectRatio) >> 12; switch(*LargerEffect) { case 0: twistVector.vx -= angle; break; case 1: twistVector.vx += angle; break; case 2: twistVector.vy -= angle; break; case 3: twistVector.vy += angle; break; case 4: twistVector.vz -= angle; break; case 5: twistVector.vz += angle; break; default: assert(FALSE); } angle = (SecondLazyRotationAngularSpeed * smallerEffectRatio) >> 12; switch(*SmallerEffect) { case 0: twistVector.vx -= angle; break; case 1: twistVector.vx += angle; break; case 2: twistVector.vy -= angle; break; case 3: twistVector.vy += angle; break; case 4: twistVector.vz -= angle; break; case 5: twistVector.vz += angle; break; default: assert(FALSE); } RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); CameraCoord.flg = 0; if (time != 0 && LazyRotationProjectionChangeFlag != FALSE) { switch(LazyRotationProjectionStateFlag) { case LOWEST_PROJECTION: assert(LazyRotationProjectionChangeFlag == INCREASE_PROJECTION); projectionDistance = LOWEST_PROJECTION + (((MEDIUM_PROJECTION - LOWEST_PROJECTION) * cycleRatio) >> 12); break; case MEDIUM_PROJECTION: switch(LazyRotationProjectionChangeFlag) { case INCREASE_PROJECTION: projectionDistance = MEDIUM_PROJECTION + (((HIGHEST_PROJECTION - MEDIUM_PROJECTION) * cycleRatio) >> 12); break; case REDUCE_PROJECTION: projectionDistance = MEDIUM_PROJECTION - (((MEDIUM_PROJECTION - LOWEST_PROJECTION) * cycleRatio) >> 12); break; default: assert(FALSE); } break; case HIGHEST_PROJECTION: assert(LazyRotationProjectionChangeFlag == REDUCE_PROJECTION); projectionDistance = HIGHEST_PROJECTION - (((HIGHEST_PROJECTION - MEDIUM_PROJECTION) * cycleRatio) >> 12); break; default: assert(FALSE); } } else { switch(LazyRotationProjectionStateFlag) { case LOWEST_PROJECTION: case MEDIUM_PROJECTION: case HIGHEST_PROJECTION: projectionDistance = LazyRotationProjectionStateFlag; break; default: assert(FALSE); } } GsSetProjection(projectionDistance); } void InitThirdLazyRotationViewer (void) { FramesWithinThirdLazyRotationViewer = 0; LazyRotationEffect1 = rand() % 6; LazyRotationEffect2 = GetDifferentLazyRotationMove(LazyRotationEffect1); SmallerEffect = &LazyRotationEffect1; LargerEffect = &LazyRotationEffect2; ViewTypeFlag = REFERENCE_VIEW; GsInitCoordinate2(WORLD, &CameraCoord); assert(TheViewShip != NULL); CameraCoord.super = &TheViewShip->coord; TheView.super = &CameraCoord; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -ThirdLazyRotationViewerDistance; } void UpdateThirdLazyRotationViewer (void) { int time, angle, crossoverValue; SVECTOR twistVector; MATRIX twistMatrix; int largerEffectRatio, smallerEffectRatio; FramesWithinThirdLazyRotationViewer++; assert(ThirdLazyRotationViewerPeriod > 0); assert(ThirdLazyRotationViewerSubPeriod > 0); time = FramesWithinThirdLazyRotationViewer % ThirdLazyRotationViewerPeriod; crossoverValue = (ONE * ThirdLazyRotationViewerSubPeriod) / ((ThirdLazyRotationViewerPeriod/2) + ThirdLazyRotationViewerSubPeriod); if (time == 0) { int *temp; temp = LargerEffect; LargerEffect = SmallerEffect; SmallerEffect = temp; } else if (time == (ThirdLazyRotationViewerPeriod/2) - ThirdLazyRotationViewerSubPeriod) { int newID; newID = GetDifferentLazyRotationMove(*SmallerEffect); *SmallerEffect = newID; } if (time < ThirdLazyRotationViewerPeriod/2) { largerEffectRatio = (ONE * (time + ThirdLazyRotationViewerSubPeriod)) / ((ThirdLazyRotationViewerPeriod/2) + ThirdLazyRotationViewerSubPeriod); } else { largerEffectRatio = (ONE * (ThirdLazyRotationViewerPeriod + ThirdLazyRotationViewerSubPeriod - time)) / ((ThirdLazyRotationViewerPeriod/2) + ThirdLazyRotationViewerSubPeriod); } assert(largerEffectRatio >= 0); assert(largerEffectRatio <= ONE); smallerEffectRatio = (2 * crossoverValue) - largerEffectRatio; if (smallerEffectRatio < 0) smallerEffectRatio = 0; setVECTOR( &twistVector, 0, 0, 0); angle = (ThirdLazyRotationAngularSpeed * largerEffectRatio) >> 12; switch(*LargerEffect) { case 0: twistVector.vx -= angle; break; case 1: twistVector.vx += angle; break; case 2: twistVector.vy -= angle; break; case 3: twistVector.vy += angle; break; case 4: twistVector.vz -= angle; break; case 5: twistVector.vz += angle; break; default: assert(FALSE); } angle = (ThirdLazyRotationAngularSpeed * smallerEffectRatio) >> 12; switch(*SmallerEffect) { case 0: twistVector.vx -= angle; break; case 1: twistVector.vx += angle; break; case 2: twistVector.vy -= angle; break; case 3: twistVector.vy += angle; break; case 4: twistVector.vz -= angle; break; case 5: twistVector.vz += angle; break; default: assert(FALSE); } RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); CameraCoord.flg = 0; } // section for miscellaneous cube and sphere geometric business void GetPointOnCuboid (int xLength, int yLength, int zLength, int whichCorner, VECTOR *output) { switch(whichCorner) { case ABOVE_FORWARD_LEFT: output->vx = -xLength; output->vy = -yLength; output->vz = zLength; break; case ABOVE_FORWARD_RIGHT: output->vx = xLength; output->vy = -yLength; output->vz = zLength; break; case ABOVE_BACKWARD_LEFT: output->vx = -xLength; output->vy = -yLength; output->vz = -zLength; break; case ABOVE_BACKWARD_RIGHT: output->vx = xLength; output->vy = -yLength; output->vz = -zLength; break; case BELOW_FORWARD_LEFT: output->vx = -xLength; output->vy = yLength; output->vz = zLength; break; case BELOW_FORWARD_RIGHT: output->vx = xLength; output->vy = yLength; output->vz = zLength; break; case BELOW_BACKWARD_LEFT: output->vx = -xLength; output->vy = yLength; output->vz = -zLength; break; case BELOW_BACKWARD_RIGHT: output->vx = xLength; output->vy = yLength; output->vz = -zLength; break; default: assert(FALSE); } } int GetNewPointOnCuboid (int oldPointOnCuboid, int whichMove) { int newPoint; switch(oldPointOnCuboid) { case ABOVE_FORWARD_LEFT: switch(whichMove) { case MOVE_LEFT: case MOVE_FORWARD: case MOVE_UP: assert(FALSE); break; case MOVE_RIGHT: newPoint = ABOVE_FORWARD_RIGHT; break; case MOVE_DOWN: newPoint = BELOW_FORWARD_LEFT; break; case MOVE_BACKWARD: newPoint = ABOVE_BACKWARD_LEFT; break; default: assert(FALSE); } break; case ABOVE_FORWARD_RIGHT: switch(whichMove) { case MOVE_RIGHT: case MOVE_FORWARD: case MOVE_UP: assert(FALSE); break; case MOVE_LEFT: newPoint = ABOVE_FORWARD_LEFT; break; case MOVE_DOWN: newPoint = BELOW_FORWARD_RIGHT; break; case MOVE_BACKWARD: newPoint = ABOVE_BACKWARD_RIGHT; break; default: assert(FALSE); } break; case ABOVE_BACKWARD_LEFT: switch(whichMove) { case MOVE_LEFT: case MOVE_BACKWARD: case MOVE_UP: assert(FALSE); break; case MOVE_RIGHT: newPoint = ABOVE_BACKWARD_RIGHT; break; case MOVE_DOWN: newPoint = BELOW_BACKWARD_LEFT; break; case MOVE_FORWARD: newPoint = ABOVE_FORWARD_LEFT; break; default: assert(FALSE); } break; case ABOVE_BACKWARD_RIGHT: switch(whichMove) { case MOVE_RIGHT: case MOVE_BACKWARD: case MOVE_UP: assert(FALSE); break; case MOVE_LEFT: newPoint = ABOVE_BACKWARD_LEFT; break; case MOVE_DOWN: newPoint = BELOW_BACKWARD_RIGHT; break; case MOVE_FORWARD: newPoint = ABOVE_FORWARD_RIGHT; break; default: assert(FALSE); } break; case BELOW_FORWARD_LEFT: switch(whichMove) { case MOVE_LEFT: case MOVE_FORWARD: case MOVE_DOWN: assert(FALSE); break; case MOVE_RIGHT: newPoint = BELOW_FORWARD_RIGHT; break; case MOVE_UP: newPoint = ABOVE_FORWARD_LEFT; break; case MOVE_BACKWARD: newPoint = BELOW_BACKWARD_LEFT; break; default: assert(FALSE); } break; case BELOW_FORWARD_RIGHT: switch(whichMove) { case MOVE_RIGHT: case MOVE_FORWARD: case MOVE_DOWN: assert(FALSE); break; case MOVE_LEFT: newPoint = BELOW_FORWARD_LEFT; break; case MOVE_UP: newPoint = ABOVE_FORWARD_RIGHT; break; case MOVE_BACKWARD: newPoint = BELOW_BACKWARD_RIGHT; break; default: assert(FALSE); } break; case BELOW_BACKWARD_LEFT: switch(whichMove) { case MOVE_LEFT: case MOVE_BACKWARD: case MOVE_DOWN: assert(FALSE); break; case MOVE_RIGHT: newPoint = BELOW_BACKWARD_RIGHT; break; case MOVE_UP: newPoint = ABOVE_BACKWARD_LEFT; break; case MOVE_FORWARD: newPoint = BELOW_FORWARD_LEFT; break; default: assert(FALSE); } break; case BELOW_BACKWARD_RIGHT: switch(whichMove) { case MOVE_RIGHT: case MOVE_BACKWARD: case MOVE_DOWN: assert(FALSE); break; case MOVE_LEFT: newPoint = BELOW_BACKWARD_LEFT; break; case MOVE_UP: newPoint = ABOVE_BACKWARD_RIGHT; break; case MOVE_FORWARD: newPoint = BELOW_FORWARD_RIGHT; break; default: assert(FALSE); } break; default: assert(FALSE); } return newPoint; } int GetAxisOfMove (int move) { int axis; switch(move) { case MOVE_RIGHT: case MOVE_LEFT: axis = X_AXIS; break; case MOVE_UP: case MOVE_DOWN: axis = Y_AXIS; break; case MOVE_BACKWARD: case MOVE_FORWARD: axis = Z_AXIS; break; default: assert(FALSE); } return axis; } void GetPointOnSphere (int radius, int whichCardinalPoint, VECTOR *output) { switch(whichCardinalPoint) { case ABOVE: output->vx = 0; output->vy = -radius; output->vz = 0; break; case BELOW: output->vx = 0; output->vy = radius; output->vz = 0; break; case LEFT: output->vx = -radius; output->vy = 0; output->vz = 0; break; case RIGHT: output->vx = radius; output->vy = 0; output->vz = 0; break; case FORWARD: output->vx = 0; output->vy = 0; output->vz = radius; break; case BACKWARD: output->vx = 0; output->vy = 0; output->vz = -radius; break; default: assert(FALSE); } } int GetNewPointOnSphere (int pointOnSphere, int move) { int newPoint; switch(pointOnSphere) { case ABOVE: switch(move) { case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: newPoint = RIGHT; break; case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: newPoint = LEFT; break; case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: newPoint = FORWARD; break; case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: newPoint = BACKWARD; break; default: assert(FALSE); } break; case BELOW: switch(move) { case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: newPoint = LEFT; break; case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: newPoint = RIGHT; break; case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: newPoint = BACKWARD; break; case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: newPoint = FORWARD; break; default: assert(FALSE); } break; case LEFT: switch(move) { case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: newPoint = ABOVE; break; case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: newPoint = BELOW; break; case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: newPoint = FORWARD; break; case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: newPoint = BACKWARD; break; default: assert(FALSE); } break; case RIGHT: switch(move) { case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: newPoint = BELOW; break; case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: newPoint = ABOVE; break; case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: newPoint = BACKWARD; break; case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: newPoint = FORWARD; break; default: assert(FALSE); } break; case FORWARD: switch(move) { case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: newPoint = BELOW; break; case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: newPoint = ABOVE; break; case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: newPoint = RIGHT; break; case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: newPoint = LEFT; break; default: assert(FALSE); } break; case BACKWARD: switch(move) { case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: newPoint = ABOVE; break; case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: newPoint = BELOW; break; case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: newPoint = LEFT; break; case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: newPoint = RIGHT; break; default: assert(FALSE); } break; default: assert(FALSE); } return newPoint; } int GetNextMoveAtPointOnSphere (int point, int move) { int newMove; switch(point) { case ABOVE: case BELOW: switch(move) { case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: if ((rand() % 2) == 0) newMove = CIRCLE_CLOCKWISE_IN_Y_Z_PLANE; else newMove = CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE; break; case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: if ((rand() % 2) == 0) newMove = CIRCLE_CLOCKWISE_IN_X_Y_PLANE; else newMove = CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE; break; default: assert(FALSE); } break; case LEFT: case RIGHT: switch(move) { case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: if ((rand() % 2) == 0) newMove = CIRCLE_CLOCKWISE_IN_X_Z_PLANE; else newMove = CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE; break; case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: if ((rand() % 2) == 0) newMove = CIRCLE_CLOCKWISE_IN_X_Y_PLANE; else newMove = CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE; break; default: assert(FALSE); } break; case FORWARD: case BACKWARD: switch(move) { case CIRCLE_CLOCKWISE_IN_X_Y_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Y_PLANE: assert(FALSE); break; case CIRCLE_CLOCKWISE_IN_Y_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE: if ((rand() % 2) == 0) newMove = CIRCLE_CLOCKWISE_IN_X_Z_PLANE; else newMove = CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE; break; case CIRCLE_CLOCKWISE_IN_X_Z_PLANE: case CIRCLE_ANTICLOCKWISE_IN_X_Z_PLANE: if ((rand() % 2) == 0) newMove = CIRCLE_CLOCKWISE_IN_Y_Z_PLANE; else newMove = CIRCLE_ANTICLOCKWISE_IN_Y_Z_PLANE; break; default: assert(FALSE); } break; default: assert(FALSE); } return newMove; } void SetMatrixByPointAndOrientation (MATRIX *matrix, int point, int orientation) { int angle; SVECTOR twistVector; MATRIX twistMatrix; assert(matrix != NULL); InitMatrix(matrix); switch(point) { case BACKWARD: // do nowt break; case FORWARD: setVECTOR( &twistVector, 0, 2048, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0(matrix, &twistMatrix, matrix); break; case LEFT: setVECTOR( &twistVector, 0, 3072, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0(matrix, &twistMatrix, matrix); break; case RIGHT: setVECTOR( &twistVector, 0, 1024, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0(matrix, &twistMatrix, matrix); break; case ABOVE: setVECTOR( &twistVector, 3072, 0, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0(matrix, &twistMatrix, matrix); break; case BELOW: setVECTOR( &twistVector, 1024, 0, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0(matrix, &twistMatrix, matrix); break; default: assert(FALSE); } // now deal with orientation, ie self-Z angular twist assert(orientation >= 0); assert(orientation <= TWIST_TWO_SEVENTY_DEGREES); angle = orientation * 1024; setVECTOR( &twistVector, 0, 0, angle); RotMatrix( &twistVector, &twistMatrix); MulMatrix0(matrix, &twistMatrix, matrix); } int FlipRelativeXYMove (int move) { int flippedMove; switch(move) { case TILT_LEFT: flippedMove = TILT_RIGHT; break; case TILT_RIGHT: flippedMove = TILT_LEFT; break; case TILT_DOWN: flippedMove = TILT_UP; break; case TILT_UP: flippedMove = TILT_DOWN; break; default: assert(FALSE); } return flippedMove; } int GetNewRelativeMove (int oldMove, int orientationAdded) { int newMove; switch(oldMove) { case TILT_LEFT: switch(orientationAdded) { case 0: newMove = TILT_LEFT; break; case TWIST_NINETY_DEGREES: newMove = TILT_DOWN; break; case TWIST_ONE_EIGHTY_DEGREES: newMove = TILT_RIGHT; break; case TWIST_TWO_SEVENTY_DEGREES: newMove = TILT_UP; break; default: assert(FALSE); } break; case TILT_RIGHT: switch(orientationAdded) { case 0: newMove = TILT_RIGHT; break; case TWIST_NINETY_DEGREES: newMove = TILT_UP; break; case TWIST_ONE_EIGHTY_DEGREES: newMove = TILT_LEFT; break; case TWIST_TWO_SEVENTY_DEGREES: newMove = TILT_DOWN; break; default: assert(FALSE); } break; case TILT_DOWN: switch(orientationAdded) { case 0: newMove = TILT_DOWN; break; case TWIST_NINETY_DEGREES: newMove = TILT_RIGHT; break; case TWIST_ONE_EIGHTY_DEGREES: newMove = TILT_UP; break; case TWIST_TWO_SEVENTY_DEGREES: newMove = TILT_LEFT; break; default: assert(FALSE); } break; case TILT_UP: switch(orientationAdded) { case 0: newMove = TILT_UP; break; case TWIST_NINETY_DEGREES: newMove = TILT_LEFT; break; case TWIST_ONE_EIGHTY_DEGREES: newMove = TILT_DOWN; break; case TWIST_TWO_SEVENTY_DEGREES: newMove = TILT_RIGHT; break; default: assert(FALSE); } break; default: assert(FALSE); } return newMove; } int AntiDirection (int direction) { switch(direction) { case CLOCKWISE: return ANTICLOCKWISE; break; case ANTICLOCKWISE: return CLOCKWISE; break; default: assert(FALSE); } } void GetNewCirclingOnCubeData (int oldPlane, int oldAngle, int oldDirection, int *newPlane, int *newAngle, int *newDirection) { switch(oldPlane) { case ABOVE: switch(oldAngle) { case 0: *newPlane = FORWARD; *newAngle = 0; *newDirection = AntiDirection(oldDirection); break; case 1024: *newPlane = RIGHT; *newAngle = 0; *newDirection = AntiDirection(oldDirection); break; case 2048: *newPlane = BACKWARD; *newAngle = 0; *newDirection = AntiDirection(oldDirection); break; case 3072: *newPlane = LEFT; *newAngle = 0; *newDirection = AntiDirection(oldDirection); break; default: assert(FALSE); } break; case BELOW: switch(oldAngle) { case 0: *newPlane = BACKWARD; *newAngle = 2048; *newDirection = AntiDirection(oldDirection); break; case 1024: *newPlane = RIGHT; *newAngle = 2048; *newDirection = AntiDirection(oldDirection); break; case 2048: *newPlane = FORWARD; *newAngle = 2048; *newDirection = AntiDirection(oldDirection); break; case 3072: *newPlane = LEFT; *newAngle = 2048; *newDirection = AntiDirection(oldDirection); break; default: assert(FALSE); } break; case LEFT: switch(oldAngle) { case 0: *newPlane = ABOVE; *newAngle = 3072; *newDirection = AntiDirection(oldDirection); break; case 1024: *newPlane = BACKWARD; *newAngle = 3072; *newDirection = AntiDirection(oldDirection); break; case 2048: *newPlane = BELOW; *newAngle = 3072; *newDirection = AntiDirection(oldDirection); break; case 3072: *newPlane = FORWARD; *newAngle = 1024; *newDirection = AntiDirection(oldDirection); break; default: assert(FALSE); } break; case RIGHT: switch(oldAngle) { case 0: *newPlane = ABOVE; *newAngle = 1024; *newDirection = AntiDirection(oldDirection); break; case 1024: *newPlane = FORWARD; *newAngle = 3072; *newDirection = AntiDirection(oldDirection); break; case 2048: *newPlane = BELOW; *newAngle = 1024; *newDirection = AntiDirection(oldDirection); break; case 3072: *newPlane = BACKWARD; *newAngle = 1024; *newDirection = AntiDirection(oldDirection); break; default: assert(FALSE); } break; case FORWARD: switch(oldAngle) { case 0: *newPlane = ABOVE; *newAngle = 0; *newDirection = AntiDirection(oldDirection); break; case 1024: *newPlane = LEFT; *newAngle = 3072; *newDirection = AntiDirection(oldDirection); break; case 2048: *newPlane = BELOW; *newAngle = 2048; *newDirection = AntiDirection(oldDirection); break; case 3072: *newPlane = RIGHT; *newAngle = 1024; *newDirection = AntiDirection(oldDirection); break; default: assert(FALSE); } break; case BACKWARD: switch(oldAngle) { case 0: *newPlane = ABOVE; *newAngle = 2048; *newDirection = AntiDirection(oldDirection); break; case 1024: *newPlane = RIGHT; *newAngle = 3072; *newDirection = AntiDirection(oldDirection); break; case 2048: *newPlane = BELOW; *newAngle = 0; *newDirection = AntiDirection(oldDirection); break; case 3072: *newPlane = LEFT; *newAngle = 1024; *newDirection = AntiDirection(oldDirection); break; default: assert(FALSE); } break; default: assert(FALSE); } }