-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathGraphics.cpp
161 lines (127 loc) · 4.24 KB
/
Graphics.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "Graphics.h"
#include "Point.h"
#include "Polygon.h"
#include "Matrix.h"
#include <vector>
#include <cstdlib> // for abs()
#include <cstdio>
using namespace std;
Point Graphics::R(0,0,-800);
Vector Graphics::X_VEL(500,0,0);
Vector Graphics::Y_VEL(0,500,0);
Vector Graphics::Z_VEL(0,0,500);
Graphics::Graphics(vector<Polygon> polygons, int FPS) {
this->polygons = polygons;
this->FPS = FPS;
}
void Graphics::addPolygons(std::vector<Polygon> newPolygons) {
for (Polygon p : newPolygons) {
this->polygons.push_back(p);
// Initialize rotatedPolygons
this->rotatedPolygons.push_back(p);
}
}
Point Graphics::intersectXY(const Point& p, const Point& q) {
double t = (double) p.z / (p.z - q.z);
Vector pq(p,q);
Point ret = p + t * pq;
ret.z = 0;
return ret;
}
Point Graphics::project(const Point& p) {
if (p.z < 0) {
fprintf(stderr, "Error: Trying to project an invalid point.\n");
}
return Graphics::intersectXY(R, p);
}
Polygon Graphics::project(const Polygon& polygon) {
vector<Point> newVertices;
for (Point p : polygon.vertices) {
newVertices.push_back(Graphics::project(p));
}
return Polygon(newVertices);
}
bool Graphics::isInView(const Point& p) {
return p.z >= 0;
}
// true if all four of the polygon's points are in view
bool Graphics::isInView(const Polygon& polygon) {
for (int i = 0; i < polygon.vertices.size(); ++i) {
if (!Graphics::isInView(polygon.vertices[i]));
return false;
}
return true;
}
void Graphics::moveLeft(double angleX) {
for (Polygon& p : polygons)
p += Matrix::rotateY(X_VEL/FPS, -angleX);
}
void Graphics::moveRight(double angleX) {
for (Polygon& p : polygons)
p -= Matrix::rotateY(X_VEL/FPS, -angleX);
}
void Graphics::moveForward(double angleX, double angleY) {
for (Polygon& p : polygons)
p -= Matrix::rotateX(Matrix::rotateY(Z_VEL/FPS, -angleX), angleY);
}
void Graphics::moveBackward(double angleX, double angleY) {
for (Polygon& p : polygons)
p += Matrix::rotateX(Matrix::rotateY(Z_VEL/FPS, -angleX), angleY);
}
void Graphics::moveUp() {
for (Polygon& p : polygons)
// Here we add because the positive y-axis is downward
p += Y_VEL/FPS;
}
void Graphics::moveDown() {
for (Polygon& p : polygons)
// Here we subtract because the positive y-axis is downward
p -= Y_VEL/FPS;
}
void Graphics::turn(double angleX, double angleY) {
// Here, Matrix.rotateY() rotates about the y-axis.
// Hence, angleX is passed to rotateY() (left-right view rotation).
// Similarly, Matrix.rotateX() rotates about the x-axis.
// So angleY is passed to rotateX() (up-down view rotation)
for (int i = 0; i < polygons.size(); ++i)
rotatedPolygons[i] = Matrix::rotateX(Matrix::rotateY(polygons[i], angleX), angleY);
}
void Graphics::render(std::vector<Polygon>& screenPolygons) {
screenPolygons = rotatedPolygons;
clipToView(screenPolygons);
// Project the polygons onto the x-y plane
for (int i = 0; i < screenPolygons.size(); ++i)
screenPolygons[i] = Graphics::project(screenPolygons[i]);
}
// Clip points to be above the x-y plane (positive z-coordinate)
void Graphics::clipToView(vector<Polygon> &polygons) {
for (int i = 0; i < polygons.size(); ++i) {
Polygon currPoly = polygons[i];
// If one or more of the vertices are below the x-y plane
// clip the polygon to have a positive z-coordinate
if (!Graphics::isInView(currPoly)) {
// All vertices of newPoly will have positive z-coordinate
Polygon newPoly;
// Number of vertices of the current polygon
int numVertices = currPoly.vertices.size();
// Loop over the current polgon's vertices
for (int j = 0; j < numVertices; ++j) {
Point currPoint = currPoly.vertices[j];
Point nextPoint = currPoly.vertices[(j+1) % numVertices];
bool currPointInView = Graphics::isInView(currPoint);
bool nextPointInView = Graphics::isInView(nextPoint);
if (currPointInView) {
newPoly.vertices.push_back(currPoint);
}
// If the points lie across the x-y plane
if (currPointInView ^ nextPointInView) {
Point intersectionPoint = Graphics::intersectXY(currPoint, nextPoint);
// Add the intersectionPoint (which is on the x-y plane) to the new polygon
newPoly.vertices.push_back(intersectionPoint);
}
}
// Replace current polygon with clipped polygon
polygons[i] = newPoly;
}
}
}