/**************************************************************************** | ABOUT THIS Header file (threed.h) and object file (threed.o) | Written by: Michael Main | Date written: Nov 3, 1994 | | To use the threed functions follow these steps: | 1. In your program put this include statement: | #include "/home/staff/faculty/main/threed.h" | 2. Create Xturbo.o and threed.o: | g++ -Wall -gstabs -c threed.c | g++ -Wall -gstabs -c Xturbo.c -I/usr/local/X11/include | 3. When you compile your program, include these items: | g++ ... Xturbo.o threed.o -L/usr/local/X11/lib -lX11 -lm | The ... is your main program and any other .o files that you use. | An example program which you may compile and run is test3d.c, | which you may copy from the ~main/1210 or ~main/1300 directory. | | WHAT threed PROVIDES: | This unit provides one new class called Polygon, and thwo fairly | simple types called Axis and Cartesian. The unit also provides | nine procedures which are used to control where a "viewer" is viewing the | Polygons from, and for drawing the view that this viewer sees. | A description of each data type and procedure follows: | | type Axis | An enumerated type for the names X, Y, and Z. These are the names of | the three axes in the usual 3-dimensional Cartesian coordinate system. | type Cartesian | A value of this type represents a point in 3-dimensional space. It is | stored as an array of three real numbers. The index of the array is | the Axis data type. For example, a Cartesian point P could be assigned an | X-coordinate of 3.1 by the assignment statement P[X] := 3.1; | type Polygon | This is a class type which represents a polygon in 3-dimensional space. | The methods of the class are listed here: | Polygon(); | Polygon(unsigned int RequestedCapacity); | Note: These are the two constructors. The constructor with no | parameter uses a RequestedCapacity of 4. The constructor should only | be called at the time that a Polygon is first declared. | Postcondition: The Polygon has been initialized and the other methods | may now be used. The RequestedCapacity is the number of vertices | that you are requesting the polygon to hold. However, sometimes | that entire request will not be met, and the polygon might not be | able to hold that many vertices. | NOTE: After the constructor executes, the "origin" of the Polygon is | (0,0,0), which means that any vertices which are later added to | the Polygon will be drawn with respect to the location (0,0,0). | The fill color of the polygon has been set to MAGENTA, the | border color has been set to BLUE, and the Polygon is not hidden. | int Full(); | Precondition: None. | Postcondition: The value returned is true if the Polygon is full (so that | no more vertices may be added.) Otherwise the value returned is false. | unsigned int ManyVertices(); | unsigned int Capacity(); | Precondition: None. | Postcondition: The value returned is the number of vertices in the | Polygon (for ManyVertices) and the maximum number of vertices (for | Capacity). | void operator = (Polygon& Other); | Precondition: Capacity() >= Other.ManyVertices(); | Postcondition: The Polygon has been assigned to be the same as Other. | void AddVertex(Cartesian Vertex); | void AddVertexXYZ(float DataX, float DataY, float DataZ); | Precondition: Full() returns false. | Postcondition: Another vertex has been added to the Polygon. In the | AddVertex version, the Cartesian value Vertex is the new vertex. In the | AddVertexXYZ version, the X, Y and Z coordinates of the new point are | given as the three parameters DataX, DataY and DataZ. | void MoveVertex(int VertexNumber, Cartesian Vertex); | void MoveVertexXYZ(int VertexNumber, float DataX, float DataY, float DataZ); | Precondition: VertexNumber is a positive integer <= the number of | vertices in the Polygon. (So that the first vertex number is 1.) | Postcondition: The vertex whose number is VertexNumber has been moved | to the indicated location. | void SetColor(int Color); | Precondition: None. | Postcondition: The color for drawing the Polygon has been set. | If Color is 0 then the Polygon is drawn in white with a black border. | Any other value draws the Polygon in black with a white border. | If SetColor is not called, then the polygon is drawn white. | void SetOrigin(Cartesian NewOrigin); | void SetOriginXYZ(float DataX, float DataY, float DataZ); | Precondition: None. | Postcondition: The "origin" of the Polygon has been set to the location | specified by the parameter to SetOrigin or SetOriginXYZ. The origin | is used to determine where the Polygon's vertices are drawn from. | For example, if the origin is (1,0,0) and a vertex is at (2,3,4) -- | then the vertex will actually be drawn at (3,3,4). In other words, | the origin gets added to each vertex location before the vertex is | actually drawn. The purpose of having an origin is to allow you | to quickly move an entire polygon by simply moving the origin. | void TranslateOrigin(float DeltaX, float DeltaY, float DeltaZ); | Precondition: None. | Postcondition: The origin of the Polygon has been moved by the | amounts DeltaX, DeltaY, and DeltaZ in the X, Y and Z directions. | void Rotate(Axis AxisOfRotation, float Amount); | Precondition: None. | Postcondition: All the vertices of the polygon have been rotated | around the origin of the polygon. The rotation is around the | axis given by AxisOfRotation, and the amount of the rotation is | given in Radians by the parameter Amount. | void Hide(); | Precondition: None. | Postcondition: The Polygon will no longer be drawn on the screen, | until Unhide() is called. Other member functions, such as | AddVertex, etc., may continue to be called to change the Polygon. | void Unhide(); | Precondition: None. | Postcondition: The Polygon will once again be drawn on the screen, | cancelling the effect of a previous call to Hide(). | int Hidden(); | Precondition: None. | Postcondition: A true return value indicates that the Polygon is being | drawn on the screen; false indicates that the Polygon is not being | drawn on the screen. | void Remove(); | Precondition: None. | Postcondition: The Polygon has been removed from the screen, and none of | the member functions may be called until Revive() is called. | void Revive(unsigned int RequestedCapacity = 4); | Precondition: The most recent activation of a member function was a call | to Remove(). | Postcondition: The Polygon has been initialized (in the same manner as | the constructor works). All member functions can again be used. | | Procedures | The unit also provides procedures for controling a "viewer" who is | looking at all the Polygons, and for drawing what the viewer sees. | All procedures assume a right-handed coordinate system, meaning that | if you point your right thumb in the direction of the positive z-axis, | then your right fingers curl from the positive x-axis to the positive | y-axis. The procedures are: | | void PutIntoGraphicsMode(); | Precondition: InGraphics returns false. | Postcondition: The computer is now has a graphics window and the various | graphics routines listed below may be called to draw Polygons. | NOTE: Call the InGraphics function to see if PutIntoGraphicsMode | failed or succeeded. | int InGraphics(); | Precondition: None. | Postcondition: The value returned is true if the machine currently | has a graphics window to draw in. | void ShutDownGraphics(); | Precondition: InGraphics returns true. | Postcondition: The machine is no longer has a graphics window to draw in. | void SetView(float DistanceFromOrigin, float Width, float Height); | Precondition: InGraphics returns true. | Postcondition: Parameters for viewing the Polygons have been set up. | The "viewer" of the Polygons is placed on the negative Y-axis, at a | distance of DistanceFromOrigin from the location (0,0,0). This | viewer is looking toward the origin. The viewer sees through a | rectangular window which is centered at the origin, with a width given | by the parameter Width, and a height given by the parameter Height. | NOTE: If you don't call SetView, then this unit will use the values | of DistanceFromOrigin = 100, Width = 15, Height = 15. | void ZoomView(float Amount); | Precondition: InGraphics returns true. | Postcondition: The "viewer" who is viewing the Polygons is moved closer | or farther from the origin. Example: Amount=2 "zooms" by a factor of 2, | so that the viewer is closer to the origin. Amount= 0.5 "unzooms" | by a factor of 1/2, so that the viewer is farther from the origin. | void RollView(float Amount) | Precondition: InGraphics returns true. | Postcondition: The "viewer" who is viewing the Polygons is moved upward | over the origin by Amount radians. Example: Amount = pi/2 | will move the viewer upward over the origin by 90 degrees. | void TiltView(float Amount); | Precondition: InGraphics returns true. | Postcondition: The "viewer" who is viewing the Polygons tilts their | head clockwise by Amount radians. | void SpinView(float Amount); | Precondition: InGraphics returns true. | Postcondition: The "viewer" who is viewing the Polygons moves in a | counterclockwise circle (as viewed from above) around the Z-axis by | Amount radians. | void RefreshScreen(); | Precondition: InGraphics returns true. | Postcondition: The screen is updated to show the current view of all | Polygons which have been initialized. NOTE: Changes that are made to | Polygons, and changes which are made to viewers do not take effect | until RefreshScreen is called! | | These last two procedures have nothing to do with graphics, but they are | useful in many graphics programs. A test program which uses these two | functions is in ~main/1300/testtime.c | float Ticks(); | Precondition: None. | Postcondition: The first time this function is called, the function will | return zero. Each subsequent call returns the approximate number of | seconds which have passed since the previous call. | Example: | cout << Ticks(); // This will print 0 | ... // Then do some computation that takes 1.5 seconds | cout << Ticks(); // This will print 1.5 | ... // Then do more computation that takes 1.1 seconds | cout << Ticks(); // This will print 1.1 | char ReadChar(); | Precondition: PRIOR TO USING THIS FUNCTION YOU SHOULD MAKE THE CALL: | system("stty raw"); | This makes the keyboard send input to the program | immediately, rather than waiting for a carriage return. | Input buffering may be turned back on with | system("stty cooked"); | As a side-effect of "stty raw", all newline characters | which are output with \n or with endl will be JUST a | a new line (and no carriage return). If you also want | a carriage return, then you must output \r. | If you want none of the input to be echoed to the screen, | then give the call: system("stty -echo"); | Postcondition: If a key is being pressed on the keyboard, then the value | of the key is read and returned by the function. Otherwise the function | returns the character value zero. | Example: | #include // Provides the system function | system("stty raw"); | Next = ReadChar(); // Next is a char variable | if (Next != 0) | cout << You just pressed the key: " << Next << "\r" << endl; | else | cout << No key is being pressed right now.\r" << endl; ****************************************************************************/ /* In general, we do not want to include all these definitions if they have | already been included from some other location. Therefore, we check whether | the definitions have previously been defined, and if so then we skip to | the end of this file. */ #ifndef THREED_DEFINITIONS #define THREED_DEFINITIONS #define FALSE 0 #define TRUE 1 const int MAXVERTICES = 4; // Maximum number of vertices in a polygon. enum Axis {X, Y, Z}; typedef float Cartesian[3]; class Polygon { unsigned int Size; unsigned int MaxSize; int FillColor; Cartesian Vertices[MAXVERTICES]; Cartesian Origin; unsigned int Location; int IsHidden; int Changed; // True if polygon has changed since last draw /* Drawing data of some sort is declared here. | This drawing data is valid if Changed = false | and ViewChanged = false too. For now, there is simple drawing data, | which means that Draw and DistanceFromViewer have to often | re-do their entire work each time they are called. A good project | for students would be to implement this improvement! */ short QuadPoints[2*MAXVERTICES]; int Behind; float DistanceRecord; void Draw(); float DistanceFromViewer(); friend void RefreshScreen(); public: Polygon() { Revive(); } Polygon(unsigned int RequestedCapacity) { Revive(RequestedCapacity); } int Full() const { return (Size == MaxSize); } unsigned int ManyVertices() const { return Size; } unsigned int Capacity() const { return MaxSize; } void operator = (const Polygon& Other); void AddVertex(Cartesian Vertex); void AddVertexXYZ(float DataX, float DataY, float DataZ); void MoveVertex(int VertexNumber, Cartesian Vertex); void MoveVertexXYZ(int VertexNumber, float DataX, float DataY, float DataZ); void SetColor(int Color); void SetOrigin(Cartesian NewOrigin); void SetOriginXYZ(float DataX, float DataY, float DataZ); void TranslateOrigin(float DeltaX, float DeltaY, float DeltaZ); void Hide() { IsHidden = Changed = TRUE; } void Rotate(Axis AxisOfRotation, float Amount); void Unhide() { IsHidden = FALSE; Changed = TRUE; } int Hidden() const { return IsHidden; } void Remove(); void Revive(unsigned int RequestedCapacity = 4); ~Polygon() { Remove(); } }; void PutIntoGraphicsMode(); int InGraphics(); void ShutDownGraphics(); void SetView(float DistanceFromOrigin, float Width, float Height); void ZoomView(float Amount); void RollView(float Amount); void TiltView(float Amount); void SpinView(float Amount); void RefreshScreen(); float Ticks(); char ReadChar(); #endif