/*********************************************************** * * * camera.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 Z_TILT_CLOCKWISE 1001 #define Z_TILT_ANTICLOCKWISE 1002 #define OVAL_ORBIT_LOW_ANGULAR_SPEED 8 #define OVAL_ORBIT_HIGH_ANGULAR_SPEED 64 #define CAMERA_CUBOID_X_LENGTH 220 #define CAMERA_CUBOID_Y_LENGTH 220 #define CAMERA_CUBOID_Z_LENGTH 220 #define CAMERA_SPHERE_RADIUS 220 #define INTRO_VIEW_MOVING_Z 1001 #define INTRO_VIEW_LOOPING_THE_LOOP 1002 #define INTRO_VIEW_NUDGING_UP 1003 #define INTRO_VIEW_NUDGING_DOWN 1004 #define NUMBER_INTRO_VIEW_TYPES 2 #define NUMBER_FIRST_DIRECTOR_SUB_MODES 8 #define NUMBER_OF_SECOND_DIRECTOR_VIEW_MODES (NUMBER_OF_DECENT_VIEW_MODES) #define NUMBER_THIRD_DIRECTOR_SUB_MODES 9 #define NUMBER_FOURTH_DIRECTOR_SUB_MODES 20 /**************************************************************************** local prototypes ****************************************************************************/ void InitLocalView (void); void InitCirclingBehindView (void); void InitSwivelsBehindView (void); void InitFixedBehindAboveView (void); void InitFixedBehindBelowView (void); void InitCirclingObjectChangingOrbitalPlaneView (void); void InitStaticFlybyView (void); void InitFirstMovingFlybyView (void); void InitSecondMovingFlybyView (void); void InitThirdMovingFlybyView (void); void InitLocalLookingBackwardsView (void); void InitSecondCuboidViewer (void); void InitThirdCuboidViewer (void); void InitSecondSphericalViewer (void); void InitThirdSphericalViewer (void); void InitHeadOnFlybyView (void); void InitHeadOnStaticShotView (void); void InitOffCentreStaticShotView (void); void InitFirstHelicalViewer (void); void InitSecondHelicalViewer (void); void InitFirstCuboidCirclingViewer (void); void InitSecondCuboidCirclingViewer (void); void UpdateLocalView (void); void UpdateLocalLookingBackwardsView (void); void UpdateCirclesBehindObjectView (void); void UpdateSwivelsBehindObjectView (void); void UpdateFixedBehindAboveObjectView (void); void UpdateFixedBehindAndBelowObjectView (void); void UpdateCirclesObjectChangingOrbitalPlaneView (void); void UpdateStaticFlybyView (void); void UpdateFirstMovingFlybyView (void); void UpdateSecondMovingFlybyView (void); void UpdateThirdMovingFlybyView (void); void UpdateFourthMovingFlybyView (void); void UpdateSplinePathBehindObjectView (void); void UpdateSplineDistanceBehindObjectView (void); void UpdateFirstCuboidViewer (void); void UpdateSecondCuboidViewer (void); void UpdateThirdCuboidViewer (void); void UpdateFirstSphericalViewer (void); void UpdateSecondSphericalViewer (void); void UpdateThirdSphericalViewer (void); void UpdateHeadOnFlyby (void); void UpdateHeadOnStaticShot (void); void UpdateOffCentreStaticShot (void); void UpdateFirstHelicalViewer (void); void UpdateSecondHelicalViewer (void); void UpdateFirstCuboidCirclingViewer (void); void UpdateSecondCuboidCirclingViewer (void); void InitExternalView (int mode); void InitCirclingView (int mode); void HandleCirclingView (int mode); void InitOvalOrbitView (int mode); void HandleOvalOrbitView (int mode); int ViewModeUsesSectionOffset (int viewMode); int SubViewModeUsesSectionOffset (int viewMode); void InitIntroView (void); void HandleFirstIntroView (int framesSinceStart); void HandleSecondIntroView (int framesSinceStart); /**************************************************************************** macros ****************************************************************************/ #define ValidID(id) ( (id >= 0) && (id < NumberTunnelSections) ) /**************************************************************************** globals ****************************************************************************/ int FramesSinceViewLastSet; // datums for view modes int FixedBehindDistance; int LocalDistance, LocalOffset; int SwivelBehindDistance; int FixedBehindAboveAngle; int FixedBehindBelowAngle; int SimpleCircleDistance, SimpleCircleRadius; int SimpleCircleDirection, SimpleCircleAngularSpeed; int SimpleCircleAngle; int FixedAheadDistance; int CirclingPlane, CirclingRadius; int CirclingAngle, CirclingDirection, CirclingAngularSpeed; int FarAwayCirclingRadius, CloseInCirclingRadius; int CirclingTwistingFlag; int OldCirclingPlane, NewCirclingPlane; int OldCirclingAngle, NewCirclingAngle, CirclingChangingPlaneStatus; int FramesWithinCirclingChangingOrbitalPlane; int CirclingChangingOrbitalPlaneDuration; int OvalTheta, OvalOrbitDirection; int OvalAngularSpeed, OvalOrbitBasicRadius; int OvalOrbitStretchRatio, OvalOrbitTwistDirection; int FlybyFrames, FlybyDistanceOffSplinePath, FlybyXYAngle; VECTOR FlybyViewpoint; int FlybyShipSpeed, FlybySection, FlybyOffsetRatio; int FlybyZTwistDirection; int SplinePathSectionDistance, SplinePathOffsetRatio; int SplinePathDistanceBehind; int PointOnCuboid, FramesSinceLastCuboidMove; int CuboidMovePeriod, CuboidMoveId; int PointOnSphere, FramesSinceLastSphericalMove; int SphericalMovePeriod, SphericalMoveId; int SphericalCameraMinRadius, SphericalCameraMaxRadius; int SphericalCameraZoomFlag; int FirstCuboidViewerTwistDirection; int FirstSphericalViewerTwistDirection; int HeadOnFlybyDuration, FramesWithinHeadOnFlyby; int HeadOnStaticShotDuration, FramesWithinHeadOnStaticShot; int OffCentreStaticShotDuration, FramesWithinOffCentreStaticShot; int OffCentreStaticShotDisplacement; int StaticShotSection; int StaticShotOffsetRatio; int FramesWithinFirstHelicalViewer, FirstHelicalViewerPeriod; int FirstHelicalViewerDistanceOffSplinePath; int FirstHelicalViewerTotalThetaZRevolutionAngle; int FirstHelicalViewerTotalThetaZCirclingDirection; int FirstHelicalViewerInitialAngle; int FirstHelicalViewerCylinderLength; int FramesWithinSecondHelicalViewer, SecondHelicalViewerPeriod; int SecondHelicalViewerDistanceOffSplinePath; int SecondHelicalViewerTotalThetaZRevolutionAngle; int SecondHelicalViewerTotalThetaZCirclingDirection; int SecondHelicalViewerTwistDirection; int SecondHelicalViewerInitialAngle; int SecondHelicalViewerCylinderLength; int FirstCuboidViewerCirclingPeriod, FramesWithinFirstCuboidCirclingViewer; int FirstCuboidViewerPlane, FirstCuboidViewerCirclingDirection; int FirstCuboidViewerAngle, FirstCuboidViewerAngleFlag; int FirstCuboidViewerCubeSideLength; int SecondCuboidViewerCirclingPeriod, FramesWithinSecondCuboidCirclingViewer; int SecondCuboidViewerPlane, SecondCuboidViewerCirclingDirection; int SecondCuboidViewerAngle, SecondCuboidViewerAngleFlag; int SecondCuboidViewerCubeSideLength; int SecondCuboidViewerTwistDirection; // directors int FirstDirectorSubMode; int FirstDirectorFlipFrequency; int FirstDirectorCurrentModeIndex; int FirstDirectorModeList[NUMBER_FIRST_DIRECTOR_SUB_MODES]; int FramesWithinFirstDirector; int SecondDirectorSubMode; int SecondDirectorFlipFrequency; int FramesWithinSecondDirector; int ThirdDirectorSubMode; int ThirdDirectorFlipFrequency; int ThirdDirectorCurrentModeIndex; int ThirdDirectorModeList[NUMBER_THIRD_DIRECTOR_SUB_MODES]; int FramesWithinThirdDirector; int FourthDirectorSubMode; int FourthDirectorFlipFrequency; int FourthDirectorCurrentModeIndex; int FourthDirectorModeList[NUMBER_FOURTH_DIRECTOR_SUB_MODES]; int FramesWithinFourthDirector; GsCOORDINATE2 CameraCoord; GsCOORDINATE2 VirtualViewShipCoord; int IntroTypeFlag; int IntroViewDurationInSeconds; int IntroViewPhase; int IntroViewStartPoint; int IntroViewDistanceFromSplinePath; int IntroViewBehindDistance; int IntroViewAboveDistance; int IntroViewInitialZValue; int IntroViewTotalZDistance; int IntroViewFinalZValue; int IntroViewTwistDirection; int IntroViewTwistAngle; /**************************************************************************** externed globals from camera2.c ****************************************************************************/ extern int CardinalFlybyDistanceOffSplinePath; extern int FramesWithinThirdHelicalViewer, ThirdHelicalViewerPeriod; extern int ThirdHelicalViewerDistanceOffSplinePath; extern int ThirdHelicalViewerTotalThetaZRevolutionAngle; extern int ThirdHelicalViewerTotalThetaZCirclingDirection; extern int ThirdHelicalViewerInitialAngle; extern int ThirdHelicalViewerCylinderLength; extern int ThirdHelicalViewerMinDistanceOffSplinePath; extern int ThirdHelicalViewerMaxDistanceOffSplinePath; extern int FramesWithinFourthHelicalViewer, FourthHelicalViewerPeriod; extern int FourthHelicalViewerDistanceOffSplinePath; extern int FourthHelicalViewerTotalThetaZRevolutionAngle; extern int FourthHelicalViewerTotalThetaZCirclingDirection; extern int FourthHelicalViewerInitialAngle; extern int FourthHelicalViewerCylinderLength; extern int FourthHelicalViewerMinDistanceOffSplinePath; extern int FourthHelicalViewerMaxDistanceOffSplinePath; extern int FirstLazyRotationViewerPeriod; extern int FirstLazyRotationViewerSubPeriod; extern int FramesWithinFirstLazyRotationViewer; extern int FirstLazyRotationViewerDistance; extern int FirstLazyRotationAngularSpeed; extern int LazyRotationEffect1, LazyRotationEffect2; extern int *SmallerEffect, *LargerEffect; extern int SecondLazyRotationViewerPeriod; extern int SecondLazyRotationViewerSubPeriod; extern int FramesWithinSecondLazyRotationViewer; extern int SecondLazyRotationViewerDistance; extern int SecondLazyRotationAngularSpeed; extern int ThirdLazyRotationViewerPeriod; extern int ThirdLazyRotationViewerSubPeriod; extern int FramesWithinThirdLazyRotationViewer; extern int ThirdLazyRotationViewerDistance; extern int ThirdLazyRotationAngularSpeed; /**************************************************************************** functions ****************************************************************************/ void SetCoreViewParameters (void) { ViewTypeFlag = REFERENCE_VIEW; // by default // set parameters of the various view modes FixedBehindDistance = 220; LocalDistance = 220; LocalOffset = 110; // forward from fixed_behind setup SwivelBehindDistance = 220; FixedBehindAboveAngle = ONE/32; FixedBehindBelowAngle = ONE/48; SimpleCircleDistance = 220; SimpleCircleRadius = 80; SimpleCircleDirection = CLOCKWISE; SimpleCircleAngularSpeed = ONE / (2 * MaximumGameFramesPerSecond); SimpleCircleAngle = 0; // theta=0 is ABOVE-BEHIND FixedAheadDistance = 220; CirclingPlane = X_Y_PLANE; CirclingRadius = 220; CirclingAngle = 0; CirclingDirection = CLOCKWISE; CirclingAngularSpeed = ONE / (4 * MaximumGameFramesPerSecond); FarAwayCirclingRadius = 1024; CloseInCirclingRadius = 195; CirclingTwistingFlag = CLOCKWISE; OldCirclingPlane = X_Y_PLANE; NewCirclingPlane = Y_Z_PLANE; OldCirclingAngle = 0; NewCirclingAngle = 0; CirclingChangingPlaneStatus = 0; FramesWithinCirclingChangingOrbitalPlane = 1; CirclingChangingOrbitalPlaneDuration = MaximumGameFramesPerSecond; OvalTheta = 0; OvalOrbitDirection = CLOCKWISE; OvalAngularSpeed = OVAL_ORBIT_LOW_ANGULAR_SPEED; OvalOrbitBasicRadius = 220; OvalOrbitStretchRatio = 5; // 3 OvalOrbitTwistDirection = CLOCKWISE; FlybyFrames = MaximumGameFramesPerSecond; FlybyDistanceOffSplinePath = DEFAULT_TRACK_OUTER_RADIUS / 8; CardinalFlybyDistanceOffSplinePath = 195; FlybyXYAngle = rand() % ONE; setVECTOR( &FlybyViewpoint, 0, 0, 0); FlybyShipSpeed = 0; FlybySection = 0; FlybyOffsetRatio = 0; FlybyZTwistDirection = -1; SplinePathSectionDistance = 0; SplinePathOffsetRatio = -ONE/2; SplinePathDistanceBehind = 220; PointOnCuboid = ABOVE_FORWARD_LEFT; FramesSinceLastCuboidMove = 0; CuboidMovePeriod = MaximumGameFramesPerSecond; CuboidMoveId = BELOW; PointOnSphere = FORWARD; FramesSinceLastSphericalMove = 0; SphericalMovePeriod = MaximumGameFramesPerSecond; SphericalMoveId = ABOVE; SphericalCameraMinRadius = 195; SphericalCameraMaxRadius = 512; SphericalCameraZoomFlag = FALSE; FirstCuboidViewerTwistDirection = CLOCKWISE; FirstSphericalViewerTwistDirection = CLOCKWISE; HeadOnFlybyDuration = MaximumGameFramesPerSecond; FramesWithinHeadOnFlyby = 0; HeadOnStaticShotDuration = MaximumGameFramesPerSecond; FramesWithinHeadOnStaticShot = 0; OffCentreStaticShotDuration = MaximumGameFramesPerSecond; FramesWithinOffCentreStaticShot = 0; OffCentreStaticShotDisplacement = DEFAULT_TRACK_OUTER_RADIUS / 6; StaticShotSection = -1; StaticShotOffsetRatio = 0; FramesWithinFirstHelicalViewer = 0; FirstHelicalViewerPeriod = MaximumGameFramesPerSecond * 6; FirstHelicalViewerDistanceOffSplinePath = 210; FirstHelicalViewerTotalThetaZRevolutionAngle = ONE * 3; FirstHelicalViewerCylinderLength = DEFAULT_TRACK_SECTION_LENGTH; FramesWithinSecondHelicalViewer = 0; SecondHelicalViewerPeriod = MaximumGameFramesPerSecond * 4; SecondHelicalViewerDistanceOffSplinePath = DEFAULT_TRACK_OUTER_RADIUS / 10; SecondHelicalViewerTotalThetaZRevolutionAngle = ONE * 3; SecondHelicalViewerCylinderLength = DEFAULT_TRACK_SECTION_LENGTH * 2; FramesWithinThirdHelicalViewer = 0; ThirdHelicalViewerPeriod = MaximumGameFramesPerSecond * 3; ThirdHelicalViewerTotalThetaZRevolutionAngle = (ONE * 3) / 2; ThirdHelicalViewerCylinderLength = DEFAULT_TRACK_SECTION_LENGTH * 2; ThirdHelicalViewerMinDistanceOffSplinePath = 200; ThirdHelicalViewerMaxDistanceOffSplinePath = 1024; FramesWithinFourthHelicalViewer = 0; FourthHelicalViewerPeriod = (MaximumGameFramesPerSecond * 3) / 2; FourthHelicalViewerTotalThetaZRevolutionAngle = (ONE * 3) / 2; FourthHelicalViewerCylinderLength = DEFAULT_TRACK_SECTION_LENGTH * 2; FourthHelicalViewerMinDistanceOffSplinePath = 200; FourthHelicalViewerMaxDistanceOffSplinePath = 1024; FirstCuboidViewerCirclingPeriod = MaximumGameFramesPerSecond * 2; FramesWithinFirstCuboidCirclingViewer = 0; FirstCuboidViewerCubeSideLength = 360; SecondCuboidViewerCirclingPeriod = MaximumGameFramesPerSecond; // * 2 FramesWithinSecondCuboidCirclingViewer = 0; SecondCuboidViewerCubeSideLength = 280; FirstLazyRotationViewerPeriod = (MaximumGameFramesPerSecond * 3) / 2; FirstLazyRotationViewerSubPeriod = MaximumGameFramesPerSecond/6; FirstLazyRotationViewerDistance = 195; FirstLazyRotationAngularSpeed = 24; SecondLazyRotationViewerPeriod = MaximumGameFramesPerSecond; SecondLazyRotationViewerSubPeriod = MaximumGameFramesPerSecond/8; SecondLazyRotationViewerDistance = 312; SecondLazyRotationAngularSpeed = 64; ThirdLazyRotationViewerPeriod = MaximumGameFramesPerSecond * 3; ThirdLazyRotationViewerSubPeriod = MaximumGameFramesPerSecond/3; ThirdLazyRotationViewerDistance = 195; ThirdLazyRotationAngularSpeed = 36; FirstDirectorSubMode = BASE_VIEW_MODE; FirstDirectorFlipFrequency = MaximumGameFramesPerSecond * 2; FirstDirectorCurrentModeIndex = 0; FirstDirectorModeList[0] = VIEW_FIXED_BEHIND_ABOVE_OBJECT; FirstDirectorModeList[1] = VIEW_OBJECT_IN_FIRST_MOVING_FLYBY; FirstDirectorModeList[2] = VIEW_CIRCLES_OBJECT; FirstDirectorModeList[3] = VIEW_BY_FOURTH_SPHERICAL_VIEWER; // VIEW_OBJECT_IN_FIRST_MOVING_FLYBY; FirstDirectorModeList[4] = VIEW_LOCAL_TO_OBJECT; FirstDirectorModeList[5] = VIEW_OBJECT_IN_FIRST_MOVING_FLYBY; FirstDirectorModeList[6] = VIEW_BY_SECOND_SPHERICAL_VIEWER; // VIEW_CIRCLES_OBJECT; FirstDirectorModeList[7] = VIEW_OBJECT_IN_FOURTH_MOVING_FLYBY; // VIEW_OBJECT_IN_FIRST_MOVING_FLYBY; SecondDirectorSubMode = BASE_VIEW_MODE; SecondDirectorFlipFrequency = MaximumGameFramesPerSecond * 2; // 4 ThirdDirectorSubMode = BASE_VIEW_MODE; ThirdDirectorFlipFrequency = MaximumGameFramesPerSecond * 2; ThirdDirectorCurrentModeIndex = 0; ThirdDirectorModeList[0] = VIEW_FIXED_BEHIND_ABOVE_OBJECT; ThirdDirectorModeList[1] = VIEW_OBJECT_IN_FIRST_MOVING_FLYBY; ThirdDirectorModeList[2] = VIEW_CIRCLES_OBJECT; ThirdDirectorModeList[3] = VIEW_OBJECT_IN_STATIC_FLYBY; ThirdDirectorModeList[4] = VIEW_LOCAL_TO_OBJECT; ThirdDirectorModeList[5] = VIEW_BY_FIRST_SPHERICAL_VIEWER; // VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT; ThirdDirectorModeList[6] = VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT; // VIEW_BY_OFF_CENTRE_STATIC_SHOT; ThirdDirectorModeList[7] = VIEW_OBJECT_IN_CARDINAL_FLYBY; // VIEW_OBJECT_IN_CARDINAL_FLYBY; ThirdDirectorModeList[8] = VIEW_BY_OFF_CENTRE_STATIC_SHOT; // VIEW_BY_HEAD_ON_FLYBY; FourthDirectorSubMode = BASE_VIEW_MODE; FourthDirectorFlipFrequency = MaximumGameFramesPerSecond * 2; FourthDirectorCurrentModeIndex = 0; FourthDirectorModeList[0] = VIEW_FIXED_BEHIND_ABOVE_OBJECT; FourthDirectorModeList[1] = VIEW_OBJECT_IN_FIRST_MOVING_FLYBY; FourthDirectorModeList[2] = VIEW_CIRCLES_OBJECT; FourthDirectorModeList[3] = VIEW_OBJECT_IN_STATIC_FLYBY; FourthDirectorModeList[4] = VIEW_BY_FOURTH_SPHERICAL_VIEWER; FourthDirectorModeList[5] = VIEW_LOCAL_TO_OBJECT; FourthDirectorModeList[6] = VIEW_OBJECT_IN_SECOND_OVAL_ORBIT; FourthDirectorModeList[7] = VIEW_OBJECT_IN_CARDINAL_FLYBY; FourthDirectorModeList[8] = VIEW_OBJECT_IN_THIRD_OVAL_ORBIT; FourthDirectorModeList[9] = VIEW_BY_HEAD_ON_FLYBY; FourthDirectorModeList[10] = VIEW_BY_THIRD_CUBOID_VIEWER; FourthDirectorModeList[11] = VIEW_BY_SECOND_SPHERICAL_VIEWER; FourthDirectorModeList[12] = VIEW_BY_HEAD_ON_STATIC_SHOT; FourthDirectorModeList[13] = VIEW_LOCAL_LOOKING_BACKWARDS; FourthDirectorModeList[14] = VIEW_BY_FIRST_CUBOID_CIRCLING_VIEWER; FourthDirectorModeList[15] = VIEW_BY_OFF_CENTRE_STATIC_SHOT; FourthDirectorModeList[16] = VIEW_BY_SECOND_HELICAL_VIEWER; FourthDirectorModeList[17] = VIEW_BY_FIRST_LAZY_ROTATION_VIEW; FourthDirectorModeList[18] = VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT; FourthDirectorModeList[19] = VIEW_BY_SECOND_LAZY_ROTATION_VIEW; IntroViewDurationInSeconds = 2; FramesSinceViewLastSet = 0; // init basic view structures TheView.super = WORLD; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = 0; TheMatrixView.super = WORLD; InitMatrix( &TheMatrixView.view); GsInitCoordinate2(WORLD, &CameraCoord); InitMatrix( &CameraCoord.coord); CameraCoord.super = WORLD; CameraCoord.flg = 0; } void SetViewInSystem (void) { switch(ViewTypeFlag) { case REFERENCE_VIEW: GsSetRefView2( &TheView); break; case MATRIX_VIEW: GsSetView2( &TheMatrixView); break; default: assert(FALSE); } } int ViewModeProhibitsDrawing (ObjectHandler *object) { assert(object != NULL); if (object == TheViewShip) { if (object->viewMode == VIEW_LOCAL_TO_OBJECT) return TRUE; else if (object->viewMode == VIEW_LOCAL_LOOKING_BACKWARDS) return TRUE; else if (object->viewMode == VIEW_BY_FIRST_DIRECTORS_CUT && FirstDirectorSubMode == VIEW_LOCAL_TO_OBJECT) return TRUE; else if (object->viewMode == VIEW_BY_SECOND_DIRECTORS_CUT && SecondDirectorSubMode == VIEW_LOCAL_TO_OBJECT) return TRUE; else return FALSE; } else { return FALSE; } } void SetViewPointSection (int sectionID) { assert(ValidID(sectionID)); ViewPointSection = sectionID; } void SetViewPositionKnowingCloseToViewShip (void) { #if 0 // NOT YET READY int sectionID, newViewPointSectionID; assert(TheViewShip != NULL); sectionID = TheViewShip->tunnelSection; newViewPointSectionID = FindSectionPointIsIn( &TheViewShip->position, sectionID); SetViewPointSection(newViewPointSectionID); #endif } // At present, this sets new view ship and will typically reset view-mode data; // function below (HandleTheView) handles updating every frame. // COMPLICATION: 2player mode, want to call this func twice per frame // without resetting all view mode data // - at present not a problem since the ship modes are non-continuous over time void SetNewViewShip (ObjectHandler *newViewShip) { assert(newViewShip != NULL); TheViewShip = newViewShip; switch(TheViewShip->viewMode) { case VIEW_BY_FIRST_DIRECTORS_CUT: // pick random initial mode FirstDirectorCurrentModeIndex = rand() % NUMBER_FIRST_DIRECTOR_SUB_MODES; FirstDirectorSubMode = FirstDirectorModeList[FirstDirectorCurrentModeIndex]; FramesWithinFirstDirector = 1; SetViewByViewMode(FirstDirectorSubMode); break; case VIEW_BY_SECOND_DIRECTORS_CUT: // pick random initial mode SecondDirectorSubMode = BASE_VIEW_MODE + (rand() % NUMBER_OF_SECOND_DIRECTOR_VIEW_MODES); FramesWithinSecondDirector = 1; SetViewByViewMode(SecondDirectorSubMode); break; case VIEW_BY_THIRD_DIRECTORS_CUT: // pick random initial mode ThirdDirectorCurrentModeIndex = rand() % NUMBER_THIRD_DIRECTOR_SUB_MODES; ThirdDirectorSubMode = ThirdDirectorModeList[ThirdDirectorCurrentModeIndex]; FramesWithinThirdDirector = 1; SetViewByViewMode(ThirdDirectorSubMode); break; case VIEW_BY_FOURTH_DIRECTORS_CUT: // pick random initial mode FourthDirectorCurrentModeIndex = rand() % NUMBER_FOURTH_DIRECTOR_SUB_MODES; FourthDirectorSubMode = FourthDirectorModeList[FourthDirectorCurrentModeIndex]; FramesWithinFourthDirector = 1; SetViewByViewMode(FourthDirectorSubMode); break; default: SetViewByViewMode(TheViewShip->viewMode); } SetViewInSystem(); } // set a specific view mode void SetViewByViewMode (int viewMode) { assert(viewMode >= BASE_VIEW_MODE); assert(viewMode < BASE_VIEW_MODE + NUMBER_OF_SHIP_VIEW_MODES); ProjectionDistance = FIXED_PROJECTION_DISTANCE; GsSetProjection(ProjectionDistance); switch(viewMode) { case VIEW_LOCAL_TO_OBJECT: InitLocalView(); break; case VIEW_CIRCLES_BEHIND_OBJECT: InitCirclingBehindView(); break; case VIEW_SWIVELS_BEHIND_OBJECT: InitSwivelsBehindView(); break; case VIEW_FIXED_BEHIND_ABOVE_OBJECT: InitFixedBehindAboveView(); break; case VIEW_FIXED_BEHIND_BELOW_OBJECT: InitFixedBehindBelowView(); break; case VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT: case VIEW_FIXED_EXTERNAL_BEHIND_OBJECT: case VIEW_FIXED_EXTERNAL_LEFT_OF_OBJECT: case VIEW_FIXED_EXTERNAL_RIGHT_OF_OBJECT: case VIEW_FIXED_EXTERNAL_ABOVE_OBJECT: case VIEW_FIXED_EXTERNAL_BELOW_OBJECT: InitExternalView(viewMode); break; case VIEW_CIRCLES_OBJECT_CLOSE_IN: case VIEW_CIRCLES_OBJECT: case VIEW_CIRCLES_OBJECT_TWISTING: case VIEW_CIRCLES_OBJECT_FAR_AWAY: case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: InitCirclingView(viewMode); break; case VIEW_CIRCLES_OBJECT_CHANGING_ORBITAL_PLANE: InitCirclingObjectChangingOrbitalPlaneView(); break; case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: InitOvalOrbitView(viewMode); break; case VIEW_OBJECT_IN_STATIC_FLYBY: InitStaticFlybyView(); break; case VIEW_OBJECT_IN_CARDINAL_FLYBY: InitCardinalFlyby(); break; case VIEW_OBJECT_IN_FOURTH_MOVING_FLYBY: FlybyZTwistDirection = CLOCKWISE + (rand() % 2); InitFirstMovingFlybyView(); break; case VIEW_OBJECT_IN_FIRST_MOVING_FLYBY: InitFirstMovingFlybyView(); break; case VIEW_OBJECT_IN_THIRD_MOVING_FLYBY: InitThirdMovingFlybyView(); break; case VIEW_OBJECT_IN_SECOND_MOVING_FLYBY: InitSecondMovingFlybyView(); break; case VIEW_FROM_SPLINE_PATH_BEHIND_OBJECT: UpdateSplinePathBehindObjectView(); break; case VIEW_LOCAL_LOOKING_BACKWARDS: InitLocalLookingBackwardsView(); break; case VIEW_BY_FIRST_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_BY_SECOND_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_BY_THIRD_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_BY_FOURTH_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_FROM_SPLINE_DISTANCE_BEHIND_OBJECT: UpdateSplineDistanceBehindObjectView(); break; case VIEW_BY_FIRST_CUBOID_VIEWER: if ((rand() % 2) == 0) FirstCuboidViewerTwistDirection = CLOCKWISE; else FirstCuboidViewerTwistDirection = ANTICLOCKWISE; InitSecondCuboidViewer(); break; case VIEW_BY_SECOND_CUBOID_VIEWER: InitSecondCuboidViewer(); break; case VIEW_BY_THIRD_CUBOID_VIEWER: InitThirdCuboidViewer(); break; case VIEW_BY_FIRST_SPHERICAL_VIEWER: if ((rand() % 2) == 0) FirstSphericalViewerTwistDirection = CLOCKWISE; else FirstSphericalViewerTwistDirection = ANTICLOCKWISE; InitSecondSphericalViewer(); break; case VIEW_BY_SECOND_SPHERICAL_VIEWER: InitSecondSphericalViewer(); break; case VIEW_BY_THIRD_SPHERICAL_VIEWER: InitThirdSphericalViewer(); break; case VIEW_BY_FOURTH_SPHERICAL_VIEWER: InitFourthSphericalViewer(); break; case VIEW_BY_HEAD_ON_FLYBY: InitHeadOnFlybyView(); break; case VIEW_BY_HEAD_ON_STATIC_SHOT: InitHeadOnStaticShotView(); break; case VIEW_BY_OFF_CENTRE_STATIC_SHOT: InitOffCentreStaticShotView(); break; case VIEW_BY_FIRST_HELICAL_VIEWER: InitFirstHelicalViewer(); break; case VIEW_BY_SECOND_HELICAL_VIEWER: InitSecondHelicalViewer(); break; case VIEW_BY_THIRD_HELICAL_VIEWER: InitThirdHelicalViewer(); break; case VIEW_BY_FOURTH_HELICAL_VIEWER: InitFourthHelicalViewer(); break; case VIEW_BY_FIRST_CUBOID_CIRCLING_VIEWER: InitFirstCuboidCirclingViewer(); break; case VIEW_BY_SECOND_CUBOID_CIRCLING_VIEWER: InitSecondCuboidCirclingViewer(); break; case VIEW_BY_FIRST_SPIRAL_VIEWER: InitFirstSpiralViewer(); break; case VIEW_BY_FIRST_LAZY_ROTATION_VIEW: InitFirstLazyRotationViewer(); break; case VIEW_BY_SECOND_LAZY_ROTATION_VIEW: InitSecondLazyRotationViewer(); break; case VIEW_BY_THIRD_LAZY_ROTATION_VIEW: InitThirdLazyRotationViewer(); break; default: assert(FALSE); } FramesSinceViewLastSet = frameNumber; } void InitLocalView (void) { VECTOR shipZaxis, trans, temp; MATRIX baseShipMatrix, tempMatrix; int z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); z = LocalDistance/2; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((-z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((-z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((-z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void InitCirclingBehindView (void) { ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; TheView.vpx = 0; TheView.vpy = -SimpleCircleRadius; if (TheViewShip->modelFlag == TMD_RIGHT_WAY) { TheView.vpz = -SimpleCircleDistance; } else { assert(TheViewShip->modelFlag == TMD_WRONG_WAY); TheView.vpz = SimpleCircleDistance; } SimpleCircleAngle = 0; SimpleCircleDirection = CLOCKWISE + (rand() % 2); TheView.rz = 0; } void InitSwivelsBehindView (void) { // this JUST like fixed_behind; // swivelling sorted in HandleTheView ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; TheView.vpx = 0; TheView.vpy = 0; if (TheViewShip->modelFlag == TMD_RIGHT_WAY) TheView.vpz = -SwivelBehindDistance; else { assert(TheViewShip->modelFlag == TMD_WRONG_WAY); TheView.vpz = SwivelBehindDistance; } TheView.rz = 0; } void InitFixedBehindAboveView (void) { VECTOR shipZaxis, shipYaxis, trans, temp; MATRIX baseShipMatrix, tempMatrix; int y, z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); setVECTOR( &shipYaxis, baseShipMatrix.m[0][1], baseShipMatrix.m[1][1], baseShipMatrix.m[2][1]); y = (FixedBehindDistance * rsin(FixedBehindAboveAngle)) >> 12; z = (FixedBehindDistance * rcos(FixedBehindAboveAngle)) >> 12; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((-y * shipYaxis.vx)>>12) + ((-z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((-y * shipYaxis.vy)>>12) + ((-z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((-y * shipYaxis.vz)>>12) + ((-z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void InitFixedBehindBelowView (void) { VECTOR shipZaxis, shipYaxis, trans, temp; MATRIX baseShipMatrix, tempMatrix; int y, z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); setVECTOR( &shipYaxis, baseShipMatrix.m[0][1], baseShipMatrix.m[1][1], baseShipMatrix.m[2][1]); y = (FixedBehindDistance * rsin(FixedBehindBelowAngle)) >> 12; z = (FixedBehindDistance * rcos(FixedBehindBelowAngle)) >> 12; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((y * shipYaxis.vx)>>12) + ((-z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((y * shipYaxis.vy)>>12) + ((-z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((y * shipYaxis.vz)>>12) + ((-z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void InitCirclingObjectChangingOrbitalPlaneView (void) { int point, orientation; ViewTypeFlag = REFERENCE_VIEW; orientation = rand() % 4; point = ABOVE + (rand() % 6); GsInitCoordinate2(WORLD, &CameraCoord); SetMatrixByPointAndOrientation( &CameraCoord.coord, point, orientation); CameraCoord.super = &TheViewShip->coord; CirclingDirection = TILT_LEFT + (rand() % 4); TheView.super = &CameraCoord; TheView.rz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -CirclingRadius; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; FramesWithinCirclingChangingOrbitalPlane = 1; } void InitStaticFlybyView (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); if (TunnelSectionLength == 0) { distanceInSections = distanceCovered / DEFAULT_TRACK_SECTION_LENGTH; distanceOffset = distanceCovered % DEFAULT_TRACK_SECTION_LENGTH; } else { distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; } if ((distanceInSections % 2) == 0) { aheadSections = (distanceInSections / 2); aheadOffset = (distanceOffset / 2); } else { aheadSections = ((distanceInSections-1) / 2); aheadOffset = ((distanceOffset / 2) + 2048); } 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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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 InitFirstMovingFlybyView (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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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 InitSecondMovingFlybyView (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; GetDividedSectionAndOffset (distanceInSections, distanceOffset, 8, &aheadSections, &aheadOffset); 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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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 InitThirdMovingFlybyView (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; GetDividedSectionAndOffset (distanceInSections, distanceOffset, 8, &aheadSections, &aheadOffset); aheadSections *= 3; aheadOffset *= 3; while (aheadOffset >= ONE) { aheadOffset -= ONE; aheadSections++; } 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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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 InitLocalLookingBackwardsView (void) { VECTOR shipZaxis, trans, temp; SVECTOR twist; MATRIX baseShipMatrix, tempMatrix; int z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); z = LocalDistance/2; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); setVECTOR( &twist, 0, 2048, 0); RotMatrix( &twist, &tempMatrix); MulMatrix0( &TheMatrixView.view, &tempMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void InitSecondCuboidViewer (void) { int axisOfMove; VECTOR point; ViewTypeFlag = REFERENCE_VIEW; PointOnCuboid = ABOVE_FORWARD_LEFT + (rand() % 8); FramesSinceLastCuboidMove = 0; TheView.super = &TheViewShip->coord; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; axisOfMove = X_AXIS + (rand() % 3); switch(axisOfMove) { case X_AXIS: if (TheView.vpx > 0) CuboidMoveId = MOVE_LEFT; else CuboidMoveId = MOVE_RIGHT; break; case Y_AXIS: if (TheView.vpy > 0) CuboidMoveId = MOVE_UP; else CuboidMoveId = MOVE_DOWN; break; case Z_AXIS: if (TheView.vpz > 0) CuboidMoveId = MOVE_BACKWARD; else CuboidMoveId = MOVE_FORWARD; break; default: assert(FALSE); } } void InitThirdCuboidViewer (void) { int moveFlag; VECTOR point; ViewTypeFlag = REFERENCE_VIEW; PointOnCuboid = ABOVE_FORWARD_LEFT + (rand() % 8); FramesSinceLastCuboidMove = 0; TheView.super = &TheViewShip->coord; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; moveFlag = rand() % 4; switch(moveFlag) { case 0: if (TheView.vpx > 0) CuboidMoveId = MOVE_LEFT; else CuboidMoveId = MOVE_RIGHT; break; case 1: if (TheView.vpy > 0) CuboidMoveId = MOVE_UP; else CuboidMoveId = MOVE_DOWN; break; case 2: if (TheView.vpz > 0) CuboidMoveId = MOVE_BACKWARD; else CuboidMoveId = MOVE_FORWARD; break; case 3: if ((rand() % 2) == 0) CuboidMoveId = Z_TILT_CLOCKWISE; else CuboidMoveId = Z_TILT_ANTICLOCKWISE; break; default: assert(FALSE); } } void InitSecondSphericalViewer (void) { int point, orientation; 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; TheView.vpz = -CAMERA_SPHERE_RADIUS; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; FramesSinceLastSphericalMove = 1; } void InitThirdSphericalViewer (void) { int point, orientation, moveFlag; ViewTypeFlag = REFERENCE_VIEW; orientation = rand() % 4; point = ABOVE + (rand() % 6); GsInitCoordinate2(WORLD, &CameraCoord); SetMatrixByPointAndOrientation( &CameraCoord.coord, point, orientation); CameraCoord.super = &TheViewShip->coord; moveFlag = rand() % 6; if (moveFlag == 4) SphericalMoveId = TILT_CLOCKWISE; else if (moveFlag == 5) SphericalMoveId = TILT_ANTICLOCKWISE; else SphericalMoveId = TILT_LEFT + moveFlag; TheView.super = &CameraCoord; TheView.rz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -CAMERA_SPHERE_RADIUS; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; FramesSinceLastSphericalMove = 1; } void InitHeadOnFlybyView (void) { int viewShipSpeed; int distanceCovered, distanceInSections, distanceOffset; int aheadSections, aheadOffset, sectionID, offsetRatio; int newSectionID, newOffsetRatio; VECTOR tunnelPoint, worldPoint; ViewTypeFlag = REFERENCE_VIEW; viewShipSpeed = GetSpeedOfViewShip(); distanceCovered = viewShipSpeed * HeadOnFlybyDuration; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; if ((distanceInSections % 2) == 0) { aheadSections = distanceInSections / 2; aheadOffset = distanceOffset / 2; } else { aheadSections = (distanceInSections-1) / 2; aheadOffset = (distanceOffset / 2) + 2048; } 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; setVECTOR( &tunnelPoint, 0, 0, ((newOffsetRatio * TunnelSectionLength) >> 12) ); ExpressSubPointInSuper( &tunnelPoint, &TheTunnel[newSectionID].coordinateData, &worldPoint); worldPoint.vx += TheTunnel[newSectionID].splinePoint.vx; worldPoint.vy += TheTunnel[newSectionID].splinePoint.vy; worldPoint.vz += TheTunnel[newSectionID].splinePoint.vz; TheView.super = WORLD; TheView.rz = 0; TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; FramesWithinHeadOnFlyby = 1; } void InitHeadOnStaticShotView (void) { int viewShipSpeed; int distanceCovered, distanceInSections, distanceOffset; int sectionID, offsetRatio; int newSectionID, newOffsetRatio; VECTOR tunnelPoint, worldPoint; viewShipSpeed = GetSpeedOfViewShip(); distanceCovered = viewShipSpeed * OffCentreStaticShotDuration; distanceCovered *= 9; distanceCovered /= 10; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); assert(offsetRatio >= 0); assert(offsetRatio < ONE); GetNewSectionAndOffset (sectionID, offsetRatio, distanceInSections, distanceOffset, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); assert(newOffsetRatio >= 0); assert(newOffsetRatio < ONE); StaticShotSection = newSectionID; StaticShotOffsetRatio = newOffsetRatio; setVECTOR( &tunnelPoint, 0, 0, ((newOffsetRatio * TunnelSectionLength) >> 12) ); ExpressSubPointInSuper( &tunnelPoint, &TheTunnel[newSectionID].coordinateData, &worldPoint); worldPoint.vx += TheTunnel[newSectionID].splinePoint.vx; worldPoint.vy += TheTunnel[newSectionID].splinePoint.vy; worldPoint.vz += TheTunnel[newSectionID].splinePoint.vz; ViewTypeFlag = REFERENCE_VIEW; TheView.super = WORLD; TheView.rz = 0; TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; FramesWithinHeadOnStaticShot = 1; } void InitOffCentreStaticShotView (void) { int viewShipSpeed, theta, x, y; int distanceCovered, distanceInSections, distanceOffset; int sectionID, offsetRatio; int newSectionID, newOffsetRatio; VECTOR tunnelPoint, worldPoint; viewShipSpeed = GetSpeedOfViewShip(); distanceCovered = viewShipSpeed * OffCentreStaticShotDuration; distanceCovered *= 9; distanceCovered /= 10; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); assert(offsetRatio >= 0); assert(offsetRatio < ONE); GetNewSectionAndOffset (sectionID, offsetRatio, distanceInSections, distanceOffset, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); assert(newOffsetRatio >= 0); assert(newOffsetRatio < ONE); StaticShotSection = newSectionID; StaticShotOffsetRatio = newOffsetRatio; theta = rand() % ONE; x = (OffCentreStaticShotDisplacement * rcos(theta)) >> 12; y = (OffCentreStaticShotDisplacement * rcos(theta)) >> 12; assert( (abs(x)) < TunnelInnerRadius); assert( (abs(y)) < TunnelInnerRadius); setVECTOR( &tunnelPoint, x, y, ((newOffsetRatio * TunnelSectionLength) >> 12) ); ExpressSubPointInSuper( &tunnelPoint, &TheTunnel[newSectionID].coordinateData, &worldPoint); worldPoint.vx += TheTunnel[newSectionID].splinePoint.vx; worldPoint.vy += TheTunnel[newSectionID].splinePoint.vy; worldPoint.vz += TheTunnel[newSectionID].splinePoint.vz; ViewTypeFlag = REFERENCE_VIEW; TheView.super = WORLD; TheView.rz = 0; TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; FramesWithinOffCentreStaticShot = 1; } void InitFirstHelicalViewer (void) { FramesWithinFirstHelicalViewer = 0; FirstHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); FirstHelicalViewerInitialAngle = rand() % ONE; ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; TheView.rz = 0; } void InitSecondHelicalViewer (void) { FramesWithinSecondHelicalViewer = 0; SecondHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); SecondHelicalViewerTwistDirection = CLOCKWISE + (rand() % 2); SecondHelicalViewerInitialAngle = rand() % ONE; ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; TheView.rz = 0; } void InitFirstCuboidCirclingViewer (void) { ViewTypeFlag = REFERENCE_VIEW; FramesWithinFirstCuboidCirclingViewer = 0; FirstCuboidViewerPlane = ABOVE + (rand() % 6); FirstCuboidViewerCirclingDirection = CLOCKWISE + (rand() % 2); FirstCuboidViewerAngle = 0; FirstCuboidViewerAngleFlag = 0; } void InitSecondCuboidCirclingViewer (void) { ViewTypeFlag = REFERENCE_VIEW; FramesWithinSecondCuboidCirclingViewer = 0; SecondCuboidViewerPlane = ABOVE + (rand() % 6); SecondCuboidViewerCirclingDirection = CLOCKWISE + (rand() % 2); SecondCuboidViewerAngle = 0; SecondCuboidViewerAngleFlag = 0; SecondCuboidViewerTwistDirection = CLOCKWISE + (rand() % 2); } void HandleTheView (void) { int newSubMode; if (OverallGameState == VIEWING_THE_TRACKS && TrackViewerMainMode == VIEW_TRACK_FROM_OUTSIDE) { SetViewInSystem(); return; } switch(TheViewShip->viewMode) { case VIEW_BY_FIRST_DIRECTORS_CUT: assert(FramesWithinFirstDirector >= 0); assert(FramesWithinFirstDirector <= FirstDirectorFlipFrequency); if (FramesWithinFirstDirector == FirstDirectorFlipFrequency) // director chooses new view { if (FirstDirectorCurrentModeIndex == NUMBER_FIRST_DIRECTOR_SUB_MODES-1) FirstDirectorCurrentModeIndex = 0; else FirstDirectorCurrentModeIndex++; FirstDirectorSubMode = FirstDirectorModeList[FirstDirectorCurrentModeIndex]; SetViewByViewMode(FirstDirectorSubMode); FramesWithinFirstDirector = 1; } else { UpdateViewMode(FirstDirectorSubMode); FramesWithinFirstDirector++; } break; case VIEW_BY_SECOND_DIRECTORS_CUT: assert(FramesWithinSecondDirector >= 0); assert(FramesWithinSecondDirector <= SecondDirectorFlipFrequency); if (FramesWithinSecondDirector == SecondDirectorFlipFrequency) // director chooses new view { for (;;) // pick any view different from the previous one { newSubMode = BASE_VIEW_MODE + (rand() % NUMBER_OF_SECOND_DIRECTOR_VIEW_MODES); if (newSubMode != SecondDirectorSubMode) break; } SecondDirectorSubMode = newSubMode; SetViewByViewMode(SecondDirectorSubMode); FramesWithinSecondDirector = 1; } else { UpdateViewMode(SecondDirectorSubMode); FramesWithinSecondDirector++; } break; case VIEW_BY_THIRD_DIRECTORS_CUT: assert(FramesWithinThirdDirector >= 0); assert(FramesWithinThirdDirector <= ThirdDirectorFlipFrequency); if (FramesWithinThirdDirector == ThirdDirectorFlipFrequency) // director chooses new view { if (ThirdDirectorCurrentModeIndex == NUMBER_THIRD_DIRECTOR_SUB_MODES-1) ThirdDirectorCurrentModeIndex = 0; else ThirdDirectorCurrentModeIndex++; ThirdDirectorSubMode = ThirdDirectorModeList[ThirdDirectorCurrentModeIndex]; SetViewByViewMode(ThirdDirectorSubMode); FramesWithinThirdDirector = 1; } else { UpdateViewMode(ThirdDirectorSubMode); FramesWithinThirdDirector++; } break; case VIEW_BY_FOURTH_DIRECTORS_CUT: assert(FramesWithinFourthDirector >= 0); assert(FramesWithinFourthDirector <= FourthDirectorFlipFrequency); if (FramesWithinFourthDirector == FourthDirectorFlipFrequency) // director chooses new view { if (FourthDirectorCurrentModeIndex == NUMBER_FOURTH_DIRECTOR_SUB_MODES-1) FourthDirectorCurrentModeIndex = 0; else FourthDirectorCurrentModeIndex++; FourthDirectorSubMode = FourthDirectorModeList[FourthDirectorCurrentModeIndex]; SetViewByViewMode(FourthDirectorSubMode); FramesWithinFourthDirector = 1; } else { UpdateViewMode(FourthDirectorSubMode); FramesWithinFourthDirector++; } break; default: UpdateViewMode(TheViewShip->viewMode); } SetViewInSystem(); } void UpdateViewMode (int viewMode) { //assert(viewMode >= BASE_VIEW_MODE); if (viewMode < BASE_VIEW_MODE) { printf("BAD viewMode %d\n", viewMode); assert(FALSE); } //assert(viewMode <= (BASE_VIEW_MODE + NUMBER_OF_SHIP_VIEW_MODES - 1)); if (viewMode > (BASE_VIEW_MODE + NUMBER_OF_SHIP_VIEW_MODES - 1)) { printf("BAD viewMode %d\n", viewMode); assert(FALSE); } if (ViewModeUsesSectionOffset(viewMode) == FALSE) { StartDrawingSectionBaseShift = 0; } switch(viewMode) { case VIEW_LOCAL_TO_OBJECT: UpdateLocalView(); break; case VIEW_CIRCLES_BEHIND_OBJECT: UpdateCirclesBehindObjectView(); break; case VIEW_SWIVELS_BEHIND_OBJECT: UpdateSwivelsBehindObjectView(); break; case VIEW_FIXED_BEHIND_ABOVE_OBJECT: UpdateFixedBehindAboveObjectView(); break; case VIEW_FIXED_BEHIND_BELOW_OBJECT: UpdateFixedBehindAndBelowObjectView(); break; case VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT: case VIEW_FIXED_EXTERNAL_BEHIND_OBJECT: case VIEW_FIXED_EXTERNAL_LEFT_OF_OBJECT: case VIEW_FIXED_EXTERNAL_RIGHT_OF_OBJECT: case VIEW_FIXED_EXTERNAL_ABOVE_OBJECT: case VIEW_FIXED_EXTERNAL_BELOW_OBJECT: // no updating needed beyond SetViewInSystem break; case VIEW_LOCAL_LOOKING_BACKWARDS: UpdateLocalLookingBackwardsView(); break; case VIEW_CIRCLES_OBJECT: case VIEW_CIRCLES_OBJECT_TWISTING: case VIEW_CIRCLES_OBJECT_FAR_AWAY: case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: case VIEW_CIRCLES_OBJECT_CLOSE_IN: HandleCirclingView(viewMode); break; case VIEW_CIRCLES_OBJECT_CHANGING_ORBITAL_PLANE: UpdateCirclesObjectChangingOrbitalPlaneView(); break; case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: HandleOvalOrbitView(viewMode); break; case VIEW_OBJECT_IN_STATIC_FLYBY: UpdateStaticFlybyView(); break; case VIEW_OBJECT_IN_CARDINAL_FLYBY: UpdateCardinalFlyby(); break; case VIEW_OBJECT_IN_FIRST_MOVING_FLYBY: UpdateFirstMovingFlybyView(); break; case VIEW_OBJECT_IN_FOURTH_MOVING_FLYBY: UpdateFourthMovingFlybyView(); break; case VIEW_OBJECT_IN_THIRD_MOVING_FLYBY: UpdateThirdMovingFlybyView(); break; case VIEW_OBJECT_IN_SECOND_MOVING_FLYBY: UpdateSecondMovingFlybyView(); break; case VIEW_FROM_SPLINE_PATH_BEHIND_OBJECT: UpdateSplinePathBehindObjectView(); break; case VIEW_FROM_SPLINE_DISTANCE_BEHIND_OBJECT: UpdateSplineDistanceBehindObjectView(); break; case VIEW_BY_FIRST_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_BY_SECOND_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_BY_THIRD_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_BY_FOURTH_DIRECTORS_CUT: assert(FALSE); // shouldn't get here break; case VIEW_BY_FIRST_CUBOID_VIEWER: UpdateFirstCuboidViewer(); break; case VIEW_BY_SECOND_CUBOID_VIEWER: UpdateSecondCuboidViewer(); break; case VIEW_BY_THIRD_CUBOID_VIEWER: UpdateThirdCuboidViewer(); break; case VIEW_BY_FIRST_SPHERICAL_VIEWER: UpdateFirstSphericalViewer(); break; case VIEW_BY_SECOND_SPHERICAL_VIEWER: UpdateSecondSphericalViewer(); break; case VIEW_BY_THIRD_SPHERICAL_VIEWER: UpdateThirdSphericalViewer(); break; case VIEW_BY_FOURTH_SPHERICAL_VIEWER: UpdateFourthSphericalViewer(); break; case VIEW_BY_HEAD_ON_FLYBY: UpdateHeadOnFlyby(); break; case VIEW_BY_HEAD_ON_STATIC_SHOT: UpdateHeadOnStaticShot(); break; case VIEW_BY_OFF_CENTRE_STATIC_SHOT: UpdateOffCentreStaticShot(); break; case VIEW_BY_FIRST_HELICAL_VIEWER: UpdateFirstHelicalViewer(); break; case VIEW_BY_SECOND_HELICAL_VIEWER: UpdateSecondHelicalViewer(); break; case VIEW_BY_THIRD_HELICAL_VIEWER: UpdateThirdHelicalViewer(); break; case VIEW_BY_FOURTH_HELICAL_VIEWER: UpdateFourthHelicalViewer(); break; case VIEW_BY_FIRST_CUBOID_CIRCLING_VIEWER: UpdateFirstCuboidCirclingViewer(); break; case VIEW_BY_SECOND_CUBOID_CIRCLING_VIEWER: UpdateSecondCuboidCirclingViewer(); break; case VIEW_BY_FIRST_SPIRAL_VIEWER: UpdateFirstSpiralViewer(); break; case VIEW_BY_FIRST_LAZY_ROTATION_VIEW: UpdateFirstLazyRotationViewer(); break; case VIEW_BY_SECOND_LAZY_ROTATION_VIEW: UpdateSecondLazyRotationViewer(); break; case VIEW_BY_THIRD_LAZY_ROTATION_VIEW: UpdateThirdLazyRotationViewer(); break; default: assert(FALSE); } } void UpdateLocalView (void) { VECTOR shipZaxis, trans, temp; MATRIX baseShipMatrix, tempMatrix; int z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); z = LocalDistance/2; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((-z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((-z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((-z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void UpdateLocalLookingBackwardsView (void) { VECTOR shipZaxis, trans, temp; SVECTOR twist; MATRIX baseShipMatrix, tempMatrix; int z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); z = LocalDistance/2; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); setVECTOR( &twist, 0, 2048, 0); RotMatrix( &twist, &tempMatrix); MulMatrix0( &TheMatrixView.view, &tempMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void UpdateCirclesBehindObjectView (void) { int x, y; // when theta==0, we are above and behind ship x = (SimpleCircleRadius * rsin(SimpleCircleAngle)) >> 12; y = -(SimpleCircleRadius * rcos(SimpleCircleAngle)) >> 12; TheView.vpx = x; TheView.vpy = y; switch(SimpleCircleDirection) { case CLOCKWISE: SimpleCircleAngle += SimpleCircleAngularSpeed; break; case ANTICLOCKWISE: SimpleCircleAngle -= SimpleCircleAngularSpeed; break; default: assert(FALSE); } } void UpdateSwivelsBehindObjectView (void) { int sectionID, offsetRatio, statusFlag, angle, x, y, z; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); ProperGetCurveStatus (sectionID, offsetRatio, &statusFlag, &angle); angle = -angle; if (OverallGameState == VIEWING_THE_TRACKS) angle += TrackViewerDeviationAngle; switch(TheTunnelDescription.twoDflag) { case X_Z_PLANE_ONLY: x = (SwivelBehindDistance * rsin(angle)) >> 12; y = 0; z = (SwivelBehindDistance * rcos(angle)) >> 12; break; case Y_Z_PLANE_ONLY: x = 0; y = -(SwivelBehindDistance * rsin(angle)) >> 12; z = (SwivelBehindDistance * rcos(angle)) >> 12; break; default: assert(FALSE); } TheView.vpx = x; TheView.vpy = y; if (TheViewShip->modelFlag == TMD_RIGHT_WAY) { TheView.vpz = -z; } else { assert(TheViewShip->modelFlag == TMD_WRONG_WAY); TheView.vpz = z; } } void UpdateFixedBehindAboveObjectView (void) { VECTOR shipZaxis, shipYaxis, trans, temp; MATRIX baseShipMatrix, tempMatrix; int y, z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); setVECTOR( &shipYaxis, baseShipMatrix.m[0][1], baseShipMatrix.m[1][1], baseShipMatrix.m[2][1]); y = (FixedBehindDistance * rsin(FixedBehindAboveAngle)) >> 12; z = (FixedBehindDistance * rcos(FixedBehindAboveAngle)) >> 12; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((-y * shipYaxis.vx)>>12) + ((-z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((-y * shipYaxis.vy)>>12) + ((-z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((-y * shipYaxis.vz)>>12) + ((-z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void UpdateFixedBehindAndBelowObjectView (void) { VECTOR shipZaxis, shipYaxis, trans, temp; MATRIX baseShipMatrix, tempMatrix; int y, z; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); setVECTOR( &shipYaxis, baseShipMatrix.m[0][1], baseShipMatrix.m[1][1], baseShipMatrix.m[2][1]); y = (FixedBehindDistance * rsin(FixedBehindBelowAngle)) >> 12; z = (FixedBehindDistance * rcos(FixedBehindBelowAngle)) >> 12; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((y * shipYaxis.vx)>>12) + ((-z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((y * shipYaxis.vy)>>12) + ((-z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((y * shipYaxis.vz)>>12) + ((-z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } void UpdateCirclesObjectChangingOrbitalPlaneView (void) { assert(FramesWithinCirclingChangingOrbitalPlane >= 0); assert(FramesWithinCirclingChangingOrbitalPlane <= CirclingChangingOrbitalPlaneDuration); if (FramesWithinCirclingChangingOrbitalPlane == CirclingChangingOrbitalPlaneDuration) { if (CirclingChangingPlaneStatus != 0) CirclingChangingPlaneStatus = 0; else { if ( (rand() % 4) == 0) { if ((rand()%2) == 0) CirclingChangingPlaneStatus = 1; else CirclingChangingPlaneStatus = 2; } else CirclingChangingPlaneStatus = 0; } FramesWithinCirclingChangingOrbitalPlane = 1; } else { int smallAngle; SVECTOR twistVector; MATRIX twistMatrix; smallAngle = CirclingAngularSpeed; switch(CirclingDirection) { 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); } assert(CirclingChangingOrbitalPlaneDuration > 0); smallAngle = 1024 / CirclingChangingOrbitalPlaneDuration; switch(CirclingChangingPlaneStatus) { case 0: // do nowt break; case 1: setVECTOR( &twistVector, 0, 0, smallAngle); RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); break; case 2: setVECTOR( &twistVector, 0, 0, -smallAngle); RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); break; default: assert(FALSE); } FramesWithinCirclingChangingOrbitalPlane++; } } void UpdateStaticFlybyView (void) { int framesSinceThisModeSet, framesWithinFlyby; int sectionID, offsetRatio; int newSectionID, newOffsetRatio; int aheadSections, aheadOffset; 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 / 2); aheadOffset = (distanceOffset / 2); } else { aheadSections = ((distanceInSections-1) / 2); aheadOffset = ((distanceOffset / 2) + 2048); } 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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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; TheView.rz = 0; // setting base shift: camera not attached to view ship StartDrawingSectionBaseShift = aheadSections; } else { int distance, direction; TheView.super = WORLD; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; TheView.vpx = FlybyViewpoint.vx; TheView.vpy = FlybyViewpoint.vy; TheView.vpz = FlybyViewpoint.vz; TheView.rz = 0; // setting base shift: camera not attached to view ship sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); FindShortestDistance (sectionID, FlybySection, &distance, &direction); if (direction == BACKWARDS) distance = -distance; StartDrawingSectionBaseShift = distance; } } void UpdateFirstMovingFlybyView (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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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; TheView.rz = 0; } 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 = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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 UpdateFourthMovingFlybyView (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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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.rz = 0; TheView.super = WORLD; FlybyZTwistDirection = CLOCKWISE + (rand() % 2); } 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 = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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; assert(FlybyFrames > 0); switch(FlybyZTwistDirection) { case CLOCKWISE: TheView.rz = (180 * framesWithinFlyby * ONE) / FlybyFrames; break; case ANTICLOCKWISE: TheView.rz = (180 * ONE) - ((180 * framesWithinFlyby * ONE) / FlybyFrames); break; default: assert(FALSE); } } } void UpdateThirdMovingFlybyView (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; GetDividedSectionAndOffset (distanceInSections, distanceOffset, 8, &aheadSections, &aheadOffset); aheadSections *= 3; aheadOffset *= 3; while (aheadOffset >= ONE) { aheadOffset -= ONE; aheadSections++; } 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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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; TheView.rz = 0; // setting base shift: camera not attached to view ship StartDrawingSectionBaseShift = aheadSections; } else { int distance, direction; TheView.super = WORLD; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; movePerFrame = FlybyShipSpeed / 4; 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 = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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; // setting base shift: camera not attached to view ship sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); FindShortestDistance (sectionID, newSectionID, &distance, &direction); if (direction == BACKWARDS) distance = -distance; StartDrawingSectionBaseShift = distance; } } void UpdateSecondMovingFlybyView (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; GetDividedSectionAndOffset (distanceInSections, distanceOffset, 8, &aheadSections, &aheadOffset); 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() % ONE; x = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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 = (3 * FlybyShipSpeed) / 4; 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 = (FlybyDistanceOffSplinePath * rcos(FlybyXYAngle)) >> 12; y = (FlybyDistanceOffSplinePath * 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 UpdateSplinePathBehindObjectView (void) { assert(FALSE); #if 0 // NOT USED int sectionID, offsetRatio; int newSectionID, newOffsetRatio; TunnelSection *newSection; VECTOR worldPoint; ViewTypeFlag = REFERENCE_VIEW; TheView.super = WORLD; TheView.rz = 0; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); assert(offsetRatio >= 0); assert(offsetRatio < ONE); GetPointOnSplinePath (sectionID, offsetRatio, &worldPoint); TheView.vrx = worldPoint.vx; TheView.vry = worldPoint.vy; TheView.vrz = worldPoint.vz; GetNewSectionAndOffset (sectionID, offsetRatio, SplinePathSectionDistance, SplinePathOffsetRatio, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); newSection = &TheTunnel[newSectionID]; GetPointOnSplinePath (newSectionID, newOffsetRatio, &worldPoint); TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; #endif } void UpdateSplineDistanceBehindObjectView (void) { assert(FALSE); #if 0 // not used VECTOR worldPoint, tunnelPoint; int sectionID; TunnelSection *section; ViewTypeFlag = REFERENCE_VIEW; TheView.super = WORLD; TheView.rz = 0; setVECTOR( &worldPoint, TheViewShip->position.vx, TheViewShip->position.vy, TheViewShip->position.vz); sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); section = &TheTunnel[sectionID]; worldPoint.vx -= section->splinePoint.vx; worldPoint.vy -= section->splinePoint.vy; worldPoint.vz -= section->splinePoint.vz; ExpressSuperPointInSub( &worldPoint, §ion->coordinateData, &tunnelPoint); if (tunnelPoint.vz < 0) { sectionID = GetRelativeSection(sectionID, 1, BACKWARDS); section = &TheTunnel[sectionID]; setVECTOR( &worldPoint, TheViewShip->position.vx, TheViewShip->position.vy, TheViewShip->position.vz); worldPoint.vx -= section->splinePoint.vx; worldPoint.vy -= section->splinePoint.vy; worldPoint.vz -= section->splinePoint.vz; ExpressSuperPointInSub( &worldPoint, §ion->coordinateData, &tunnelPoint); //assert(tunnelPoint.vz >= 0); if (tunnelPoint.vz < 0) { printf("BAD value tunnelPoint.vz %d\n", (int)tunnelPoint.vz); HERE; exit(1); } } if (tunnelPoint.vz >= TunnelSectionLength) { sectionID = GetRelativeSection(sectionID, 1, FORWARDS); section = &TheTunnel[sectionID]; setVECTOR( &worldPoint, TheViewShip->position.vx, TheViewShip->position.vy, TheViewShip->position.vz); worldPoint.vx -= section->splinePoint.vx; worldPoint.vy -= section->splinePoint.vy; worldPoint.vz -= section->splinePoint.vz; ExpressSuperPointInSub( &worldPoint, §ion->coordinateData, &tunnelPoint); //assert(tunnelPoint.vz < TunnelSectionLength); if (tunnelPoint.vz >= TunnelSectionLength) { printf("BAD value tunnelPoint.vz %d\n", (int)tunnelPoint.vz); printf("TunnelSectionLength %d\n", TunnelSectionLength); HERE; exit(1); } } // get view point: given distance further back along spline path tunnelPoint.vz -= SplinePathDistanceBehind; if (tunnelPoint.vz < 0) { sectionID = GetRelativeSection(sectionID, 1, BACKWARDS); section = &TheTunnel[sectionID]; setVECTOR( &worldPoint, TheViewShip->position.vx, TheViewShip->position.vy, TheViewShip->position.vz); worldPoint.vx -= section->splinePoint.vx; worldPoint.vy -= section->splinePoint.vy; worldPoint.vz -= section->splinePoint.vz; ExpressSuperPointInSub( &worldPoint, §ion->coordinateData, &tunnelPoint); tunnelPoint.vz -= SplinePathDistanceBehind; assert(tunnelPoint.vz >= 0); assert(tunnelPoint.vz < TunnelSectionLength); } ExpressSubPointInSuper( &tunnelPoint, §ion->coordinateData, &worldPoint); worldPoint.vx += section->splinePoint.vx; worldPoint.vy += section->splinePoint.vy; worldPoint.vz += section->splinePoint.vz; TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; #endif } void UpdateFirstCuboidViewer (void) { assert(FramesSinceLastCuboidMove >= 0); assert(FramesSinceLastCuboidMove <= CuboidMovePeriod); if (FramesSinceLastCuboidMove == CuboidMovePeriod) { int oldAxis, newAxis; VECTOR point; PointOnCuboid = GetNewPointOnCuboid(PointOnCuboid, CuboidMoveId); GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; oldAxis = GetAxisOfMove(CuboidMoveId); for (;;) { newAxis = X_AXIS + (rand() % 3); if (newAxis != oldAxis) break; } switch(newAxis) { case X_AXIS: if (TheView.vpx > 0) CuboidMoveId = MOVE_LEFT; else CuboidMoveId = MOVE_RIGHT; break; case Y_AXIS: if (TheView.vpy > 0) CuboidMoveId = MOVE_UP; else CuboidMoveId = MOVE_DOWN; break; case Z_AXIS: if (TheView.vpz > 0) CuboidMoveId = MOVE_BACKWARD; else CuboidMoveId = MOVE_FORWARD; break; default: assert(FALSE); } FramesSinceLastCuboidMove = 0; if ((rand() % 4) == 0) { switch(FirstCuboidViewerTwistDirection) { case CLOCKWISE: FirstCuboidViewerTwistDirection = ANTICLOCKWISE; break; case ANTICLOCKWISE: FirstCuboidViewerTwistDirection = CLOCKWISE; break; default: assert(FALSE); } } } else { VECTOR point; int period; GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); assert(CuboidMovePeriod > 0); period = (FramesSinceLastCuboidMove * ONE) / CuboidMovePeriod; switch(CuboidMoveId) { case MOVE_UP: point.vy -= (CAMERA_CUBOID_Y_LENGTH * 2 * period) / ONE; break; case MOVE_DOWN: point.vy += (CAMERA_CUBOID_Y_LENGTH * 2 * period) / ONE; break; case MOVE_LEFT: point.vx -= (CAMERA_CUBOID_X_LENGTH * 2 * period) / ONE; break; case MOVE_RIGHT: point.vx += (CAMERA_CUBOID_X_LENGTH * 2 * period) / ONE; break; case MOVE_FORWARD: point.vz += (CAMERA_CUBOID_Z_LENGTH * 2 * period) / ONE; break; case MOVE_BACKWARD: point.vz -= (CAMERA_CUBOID_Z_LENGTH * 2 * period) / ONE; break; default: assert(FALSE); } TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; switch(FirstCuboidViewerTwistDirection) { case CLOCKWISE: TheView.rz += ((90 * ONE) / CuboidMovePeriod); break; case ANTICLOCKWISE: TheView.rz -= ((90 * ONE) / CuboidMovePeriod); break; default: printf("BAD value %d\n", FirstCuboidViewerTwistDirection); assert(FALSE); } FramesSinceLastCuboidMove++; } } void UpdateSecondCuboidViewer (void) { assert(FramesSinceLastCuboidMove >= 0); assert(FramesSinceLastCuboidMove <= CuboidMovePeriod); if (FramesSinceLastCuboidMove == CuboidMovePeriod) { int oldAxis, newAxis; VECTOR point; PointOnCuboid = GetNewPointOnCuboid(PointOnCuboid, CuboidMoveId); GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; oldAxis = GetAxisOfMove(CuboidMoveId); for (;;) { newAxis = X_AXIS + (rand() % 3); if (newAxis != oldAxis) break; } switch(newAxis) { case X_AXIS: if (TheView.vpx > 0) CuboidMoveId = MOVE_LEFT; else CuboidMoveId = MOVE_RIGHT; break; case Y_AXIS: if (TheView.vpy > 0) CuboidMoveId = MOVE_UP; else CuboidMoveId = MOVE_DOWN; break; case Z_AXIS: if (TheView.vpz > 0) CuboidMoveId = MOVE_BACKWARD; else CuboidMoveId = MOVE_FORWARD; break; default: assert(FALSE); } FramesSinceLastCuboidMove = 0; TheView.rz = 0; } else { VECTOR point; int period; GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); assert(CuboidMovePeriod > 0); period = (FramesSinceLastCuboidMove * ONE) / CuboidMovePeriod; switch(CuboidMoveId) { case MOVE_UP: point.vy -= (CAMERA_CUBOID_Y_LENGTH * 2 * period) / ONE; break; case MOVE_DOWN: point.vy += (CAMERA_CUBOID_Y_LENGTH * 2 * period) / ONE; break; case MOVE_LEFT: point.vx -= (CAMERA_CUBOID_X_LENGTH * 2 * period) / ONE; break; case MOVE_RIGHT: point.vx += (CAMERA_CUBOID_X_LENGTH * 2 * period) / ONE; break; case MOVE_FORWARD: point.vz += (CAMERA_CUBOID_Z_LENGTH * 2 * period) / ONE; break; case MOVE_BACKWARD: point.vz -= (CAMERA_CUBOID_Z_LENGTH * 2 * period) / ONE; break; default: assert(FALSE); } TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; TheView.rz = 0; FramesSinceLastCuboidMove++; } } void UpdateThirdCuboidViewer (void) { assert(FramesSinceLastCuboidMove >= 0); assert(FramesSinceLastCuboidMove <= CuboidMovePeriod); if (FramesSinceLastCuboidMove == CuboidMovePeriod) { int oldAxis, newMove; VECTOR point; if (CuboidMoveId != Z_TILT_CLOCKWISE && CuboidMoveId != Z_TILT_ANTICLOCKWISE) { PointOnCuboid = GetNewPointOnCuboid(PointOnCuboid, CuboidMoveId); GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; oldAxis = GetAxisOfMove(CuboidMoveId); // get new move for (;;) { newMove = X_AXIS + (rand() % 4); // 4th 'axis' is tilt option if (newMove != oldAxis) break; } if (newMove == X_AXIS + 3) // tilt option { if ((rand() % 2) == 0) CuboidMoveId = Z_TILT_CLOCKWISE; else CuboidMoveId = Z_TILT_ANTICLOCKWISE; } else // axis move { switch(newMove) { case X_AXIS: if (TheView.vpx > 0) CuboidMoveId = MOVE_LEFT; else CuboidMoveId = MOVE_RIGHT; break; case Y_AXIS: if (TheView.vpy > 0) CuboidMoveId = MOVE_UP; else CuboidMoveId = MOVE_DOWN; break; case Z_AXIS: if (TheView.vpz > 0) CuboidMoveId = MOVE_BACKWARD; else CuboidMoveId = MOVE_FORWARD; break; default: assert(FALSE); } } } else // have just done tilt move, so do any axis move { newMove = X_AXIS + (rand() % 3); switch(newMove) { case X_AXIS: if (TheView.vpx > 0) CuboidMoveId = MOVE_LEFT; else CuboidMoveId = MOVE_RIGHT; break; case Y_AXIS: if (TheView.vpy > 0) CuboidMoveId = MOVE_UP; else CuboidMoveId = MOVE_DOWN; break; case Z_AXIS: if (TheView.vpz > 0) CuboidMoveId = MOVE_BACKWARD; else CuboidMoveId = MOVE_FORWARD; break; default: assert(FALSE); } } FramesSinceLastCuboidMove = 0; } else { VECTOR point; int period; assert(CuboidMovePeriod > 0); period = (FramesSinceLastCuboidMove * ONE) / CuboidMovePeriod; if (CuboidMoveId != Z_TILT_CLOCKWISE && CuboidMoveId != Z_TILT_ANTICLOCKWISE) { GetPointOnCuboid(CAMERA_CUBOID_X_LENGTH, CAMERA_CUBOID_Y_LENGTH, CAMERA_CUBOID_Z_LENGTH, PointOnCuboid, &point); switch(CuboidMoveId) { case MOVE_UP: point.vy -= (CAMERA_CUBOID_Y_LENGTH * 2 * period) / ONE; break; case MOVE_DOWN: point.vy += (CAMERA_CUBOID_Y_LENGTH * 2 * period) / ONE; break; case MOVE_LEFT: point.vx -= (CAMERA_CUBOID_X_LENGTH * 2 * period) / ONE; break; case MOVE_RIGHT: point.vx += (CAMERA_CUBOID_X_LENGTH * 2 * period) / ONE; break; case MOVE_FORWARD: point.vz += (CAMERA_CUBOID_Z_LENGTH * 2 * period) / ONE; break; case MOVE_BACKWARD: point.vz -= (CAMERA_CUBOID_Z_LENGTH * 2 * period) / ONE; break; default: assert(FALSE); } TheView.vpx = point.vx; TheView.vpy = point.vy; TheView.vpz = point.vz; } else { switch(CuboidMoveId) { case Z_TILT_CLOCKWISE: TheView.rz += ((120 * ONE) / CuboidMovePeriod); break; case Z_TILT_ANTICLOCKWISE: TheView.rz -= ((120 * ONE) / CuboidMovePeriod); break; default: assert(FALSE); } } FramesSinceLastCuboidMove++; } } void UpdateFirstSphericalViewer (void) { assert(FramesSinceLastSphericalMove >= 0); assert(FramesSinceLastSphericalMove <= SphericalMovePeriod); 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); } if ((rand() % 2) == 0) FirstSphericalViewerTwistDirection = CLOCKWISE; else FirstSphericalViewerTwistDirection = ANTICLOCKWISE; FramesSinceLastSphericalMove = 1; } else { int smallAngle; SVECTOR twistVector; MATRIX twistMatrix; int period; assert(SphericalMovePeriod > 0); smallAngle = 1024 / SphericalMovePeriod; 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); } assert(SphericalMovePeriod > 0); period = (FramesSinceLastSphericalMove * ONE) / SphericalMovePeriod; switch(FirstSphericalViewerTwistDirection) { case CLOCKWISE: TheView.rz += ((90 * ONE) / SphericalMovePeriod); break; case ANTICLOCKWISE: TheView.rz -= ((90 * ONE) / SphericalMovePeriod); break; default: assert(FALSE); } FramesSinceLastSphericalMove++; } } void UpdateSecondSphericalViewer (void) { 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; } else { int smallAngle; SVECTOR twistVector; MATRIX twistMatrix; assert(SphericalMovePeriod > 0); smallAngle = 1024 / SphericalMovePeriod; 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 UpdateThirdSphericalViewer (void) { assert(FramesSinceLastSphericalMove >= 0); assert(FramesSinceLastSphericalMove <= SphericalMovePeriod); if (FramesSinceLastSphericalMove == SphericalMovePeriod) { switch(SphericalMoveId) { case TILT_CLOCKWISE: case TILT_ANTICLOCKWISE: SphericalMoveId = TILT_LEFT + (rand() % 4); break; case TILT_LEFT: case TILT_RIGHT: if ((rand() % 2) == 0) { if ((rand() % 2) == 0) SphericalMoveId = TILT_UP; else SphericalMoveId = TILT_DOWN; } else { if ((rand() % 2) == 0) SphericalMoveId = TILT_CLOCKWISE; else SphericalMoveId = TILT_ANTICLOCKWISE; } break; case TILT_UP: case TILT_DOWN: if ((rand() % 2) == 0) { if ((rand() % 2) == 0) SphericalMoveId = TILT_LEFT; else SphericalMoveId = TILT_RIGHT; } else { if ((rand() % 2) == 0) SphericalMoveId = TILT_CLOCKWISE; else SphericalMoveId = TILT_ANTICLOCKWISE; } break; default: assert(FALSE); } FramesSinceLastSphericalMove = 1; } else { int smallAngle; SVECTOR twistVector; MATRIX twistMatrix; assert(SphericalMovePeriod > 0); smallAngle = 1024 / SphericalMovePeriod; 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; case TILT_CLOCKWISE: TheView.rz += ((90 * ONE) / SphericalMovePeriod); break; case TILT_ANTICLOCKWISE: TheView.rz -= ((90 * ONE) / SphericalMovePeriod); break; default: assert(FALSE); } FramesSinceLastSphericalMove++; } } void UpdateHeadOnFlyby (void) { assert(FramesWithinHeadOnFlyby >= 0); assert(FramesWithinHeadOnFlyby <= HeadOnFlybyDuration); if (FramesWithinHeadOnFlyby == HeadOnFlybyDuration) { int viewShipSpeed; int distanceCovered, distanceInSections, distanceOffset; int aheadSections, aheadOffset, sectionID, offsetRatio; int newSectionID, newOffsetRatio; VECTOR tunnelPoint, worldPoint; viewShipSpeed = GetSpeedOfViewShip(); distanceCovered = viewShipSpeed * HeadOnFlybyDuration; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; if ((distanceInSections % 2) == 0) { aheadSections = distanceInSections / 2; aheadOffset = distanceOffset / 2; } else { aheadSections = (distanceInSections-1) / 2; aheadOffset = (distanceOffset / 2) + 2048; } sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); GetNewSectionAndOffset (sectionID, offsetRatio, aheadSections, aheadOffset, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); assert(newOffsetRatio >= 0); assert(newOffsetRatio < ONE); FlybySection = newSectionID; FlybyOffsetRatio = newOffsetRatio; setVECTOR( &tunnelPoint, 0, 0, ((newOffsetRatio * TunnelSectionLength) >> 12) ); ExpressSubPointInSuper( &tunnelPoint, &TheTunnel[newSectionID].coordinateData, &worldPoint); worldPoint.vx += TheTunnel[newSectionID].splinePoint.vx; worldPoint.vy += TheTunnel[newSectionID].splinePoint.vy; worldPoint.vz += TheTunnel[newSectionID].splinePoint.vz; TheView.super = WORLD; TheView.rz = 0; TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; FramesWithinHeadOnFlyby = 1; // setting base shift: camera not attached to view ship StartDrawingSectionBaseShift = aheadSections; } else { int distance, direction; int sectionID; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; FramesWithinHeadOnFlyby++; // setting base shift: camera not attached to view ship sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); FindShortestDistance (sectionID, FlybySection, &distance, &direction); if (direction == BACKWARDS) distance = -distance; StartDrawingSectionBaseShift = distance; } } void UpdateHeadOnStaticShot (void) { assert(FramesWithinHeadOnStaticShot >= 0); assert(FramesWithinHeadOnStaticShot <= HeadOnStaticShotDuration); if (FramesWithinHeadOnStaticShot == HeadOnStaticShotDuration) { int viewShipSpeed; int distanceCovered, distanceInSections, distanceOffset; int sectionID, offsetRatio; int newSectionID, newOffsetRatio; VECTOR tunnelPoint, worldPoint; viewShipSpeed = GetSpeedOfViewShip(); distanceCovered = viewShipSpeed * HeadOnStaticShotDuration; distanceCovered *= 9; distanceCovered /= 10; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); assert(offsetRatio >= 0); assert(offsetRatio < ONE); GetNewSectionAndOffset (sectionID, offsetRatio, distanceInSections, distanceOffset, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); assert(newOffsetRatio >= 0); assert(newOffsetRatio < ONE); StaticShotSection = newSectionID; StaticShotOffsetRatio = newOffsetRatio; setVECTOR( &tunnelPoint, 0, 0, ((newOffsetRatio * TunnelSectionLength) >> 12) ); ExpressSubPointInSuper( &tunnelPoint, &TheTunnel[newSectionID].coordinateData, &worldPoint); worldPoint.vx += TheTunnel[newSectionID].splinePoint.vx; worldPoint.vy += TheTunnel[newSectionID].splinePoint.vy; worldPoint.vz += TheTunnel[newSectionID].splinePoint.vz; TheView.super = WORLD; TheView.rz = 0; TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; FramesWithinHeadOnStaticShot = 1; #if 1 // calc section dist from view ship to viewpoiint // note: only the former moves { int distance, direction; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); FindShortestDistance (sectionID, StaticShotSection, &distance, &direction); StartDrawingSectionBaseShift = distance; } #endif } else { FramesWithinHeadOnStaticShot++; #if 1 // calc section dist from view ship to viewpoiint // note: only the former moves { int distance, direction; int sectionID; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); FindShortestDistance (sectionID, StaticShotSection, &distance, &direction); StartDrawingSectionBaseShift = distance; } #endif } } void UpdateOffCentreStaticShot (void) { assert(FramesWithinOffCentreStaticShot >= 0); assert(FramesWithinOffCentreStaticShot <= OffCentreStaticShotDuration); if (FramesWithinOffCentreStaticShot == OffCentreStaticShotDuration) { int viewShipSpeed, theta, x, y; int distanceCovered, distanceInSections, distanceOffset; int sectionID, offsetRatio; int newSectionID, newOffsetRatio; VECTOR tunnelPoint, worldPoint; viewShipSpeed = GetSpeedOfViewShip(); distanceCovered = viewShipSpeed * OffCentreStaticShotDuration; distanceCovered *= 9; distanceCovered /= 10; assert(TunnelSectionLength > 0); distanceInSections = distanceCovered / TunnelSectionLength; distanceOffset = distanceCovered % TunnelSectionLength; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); offsetRatio = GetOffsetOfPoint( &TheViewShip->position, sectionID); assert(offsetRatio >= 0); assert(offsetRatio < ONE); GetNewSectionAndOffset (sectionID, offsetRatio, distanceInSections, distanceOffset, &newSectionID, &newOffsetRatio); assert(ValidID(newSectionID)); assert(newOffsetRatio >= 0); assert(newOffsetRatio < ONE); StaticShotSection = newSectionID; StaticShotOffsetRatio = newOffsetRatio; theta = rand() % ONE; x = (OffCentreStaticShotDisplacement * rcos(theta)) >> 12; y = (OffCentreStaticShotDisplacement * rcos(theta)) >> 12; assert( (abs(x)) < TunnelInnerRadius); assert( (abs(y)) < TunnelInnerRadius); setVECTOR( &tunnelPoint, x, y, ((newOffsetRatio * TunnelSectionLength) >> 12) ); ExpressSubPointInSuper( &tunnelPoint, &TheTunnel[newSectionID].coordinateData, &worldPoint); worldPoint.vx += TheTunnel[newSectionID].splinePoint.vx; worldPoint.vy += TheTunnel[newSectionID].splinePoint.vy; worldPoint.vz += TheTunnel[newSectionID].splinePoint.vz; TheView.super = WORLD; TheView.rz = 0; TheView.vpx = worldPoint.vx; TheView.vpy = worldPoint.vy; TheView.vpz = worldPoint.vz; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; FramesWithinOffCentreStaticShot = 1; #if 1 // calc section dist from view ship to viewpoiint // note: only the former moves { int distance, direction; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); FindShortestDistance (sectionID, StaticShotSection, &distance, &direction); StartDrawingSectionBaseShift = distance; } #endif } else { FramesWithinOffCentreStaticShot++; #if 1 // calc section dist from view ship to viewpoiint // note: only the former moves { int distance, direction; int sectionID; sectionID = TheViewShip->tunnelSection; assert(ValidID(sectionID)); FindShortestDistance (sectionID, StaticShotSection, &distance, &direction); StartDrawingSectionBaseShift = distance; } #endif } } void UpdateFirstHelicalViewer (void) { int cycleRatio, theta; ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; FramesWithinFirstHelicalViewer++; assert(FramesWithinFirstHelicalViewer <= FirstHelicalViewerPeriod); if (FramesWithinFirstHelicalViewer == FirstHelicalViewerPeriod) { FramesWithinFirstHelicalViewer = 0; FirstHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); FirstHelicalViewerInitialAngle = rand() % ONE; } assert(FirstHelicalViewerPeriod > 0); cycleRatio = (FramesWithinFirstHelicalViewer * ONE) / FirstHelicalViewerPeriod; assert(cycleRatio >= 0); assert(cycleRatio < ONE); TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; theta = FirstHelicalViewerInitialAngle; switch(FirstHelicalViewerTotalThetaZCirclingDirection) { case CLOCKWISE: theta += (FirstHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; case ANTICLOCKWISE: theta -= (FirstHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; default: assert(FALSE); } TheView.vpx = (FirstHelicalViewerDistanceOffSplinePath * rcos(theta)) >> 12; TheView.vpy = (FirstHelicalViewerDistanceOffSplinePath * rsin(theta)) >> 12; TheView.vpz = (FirstHelicalViewerCylinderLength/2) - ((FirstHelicalViewerCylinderLength * cycleRatio) >> 12); TheView.rz = 0; } void UpdateSecondHelicalViewer (void) { int cycleRatio, theta; FramesWithinSecondHelicalViewer++; assert(FramesWithinSecondHelicalViewer <= SecondHelicalViewerPeriod); if (FramesWithinSecondHelicalViewer == SecondHelicalViewerPeriod) { FramesWithinSecondHelicalViewer = 0; SecondHelicalViewerTotalThetaZCirclingDirection = CLOCKWISE + (rand() % 2); SecondHelicalViewerTwistDirection = CLOCKWISE + (rand() % 2); SecondHelicalViewerInitialAngle = rand() % ONE; TheView.rz = 0; } assert(SecondHelicalViewerPeriod > 0); cycleRatio = (FramesWithinSecondHelicalViewer * ONE) / SecondHelicalViewerPeriod; assert(cycleRatio >= 0); assert(cycleRatio < ONE); theta = SecondHelicalViewerInitialAngle; switch(SecondHelicalViewerTotalThetaZCirclingDirection) { case CLOCKWISE: theta += (SecondHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; case ANTICLOCKWISE: theta -= (SecondHelicalViewerTotalThetaZRevolutionAngle * cycleRatio) >> 12; break; default: assert(FALSE); } TheView.vpx = (SecondHelicalViewerDistanceOffSplinePath * rcos(theta)) >> 12; TheView.vpy = (SecondHelicalViewerDistanceOffSplinePath * rsin(theta)) >> 12; TheView.vpz = (SecondHelicalViewerCylinderLength/2) - ((SecondHelicalViewerCylinderLength * cycleRatio) >> 12); switch(SecondHelicalViewerTwistDirection) { case CLOCKWISE: TheView.rz += (180 * ONE) / SecondHelicalViewerPeriod; break; case ANTICLOCKWISE: TheView.rz -= (180 * ONE) / SecondHelicalViewerPeriod; break; default: assert(FALSE); } } void UpdateFirstCuboidCirclingViewer (void) { TheView.super = &TheViewShip->coord; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; if (FramesWithinFirstCuboidCirclingViewer == FirstCuboidViewerCirclingPeriod) { int newPlane, newAngle, newDirection; FramesWithinFirstCuboidCirclingViewer = 0; GetNewCirclingOnCubeData(FirstCuboidViewerPlane, FirstCuboidViewerAngle, FirstCuboidViewerCirclingDirection, &newPlane, &newAngle, &newDirection); FirstCuboidViewerPlane = newPlane; FirstCuboidViewerAngle = newAngle; FirstCuboidViewerCirclingDirection = newDirection; FirstCuboidViewerAngleFlag = FirstCuboidViewerAngle / 1024; } else { int cycleRatio, x, y; VECTOR xAxis, yAxis, circleCentre; FramesWithinFirstCuboidCirclingViewer++; assert(FirstCuboidViewerCirclingPeriod > 0); cycleRatio = (FramesWithinFirstCuboidCirclingViewer * ONE) / FirstCuboidViewerCirclingPeriod; switch(FirstCuboidViewerPlane) { case ABOVE: setVECTOR( &xAxis, ONE, 0, 0); setVECTOR( &yAxis, 0, 0, ONE); setVECTOR( &circleCentre, 0, -FirstCuboidViewerCubeSideLength/2, 0); break; case BELOW: setVECTOR( &xAxis, ONE, 0, 0); setVECTOR( &yAxis, 0, 0, -ONE); setVECTOR( &circleCentre, 0, FirstCuboidViewerCubeSideLength/2, 0); break; case FORWARD: setVECTOR( &xAxis, -ONE, 0, 0); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, 0, 0, FirstCuboidViewerCubeSideLength/2); break; case BACKWARD: setVECTOR( &xAxis, ONE, 0, 0); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, 0, 0, -FirstCuboidViewerCubeSideLength/2); break; case LEFT: setVECTOR( &xAxis, 0, 0, -ONE); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, -FirstCuboidViewerCubeSideLength/2, 0, 0); break; case RIGHT: setVECTOR( &xAxis, 0, 0, ONE); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, FirstCuboidViewerCubeSideLength/2, 0, 0); break; default: assert(FALSE); } FirstCuboidViewerAngle = FirstCuboidViewerAngleFlag * 1024; switch(FirstCuboidViewerCirclingDirection) { case CLOCKWISE: FirstCuboidViewerAngle += (1024 * cycleRatio) >> 12; break; case ANTICLOCKWISE: FirstCuboidViewerAngle -= (1024 * cycleRatio) >> 12; break; default: assert(FALSE); } if (FirstCuboidViewerAngle < 0) FirstCuboidViewerAngle += ONE; else if (FirstCuboidViewerAngle >= ONE) FirstCuboidViewerAngle -= ONE; x = ((FirstCuboidViewerCubeSideLength/2) * rsin(FirstCuboidViewerAngle)) >> 12; y = ((FirstCuboidViewerCubeSideLength/2) * rcos(FirstCuboidViewerAngle)) >> 12; TheView.vpx = circleCentre.vx + ((xAxis.vx * x) >> 12) + ((yAxis.vx * y) >> 12); TheView.vpy = circleCentre.vy + ((xAxis.vy * x) >> 12) + ((yAxis.vy * y) >> 12); TheView.vpz = circleCentre.vz + ((xAxis.vz * x) >> 12) + ((yAxis.vz * y) >> 12); } } void UpdateSecondCuboidCirclingViewer (void) { TheView.super = &TheViewShip->coord; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; if (FramesWithinSecondCuboidCirclingViewer == SecondCuboidViewerCirclingPeriod) { int newPlane, newAngle, newDirection; FramesWithinSecondCuboidCirclingViewer = 0; GetNewCirclingOnCubeData(SecondCuboidViewerPlane, SecondCuboidViewerAngle, SecondCuboidViewerCirclingDirection, &newPlane, &newAngle, &newDirection); SecondCuboidViewerPlane = newPlane; SecondCuboidViewerAngle = newAngle; SecondCuboidViewerCirclingDirection = newDirection; SecondCuboidViewerAngleFlag = SecondCuboidViewerAngle / 1024; if ((rand() % 4) == 0) { switch(SecondCuboidViewerTwistDirection) { case CLOCKWISE: SecondCuboidViewerTwistDirection = ANTICLOCKWISE; break; case ANTICLOCKWISE: SecondCuboidViewerTwistDirection = CLOCKWISE; break; default: assert(FALSE); } } } else { int cycleRatio, x, y; VECTOR xAxis, yAxis, circleCentre; FramesWithinSecondCuboidCirclingViewer++; assert(SecondCuboidViewerCirclingPeriod > 0); cycleRatio = (FramesWithinSecondCuboidCirclingViewer * ONE) / SecondCuboidViewerCirclingPeriod; switch(SecondCuboidViewerPlane) { case ABOVE: setVECTOR( &xAxis, ONE, 0, 0); setVECTOR( &yAxis, 0, 0, ONE); setVECTOR( &circleCentre, 0, -SecondCuboidViewerCubeSideLength/2, 0); break; case BELOW: setVECTOR( &xAxis, ONE, 0, 0); setVECTOR( &yAxis, 0, 0, -ONE); setVECTOR( &circleCentre, 0, SecondCuboidViewerCubeSideLength/2, 0); break; case FORWARD: setVECTOR( &xAxis, -ONE, 0, 0); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, 0, 0, SecondCuboidViewerCubeSideLength/2); break; case BACKWARD: setVECTOR( &xAxis, ONE, 0, 0); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, 0, 0, -SecondCuboidViewerCubeSideLength/2); break; case LEFT: setVECTOR( &xAxis, 0, 0, -ONE); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, -SecondCuboidViewerCubeSideLength/2, 0, 0); break; case RIGHT: setVECTOR( &xAxis, 0, 0, ONE); setVECTOR( &yAxis, 0, -ONE, 0); setVECTOR( &circleCentre, SecondCuboidViewerCubeSideLength/2, 0, 0); break; default: assert(FALSE); } SecondCuboidViewerAngle = SecondCuboidViewerAngleFlag * 1024; switch(SecondCuboidViewerCirclingDirection) { case CLOCKWISE: SecondCuboidViewerAngle += (1024 * cycleRatio) >> 12; break; case ANTICLOCKWISE: SecondCuboidViewerAngle -= (1024 * cycleRatio) >> 12; break; default: assert(FALSE); } if (SecondCuboidViewerAngle < 0) SecondCuboidViewerAngle += ONE; else if (SecondCuboidViewerAngle >= ONE) SecondCuboidViewerAngle -= ONE; x = ((SecondCuboidViewerCubeSideLength/2) * rsin(SecondCuboidViewerAngle)) >> 12; y = ((SecondCuboidViewerCubeSideLength/2) * rcos(SecondCuboidViewerAngle)) >> 12; TheView.vpx = circleCentre.vx + ((xAxis.vx * x) >> 12) + ((yAxis.vx * y) >> 12); TheView.vpy = circleCentre.vy + ((xAxis.vy * x) >> 12) + ((yAxis.vy * y) >> 12); TheView.vpz = circleCentre.vz + ((xAxis.vz * x) >> 12) + ((yAxis.vz * y) >> 12); switch(SecondCuboidViewerTwistDirection) { case CLOCKWISE: TheView.rz += (45 * ONE) / SecondCuboidViewerCirclingPeriod; break; case ANTICLOCKWISE: TheView.rz -= (45 * ONE) / SecondCuboidViewerCirclingPeriod; break; default: assert(FALSE); } } } void InitExternalView (int mode) { ViewTypeFlag = REFERENCE_VIEW; TheView.super = &TheViewShip->coord; assert(TheViewShip->modelFlag == TMD_RIGHT_WAY); TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = 0; TheView.rz = 0; switch(mode) { case VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT: TheView.vpz = FixedAheadDistance; break; case VIEW_FIXED_EXTERNAL_BEHIND_OBJECT: TheView.vpz = -FixedAheadDistance; break; case VIEW_FIXED_EXTERNAL_RIGHT_OF_OBJECT: TheView.vpx = FixedAheadDistance; break; case VIEW_FIXED_EXTERNAL_LEFT_OF_OBJECT: TheView.vpx = -FixedAheadDistance; break; case VIEW_FIXED_EXTERNAL_ABOVE_OBJECT: TheView.vpy = -FixedAheadDistance; break; case VIEW_FIXED_EXTERNAL_BELOW_OBJECT: TheView.vpy = FixedAheadDistance; break; default: assert(FALSE); } SetViewPositionKnowingCloseToViewShip(); } void InitCirclingView (int mode) { #if 0 // NEWEST // smoothest, but 3d engine needs sorting with View2 int choice, point, orientation, clockDirection; ViewTypeFlag = MATRIX_VIEW; clockDirection = CLOCKWISE + (rand() % 2); CirclingPlane = X_Y_PLANE + (rand() % 3); // get a cardinal point on circling plane switch(CirclingPlane) { case X_Z_PLANE: choice = rand() % 4; switch(choice) { case 0: point = FORWARD; break; case 1: point = LEFT; break; case 2: point = BACKWARD; break; case 3: point = RIGHT; break; default: assert(FALSE); } CirclingDirection = TILT_RIGHT; break; case X_Y_PLANE: choice = rand() % 4; switch(choice) { case 0: point = LEFT; break; case 1: point = ABOVE; break; case 2: point = RIGHT; break; case 3: point = BELOW; break; default: assert(FALSE); } CirclingDirection = TILT_RIGHT; break; case Y_Z_PLANE: choice = rand() % 4; switch(choice) { case 0: point = FORWARD; break; case 1: point = ABOVE; break; case 2: point = BACKWARD; break; case 3: point = BELOW; break; default: assert(FALSE); } CirclingDirection = TILT_UP; break; default: assert(FALSE); } orientation = rand() % 4; if (clockDirection == ANTICLOCKWISE) CirclingDirection = FlipRelativeXYMove(CirclingDirection); CirclingDirection = GetNewRelativeMove(CirclingDirection, orientation); GsInitCoordinate2(WORLD, &CameraCoord); SetMatrixByPointAndOrientation( &CameraCoord.coord, point, orientation); CameraCoord.super = &TheViewShip->coord; TheMatrixView.super = &CameraCoord; InitMatrix( &TheMatrixView.view); switch(mode) { case VIEW_CIRCLES_OBJECT_CLOSE_IN: TheMatrixView.view.t[2] = CloseInCirclingRadius; break; case VIEW_CIRCLES_OBJECT: TheMatrixView.view.t[2] = CirclingRadius; break; case VIEW_CIRCLES_OBJECT_TWISTING: TheMatrixView.view.t[2] = CirclingRadius; CirclingTwistingFlag = CLOCKWISE + (rand() % 2); break; case VIEW_CIRCLES_OBJECT_FAR_AWAY: TheMatrixView.view.t[2] = FarAwayCirclingRadius; break; case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: TheMatrixView.view.t[2] = FarAwayCirclingRadius; CirclingTwistingFlag = CLOCKWISE + (rand() % 2); break; default: assert(FALSE); } #endif #if 1 // NEWISH int choice, point, orientation, clockDirection; ViewTypeFlag = REFERENCE_VIEW; clockDirection = CLOCKWISE + (rand() % 2); CirclingPlane = X_Y_PLANE + (rand() % 3); // get a cardinal point on circling plane switch(CirclingPlane) { case X_Z_PLANE: choice = rand() % 4; switch(choice) { case 0: point = FORWARD; break; case 1: point = LEFT; break; case 2: point = BACKWARD; break; case 3: point = RIGHT; break; default: assert(FALSE); } CirclingDirection = TILT_RIGHT; break; case X_Y_PLANE: choice = rand() % 4; switch(choice) { case 0: point = LEFT; break; case 1: point = ABOVE; break; case 2: point = RIGHT; break; case 3: point = BELOW; break; default: assert(FALSE); } CirclingDirection = TILT_RIGHT; break; case Y_Z_PLANE: choice = rand() % 4; switch(choice) { case 0: point = FORWARD; break; case 1: point = ABOVE; break; case 2: point = BACKWARD; break; case 3: point = BELOW; break; default: assert(FALSE); } CirclingDirection = TILT_UP; break; default: assert(FALSE); } orientation = rand() % 4; if (clockDirection == ANTICLOCKWISE) CirclingDirection = FlipRelativeXYMove(CirclingDirection); CirclingDirection = GetNewRelativeMove(CirclingDirection, orientation); GsInitCoordinate2(WORLD, &CameraCoord); SetMatrixByPointAndOrientation( &CameraCoord.coord, point, orientation); CameraCoord.super = &TheViewShip->coord; TheView.super = &CameraCoord; TheView.rz = 0; TheView.vpx = 0; TheView.vpy = 0; switch(mode) { case VIEW_CIRCLES_OBJECT_CLOSE_IN: TheView.vpz = -CloseInCirclingRadius; break; case VIEW_CIRCLES_OBJECT: TheView.vpz = -CirclingRadius; break; case VIEW_CIRCLES_OBJECT_TWISTING: TheView.vpz = -CirclingRadius; CirclingTwistingFlag = CLOCKWISE + (rand() % 2); break; case VIEW_CIRCLES_OBJECT_FAR_AWAY: TheView.vpz = -FarAwayCirclingRadius; break; case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: TheView.vpz = -FarAwayCirclingRadius; CirclingTwistingFlag = CLOCKWISE + (rand() % 2); break; default: assert(FALSE); } TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; #endif #if 0 // OLD WAY ViewTypeFlag = REFERENCE_VIEW; CirclingPlane = X_Y_PLANE + (rand() % 3); switch(CirclingPlane) { case X_Y_PLANE: CirclingAngle = 1024; break; case X_Z_PLANE: case Y_Z_PLANE: CirclingAngle = 0; break; default: assert(FALSE); } CirclingDirection = CLOCKWISE + (rand() % 2); TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; switch(mode) { case VIEW_CIRCLES_OBJECT_CLOSE_IN: case VIEW_CIRCLES_OBJECT: case VIEW_CIRCLES_OBJECT_FAR_AWAY: // do nowt break; case VIEW_CIRCLES_OBJECT_TWISTING: case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: CirclingTwistingFlag = CLOCKWISE + (rand() % 2); break; default: assert(FALSE); } TheView.super = &TheViewShip->coord; TheView.rz = 0; #endif SetViewPositionKnowingCloseToViewShip(); } void HandleCirclingView (int mode) { #if 0 // NEWEST // smoothest, but 3d engine needs sorting with View2 int smallAngle; SVECTOR twistVector; MATRIX twistMatrix; smallAngle = CirclingAngularSpeed; ViewTypeFlag = MATRIX_VIEW; switch(CirclingDirection) { 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); } switch(mode) { case VIEW_CIRCLES_OBJECT_CLOSE_IN: case VIEW_CIRCLES_OBJECT: case VIEW_CIRCLES_OBJECT_FAR_AWAY: // do nowt break; case VIEW_CIRCLES_OBJECT_TWISTING: case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: assert(MaximumGameFramesPerSecond > 0); smallAngle = 1024 / MaximumGameFramesPerSecond; switch(CirclingTwistingFlag) { case CLOCKWISE: setVECTOR( &twistVector, 0, 0, smallAngle); break; case ANTICLOCKWISE: setVECTOR( &twistVector, 0, 0, -smallAngle); break; default: assert(FALSE); } RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); break; default: assert(FALSE); } #endif #if 1 // NEW WAY int smallAngle; SVECTOR twistVector; MATRIX twistMatrix; smallAngle = CirclingAngularSpeed; switch(CirclingDirection) { 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); } switch(mode) { case VIEW_CIRCLES_OBJECT_CLOSE_IN: case VIEW_CIRCLES_OBJECT: case VIEW_CIRCLES_OBJECT_FAR_AWAY: // do nowt break; case VIEW_CIRCLES_OBJECT_TWISTING: case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: assert(MaximumGameFramesPerSecond > 0); switch(CirclingTwistingFlag) { case CLOCKWISE: TheView.rz += ((90 * ONE) / MaximumGameFramesPerSecond); break; case ANTICLOCKWISE: TheView.rz -= ((90 * ONE) / MaximumGameFramesPerSecond); break; default: assert(FALSE); } break; default: assert(FALSE); } #endif #if 0 // OLD WAY int x, y, z, radius; switch(mode) { case VIEW_CIRCLES_OBJECT_CLOSE_IN: radius = CloseInCirclingRadius; break; case VIEW_CIRCLES_OBJECT: case VIEW_CIRCLES_OBJECT_TWISTING: radius = CirclingRadius; break; case VIEW_CIRCLES_OBJECT_FAR_AWAY: case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: radius = FarAwayCirclingRadius; break; default: assert(FALSE); } switch(CirclingPlane) { case X_Y_PLANE: x = (radius * rcos(CirclingAngle)) >> 12; y = (radius * rsin(CirclingAngle)) >> 12; z = 0; break; case X_Z_PLANE: x = (radius * rsin(CirclingAngle)) >> 12; y = 0; z = (radius * rcos(CirclingAngle)) >> 12; break; case Y_Z_PLANE: x = 0; y = (radius * rcos(CirclingAngle)) >> 12; z = (radius * rsin(CirclingAngle)) >> 12; break; default: assert(FALSE); } TheView.vpx = x; TheView.vpy = y; TheView.vpz = z; switch(CirclingDirection) { case CLOCKWISE: CirclingAngle += CirclingAngularSpeed; break; case ANTICLOCKWISE: CirclingAngle -= CirclingAngularSpeed; break; default: assert(FALSE); } switch(mode) { case VIEW_CIRCLES_OBJECT_CLOSE_IN: case VIEW_CIRCLES_OBJECT: case VIEW_CIRCLES_OBJECT_FAR_AWAY: // do nowt break; case VIEW_CIRCLES_OBJECT_TWISTING: case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: assert(MaximumGameFramesPerSecond > 0); switch(CirclingTwistingFlag) { case CLOCKWISE: TheView.rz += ((90 * ONE) / MaximumGameFramesPerSecond); break; case ANTICLOCKWISE: TheView.rz -= ((90 * ONE) / MaximumGameFramesPerSecond); break; default: assert(FALSE); } break; default: assert(FALSE); } #endif } void InitOvalOrbitView (int mode) { #if 0 // OLD WAY ViewTypeFlag = REFERENCE_VIEW; OvalTheta = 0; OvalOrbitDirection = CLOCKWISE + (rand() % 2); OvalAngularSpeed = OVAL_ORBIT_LOW_ANGULAR_SPEED; TheView.super = &TheViewShip->coord; TheView.rz = 0; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; switch(mode) { case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: // do nowt; break; case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: OvalOrbitTwistDirection = CLOCKWISE + (rand() % 2); break; default: assert(FALSE); } #endif #if 0 // NEW ViewTypeFlag = MATRIX_VIEW; OvalTheta = 0; OvalOrbitDirection = CLOCKWISE + (rand() % 2); OvalAngularSpeed = OVAL_ORBIT_LOW_ANGULAR_SPEED; GsInitCoordinate2(WORLD, &CameraCoord); SetMatrixByPointAndOrientation( &CameraCoord.coord, FORWARD, 0); CameraCoord.super = &TheViewShip->coord; TheMatrixView.super = &CameraCoord; InitMatrix( &TheMatrixView.view); TheMatrixView.view.t[2] = OvalOrbitBasicRadius; #endif #if 1 // NEWISH ViewTypeFlag = REFERENCE_VIEW; OvalTheta = 0; OvalOrbitDirection = CLOCKWISE + (rand() % 2); OvalAngularSpeed = OVAL_ORBIT_LOW_ANGULAR_SPEED; GsInitCoordinate2(WORLD, &CameraCoord); SetMatrixByPointAndOrientation( &CameraCoord.coord, FORWARD, 0); CameraCoord.super = &TheViewShip->coord; TheView.super = &CameraCoord; TheView.rz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -OvalOrbitBasicRadius; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; #endif SetViewPositionKnowingCloseToViewShip(); } void HandleOvalOrbitView (int mode) { #if 0 // OLD WAY int smallAngle; switch(OvalOrbitDirection) { case CLOCKWISE: OvalTheta += OvalAngularSpeed; break; case ANTICLOCKWISE: OvalTheta -= OvalAngularSpeed; break; default: assert(FALSE); } while (OvalTheta < 0) OvalTheta += ONE; while (OvalTheta >= ONE) OvalTheta -= ONE; // set angular speed wrt theta if (OvalTheta >= 0 && OvalTheta < 1024) { smallAngle = OvalTheta; } else if (OvalTheta >= 1024 && OvalTheta < 2048) { smallAngle = 2048 - OvalTheta; } else if (OvalTheta >= 2048 && OvalTheta < 3072) { smallAngle = OvalTheta - 2048; } else if (OvalTheta >= 3072 && OvalTheta < ONE) { smallAngle = ONE - OvalTheta; } else { assert(FALSE); } assert(smallAngle >= 0 && smallAngle < 1024); OvalAngularSpeed = OVAL_ORBIT_LOW_ANGULAR_SPEED + (((OVAL_ORBIT_HIGH_ANGULAR_SPEED - OVAL_ORBIT_LOW_ANGULAR_SPEED) * smallAngle) / 1024); assert(OvalAngularSpeed >= OVAL_ORBIT_LOW_ANGULAR_SPEED); assert(OvalAngularSpeed <= OVAL_ORBIT_HIGH_ANGULAR_SPEED); switch(mode) { case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: // oval orbit in xz plane //achieved by just doubling circle coords in one axis TheView.vpx = (OvalOrbitBasicRadius * rsin(OvalTheta)) >> 12; TheView.vpy = 0; TheView.vpz = (OvalOrbitStretchRatio * OvalOrbitBasicRadius * rcos(OvalTheta)) >> 12; break; case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: // oval orbit in xz plane //achieved by just doubling circle coords in one axis TheView.vpx = 0; TheView.vpy = (OvalOrbitBasicRadius * rsin(OvalTheta)) >> 12; TheView.vpz = (OvalOrbitStretchRatio * OvalOrbitBasicRadius * rcos(OvalTheta)) >> 12; break; default: assert(FALSE); } switch(mode) { case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: // do nowt; break; case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: switch(OvalOrbitTwistDirection) { case CLOCKWISE: TheView.rz += 90 * OvalAngularSpeed; break; case ANTICLOCKWISE: TheView.rz -= 90 * OvalAngularSpeed; break; default: assert(FALSE); } break; default: assert(FALSE); } #endif #if 0 // NEW int smallAngle; int twistThisFrame; SVECTOR twistVector; MATRIX twistMatrix; int distanceOut; twistThisFrame = OvalAngularSpeed; switch(OvalOrbitDirection) { case CLOCKWISE: OvalTheta += OvalAngularSpeed; break; case ANTICLOCKWISE: OvalTheta -= OvalAngularSpeed; break; default: assert(FALSE); } while (OvalTheta < 0) OvalTheta += ONE; while (OvalTheta >= ONE) OvalTheta -= ONE; // set angular speed wrt theta if (OvalTheta >= 0 && OvalTheta < 1024) { smallAngle = OvalTheta; } else if (OvalTheta >= 1024 && OvalTheta < 2048) { smallAngle = 2048 - OvalTheta; } else if (OvalTheta >= 2048 && OvalTheta < 3072) { smallAngle = OvalTheta - 2048; } else if (OvalTheta >= 3072 && OvalTheta < ONE) { smallAngle = ONE - OvalTheta; } else { assert(FALSE); } assert(smallAngle >= 0 && smallAngle < 1024); OvalAngularSpeed = OVAL_ORBIT_LOW_ANGULAR_SPEED + (((OVAL_ORBIT_HIGH_ANGULAR_SPEED - OVAL_ORBIT_LOW_ANGULAR_SPEED) * smallAngle) / 1024); assert(OvalAngularSpeed >= OVAL_ORBIT_LOW_ANGULAR_SPEED); assert(OvalAngularSpeed <= OVAL_ORBIT_HIGH_ANGULAR_SPEED); distanceOut = OvalOrbitBasicRadius + (((OvalOrbitBasicRadius * (OvalOrbitStretchRatio-1)) * (1024 - smallAngle)) / 1024); TheMatrixView.view.t[2] = distanceOut; switch(mode) { case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: switch(OvalOrbitDirection) { case CLOCKWISE: setVECTOR( &twistVector, 0, -twistThisFrame, 0); break; case ANTICLOCKWISE: setVECTOR( &twistVector, 0, twistThisFrame, 0); break; default: assert(FALSE); } break; case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: switch(OvalOrbitDirection) { case CLOCKWISE: setVECTOR( &twistVector, -twistThisFrame, 0, 0); break; case ANTICLOCKWISE: setVECTOR( &twistVector, twistThisFrame, 0, 0); break; default: assert(FALSE); } break; default: assert(FALSE); } RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); switch(mode) { case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: // do nowt; break; case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: switch(OvalOrbitTwistDirection) { case CLOCKWISE: setVECTOR( &twistVector, 0, 0, OvalAngularSpeed); break; case ANTICLOCKWISE: setVECTOR( &twistVector, 0, 0, -OvalAngularSpeed); break; default: assert(FALSE); } RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &TheMatrixView.view, &twistMatrix, &TheMatrixView.view); break; default: assert(FALSE); } #endif #if 1 // NEWISH int smallAngle; int twistThisFrame; SVECTOR twistVector; MATRIX twistMatrix; int distanceOut; twistThisFrame = OvalAngularSpeed; switch(OvalOrbitDirection) { case CLOCKWISE: OvalTheta += OvalAngularSpeed; break; case ANTICLOCKWISE: OvalTheta -= OvalAngularSpeed; break; default: assert(FALSE); } while (OvalTheta < 0) OvalTheta += ONE; while (OvalTheta >= ONE) OvalTheta -= ONE; // set angular speed wrt theta if (OvalTheta >= 0 && OvalTheta < 1024) { smallAngle = OvalTheta; } else if (OvalTheta >= 1024 && OvalTheta < 2048) { smallAngle = 2048 - OvalTheta; } else if (OvalTheta >= 2048 && OvalTheta < 3072) { smallAngle = OvalTheta - 2048; } else if (OvalTheta >= 3072 && OvalTheta < ONE) { smallAngle = ONE - OvalTheta; } else { assert(FALSE); } assert(smallAngle >= 0 && smallAngle < 1024); OvalAngularSpeed = OVAL_ORBIT_LOW_ANGULAR_SPEED + (((OVAL_ORBIT_HIGH_ANGULAR_SPEED - OVAL_ORBIT_LOW_ANGULAR_SPEED) * smallAngle) / 1024); assert(OvalAngularSpeed >= OVAL_ORBIT_LOW_ANGULAR_SPEED); assert(OvalAngularSpeed <= OVAL_ORBIT_HIGH_ANGULAR_SPEED); distanceOut = OvalOrbitBasicRadius + (((OvalOrbitBasicRadius * (OvalOrbitStretchRatio-1)) * (1024 - smallAngle)) / 1024); TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -distanceOut; switch(mode) { case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: switch(OvalOrbitDirection) { case CLOCKWISE: setVECTOR( &twistVector, 0, -twistThisFrame, 0); break; case ANTICLOCKWISE: setVECTOR( &twistVector, 0, twistThisFrame, 0); break; default: assert(FALSE); } break; case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: switch(OvalOrbitDirection) { case CLOCKWISE: setVECTOR( &twistVector, -twistThisFrame, 0, 0); break; case ANTICLOCKWISE: setVECTOR( &twistVector, twistThisFrame, 0, 0); break; default: assert(FALSE); } break; default: assert(FALSE); } RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); switch(mode) { case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: // do nowt; break; case VIEW_OBJECT_IN_THIRD_OVAL_ORBIT: case VIEW_OBJECT_IN_FOURTH_OVAL_ORBIT: switch(OvalOrbitTwistDirection) { case CLOCKWISE: TheView.rz += 90 * OvalAngularSpeed; break; case ANTICLOCKWISE: TheView.rz -= 90 * OvalAngularSpeed; break; default: assert(FALSE); } break; default: assert(FALSE); } #endif } void PrintViewMode (void) { assert(TheViewShip != NULL); printf("\n\n"); if (TheViewShip->viewMode == VIEW_BY_FIRST_DIRECTORS_CUT) { printf("First Director's Cut\n"); PrintViewInWords(FirstDirectorSubMode); } else if (TheViewShip->viewMode == VIEW_BY_SECOND_DIRECTORS_CUT) { printf("Second Directors' Cut\n"); PrintViewInWords(SecondDirectorSubMode); } else if (TheViewShip->viewMode == VIEW_BY_THIRD_DIRECTORS_CUT) { printf("Third Directors' Cut\n"); PrintViewInWords(ThirdDirectorSubMode); } else if (TheViewShip->viewMode == VIEW_BY_FOURTH_DIRECTORS_CUT) { printf("Fourth Directors' Cut\n"); PrintViewInWords(FourthDirectorSubMode); } else { PrintViewInWords(TheViewShip->viewMode); } printf("\n\n"); } void PrintViewInWords (int viewMode) { switch(viewMode) { case VIEW_FIXED_BEHIND_ABOVE_OBJECT: printf("VIEW_FIXED_BEHIND_ABOVE_OBJECT\n"); break; case VIEW_FIXED_BEHIND_BELOW_OBJECT: printf("VIEW_FIXED_BEHIND_BELOW_OBJECT\n"); break; case VIEW_LOCAL_TO_OBJECT: printf("VIEW_LOCAL_TO_OBJECT\n"); break; case VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT: printf("VIEW_FIXED_EXTERNAL_AHEAD_OF_OBJECT\n"); break; case VIEW_OBJECT_IN_STATIC_FLYBY: printf("VIEW_OBJECT_IN_STATIC_FLYBY\n"); break; case VIEW_OBJECT_IN_CARDINAL_FLYBY: printf("VIEW_OBJECT_IN_CARDINAL_FLYBY\n"); break; case VIEW_CIRCLES_OBJECT_CLOSE_IN: printf("VIEW_CIRCLES_OBJECT_CLOSE_IN\n"); break; case VIEW_CIRCLES_OBJECT: printf("VIEW_CIRCLES_OBJECT\n"); break; case VIEW_CIRCLES_OBJECT_TWISTING: printf("VIEW_CIRCLES_OBJECT_TWISTING\n"); break; case VIEW_CIRCLES_OBJECT_FAR_AWAY: printf("VIEW_CIRCLES_OBJECT_FAR_AWAY\n"); break; case VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING: printf("VIEW_CIRCLES_OBJECT_FAR_AWAY_TWISTING\n"); break; case VIEW_CIRCLES_OBJECT_CHANGING_ORBITAL_PLANE: printf("VIEW_CIRCLES_OBJECT_CHANGING_ORBITAL_PLANE\n"); break; case VIEW_OBJECT_IN_FIRST_OVAL_ORBIT: printf("VIEW_OBJECT_IN_FIRST_OVAL_ORBIT\n"); break; case VIEW_OBJECT_IN_SECOND_OVAL_ORBIT: printf("VIEW_OBJECT_IN_SECOND_OVAL_ORBIT\n"); break; case VIEW_OBJECT_IN_FIRST_MOVING_FLYBY: printf("VIEW_OBJECT_IN_FIRST_MOVING_FLYBY\n"); break; case VIEW_OBJECT_IN_FOURTH_MOVING_FLYBY: printf("VIEW_OBJECT_IN_FOURTH_MOVING_FLYBY\n"); break; case VIEW_OBJECT_IN_SECOND_MOVING_FLYBY: printf("VIEW_OBJECT_IN_SECOND_MOVING_FLYBY\n"); break; case VIEW_OBJECT_IN_THIRD_MOVING_FLYBY: printf("VIEW_OBJECT_IN_THIRD_MOVING_FLYBY\n"); break; case VIEW_CIRCLES_BEHIND_OBJECT: printf("VIEW_CIRCLES_BEHIND_OBJECT\n"); break; case VIEW_SWIVELS_BEHIND_OBJECT: printf("VIEW_SWIVELS_BEHIND_OBJECT\n"); break; case VIEW_BY_FIRST_DIRECTORS_CUT: printf("VIEW_BY_FIRST_DIRECTORS_CUT\n"); break; case VIEW_BY_SECOND_DIRECTORS_CUT: printf("VIEW_BY_SECOND_DIRECTORS_CUT\n"); break; case VIEW_BY_THIRD_DIRECTORS_CUT: printf("VIEW_BY_THIRD_DIRECTORS_CUT\n"); break; case VIEW_BY_FOURTH_DIRECTORS_CUT: printf("VIEW_BY_FOURTH_DIRECTORS_CUT\n"); break; case VIEW_FIXED_EXTERNAL_BEHIND_OBJECT: printf("VIEW_FIXED_EXTERNAL_BEHIND_OBJECT\n"); break; case VIEW_FIXED_EXTERNAL_LEFT_OF_OBJECT: printf("VIEW_FIXED_EXTERNAL_LEFT_OF_OBJECT\n"); break; case VIEW_FIXED_EXTERNAL_RIGHT_OF_OBJECT: printf("VIEW_FIXED_EXTERNAL_RIGHT_OF_OBJECT\n"); break; case VIEW_FIXED_EXTERNAL_ABOVE_OBJECT: printf("VIEW_FIXED_EXTERNAL_ABOVE_OBJECT\n"); break; case VIEW_FIXED_EXTERNAL_BELOW_OBJECT: printf("VIEW_FIXED_EXTERNAL_BELOW_OBJECT\n"); break; case VIEW_FROM_SPLINE_PATH_BEHIND_OBJECT: printf("VIEW_FROM_SPLINE_PATH_BEHIND_OBJECT\n"); break; case VIEW_FROM_SPLINE_DISTANCE_BEHIND_OBJECT: printf("VIEW_FROM_SPLINE_DISTANCE_BEHIND_OBJECT\n"); break; case VIEW_LOCAL_LOOKING_BACKWARDS: printf("VIEW_LOCAL_LOOKING_BACKWARDS\n"); break; case VIEW_BY_FIRST_CUBOID_VIEWER: printf("VIEW_BY_FIRST_CUBOID_VIEWER\n"); break; case VIEW_BY_SECOND_CUBOID_VIEWER: printf("VIEW_BY_SECOND_CUBOID_VIEWER\n"); break; case VIEW_BY_THIRD_CUBOID_VIEWER: printf("VIEW_BY_THIRD_CUBOID_VIEWER\n"); break; case VIEW_BY_FIRST_SPHERICAL_VIEWER: printf("VIEW_BY_FIRST_SPHERICAL_VIEWER\n"); break; case VIEW_BY_SECOND_SPHERICAL_VIEWER: printf("VIEW_BY_SECOND_SPHERICAL_VIEWER\n"); break; case VIEW_BY_THIRD_SPHERICAL_VIEWER: printf("VIEW_BY_THIRD_SPHERICAL_VIEWER\n"); break; case VIEW_BY_FOURTH_SPHERICAL_VIEWER: printf("VIEW_BY_FOURTH_SPHERICAL_VIEWER\n"); break; case VIEW_BY_HEAD_ON_FLYBY: printf("VIEW_BY_HEAD_ON_FLYBY\n"); break; case VIEW_BY_HEAD_ON_STATIC_SHOT: printf("VIEW_BY_HEAD_ON_STATIC_SHOT\n"); break; case VIEW_BY_OFF_CENTRE_STATIC_SHOT: printf("VIEW_BY_OFF_CENTRE_STATIC_SHOT\n"); break; case VIEW_BY_FIRST_HELICAL_VIEWER: printf("VIEW_BY_FIRST_HELICAL_VIEWER\n"); break; case VIEW_BY_SECOND_HELICAL_VIEWER: printf("VIEW_BY_SECOND_HELICAL_VIEWER\n"); break; case VIEW_BY_THIRD_HELICAL_VIEWER: printf("VIEW_BY_THIRD_HELICAL_VIEWER\n"); break; case VIEW_BY_FOURTH_HELICAL_VIEWER: printf("VIEW_BY_FOURTH_HELICAL_VIEWER\n"); break; case VIEW_BY_FIRST_CUBOID_CIRCLING_VIEWER: printf("VIEW_BY_FIRST_CUBOID_CIRCLING_VIEWER\n"); break; case VIEW_BY_SECOND_CUBOID_CIRCLING_VIEWER: printf("VIEW_BY_SECOND_CUBOID_CIRCLING_VIEWER\n"); break; case VIEW_BY_FIRST_SPIRAL_VIEWER: printf("VIEW_BY_FIRST_SPIRAL_VIEWER\n"); break; case VIEW_BY_FIRST_LAZY_ROTATION_VIEW: printf("VIEW_BY_FIRST_LAZY_ROTATION_VIEW\n"); break; case VIEW_BY_SECOND_LAZY_ROTATION_VIEW: printf("VIEW_BY_SECOND_LAZY_ROTATION_VIEW\n"); break; case VIEW_BY_THIRD_LAZY_ROTATION_VIEW: printf("VIEW_BY_THIRD_LAZY_ROTATION_VIEW\n"); break; default: printf("Bad value %d\n", viewMode); assert(FALSE); } } int ViewModeUsesSectionOffset (int viewMode) { int flag; if (viewMode == VIEW_BY_FIRST_DIRECTORS_CUT) { flag = SubViewModeUsesSectionOffset(FirstDirectorSubMode); } else if (viewMode == VIEW_BY_SECOND_DIRECTORS_CUT) { flag = SubViewModeUsesSectionOffset(SecondDirectorSubMode); } else if (viewMode == VIEW_BY_THIRD_DIRECTORS_CUT) { flag = SubViewModeUsesSectionOffset(ThirdDirectorSubMode); } else if (viewMode == VIEW_BY_FOURTH_DIRECTORS_CUT) { flag = SubViewModeUsesSectionOffset(FourthDirectorSubMode); } else { flag = SubViewModeUsesSectionOffset(viewMode); } return flag; } // in some view modes, camera is far from view ship // need to set a section offset for tunnel drawing int SubViewModeUsesSectionOffset (int viewMode) { int boolean; switch(viewMode) { case VIEW_OBJECT_IN_STATIC_FLYBY: case VIEW_BY_HEAD_ON_FLYBY: case VIEW_OBJECT_IN_THIRD_MOVING_FLYBY: case VIEW_BY_HEAD_ON_STATIC_SHOT: case VIEW_BY_OFF_CENTRE_STATIC_SHOT: boolean = TRUE; break; default: boolean = FALSE; } return boolean; } int ViewModeIsShipViewMode (int viewMode) { int boolean; assert(viewMode >= BASE_VIEW_MODE); assert(viewMode < BASE_VIEW_MODE + NUMBER_OF_SHIP_VIEW_MODES); if (viewMode >= BASE_PLAYER_VIEW_MODE && viewMode < BASE_PLAYER_VIEW_MODE + NUMBER_OF_PLAYER_VIEW_MODES) boolean = TRUE; else boolean = FALSE; return boolean; } void CopyReferenceView (GsRVIEW2 *from, GsRVIEW2 *to) { assert(from != NULL); assert(to != NULL); assert(from != to); to->super = from->super; to->rz = from->rz; to->vrx = from->vrx; to->vry = from->vry; to->vrz = from->vrz; to->vpx = from->vpx; to->vpy = from->vpy; to->vpz = from->vpz; } void CopyMatrixView (GsVIEW2 *from, GsVIEW2 *to) { assert(from != NULL); assert(to != NULL); assert(from != to); to->super = from->super; CopyMatrix( &from->view, &to->view); } void InitIntroView (void) { //IntroTypeFlag = FIRST; IntroTypeFlag = FIRST + (rand() % NUMBER_INTRO_VIEW_TYPES); //printf("IntroTypeFlag %d\n", IntroTypeFlag); IntroViewBehindDistance = (FixedBehindDistance * rcos(FixedBehindAboveAngle)) >> 12; IntroViewAboveDistance = (FixedBehindDistance * rsin(FixedBehindAboveAngle)) >> 12; switch(IntroTypeFlag) { case FIRST: { SVECTOR twistVector; MATRIX twistMatrix; IntroViewPhase = -1; IntroViewStartPoint = ABOVE + (rand() % 4); assert(TunnelMiddleRadius > 0); IntroViewDistanceFromSplinePath = TunnelMiddleRadius / 2; assert(TunnelSectionLength > 0); assert(NumberOfShipsInRace >= 1); IntroViewInitialZValue = (TunnelSectionLength * NumberOfShipsInRace) + (TunnelSectionLength/2); IntroViewTotalZDistance = (TunnelSectionLength * NumberOfShipsInRace); IntroViewFinalZValue = (TunnelSectionLength/2); ViewTypeFlag = REFERENCE_VIEW; GsInitCoordinate2(WORLD, &CameraCoord); setVECTOR( &twistVector, 0, ONE/2, 0); RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); switch(IntroViewStartPoint) { case ABOVE: CameraCoord.coord.t[1] -= IntroViewDistanceFromSplinePath; break; case BELOW: CameraCoord.coord.t[1] += IntroViewDistanceFromSplinePath; break; case LEFT: CameraCoord.coord.t[0] -= IntroViewDistanceFromSplinePath; break; case RIGHT: CameraCoord.coord.t[0] += IntroViewDistanceFromSplinePath; break; default: assert(FALSE); } CameraCoord.coord.t[2] = IntroViewInitialZValue; CameraCoord.flg = 0; TheView.super = &CameraCoord; TheView.rz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = -FixedBehindDistance; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; } break; case SECOND: { IntroViewTwistDirection = CLOCKWISE + (rand() % 2); IntroViewTwistAngle = 0; IntroViewPhase = -1; assert(TunnelMiddleRadius > 0); IntroViewDistanceFromSplinePath = TunnelMiddleRadius / 2; // now they are offsets IntroViewInitialZValue = (TunnelSectionLength * NumberOfShipsInRace); IntroViewFinalZValue = -IntroViewBehindDistance; ViewTypeFlag = REFERENCE_VIEW; TheView.super = WORLD; TheView.rz = 0; TheView.vpx = 0; TheView.vpy = 0; TheView.vpz = IntroViewInitialZValue; TheView.vrx = 0; TheView.vry = 0; TheView.vrz = 0; } break; default: assert(FALSE); } SetViewInSystem(); } void HandleIntroView (int framesSinceStart) { if (framesSinceStart == 0) { InitIntroView(); } switch(IntroTypeFlag) { case FIRST: HandleFirstIntroView(framesSinceStart); break; case SECOND: HandleSecondIntroView(framesSinceStart); break; default: assert(FALSE); } SetViewInSystem(); } void HandleFirstIntroView (int framesSinceStart) { int cycleRatio; SVECTOR twistVector; VECTOR circleCentre; MATRIX twistMatrix; int ratio, fraction, zPosition; int loopDuration, theta; int dx, dy, dz; assert(MaximumGameFramesPerSecond > 0); assert(IntroViewDurationInSeconds > 0); assert(framesSinceStart >= 0); assert(framesSinceStart <= (MaximumGameFramesPerSecond*IntroViewDurationInSeconds)); cycleRatio = (framesSinceStart * ONE) / (MaximumGameFramesPerSecond * IntroViewDurationInSeconds); //loopDuration // = (MaximumGameFramesPerSecond*IntroViewDurationInSeconds) / 4; loopDuration = (MaximumGameFramesPerSecond*IntroViewDurationInSeconds*3) / 8; assert(loopDuration > 0); if (cycleRatio < 1536) IntroViewPhase = INTRO_VIEW_MOVING_Z; else if (cycleRatio < 3072) IntroViewPhase = INTRO_VIEW_LOOPING_THE_LOOP; else IntroViewPhase = INTRO_VIEW_NUDGING_UP; switch(IntroViewPhase) { case INTRO_VIEW_MOVING_Z: ratio = (cycleRatio * 8) / 3; fraction = (ratio * ratio) >> 12; zPosition = IntroViewInitialZValue - ((IntroViewTotalZDistance * fraction) >> 12); CameraCoord.coord.t[2] = zPosition; CameraCoord.flg = 0; break; case INTRO_VIEW_LOOPING_THE_LOOP: theta = ((cycleRatio-1536) * 4) / 3; switch(IntroViewStartPoint) { case ABOVE: setVECTOR( &twistVector, 2048/loopDuration, 0, 0); setVECTOR( &circleCentre, 0, -IntroViewDistanceFromSplinePath/2, IntroViewFinalZValue); dx = 0; dy = ((-IntroViewDistanceFromSplinePath/2) * rcos(theta)) >> 12; TheView.rz += (180 * ONE) / loopDuration; break; case BELOW: setVECTOR( &twistVector, -2048/loopDuration, 0, 0); setVECTOR( &circleCentre, 0, IntroViewDistanceFromSplinePath/2, IntroViewFinalZValue); dx = 0; dy = ((IntroViewDistanceFromSplinePath/2) * rcos(theta)) >> 12; TheView.rz -= (180 * ONE) / loopDuration; break; case LEFT: setVECTOR( &twistVector, 0, -2048/loopDuration, 0); setVECTOR( &circleCentre, -IntroViewDistanceFromSplinePath/2, 0, IntroViewFinalZValue); dx = ((-IntroViewDistanceFromSplinePath/2) * rcos(theta)) >> 12; dy = 0; break; case RIGHT: setVECTOR( &twistVector, 0, 2048/loopDuration, 0); setVECTOR( &circleCentre, IntroViewDistanceFromSplinePath/2, 0, IntroViewFinalZValue); dx = ((IntroViewDistanceFromSplinePath/2) * rcos(theta)) >> 12; dy = 0; break; default: assert(FALSE); } dz = ((-IntroViewDistanceFromSplinePath/2) * rsin(theta)) >> 12; RotMatrix( &twistVector, &twistMatrix); MulMatrix0( &CameraCoord.coord, &twistMatrix, &CameraCoord.coord); CameraCoord.coord.t[0] = circleCentre.vx + dx; CameraCoord.coord.t[1] = circleCentre.vy + dy; CameraCoord.coord.t[2] = circleCentre.vz + dz; CameraCoord.flg = 0; break; case INTRO_VIEW_NUDGING_UP: { VECTOR trans, temp, shipZaxis, shipYaxis; MATRIX baseShipMatrix, tempMatrix; int y, z; fraction = (cycleRatio - 3072) * 4; assert(TheViewShip != NULL); GetShipMatrixWithoutTilt (TheViewShip, &baseShipMatrix); setVECTOR( &shipZaxis, baseShipMatrix.m[0][2], baseShipMatrix.m[1][2], baseShipMatrix.m[2][2]); setVECTOR( &shipYaxis, baseShipMatrix.m[0][1], baseShipMatrix.m[1][1], baseShipMatrix.m[2][1]); y = (IntroViewAboveDistance * fraction) >> 12; z = IntroViewBehindDistance; ViewTypeFlag = MATRIX_VIEW; TheMatrixView.super = WORLD; CopyMatrix( &baseShipMatrix, &TheMatrixView.view); GetMatrixFlippedOnDiagonal( &TheMatrixView.view, &tempMatrix); TheMatrixView.view = tempMatrix; // know the position wrt view ship in world coord terms // must re-express in terms of view matrix trans.vx = -(TheViewShip->position.vx + ((-y * shipYaxis.vx)>>12) + ((-z * shipZaxis.vx)>>12)); trans.vy = -(TheViewShip->position.vy + ((-y * shipYaxis.vy)>>12) + ((-z * shipZaxis.vy)>>12)); trans.vz = -(TheViewShip->position.vz + ((-y * shipYaxis.vz)>>12) + ((-z * shipZaxis.vz)>>12)); ExpressSuperPointInSubMatrix( &trans, &TheMatrixView.view, &temp); TheMatrixView.view.t[0] = temp.vx; TheMatrixView.view.t[1] = temp.vy; TheMatrixView.view.t[2] = temp.vz; } break; default: assert(FALSE); } } void HandleSecondIntroView (int framesSinceStart) { int cycleRatio, fraction; int x, y, z; assert(MaximumGameFramesPerSecond > 0); assert(IntroViewDurationInSeconds > 0); assert(framesSinceStart >= 0); assert(framesSinceStart <= (MaximumGameFramesPerSecond*IntroViewDurationInSeconds)); cycleRatio = (framesSinceStart * ONE) / (MaximumGameFramesPerSecond * IntroViewDurationInSeconds); assert(cycleRatio >= 0); assert(cycleRatio < ONE); if (cycleRatio < 3072) IntroViewPhase = INTRO_VIEW_LOOPING_THE_LOOP; else IntroViewPhase = INTRO_VIEW_NUDGING_DOWN; switch(IntroViewPhase) { case INTRO_VIEW_LOOPING_THE_LOOP: fraction = (cycleRatio * 4) / 3; assert(fraction >= 0); assert(fraction < ONE); z = ((IntroViewInitialZValue * (ONE-fraction)) + (IntroViewFinalZValue * fraction)) >> 12; // at theta = 0, we are just above, ie dy is -k, dx is 0 switch(IntroViewTwistDirection) { case CLOCKWISE: x = (IntroViewDistanceFromSplinePath * rsin(IntroViewTwistAngle)) >> 12; y = (IntroViewDistanceFromSplinePath * -rcos(IntroViewTwistAngle)) >> 12; IntroViewTwistAngle = fraction; break; case ANTICLOCKWISE: x = (IntroViewDistanceFromSplinePath * -rsin(IntroViewTwistAngle)) >> 12; y = (IntroViewDistanceFromSplinePath * -rcos(IntroViewTwistAngle)) >> 12; IntroViewTwistAngle = fraction; // -fraction? break; default: assert(FALSE); } ViewTypeFlag = REFERENCE_VIEW; TheView.super = WORLD; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy; TheView.vrz = TheViewShip->position.vz; TheView.vpx = TheViewShip->position.vx + x; TheView.vpy = TheViewShip->position.vy + y; TheView.vpz = TheViewShip->position.vz + z; TheView.rz = 0; break; case INTRO_VIEW_NUDGING_DOWN: ViewTypeFlag = REFERENCE_VIEW; TheView.super = WORLD; fraction = (cycleRatio - 3072) * 4; x = (IntroViewAboveDistance * fraction) >> 12; TheView.vrx = TheViewShip->position.vx; TheView.vry = TheViewShip->position.vy - x; TheView.vrz = TheViewShip->position.vz; y = ((IntroViewDistanceFromSplinePath * (ONE-fraction)) + (IntroViewAboveDistance * fraction)) >> 12; z = IntroViewBehindDistance; TheView.vpx = TheViewShip->position.vx; TheView.vpy = TheViewShip->position.vy - y; TheView.vpz = TheViewShip->position.vz - z; TheView.rz = 0; break; default: assert(FALSE); } }