This repository has been archived by the owner on May 18, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sketch.js
149 lines (120 loc) · 5.66 KB
/
sketch.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
// Simple 3D Renderer - MATH IA SAMPLE CASE
// Essential variables
var objectsInWorld = []
var activeCamera = null
/* Object & function declarations */
class Vector {
/// Create a vector object using regular 3D coordinates
constructor(x, y, z) { this.x = x; this.y = y; this.z = z }
/// Translate the vector by the given change in 3D coordinate position
translateBy(deltaX, deltaY, deltaZ) { this.x += deltaX; this.y += deltaY; this.z += deltaZ }
/// GET the magnitude (modulus) of the vector
magnitude() { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z) }
}
/// Calculate the scalar product of two vectors
function scalarProduct(vectorA, vectorB) {
return vectorA.x * vectorB.x + vectorA.y * vectorB.y + vectorA.z * vectorB.z
}
/// Calculate the angle between two vectors using the arc-cosine of the scalar product
function angleBetweenVectors(vectorA, vectorB) {
var scalarProductOfVectors = scalarProduct(vectorA, vectorB)
var productOfMagnitudes = vectorA.magnitude() * vectorB.magnitude()
return Math.acos(scalarProductOfVectors / productOfMagnitudes)
}
/// A function from my mathematical work
function computeAngle(visionAngle, directionalAngle, complementAngle) {
var numerator = Math.pow(visionAngle, 2) + Math.pow(directionalAngle, 2) - Math.pow(complementAngle, 2)
var denominator = 2 * visionAngle * directionalAngle
return Math.acos(numerator / denominator)
}
/// A function from my mathematical work
function computeRPoint(r0, visionAngle, thetaPoint) {
return r0 * (thetaPoint / visionAngle)
}
/// A function from my mathematical work
function computeScreenX(rPoint, planeAngle) {
return rPoint * Math.cos(planeAngle)
}
/// A function from my mathematical work
function computeScreenY(rPoint, planeAngle) {
return rPoint * Math.sin(planeAngle)
}
class Point extends Vector {
/// Create a vector object representing a single point in the 3D world
constructor(x, y, z) { super(x, y, z) }
/// GET the distance from this point to the camera
distanceToCamera(camera) {
var positionToCamera = new Vector(this.x - camera.x, this.y - camera.y, this.z - camera.z)
return positionToCamera.magnitude()
}
// GET the point's relative positional vector to the camera
getPointRelativeToCamera(camera) {
return new Vector(this.x - camera.x, this.y - camera.y, this.z - camera.z)
}
// GET the angle to the camera's directional vector
getAngleToDirectionalVector(camera) {
var pointRelativeToCamera = this.getPointRelativeToCamera(camera)
var cameraDirection = new Vector(Math.cos(camera.yRotation), 0, Math.sin(camera.yRotation))
return angleBetweenVectors(pointRelativeToCamera, cameraDirection)
}
// GET the angle to the camera's complement vector
getAngleToComplementVector(camera) {
var pointRelativeToCamera = this.getPointRelativeToCamera(camera)
var complementVector = new Vector(Math.cos(camera.yRotation + camera.visionAngle), 0, Math.sin(camera.yRotation + camera.visionAngle))
return angleBetweenVectors(pointRelativeToCamera, complementVector)
}
/// GET the point's translated position on the 2D screen
renderPositionInCamera(camera) {
console.log("")
console.log("(x: " + this.x + ", y: " + this.y + ", z: " + this.z + ")")
var screenDiagonalRadius = 400
var angleToDirectionalVector = this.getAngleToDirectionalVector(camera)
var angleToComplementVector = this.getAngleToComplementVector(camera)
console.log("th: " + angleToDirectionalVector + ", thP: " + angleToComplementVector)
var planeAngle = computeAngle(camera.visionAngle, angleToDirectionalVector, angleToComplementVector)
var rPoint = computeRPoint(screenDiagonalRadius, camera.visionAngle, angleToDirectionalVector)
console.log("A: " + planeAngle + ", rPoint: " + rPoint)
var screenX = computeScreenX(rPoint, planeAngle)
var screenY = computeScreenY(rPoint, planeAngle)
console.log("(" + screenX + ", " + screenY + ")")
// Test which of the two intersections to use (inverted because p5.js coordinates are inverted from Cartesian)
if (this.y > camera.y) {
// above midline
console.log("+ (POSITIVE)")
return [screenX + screenDiagonalRadius / 2, -screenY + screenDiagonalRadius / 2]
} else {
// below midline
console.log("- (NEGATIVE)")
return [screenX + screenDiagonalRadius / 2, screenY + screenDiagonalRadius / 2]
}
}
}
class Camera extends Vector {
/// Create a vector object representing a camera, with vision range and starting y-rotation provided
constructor(x, y, z, visionAngle, yRotation) {
super(x, y, z); this.visionAngle = visionAngle; this.yRotation = yRotation
}
/// Render all items in a 3D world onto the 2D screen through this camera
renderItemsInWorld(world) {
var thisCamera = this
world.sort(function (a, b) { return a.distanceToCamera(thisCamera) < b.distanceToCamera(thisCamera) })
for (var thisItem of world) { thisItem.renderInCamera(this) }
}
/// Rotate the camera's y-rotation by a certain angle
rotateYBy(rotation) { this.yRotation += rotation; this.yRotation %= Math.PI }
}
/* Main */
activeCamera = new Camera(0, 0, 0, Math.PI / 4, Math.PI / 4)
objectsInWorld = [
new Point(1, 0.8, 1),
new Point(1, 0.8, 2),
new Point(2, 0.8, 1),
new Point(2, 0.8, 2),
new Point(1, -0.2, 1),
new Point(1, -0.2, 2),
new Point(2, -0.2, 1),
new Point(2, -0.2, 2),
]
for (var currentPoint of objectsInWorld) {
currentPoint.renderPositionInCamera(activeCamera)
}