-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
163 lines (154 loc) · 5.71 KB
/
main.js
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
162
163
// Canvas
const canvas = document.getElementById('c1');
const c = canvas.getContext('2d');
// Pixel Dimensions
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
c.translate(canvas.width / 2, canvas.height / 2);
let rx = 0;
let ry = 0;
let rz = 0;
let rw = 0;
// Camera Data
const Camera = {
// Focal Length
focalLength: 35,
wFocalLength: 12,
// Pinhole Location
x: 0, y: 0, z: 0, w: 0,
// Camera Rotation
rotX: 0, rotY: 0, rotZ: 0
};
Camera.z = -(Camera.focalLength ** 2);
Camera.w = -(Camera.wFocalLength ** 2);
// Vertex Object
class Vertex {
constructor(x, y, z, w) {
this.loc = [x / Camera.focalLength, y / Camera.focalLength, z / Camera.focalLength, w / Camera.focalLength];
this.ploc = [];
}
// 3D Rotation Transformation
rotate(xr, yr, zr, wr) {
// 4D Rotation on YW Axis
let yy = this.loc[1];
this.loc[1] = yy * Math.cos(wr) - this.loc[3] * Math.sin(wr);
this.loc[3] = yy * Math.sin(wr) + this.loc[3] * Math.cos(wr);
// Constants
let x = this.loc[0];
let y = this.loc[1];
let z = this.loc[2];
// Rotation Data
let sx = Math.sin(xr);
let sy = Math.sin(yr);
let sz = Math.sin(zr);
let cx = Math.cos(xr);
let cy = Math.cos(yr);
let cz = Math.cos(zr);
// Repeating Parts of Equation
let eq1 = sz * y + cz * x;
let eq2 = cz * y - sz * x;
let eq3 = cy * z + sy * eq1;
// Applying Transformations
this.loc[0] = cy * eq1 - sy * z;
this.loc[1] = sx * eq3 + cx * eq2;
this.loc[2] = cx * eq3 - sx * eq2;
}
// Projected 2D Coordinates
project() {
// Projects 4D to 3D
this.loc[3] -= Camera.w / Camera.wFocalLength;
this.loc[0] = -this.loc[0] / this.loc[3] * Camera.wFocalLength;
this.loc[1] = -this.loc[1] / this.loc[3] * Camera.wFocalLength;
this.loc[2] = -this.loc[2] / this.loc[3] * Camera.wFocalLength;
// Camera Location
let x = this.loc[0] - Camera.x / Camera.focalLength;
let y = this.loc[1] - Camera.y / Camera.focalLength;
let z = this.loc[2] - Camera.z / Camera.focalLength;
// Camera Rotation
let sx = Math.sin(Camera.rotX);
let sy = Math.sin(Camera.rotY);
let sz = Math.sin(Camera.rotZ);
let cx = Math.cos(Camera.rotX);
let cy = Math.cos(Camera.rotY);
let cz = Math.cos(Camera.rotZ);
// Repeating Parts of Equation
let eq1 = sz * y + cz * x;
let eq2 = cz * y - sz * x;
let eq3 = cy * z + sy * eq1;
// Camera Transformations
let dx = cy * eq1 - sy * z;
let dy = sx * eq3 + cx * eq2;
let dz = cx * eq3 - sx * eq2;
// Projection
this.ploc = [Camera.focalLength / dz * dx * Camera.focalLength, Camera.focalLength / dz * dy * Camera.focalLength];
}
}
// Edge Object
class Edge {
constructor(v1, v2) {
this.v1 = v1;
this.v2 = v2;
}
show() {
c.beginPath();
c.moveTo(this.v1.ploc[0], this.v1.ploc[1]);
c.lineTo(this.v2.ploc[0], this.v2.ploc[1]);
c.strokeStyle = 'white';
c.lineWidth = 2;
c.stroke();
}
}
function draw() {
requestAnimationFrame(draw);
c.clearRect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
// Update rotation for multiple axes
rx = (rx - 0.01) % (Math.PI * 2);
ry = (ry - 0.012) % (Math.PI * 2);
rz = (rz - 0.008) % (Math.PI * 2);
rw = (rw - 0.01) % (Math.PI * 2);
let edges = [];
let w = 175;
// Vertices
let v = [];
v[0] = new Vertex(-w / 2, w / 2, -w / 2, w / 2);
v[1] = new Vertex(w / 2, w / 2, -w / 2, w / 2);
v[2] = new Vertex(w / 2, w / 2, w / 2, w / 2);
v[3] = new Vertex(-w / 2, w / 2, w / 2, w / 2);
v[4] = new Vertex(-w / 2, -w / 2, -w / 2, w / 2);
v[5] = new Vertex(w / 2, -w / 2, -w / 2, w / 2);
v[6] = new Vertex(w / 2, -w / 2, w / 2, w / 2);
v[7] = new Vertex(-w / 2, -w / 2, w / 2, w / 2);
v[8] = new Vertex(-w / 2, w / 2, -w / 2, -w / 2);
v[9] = new Vertex(w / 2, w / 2, -w / 2, -w / 2);
v[10] = new Vertex(w / 2, w / 2, w / 2, -w / 2);
v[11] = new Vertex(-w / 2, w / 2, w / 2, -w / 2);
v[12] = new Vertex(-w / 2, -w / 2, -w / 2, -w / 2);
v[13] = new Vertex(w / 2, -w / 2, -w / 2, -w / 2);
v[14] = new Vertex(w / 2, -w / 2, w / 2, -w / 2);
v[15] = new Vertex(-w / 2, -w / 2, w / 2, -w / 2);
// Rotating and Projecting vertices
for (let i = 0; i < v.length; i++) {
// If Rotation is Needed
if (Math.abs(rx) + Math.abs(ry) + Math.abs(rz) + Math.abs(rw) > 0) v[i].rotate(rx, ry, rz, rw);
v[i].project();
}
// Edges
const edgeIndices = [
[0, 1], [1, 2], [2, 3], [3, 0], // Front cube edges
[4, 5], [5, 6], [6, 7], [7, 4], // Back cube edges
[0, 4], [1, 5], [2, 6], [3, 7], // Connecting front and back cubes
[8, 9], [9, 10], [10, 11], [11, 8], // Second front cube edges
[12, 13], [13, 14], [14, 15], [15, 12], // Second back cube edges
[8, 12], [9, 13], [10, 14], [11, 15], // Connecting second front and back cubes
[0, 8], [1, 9], [2, 10], [3, 11], // Connecting first front cube to second front cube
[4, 12], [5, 13], [6, 14], [7, 15] // Connecting first back cube to second back cube
];
for (let i = 0; i < edgeIndices.length; i++) {
edges.push(new Edge(v[edgeIndices[i][0]], v[edgeIndices[i][1]]));
}
// Rendering Edges
for (let i = 0; i < edges.length; i++) {
edges[i].show();
}
}
draw();