home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////////////////////
- // //
- // TUTPROG9.CPP - VGA Trainer Program 9 (in Turbo C++ 3.0) //
- // //
- // "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
- // was limited to only Pascal in its first run. All I have done is taken //
- // his original release, translated it to C++ and touched up a few things. //
- // I take absolutely no credit for the concepts presented in this code. //
- // //
- // Program Notes : This program demonstrates polygon moving and rotation. //
- // //
- // If you are compiling this program from within the //
- // Turbo C++ environment, you must go under Options, //
- // Debugger, and change the "Program Heap Size" to a value //
- // 80 or greater. If you are going to be fooling around //
- // with the code a bit, I suggest raising this to about //
- // 100 just to be on the safe side. You don't have to //
- // worry about this if you are compiling command line. //
- // //
- // Just for reference, this is what I use: //
- // //
- // tcc -mc -a -G -2 -O tut9.cpp //
- // //
- // The way things are set up, there is no need to compile //
- // or link tut9.cpp and gfx2.cpp seperately. //
- // //
- // The Compact memory model (-mc) seems to provide the //
- // best results for this tutorial. Remember, use this //
- // memory model when you have little code (less than 64k) //
- // and lots of data. //
- // //
- // Author : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za //
- // Translator : Christopher G. Mann - r3cgm@dax.cc.uakron.edu //
- // //
- // Last Modified : January 21, 1995 //
- // //
- /////////////////////////////////////////////////////////////////////////////
-
- // //
- // INCLUDE FILES //
- // //
-
- #include <conio.h>
- // clrscr(), getch(), kbhit()
- #include <iostream.h>
- // cout()
- #include <math.h>
- // sin(), cos()
- #include <stdlib.h>
- // exit()
- #include "gfx2.cpp"
- // our graphics library tools
-
- // //
- // TYPEDEFS //
- // //
-
- typedef unsigned char byte;
- typedef unsigned int word;
-
- // //
- // CONSTANTS //
- // //
-
- const MAXPOLYS = 5;
- const POLYPOINTS = 4;
- const POLYCORDS = 3;
-
- // //
- // LETTER DATA //
- // //
-
- // The 3-D coordinates of our object ... stored as {X1,Y1,Z1},
- // {X2,Y2,Z2} ... for the 4 points of a poly.
- const int A[MAXPOLYS][POLYPOINTS][POLYCORDS] =
- { {{-10, 10, 0},{ -2,-10, 0},{ 0,-10, 0},{ -5,10, 0}}, // 1
- {{ 10, 10, 0},{ 2,-10, 0},{ 0,-10, 0},{ 5,10, 0}}, // 2
- {{ -2,-10, 0},{ 2,-10, 0},{ 2, -5, 0},{ -2,-5, 0}}, // 3
- {{ -6, 0, 0},{ 6, 0, 0},{ 7, 5, 0},{ -7, 5, 0}}, // 4
- {{ 0, 0, 0},{ 0, 0, 0},{ 0, 0, 0},{ 0, 0, 0}} }; // 5
-
- // 1----1 + 2----2
- // |....| | |....|
- // |....| | |....|
- // `....` | '....'
- // |....| | |....|
- // `.4------+------4.'
- // ||......|......||
- // ``......|......''
- // ||.....|.....||
- // ||.....|.....||
- // -------+---4+----+----+4---+-------
- // |...| | |...|
- // `...` | '...'
- // |...|||...|
- // |...|...|
- // |.3-+-3.|
- // `.|.|.|.'
- // ||.|.||
- // ||.|.||
- // `|.|.|'
- // 3-2-3
-
- const int S[MAXPOLYS][POLYPOINTS][POLYCORDS] =
- { {{-10,-10, 0},{ 10,-10, 0},{10, -7, 0},{-10, -7, 0}},
- {{-10, 10, 0},{ 10, 10, 0},{10, 7, 0},{-10, 7, 0}},
- {{-10, 1, 0},{ 10, 1, 0},{10, -2, 0},{-10, -2, 0}},
- {{-10, -8, 0},{ -7, -8, 0},{-7, 0, 0},{-10, 0, 0}},
- {{ 10, 8, 0},{ 7, 8, 0},{ 7, 0, 0},{ 10, 0, 0}} };
-
- const int P[MAXPOLYS][POLYPOINTS][POLYCORDS] =
- { {{-10,-10,0},{-7,-10,0},{-7,10,0},{-10,10,0}},
- {{10,-10,0},{7,-10,0},{7,0,0},{10,0,0}},
- {{-9,-10,0},{9,-10,0},{9,-7,0},{-9,-7,0}},
- {{-9,-1,0},{9,-1,0},{9,2,0},{-9,2,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}} };
-
- const int H[MAXPOLYS][POLYPOINTS][POLYCORDS] =
- { {{-10,-10,0},{-7,-10,0},{-7,10,0},{-10,10,0}},
- {{10,-10,0},{7,-10,0},{7,10,0},{10,10,0}},
- {{-9,-1,0},{9,-1,0},{9,2,0},{-9,2,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}} };
-
- const int Y[MAXPOLYS][POLYPOINTS][POLYCORDS] =
- { {{-7,-10,0},{0,-3,0},{0,0,0},{-10,-7,0}},
- {{7,-10,0},{0,-3,0},{0,0,0},{10,-7,0}},
- {{-2,-3,0},{2,-3,0},{2,10,0},{-2,10,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}} };
-
- const int X[MAXPOLYS][POLYPOINTS][POLYCORDS] =
- { {{-7,-10,0},{10,7,0},{7,10,0},{-10,-7,0}},
- {{7,-10,0},{-10,7,0},{-7,10,0},{10,-7,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}} };
-
- const int I[MAXPOLYS][POLYPOINTS][POLYCORDS] =
- { {{-10,-10,0},{10,-10,0},{10,-7,0},{-10,-7,0}},
- {{-10,10,0},{10,10,0},{10,7,0},{-10,7,0}},
- {{-2,-9,0},{2,-9,0},{2,9,0},{-2,9,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
- {{0,0,0},{0,0,0},{0,0,0},{0,0,0}} };
-
- // //
- // FUNCTION PROTOTYPES //
- // //
-
- void DrawPoly (int x1, int y1, int x2, int y2,
- int x3, int y3, int x4, int y4,
- byte Col, word Where);
- void SetUpPoints ();
- void RotatePoints (int X, int Y, int Z);
- void DrawPoints ();
- void Whizz (int sub, int °);
- void MoveAround ();
-
- // //
- // STRUCTURES //
- // //
-
- // The data for every point we rotate
- struct Point {
- float x;
- float y;
- float z;
- };
-
- // //
- // GLOBAL VARIABLE DECLARATIONS //
- // //
-
- byte far *Virscr=NULL; // Pointer to our virtual screen
- word Vaddr; // Segment of our virtual screen
- float Lookup[360][2]; // Our sin and cos lookup tables
- int Xoff, Yoff, Zoff; // Used for movement of the object
- Point Lines[MAXPOLYS][4]; // The base object being rotated
- Point Translated[MAXPOLYS][4]; // The rotated object
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // MAIN FUNCTION //
- // //
- ///////////////////////////////////////////////////////////////////////////////
-
- void main() {
-
- SetUpVirtual(Virscr,Vaddr);
- // always check to see if enough memory was allocated
- if (Virscr == NULL) {
- SetText();
- cout << "Insufficient memory for virtual screens, exiting...";
- exit(1);
- }
-
- clrscr();
- cout
- << "Hello there! Varsity has begun once again, so it is once again\n"
- << "back to the grindstone ;-) ... anyway, this tutorial is, by\n"
- << "popular demand, on poly-filling, in relation to 3-D solids.\n\n"
- << "In this program, the letters of ASPHYXIA will fly past you. As you\n"
- << "will see, they are solid, not wireframe. After the last letter has\n"
- << "flown by, a large A will be left in the middle of the screen.\n\n"
- << "You will be able to move it around the screen, and you will notice\n"
- << "that it may have bits only half on the screen, i.e. clipping is\n"
- << "perfomed. To control it use the following : ""A"" and ""Z"" control the Z\n"
- << "movement, "","" and ""."" control the X movement, and ""S"" and ""X""\n"
- << "control the Y movement. I have not included rotation control, but\n"
- << "it should be easy enough to put in yourself ... if you have any\n"
- << "hassles, leave me mail.\n\n";
- cout << "Hit any key to continue ...\n";
- getch();
- SetMCGA();
-
- SetUpPoints();
-
- MoveAround();
- SetText();
-
- ShutDown(Virscr);
-
- cout
- << "All done. This concludes the ninth sample program in the ASPHYXIA\n"
- << "Training series. You may reach DENTHOR under the names of GRANT\n"
- << "SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid\n"
- << "Connectix BBS user, and occasionally read RSAProg.\n"
- << "The numbers are available in the main text. You may also write to me at:\n"
- << " Grant Smith\n"
- << " P.O. Box 270\n"
- << " Kloof\n"
- << " 3640\n"
- << "I hope to hear from you soon!\n\n";
- cout << "Hit any key to exit ...\n";
- getch();
-
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // //
- // DrawPoly() - This draws a polygon with 4 points at x1,y1, x2,y2, x3,y3, //
- // x4,y4 in color Col at location Where //
- // //
- /////////////////////////////////////////////////////////////////////////////
-
- void DrawPoly(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,
- byte Col, word Where) {
-
- int x, mny, mxy, mnx, mxx, yc;
- int mul1, div1, mul2, div2, mul3, div3, mul4, div4;
-
- // find the maximum y (mny) and minimum y (mny)
- mny = y1;
- mxy = y1;
- if (y2<mny) mny = y2;
- if (y2>mxy) mxy = y2;
- if (y3<mny) mny = y3;
- if (y3>mxy) mxy = y3;
- if (y4<mny) mny = y4;
- if (y4>mxy) mxy = y4;
-
- // if the mimimum or maximum is out of bounds, bring it back in
- if (mny< 0) mny = 0;
- if (mxy>199) mxy = 199;
-
- // verticle range checking
- if (mny>199) return;
- if (mxy< 0) return;
-
- // constants needed for intersection calculations
- mul1 = x1-x4; div1 = y1-y4;
- mul2 = x2-x1; div2 = y2-y1;
- mul3 = x3-x2; div3 = y3-y2;
- mul4 = x4-x3; div4 = y4-y3;
-
- for (yc=mny; yc<mxy; yc++) {
- mnx = 320;
- mxx = -1;
-
- if ((y4 >= yc) || (y1 >= yc))
- if ((y4 <= yc) || (y1 <= yc))
- if (y4 != y1) {
- x = ((yc-y4) * mul1 / div1) + x4;
- if (x<mnx) mnx = x;
- if (x>mxx) mxx = x;
- }
-
- if ((y1 >= yc) || (y2 >= yc))
- if ((y1 <= yc) || (y2 <= yc))
- if (y1 != y2) {
- x = ((yc-y1) * mul2 / div2) + x1;
- if (x<mnx) mnx = x;
- if (x>mxx) mxx = x;
- }
-
- if ((y2 >= yc) || (y3 >= yc))
- if ((y2 <= yc) || (y3 <= yc))
- if (y2 != y3) {
- x = ((yc-y2) * mul3 / div3) + x2;
- if (x<mnx) mnx = x;
- if (x>mxx) mxx = x;
- }
-
- if ((y3 >= yc) || (y4 >= yc))
- if ((y3 <= yc) || (y4 <= yc))
- if (y3 != y4) {
- x = ((yc-y3) * mul4 / div4) + x3;
- if (x<mnx) mnx = x;
- if (x>mxx) mxx = x;
- }
-
- // horizontal range checking
- if (mnx< 0) mnx = 0;
- if (mxx>319) mxx = 319;
-
- if (mnx<=mxx)
- // draw the horizontal line
- Hline(mnx,mxx,yc,Col,Where);
-
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // //
- // SetUpPoints() - This creates the lookup table. //
- // //
- /////////////////////////////////////////////////////////////////////////////
-
- void SetUpPoints() {
-
- int loop1;
-
- // generate the sin() and cos() tables
- for (loop1=0; loop1<360; loop1++) {
- Lookup [loop1][0] = sin(rad(loop1));
- Lookup [loop1][1] = cos(rad(loop1));
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // //
- // RotatePoints() - This rotates object lines by X,Y and Z, then places //
- // the result in Translated[] //
- // //
- /////////////////////////////////////////////////////////////////////////////
-
- void RotatePoints(int X, int Y, int Z) {
-
- int loop1, loop2;
- Point temp;
-
- for (loop1=0; loop1<MAXPOLYS; loop1++) {
- for (loop2=0; loop2<4; loop2++) {
- temp.x = Lines[loop1][loop2].x;
- temp.y = Lookup[X][1] * Lines[loop1][loop2].y - Lookup[X][0] * Lines[loop1][loop2].z;
- temp.z = Lookup[X][0] * Lines[loop1][loop2].y + Lookup[X][1] * Lines[loop1][loop2].z;
- Translated[loop1][loop2] = temp;
-
- if (Y>0) {
- temp.x = Lookup[Y][1] * Translated[loop1][loop2].x - Lookup[Y][0] * Translated[loop1][loop2].y;
- temp.y = Lookup[Y][0] * Translated[loop1][loop2].x + Lookup[Y][1] * Translated[loop1][loop2].y;
- temp.z = Translated[loop1][loop2].z;
- Translated[loop1][loop2] = temp;
- }
-
- if (Z>0) {
- temp.x = Lookup[Z][1] * Translated[loop1][loop2].x + Lookup[Z][0] * Translated[loop1][loop2].z;
- temp.y = Translated[loop1][loop2].y;
- temp.z = Lookup[Z][0] * Translated[loop1][loop2].x + Lookup[Z][1] * Translated[loop1][loop2].z;
- Translated[loop1][loop2] = temp;
- }
- }
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // //
- // DrawPoints() - This draws the translated object to the virtual screen. //
- // //
- /////////////////////////////////////////////////////////////////////////////
-
- void DrawPoints() {
-
- int nx, ny, nx2, ny2, nx3, ny3, nx4, ny4, temp, loop1;
-
- for (loop1=0; loop1<MAXPOLYS; loop1++) {
- if ((Translated[loop1][0].z+Zoff<0) && (Translated[loop1][1].z+Zoff<0) &&
- (Translated[loop1][2].z+Zoff<0) && (Translated[loop1][4].z+Zoff<0)) {
-
- temp = Translated[loop1][0].z + Zoff;
- nx = ((256*Translated[loop1][0].x) / temp) + Xoff;
- ny = ((256*Translated[loop1][0].y) / temp) + Yoff;
-
- temp = Translated[loop1][1].z + Zoff;
- nx2 = ((256*Translated[loop1][1].x) / temp) + Xoff;
- ny2 = ((256*Translated[loop1][1].y) / temp) + Yoff;
-
- temp = Translated[loop1][2].z + Zoff;
- nx3 = ((256*Translated[loop1][2].x) / temp) + Xoff;
- ny3 = ((256*Translated[loop1][2].y) / temp) + Yoff;
-
- temp = Translated[loop1][3].z + Zoff;
- nx4 = ((256*Translated[loop1][3].x) / temp) + Xoff;
- ny4 = ((256*Translated[loop1][3].y) / temp) + Yoff;
-
- DrawPoly(nx,ny,nx2,ny2,nx3,ny3,nx4,ny4,13,Vaddr);
- }
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // //
- // Whizz() - This function moves the letters from one side of the screen //
- // to the other and also zooms them closer as they move. //
- // //
- /////////////////////////////////////////////////////////////////////////////
-
- void Whizz(int sub, int °) {
-
- int loop1;
-
- for (loop1=(-64); loop1<(-4); loop1++) {
-
- Zoff = (loop1 * 8) - 15;
- if (sub == 1) Xoff -= 7; else Xoff += 7;
- RotatePoints(deg,deg,deg);
- DrawPoints();
- Flip(Vaddr,VGA);
- Cls(0,Vaddr);
- deg = (deg + 5) % 360;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // //
- // MoveAround() - This is the main display function. First it brings the //
- // object towards the viewer by increasing the Zoff, then //
- // it passes control to the user. //
- // //
- /////////////////////////////////////////////////////////////////////////////
-
- void MoveAround() {
-
- int deg=0, loop1, loop2;
- byte ch=1; // assign a dummy value to ch
-
- Yoff = 100;
- Xoff = 350;
- Cls(0,Vaddr);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = A[loop1][loop2][0];
- Lines[loop1][loop2].y = A[loop1][loop2][1];
- Lines[loop1][loop2].z = A[loop1][loop2][2];
- }
- Whizz(1,deg);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = S[loop1][loop2][0];
- Lines[loop1][loop2].y = S[loop1][loop2][1];
- Lines[loop1][loop2].z = S[loop1][loop2][2];
- }
- Whizz(0,deg);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = P[loop1][loop2][0];
- Lines[loop1][loop2].y = P[loop1][loop2][1];
- Lines[loop1][loop2].z = P[loop1][loop2][2];
- }
- Whizz(1,deg);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = H[loop1][loop2][0];
- Lines[loop1][loop2].y = H[loop1][loop2][1];
- Lines[loop1][loop2].z = H[loop1][loop2][2];
- }
- Whizz(0,deg);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = Y[loop1][loop2][0];
- Lines[loop1][loop2].y = Y[loop1][loop2][1];
- Lines[loop1][loop2].z = Y[loop1][loop2][2];
- }
- Whizz(1,deg);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = X[loop1][loop2][0];
- Lines[loop1][loop2].y = X[loop1][loop2][1];
- Lines[loop1][loop2].z = X[loop1][loop2][2];
- }
- Whizz(0,deg);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = I[loop1][loop2][0];
- Lines[loop1][loop2].y = I[loop1][loop2][1];
- Lines[loop1][loop2].z = I[loop1][loop2][2];
- }
- Whizz(1,deg);
-
- for (loop1=0; loop1<MAXPOLYS; loop1++)
- for (loop2=0; loop2<POLYPOINTS; loop2++) {
- Lines[loop1][loop2].x = A[loop1][loop2][0];
- Lines[loop1][loop2].y = A[loop1][loop2][1];
- Lines[loop1][loop2].z = A[loop1][loop2][2];
- }
- Whizz(0,deg);
-
- Cls(0,Vaddr);
- Cls(0,VGA);
-
- Xoff = 160;
-
- do {
- if (kbhit()) {
- ch = getch();
- switch (ch) {
- case 'A': case 'a': Zoff += 5; break; // away
- case 'Z': case 'z': Zoff -= 5; break; // toward
- case ',': Xoff -= 5; break; // left
- case '.': Xoff += 5; break; // right
- case 'S': case 's': Yoff -= 5; break; // down
- case 'X': case 'x': Yoff += 5; break; // up
- }
- }
- DrawPoints();
- Flip(Vaddr,VGA);
- Cls(0,Vaddr);
- RotatePoints(deg,deg,deg);
- deg = (deg + 5) % 360;
-
- // if the key pressed above was 0 (i.e. a control character) then
- // read the character code
- if (ch == 0) ch = getch();
-
- } while (ch != 27); // if the escape code was 27 (escape key) then exit
-
- }
-