home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
- #include <stdio.h>
- #include <math.h>
-
- // delete this later:
- #include <applicat.h>
-
- #include "threedq.h"
- #include "quake.h"
-
- #define Pi 3.141592653589793238
-
- inline double MaxOf(double v1, double v2)
- {
- return (v1 > v2) ? v1 : v2;
- }
-
- extern ARRAY<plane_t> planes;
- extern ARRAY<dsurface_t> surfaces;
-
- extern ARRAY<vertex_t> vertices;
- extern ARRAY<edge_t> edges;
-
-
- TThreeD::TThreeD()
- {
- Vb = VB; Vt = VT;
- Vr = VR; Vl = VL;
-
- A = (Vr -Vl) / 2.0;
- B = Vl + A;
- C = (Vt - Vb) / 2.0;
- D = Vb + C;
-
- // Set default values for FROM, AT, UP
- From.x = 1.0; From.y = 0.0; From.z = 0.0;
- At.x = 0.0; At.y = 0.0; At.z = 0.0;
- Up.x = 0.0; Up.y = 0.0; Up.z = 1.0;
-
- Angle = 60.0 * Pi / 180.0; // 60 deg converted to radians
- }
-
-
- // High-level routine to display wireframe model
- void TThreeD::Display(HDC DC, RECT& rect)
- {
- // Use isotropic mapping to make sure x and y coordinates are
- // displayed in the same way
- SetMapMode(DC,MM_ISOTROPIC);
-
- SetWindowExt(DC, VR-VL, VB-VT);
-
-
- if (rect.right <= rect.bottom) {
- SetViewportOrg(DC,-(rect.bottom-rect.right)/2,0);
- SetViewportExt(DC,rect.bottom,rect.bottom);
- }
- else {
- SetViewportOrg(DC,0,-(rect.right-rect.bottom)/2);
- SetViewportExt(DC,rect.right,rect.right);
- }
-
-
- SetEye();
- View(DC);
- }
-
-
- // Convert Clipped coordinates to window coordinates
- inline void TThreeD::WORLDtoPC(double xw, double yw, POINT& pc)
- {
- pc.x = (int)(A * xw + B);
- pc.y = (int)(C * yw + D);
- }
-
-
- // Find the minimum/maximum coordinates.
- void TThreeD::MinMax()
- {
- ObjMinx = Points[1].x; ObjMiny = Points[1].y; ObjMinz = Points[1].z;
- ObjMaxx = Points[1].x; ObjMaxy = Points[1].y; ObjMaxz = Points[1].z;
-
- for (long i=1; i<=Vertices; i++) {
- if (Points[i].x > ObjMaxx) { ObjMaxx = Points[i].x; }
- else if (Points[i].x <ObjMinx) { ObjMinx = Points[i].x; }
-
- if (Points[i].y > ObjMaxy) { ObjMaxy = Points[i].y; }
- else if (Points[i].y <ObjMiny) { ObjMiny = Points[i].y; }
-
- if (Points[i].z > ObjMaxz) { ObjMaxz = Points[i].z; }
- else if (Points[i].z <ObjMinz) { ObjMinz = Points[i].z; }
- }
- }
-
-
- // Default value for AT
- void TThreeD::SetAt()
- {
- MinMax();
-
- At.x = (ObjMaxx + ObjMinx) / 2.0;
- At.y = (ObjMaxy + ObjMiny) / 2.0;
- At.z = (ObjMaxz + ObjMinz) / 2.0;
- }
-
-
- // default value for FROM
- void TThreeD::SetFrom()
- {
- const double WIDTH = 1.8; // ratio used
- From.x = At.x + (ObjMaxx -ObjMinx) / 2.0 + WIDTH *
- MaxOf((ObjMaxz-ObjMinz)/2.0, (ObjMaxy-ObjMiny)/2.0);
- From.y = At.y;
- From.z = At.z;
- }
-
- // Set up parameters in the world to eye transformation.
- void TThreeD::SetEye()
- {
- VECTOR temp;
-
- DVal = cos(Angle/2.0) / sin(Angle/2.0);
-
-
- Dist = Subtract(At, From);
- double amarkmag = Mag(Dist);
- A3 = Divide(Dist, amarkmag);
-
- temp = Cross(Dist, Up);
- double tempmag = Mag(temp);
- A1 = Divide(temp,tempmag);
-
- temp = Cross(A1, A3);
- tempmag = Mag(temp);
- A2 = Divide(temp,tempmag);
-
- Offsx = -A1.x * From.x - A1.y * From.y - A1.z * From.z;
- Offsy = -A2.x * From.x - A2.y * From.y - A2.z * From.z;
- Offsz = -A3.x * From.x - A3.y * From.y - A3.z * From.z;
-
- }
-
- const int NOEDGE = 0;
- const int LEFTEDGE = 1;
- const int RIGHTEDGE = 2;
- const int BOTTOMEDGE = 4;
- const int TOPEDGE = 8;
-
- int TThreeD::Code(double x, double y, double z)
- {
- int c = NOEDGE;
-
- if (x < -z) c |= LEFTEDGE;
- if (x > z) c |= RIGHTEDGE;
- if (y < -z) c |= BOTTOMEDGE;
- if (y > z) c |= TOPEDGE;
-
- return (c);
- }
-
- // Clip the line in 3d coordinates
- void TThreeD::Clip3D(HDC DC, double x1, double y1, double z1,
- double x2, double y2, double z2, POINT& pc1, POINT& pc2)
- {
- int c, c1, c2;
- double x, y, z, t;
- c1 = Code(x1,y1,z1);
- if (c1 > 16) cout << "ERROR (c1): " << x1 << " " << y1 << " "
- << z1 << " " << c1 << "\n";
-
- c2 = Code(x2,y2,z2);
- if (c2 > 16) cout << "ERROR (c2): " << x2 << " " << y2 << " "
- << z2 << " " << c2 << "\n";
-
- while ((c1 != NOEDGE) || (c2 != NOEDGE)) {
- if ((c1 & c2) != NOEDGE) return; // Not in viewing pyramid
-
- c = c1;
- if (c == NOEDGE) c = c2;
- if (c & LEFTEDGE) {
- t = (z1 + x1) /((x1 - x2) - (z2 - z1));
- z = t * (z2 - z1) + z1;
- x = -z;
- y = t * (y2 - y1) + y1;
- }
- else if (c & RIGHTEDGE) {
- t = (z1 - x1) /((x2 - x1) - (z2 - z1));
- z = t * (z2 - z1) + z1;
- x = z;
- y = t * (y2 - y1) + y1;
- }
- else if (c & BOTTOMEDGE) {
- t = (z1 + y1) /((y1 - y2) - (z2 - z1));
- z = t * (z2 - z1) + z1;
- x = t * (x2 - x1) + x1;
- y = -z;
- }
- else if (c & TOPEDGE) {
- t = (z1 - y1) /((y2 - y1) - (z2 - z1));
- z = t * (z2 - z1) + z1;
- x = t * (x2 - x1) + x1;
- y = z;
- }
-
- if (c == c1) {
- x1 = x; y1 = y; z1 = z;
- c1 = Code(x,y,z);
- if (c1 > 16) cout << "ERROR (c1): " << x1 << " " << y1 << " "
- << z1 << " " << c1 << "\n";
-
- }
- else {
- x2 = x; y2 = y; z2 = z;
- c2 = Code(x,y,z);
- if (c2 > 16) cout << "ERROR (c2): " << x2 << " " << y2 << " "
- << z2 << " " << c2 << "\n";
- }
- }
- if (z1 != 0) {
- WORLDtoPC(x1 / z1, y1/z1, pc1);
- WORLDtoPC(x2/z2, y2/z2, pc2);
- }
- else {
- WORLDtoPC(x1,y1,pc1);
- WORLDtoPC(x2,y2,pc2);
- }
-
- MoveTo(DC, pc1.x, pc1.y);
- LineTo(DC, pc2.x,pc2.y);
- }
-
-
- // Transform 3d line to screen coordinates
- void TThreeD::TransformSeg(HDC DC, VECTOR& v1, VECTOR& v2, POINT& pc1, POINT& pc2)
- {
- double x1, y1, z1, x2, y2, z2;
- x1 = (v1.x * A1.x + A1.y * v1.y + A1.z * v1.z + Offsx) * DVal;
- y1 = (v1.x * A2.x + A2.y * v1.y + A2.z * v1.z + Offsy) * DVal;
- z1 = (v1.x * A3.x + A3.y * v1.y + A3.z * v1.z + Offsz);
-
- x2 = (v2.x * A1.x + A1.y * v2.y + A1.z * v2.z + Offsx) * DVal;
- y2 = (v2.x * A2.x + A2.y * v2.y + A2.z * v2.z + Offsy) * DVal;
- z2 = (v2.x * A3.x + A3.y * v2.y + A3.z * v2.z + Offsz);
-
- Clip3D(DC, x1, y1, z1, x2, y2, z2, pc1, pc2);
- }
-
- // Go through the POINTS, and draw the object
- void TThreeD::View(HDC DC)
- {
- long i=1, startOfSide;
- POINT pc1, pc2;
- while (i < Length) {
- startOfSide = i; i++;
- while (Connect[i] != -1) {
- TransformSeg(DC, Points[(long)Connect[i-1]], Points[(long)Connect[i]], pc1, pc2);
- i++;
- }
- // Close off the polygon
-
- // *** CLOSE POLYGON
- // TransformSeg(DC, Points[Connect[i-1]], Points[Connect[startOfSide]], pc1, pc2);
- i++;
- }
- }
-
-
- int TThreeD::Get3dObject()
- {
-
- }
-
-
- // Read a text file
- int TThreeD::Read3DObject(char* filename)
- {
- long i, skipNumColors, r, g, b;
- FILE *infile;
-
- if ((infile = fopen(filename, "r")) == NULL)
- return EM_FILEOPENERROR;
- fscanf(infile, "%ld", &skipNumColors);
- // skip colors
- for (i=1; i<=skipNumColors; i++)
- fscanf(infile,"%ld %ld %ld", &r, &g, &b);
-
- fscanf(infile, "%u %u", &Vertices, &Length);
- if ((Vertices > NUMVERTICES) || (Length > NUMCONNECTIONS))
- return EM_FILETOOBIG;
-
- for (i=1; i<= Vertices; i++) {
- fscanf(infile, "%lf %lf %lf", &Points[i].x, &Points[i].y, &Points[i].z);
- }
-
- for(i=1; i<=Length; i++)
- fscanf(infile, "%u", &Connect[i]);
-
- fclose(infile);
-
- return TRUE;
- }
-