home *** CD-ROM | disk | FTP | other *** search
- //
- // File name: OrbitSim.CPP
- //
- // Description: A simple orbit model illustrating 3-dimensional
- // transformations
- //
- // Author: John De Goes
- //
- // Project: Cutting Edge 3D Game Programming
- //
-
- // ------------------------------------------------------------
- // | Global headers: |
- // ------------------------------------------------------------
-
- #include <Dos.H>
- #include <Time.H>
- #include <Math.H>
- #include <Stdio.H>
- #include <Assert.H>
- #include <Conio.H>
- #include <Stdlib.H>
- #include <Iostream.H>
-
- // ------------------------------------------------------------
- // | Local headers: |
- // ------------------------------------------------------------
-
- #include "32bit.HPP"
- #include "TGA32.HPP"
- #include "OutPort.HPP"
-
- // ------------------------------------------------------------
- // | Globals/constants: |
- // ------------------------------------------------------------
-
- #pragma inline
-
- // ------------------------------------------------------------
- // | Local structs/classes |
- // ------------------------------------------------------------
-
- // A view port struct:
- struct ViewPort {
- // The distance between the viewer and the screen:
- float Distance;
- // The buffer containing the image to be displayed:
- unsigned char *Buffer;
- // The background color:
- unsigned char BackColor;
- // The screen width and height:
- int Width, Height;
- // The center of the view port:
- int XCenter, YCenter;
- // The clipping coordinates:
- int Left, Right, Top, Bottom;
- };
-
- // A Planet class:
- class Planet {
- protected:
- float X, Y, Z, Velocity;
- int Sx, Sy, OldSx, OldSy;
- unsigned char Color;
- ViewPort *LastScreen;
- // Protected project function:
- void Project ( ViewPort &Screen );
- public:
- // No argument constructor:
- Planet () { }
- // Three argument constructor:
- Planet ( float Nx, float Ny, float Nz )
- {
- Position ( Nx, Ny, Nz );
- }
- // Rotatation functions:
- void RotateX ( float Angle );
- void RotateY ( float Angle );
- void RotateZ ( float Angle );
- // Translation functions:
- void Translate ( float Xt, float Yt, float Zt );
- // Display function:
- void Display ( ViewPort &Screen );
- // Position functions:
- float GetX () { return X; }
- float GetY () { return Y; }
- float GetZ () { return Z; }
- // Erase function:
- void Erase ();
- // Position function:
- void Position ( float Nx, float Ny, float Nz )
- {
- X = Nx; Y = Ny; Z = Nz;
- }
- // Color function:
- void SetColor ( unsigned char NewColor )
- {
- Color = NewColor;
- }
- };
-
- void Planet::Project ( ViewPort &Screen )
- {
- // Project the planets (X, Y, Z) coordinates onto
- // the 2-dimensional viewport by dividing the world (X, Y)
- // by the world Z - multiplying by viewing distance:
- assert ( Z > 0 );
- Sx = X * Screen.Distance / Z + Screen.XCenter;
- Sy = Y * ( -Screen.Distance ) / Z + Screen.YCenter;
- }
-
- void Planet::RotateX ( float Angle )
- {
- // Function rotates planet around the X axis by Angle
- float OldX = X, OldY = Y, OldZ = Z;
- X = OldX;
- Y = OldY * cos ( Angle ) - OldZ * sin ( Angle );
- Z = OldY * sin ( Angle ) + OldZ * cos ( Angle );
- }
-
- void Planet::RotateY ( float Angle )
- {
- // Function rotates planet around Y axis by Angle
- float OldX = X, OldY = Y, OldZ = Z;
- X = OldZ * sin ( Angle ) + OldX * cos ( Angle );
- Y = OldY;
- Z = OldZ * cos ( Angle ) - OldX * sin ( Angle );
- }
-
- void Planet::RotateZ ( float Angle )
- {
- // Function rotates planet around Z axis by Angle
- float OldX = X, OldY = Y, OldZ = Z;
- X = OldX * cos ( Angle ) - OldY * sin ( Angle );
- Y = OldX * sin ( Angle ) + OldY * cos ( Angle );
- Z = OldZ;
- }
-
- void Planet::Translate ( float Xt, float Yt, float Zt )
- {
- // Translate planet by (Xt, Yt, Zt)
- X += Xt; Y += Yt; Z += Zt;
- }
-
- void Planet::Display ( ViewPort &Screen )
- {
- // Project 3-dimensional coordinates:
- Project ( Screen );
- // Determine if point is on view port:
- if ( ( Sx >= Screen.Left) && ( Sx <= Screen.Right ) )
- if ( ( Sy >= Screen.Top) && (Sy <= Screen.Bottom ) )
- {
- // If so, display planet:
- Screen.Buffer [ Sy * Screen.Width + Sx ] = Color;
- }
- // Record these points:
- OldSx = Sx; OldSy = Sy;
- LastScreen = &Screen;
- }
-
- void Planet::Erase ()
- {
- // Function erases planet - remembers last ViewPort
- int Width = LastScreen -> Width;
- unsigned char OldColor = LastScreen -> BackColor;
- LastScreen -> Buffer [ OldSy * Width + Sx ] = OldColor;
- }
-
- // A timer class
- class Timer {
- protected:
- unsigned long StartTime, CurrentTime, FunctionTime, Lapse;
- int UpdateFlag, AttachFlag;
- void (*CallFunction) ();
- public:
- Timer ()
- {
- AttachFlag = 0;
- UpdateFlag = 0;
- StartTime = 0;
- }
- void Start ()
- {
- StartTime = clock ();
- UpdateFlag = 1;
- }
- void Reset ()
- {
- StartTime = clock ();
- UpdateFlag = 1;
- }
- unsigned long Time ()
- {
- if ( UpdateFlag )
- {
- CurrentTime = clock();
- return (CurrentTime - StartTime);
- }
- return 0;
- }
- void Update ();
- void Attach(void (*NewFunction)(), long Delay );
- void operator ++ () { Update (); }
- void operator ++ (int) { Update (); }
- };
-
- void Timer::Update ()
- {
- CurrentTime = clock();
- if (AttachFlag)
- {
- if (CurrentTime >= FunctionTime)
- {
- FunctionTime = CurrentTime + Lapse;
- CallFunction ();
- }
- }
- }
-
- // Function that will attach a function to specified time
- // intervals.
- void Timer::Attach(void (*NewFunction)(), long Delay )
- {
- Timer::CallFunction = NewFunction;
- Lapse = Delay;
- CurrentTime = clock();
- FunctionTime = CurrentTime + Delay;
- AttachFlag = 1;
- }
-
- // ------------------------------------------------------------
- // | Function section: |
- // ------------------------------------------------------------
-
- // Function designed to initialize the two view ports
- void InitializeViews ( ViewPort &View1, ViewPort &View2 )
- {
- // Initialize view 1:
- View1.Distance = 120;
- View1.BackColor = 0;
- View1.Width = 320;
- View1.Height = 200;
- View1.XCenter = 100;
- View1.YCenter = 100;
- View1.Left = 50;
- View1.Right = 150;
- View1.Top = 50;
- View1.Bottom = 150;
-
- // Initialize view 2:
- View2.Distance = 120;
- View2.BackColor = 0;
- View2.Width = 320;
- View2.Height = 200;
- View2.XCenter = 220;
- View2.YCenter = 100;
- View2.Left = 170;
- View2.Right = 270;
- View2.Top = 50;
- View2.Bottom = 150;
- }
-
- // Function designed to blit a view port to a 320x200 screen:
- void BlitView ( ViewPort &ViewScreen,
- unsigned char *ScreenPtr )
- {
- int X1 = ViewScreen.Left, X2 = ViewScreen.Right;
- int Y1 = ViewScreen.Top, Y2 = ViewScreen.Bottom;
- unsigned char *BufferPtr = ViewScreen.Buffer;
- unsigned char *ScanBuffer, *ScanScreen;
- ScreenPtr += Y1 * 320 + X1;
- BufferPtr += Y1 * ViewScreen.Width + X1;
- for ( int Y = Y1; Y < Y2; Y++ )
- {
- ScanBuffer = BufferPtr;
- ScanScreen = ScreenPtr;
- // Blit scan-line - buffer width must be evenly
- // divisible by 4:
- int Length = (X2 - X1) >> 2;
- for ( register int X = 0; X < Length; X++ )
- {
- *ScanScreen++ = *ScanBuffer++;
- *ScanScreen++ = *ScanBuffer++;
- *ScanScreen++ = *ScanBuffer++;
- *ScanScreen++ = *ScanBuffer++;
- }
- ScreenPtr += 320;
- BufferPtr += ViewScreen.Width;
- }
- }
-
- void SetPalReg ( long Index, char Red, char Green, char Blue )
- {
- REGS Regs;
- Regs.w.ax = 0x1010;
- Regs.x.ebx = Index;
- Regs.h.ch = Red;
- Regs.h.cl = Green;
- Regs.h.dh = Blue;
- int386 ( 0x10, &Regs, &Regs );
- }
-
- // A function designed to set the palette:
- void SetPalette(unsigned char *Palette)
- {
- int N = 0; N; Palette;
- for (short unsigned int Index = 0; Index < 256; Index++)
- {
- SetPalReg ( Index, ( short unsigned int ) Palette [ N++ ],
- ( short unsigned int ) Palette [ N++ ],
- ( short unsigned int ) Palette [ N++ ] );
- }
- }
-
- // Changes the speed of the internal clock
- void ChangeClock ( unsigned short int Value )
- {
- unsigned char LowByte = ( unsigned char )
- ( Value & 0x00FF );
- unsigned char HighByte = ( unsigned char )
- ( ( Value >> 8 ) & 0x00FF );
- // Send control word to 8253's control register:
- outportbr ( 0x43, 0x3C );
- // Set the new counter time:
- outportbr ( 0x40, LowByte );
- outportbr ( 0x40, HighByte );
- }
-
- // Program entry:
- void main ()
- {
- // Create a pointer to video memory:
- unsigned char *ScreenPtr = VideoAddress ();
- // Create a video buffer:
- unsigned char *ScreenBuffer = new unsigned char [64000];
- float TScale, ElapsedTime = 0; Timer T;
- if ( ScreenBuffer == NULL )
- {
- cout << "\nNot enough memory to run application\n";
- return;
- }
- TGAImage BackGround;
- if ( BackGround.Load ( "Orbitbck.TGA" ) == 0 )
- {
- cout << "\nError loading OrbitBCK.TGA\n";
- delete [] ScreenBuffer;
- return;
- }
- int Input = 0;
- ViewPort View1, View2;
- InitializeViews ( View1, View2 );
- View1.Buffer = ScreenBuffer;
- View2.Buffer = ScreenBuffer;
- Planet Earth (0, -1, 10 ), Moon (-3, -1, 10 );
- Planet Jupiter (0, 0, 10 ), JMoon ( -3, 0, 10 );
- Earth.SetColor ( BLUE + 100 );
- Moon.SetColor ( LIGHTGRAY + 100 );
- Jupiter.SetColor ( RED + 100 );
- JMoon.SetColor ( DARKGRAY + 100 );
-
- // Set the video mode to 13h:
- SetVideo ( 0x13 );
-
- // Set the palette:
- SetPalette ( BackGround.Palette );
-
- // Initialize inertia values:
- float MoonVSign = 1;
-
- // Set the system clock to 119.2 ticks a second:
- ChangeClock ( 10000 );
-
- // Start the timer:
- T.Start ();
-
- // Loop until escape key pressed:
- while ( Input != 27 )
- {
- TScale = 0.05 * ElapsedTime;
-
- // Check for keyboard input:
- if ( kbhit() )
- Input = getch ();
-
- // Blit background to screen:
- memmove ( ScreenBuffer, BackGround.Image, 64000 );
-
- // Display earth and moon:
- Earth.Display ( View1 );
- Moon.Display ( View1 );
-
- // Translate moon to origin:
- Moon.Translate ( 0, 1, -10 );
-
- // Rotate moon:
- Moon.RotateY ( 0.01 * TScale );
-
- // Translate moon:
- Moon.Translate ( 0, MoonVSign, 0 );
-
- if ( Moon.GetY() < -0.25 )
- {
- MoonVSign = ( 0.01 * TScale );
- }
-
- if ( Moon.GetY() > 0.25 )
- {
- MoonVSign = -( 0.01 * TScale );
- }
-
- // Translate moon to original position:
- Moon.Translate ( 0, -1, 10 );
-
- // Display Jupiter and it's moon:
- Jupiter.Display ( View2 );
- JMoon.Display ( View2 );
-
- // Rotate moon:
- JMoon.RotateZ ( 0.01 * TScale );
-
- // Blit the various viewports:
- BlitView ( View1, ScreenBuffer );
- BlitView ( View2, ScreenBuffer );
-
- // Copy the screen buffer into the video ram:
- memmove ( ScreenPtr, ScreenBuffer, 64000 );
-
- // Record elapsed time and reset the timer:
- ElapsedTime = T.Time ();
- T.Reset ();
- }
- // Set the video mode to 03h:
- SetVideo ( 0x03 );
-
- // Unlock memory:
- delete [] ScreenBuffer;
-
- // Reset the speed of the system's clock:
- ChangeClock ( 0xFFFF );
- }
-