-
Notifications
You must be signed in to change notification settings - Fork 0
/
v5.html
81 lines (71 loc) · 3.01 KB
/
v5.html
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
<html>
<body>
<canvas id='canvas' width='800' height='600'
style='border: 1px solid black;'></canvas>
<script>
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let faces = [
// Each element describes a face: [color, [vertices]].
[[230, 25, 75], [[-2, 0, 1], [-2, 0, 2], [-1, 0, 2], [-1, 0, 1]]],
[[60, 180, 75], [[-2, 1, 1], [-2, 1, 2], [-1, 1, 2], [-1, 1, 1]]],
[[255, 225, 25], [[-2, 0, 1], [-2, 0, 2], [-2, 1, 2], [-2, 1, 1]]],
[[67, 99, 216], [[-1, 0, 1], [-1, 0, 2], [-1, 1, 2], [-1, 1, 1]]],
[[245, 130, 49], [[-2, 0, 1], [-1, 0, 1], [-1, 1, 1], [-2, 1, 1]]],
[[145, 30, 180], [[-2, 0, 2], [-1, 0, 2], [-1, 1, 2], [-2, 1, 2]]],
[[70, 240, 240], [[1, 0, 1], [1, 0, 2], [2, 0, 2], [2, 0, 1]]],
[[240, 50, 230], [[1, 1, 1], [1, 1, 2], [2, 1, 2], [2, 1, 1]]],
[[188, 246, 12], [[1, 0, 1], [1, 0, 2], [1, 1, 2], [1, 1, 1]]],
[[250, 190, 190],[[2, 0, 1], [2, 0, 2], [2, 1, 2], [2, 1, 1]]],
[[0, 128, 128], [[1, 0, 1], [2, 0, 1], [2, 1, 1], [1, 1, 1]]],
[[230, 190, 255],[[1, 0, 2], [2, 0, 2], [2, 1, 2], [1, 1, 2]]],
[[154, 99, 36], [[-0.5, 0, 4], [-0.5, 0, 5], [0.5, 0, 5], [0.5, 0, 4]]],
[[0, 0, 0], [[-0.5, 0, 4], [-0.5, 0, 5], [0.0, 1, 4.5]]],
[[128, 0, 0], [[-0.5, 0, 5], [0.5, 0, 5], [0.0, 1, 4.5]]],
[[0, 0, 117], [[0.5, 0, 5], [0.5, 0, 4], [0.0, 1, 4.5]]],
[[128, 128, 128],[[0.5, 0, 4], [-0.5, 0, 4], [0.0, 1, 4.5]]],
];
function distance(a, b) {
return ((a[0] - b[0])**2 + (a[1] - b[1])**2 + (a[2] - b[2])**2) ** 0.5;
}
function centroid(vertices) {
let sum = [0, 0, 0];
for (let vertex of vertices) {
sum[0] += vertex[0];
sum[1] += vertex[1];
sum[2] += vertex[2];
}
let n = vertices.length;
return [sum[0] / n, sum[1] / n, sum[2] / n];
}
// Define a field of view. Only vertices with angles between -fov/2 <--> fov/2
// will be rendered.
let fov = 90;
faces.sort(function (face_a, face_b) {
let vertices_a = face_a[1];
let vertices_b = face_b[1];
return distance(centroid(vertices_b), [0, 0, 0]) -
distance(centroid(vertices_a), [0, 0, 0]);
});
for (let face of faces) {
let [color, vertices] = face;
ctx.fillStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')';
ctx.beginPath();
for (let j = 0; j < vertices.length; j++) {
let vertex = vertices[j];
// Project the 3D vertex to 2D using perspective projection. This is
// similar to orthographic projection, except we divide by the vertex's
// z-coordinate so that the further away the vertex is, the more it
// approaches the camera's direction. Note that we also scale based off
// the fov parameter.
let scale = (canvas.width / 2) / Math.tan(fov/2 * Math.PI / 180);
let x = canvas.width / 2 + vertex[0] / vertex[2] * scale;
let y = canvas.height / 2 - vertex[1] / vertex[2] * scale;
if (j == 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.fill();
}
</script>
</body>
</html>