p5 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{src → dist}/accessibility/color_namer.js +48 -3
- package/{src → dist}/accessibility/describe.js +12 -2
- package/{src → dist}/accessibility/gridOutput.js +2 -2
- package/dist/accessibility/index.js +60 -0
- package/{src → dist}/accessibility/outputs.js +23 -2
- package/{src → dist}/accessibility/textOutput.js +2 -2
- package/dist/app.js +120 -0
- package/{src → dist}/color/color_conversion.js +48 -10
- package/{src → dist}/color/color_spaces/hsb.js +3 -1
- package/dist/color/creating_reading.js +3 -0
- package/dist/color/index.js +13 -0
- package/dist/color/p5.Color.culori.js +1 -0
- package/dist/color/p5.Color.js +3 -0
- package/{src → dist}/color/setting.js +9 -6
- package/{src/core/constants.js → dist/constants-tYr0tCl8.js} +284 -132
- package/{src → dist}/core/States.js +3 -1
- package/dist/core/constants.js +1 -0
- package/{src → dist}/core/environment.js +12 -10
- package/{src → dist}/core/friendly_errors/browser_errors.js +1 -1
- package/{src → dist}/core/friendly_errors/fes_core.js +14 -44
- package/{src → dist}/core/friendly_errors/file_errors.js +6 -3
- package/dist/core/friendly_errors/index.js +23 -0
- package/dist/core/friendly_errors/param_validator.js +5421 -0
- package/{src → dist}/core/friendly_errors/sketch_reader.js +50 -4
- package/{src → dist}/core/friendly_errors/sketch_verifier.js +6 -6
- package/{src → dist}/core/friendly_errors/stacktrace.js +3 -5
- package/{src → dist}/core/friendly_errors/validate_params.js +50 -41
- package/{src → dist}/core/helpers.js +9 -6
- package/dist/core/init.js +105 -0
- package/dist/core/internationalization.js +302 -0
- package/dist/core/legacy.js +73 -0
- package/dist/core/main.js +44 -0
- package/dist/core/noop.js +3 -0
- package/dist/core/p5.Graphics.js +40 -0
- package/dist/core/p5.Renderer.js +11 -0
- package/dist/core/p5.Renderer2D.js +44 -0
- package/dist/core/reference.js +1 -0
- package/dist/core/rendering.js +40 -0
- package/{src → dist}/core/structure.js +3 -3
- package/{src → dist}/core/transform.js +2 -2
- package/{src/color/creating_reading.js → dist/creating_reading-Cr8L2Jnm.js} +841 -13
- package/{src → dist}/data/index.js +3 -1
- package/{src → dist}/data/local_storage.js +2 -8
- package/{src → dist}/dom/dom.js +19 -13
- package/dist/dom/index.js +18 -0
- package/{src → dist}/dom/p5.Element.js +14 -12
- package/{src → dist}/dom/p5.File.js +4 -4
- package/{src → dist}/dom/p5.MediaElement.js +10 -4
- package/{src → dist}/events/acceleration.js +26 -26
- package/{src → dist}/events/index.js +3 -1
- package/{src → dist}/events/keyboard.js +14 -12
- package/{src → dist}/events/pointer.js +16 -17
- package/dist/image/const.js +9 -0
- package/{src → dist}/image/filterRenderer2D.js +57 -37
- package/{src → dist}/image/filters.js +1 -3
- package/dist/image/image.js +40 -0
- package/dist/image/index.js +51 -0
- package/dist/image/loading_displaying.js +40 -0
- package/dist/image/p5.Image.js +11 -0
- package/{src → dist}/image/pixels.js +5 -3
- package/{src → dist}/io/csv.js +72 -70
- package/dist/io/files.js +40 -0
- package/dist/io/index.js +51 -0
- package/{src → dist}/io/p5.Table.js +6 -6
- package/{src → dist}/io/p5.TableRow.js +5 -6
- package/{src → dist}/io/p5.XML.js +2 -5
- package/{src → dist}/io/utilities.js +1 -1
- package/{src/core/p5.Renderer2D.js → dist/main-CAxvgiOV.js} +738 -57
- package/{src → dist}/math/Matrices/Matrix.js +10 -8
- package/{src → dist}/math/Matrices/MatrixInterface.js +5 -3
- package/{src → dist}/math/Matrices/MatrixNumjs.js +12 -26
- package/{src → dist}/math/calculation.js +2 -2
- package/{src → dist}/math/index.js +6 -3
- package/{src → dist}/math/math.js +3 -3
- package/{src → dist}/math/noise.js +2 -2
- package/{src → dist}/math/p5.Matrix.js +7 -4
- package/{src → dist}/math/p5.Vector.js +6 -6
- package/{src → dist}/math/random.js +2 -2
- package/{src → dist}/math/trigonometry.js +16 -15
- package/{src/image/p5.Image.js → dist/p5.Renderer-Swjl9HQO.js} +393 -22
- package/dist/rendering-B5TRR7aY.js +24960 -0
- package/{src → dist}/shape/2d_primitives.js +18 -17
- package/{src → dist}/shape/attributes.js +18 -17
- package/{src → dist}/shape/curves.js +2 -2
- package/{src → dist}/shape/custom_shapes.js +44 -64
- package/{src → dist}/shape/index.js +10 -2
- package/{src → dist}/shape/vertex.js +2 -3
- package/dist/type/index.js +25 -0
- package/{src → dist}/type/lib/Typr.js +76 -94
- package/{src → dist}/type/p5.Font.js +37 -63
- package/{src → dist}/type/textCore.js +35 -58
- package/{src → dist}/type/unicodeRanges.js +3 -1
- package/{src → dist}/utilities/conversion.js +2 -2
- package/{src → dist}/utilities/index.js +3 -1
- package/{src → dist}/utilities/time_date.js +6 -7
- package/{src → dist}/utilities/utility_functions.js +2 -2
- package/dist/webgl/3d_primitives.js +40 -0
- package/{src → dist}/webgl/GeometryBufferCache.js +3 -1
- package/{src → dist}/webgl/GeometryBuilder.js +12 -8
- package/{src → dist}/webgl/ShaderGenerator.js +79 -82
- package/{src → dist}/webgl/ShapeBuilder.js +26 -23
- package/dist/webgl/index.js +76 -0
- package/{src → dist}/webgl/interaction.js +7 -6
- package/dist/webgl/light.js +40 -0
- package/{src → dist}/webgl/loading.js +45 -12
- package/dist/webgl/material.js +40 -0
- package/dist/webgl/p5.Camera.js +40 -0
- package/{src → dist}/webgl/p5.DataArray.js +3 -5
- package/dist/webgl/p5.Framebuffer.js +40 -0
- package/{src → dist}/webgl/p5.Geometry.js +12 -15
- package/{src → dist}/webgl/p5.Quat.js +5 -4
- package/{src → dist}/webgl/p5.RenderBuffer.js +2 -3
- package/dist/webgl/p5.RendererGL.js +40 -0
- package/dist/webgl/p5.Shader.js +40 -0
- package/dist/webgl/p5.Texture.js +40 -0
- package/{src → dist}/webgl/text.js +78 -38
- package/lib/p5.esm.js +296 -194
- package/lib/p5.js +296 -194
- package/lib/p5.min.js +1 -1
- package/package.json +17 -17
- package/translations/dev.js +6 -6
- package/translations/index.js +1 -1
- package/types/accessibility/color_namer.d.ts +8 -0
- package/types/accessibility/describe.d.ts +184 -0
- package/types/accessibility/gridOutput.d.ts +8 -0
- package/types/accessibility/outputs.d.ts +235 -0
- package/types/accessibility/textOutput.d.ts +8 -0
- package/types/color/color_conversion.d.ts +47 -0
- package/types/color/creating_reading.d.ts +1348 -0
- package/types/color/p5.Color.d.ts +1070 -0
- package/types/color/setting.d.ts +2085 -0
- package/types/core/constants.d.ts +341 -0
- package/types/core/environment.d.ts +668 -0
- package/types/core/friendly_errors/fes_core.d.ts +8 -0
- package/types/core/friendly_errors/file_errors.d.ts +8 -0
- package/types/core/friendly_errors/param_validator.d.ts +30 -0
- package/types/core/friendly_errors/sketch_reader.d.ts +8 -0
- package/types/core/friendly_errors/stacktrace.d.ts +11 -0
- package/types/core/friendly_errors/validate_params.d.ts +8 -0
- package/types/core/helpers.d.ts +8 -0
- package/types/core/legacy.d.ts +8 -0
- package/types/core/main.d.ts +5996 -0
- package/types/core/p5.Graphics.d.ts +484 -0
- package/types/core/p5.Renderer.d.ts +14 -0
- package/types/core/reference.d.ts +8 -0
- package/types/core/rendering.d.ts +481 -0
- package/types/core/structure.d.ts +492 -0
- package/types/core/transform.d.ts +1638 -0
- package/types/data/local_storage.d.ts +323 -0
- package/types/dom/dom.d.ts +1295 -0
- package/types/dom/p5.Element.d.ts +2011 -0
- package/types/dom/p5.File.d.ts +13 -0
- package/types/dom/p5.MediaElement.d.ts +1249 -0
- package/types/events/acceleration.d.ts +193 -0
- package/types/events/keyboard.d.ts +499 -0
- package/types/events/pointer.d.ts +782 -0
- package/types/global.d.ts +5542 -0
- package/types/image/filterRenderer2D.d.ts +54 -0
- package/types/image/image.d.ts +326 -0
- package/types/image/loading_displaying.d.ts +580 -0
- package/types/image/p5.Image.d.ts +5882 -0
- package/types/image/pixels.d.ts +832 -0
- package/types/io/files.d.ts +1447 -0
- package/types/io/p5.Table.d.ts +1247 -0
- package/types/io/p5.TableRow.d.ts +343 -0
- package/types/io/p5.XML.d.ts +1188 -0
- package/types/math/Matrices/Matrix.d.ts +1029 -0
- package/types/math/Matrices/MatrixNumjs.d.ts +8 -0
- package/types/math/calculation.d.ts +923 -0
- package/types/math/math.d.ts +90 -0
- package/types/math/noise.d.ts +311 -0
- package/types/math/p5.Matrix.d.ts +8 -0
- package/types/math/p5.Vector.d.ts +3416 -0
- package/types/math/random.d.ts +267 -0
- package/types/math/trigonometry.d.ts +663 -0
- package/types/p5.d.ts +6663 -0
- package/types/shape/2d_primitives.d.ts +1033 -0
- package/types/shape/attributes.d.ts +466 -0
- package/types/shape/curves.d.ts +740 -0
- package/types/shape/custom_shapes.d.ts +888 -0
- package/types/shape/vertex.d.ts +1141 -0
- package/types/type/p5.Font.d.ts +575 -0
- package/types/type/textCore.d.ts +1198 -0
- package/types/utilities/conversion.d.ts +894 -0
- package/types/utilities/time_date.d.ts +295 -0
- package/types/utilities/utility_functions.d.ts +587 -0
- package/types/webgl/3d_primitives.d.ts +1432 -0
- package/types/webgl/ShaderGenerator.d.ts +8 -0
- package/types/webgl/interaction.d.ts +371 -0
- package/types/webgl/light.d.ts +1184 -0
- package/types/webgl/loading.d.ts +481 -0
- package/types/webgl/material.d.ts +2656 -0
- package/types/webgl/p5.Camera.d.ts +3023 -0
- package/types/webgl/p5.DataArray.d.ts +61 -0
- package/types/webgl/p5.Framebuffer.d.ts +760 -0
- package/types/webgl/p5.Geometry.d.ts +1191 -0
- package/types/webgl/p5.Quat.d.ts +45 -0
- package/types/webgl/p5.RendererGL.d.ts +234 -0
- package/types/webgl/p5.Shader.d.ts +660 -0
- package/types/webgl/p5.Texture.d.ts +61 -0
- package/types/webgl/text.d.ts +74 -0
- package/src/README.md +0 -27
- package/src/accessibility/index.js +0 -13
- package/src/app.js +0 -61
- package/src/color/index.js +0 -9
- package/src/color/p5.Color.culori.js +0 -66
- package/src/color/p5.Color.js +0 -851
- package/src/core/README.md +0 -91
- package/src/core/friendly_errors/index.js +0 -13
- package/src/core/friendly_errors/param_validator.js +0 -561
- package/src/core/init.js +0 -58
- package/src/core/internationalization.js +0 -195
- package/src/core/legacy.js +0 -29
- package/src/core/main.js +0 -689
- package/src/core/noop.js +0 -1
- package/src/core/p5.Graphics.js +0 -696
- package/src/core/p5.Renderer.js +0 -408
- package/src/core/reference.js +0 -2060
- package/src/core/rendering.js +0 -697
- package/src/dom/index.js +0 -11
- package/src/image/const.js +0 -6
- package/src/image/image.js +0 -731
- package/src/image/index.js +0 -15
- package/src/image/loading_displaying.js +0 -1431
- package/src/io/files.js +0 -2210
- package/src/io/index.js +0 -11
- package/src/math/README.md +0 -40
- package/src/type/index.js +0 -9
- package/src/webgl/3d_primitives.js +0 -2741
- package/src/webgl/index.js +0 -37
- package/src/webgl/light.js +0 -1851
- package/src/webgl/material.js +0 -3854
- package/src/webgl/p5.Camera.js +0 -4010
- package/src/webgl/p5.Framebuffer.js +0 -1865
- package/src/webgl/p5.RendererGL.js +0 -2867
- package/src/webgl/p5.Shader.js +0 -1505
- package/src/webgl/p5.Texture.js +0 -541
- package/src/webgl/shaders/basic.frag +0 -6
- package/src/webgl/shaders/filters/base.frag +0 -22
- package/src/webgl/shaders/filters/base.vert +0 -19
- package/src/webgl/shaders/filters/blur.frag +0 -60
- package/src/webgl/shaders/filters/default.vert +0 -18
- package/src/webgl/shaders/filters/dilate.frag +0 -39
- package/src/webgl/shaders/filters/erode.frag +0 -39
- package/src/webgl/shaders/filters/gray.frag +0 -16
- package/src/webgl/shaders/filters/invert.frag +0 -15
- package/src/webgl/shaders/filters/opaque.frag +0 -12
- package/src/webgl/shaders/filters/posterize.frag +0 -29
- package/src/webgl/shaders/filters/threshold.frag +0 -23
- package/src/webgl/shaders/font.frag +0 -216
- package/src/webgl/shaders/font.vert +0 -44
- package/src/webgl/shaders/imageLight.vert +0 -33
- package/src/webgl/shaders/imageLightDiffused.frag +0 -82
- package/src/webgl/shaders/imageLightSpecular.frag +0 -134
- package/src/webgl/shaders/light.vert +0 -37
- package/src/webgl/shaders/light_texture.frag +0 -26
- package/src/webgl/shaders/lighting.glsl +0 -227
- package/src/webgl/shaders/line.frag +0 -74
- package/src/webgl/shaders/line.vert +0 -294
- package/src/webgl/shaders/normal.frag +0 -6
- package/src/webgl/shaders/normal.vert +0 -72
- package/src/webgl/shaders/phong.frag +0 -84
- package/src/webgl/shaders/phong.vert +0 -87
- package/src/webgl/shaders/point.frag +0 -29
- package/src/webgl/shaders/point.vert +0 -19
- package/src/webgl/shaders/sphereMapping.frag +0 -26
- package/src/webgl/shaders/webgl2Compatibility.glsl +0 -34
package/src/webgl/p5.Camera.js
DELETED
|
@@ -1,4010 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module 3D
|
|
3
|
-
* @submodule Camera
|
|
4
|
-
* @requires core
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Matrix } from '../math/p5.Matrix';
|
|
8
|
-
import { Vector } from '../math/p5.Vector';
|
|
9
|
-
import { Quat } from './p5.Quat';
|
|
10
|
-
import { RendererGL } from './p5.RendererGL';
|
|
11
|
-
|
|
12
|
-
class Camera {
|
|
13
|
-
constructor(renderer) {
|
|
14
|
-
this._renderer = renderer;
|
|
15
|
-
|
|
16
|
-
this.cameraType = 'default';
|
|
17
|
-
this.useLinePerspective = true;
|
|
18
|
-
this.cameraMatrix = new Matrix(4);
|
|
19
|
-
this.projMatrix = new Matrix(4);
|
|
20
|
-
this.yScale = 1;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* The camera’s x-coordinate.
|
|
24
|
-
*
|
|
25
|
-
* By default, the camera’s x-coordinate is set to 0 in "world" space.
|
|
26
|
-
*
|
|
27
|
-
* @property {Number} eyeX
|
|
28
|
-
* @readonly
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* <div>
|
|
32
|
-
* <code>
|
|
33
|
-
* let cam;
|
|
34
|
-
* let font;
|
|
35
|
-
*
|
|
36
|
-
* async function setup() {
|
|
37
|
-
* // Load a font and create a p5.Font object.
|
|
38
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
39
|
-
* createCanvas(100, 100, WEBGL);
|
|
40
|
-
*
|
|
41
|
-
* // Create a p5.Camera object.
|
|
42
|
-
* cam = createCamera();
|
|
43
|
-
*
|
|
44
|
-
* // Set the camera
|
|
45
|
-
* setCamera(cam);
|
|
46
|
-
*
|
|
47
|
-
* // Place the camera at the top-center.
|
|
48
|
-
* cam.setPosition(0, -400, 800);
|
|
49
|
-
*
|
|
50
|
-
* // Point the camera at the origin.
|
|
51
|
-
* cam.lookAt(0, 0, 0);
|
|
52
|
-
*
|
|
53
|
-
* describe(
|
|
54
|
-
* 'A white cube on a gray background. The text "eyeX: 0" is written in black beneath it.'
|
|
55
|
-
* );
|
|
56
|
-
* }
|
|
57
|
-
*
|
|
58
|
-
* function draw() {
|
|
59
|
-
* background(200);
|
|
60
|
-
*
|
|
61
|
-
* // Style the box.
|
|
62
|
-
* fill(255);
|
|
63
|
-
*
|
|
64
|
-
* // Draw the box.
|
|
65
|
-
* box();
|
|
66
|
-
*
|
|
67
|
-
* // Style the text.
|
|
68
|
-
* textAlign(CENTER);
|
|
69
|
-
* textSize(16);
|
|
70
|
-
* textFont(font);
|
|
71
|
-
* fill(0);
|
|
72
|
-
*
|
|
73
|
-
* // Display the value of eyeX, rounded to the nearest integer.
|
|
74
|
-
* text(`eyeX: ${round(cam.eyeX)}`, 0, 55);
|
|
75
|
-
* }
|
|
76
|
-
* </code>
|
|
77
|
-
* </div>
|
|
78
|
-
*
|
|
79
|
-
* <div>
|
|
80
|
-
* <code>
|
|
81
|
-
* let cam;
|
|
82
|
-
* let font;
|
|
83
|
-
*
|
|
84
|
-
* async function setup() {
|
|
85
|
-
* // Load a font and create a p5.Font object.
|
|
86
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
87
|
-
* createCanvas(100, 100, WEBGL);
|
|
88
|
-
*
|
|
89
|
-
* // Create a p5.Camera object.
|
|
90
|
-
* cam = createCamera();
|
|
91
|
-
*
|
|
92
|
-
* // Set the camera
|
|
93
|
-
* setCamera(cam);
|
|
94
|
-
*
|
|
95
|
-
* // Place the camera at the top-center.
|
|
96
|
-
* cam.setPosition(0, -400, 800);
|
|
97
|
-
*
|
|
98
|
-
* // Point the camera at the origin.
|
|
99
|
-
* cam.lookAt(0, 0, 0);
|
|
100
|
-
*
|
|
101
|
-
* describe(
|
|
102
|
-
* 'A white cube on a gray background. The cube appears to move left and right as the camera moves. The text "eyeX: X" is written in black beneath the cube. X oscillates between -25 and 25.'
|
|
103
|
-
* );
|
|
104
|
-
* }
|
|
105
|
-
*
|
|
106
|
-
* function draw() {
|
|
107
|
-
* background(200);
|
|
108
|
-
*
|
|
109
|
-
* // Style the box.
|
|
110
|
-
* fill(255);
|
|
111
|
-
*
|
|
112
|
-
* // Draw the box.
|
|
113
|
-
* box();
|
|
114
|
-
*
|
|
115
|
-
* // Style the text.
|
|
116
|
-
* textAlign(CENTER);
|
|
117
|
-
* textSize(16);
|
|
118
|
-
* textFont(font);
|
|
119
|
-
* fill(0);
|
|
120
|
-
*
|
|
121
|
-
* // Calculate the new x-coordinate.
|
|
122
|
-
* let x = 25 * sin(frameCount * 0.01);
|
|
123
|
-
*
|
|
124
|
-
* // Set the camera's position.
|
|
125
|
-
* cam.setPosition(x, -400, 800);
|
|
126
|
-
*
|
|
127
|
-
* // Display the value of eyeX, rounded to the nearest integer.
|
|
128
|
-
* text(`eyeX: ${round(cam.eyeX)}`, 0, 55);
|
|
129
|
-
* }
|
|
130
|
-
* </code>
|
|
131
|
-
* </div>
|
|
132
|
-
*/
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* The camera’s y-coordinate.
|
|
136
|
-
*
|
|
137
|
-
* By default, the camera’s y-coordinate is set to 0 in "world" space.
|
|
138
|
-
*
|
|
139
|
-
* @property {Number} eyeY
|
|
140
|
-
* @readonly
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* <div>
|
|
144
|
-
* <code>
|
|
145
|
-
* let cam;
|
|
146
|
-
* let font;
|
|
147
|
-
*
|
|
148
|
-
* async function setup() {
|
|
149
|
-
* // Load a font and create a p5.Font object.
|
|
150
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
151
|
-
* createCanvas(100, 100, WEBGL);
|
|
152
|
-
*
|
|
153
|
-
* // Create a p5.Camera object.
|
|
154
|
-
* cam = createCamera();
|
|
155
|
-
*
|
|
156
|
-
* // Place the camera at the top-center.
|
|
157
|
-
* cam.setPosition(0, -400, 800);
|
|
158
|
-
*
|
|
159
|
-
* // Point the camera at the origin.
|
|
160
|
-
* cam.lookAt(0, 0, 0);
|
|
161
|
-
*
|
|
162
|
-
* // Set the camera.
|
|
163
|
-
* setCamera(cam);
|
|
164
|
-
*
|
|
165
|
-
* describe(
|
|
166
|
-
* 'A white cube on a gray background. The text "eyeY: -400" is written in black beneath it.'
|
|
167
|
-
* );
|
|
168
|
-
* }
|
|
169
|
-
*
|
|
170
|
-
* function draw() {
|
|
171
|
-
* background(200);
|
|
172
|
-
*
|
|
173
|
-
* // Style the box.
|
|
174
|
-
* fill(255);
|
|
175
|
-
*
|
|
176
|
-
* // Draw the box.
|
|
177
|
-
* box();
|
|
178
|
-
*
|
|
179
|
-
* // Style the text.
|
|
180
|
-
* textAlign(CENTER);
|
|
181
|
-
* textSize(16);
|
|
182
|
-
* textFont(font);
|
|
183
|
-
* fill(0);
|
|
184
|
-
*
|
|
185
|
-
* // Display the value of eyeY, rounded to the nearest integer.
|
|
186
|
-
* text(`eyeY: ${round(cam.eyeY)}`, 0, 55);
|
|
187
|
-
* }
|
|
188
|
-
* </code>
|
|
189
|
-
* </div>
|
|
190
|
-
*
|
|
191
|
-
* <div>
|
|
192
|
-
* <code>
|
|
193
|
-
* let cam;
|
|
194
|
-
* let font;
|
|
195
|
-
*
|
|
196
|
-
* async function setup() {
|
|
197
|
-
* // Load a font and create a p5.Font object.
|
|
198
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
199
|
-
* createCanvas(100, 100, WEBGL);
|
|
200
|
-
*
|
|
201
|
-
* // Create a p5.Camera object.
|
|
202
|
-
* cam = createCamera();
|
|
203
|
-
*
|
|
204
|
-
* // Set the camera
|
|
205
|
-
* setCamera(cam);
|
|
206
|
-
*
|
|
207
|
-
* // Place the camera at the top-center.
|
|
208
|
-
* cam.setPosition(0, -400, 800);
|
|
209
|
-
*
|
|
210
|
-
* // Point the camera at the origin.
|
|
211
|
-
* cam.lookAt(0, 0, 0);
|
|
212
|
-
*
|
|
213
|
-
* describe(
|
|
214
|
-
* 'A white cube on a gray background. The cube appears to move up and down as the camera moves. The text "eyeY: Y" is written in black beneath the cube. Y oscillates between -374 and -425.'
|
|
215
|
-
* );
|
|
216
|
-
* }
|
|
217
|
-
*
|
|
218
|
-
* function draw() {
|
|
219
|
-
* background(200);
|
|
220
|
-
*
|
|
221
|
-
* // Style the box.
|
|
222
|
-
* fill(255);
|
|
223
|
-
*
|
|
224
|
-
* // Draw the box.
|
|
225
|
-
* box();
|
|
226
|
-
*
|
|
227
|
-
* // Style the text.
|
|
228
|
-
* textAlign(CENTER);
|
|
229
|
-
* textSize(16);
|
|
230
|
-
* textFont(font);
|
|
231
|
-
* fill(0);
|
|
232
|
-
*
|
|
233
|
-
* // Calculate the new y-coordinate.
|
|
234
|
-
* let y = 25 * sin(frameCount * 0.01) - 400;
|
|
235
|
-
*
|
|
236
|
-
* // Set the camera's position.
|
|
237
|
-
* cam.setPosition(0, y, 800);
|
|
238
|
-
*
|
|
239
|
-
* // Display the value of eyeY, rounded to the nearest integer.
|
|
240
|
-
* text(`eyeY: ${round(cam.eyeY)}`, 0, 55);
|
|
241
|
-
* }
|
|
242
|
-
* </code>
|
|
243
|
-
* </div>
|
|
244
|
-
*/
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* The camera’s z-coordinate.
|
|
248
|
-
*
|
|
249
|
-
* By default, the camera’s z-coordinate is set to 800 in "world" space.
|
|
250
|
-
*
|
|
251
|
-
* @property {Number} eyeZ
|
|
252
|
-
* @readonly
|
|
253
|
-
*
|
|
254
|
-
* @example
|
|
255
|
-
* <div>
|
|
256
|
-
* <code>
|
|
257
|
-
* let cam;
|
|
258
|
-
* let font;
|
|
259
|
-
*
|
|
260
|
-
* async function setup() {
|
|
261
|
-
* // Load a font and create a p5.Font object.
|
|
262
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
263
|
-
* createCanvas(100, 100, WEBGL);
|
|
264
|
-
*
|
|
265
|
-
* // Create a p5.Camera object.
|
|
266
|
-
* cam = createCamera();
|
|
267
|
-
*
|
|
268
|
-
* // Set the camera
|
|
269
|
-
* setCamera(cam);
|
|
270
|
-
*
|
|
271
|
-
* // Place the camera at the top-center.
|
|
272
|
-
* cam.setPosition(0, -400, 800);
|
|
273
|
-
*
|
|
274
|
-
* // Point the camera at the origin.
|
|
275
|
-
* cam.lookAt(0, 0, 0);
|
|
276
|
-
*
|
|
277
|
-
* describe(
|
|
278
|
-
* 'A white cube on a gray background. The text "eyeZ: 800" is written in black beneath it.'
|
|
279
|
-
* );
|
|
280
|
-
* }
|
|
281
|
-
*
|
|
282
|
-
* function draw() {
|
|
283
|
-
* background(200);
|
|
284
|
-
*
|
|
285
|
-
* // Style the box.
|
|
286
|
-
* fill(255);
|
|
287
|
-
*
|
|
288
|
-
* // Draw the box.
|
|
289
|
-
* box();
|
|
290
|
-
*
|
|
291
|
-
* // Style the text.
|
|
292
|
-
* textAlign(CENTER);
|
|
293
|
-
* textSize(16);
|
|
294
|
-
* textFont(font);
|
|
295
|
-
* fill(0);
|
|
296
|
-
*
|
|
297
|
-
* // Display the value of eyeZ, rounded to the nearest integer.
|
|
298
|
-
* text(`eyeZ: ${round(cam.eyeZ)}`, 0, 55);
|
|
299
|
-
* }
|
|
300
|
-
* </code>
|
|
301
|
-
* </div>
|
|
302
|
-
*
|
|
303
|
-
* <div>
|
|
304
|
-
* <code>
|
|
305
|
-
* let cam;
|
|
306
|
-
* let font;
|
|
307
|
-
*
|
|
308
|
-
* async function setup() {
|
|
309
|
-
* // Load a font and create a p5.Font object.
|
|
310
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
311
|
-
* createCanvas(100, 100, WEBGL);
|
|
312
|
-
*
|
|
313
|
-
* // Create a p5.Camera object.
|
|
314
|
-
* cam = createCamera();
|
|
315
|
-
*
|
|
316
|
-
* // Set the camera
|
|
317
|
-
* setCamera(cam);
|
|
318
|
-
*
|
|
319
|
-
* // Place the camera at the top-center.
|
|
320
|
-
* cam.setPosition(0, -400, 800);
|
|
321
|
-
*
|
|
322
|
-
* // Point the camera at the origin.
|
|
323
|
-
* cam.lookAt(0, 0, 0);
|
|
324
|
-
*
|
|
325
|
-
* describe(
|
|
326
|
-
* 'A white cube on a gray background. The cube appears to move forward and back as the camera moves. The text "eyeZ: Z" is written in black beneath the cube. Z oscillates between 700 and 900.'
|
|
327
|
-
* );
|
|
328
|
-
* }
|
|
329
|
-
*
|
|
330
|
-
* function draw() {
|
|
331
|
-
* background(200);
|
|
332
|
-
*
|
|
333
|
-
* // Style the box.
|
|
334
|
-
* fill(255);
|
|
335
|
-
*
|
|
336
|
-
* // Draw the box.
|
|
337
|
-
* box();
|
|
338
|
-
*
|
|
339
|
-
* // Style the text.
|
|
340
|
-
* textAlign(CENTER);
|
|
341
|
-
* textSize(16);
|
|
342
|
-
* textFont(font);
|
|
343
|
-
* fill(0);
|
|
344
|
-
*
|
|
345
|
-
* // Calculate the new z-coordinate.
|
|
346
|
-
* let z = 100 * sin(frameCount * 0.01) + 800;
|
|
347
|
-
*
|
|
348
|
-
* // Set the camera's position.
|
|
349
|
-
* cam.setPosition(0, -400, z);
|
|
350
|
-
*
|
|
351
|
-
* // Display the value of eyeZ, rounded to the nearest integer.
|
|
352
|
-
* text(`eyeZ: ${round(cam.eyeZ)}`, 0, 55);
|
|
353
|
-
* }
|
|
354
|
-
* </code>
|
|
355
|
-
* </div>
|
|
356
|
-
*/
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* The x-coordinate of the place where the camera looks.
|
|
360
|
-
*
|
|
361
|
-
* By default, the camera looks at the origin `(0, 0, 0)` in "world" space, so
|
|
362
|
-
* `myCamera.centerX` is 0.
|
|
363
|
-
*
|
|
364
|
-
* @property {Number} centerX
|
|
365
|
-
* @readonly
|
|
366
|
-
*
|
|
367
|
-
* @example
|
|
368
|
-
* <div>
|
|
369
|
-
* <code>
|
|
370
|
-
* let cam;
|
|
371
|
-
* let font;
|
|
372
|
-
*
|
|
373
|
-
* async function setup() {
|
|
374
|
-
* // Load a font and create a p5.Font object.
|
|
375
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
376
|
-
* createCanvas(100, 100, WEBGL);
|
|
377
|
-
*
|
|
378
|
-
* // Create a p5.Camera object.
|
|
379
|
-
* cam = createCamera();
|
|
380
|
-
*
|
|
381
|
-
* // Set the camera
|
|
382
|
-
* setCamera(cam);
|
|
383
|
-
*
|
|
384
|
-
* // Place the camera at the top-center.
|
|
385
|
-
* cam.setPosition(0, -400, 800);
|
|
386
|
-
*
|
|
387
|
-
* // Point the camera at (10, 20, -30).
|
|
388
|
-
* cam.lookAt(10, 20, -30);
|
|
389
|
-
*
|
|
390
|
-
* describe(
|
|
391
|
-
* 'A white cube on a gray background. The text "centerX: 10" is written in black beneath it.'
|
|
392
|
-
* );
|
|
393
|
-
* }
|
|
394
|
-
*
|
|
395
|
-
* function draw() {
|
|
396
|
-
* background(200);
|
|
397
|
-
*
|
|
398
|
-
* // Style the box.
|
|
399
|
-
* fill(255);
|
|
400
|
-
*
|
|
401
|
-
* // Draw the box.
|
|
402
|
-
* box();
|
|
403
|
-
*
|
|
404
|
-
* // Style the text.
|
|
405
|
-
* textAlign(CENTER);
|
|
406
|
-
* textSize(16);
|
|
407
|
-
* textFont(font);
|
|
408
|
-
* fill(0);
|
|
409
|
-
*
|
|
410
|
-
* // Display the value of centerX, rounded to the nearest integer.
|
|
411
|
-
* text(`centerX: ${round(cam.centerX)}`, 0, 55);
|
|
412
|
-
* }
|
|
413
|
-
* </code>
|
|
414
|
-
* </div>
|
|
415
|
-
*
|
|
416
|
-
* <div>
|
|
417
|
-
* <code>
|
|
418
|
-
* let cam;
|
|
419
|
-
* let font;
|
|
420
|
-
*
|
|
421
|
-
* async function setup() {
|
|
422
|
-
* // Load a font and create a p5.Font object.
|
|
423
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
424
|
-
* createCanvas(100, 100, WEBGL);
|
|
425
|
-
*
|
|
426
|
-
* // Create a p5.Camera object.
|
|
427
|
-
* cam = createCamera();
|
|
428
|
-
*
|
|
429
|
-
* // Set the camera
|
|
430
|
-
* setCamera(cam);
|
|
431
|
-
*
|
|
432
|
-
* // Place the camera at the top-right.
|
|
433
|
-
* cam.setPosition(100, -400, 800);
|
|
434
|
-
*
|
|
435
|
-
* // Point the camera at (10, 20, -30).
|
|
436
|
-
* cam.lookAt(10, 20, -30);
|
|
437
|
-
*
|
|
438
|
-
* describe(
|
|
439
|
-
* 'A white cube on a gray background. The cube appears to move left and right as the camera shifts its focus. The text "centerX: X" is written in black beneath the cube. X oscillates between -15 and 35.'
|
|
440
|
-
* );
|
|
441
|
-
* }
|
|
442
|
-
*
|
|
443
|
-
* function draw() {
|
|
444
|
-
* background(200);
|
|
445
|
-
*
|
|
446
|
-
* // Style the box.
|
|
447
|
-
* fill(255);
|
|
448
|
-
*
|
|
449
|
-
* // Draw the box.
|
|
450
|
-
* box();
|
|
451
|
-
*
|
|
452
|
-
* // Style the text.
|
|
453
|
-
* textAlign(CENTER);
|
|
454
|
-
* textSize(16);
|
|
455
|
-
* textFont(font);
|
|
456
|
-
* fill(0);
|
|
457
|
-
*
|
|
458
|
-
* // Calculate the new x-coordinate.
|
|
459
|
-
* let x = 25 * sin(frameCount * 0.01) + 10;
|
|
460
|
-
*
|
|
461
|
-
* // Point the camera.
|
|
462
|
-
* cam.lookAt(x, 20, -30);
|
|
463
|
-
*
|
|
464
|
-
* // Display the value of centerX, rounded to the nearest integer.
|
|
465
|
-
* text(`centerX: ${round(cam.centerX)}`, 0, 55);
|
|
466
|
-
* }
|
|
467
|
-
* </code>
|
|
468
|
-
* </div>
|
|
469
|
-
*/
|
|
470
|
-
|
|
471
|
-
/**
|
|
472
|
-
* The y-coordinate of the place where the camera looks.
|
|
473
|
-
*
|
|
474
|
-
* By default, the camera looks at the origin `(0, 0, 0)` in "world" space, so
|
|
475
|
-
* `myCamera.centerY` is 0.
|
|
476
|
-
*
|
|
477
|
-
* @property {Number} centerY
|
|
478
|
-
* @readonly
|
|
479
|
-
*
|
|
480
|
-
* @example
|
|
481
|
-
* <div>
|
|
482
|
-
* <code>
|
|
483
|
-
* let cam;
|
|
484
|
-
* let font;
|
|
485
|
-
*
|
|
486
|
-
* async function setup() {
|
|
487
|
-
* // Load a font and create a p5.Font object.
|
|
488
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
489
|
-
* createCanvas(100, 100, WEBGL);
|
|
490
|
-
*
|
|
491
|
-
* // Create a p5.Camera object.
|
|
492
|
-
* cam = createCamera();
|
|
493
|
-
*
|
|
494
|
-
* // Set the camera
|
|
495
|
-
* setCamera(cam);
|
|
496
|
-
*
|
|
497
|
-
* // Place the camera at the top-center.
|
|
498
|
-
* cam.setPosition(0, -400, 800);
|
|
499
|
-
*
|
|
500
|
-
* // Point the camera at (10, 20, -30).
|
|
501
|
-
* cam.lookAt(10, 20, -30);
|
|
502
|
-
*
|
|
503
|
-
* describe(
|
|
504
|
-
* 'A white cube on a gray background. The text "centerY: 20" is written in black beneath it.'
|
|
505
|
-
* );
|
|
506
|
-
* }
|
|
507
|
-
*
|
|
508
|
-
* function draw() {
|
|
509
|
-
* background(200);
|
|
510
|
-
*
|
|
511
|
-
* // Style the box.
|
|
512
|
-
* fill(255);
|
|
513
|
-
*
|
|
514
|
-
* // Draw the box.
|
|
515
|
-
* box();
|
|
516
|
-
*
|
|
517
|
-
* // Style the text.
|
|
518
|
-
* textAlign(CENTER);
|
|
519
|
-
* textSize(16);
|
|
520
|
-
* textFont(font);
|
|
521
|
-
* fill(0);
|
|
522
|
-
*
|
|
523
|
-
* // Display the value of centerY, rounded to the nearest integer.
|
|
524
|
-
* text(`centerY: ${round(cam.centerY)}`, 0, 55);
|
|
525
|
-
* }
|
|
526
|
-
* </code>
|
|
527
|
-
* </div>
|
|
528
|
-
*
|
|
529
|
-
* <div>
|
|
530
|
-
* <code>
|
|
531
|
-
* let cam;
|
|
532
|
-
* let font;
|
|
533
|
-
*
|
|
534
|
-
* async function setup() {
|
|
535
|
-
* // Load a font and create a p5.Font object.
|
|
536
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
537
|
-
* createCanvas(100, 100, WEBGL);
|
|
538
|
-
*
|
|
539
|
-
* // Create a p5.Camera object.
|
|
540
|
-
* cam = createCamera();
|
|
541
|
-
*
|
|
542
|
-
* // Set the camera
|
|
543
|
-
* setCamera(cam);
|
|
544
|
-
*
|
|
545
|
-
* // Place the camera at the top-right.
|
|
546
|
-
* cam.setPosition(100, -400, 800);
|
|
547
|
-
*
|
|
548
|
-
* // Point the camera at (10, 20, -30).
|
|
549
|
-
* cam.lookAt(10, 20, -30);
|
|
550
|
-
*
|
|
551
|
-
* describe(
|
|
552
|
-
* 'A white cube on a gray background. The cube appears to move up and down as the camera shifts its focus. The text "centerY: Y" is written in black beneath the cube. Y oscillates between -5 and 45.'
|
|
553
|
-
* );
|
|
554
|
-
* }
|
|
555
|
-
*
|
|
556
|
-
* function draw() {
|
|
557
|
-
* background(200);
|
|
558
|
-
*
|
|
559
|
-
* // Style the box.
|
|
560
|
-
* fill(255);
|
|
561
|
-
*
|
|
562
|
-
* // Draw the box.
|
|
563
|
-
* box();
|
|
564
|
-
*
|
|
565
|
-
* // Style the text.
|
|
566
|
-
* textAlign(CENTER);
|
|
567
|
-
* textSize(16);
|
|
568
|
-
* textFont(font);
|
|
569
|
-
* fill(0);
|
|
570
|
-
*
|
|
571
|
-
* // Calculate the new y-coordinate.
|
|
572
|
-
* let y = 25 * sin(frameCount * 0.01) + 20;
|
|
573
|
-
*
|
|
574
|
-
* // Point the camera.
|
|
575
|
-
* cam.lookAt(10, y, -30);
|
|
576
|
-
*
|
|
577
|
-
* // Display the value of centerY, rounded to the nearest integer.
|
|
578
|
-
* text(`centerY: ${round(cam.centerY)}`, 0, 55);
|
|
579
|
-
* }
|
|
580
|
-
* </code>
|
|
581
|
-
* </div>
|
|
582
|
-
*/
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* The y-coordinate of the place where the camera looks.
|
|
586
|
-
*
|
|
587
|
-
* By default, the camera looks at the origin `(0, 0, 0)` in "world" space, so
|
|
588
|
-
* `myCamera.centerZ` is 0.
|
|
589
|
-
*
|
|
590
|
-
* @property {Number} centerZ
|
|
591
|
-
* @readonly
|
|
592
|
-
*
|
|
593
|
-
* @example
|
|
594
|
-
* <div>
|
|
595
|
-
* <code>
|
|
596
|
-
* let cam;
|
|
597
|
-
* let font;
|
|
598
|
-
*
|
|
599
|
-
* async function setup() {
|
|
600
|
-
* // Load a font and create a p5.Font object.
|
|
601
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
602
|
-
* createCanvas(100, 100, WEBGL);
|
|
603
|
-
*
|
|
604
|
-
* // Create a p5.Camera object.
|
|
605
|
-
* cam = createCamera();
|
|
606
|
-
*
|
|
607
|
-
* // Set the camera
|
|
608
|
-
* setCamera(cam);
|
|
609
|
-
*
|
|
610
|
-
* // Place the camera at the top-center.
|
|
611
|
-
* cam.setPosition(0, -400, 800);
|
|
612
|
-
*
|
|
613
|
-
* // Point the camera at (10, 20, -30).
|
|
614
|
-
* cam.lookAt(10, 20, -30);
|
|
615
|
-
*
|
|
616
|
-
* describe(
|
|
617
|
-
* 'A white cube on a gray background. The text "centerZ: -30" is written in black beneath it.'
|
|
618
|
-
* );
|
|
619
|
-
* }
|
|
620
|
-
*
|
|
621
|
-
* function draw() {
|
|
622
|
-
* background(200);
|
|
623
|
-
*
|
|
624
|
-
* // Style the box.
|
|
625
|
-
* fill(255);
|
|
626
|
-
*
|
|
627
|
-
* // Draw the box.
|
|
628
|
-
* box();
|
|
629
|
-
*
|
|
630
|
-
* // Style the text.
|
|
631
|
-
* textAlign(CENTER);
|
|
632
|
-
* textSize(16);
|
|
633
|
-
* textFont(font);
|
|
634
|
-
* fill(0);
|
|
635
|
-
*
|
|
636
|
-
* // Display the value of centerZ, rounded to the nearest integer.
|
|
637
|
-
* text(`centerZ: ${round(cam.centerZ)}`, 0, 55);
|
|
638
|
-
* }
|
|
639
|
-
* </code>
|
|
640
|
-
* </div>
|
|
641
|
-
*
|
|
642
|
-
* <div>
|
|
643
|
-
* <code>
|
|
644
|
-
* let cam;
|
|
645
|
-
* let font;
|
|
646
|
-
*
|
|
647
|
-
* async function setup() {
|
|
648
|
-
* // Load a font and create a p5.Font object.
|
|
649
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
650
|
-
* createCanvas(100, 100, WEBGL);
|
|
651
|
-
*
|
|
652
|
-
* // Create a p5.Camera object.
|
|
653
|
-
* cam = createCamera();
|
|
654
|
-
*
|
|
655
|
-
* // Set the camera
|
|
656
|
-
* setCamera(cam);
|
|
657
|
-
*
|
|
658
|
-
* // Place the camera at the top-right.
|
|
659
|
-
* cam.setPosition(100, -400, 800);
|
|
660
|
-
*
|
|
661
|
-
* // Point the camera at (10, 20, -30).
|
|
662
|
-
* cam.lookAt(10, 20, -30);
|
|
663
|
-
*
|
|
664
|
-
* describe(
|
|
665
|
-
* 'A white cube on a gray background. The cube appears to move forward and back as the camera shifts its focus. The text "centerZ: Z" is written in black beneath the cube. Z oscillates between -55 and -25.'
|
|
666
|
-
* );
|
|
667
|
-
* }
|
|
668
|
-
*
|
|
669
|
-
* function draw() {
|
|
670
|
-
* background(200);
|
|
671
|
-
*
|
|
672
|
-
* // Style the box.
|
|
673
|
-
* fill(255);
|
|
674
|
-
*
|
|
675
|
-
* // Draw the box.
|
|
676
|
-
* box();
|
|
677
|
-
*
|
|
678
|
-
* // Style the text.
|
|
679
|
-
* textAlign(CENTER);
|
|
680
|
-
* textSize(16);
|
|
681
|
-
* textFont(font);
|
|
682
|
-
* fill(0);
|
|
683
|
-
*
|
|
684
|
-
* // Calculate the new z-coordinate.
|
|
685
|
-
* let z = 25 * sin(frameCount * 0.01) - 30;
|
|
686
|
-
*
|
|
687
|
-
* // Point the camera.
|
|
688
|
-
* cam.lookAt(10, 20, z);
|
|
689
|
-
*
|
|
690
|
-
* // Display the value of centerZ, rounded to the nearest integer.
|
|
691
|
-
* text(`centerZ: ${round(cam.centerZ)}`, 0, 55);
|
|
692
|
-
* }
|
|
693
|
-
* </code>
|
|
694
|
-
* </div>
|
|
695
|
-
*/
|
|
696
|
-
|
|
697
|
-
/**
|
|
698
|
-
* The x-component of the camera's "up" vector.
|
|
699
|
-
*
|
|
700
|
-
* The camera's "up" vector orients its y-axis. By default, the "up" vector is
|
|
701
|
-
* `(0, 1, 0)`, so its x-component is 0 in "local" space.
|
|
702
|
-
*
|
|
703
|
-
* @property {Number} upX
|
|
704
|
-
* @readonly
|
|
705
|
-
*
|
|
706
|
-
* @example
|
|
707
|
-
* <div>
|
|
708
|
-
* <code>
|
|
709
|
-
* let cam;
|
|
710
|
-
* let font;
|
|
711
|
-
*
|
|
712
|
-
* async function setup() {
|
|
713
|
-
* // Load a font and create a p5.Font object.
|
|
714
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
715
|
-
* createCanvas(100, 100, WEBGL);
|
|
716
|
-
*
|
|
717
|
-
* // Create a p5.Camera object.
|
|
718
|
-
* cam = createCamera();
|
|
719
|
-
*
|
|
720
|
-
* // Set the camera
|
|
721
|
-
* setCamera(cam);
|
|
722
|
-
*
|
|
723
|
-
* // Place the camera at the top-right: (100, -400, 800)
|
|
724
|
-
* // Point it at the origin: (0, 0, 0)
|
|
725
|
-
* // Set its "up" vector: (0, 1, 0).
|
|
726
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0);
|
|
727
|
-
*
|
|
728
|
-
* describe(
|
|
729
|
-
* 'A white cube on a gray background. The text "upX: 0" is written in black beneath it.'
|
|
730
|
-
* );
|
|
731
|
-
* }
|
|
732
|
-
*
|
|
733
|
-
* function draw() {
|
|
734
|
-
* background(200);
|
|
735
|
-
*
|
|
736
|
-
* // Style the box.
|
|
737
|
-
* fill(255);
|
|
738
|
-
*
|
|
739
|
-
* // Draw the box.
|
|
740
|
-
* box();
|
|
741
|
-
*
|
|
742
|
-
* // Style the text.
|
|
743
|
-
* textAlign(CENTER);
|
|
744
|
-
* textSize(16);
|
|
745
|
-
* textFont(font);
|
|
746
|
-
* fill(0);
|
|
747
|
-
*
|
|
748
|
-
* // Display the value of upX, rounded to the nearest tenth.
|
|
749
|
-
* text(`upX: ${round(cam.upX, 1)}`, 0, 55);
|
|
750
|
-
* }
|
|
751
|
-
* </code>
|
|
752
|
-
* </div>
|
|
753
|
-
*
|
|
754
|
-
* <div>
|
|
755
|
-
* <code>
|
|
756
|
-
* let cam;
|
|
757
|
-
* let font;
|
|
758
|
-
*
|
|
759
|
-
* async function setup() {
|
|
760
|
-
* // Load a font and create a p5.Font object.
|
|
761
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
762
|
-
* createCanvas(100, 100, WEBGL);
|
|
763
|
-
*
|
|
764
|
-
* // Create a p5.Camera object.
|
|
765
|
-
* cam = createCamera();
|
|
766
|
-
*
|
|
767
|
-
* // Set the camera
|
|
768
|
-
* setCamera(cam);
|
|
769
|
-
*
|
|
770
|
-
* // Place the camera at the top-right: (100, -400, 800)
|
|
771
|
-
* // Point it at the origin: (0, 0, 0)
|
|
772
|
-
* // Set its "up" vector: (0, 1, 0).
|
|
773
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0);
|
|
774
|
-
*
|
|
775
|
-
* describe(
|
|
776
|
-
* 'A white cube on a gray background. The cube appears to rock back and forth. The text "upX: X" is written in black beneath it. X oscillates between -1 and 1.'
|
|
777
|
-
* );
|
|
778
|
-
* }
|
|
779
|
-
*
|
|
780
|
-
* function draw() {
|
|
781
|
-
* background(200);
|
|
782
|
-
*
|
|
783
|
-
* // Style the box.
|
|
784
|
-
* fill(255);
|
|
785
|
-
*
|
|
786
|
-
* // Draw the box.
|
|
787
|
-
* box();
|
|
788
|
-
*
|
|
789
|
-
* // Style the text.
|
|
790
|
-
* textAlign(CENTER);
|
|
791
|
-
* textSize(16);
|
|
792
|
-
* textFont(font);
|
|
793
|
-
* fill(0);
|
|
794
|
-
*
|
|
795
|
-
* // Calculate the x-component.
|
|
796
|
-
* let x = sin(frameCount * 0.01);
|
|
797
|
-
*
|
|
798
|
-
* // Update the camera's "up" vector.
|
|
799
|
-
* cam.camera(100, -400, 800, 0, 0, 0, x, 1, 0);
|
|
800
|
-
*
|
|
801
|
-
* // Display the value of upX, rounded to the nearest tenth.
|
|
802
|
-
* text(`upX: ${round(cam.upX, 1)}`, 0, 55);
|
|
803
|
-
* }
|
|
804
|
-
* </code>
|
|
805
|
-
* </div>
|
|
806
|
-
*/
|
|
807
|
-
|
|
808
|
-
/**
|
|
809
|
-
* The y-component of the camera's "up" vector.
|
|
810
|
-
*
|
|
811
|
-
* The camera's "up" vector orients its y-axis. By default, the "up" vector is
|
|
812
|
-
* `(0, 1, 0)`, so its y-component is 1 in "local" space.
|
|
813
|
-
*
|
|
814
|
-
* @property {Number} upY
|
|
815
|
-
* @readonly
|
|
816
|
-
*
|
|
817
|
-
* @example
|
|
818
|
-
* <div>
|
|
819
|
-
* <code>
|
|
820
|
-
* let cam;
|
|
821
|
-
* let font;
|
|
822
|
-
*
|
|
823
|
-
* async function setup() {
|
|
824
|
-
* // Load a font and create a p5.Font object.
|
|
825
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
826
|
-
* createCanvas(100, 100, WEBGL);
|
|
827
|
-
*
|
|
828
|
-
* // Create a p5.Camera object.
|
|
829
|
-
* cam = createCamera();
|
|
830
|
-
*
|
|
831
|
-
* // Set the camera
|
|
832
|
-
* setCamera(cam);
|
|
833
|
-
*
|
|
834
|
-
* // Place the camera at the top-right: (100, -400, 800)
|
|
835
|
-
* // Point it at the origin: (0, 0, 0)
|
|
836
|
-
* // Set its "up" vector: (0, 1, 0).
|
|
837
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0);
|
|
838
|
-
*
|
|
839
|
-
* describe(
|
|
840
|
-
* 'A white cube on a gray background. The text "upY: 1" is written in black beneath it.'
|
|
841
|
-
* );
|
|
842
|
-
* }
|
|
843
|
-
*
|
|
844
|
-
* function draw() {
|
|
845
|
-
* background(200);
|
|
846
|
-
*
|
|
847
|
-
* // Style the box.
|
|
848
|
-
* fill(255);
|
|
849
|
-
*
|
|
850
|
-
* // Draw the box.
|
|
851
|
-
* box();
|
|
852
|
-
*
|
|
853
|
-
* // Style the text.
|
|
854
|
-
* textAlign(CENTER);
|
|
855
|
-
* textSize(16);
|
|
856
|
-
* textFont(font);
|
|
857
|
-
* fill(0);
|
|
858
|
-
*
|
|
859
|
-
* // Display the value of upY, rounded to the nearest tenth.
|
|
860
|
-
* text(`upY: ${round(cam.upY, 1)}`, 0, 55);
|
|
861
|
-
* }
|
|
862
|
-
* </code>
|
|
863
|
-
* </div>
|
|
864
|
-
*
|
|
865
|
-
* <div>
|
|
866
|
-
* <code>
|
|
867
|
-
* let cam;
|
|
868
|
-
* let font;
|
|
869
|
-
*
|
|
870
|
-
* async function setup() {
|
|
871
|
-
* // Load a font and create a p5.Font object.
|
|
872
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
873
|
-
* createCanvas(100, 100, WEBGL);
|
|
874
|
-
*
|
|
875
|
-
* // Create a p5.Camera object.
|
|
876
|
-
* cam = createCamera();
|
|
877
|
-
*
|
|
878
|
-
* // Set the camera
|
|
879
|
-
* setCamera(cam);
|
|
880
|
-
*
|
|
881
|
-
* // Place the camera at the top-right: (100, -400, 800)
|
|
882
|
-
* // Point it at the origin: (0, 0, 0)
|
|
883
|
-
* // Set its "up" vector: (0, 1, 0).
|
|
884
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0);
|
|
885
|
-
*
|
|
886
|
-
* describe(
|
|
887
|
-
* 'A white cube on a gray background. The cube flips upside-down periodically. The text "upY: Y" is written in black beneath it. Y oscillates between -1 and 1.'
|
|
888
|
-
* );
|
|
889
|
-
* }
|
|
890
|
-
*
|
|
891
|
-
* function draw() {
|
|
892
|
-
* background(200);
|
|
893
|
-
*
|
|
894
|
-
* // Style the box.
|
|
895
|
-
* fill(255);
|
|
896
|
-
*
|
|
897
|
-
* // Draw the box.
|
|
898
|
-
* box();
|
|
899
|
-
*
|
|
900
|
-
* // Style the text.
|
|
901
|
-
* textAlign(CENTER);
|
|
902
|
-
* textSize(16);
|
|
903
|
-
* textFont(font);
|
|
904
|
-
* fill(0);
|
|
905
|
-
*
|
|
906
|
-
* // Calculate the y-component.
|
|
907
|
-
* let y = sin(frameCount * 0.01);
|
|
908
|
-
*
|
|
909
|
-
* // Update the camera's "up" vector.
|
|
910
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, y, 0);
|
|
911
|
-
*
|
|
912
|
-
* // Display the value of upY, rounded to the nearest tenth.
|
|
913
|
-
* text(`upY: ${round(cam.upY, 1)}`, 0, 55);
|
|
914
|
-
* }
|
|
915
|
-
* </code>
|
|
916
|
-
* </div>
|
|
917
|
-
*/
|
|
918
|
-
|
|
919
|
-
/**
|
|
920
|
-
* The z-component of the camera's "up" vector.
|
|
921
|
-
*
|
|
922
|
-
* The camera's "up" vector orients its y-axis. By default, the "up" vector is
|
|
923
|
-
* `(0, 1, 0)`, so its z-component is 0 in "local" space.
|
|
924
|
-
*
|
|
925
|
-
* @property {Number} upZ
|
|
926
|
-
* @readonly
|
|
927
|
-
*
|
|
928
|
-
* @example
|
|
929
|
-
* <div>
|
|
930
|
-
* <code>
|
|
931
|
-
* let cam;
|
|
932
|
-
* let font;
|
|
933
|
-
*
|
|
934
|
-
* async function setup() {
|
|
935
|
-
* // Load a font and create a p5.Font object.
|
|
936
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
937
|
-
* createCanvas(100, 100, WEBGL);
|
|
938
|
-
*
|
|
939
|
-
* // Create a p5.Camera object.
|
|
940
|
-
* cam = createCamera();
|
|
941
|
-
*
|
|
942
|
-
* // Set the camera
|
|
943
|
-
* setCamera(cam);
|
|
944
|
-
*
|
|
945
|
-
* // Place the camera at the top-right: (100, -400, 800)
|
|
946
|
-
* // Point it at the origin: (0, 0, 0)
|
|
947
|
-
* // Set its "up" vector: (0, 1, 0).
|
|
948
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0);
|
|
949
|
-
*
|
|
950
|
-
* describe(
|
|
951
|
-
* 'A white cube on a gray background. The text "upZ: 0" is written in black beneath it.'
|
|
952
|
-
* );
|
|
953
|
-
* }
|
|
954
|
-
*
|
|
955
|
-
* function draw() {
|
|
956
|
-
* background(200);
|
|
957
|
-
*
|
|
958
|
-
* // Style the box.
|
|
959
|
-
* fill(255);
|
|
960
|
-
*
|
|
961
|
-
* // Draw the box.
|
|
962
|
-
* box();
|
|
963
|
-
*
|
|
964
|
-
* // Style the text.
|
|
965
|
-
* textAlign(CENTER);
|
|
966
|
-
* textSize(16);
|
|
967
|
-
* textFont(font);
|
|
968
|
-
* fill(0);
|
|
969
|
-
*
|
|
970
|
-
* // Display the value of upZ, rounded to the nearest tenth.
|
|
971
|
-
* text(`upZ: ${round(cam.upZ, 1)}`, 0, 55);
|
|
972
|
-
* }
|
|
973
|
-
* </code>
|
|
974
|
-
* </div>
|
|
975
|
-
*
|
|
976
|
-
* <div>
|
|
977
|
-
* <code>
|
|
978
|
-
* let cam;
|
|
979
|
-
* let font;
|
|
980
|
-
*
|
|
981
|
-
* async function setup() {
|
|
982
|
-
* // Load a font and create a p5.Font object.
|
|
983
|
-
* font = await loadFont('assets/inconsolata.otf');
|
|
984
|
-
* createCanvas(100, 100, WEBGL);
|
|
985
|
-
*
|
|
986
|
-
* // Create a p5.Camera object.
|
|
987
|
-
* cam = createCamera();
|
|
988
|
-
*
|
|
989
|
-
* // Set the camera
|
|
990
|
-
* setCamera(cam);
|
|
991
|
-
*
|
|
992
|
-
* // Place the camera at the top-right: (100, -400, 800)
|
|
993
|
-
* // Point it at the origin: (0, 0, 0)
|
|
994
|
-
* // Set its "up" vector: (0, 1, 0).
|
|
995
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0);
|
|
996
|
-
*
|
|
997
|
-
* describe(
|
|
998
|
-
* 'A white cube on a gray background. The cube appears to rock back and forth. The text "upZ: Z" is written in black beneath it. Z oscillates between -1 and 1.'
|
|
999
|
-
* );
|
|
1000
|
-
* }
|
|
1001
|
-
*
|
|
1002
|
-
* function draw() {
|
|
1003
|
-
* background(200);
|
|
1004
|
-
*
|
|
1005
|
-
* // Style the box.
|
|
1006
|
-
* fill(255);
|
|
1007
|
-
*
|
|
1008
|
-
* // Draw the box.
|
|
1009
|
-
* box();
|
|
1010
|
-
*
|
|
1011
|
-
* // Style the text.
|
|
1012
|
-
* textAlign(CENTER);
|
|
1013
|
-
* textSize(16);
|
|
1014
|
-
* textFont(font);
|
|
1015
|
-
* fill(0);
|
|
1016
|
-
*
|
|
1017
|
-
* // Calculate the z-component.
|
|
1018
|
-
* let z = sin(frameCount * 0.01);
|
|
1019
|
-
*
|
|
1020
|
-
* // Update the camera's "up" vector.
|
|
1021
|
-
* cam.camera(100, -400, 800, 0, 0, 0, 0, 1, z);
|
|
1022
|
-
*
|
|
1023
|
-
* // Display the value of upZ, rounded to the nearest tenth.
|
|
1024
|
-
* text(`upZ: ${round(cam.upZ, 1)}`, 0, 55);
|
|
1025
|
-
* }
|
|
1026
|
-
* </code>
|
|
1027
|
-
* </div>
|
|
1028
|
-
*/
|
|
1029
|
-
|
|
1030
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
1031
|
-
// Camera Projection Methods
|
|
1032
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* Sets a perspective projection for the camera.
|
|
1036
|
-
*
|
|
1037
|
-
* In a perspective projection, shapes that are further from the camera appear
|
|
1038
|
-
* smaller than shapes that are near the camera. This technique, called
|
|
1039
|
-
* foreshortening, creates realistic 3D scenes. It’s applied by default in new
|
|
1040
|
-
* `p5.Camera` objects.
|
|
1041
|
-
*
|
|
1042
|
-
* `myCamera.perspective()` changes the camera’s perspective by changing its
|
|
1043
|
-
* viewing frustum. The frustum is the volume of space that’s visible to the
|
|
1044
|
-
* camera. The frustum’s shape is a pyramid with its top cut off. The camera
|
|
1045
|
-
* is placed where the top of the pyramid should be and points towards the
|
|
1046
|
-
* base of the pyramid. It views everything within the frustum.
|
|
1047
|
-
*
|
|
1048
|
-
* The first parameter, `fovy`, is the camera’s vertical field of view. It’s
|
|
1049
|
-
* an angle that describes how tall or narrow a view the camera has. For
|
|
1050
|
-
* example, calling `myCamera.perspective(0.5)` sets the camera’s vertical
|
|
1051
|
-
* field of view to 0.5 radians. By default, `fovy` is calculated based on the
|
|
1052
|
-
* sketch’s height and the camera’s default z-coordinate, which is 800. The
|
|
1053
|
-
* formula for the default `fovy` is `2 * atan(height / 2 / 800)`.
|
|
1054
|
-
*
|
|
1055
|
-
* The second parameter, `aspect`, is the camera’s aspect ratio. It’s a number
|
|
1056
|
-
* that describes the ratio of the top plane’s width to its height. For
|
|
1057
|
-
* example, calling `myCamera.perspective(0.5, 1.5)` sets the camera’s field
|
|
1058
|
-
* of view to 0.5 radians and aspect ratio to 1.5, which would make shapes
|
|
1059
|
-
* appear thinner on a square canvas. By default, `aspect` is set to
|
|
1060
|
-
* `width / height`.
|
|
1061
|
-
*
|
|
1062
|
-
* The third parameter, `near`, is the distance from the camera to the near
|
|
1063
|
-
* plane. For example, calling `myCamera.perspective(0.5, 1.5, 100)` sets the
|
|
1064
|
-
* camera’s field of view to 0.5 radians, its aspect ratio to 1.5, and places
|
|
1065
|
-
* the near plane 100 pixels from the camera. Any shapes drawn less than 100
|
|
1066
|
-
* pixels from the camera won’t be visible. By default, `near` is set to
|
|
1067
|
-
* `0.1 * 800`, which is 1/10th the default distance between the camera and
|
|
1068
|
-
* the origin.
|
|
1069
|
-
*
|
|
1070
|
-
* The fourth parameter, `far`, is the distance from the camera to the far
|
|
1071
|
-
* plane. For example, calling `myCamera.perspective(0.5, 1.5, 100, 10000)`
|
|
1072
|
-
* sets the camera’s field of view to 0.5 radians, its aspect ratio to 1.5,
|
|
1073
|
-
* places the near plane 100 pixels from the camera, and places the far plane
|
|
1074
|
-
* 10,000 pixels from the camera. Any shapes drawn more than 10,000 pixels
|
|
1075
|
-
* from the camera won’t be visible. By default, `far` is set to `10 * 800`,
|
|
1076
|
-
* which is 10 times the default distance between the camera and the origin.
|
|
1077
|
-
*
|
|
1078
|
-
* @for p5.Camera
|
|
1079
|
-
* @param {Number} [fovy] camera frustum vertical field of view. Defaults to
|
|
1080
|
-
* `2 * atan(height / 2 / 800)`.
|
|
1081
|
-
* @param {Number} [aspect] camera frustum aspect ratio. Defaults to
|
|
1082
|
-
* `width / height`.
|
|
1083
|
-
* @param {Number} [near] distance from the camera to the near clipping plane.
|
|
1084
|
-
* Defaults to `0.1 * 800`.
|
|
1085
|
-
* @param {Number} [far] distance from the camera to the far clipping plane.
|
|
1086
|
-
* Defaults to `10 * 800`.
|
|
1087
|
-
*
|
|
1088
|
-
* @example
|
|
1089
|
-
* <div>
|
|
1090
|
-
* <code>
|
|
1091
|
-
* // Double-click to toggle between cameras.
|
|
1092
|
-
*
|
|
1093
|
-
* let cam1;
|
|
1094
|
-
* let cam2;
|
|
1095
|
-
* let isDefaultCamera = true;
|
|
1096
|
-
*
|
|
1097
|
-
* function setup() {
|
|
1098
|
-
* createCanvas(100, 100, WEBGL);
|
|
1099
|
-
*
|
|
1100
|
-
* // Create the first camera.
|
|
1101
|
-
* // Keep its default settings.
|
|
1102
|
-
* cam1 = createCamera();
|
|
1103
|
-
*
|
|
1104
|
-
* // Create the second camera.
|
|
1105
|
-
* cam2 = createCamera();
|
|
1106
|
-
*
|
|
1107
|
-
* // Place it at the top-right.
|
|
1108
|
-
* cam2.camera(400, -400, 800);
|
|
1109
|
-
*
|
|
1110
|
-
* // Set its fovy to 0.2.
|
|
1111
|
-
* // Set its aspect to 1.5.
|
|
1112
|
-
* // Set its near to 600.
|
|
1113
|
-
* // Set its far to 1200.
|
|
1114
|
-
* cam2.perspective(0.2, 1.5, 600, 1200);
|
|
1115
|
-
*
|
|
1116
|
-
* // Set the current camera to cam1.
|
|
1117
|
-
* setCamera(cam1);
|
|
1118
|
-
*
|
|
1119
|
-
* describe('A white cube on a gray background. The camera toggles between a frontal view and a skewed aerial view when the user double-clicks.');
|
|
1120
|
-
* }
|
|
1121
|
-
*
|
|
1122
|
-
* function draw() {
|
|
1123
|
-
* background(200);
|
|
1124
|
-
*
|
|
1125
|
-
* // Draw the box.
|
|
1126
|
-
* box();
|
|
1127
|
-
* }
|
|
1128
|
-
*
|
|
1129
|
-
* // Toggle the current camera when the user double-clicks.
|
|
1130
|
-
* function doubleClicked() {
|
|
1131
|
-
* if (isDefaultCamera === true) {
|
|
1132
|
-
* setCamera(cam2);
|
|
1133
|
-
* isDefaultCamera = false;
|
|
1134
|
-
* } else {
|
|
1135
|
-
* setCamera(cam1);
|
|
1136
|
-
* isDefaultCamera = true;
|
|
1137
|
-
* }
|
|
1138
|
-
* }
|
|
1139
|
-
* </code>
|
|
1140
|
-
* </div>
|
|
1141
|
-
*
|
|
1142
|
-
* <div>
|
|
1143
|
-
* <code>
|
|
1144
|
-
* // Double-click to toggle between cameras.
|
|
1145
|
-
*
|
|
1146
|
-
* let cam1;
|
|
1147
|
-
* let cam2;
|
|
1148
|
-
* let isDefaultCamera = true;
|
|
1149
|
-
*
|
|
1150
|
-
* function setup() {
|
|
1151
|
-
* createCanvas(100, 100, WEBGL);
|
|
1152
|
-
*
|
|
1153
|
-
* // Create the first camera.
|
|
1154
|
-
* // Keep its default settings.
|
|
1155
|
-
* cam1 = createCamera();
|
|
1156
|
-
*
|
|
1157
|
-
* // Create the second camera.
|
|
1158
|
-
* cam2 = createCamera();
|
|
1159
|
-
*
|
|
1160
|
-
* // Place it at the top-right.
|
|
1161
|
-
* cam2.camera(400, -400, 800);
|
|
1162
|
-
*
|
|
1163
|
-
* // Set its fovy to 0.2.
|
|
1164
|
-
* // Set its aspect to 1.5.
|
|
1165
|
-
* // Set its near to 600.
|
|
1166
|
-
* // Set its far to 1200.
|
|
1167
|
-
* cam2.perspective(0.2, 1.5, 600, 1200);
|
|
1168
|
-
*
|
|
1169
|
-
* // Set the current camera to cam1.
|
|
1170
|
-
* setCamera(cam1);
|
|
1171
|
-
*
|
|
1172
|
-
* describe('A white cube moves left and right on a gray background. The camera toggles between a frontal and a skewed aerial view when the user double-clicks.');
|
|
1173
|
-
* }
|
|
1174
|
-
*
|
|
1175
|
-
* function draw() {
|
|
1176
|
-
* background(200);
|
|
1177
|
-
*
|
|
1178
|
-
* // Translate the origin left and right.
|
|
1179
|
-
* let x = 100 * sin(frameCount * 0.01);
|
|
1180
|
-
* translate(x, 0, 0);
|
|
1181
|
-
*
|
|
1182
|
-
* // Draw the box.
|
|
1183
|
-
* box();
|
|
1184
|
-
* }
|
|
1185
|
-
*
|
|
1186
|
-
* // Toggle the current camera when the user double-clicks.
|
|
1187
|
-
* function doubleClicked() {
|
|
1188
|
-
* if (isDefaultCamera === true) {
|
|
1189
|
-
* setCamera(cam2);
|
|
1190
|
-
* isDefaultCamera = false;
|
|
1191
|
-
* } else {
|
|
1192
|
-
* setCamera(cam1);
|
|
1193
|
-
* isDefaultCamera = true;
|
|
1194
|
-
* }
|
|
1195
|
-
* }
|
|
1196
|
-
* </code>
|
|
1197
|
-
* </div>
|
|
1198
|
-
*/
|
|
1199
|
-
perspective(fovy, aspect, near, far) {
|
|
1200
|
-
this.cameraType = arguments.length > 0 ? 'custom' : 'default';
|
|
1201
|
-
if (typeof fovy === 'undefined') {
|
|
1202
|
-
fovy = this.defaultCameraFOV;
|
|
1203
|
-
// this avoids issue where setting angleMode(DEGREES) before calling
|
|
1204
|
-
// perspective leads to a smaller than expected FOV (because
|
|
1205
|
-
// _computeCameraDefaultSettings computes in radians)
|
|
1206
|
-
this.cameraFOV = fovy;
|
|
1207
|
-
} else {
|
|
1208
|
-
this.cameraFOV = this._renderer._pInst._toRadians(fovy);
|
|
1209
|
-
}
|
|
1210
|
-
if (typeof aspect === 'undefined') {
|
|
1211
|
-
aspect = this.defaultAspectRatio;
|
|
1212
|
-
}
|
|
1213
|
-
if (typeof near === 'undefined') {
|
|
1214
|
-
near = this.defaultCameraNear;
|
|
1215
|
-
}
|
|
1216
|
-
if (typeof far === 'undefined') {
|
|
1217
|
-
far = this.defaultCameraFar;
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
if (near <= 0.0001) {
|
|
1221
|
-
near = 0.01;
|
|
1222
|
-
console.log(
|
|
1223
|
-
'Avoid perspective near plane values close to or below 0. ' +
|
|
1224
|
-
'Setting value to 0.01.'
|
|
1225
|
-
);
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
if (far < near) {
|
|
1229
|
-
console.log(
|
|
1230
|
-
'Perspective far plane value is less than near plane value. ' +
|
|
1231
|
-
'Nothing will be shown.'
|
|
1232
|
-
);
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
this.aspectRatio = aspect;
|
|
1236
|
-
this.cameraNear = near;
|
|
1237
|
-
this.cameraFar = far;
|
|
1238
|
-
|
|
1239
|
-
this.projMatrix = new Matrix(4);
|
|
1240
|
-
|
|
1241
|
-
const f = 1.0 / Math.tan(this.cameraFOV / 2);
|
|
1242
|
-
const nf = 1.0 / (this.cameraNear - this.cameraFar);
|
|
1243
|
-
|
|
1244
|
-
/* eslint-disable indent */
|
|
1245
|
-
this.projMatrix.set(f / aspect, 0, 0, 0,
|
|
1246
|
-
0, -f * this.yScale, 0, 0,
|
|
1247
|
-
0, 0, (far + near) * nf, -1,
|
|
1248
|
-
0, 0, (2 * far * near) * nf, 0);
|
|
1249
|
-
/* eslint-enable indent */
|
|
1250
|
-
|
|
1251
|
-
if (this._isActive()) {
|
|
1252
|
-
this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
|
|
1253
|
-
this._renderer.states.uPMatrix.set(this.projMatrix);
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
/**
|
|
1258
|
-
* Sets an orthographic projection for the camera.
|
|
1259
|
-
*
|
|
1260
|
-
* In an orthographic projection, shapes with the same size always appear the
|
|
1261
|
-
* same size, regardless of whether they are near or far from the camera.
|
|
1262
|
-
*
|
|
1263
|
-
* `myCamera.ortho()` changes the camera’s perspective by changing its viewing
|
|
1264
|
-
* frustum from a truncated pyramid to a rectangular prism. The frustum is the
|
|
1265
|
-
* volume of space that’s visible to the camera. The camera is placed in front
|
|
1266
|
-
* of the frustum and views everything within the frustum. `myCamera.ortho()`
|
|
1267
|
-
* has six optional parameters to define the viewing frustum.
|
|
1268
|
-
*
|
|
1269
|
-
* The first four parameters, `left`, `right`, `bottom`, and `top`, set the
|
|
1270
|
-
* coordinates of the frustum’s sides, bottom, and top. For example, calling
|
|
1271
|
-
* `myCamera.ortho(-100, 100, 200, -200)` creates a frustum that’s 200 pixels
|
|
1272
|
-
* wide and 400 pixels tall. By default, these dimensions are set based on
|
|
1273
|
-
* the sketch’s width and height, as in
|
|
1274
|
-
* `myCamera.ortho(-width / 2, width / 2, -height / 2, height / 2)`.
|
|
1275
|
-
*
|
|
1276
|
-
* The last two parameters, `near` and `far`, set the distance of the
|
|
1277
|
-
* frustum’s near and far plane from the camera. For example, calling
|
|
1278
|
-
* `myCamera.ortho(-100, 100, 200, -200, 50, 1000)` creates a frustum that’s
|
|
1279
|
-
* 200 pixels wide, 400 pixels tall, starts 50 pixels from the camera, and
|
|
1280
|
-
* ends 1,000 pixels from the camera. By default, `near` and `far` are set to
|
|
1281
|
-
* 0 and `max(width, height) + 800`, respectively.
|
|
1282
|
-
*
|
|
1283
|
-
* @for p5.Camera
|
|
1284
|
-
* @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 2`.
|
|
1285
|
-
* @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 2`.
|
|
1286
|
-
* @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 2`.
|
|
1287
|
-
* @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 2`.
|
|
1288
|
-
* @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to 0.
|
|
1289
|
-
* @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `max(width, height) + 800`.
|
|
1290
|
-
*
|
|
1291
|
-
* @example
|
|
1292
|
-
* <div>
|
|
1293
|
-
* <code>
|
|
1294
|
-
* // Double-click to toggle between cameras.
|
|
1295
|
-
*
|
|
1296
|
-
* let cam1;
|
|
1297
|
-
* let cam2;
|
|
1298
|
-
* let isDefaultCamera = true;
|
|
1299
|
-
*
|
|
1300
|
-
* function setup() {
|
|
1301
|
-
* createCanvas(100, 100, WEBGL);
|
|
1302
|
-
*
|
|
1303
|
-
* // Create the first camera.
|
|
1304
|
-
* // Keep its default settings.
|
|
1305
|
-
* cam1 = createCamera();
|
|
1306
|
-
*
|
|
1307
|
-
* // Create the second camera.
|
|
1308
|
-
* cam2 = createCamera();
|
|
1309
|
-
*
|
|
1310
|
-
* // Apply an orthographic projection.
|
|
1311
|
-
* cam2.ortho();
|
|
1312
|
-
*
|
|
1313
|
-
* // Set the current camera to cam1.
|
|
1314
|
-
* setCamera(cam1);
|
|
1315
|
-
*
|
|
1316
|
-
* describe('A row of white cubes against a gray background. The camera toggles between a perspective and an orthographic projection when the user double-clicks.');
|
|
1317
|
-
* }
|
|
1318
|
-
*
|
|
1319
|
-
* function draw() {
|
|
1320
|
-
* background(200);
|
|
1321
|
-
*
|
|
1322
|
-
* // Translate the origin toward the camera.
|
|
1323
|
-
* translate(-10, 10, 500);
|
|
1324
|
-
*
|
|
1325
|
-
* // Rotate the coordinate system.
|
|
1326
|
-
* rotateY(-0.1);
|
|
1327
|
-
* rotateX(-0.1);
|
|
1328
|
-
*
|
|
1329
|
-
* // Draw the row of boxes.
|
|
1330
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
1331
|
-
* translate(0, 0, -40);
|
|
1332
|
-
* box(10);
|
|
1333
|
-
* }
|
|
1334
|
-
* }
|
|
1335
|
-
*
|
|
1336
|
-
* // Toggle the current camera when the user double-clicks.
|
|
1337
|
-
* function doubleClicked() {
|
|
1338
|
-
* if (isDefaultCamera === true) {
|
|
1339
|
-
* setCamera(cam2);
|
|
1340
|
-
* isDefaultCamera = false;
|
|
1341
|
-
* } else {
|
|
1342
|
-
* setCamera(cam1);
|
|
1343
|
-
* isDefaultCamera = true;
|
|
1344
|
-
* }
|
|
1345
|
-
* }
|
|
1346
|
-
* </code>
|
|
1347
|
-
* </div>
|
|
1348
|
-
*
|
|
1349
|
-
* <div>
|
|
1350
|
-
* <code>
|
|
1351
|
-
* // Double-click to toggle between cameras.
|
|
1352
|
-
*
|
|
1353
|
-
* let cam1;
|
|
1354
|
-
* let cam2;
|
|
1355
|
-
* let isDefaultCamera = true;
|
|
1356
|
-
*
|
|
1357
|
-
* function setup() {
|
|
1358
|
-
* createCanvas(100, 100, WEBGL);
|
|
1359
|
-
*
|
|
1360
|
-
* // Create the first camera.
|
|
1361
|
-
* // Keep its default settings.
|
|
1362
|
-
* cam1 = createCamera();
|
|
1363
|
-
*
|
|
1364
|
-
* // Create the second camera.
|
|
1365
|
-
* cam2 = createCamera();
|
|
1366
|
-
*
|
|
1367
|
-
* // Apply an orthographic projection.
|
|
1368
|
-
* cam2.ortho();
|
|
1369
|
-
*
|
|
1370
|
-
* // Set the current camera to cam1.
|
|
1371
|
-
* setCamera(cam1);
|
|
1372
|
-
*
|
|
1373
|
-
* describe('A row of white cubes slither like a snake against a gray background. The camera toggles between a perspective and an orthographic projection when the user double-clicks.');
|
|
1374
|
-
* }
|
|
1375
|
-
*
|
|
1376
|
-
* function draw() {
|
|
1377
|
-
* background(200);
|
|
1378
|
-
*
|
|
1379
|
-
* // Translate the origin toward the camera.
|
|
1380
|
-
* translate(-10, 10, 500);
|
|
1381
|
-
*
|
|
1382
|
-
* // Rotate the coordinate system.
|
|
1383
|
-
* rotateY(-0.1);
|
|
1384
|
-
* rotateX(-0.1);
|
|
1385
|
-
*
|
|
1386
|
-
* // Draw the row of boxes.
|
|
1387
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
1388
|
-
* push();
|
|
1389
|
-
* // Calculate the box's coordinates.
|
|
1390
|
-
* let x = 10 * sin(frameCount * 0.02 + i * 0.6);
|
|
1391
|
-
* let z = -40 * i;
|
|
1392
|
-
* // Translate the origin.
|
|
1393
|
-
* translate(x, 0, z);
|
|
1394
|
-
* // Draw the box.
|
|
1395
|
-
* box(10);
|
|
1396
|
-
* pop();
|
|
1397
|
-
* }
|
|
1398
|
-
* }
|
|
1399
|
-
*
|
|
1400
|
-
* // Toggle the current camera when the user double-clicks.
|
|
1401
|
-
* function doubleClicked() {
|
|
1402
|
-
* if (isDefaultCamera === true) {
|
|
1403
|
-
* setCamera(cam2);
|
|
1404
|
-
* isDefaultCamera = false;
|
|
1405
|
-
* } else {
|
|
1406
|
-
* setCamera(cam1);
|
|
1407
|
-
* isDefaultCamera = true;
|
|
1408
|
-
* }
|
|
1409
|
-
* }
|
|
1410
|
-
* </code>
|
|
1411
|
-
* </div>
|
|
1412
|
-
*/
|
|
1413
|
-
ortho(left, right, bottom, top, near, far) {
|
|
1414
|
-
const source = this.fbo || this._renderer;
|
|
1415
|
-
if (left === undefined) left = -source.width / 2;
|
|
1416
|
-
if (right === undefined) right = +source.width / 2;
|
|
1417
|
-
if (bottom === undefined) bottom = -source.height / 2;
|
|
1418
|
-
if (top === undefined) top = +source.height / 2;
|
|
1419
|
-
if (near === undefined) near = 0;
|
|
1420
|
-
if (far === undefined) far = Math.max(source.width, source.height) + 800;
|
|
1421
|
-
this.cameraNear = near;
|
|
1422
|
-
this.cameraFar = far;
|
|
1423
|
-
const w = right - left;
|
|
1424
|
-
const h = top - bottom;
|
|
1425
|
-
const d = far - near;
|
|
1426
|
-
const x = +2.0 / w;
|
|
1427
|
-
const y = +2.0 / h * this.yScale;
|
|
1428
|
-
const z = -2.0 / d;
|
|
1429
|
-
const tx = -(right + left) / w;
|
|
1430
|
-
const ty = -(top + bottom) / h;
|
|
1431
|
-
const tz = -(far + near) / d;
|
|
1432
|
-
this.projMatrix = new Matrix(4);
|
|
1433
|
-
/* eslint-disable indent */
|
|
1434
|
-
this.projMatrix.set(x, 0, 0, 0,
|
|
1435
|
-
0, -y, 0, 0,
|
|
1436
|
-
0, 0, z, 0,
|
|
1437
|
-
tx, ty, tz, 1);
|
|
1438
|
-
/* eslint-enable indent */
|
|
1439
|
-
if (this._isActive()) {
|
|
1440
|
-
this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
|
|
1441
|
-
this._renderer.states.uPMatrix.set(this.projMatrix);
|
|
1442
|
-
}
|
|
1443
|
-
this.cameraType = 'custom';
|
|
1444
|
-
}
|
|
1445
|
-
/**
|
|
1446
|
-
* Sets the camera's frustum.
|
|
1447
|
-
*
|
|
1448
|
-
* In a frustum projection, shapes that are further from the camera appear
|
|
1449
|
-
* smaller than shapes that are near the camera. This technique, called
|
|
1450
|
-
* foreshortening, creates realistic 3D scenes.
|
|
1451
|
-
*
|
|
1452
|
-
* `myCamera.frustum()` changes the camera’s perspective by changing its
|
|
1453
|
-
* viewing frustum. The frustum is the volume of space that’s visible to the
|
|
1454
|
-
* camera. The frustum’s shape is a pyramid with its top cut off. The camera
|
|
1455
|
-
* is placed where the top of the pyramid should be and points towards the
|
|
1456
|
-
* base of the pyramid. It views everything within the frustum.
|
|
1457
|
-
*
|
|
1458
|
-
* The first four parameters, `left`, `right`, `bottom`, and `top`, set the
|
|
1459
|
-
* coordinates of the frustum’s sides, bottom, and top. For example, calling
|
|
1460
|
-
* `myCamera.frustum(-100, 100, 200, -200)` creates a frustum that’s 200
|
|
1461
|
-
* pixels wide and 400 pixels tall. By default, these coordinates are set
|
|
1462
|
-
* based on the sketch’s width and height, as in
|
|
1463
|
-
* `myCamera.frustum(-width / 20, width / 20, height / 20, -height / 20)`.
|
|
1464
|
-
*
|
|
1465
|
-
* The last two parameters, `near` and `far`, set the distance of the
|
|
1466
|
-
* frustum’s near and far plane from the camera. For example, calling
|
|
1467
|
-
* `myCamera.frustum(-100, 100, 200, -200, 50, 1000)` creates a frustum that’s
|
|
1468
|
-
* 200 pixels wide, 400 pixels tall, starts 50 pixels from the camera, and ends
|
|
1469
|
-
* 1,000 pixels from the camera. By default, near is set to `0.1 * 800`, which
|
|
1470
|
-
* is 1/10th the default distance between the camera and the origin. `far` is
|
|
1471
|
-
* set to `10 * 800`, which is 10 times the default distance between the
|
|
1472
|
-
* camera and the origin.
|
|
1473
|
-
*
|
|
1474
|
-
* @for p5.Camera
|
|
1475
|
-
* @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 20`.
|
|
1476
|
-
* @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 20`.
|
|
1477
|
-
* @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 20`.
|
|
1478
|
-
* @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 20`.
|
|
1479
|
-
* @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to `0.1 * 800`.
|
|
1480
|
-
* @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `10 * 800`.
|
|
1481
|
-
*
|
|
1482
|
-
* @example
|
|
1483
|
-
* <div>
|
|
1484
|
-
* <code>
|
|
1485
|
-
* // Double-click to toggle between cameras.
|
|
1486
|
-
*
|
|
1487
|
-
* let cam1;
|
|
1488
|
-
* let cam2;
|
|
1489
|
-
* let isDefaultCamera = true;
|
|
1490
|
-
*
|
|
1491
|
-
* function setup() {
|
|
1492
|
-
* createCanvas(100, 100, WEBGL);
|
|
1493
|
-
*
|
|
1494
|
-
* // Create the first camera.
|
|
1495
|
-
* // Keep its default settings.
|
|
1496
|
-
* cam1 = createCamera();
|
|
1497
|
-
*
|
|
1498
|
-
* // Create the second camera.
|
|
1499
|
-
* cam2 = createCamera();
|
|
1500
|
-
*
|
|
1501
|
-
* // Adjust the frustum.
|
|
1502
|
-
* // Center it.
|
|
1503
|
-
* // Set its width and height to 20 pixels.
|
|
1504
|
-
* // Place its near plane 300 pixels from the camera.
|
|
1505
|
-
* // Place its far plane 350 pixels from the camera.
|
|
1506
|
-
* cam2.frustum(-10, 10, -10, 10, 300, 350);
|
|
1507
|
-
*
|
|
1508
|
-
* // Set the current camera to cam1.
|
|
1509
|
-
* setCamera(cam1);
|
|
1510
|
-
*
|
|
1511
|
-
* describe(
|
|
1512
|
-
* 'A row of white cubes against a gray background. The camera zooms in on one cube when the user double-clicks.'
|
|
1513
|
-
* );
|
|
1514
|
-
* }
|
|
1515
|
-
*
|
|
1516
|
-
* function draw() {
|
|
1517
|
-
* background(200);
|
|
1518
|
-
*
|
|
1519
|
-
* // Translate the origin toward the camera.
|
|
1520
|
-
* translate(-10, 10, 600);
|
|
1521
|
-
*
|
|
1522
|
-
* // Rotate the coordinate system.
|
|
1523
|
-
* rotateY(-0.1);
|
|
1524
|
-
* rotateX(-0.1);
|
|
1525
|
-
*
|
|
1526
|
-
* // Draw the row of boxes.
|
|
1527
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
1528
|
-
* translate(0, 0, -40);
|
|
1529
|
-
* box(10);
|
|
1530
|
-
* }
|
|
1531
|
-
* }
|
|
1532
|
-
*
|
|
1533
|
-
* // Toggle the current camera when the user double-clicks.
|
|
1534
|
-
* function doubleClicked() {
|
|
1535
|
-
* if (isDefaultCamera === true) {
|
|
1536
|
-
* setCamera(cam2);
|
|
1537
|
-
* isDefaultCamera = false;
|
|
1538
|
-
* } else {
|
|
1539
|
-
* setCamera(cam1);
|
|
1540
|
-
* isDefaultCamera = true;
|
|
1541
|
-
* }
|
|
1542
|
-
* }
|
|
1543
|
-
* </code>
|
|
1544
|
-
* </div>
|
|
1545
|
-
*/
|
|
1546
|
-
frustum(left, right, bottom, top, near, far) {
|
|
1547
|
-
if (left === undefined) left = -this._renderer.width * 0.05;
|
|
1548
|
-
if (right === undefined) right = +this._renderer.width * 0.05;
|
|
1549
|
-
if (bottom === undefined) bottom = +this._renderer.height * 0.05;
|
|
1550
|
-
if (top === undefined) top = -this._renderer.height * 0.05;
|
|
1551
|
-
if (near === undefined) near = this.defaultCameraNear;
|
|
1552
|
-
if (far === undefined) far = this.defaultCameraFar;
|
|
1553
|
-
|
|
1554
|
-
this.cameraNear = near;
|
|
1555
|
-
this.cameraFar = far;
|
|
1556
|
-
|
|
1557
|
-
const w = right - left;
|
|
1558
|
-
const h = top - bottom;
|
|
1559
|
-
const d = far - near;
|
|
1560
|
-
|
|
1561
|
-
const x = +(2.0 * near) / w;
|
|
1562
|
-
const y = +(2.0 * near) / h * this.yScale;
|
|
1563
|
-
const z = -(2.0 * far * near) / d;
|
|
1564
|
-
|
|
1565
|
-
const tx = (right + left) / w;
|
|
1566
|
-
const ty = (top + bottom) / h;
|
|
1567
|
-
const tz = -(far + near) / d;
|
|
1568
|
-
|
|
1569
|
-
this.projMatrix = new Matrix(4);
|
|
1570
|
-
|
|
1571
|
-
/* eslint-disable indent */
|
|
1572
|
-
this.projMatrix.set(x, 0, 0, 0,
|
|
1573
|
-
0, -y, 0, 0,
|
|
1574
|
-
tx, ty, tz, -1,
|
|
1575
|
-
0, 0, z, 0);
|
|
1576
|
-
/* eslint-enable indent */
|
|
1577
|
-
|
|
1578
|
-
if (this._isActive()) {
|
|
1579
|
-
this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
|
|
1580
|
-
this._renderer.states.uPMatrix.set(this.projMatrix);
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
this.cameraType = 'custom';
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
1587
|
-
// Camera Orientation Methods
|
|
1588
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
1589
|
-
|
|
1590
|
-
/**
|
|
1591
|
-
* Rotate camera view about arbitrary axis defined by x,y,z
|
|
1592
|
-
* based on http://learnwebgl.brown37.net/07_cameras/camera_rotating_motion.html
|
|
1593
|
-
* @private
|
|
1594
|
-
*/
|
|
1595
|
-
_rotateView(a, x, y, z) {
|
|
1596
|
-
let centerX = this.centerX;
|
|
1597
|
-
let centerY = this.centerY;
|
|
1598
|
-
let centerZ = this.centerZ;
|
|
1599
|
-
|
|
1600
|
-
// move center by eye position such that rotation happens around eye position
|
|
1601
|
-
centerX -= this.eyeX;
|
|
1602
|
-
centerY -= this.eyeY;
|
|
1603
|
-
centerZ -= this.eyeZ;
|
|
1604
|
-
|
|
1605
|
-
const rotation = new Matrix(4); // TODO Maybe pass p5
|
|
1606
|
-
rotation.rotate4x4(this._renderer._pInst._toRadians(a), x, y, z);
|
|
1607
|
-
|
|
1608
|
-
/* eslint-disable max-len */
|
|
1609
|
-
const rotatedCenter = [
|
|
1610
|
-
centerX * rotation.mat4[0] + centerY * rotation.mat4[4] + centerZ * rotation.mat4[8],
|
|
1611
|
-
centerX * rotation.mat4[1] + centerY * rotation.mat4[5] + centerZ * rotation.mat4[9],
|
|
1612
|
-
centerX * rotation.mat4[2] + centerY * rotation.mat4[6] + centerZ * rotation.mat4[10]
|
|
1613
|
-
];
|
|
1614
|
-
/* eslint-enable max-len */
|
|
1615
|
-
|
|
1616
|
-
// add eye position back into center
|
|
1617
|
-
rotatedCenter[0] += this.eyeX;
|
|
1618
|
-
rotatedCenter[1] += this.eyeY;
|
|
1619
|
-
rotatedCenter[2] += this.eyeZ;
|
|
1620
|
-
|
|
1621
|
-
this.camera(
|
|
1622
|
-
this.eyeX,
|
|
1623
|
-
this.eyeY,
|
|
1624
|
-
this.eyeZ,
|
|
1625
|
-
rotatedCenter[0],
|
|
1626
|
-
rotatedCenter[1],
|
|
1627
|
-
rotatedCenter[2],
|
|
1628
|
-
this.upX,
|
|
1629
|
-
this.upY,
|
|
1630
|
-
this.upZ
|
|
1631
|
-
);
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
/**
|
|
1635
|
-
* Rotates the camera in a clockwise/counter-clockwise direction.
|
|
1636
|
-
*
|
|
1637
|
-
* Rolling rotates the camera without changing its orientation. The rotation
|
|
1638
|
-
* happens in the camera’s "local" space.
|
|
1639
|
-
*
|
|
1640
|
-
* The parameter, `angle`, is the angle the camera should rotate. Passing a
|
|
1641
|
-
* positive angle, as in `myCamera.roll(0.001)`, rotates the camera in counter-clockwise direction.
|
|
1642
|
-
* Passing a negative angle, as in `myCamera.roll(-0.001)`, rotates the
|
|
1643
|
-
* camera in clockwise direction.
|
|
1644
|
-
*
|
|
1645
|
-
* Note: Angles are interpreted based on the current
|
|
1646
|
-
* <a href="#/p5/angleMode">angleMode()</a>.
|
|
1647
|
-
*
|
|
1648
|
-
* @method roll
|
|
1649
|
-
* @param {Number} angle amount to rotate camera in current
|
|
1650
|
-
* <a href="#/p5/angleMode">angleMode</a> units.
|
|
1651
|
-
* @example
|
|
1652
|
-
* <div>
|
|
1653
|
-
* <code>
|
|
1654
|
-
* let cam;
|
|
1655
|
-
* let delta = 0.01;
|
|
1656
|
-
*
|
|
1657
|
-
* function setup() {
|
|
1658
|
-
* createCanvas(100, 100, WEBGL);
|
|
1659
|
-
* normalMaterial();
|
|
1660
|
-
* // Create a p5.Camera object.
|
|
1661
|
-
* cam = createCamera();
|
|
1662
|
-
*
|
|
1663
|
-
* // Set the camera
|
|
1664
|
-
* setCamera(cam);
|
|
1665
|
-
* }
|
|
1666
|
-
*
|
|
1667
|
-
* function draw() {
|
|
1668
|
-
* background(200);
|
|
1669
|
-
*
|
|
1670
|
-
* // Roll camera according to angle 'delta'
|
|
1671
|
-
* cam.roll(delta);
|
|
1672
|
-
*
|
|
1673
|
-
* translate(0, 0, 0);
|
|
1674
|
-
* box(20);
|
|
1675
|
-
* translate(0, 25, 0);
|
|
1676
|
-
* box(20);
|
|
1677
|
-
* translate(0, 26, 0);
|
|
1678
|
-
* box(20);
|
|
1679
|
-
* translate(0, 27, 0);
|
|
1680
|
-
* box(20);
|
|
1681
|
-
* translate(0, 28, 0);
|
|
1682
|
-
* box(20);
|
|
1683
|
-
* translate(0,29, 0);
|
|
1684
|
-
* box(20);
|
|
1685
|
-
* translate(0, 30, 0);
|
|
1686
|
-
* box(20);
|
|
1687
|
-
* }
|
|
1688
|
-
* </code>
|
|
1689
|
-
* </div>
|
|
1690
|
-
*
|
|
1691
|
-
* @alt
|
|
1692
|
-
* camera view rotates in counter clockwise direction with vertically stacked boxes in front of it.
|
|
1693
|
-
*/
|
|
1694
|
-
roll(amount) {
|
|
1695
|
-
const local = this._getLocalAxes();
|
|
1696
|
-
const axisQuaternion = Quat.fromAxisAngle(
|
|
1697
|
-
this._renderer._pInst._toRadians(amount),
|
|
1698
|
-
local.z[0], local.z[1], local.z[2]);
|
|
1699
|
-
// const upQuat = new p5.Quat(0, this.upX, this.upY, this.upZ);
|
|
1700
|
-
const newUpVector = axisQuaternion.rotateVector(
|
|
1701
|
-
new Vector(this.upX, this.upY, this.upZ));
|
|
1702
|
-
this.camera(
|
|
1703
|
-
this.eyeX,
|
|
1704
|
-
this.eyeY,
|
|
1705
|
-
this.eyeZ,
|
|
1706
|
-
this.centerX,
|
|
1707
|
-
this.centerY,
|
|
1708
|
-
this.centerZ,
|
|
1709
|
-
newUpVector.x,
|
|
1710
|
-
newUpVector.y,
|
|
1711
|
-
newUpVector.z
|
|
1712
|
-
);
|
|
1713
|
-
}
|
|
1714
|
-
|
|
1715
|
-
/**
|
|
1716
|
-
* Rotates the camera left and right.
|
|
1717
|
-
*
|
|
1718
|
-
* Panning rotates the camera without changing its position. The rotation
|
|
1719
|
-
* happens in the camera’s "local" space.
|
|
1720
|
-
*
|
|
1721
|
-
* The parameter, `angle`, is the angle the camera should rotate. Passing a
|
|
1722
|
-
* positive angle, as in `myCamera.pan(0.001)`, rotates the camera to the
|
|
1723
|
-
* right. Passing a negative angle, as in `myCamera.pan(-0.001)`, rotates the
|
|
1724
|
-
* camera to the left.
|
|
1725
|
-
*
|
|
1726
|
-
* Note: Angles are interpreted based on the current
|
|
1727
|
-
* <a href="#/p5/angleMode">angleMode()</a>.
|
|
1728
|
-
*
|
|
1729
|
-
* @param {Number} angle amount to rotate in the current
|
|
1730
|
-
* <a href="#/p5/angleMode">angleMode()</a>.
|
|
1731
|
-
*
|
|
1732
|
-
* @example
|
|
1733
|
-
* <div>
|
|
1734
|
-
* <code>
|
|
1735
|
-
* let cam;
|
|
1736
|
-
* let delta = 0.001;
|
|
1737
|
-
*
|
|
1738
|
-
* function setup() {
|
|
1739
|
-
* createCanvas(100, 100, WEBGL);
|
|
1740
|
-
*
|
|
1741
|
-
* // Create a p5.Camera object.
|
|
1742
|
-
* cam = createCamera();
|
|
1743
|
-
*
|
|
1744
|
-
* // Set the camera
|
|
1745
|
-
* setCamera(cam);
|
|
1746
|
-
*
|
|
1747
|
-
* // Place the camera at the top-center.
|
|
1748
|
-
* cam.setPosition(0, -400, 800);
|
|
1749
|
-
*
|
|
1750
|
-
* // Point the camera at the origin.
|
|
1751
|
-
* cam.lookAt(0, 0, 0);
|
|
1752
|
-
*
|
|
1753
|
-
* describe(
|
|
1754
|
-
* 'A white cube on a gray background. The cube goes in and out of view as the camera pans left and right.'
|
|
1755
|
-
* );
|
|
1756
|
-
* }
|
|
1757
|
-
*
|
|
1758
|
-
* function draw() {
|
|
1759
|
-
* background(200);
|
|
1760
|
-
*
|
|
1761
|
-
* // Pan with the camera.
|
|
1762
|
-
* cam.pan(delta);
|
|
1763
|
-
*
|
|
1764
|
-
* // Switch directions every 120 frames.
|
|
1765
|
-
* if (frameCount % 120 === 0) {
|
|
1766
|
-
* delta *= -1;
|
|
1767
|
-
* }
|
|
1768
|
-
*
|
|
1769
|
-
* // Draw the box.
|
|
1770
|
-
* box();
|
|
1771
|
-
* }
|
|
1772
|
-
* </code>
|
|
1773
|
-
* </div>
|
|
1774
|
-
*/
|
|
1775
|
-
pan(amount) {
|
|
1776
|
-
const local = this._getLocalAxes();
|
|
1777
|
-
this._rotateView(amount, local.y[0], local.y[1], local.y[2]);
|
|
1778
|
-
}
|
|
1779
|
-
|
|
1780
|
-
/**
|
|
1781
|
-
* Rotates the camera up and down.
|
|
1782
|
-
*
|
|
1783
|
-
* Tilting rotates the camera without changing its position. The rotation
|
|
1784
|
-
* happens in the camera’s "local" space.
|
|
1785
|
-
*
|
|
1786
|
-
* The parameter, `angle`, is the angle the camera should rotate. Passing a
|
|
1787
|
-
* positive angle, as in `myCamera.tilt(0.001)`, rotates the camera down.
|
|
1788
|
-
* Passing a negative angle, as in `myCamera.tilt(-0.001)`, rotates the camera
|
|
1789
|
-
* up.
|
|
1790
|
-
*
|
|
1791
|
-
* Note: Angles are interpreted based on the current
|
|
1792
|
-
* <a href="#/p5/angleMode">angleMode()</a>.
|
|
1793
|
-
*
|
|
1794
|
-
* @param {Number} angle amount to rotate in the current
|
|
1795
|
-
* <a href="#/p5/angleMode">angleMode()</a>.
|
|
1796
|
-
*
|
|
1797
|
-
* @example
|
|
1798
|
-
* <div>
|
|
1799
|
-
* <code>
|
|
1800
|
-
* let cam;
|
|
1801
|
-
* let delta = 0.001;
|
|
1802
|
-
*
|
|
1803
|
-
* function setup() {
|
|
1804
|
-
* createCanvas(100, 100, WEBGL);
|
|
1805
|
-
*
|
|
1806
|
-
* // Create a p5.Camera object.
|
|
1807
|
-
* cam = createCamera();
|
|
1808
|
-
*
|
|
1809
|
-
* // Set the camera
|
|
1810
|
-
* setCamera(cam);
|
|
1811
|
-
*
|
|
1812
|
-
* // Place the camera at the top-center.
|
|
1813
|
-
* cam.setPosition(0, -400, 800);
|
|
1814
|
-
*
|
|
1815
|
-
* // Point the camera at the origin.
|
|
1816
|
-
* cam.lookAt(0, 0, 0);
|
|
1817
|
-
*
|
|
1818
|
-
* describe(
|
|
1819
|
-
* 'A white cube on a gray background. The cube goes in and out of view as the camera tilts up and down.'
|
|
1820
|
-
* );
|
|
1821
|
-
* }
|
|
1822
|
-
*
|
|
1823
|
-
* function draw() {
|
|
1824
|
-
* background(200);
|
|
1825
|
-
*
|
|
1826
|
-
* // Pan with the camera.
|
|
1827
|
-
* cam.tilt(delta);
|
|
1828
|
-
*
|
|
1829
|
-
* // Switch directions every 120 frames.
|
|
1830
|
-
* if (frameCount % 120 === 0) {
|
|
1831
|
-
* delta *= -1;
|
|
1832
|
-
* }
|
|
1833
|
-
*
|
|
1834
|
-
* // Draw the box.
|
|
1835
|
-
* box();
|
|
1836
|
-
* }
|
|
1837
|
-
* </code>
|
|
1838
|
-
* </div>
|
|
1839
|
-
*/
|
|
1840
|
-
tilt(amount) {
|
|
1841
|
-
const local = this._getLocalAxes();
|
|
1842
|
-
this._rotateView(amount, local.x[0], local.x[1], local.x[2]);
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
/**
|
|
1846
|
-
* Points the camera at a location.
|
|
1847
|
-
*
|
|
1848
|
-
* `myCamera.lookAt()` changes the camera’s orientation without changing its
|
|
1849
|
-
* position.
|
|
1850
|
-
*
|
|
1851
|
-
* The parameters, `x`, `y`, and `z`, are the coordinates in "world" space
|
|
1852
|
-
* where the camera should point. For example, calling
|
|
1853
|
-
* `myCamera.lookAt(10, 20, 30)` points the camera at the coordinates
|
|
1854
|
-
* `(10, 20, 30)`.
|
|
1855
|
-
*
|
|
1856
|
-
* @for p5.Camera
|
|
1857
|
-
* @param {Number} x x-coordinate of the position where the camera should look in "world" space.
|
|
1858
|
-
* @param {Number} y y-coordinate of the position where the camera should look in "world" space.
|
|
1859
|
-
* @param {Number} z z-coordinate of the position where the camera should look in "world" space.
|
|
1860
|
-
*
|
|
1861
|
-
* @example
|
|
1862
|
-
* <div>
|
|
1863
|
-
* <code>
|
|
1864
|
-
* // Double-click to look at a different cube.
|
|
1865
|
-
*
|
|
1866
|
-
* let cam;
|
|
1867
|
-
* let isLookingLeft = true;
|
|
1868
|
-
*
|
|
1869
|
-
* function setup() {
|
|
1870
|
-
* createCanvas(100, 100, WEBGL);
|
|
1871
|
-
*
|
|
1872
|
-
* // Create a p5.Camera object.
|
|
1873
|
-
* cam = createCamera();
|
|
1874
|
-
*
|
|
1875
|
-
* // Set the camera
|
|
1876
|
-
* setCamera(cam);
|
|
1877
|
-
*
|
|
1878
|
-
* // Place the camera at the top-center.
|
|
1879
|
-
* cam.setPosition(0, -400, 800);
|
|
1880
|
-
*
|
|
1881
|
-
* // Point the camera at the origin.
|
|
1882
|
-
* cam.lookAt(-30, 0, 0);
|
|
1883
|
-
*
|
|
1884
|
-
* describe(
|
|
1885
|
-
* 'A red cube and a blue cube on a gray background. The camera switches focus between the cubes when the user double-clicks.'
|
|
1886
|
-
* );
|
|
1887
|
-
* }
|
|
1888
|
-
*
|
|
1889
|
-
* function draw() {
|
|
1890
|
-
* background(200);
|
|
1891
|
-
*
|
|
1892
|
-
* // Draw the box on the left.
|
|
1893
|
-
* push();
|
|
1894
|
-
* // Translate the origin to the left.
|
|
1895
|
-
* translate(-30, 0, 0);
|
|
1896
|
-
* // Style the box.
|
|
1897
|
-
* fill(255, 0, 0);
|
|
1898
|
-
* // Draw the box.
|
|
1899
|
-
* box(20);
|
|
1900
|
-
* pop();
|
|
1901
|
-
*
|
|
1902
|
-
* // Draw the box on the right.
|
|
1903
|
-
* push();
|
|
1904
|
-
* // Translate the origin to the right.
|
|
1905
|
-
* translate(30, 0, 0);
|
|
1906
|
-
* // Style the box.
|
|
1907
|
-
* fill(0, 0, 255);
|
|
1908
|
-
* // Draw the box.
|
|
1909
|
-
* box(20);
|
|
1910
|
-
* pop();
|
|
1911
|
-
* }
|
|
1912
|
-
*
|
|
1913
|
-
* // Change the camera's focus when the user double-clicks.
|
|
1914
|
-
* function doubleClicked() {
|
|
1915
|
-
* if (isLookingLeft === true) {
|
|
1916
|
-
* cam.lookAt(30, 0, 0);
|
|
1917
|
-
* isLookingLeft = false;
|
|
1918
|
-
* } else {
|
|
1919
|
-
* cam.lookAt(-30, 0, 0);
|
|
1920
|
-
* isLookingLeft = true;
|
|
1921
|
-
* }
|
|
1922
|
-
* }
|
|
1923
|
-
* </code>
|
|
1924
|
-
* </div>
|
|
1925
|
-
*/
|
|
1926
|
-
lookAt(x, y, z) {
|
|
1927
|
-
this.camera(
|
|
1928
|
-
this.eyeX,
|
|
1929
|
-
this.eyeY,
|
|
1930
|
-
this.eyeZ,
|
|
1931
|
-
x,
|
|
1932
|
-
y,
|
|
1933
|
-
z,
|
|
1934
|
-
this.upX,
|
|
1935
|
-
this.upY,
|
|
1936
|
-
this.upZ
|
|
1937
|
-
);
|
|
1938
|
-
}
|
|
1939
|
-
|
|
1940
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
1941
|
-
// Camera Position Methods
|
|
1942
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
1943
|
-
|
|
1944
|
-
/**
|
|
1945
|
-
* Sets the position and orientation of the camera.
|
|
1946
|
-
*
|
|
1947
|
-
* `myCamera.camera()` allows objects to be viewed from different angles. It
|
|
1948
|
-
* has nine parameters that are all optional.
|
|
1949
|
-
*
|
|
1950
|
-
* The first three parameters, `x`, `y`, and `z`, are the coordinates of the
|
|
1951
|
-
* camera’s position in "world" space. For example, calling
|
|
1952
|
-
* `myCamera.camera(0, 0, 0)` places the camera at the origin `(0, 0, 0)`. By
|
|
1953
|
-
* default, the camera is placed at `(0, 0, 800)`.
|
|
1954
|
-
*
|
|
1955
|
-
* The next three parameters, `centerX`, `centerY`, and `centerZ` are the
|
|
1956
|
-
* coordinates of the point where the camera faces in "world" space. For
|
|
1957
|
-
* example, calling `myCamera.camera(0, 0, 0, 10, 20, 30)` places the camera
|
|
1958
|
-
* at the origin `(0, 0, 0)` and points it at `(10, 20, 30)`. By default, the
|
|
1959
|
-
* camera points at the origin `(0, 0, 0)`.
|
|
1960
|
-
*
|
|
1961
|
-
* The last three parameters, `upX`, `upY`, and `upZ` are the components of
|
|
1962
|
-
* the "up" vector in "local" space. The "up" vector orients the camera’s
|
|
1963
|
-
* y-axis. For example, calling
|
|
1964
|
-
* `myCamera.camera(0, 0, 0, 10, 20, 30, 0, -1, 0)` places the camera at the
|
|
1965
|
-
* origin `(0, 0, 0)`, points it at `(10, 20, 30)`, and sets the "up" vector
|
|
1966
|
-
* to `(0, -1, 0)` which is like holding it upside-down. By default, the "up"
|
|
1967
|
-
* vector is `(0, 1, 0)`.
|
|
1968
|
-
*
|
|
1969
|
-
* @for p5.Camera
|
|
1970
|
-
* @param {Number} [x] x-coordinate of the camera. Defaults to 0.
|
|
1971
|
-
* @param {Number} [y] y-coordinate of the camera. Defaults to 0.
|
|
1972
|
-
* @param {Number} [z] z-coordinate of the camera. Defaults to 800.
|
|
1973
|
-
* @param {Number} [centerX] x-coordinate of the point the camera faces. Defaults to 0.
|
|
1974
|
-
* @param {Number} [centerY] y-coordinate of the point the camera faces. Defaults to 0.
|
|
1975
|
-
* @param {Number} [centerZ] z-coordinate of the point the camera faces. Defaults to 0.
|
|
1976
|
-
* @param {Number} [upX] x-component of the camera’s "up" vector. Defaults to 0.
|
|
1977
|
-
* @param {Number} [upY] x-component of the camera’s "up" vector. Defaults to 1.
|
|
1978
|
-
* @param {Number} [upZ] z-component of the camera’s "up" vector. Defaults to 0.
|
|
1979
|
-
*
|
|
1980
|
-
* @example
|
|
1981
|
-
* <div>
|
|
1982
|
-
* <code>
|
|
1983
|
-
* // Double-click to toggle between cameras.
|
|
1984
|
-
*
|
|
1985
|
-
* let cam1;
|
|
1986
|
-
* let cam2;
|
|
1987
|
-
* let isDefaultCamera = true;
|
|
1988
|
-
*
|
|
1989
|
-
* function setup() {
|
|
1990
|
-
* createCanvas(100, 100, WEBGL);
|
|
1991
|
-
*
|
|
1992
|
-
* // Create the first camera.
|
|
1993
|
-
* // Keep its default settings.
|
|
1994
|
-
* cam1 = createCamera();
|
|
1995
|
-
*
|
|
1996
|
-
* // Create the second camera.
|
|
1997
|
-
* cam2 = createCamera();
|
|
1998
|
-
*
|
|
1999
|
-
* // Place it at the top-right: (1200, -600, 100)
|
|
2000
|
-
* // Point it at the row of boxes: (-10, -10, 400)
|
|
2001
|
-
* // Set its "up" vector to the default: (0, 1, 0)
|
|
2002
|
-
* cam2.camera(1200, -600, 100, -10, -10, 400, 0, 1, 0);
|
|
2003
|
-
*
|
|
2004
|
-
* // Set the current camera to cam1.
|
|
2005
|
-
* setCamera(cam1);
|
|
2006
|
-
*
|
|
2007
|
-
* describe(
|
|
2008
|
-
* 'A row of white cubes against a gray background. The camera toggles between a frontal and an aerial view when the user double-clicks.'
|
|
2009
|
-
* );
|
|
2010
|
-
* }
|
|
2011
|
-
*
|
|
2012
|
-
* function draw() {
|
|
2013
|
-
* background(200);
|
|
2014
|
-
*
|
|
2015
|
-
* // Translate the origin toward the camera.
|
|
2016
|
-
* translate(-10, 10, 500);
|
|
2017
|
-
*
|
|
2018
|
-
* // Rotate the coordinate system.
|
|
2019
|
-
* rotateY(-0.1);
|
|
2020
|
-
* rotateX(-0.1);
|
|
2021
|
-
*
|
|
2022
|
-
* // Draw the row of boxes.
|
|
2023
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
2024
|
-
* translate(0, 0, -30);
|
|
2025
|
-
* box(10);
|
|
2026
|
-
* }
|
|
2027
|
-
* }
|
|
2028
|
-
*
|
|
2029
|
-
* // Toggle the current camera when the user double-clicks.
|
|
2030
|
-
* function doubleClicked() {
|
|
2031
|
-
* if (isDefaultCamera === true) {
|
|
2032
|
-
* setCamera(cam2);
|
|
2033
|
-
* isDefaultCamera = false;
|
|
2034
|
-
* } else {
|
|
2035
|
-
* setCamera(cam1);
|
|
2036
|
-
* isDefaultCamera = true;
|
|
2037
|
-
* }
|
|
2038
|
-
* }
|
|
2039
|
-
* </code>
|
|
2040
|
-
* </div>
|
|
2041
|
-
*
|
|
2042
|
-
* <div>
|
|
2043
|
-
* <code>
|
|
2044
|
-
* // Double-click to toggle between cameras.
|
|
2045
|
-
*
|
|
2046
|
-
* let cam1;
|
|
2047
|
-
* let cam2;
|
|
2048
|
-
* let isDefaultCamera = true;
|
|
2049
|
-
*
|
|
2050
|
-
* function setup() {
|
|
2051
|
-
* createCanvas(100, 100, WEBGL);
|
|
2052
|
-
*
|
|
2053
|
-
* // Create the first camera.
|
|
2054
|
-
* // Keep its default settings.
|
|
2055
|
-
* cam1 = createCamera();
|
|
2056
|
-
*
|
|
2057
|
-
* // Create the second camera.
|
|
2058
|
-
* cam2 = createCamera();
|
|
2059
|
-
*
|
|
2060
|
-
* // Place it at the right: (1200, 0, 100)
|
|
2061
|
-
* // Point it at the row of boxes: (-10, -10, 400)
|
|
2062
|
-
* // Set its "up" vector to the default: (0, 1, 0)
|
|
2063
|
-
* cam2.camera(1200, 0, 100, -10, -10, 400, 0, 1, 0);
|
|
2064
|
-
*
|
|
2065
|
-
* // Set the current camera to cam1.
|
|
2066
|
-
* setCamera(cam1);
|
|
2067
|
-
*
|
|
2068
|
-
* describe(
|
|
2069
|
-
* 'A row of white cubes against a gray background. The camera toggles between a static frontal view and an orbiting view when the user double-clicks.'
|
|
2070
|
-
* );
|
|
2071
|
-
* }
|
|
2072
|
-
*
|
|
2073
|
-
* function draw() {
|
|
2074
|
-
* background(200);
|
|
2075
|
-
*
|
|
2076
|
-
* // Update cam2's position.
|
|
2077
|
-
* let x = 1200 * cos(frameCount * 0.01);
|
|
2078
|
-
* let y = -600 * sin(frameCount * 0.01);
|
|
2079
|
-
* cam2.camera(x, y, 100, -10, -10, 400, 0, 1, 0);
|
|
2080
|
-
*
|
|
2081
|
-
* // Translate the origin toward the camera.
|
|
2082
|
-
* translate(-10, 10, 500);
|
|
2083
|
-
*
|
|
2084
|
-
* // Rotate the coordinate system.
|
|
2085
|
-
* rotateY(-0.1);
|
|
2086
|
-
* rotateX(-0.1);
|
|
2087
|
-
*
|
|
2088
|
-
* // Draw the row of boxes.
|
|
2089
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
2090
|
-
* translate(0, 0, -30);
|
|
2091
|
-
* box(10);
|
|
2092
|
-
* }
|
|
2093
|
-
* }
|
|
2094
|
-
*
|
|
2095
|
-
* // Toggle the current camera when the user double-clicks.
|
|
2096
|
-
* function doubleClicked() {
|
|
2097
|
-
* if (isDefaultCamera === true) {
|
|
2098
|
-
* setCamera(cam2);
|
|
2099
|
-
* isDefaultCamera = false;
|
|
2100
|
-
* } else {
|
|
2101
|
-
* setCamera(cam1);
|
|
2102
|
-
* isDefaultCamera = true;
|
|
2103
|
-
* }
|
|
2104
|
-
* }
|
|
2105
|
-
* </code>
|
|
2106
|
-
* </div>
|
|
2107
|
-
*/
|
|
2108
|
-
camera(
|
|
2109
|
-
eyeX,
|
|
2110
|
-
eyeY,
|
|
2111
|
-
eyeZ,
|
|
2112
|
-
centerX,
|
|
2113
|
-
centerY,
|
|
2114
|
-
centerZ,
|
|
2115
|
-
upX,
|
|
2116
|
-
upY,
|
|
2117
|
-
upZ
|
|
2118
|
-
) {
|
|
2119
|
-
if (typeof eyeX === 'undefined') {
|
|
2120
|
-
eyeX = this.defaultEyeX;
|
|
2121
|
-
eyeY = this.defaultEyeY;
|
|
2122
|
-
eyeZ = this.defaultEyeZ;
|
|
2123
|
-
centerX = eyeX;
|
|
2124
|
-
centerY = eyeY;
|
|
2125
|
-
centerZ = 0;
|
|
2126
|
-
upX = 0;
|
|
2127
|
-
upY = 1;
|
|
2128
|
-
upZ = 0;
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
this.eyeX = eyeX;
|
|
2132
|
-
this.eyeY = eyeY;
|
|
2133
|
-
this.eyeZ = eyeZ;
|
|
2134
|
-
|
|
2135
|
-
if (typeof centerX !== 'undefined') {
|
|
2136
|
-
this.centerX = centerX;
|
|
2137
|
-
this.centerY = centerY;
|
|
2138
|
-
this.centerZ = centerZ;
|
|
2139
|
-
}
|
|
2140
|
-
|
|
2141
|
-
if (typeof upX !== 'undefined') {
|
|
2142
|
-
this.upX = upX;
|
|
2143
|
-
this.upY = upY;
|
|
2144
|
-
this.upZ = upZ;
|
|
2145
|
-
}
|
|
2146
|
-
|
|
2147
|
-
const local = this._getLocalAxes();
|
|
2148
|
-
|
|
2149
|
-
// the camera affects the model view matrix, insofar as it
|
|
2150
|
-
// inverse translates the world to the eye position of the camera
|
|
2151
|
-
// and rotates it.
|
|
2152
|
-
/* eslint-disable indent */
|
|
2153
|
-
this.cameraMatrix.set(local.x[0], local.y[0], local.z[0], 0,
|
|
2154
|
-
local.x[1], local.y[1], local.z[1], 0,
|
|
2155
|
-
local.x[2], local.y[2], local.z[2], 0,
|
|
2156
|
-
0, 0, 0, 1);
|
|
2157
|
-
/* eslint-enable indent */
|
|
2158
|
-
|
|
2159
|
-
const tx = -eyeX;
|
|
2160
|
-
const ty = -eyeY;
|
|
2161
|
-
const tz = -eyeZ;
|
|
2162
|
-
|
|
2163
|
-
this.cameraMatrix.translate([tx, ty, tz]);
|
|
2164
|
-
|
|
2165
|
-
if (this._isActive()) {
|
|
2166
|
-
this._renderer.states.setValue('uViewMatrix', this._renderer.states.uViewMatrix.clone());
|
|
2167
|
-
this._renderer.states.uViewMatrix.set(this.cameraMatrix);
|
|
2168
|
-
}
|
|
2169
|
-
return this;
|
|
2170
|
-
}
|
|
2171
|
-
|
|
2172
|
-
/**
|
|
2173
|
-
* Moves the camera along its "local" axes without changing its orientation.
|
|
2174
|
-
*
|
|
2175
|
-
* The parameters, `x`, `y`, and `z`, are the distances the camera should
|
|
2176
|
-
* move. For example, calling `myCamera.move(10, 20, 30)` moves the camera 10
|
|
2177
|
-
* pixels to the right, 20 pixels down, and 30 pixels backward in its "local"
|
|
2178
|
-
* space.
|
|
2179
|
-
*
|
|
2180
|
-
* @param {Number} x distance to move along the camera’s "local" x-axis.
|
|
2181
|
-
* @param {Number} y distance to move along the camera’s "local" y-axis.
|
|
2182
|
-
* @param {Number} z distance to move along the camera’s "local" z-axis.
|
|
2183
|
-
* @example
|
|
2184
|
-
* <div>
|
|
2185
|
-
* <code>
|
|
2186
|
-
* // Click the canvas to begin detecting key presses.
|
|
2187
|
-
*
|
|
2188
|
-
* let cam;
|
|
2189
|
-
*
|
|
2190
|
-
* function setup() {
|
|
2191
|
-
* createCanvas(100, 100, WEBGL);
|
|
2192
|
-
*
|
|
2193
|
-
* // Create the first camera.
|
|
2194
|
-
* // Keep its default settings.
|
|
2195
|
-
* cam = createCamera();
|
|
2196
|
-
*
|
|
2197
|
-
* // Place the camera at the top-right.
|
|
2198
|
-
* cam.setPosition(400, -400, 800);
|
|
2199
|
-
*
|
|
2200
|
-
* // Point it at the origin.
|
|
2201
|
-
* cam.lookAt(0, 0, 0);
|
|
2202
|
-
*
|
|
2203
|
-
* // Set the camera.
|
|
2204
|
-
* setCamera(cam);
|
|
2205
|
-
*
|
|
2206
|
-
* describe(
|
|
2207
|
-
* 'A white cube drawn against a gray background. The cube appears to move when the user presses certain keys.'
|
|
2208
|
-
* );
|
|
2209
|
-
* }
|
|
2210
|
-
*
|
|
2211
|
-
* function draw() {
|
|
2212
|
-
* background(200);
|
|
2213
|
-
*
|
|
2214
|
-
* // Move the camera along its "local" axes
|
|
2215
|
-
* // when the user presses certain keys.
|
|
2216
|
-
*
|
|
2217
|
-
* // Move horizontally.
|
|
2218
|
-
* if (keyIsDown(LEFT_ARROW)) {
|
|
2219
|
-
* cam.move(-1, 0, 0);
|
|
2220
|
-
* }
|
|
2221
|
-
* if (keyIsDown(RIGHT_ARROW)) {
|
|
2222
|
-
* cam.move(1, 0, 0);
|
|
2223
|
-
* }
|
|
2224
|
-
*
|
|
2225
|
-
* // Move vertically.
|
|
2226
|
-
* if (keyIsDown(UP_ARROW)) {
|
|
2227
|
-
* cam.move(0, -1, 0);
|
|
2228
|
-
* }
|
|
2229
|
-
* if (keyIsDown(DOWN_ARROW)) {
|
|
2230
|
-
* cam.move(0, 1, 0);
|
|
2231
|
-
* }
|
|
2232
|
-
*
|
|
2233
|
-
* // Move in/out of the screen.
|
|
2234
|
-
* if (keyIsDown('i')) {
|
|
2235
|
-
* cam.move(0, 0, -1);
|
|
2236
|
-
* }
|
|
2237
|
-
* if (keyIsDown('o')) {
|
|
2238
|
-
* cam.move(0, 0, 1);
|
|
2239
|
-
* }
|
|
2240
|
-
*
|
|
2241
|
-
* // Draw the box.
|
|
2242
|
-
* box();
|
|
2243
|
-
* }
|
|
2244
|
-
* </code>
|
|
2245
|
-
* </div>
|
|
2246
|
-
*/
|
|
2247
|
-
move(x, y, z) {
|
|
2248
|
-
const local = this._getLocalAxes();
|
|
2249
|
-
|
|
2250
|
-
// scale local axes by movement amounts
|
|
2251
|
-
// based on http://learnwebgl.brown37.net/07_cameras/camera_linear_motion.html
|
|
2252
|
-
const dx = [local.x[0] * x, local.x[1] * x, local.x[2] * x];
|
|
2253
|
-
const dy = [local.y[0] * y, local.y[1] * y, local.y[2] * y];
|
|
2254
|
-
const dz = [local.z[0] * z, local.z[1] * z, local.z[2] * z];
|
|
2255
|
-
|
|
2256
|
-
this.camera(
|
|
2257
|
-
this.eyeX + dx[0] + dy[0] + dz[0],
|
|
2258
|
-
this.eyeY + dx[1] + dy[1] + dz[1],
|
|
2259
|
-
this.eyeZ + dx[2] + dy[2] + dz[2],
|
|
2260
|
-
this.centerX + dx[0] + dy[0] + dz[0],
|
|
2261
|
-
this.centerY + dx[1] + dy[1] + dz[1],
|
|
2262
|
-
this.centerZ + dx[2] + dy[2] + dz[2],
|
|
2263
|
-
this.upX,
|
|
2264
|
-
this.upY,
|
|
2265
|
-
this.upZ
|
|
2266
|
-
);
|
|
2267
|
-
}
|
|
2268
|
-
|
|
2269
|
-
/**
|
|
2270
|
-
* Sets the camera’s position in "world" space without changing its
|
|
2271
|
-
* orientation.
|
|
2272
|
-
*
|
|
2273
|
-
* The parameters, `x`, `y`, and `z`, are the coordinates where the camera
|
|
2274
|
-
* should be placed. For example, calling `myCamera.setPosition(10, 20, 30)`
|
|
2275
|
-
* places the camera at coordinates `(10, 20, 30)` in "world" space.
|
|
2276
|
-
*
|
|
2277
|
-
* @param {Number} x x-coordinate in "world" space.
|
|
2278
|
-
* @param {Number} y y-coordinate in "world" space.
|
|
2279
|
-
* @param {Number} z z-coordinate in "world" space.
|
|
2280
|
-
*
|
|
2281
|
-
* @example
|
|
2282
|
-
* <div>
|
|
2283
|
-
* <code>
|
|
2284
|
-
* // Double-click to toggle between cameras.
|
|
2285
|
-
*
|
|
2286
|
-
* let cam1;
|
|
2287
|
-
* let cam2;
|
|
2288
|
-
* let isDefaultCamera = true;
|
|
2289
|
-
*
|
|
2290
|
-
* function setup() {
|
|
2291
|
-
* createCanvas(100, 100, WEBGL);
|
|
2292
|
-
*
|
|
2293
|
-
* // Create the first camera.
|
|
2294
|
-
* // Keep its default settings.
|
|
2295
|
-
* cam1 = createCamera();
|
|
2296
|
-
*
|
|
2297
|
-
* // Create the second camera.
|
|
2298
|
-
* cam2 = createCamera();
|
|
2299
|
-
*
|
|
2300
|
-
* // Place it closer to the origin.
|
|
2301
|
-
* cam2.setPosition(0, 0, 600);
|
|
2302
|
-
*
|
|
2303
|
-
* // Set the current camera to cam1.
|
|
2304
|
-
* setCamera(cam1);
|
|
2305
|
-
*
|
|
2306
|
-
* describe(
|
|
2307
|
-
* 'A row of white cubes against a gray background. The camera toggles the amount of zoom when the user double-clicks.'
|
|
2308
|
-
* );
|
|
2309
|
-
* }
|
|
2310
|
-
*
|
|
2311
|
-
* function draw() {
|
|
2312
|
-
* background(200);
|
|
2313
|
-
*
|
|
2314
|
-
* // Translate the origin toward the camera.
|
|
2315
|
-
* translate(-10, 10, 500);
|
|
2316
|
-
*
|
|
2317
|
-
* // Rotate the coordinate system.
|
|
2318
|
-
* rotateY(-0.1);
|
|
2319
|
-
* rotateX(-0.1);
|
|
2320
|
-
*
|
|
2321
|
-
* // Draw the row of boxes.
|
|
2322
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
2323
|
-
* translate(0, 0, -30);
|
|
2324
|
-
* box(10);
|
|
2325
|
-
* }
|
|
2326
|
-
* }
|
|
2327
|
-
*
|
|
2328
|
-
* // Toggle the current camera when the user double-clicks.
|
|
2329
|
-
* function doubleClicked() {
|
|
2330
|
-
* if (isDefaultCamera === true) {
|
|
2331
|
-
* setCamera(cam2);
|
|
2332
|
-
* isDefaultCamera = false;
|
|
2333
|
-
* } else {
|
|
2334
|
-
* setCamera(cam1);
|
|
2335
|
-
* isDefaultCamera = true;
|
|
2336
|
-
* }
|
|
2337
|
-
* }
|
|
2338
|
-
* </code>
|
|
2339
|
-
* </div>
|
|
2340
|
-
*
|
|
2341
|
-
* <div>
|
|
2342
|
-
* <code>
|
|
2343
|
-
* // Double-click to toggle between cameras.
|
|
2344
|
-
*
|
|
2345
|
-
* let cam1;
|
|
2346
|
-
* let cam2;
|
|
2347
|
-
* let isDefaultCamera = true;
|
|
2348
|
-
*
|
|
2349
|
-
* function setup() {
|
|
2350
|
-
* createCanvas(100, 100, WEBGL);
|
|
2351
|
-
*
|
|
2352
|
-
* // Create the first camera.
|
|
2353
|
-
* // Keep its default settings.
|
|
2354
|
-
* cam1 = createCamera();
|
|
2355
|
-
*
|
|
2356
|
-
* // Create the second camera.
|
|
2357
|
-
* cam2 = createCamera();
|
|
2358
|
-
*
|
|
2359
|
-
* // Place it closer to the origin.
|
|
2360
|
-
* cam2.setPosition(0, 0, 600);
|
|
2361
|
-
*
|
|
2362
|
-
* // Set the current camera to cam1.
|
|
2363
|
-
* setCamera(cam1);
|
|
2364
|
-
*
|
|
2365
|
-
* describe(
|
|
2366
|
-
* 'A row of white cubes against a gray background. The camera toggles between a static view and a view that zooms in and out when the user double-clicks.'
|
|
2367
|
-
* );
|
|
2368
|
-
* }
|
|
2369
|
-
*
|
|
2370
|
-
* function draw() {
|
|
2371
|
-
* background(200);
|
|
2372
|
-
*
|
|
2373
|
-
* // Update cam2's z-coordinate.
|
|
2374
|
-
* let z = 100 * sin(frameCount * 0.01) + 700;
|
|
2375
|
-
* cam2.setPosition(0, 0, z);
|
|
2376
|
-
*
|
|
2377
|
-
* // Translate the origin toward the camera.
|
|
2378
|
-
* translate(-10, 10, 500);
|
|
2379
|
-
*
|
|
2380
|
-
* // Rotate the coordinate system.
|
|
2381
|
-
* rotateY(-0.1);
|
|
2382
|
-
* rotateX(-0.1);
|
|
2383
|
-
*
|
|
2384
|
-
* // Draw the row of boxes.
|
|
2385
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
2386
|
-
* translate(0, 0, -30);
|
|
2387
|
-
* box(10);
|
|
2388
|
-
* }
|
|
2389
|
-
* }
|
|
2390
|
-
*
|
|
2391
|
-
* // Toggle the current camera when the user double-clicks.
|
|
2392
|
-
* function doubleClicked() {
|
|
2393
|
-
* if (isDefaultCamera === true) {
|
|
2394
|
-
* setCamera(cam2);
|
|
2395
|
-
* isDefaultCamera = false;
|
|
2396
|
-
* } else {
|
|
2397
|
-
* setCamera(cam1);
|
|
2398
|
-
* isDefaultCamera = true;
|
|
2399
|
-
* }
|
|
2400
|
-
* }
|
|
2401
|
-
* </code>
|
|
2402
|
-
* </div>
|
|
2403
|
-
*/
|
|
2404
|
-
setPosition(x, y, z) {
|
|
2405
|
-
const diffX = x - this.eyeX;
|
|
2406
|
-
const diffY = y - this.eyeY;
|
|
2407
|
-
const diffZ = z - this.eyeZ;
|
|
2408
|
-
|
|
2409
|
-
this.camera(
|
|
2410
|
-
x,
|
|
2411
|
-
y,
|
|
2412
|
-
z,
|
|
2413
|
-
this.centerX + diffX,
|
|
2414
|
-
this.centerY + diffY,
|
|
2415
|
-
this.centerZ + diffZ,
|
|
2416
|
-
this.upX,
|
|
2417
|
-
this.upY,
|
|
2418
|
-
this.upZ
|
|
2419
|
-
);
|
|
2420
|
-
}
|
|
2421
|
-
|
|
2422
|
-
/**
|
|
2423
|
-
* Sets the camera’s position, orientation, and projection by copying another
|
|
2424
|
-
* camera.
|
|
2425
|
-
*
|
|
2426
|
-
* The parameter, `cam`, is the `p5.Camera` object to copy. For example, calling
|
|
2427
|
-
* `cam2.set(cam1)` will set `cam2` using `cam1`’s configuration.
|
|
2428
|
-
*
|
|
2429
|
-
* @param {p5.Camera} cam camera to copy.
|
|
2430
|
-
*
|
|
2431
|
-
* @example
|
|
2432
|
-
* <div>
|
|
2433
|
-
* <code>
|
|
2434
|
-
* // Double-click to "reset" the camera zoom.
|
|
2435
|
-
*
|
|
2436
|
-
* let cam1;
|
|
2437
|
-
* let cam2;
|
|
2438
|
-
*
|
|
2439
|
-
* function setup() {
|
|
2440
|
-
* createCanvas(100, 100, WEBGL);
|
|
2441
|
-
*
|
|
2442
|
-
* // Create the first camera.
|
|
2443
|
-
* cam1 = createCamera();
|
|
2444
|
-
*
|
|
2445
|
-
* // Place the camera at the top-right.
|
|
2446
|
-
* cam1.setPosition(400, -400, 800);
|
|
2447
|
-
*
|
|
2448
|
-
* // Point it at the origin.
|
|
2449
|
-
* cam1.lookAt(0, 0, 0);
|
|
2450
|
-
*
|
|
2451
|
-
* // Create the second camera.
|
|
2452
|
-
* cam2 = createCamera();
|
|
2453
|
-
*
|
|
2454
|
-
* // Copy cam1's configuration.
|
|
2455
|
-
* cam2.set(cam1);
|
|
2456
|
-
*
|
|
2457
|
-
* // Set the camera.
|
|
2458
|
-
* setCamera(cam2);
|
|
2459
|
-
*
|
|
2460
|
-
* describe(
|
|
2461
|
-
* 'A white cube drawn against a gray background. The camera slowly moves forward. The camera resets when the user double-clicks.'
|
|
2462
|
-
* );
|
|
2463
|
-
* }
|
|
2464
|
-
*
|
|
2465
|
-
* function draw() {
|
|
2466
|
-
* background(200);
|
|
2467
|
-
*
|
|
2468
|
-
* // Update cam2's position.
|
|
2469
|
-
* cam2.move(0, 0, -1);
|
|
2470
|
-
*
|
|
2471
|
-
* // Draw the box.
|
|
2472
|
-
* box();
|
|
2473
|
-
* }
|
|
2474
|
-
*
|
|
2475
|
-
* // "Reset" the camera when the user double-clicks.
|
|
2476
|
-
* function doubleClicked() {
|
|
2477
|
-
* cam2.set(cam1);
|
|
2478
|
-
* }
|
|
2479
|
-
*/
|
|
2480
|
-
set(cam) {
|
|
2481
|
-
const keyNamesOfThePropToCopy = [
|
|
2482
|
-
'eyeX', 'eyeY', 'eyeZ',
|
|
2483
|
-
'centerX', 'centerY', 'centerZ',
|
|
2484
|
-
'upX', 'upY', 'upZ',
|
|
2485
|
-
'cameraFOV', 'aspectRatio', 'cameraNear', 'cameraFar', 'cameraType',
|
|
2486
|
-
'yScale', 'useLinePerspective'
|
|
2487
|
-
];
|
|
2488
|
-
for (const keyName of keyNamesOfThePropToCopy) {
|
|
2489
|
-
this[keyName] = cam[keyName];
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
|
-
this.cameraMatrix = cam.cameraMatrix.copy();
|
|
2493
|
-
this.projMatrix = cam.projMatrix.copy();
|
|
2494
|
-
|
|
2495
|
-
if (this._isActive()) {
|
|
2496
|
-
this._renderer.states.setValue('uModelMatrix', this._renderer.states.uModelMatrix.clone());
|
|
2497
|
-
this._renderer.states.setValue('uViewMatrix', this._renderer.states.uViewMatrix.clone());
|
|
2498
|
-
this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
|
|
2499
|
-
this._renderer.states.uModelMatrix.reset();
|
|
2500
|
-
this._renderer.states.uViewMatrix.set(this.cameraMatrix);
|
|
2501
|
-
this._renderer.states.uPMatrix.set(this.projMatrix);
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
/**
|
|
2505
|
-
* Sets the camera’s position and orientation to values that are in-between
|
|
2506
|
-
* those of two other cameras.
|
|
2507
|
-
*
|
|
2508
|
-
* `myCamera.slerp()` uses spherical linear interpolation to calculate a
|
|
2509
|
-
* position and orientation that’s in-between two other cameras. Doing so is
|
|
2510
|
-
* helpful for transitioning smoothly between two perspectives.
|
|
2511
|
-
*
|
|
2512
|
-
* The first two parameters, `cam0` and `cam1`, are the `p5.Camera` objects
|
|
2513
|
-
* that should be used to set the current camera.
|
|
2514
|
-
*
|
|
2515
|
-
* The third parameter, `amt`, is the amount to interpolate between `cam0` and
|
|
2516
|
-
* `cam1`. 0.0 keeps the camera’s position and orientation equal to `cam0`’s,
|
|
2517
|
-
* 0.5 sets them halfway between `cam0`’s and `cam1`’s , and 1.0 sets the
|
|
2518
|
-
* position and orientation equal to `cam1`’s.
|
|
2519
|
-
*
|
|
2520
|
-
* For example, calling `myCamera.slerp(cam0, cam1, 0.1)` sets cam’s position
|
|
2521
|
-
* and orientation very close to `cam0`’s. Calling
|
|
2522
|
-
* `myCamera.slerp(cam0, cam1, 0.9)` sets cam’s position and orientation very
|
|
2523
|
-
* close to `cam1`’s.
|
|
2524
|
-
*
|
|
2525
|
-
* Note: All of the cameras must use the same projection.
|
|
2526
|
-
*
|
|
2527
|
-
* @param {p5.Camera} cam0 first camera.
|
|
2528
|
-
* @param {p5.Camera} cam1 second camera.
|
|
2529
|
-
* @param {Number} amt amount of interpolation between 0.0 (`cam0`) and 1.0 (`cam1`).
|
|
2530
|
-
*
|
|
2531
|
-
* @example
|
|
2532
|
-
* <div>
|
|
2533
|
-
* <code>
|
|
2534
|
-
* let cam;
|
|
2535
|
-
* let cam0;
|
|
2536
|
-
* let cam1;
|
|
2537
|
-
*
|
|
2538
|
-
* function setup() {
|
|
2539
|
-
* createCanvas(100, 100, WEBGL);
|
|
2540
|
-
*
|
|
2541
|
-
* // Create the main camera.
|
|
2542
|
-
* // Keep its default settings.
|
|
2543
|
-
* cam = createCamera();
|
|
2544
|
-
*
|
|
2545
|
-
* // Create the first camera.
|
|
2546
|
-
* // Keep its default settings.
|
|
2547
|
-
* cam0 = createCamera();
|
|
2548
|
-
*
|
|
2549
|
-
* // Create the second camera.
|
|
2550
|
-
* cam1 = createCamera();
|
|
2551
|
-
*
|
|
2552
|
-
* // Place it at the top-right.
|
|
2553
|
-
* cam1.setPosition(400, -400, 800);
|
|
2554
|
-
*
|
|
2555
|
-
* // Point it at the origin.
|
|
2556
|
-
* cam1.lookAt(0, 0, 0);
|
|
2557
|
-
*
|
|
2558
|
-
* // Set the current camera to cam.
|
|
2559
|
-
* setCamera(cam);
|
|
2560
|
-
*
|
|
2561
|
-
* describe('A white cube drawn against a gray background. The camera slowly oscillates between a frontal view and an aerial view.');
|
|
2562
|
-
* }
|
|
2563
|
-
*
|
|
2564
|
-
* function draw() {
|
|
2565
|
-
* background(200);
|
|
2566
|
-
*
|
|
2567
|
-
* // Calculate the amount to interpolate between cam0 and cam1.
|
|
2568
|
-
* let amt = 0.5 * sin(frameCount * 0.01) + 0.5;
|
|
2569
|
-
*
|
|
2570
|
-
* // Update the main camera's position and orientation.
|
|
2571
|
-
* cam.slerp(cam0, cam1, amt);
|
|
2572
|
-
*
|
|
2573
|
-
* box();
|
|
2574
|
-
* }
|
|
2575
|
-
* </code>
|
|
2576
|
-
* </div>
|
|
2577
|
-
*/
|
|
2578
|
-
slerp(cam0, cam1, amt) {
|
|
2579
|
-
// If t is 0 or 1, do not interpolate and set the argument camera.
|
|
2580
|
-
if (amt === 0) {
|
|
2581
|
-
this.set(cam0);
|
|
2582
|
-
return;
|
|
2583
|
-
} else if (amt === 1) {
|
|
2584
|
-
this.set(cam1);
|
|
2585
|
-
return;
|
|
2586
|
-
}
|
|
2587
|
-
|
|
2588
|
-
// For this cameras is ortho, assume that cam0 and cam1 are also ortho
|
|
2589
|
-
// and interpolate the elements of the projection matrix.
|
|
2590
|
-
// Use logarithmic interpolation for interpolation.
|
|
2591
|
-
if (this.projMatrix.mat4[15] !== 0) {
|
|
2592
|
-
this.projMatrix.setElement(
|
|
2593
|
-
0,
|
|
2594
|
-
cam0.projMatrix.mat4[0] *
|
|
2595
|
-
Math.pow(cam1.projMatrix.mat4[0] / cam0.projMatrix.mat4[0], amt)
|
|
2596
|
-
);
|
|
2597
|
-
this.projMatrix.setElement(
|
|
2598
|
-
5,
|
|
2599
|
-
cam0.projMatrix.mat4[5] *
|
|
2600
|
-
Math.pow(cam1.projMatrix.mat4[5] / cam0.projMatrix.mat4[5], amt)
|
|
2601
|
-
);
|
|
2602
|
-
// If the camera is active, make uPMatrix reflect changes in projMatrix.
|
|
2603
|
-
if (this._isActive()) {
|
|
2604
|
-
this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
|
|
2605
|
-
this._renderer.states.uPMatrix.mat4 = this.projMatrix.mat4.slice();
|
|
2606
|
-
}
|
|
2607
|
-
}
|
|
2608
|
-
|
|
2609
|
-
// prepare eye vector and center vector of argument cameras.
|
|
2610
|
-
const eye0 = new Vector(cam0.eyeX, cam0.eyeY, cam0.eyeZ);
|
|
2611
|
-
const eye1 = new Vector(cam1.eyeX, cam1.eyeY, cam1.eyeZ);
|
|
2612
|
-
const center0 = new Vector(cam0.centerX, cam0.centerY, cam0.centerZ);
|
|
2613
|
-
const center1 = new Vector(cam1.centerX, cam1.centerY, cam1.centerZ);
|
|
2614
|
-
|
|
2615
|
-
// Calculate the distance between eye and center for each camera.
|
|
2616
|
-
// Logarithmically interpolate these with amt.
|
|
2617
|
-
const dist0 = Vector.dist(eye0, center0);
|
|
2618
|
-
const dist1 = Vector.dist(eye1, center1);
|
|
2619
|
-
const lerpedDist = dist0 * Math.pow(dist1 / dist0, amt);
|
|
2620
|
-
|
|
2621
|
-
// Next, calculate the ratio to interpolate the eye and center by a constant
|
|
2622
|
-
// ratio for each camera. This ratio is the same for both. Also, with this ratio
|
|
2623
|
-
// of points, the distance is the minimum distance of the two points of
|
|
2624
|
-
// the same ratio.
|
|
2625
|
-
// With this method, if the viewpoint is fixed, linear interpolation is performed
|
|
2626
|
-
// at the viewpoint, and if the center is fixed, linear interpolation is performed
|
|
2627
|
-
// at the center, resulting in reasonable interpolation. If both move, the point
|
|
2628
|
-
// halfway between them is taken.
|
|
2629
|
-
const eyeDiff = Vector.sub(eye0, eye1);
|
|
2630
|
-
const diffDiff = eye0.copy().sub(eye1).sub(center0).add(center1);
|
|
2631
|
-
// Suppose there are two line segments. Consider the distance between the points
|
|
2632
|
-
// above them as if they were taken in the same ratio. This calculation figures out
|
|
2633
|
-
// a ratio that minimizes this.
|
|
2634
|
-
// Each line segment is, a line segment connecting the viewpoint and the center
|
|
2635
|
-
// for each camera.
|
|
2636
|
-
const divider = diffDiff.magSq();
|
|
2637
|
-
let ratio = 1; // default.
|
|
2638
|
-
if (divider > 0.000001) {
|
|
2639
|
-
ratio = Vector.dot(eyeDiff, diffDiff) / divider;
|
|
2640
|
-
ratio = Math.max(0, Math.min(ratio, 1));
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
|
-
// Take the appropriate proportions and work out the points
|
|
2644
|
-
// that are between the new viewpoint and the new center position.
|
|
2645
|
-
const lerpedMedium = Vector.lerp(
|
|
2646
|
-
Vector.lerp(eye0, center0, ratio),
|
|
2647
|
-
Vector.lerp(eye1, center1, ratio),
|
|
2648
|
-
amt
|
|
2649
|
-
);
|
|
2650
|
-
|
|
2651
|
-
// Prepare each of rotation matrix from their camera matrix
|
|
2652
|
-
const rotMat0 = cam0.cameraMatrix.createSubMatrix3x3();
|
|
2653
|
-
const rotMat1 = cam1.cameraMatrix.createSubMatrix3x3();
|
|
2654
|
-
|
|
2655
|
-
// get front and up vector from local-coordinate-system.
|
|
2656
|
-
const front0 = rotMat0.row(2);
|
|
2657
|
-
const front1 = rotMat1.row(2);
|
|
2658
|
-
const up0 = rotMat0.row(1);
|
|
2659
|
-
const up1 = rotMat1.row(1);
|
|
2660
|
-
|
|
2661
|
-
// prepare new vectors.
|
|
2662
|
-
const newFront = new Vector();
|
|
2663
|
-
const newUp = new Vector();
|
|
2664
|
-
const newEye = new Vector();
|
|
2665
|
-
const newCenter = new Vector();
|
|
2666
|
-
|
|
2667
|
-
// Create the inverse matrix of mat0 by transposing mat0,
|
|
2668
|
-
// and multiply it to mat1 from the right.
|
|
2669
|
-
// This matrix represents the difference between the two.
|
|
2670
|
-
// 'deltaRot' means 'difference of rotation matrices'.
|
|
2671
|
-
const deltaRot = rotMat1.mult(rotMat0.copy().transpose()); // mat1 is 3x3
|
|
2672
|
-
|
|
2673
|
-
// Calculate the trace and from it the cos value of the angle.
|
|
2674
|
-
// An orthogonal matrix is just an orthonormal basis. If this is not the identity
|
|
2675
|
-
// matrix, it is a centered orthonormal basis plus some angle of rotation about
|
|
2676
|
-
// some axis. That's the angle. Letting this be theta, trace becomes 1+2cos(theta).
|
|
2677
|
-
// reference: https://en.wikipedia.org/wiki/Rotation_matrix#Determining_the_angle
|
|
2678
|
-
const diag = deltaRot.diagonal();
|
|
2679
|
-
let cosTheta = 0.5 * (diag[0] + diag[1] + diag[2] - 1);
|
|
2680
|
-
|
|
2681
|
-
// If the angle is close to 0, the two matrices are very close,
|
|
2682
|
-
// so in that case we execute linearly interpolate.
|
|
2683
|
-
if (1 - cosTheta < 0.0000001) {
|
|
2684
|
-
// Obtain the front vector and up vector by linear interpolation
|
|
2685
|
-
// and normalize them.
|
|
2686
|
-
// calculate newEye, newCenter with newFront vector.
|
|
2687
|
-
newFront.set(Vector.lerp(front0, front1, amt)).normalize();
|
|
2688
|
-
|
|
2689
|
-
newEye.set(newFront).mult(ratio * lerpedDist).add(lerpedMedium);
|
|
2690
|
-
newCenter.set(newFront).mult((ratio - 1) * lerpedDist).add(lerpedMedium);
|
|
2691
|
-
|
|
2692
|
-
newUp.set(Vector.lerp(up0, up1, amt)).normalize();
|
|
2693
|
-
|
|
2694
|
-
// set the camera
|
|
2695
|
-
this.camera(
|
|
2696
|
-
newEye.x, newEye.y, newEye.z,
|
|
2697
|
-
newCenter.x, newCenter.y, newCenter.z,
|
|
2698
|
-
newUp.x, newUp.y, newUp.z
|
|
2699
|
-
);
|
|
2700
|
-
return;
|
|
2701
|
-
}
|
|
2702
|
-
|
|
2703
|
-
// Calculates the axis vector and the angle of the difference orthogonal matrix.
|
|
2704
|
-
// The axis vector is what I explained earlier in the comments.
|
|
2705
|
-
// similar calculation is here:
|
|
2706
|
-
// https://github.com/mrdoob/three.js/blob/883249620049d1632e8791732808fefd1a98c871/src/math/Quaternion.js#L294
|
|
2707
|
-
let a, b, c, sinTheta;
|
|
2708
|
-
let invOneMinusCosTheta = 1 / (1 - cosTheta);
|
|
2709
|
-
const maxDiag = Math.max(diag[0], diag[1], diag[2]);
|
|
2710
|
-
const offDiagSum13 = deltaRot.mat3[1] + deltaRot.mat3[3];
|
|
2711
|
-
const offDiagSum26 = deltaRot.mat3[2] + deltaRot.mat3[6];
|
|
2712
|
-
const offDiagSum57 = deltaRot.mat3[5] + deltaRot.mat3[7];
|
|
2713
|
-
|
|
2714
|
-
if (maxDiag === diag[0]) {
|
|
2715
|
-
a = Math.sqrt((diag[0] - cosTheta) * invOneMinusCosTheta); // not zero.
|
|
2716
|
-
invOneMinusCosTheta /= a;
|
|
2717
|
-
b = 0.5 * offDiagSum13 * invOneMinusCosTheta;
|
|
2718
|
-
c = 0.5 * offDiagSum26 * invOneMinusCosTheta;
|
|
2719
|
-
sinTheta = 0.5 * (deltaRot.mat3[7] - deltaRot.mat3[5]) / a;
|
|
2720
|
-
|
|
2721
|
-
} else if (maxDiag === diag[1]) {
|
|
2722
|
-
b = Math.sqrt((diag[1] - cosTheta) * invOneMinusCosTheta); // not zero.
|
|
2723
|
-
invOneMinusCosTheta /= b;
|
|
2724
|
-
c = 0.5 * offDiagSum57 * invOneMinusCosTheta;
|
|
2725
|
-
a = 0.5 * offDiagSum13 * invOneMinusCosTheta;
|
|
2726
|
-
sinTheta = 0.5 * (deltaRot.mat3[2] - deltaRot.mat3[6]) / b;
|
|
2727
|
-
|
|
2728
|
-
} else {
|
|
2729
|
-
c = Math.sqrt((diag[2] - cosTheta) * invOneMinusCosTheta); // not zero.
|
|
2730
|
-
invOneMinusCosTheta /= c;
|
|
2731
|
-
a = 0.5 * offDiagSum26 * invOneMinusCosTheta;
|
|
2732
|
-
b = 0.5 * offDiagSum57 * invOneMinusCosTheta;
|
|
2733
|
-
sinTheta = 0.5 * (deltaRot.mat3[3] - deltaRot.mat3[1]) / c;
|
|
2734
|
-
}
|
|
2735
|
-
|
|
2736
|
-
// Constructs a new matrix after interpolating the angles.
|
|
2737
|
-
// Multiplying mat0 by the first matrix yields mat1, but by creating a state
|
|
2738
|
-
// in the middle of that matrix, you can obtain a matrix that is
|
|
2739
|
-
// an intermediate state between mat0 and mat1.
|
|
2740
|
-
const angle = amt * Math.atan2(sinTheta, cosTheta);
|
|
2741
|
-
const cosAngle = Math.cos(angle);
|
|
2742
|
-
const sinAngle = Math.sin(angle);
|
|
2743
|
-
const oneMinusCosAngle = 1 - cosAngle;
|
|
2744
|
-
const ab = a * b;
|
|
2745
|
-
const bc = b * c;
|
|
2746
|
-
const ca = c * a;
|
|
2747
|
-
// 3x3
|
|
2748
|
-
const lerpedRotMat = new Matrix( [
|
|
2749
|
-
cosAngle + oneMinusCosAngle * a * a,
|
|
2750
|
-
oneMinusCosAngle * ab + sinAngle * c,
|
|
2751
|
-
oneMinusCosAngle * ca - sinAngle * b,
|
|
2752
|
-
oneMinusCosAngle * ab - sinAngle * c,
|
|
2753
|
-
cosAngle + oneMinusCosAngle * b * b,
|
|
2754
|
-
oneMinusCosAngle * bc + sinAngle * a,
|
|
2755
|
-
oneMinusCosAngle * ca + sinAngle * b,
|
|
2756
|
-
oneMinusCosAngle * bc - sinAngle * a,
|
|
2757
|
-
cosAngle + oneMinusCosAngle * c * c
|
|
2758
|
-
]);
|
|
2759
|
-
|
|
2760
|
-
// Multiply this to mat0 from left to get the interpolated front vector.
|
|
2761
|
-
// calculate newEye, newCenter with newFront vector.
|
|
2762
|
-
lerpedRotMat.multiplyVec(front0, newFront); // this is vec3
|
|
2763
|
-
|
|
2764
|
-
newEye.set(newFront).mult(ratio * lerpedDist).add(lerpedMedium);
|
|
2765
|
-
newCenter.set(newFront).mult((ratio - 1) * lerpedDist).add(lerpedMedium);
|
|
2766
|
-
|
|
2767
|
-
lerpedRotMat.multiplyVec(up0, newUp); // this is vec3
|
|
2768
|
-
|
|
2769
|
-
// We also get the up vector in the same way and set the camera.
|
|
2770
|
-
// The eye position and center position are calculated based on the front vector.
|
|
2771
|
-
this.camera(
|
|
2772
|
-
newEye.x, newEye.y, newEye.z,
|
|
2773
|
-
newCenter.x, newCenter.y, newCenter.z,
|
|
2774
|
-
newUp.x, newUp.y, newUp.z
|
|
2775
|
-
);
|
|
2776
|
-
}
|
|
2777
|
-
|
|
2778
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
2779
|
-
// Camera Helper Methods
|
|
2780
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
2781
|
-
|
|
2782
|
-
// @TODO: combine this function with _setDefaultCamera to compute these values
|
|
2783
|
-
// as-needed
|
|
2784
|
-
_computeCameraDefaultSettings() {
|
|
2785
|
-
this.defaultAspectRatio = this._renderer.width / this._renderer.height;
|
|
2786
|
-
this.defaultEyeX = 0;
|
|
2787
|
-
this.defaultEyeY = 0;
|
|
2788
|
-
this.defaultEyeZ = 800;
|
|
2789
|
-
this.defaultCameraFOV =
|
|
2790
|
-
2 * Math.atan(this._renderer.height / 2 / this.defaultEyeZ);
|
|
2791
|
-
this.defaultCenterX = 0;
|
|
2792
|
-
this.defaultCenterY = 0;
|
|
2793
|
-
this.defaultCenterZ = 0;
|
|
2794
|
-
this.defaultCameraNear = this.defaultEyeZ * 0.1;
|
|
2795
|
-
this.defaultCameraFar = this.defaultEyeZ * 10;
|
|
2796
|
-
}
|
|
2797
|
-
|
|
2798
|
-
//detect if user didn't set the camera
|
|
2799
|
-
//then call this function below
|
|
2800
|
-
_setDefaultCamera() {
|
|
2801
|
-
this.cameraFOV = this.defaultCameraFOV;
|
|
2802
|
-
this.aspectRatio = this.defaultAspectRatio;
|
|
2803
|
-
this.eyeX = this.defaultEyeX;
|
|
2804
|
-
this.eyeY = this.defaultEyeY;
|
|
2805
|
-
this.eyeZ = this.defaultEyeZ;
|
|
2806
|
-
this.centerX = this.defaultCenterX;
|
|
2807
|
-
this.centerY = this.defaultCenterY;
|
|
2808
|
-
this.centerZ = this.defaultCenterZ;
|
|
2809
|
-
this.upX = 0;
|
|
2810
|
-
this.upY = 1;
|
|
2811
|
-
this.upZ = 0;
|
|
2812
|
-
this.cameraNear = this.defaultCameraNear;
|
|
2813
|
-
this.cameraFar = this.defaultCameraFar;
|
|
2814
|
-
|
|
2815
|
-
this.perspective();
|
|
2816
|
-
this.camera();
|
|
2817
|
-
|
|
2818
|
-
this.cameraType = 'default';
|
|
2819
|
-
}
|
|
2820
|
-
|
|
2821
|
-
_resize() {
|
|
2822
|
-
// If we're using the default camera, update the aspect ratio
|
|
2823
|
-
if (this.cameraType === 'default') {
|
|
2824
|
-
this._computeCameraDefaultSettings();
|
|
2825
|
-
this.cameraFOV = this.defaultCameraFOV;
|
|
2826
|
-
this.aspectRatio = this.defaultAspectRatio;
|
|
2827
|
-
this.perspective();
|
|
2828
|
-
}
|
|
2829
|
-
}
|
|
2830
|
-
|
|
2831
|
-
/**
|
|
2832
|
-
* Returns a copy of a camera.
|
|
2833
|
-
* @private
|
|
2834
|
-
*/
|
|
2835
|
-
copy() {
|
|
2836
|
-
const _cam = new Camera(this._renderer);
|
|
2837
|
-
_cam.cameraFOV = this.cameraFOV;
|
|
2838
|
-
_cam.aspectRatio = this.aspectRatio;
|
|
2839
|
-
_cam.eyeX = this.eyeX;
|
|
2840
|
-
_cam.eyeY = this.eyeY;
|
|
2841
|
-
_cam.eyeZ = this.eyeZ;
|
|
2842
|
-
_cam.centerX = this.centerX;
|
|
2843
|
-
_cam.centerY = this.centerY;
|
|
2844
|
-
_cam.centerZ = this.centerZ;
|
|
2845
|
-
_cam.upX = this.upX;
|
|
2846
|
-
_cam.upY = this.upY;
|
|
2847
|
-
_cam.upZ = this.upZ;
|
|
2848
|
-
_cam.cameraNear = this.cameraNear;
|
|
2849
|
-
_cam.cameraFar = this.cameraFar;
|
|
2850
|
-
|
|
2851
|
-
_cam.cameraType = this.cameraType;
|
|
2852
|
-
_cam.useLinePerspective = this.useLinePerspective;
|
|
2853
|
-
|
|
2854
|
-
_cam.cameraMatrix = this.cameraMatrix.copy();
|
|
2855
|
-
_cam.projMatrix = this.projMatrix.copy();
|
|
2856
|
-
_cam.yScale = this.yScale;
|
|
2857
|
-
|
|
2858
|
-
return _cam;
|
|
2859
|
-
}
|
|
2860
|
-
|
|
2861
|
-
clone() {
|
|
2862
|
-
return this.copy();
|
|
2863
|
-
}
|
|
2864
|
-
|
|
2865
|
-
/**
|
|
2866
|
-
* Returns a camera's local axes: left-right, up-down, and forward-backward,
|
|
2867
|
-
* as defined by vectors in world-space.
|
|
2868
|
-
* @private
|
|
2869
|
-
*/
|
|
2870
|
-
_getLocalAxes() {
|
|
2871
|
-
// calculate camera local Z vector
|
|
2872
|
-
let z0 = this.eyeX - this.centerX;
|
|
2873
|
-
let z1 = this.eyeY - this.centerY;
|
|
2874
|
-
let z2 = this.eyeZ - this.centerZ;
|
|
2875
|
-
|
|
2876
|
-
// normalize camera local Z vector
|
|
2877
|
-
const eyeDist = Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
|
|
2878
|
-
if (eyeDist !== 0) {
|
|
2879
|
-
z0 /= eyeDist;
|
|
2880
|
-
z1 /= eyeDist;
|
|
2881
|
-
z2 /= eyeDist;
|
|
2882
|
-
}
|
|
2883
|
-
|
|
2884
|
-
// calculate camera Y vector
|
|
2885
|
-
let y0 = this.upX;
|
|
2886
|
-
let y1 = this.upY;
|
|
2887
|
-
let y2 = this.upZ;
|
|
2888
|
-
|
|
2889
|
-
// compute camera local X vector as up vector (local Y) cross local Z
|
|
2890
|
-
let x0 = y1 * z2 - y2 * z1;
|
|
2891
|
-
let x1 = -y0 * z2 + y2 * z0;
|
|
2892
|
-
let x2 = y0 * z1 - y1 * z0;
|
|
2893
|
-
|
|
2894
|
-
// recompute y = z cross x
|
|
2895
|
-
y0 = z1 * x2 - z2 * x1;
|
|
2896
|
-
y1 = -z0 * x2 + z2 * x0;
|
|
2897
|
-
y2 = z0 * x1 - z1 * x0;
|
|
2898
|
-
|
|
2899
|
-
// cross product gives area of parallelogram, which is < 1.0 for
|
|
2900
|
-
// non-perpendicular unit-length vectors; so normalize x, y here:
|
|
2901
|
-
const xmag = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
|
|
2902
|
-
if (xmag !== 0) {
|
|
2903
|
-
x0 /= xmag;
|
|
2904
|
-
x1 /= xmag;
|
|
2905
|
-
x2 /= xmag;
|
|
2906
|
-
}
|
|
2907
|
-
|
|
2908
|
-
const ymag = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
|
|
2909
|
-
if (ymag !== 0) {
|
|
2910
|
-
y0 /= ymag;
|
|
2911
|
-
y1 /= ymag;
|
|
2912
|
-
y2 /= ymag;
|
|
2913
|
-
}
|
|
2914
|
-
|
|
2915
|
-
return {
|
|
2916
|
-
x: [x0, x1, x2],
|
|
2917
|
-
y: [y0, y1, y2],
|
|
2918
|
-
z: [z0, z1, z2]
|
|
2919
|
-
};
|
|
2920
|
-
}
|
|
2921
|
-
|
|
2922
|
-
/**
|
|
2923
|
-
* Orbits the camera about center point. For use with orbitControl().
|
|
2924
|
-
* @private
|
|
2925
|
-
* @param {Number} dTheta change in spherical coordinate theta
|
|
2926
|
-
* @param {Number} dPhi change in spherical coordinate phi
|
|
2927
|
-
* @param {Number} dRadius change in radius
|
|
2928
|
-
*/
|
|
2929
|
-
_orbit(dTheta, dPhi, dRadius) {
|
|
2930
|
-
// Calculate the vector and its magnitude from the center to the viewpoint
|
|
2931
|
-
const diffX = this.eyeX - this.centerX;
|
|
2932
|
-
const diffY = this.eyeY - this.centerY;
|
|
2933
|
-
const diffZ = this.eyeZ - this.centerZ;
|
|
2934
|
-
let camRadius = Math.hypot(diffX, diffY, diffZ);
|
|
2935
|
-
// front vector. unit vector from center to eye.
|
|
2936
|
-
const front = new Vector(diffX, diffY, diffZ).normalize();
|
|
2937
|
-
// up vector. normalized camera's up vector.
|
|
2938
|
-
const up = new Vector(this.upX, this.upY, this.upZ).normalize(); // y-axis
|
|
2939
|
-
// side vector. Right when viewed from the front
|
|
2940
|
-
const side = Vector.cross(up, front).normalize(); // x-axis
|
|
2941
|
-
// vertical vector. normalized vector of projection of front vector.
|
|
2942
|
-
const vertical = Vector.cross(side, up); // z-axis
|
|
2943
|
-
|
|
2944
|
-
// update camRadius
|
|
2945
|
-
camRadius *= Math.pow(10, dRadius);
|
|
2946
|
-
// prevent zooming through the center:
|
|
2947
|
-
if (camRadius < this.cameraNear) {
|
|
2948
|
-
camRadius = this.cameraNear;
|
|
2949
|
-
}
|
|
2950
|
-
if (camRadius > this.cameraFar) {
|
|
2951
|
-
camRadius = this.cameraFar;
|
|
2952
|
-
}
|
|
2953
|
-
|
|
2954
|
-
// calculate updated camera angle
|
|
2955
|
-
// Find the angle between the "up" and the "front", add dPhi to that.
|
|
2956
|
-
// angleBetween() may return negative value. Since this specification is subject to change
|
|
2957
|
-
// due to version updates, it cannot be adopted, so here we calculate using a method
|
|
2958
|
-
// that directly obtains the absolute value.
|
|
2959
|
-
const camPhi =
|
|
2960
|
-
Math.acos(Math.max(-1, Math.min(1, Vector.dot(front, up)))) + dPhi;
|
|
2961
|
-
// Rotate by dTheta in the shortest direction from "vertical" to "side"
|
|
2962
|
-
const camTheta = dTheta;
|
|
2963
|
-
|
|
2964
|
-
// Invert camera's upX, upY, upZ if dPhi is below 0 or above PI
|
|
2965
|
-
if (camPhi <= 0 || camPhi >= Math.PI) {
|
|
2966
|
-
this.upX *= -1;
|
|
2967
|
-
this.upY *= -1;
|
|
2968
|
-
this.upZ *= -1;
|
|
2969
|
-
}
|
|
2970
|
-
|
|
2971
|
-
// update eye vector by calculate new front vector
|
|
2972
|
-
up.mult(Math.cos(camPhi));
|
|
2973
|
-
vertical.mult(Math.cos(camTheta) * Math.sin(camPhi));
|
|
2974
|
-
side.mult(Math.sin(camTheta) * Math.sin(camPhi));
|
|
2975
|
-
|
|
2976
|
-
front.set(up).add(vertical).add(side);
|
|
2977
|
-
|
|
2978
|
-
this.eyeX = camRadius * front.x + this.centerX;
|
|
2979
|
-
this.eyeY = camRadius * front.y + this.centerY;
|
|
2980
|
-
this.eyeZ = camRadius * front.z + this.centerZ;
|
|
2981
|
-
|
|
2982
|
-
// update camera
|
|
2983
|
-
this.camera(
|
|
2984
|
-
this.eyeX, this.eyeY, this.eyeZ,
|
|
2985
|
-
this.centerX, this.centerY, this.centerZ,
|
|
2986
|
-
this.upX, this.upY, this.upZ
|
|
2987
|
-
);
|
|
2988
|
-
}
|
|
2989
|
-
|
|
2990
|
-
/**
|
|
2991
|
-
* Orbits the camera about center point. For use with orbitControl().
|
|
2992
|
-
* Unlike _orbit(), the direction of rotation always matches the direction of pointer movement.
|
|
2993
|
-
* @private
|
|
2994
|
-
* @param {Number} dx the x component of the rotation vector.
|
|
2995
|
-
* @param {Number} dy the y component of the rotation vector.
|
|
2996
|
-
* @param {Number} dRadius change in radius
|
|
2997
|
-
*/
|
|
2998
|
-
_orbitFree(dx, dy, dRadius) {
|
|
2999
|
-
// Calculate the vector and its magnitude from the center to the viewpoint
|
|
3000
|
-
const diffX = this.eyeX - this.centerX;
|
|
3001
|
-
const diffY = this.eyeY - this.centerY;
|
|
3002
|
-
const diffZ = this.eyeZ - this.centerZ;
|
|
3003
|
-
let camRadius = Math.hypot(diffX, diffY, diffZ);
|
|
3004
|
-
// front vector. unit vector from center to eye.
|
|
3005
|
-
const front = new Vector(diffX, diffY, diffZ).normalize();
|
|
3006
|
-
// up vector. camera's up vector.
|
|
3007
|
-
const up = new Vector(this.upX, this.upY, this.upZ);
|
|
3008
|
-
// side vector. Right when viewed from the front. (like x-axis)
|
|
3009
|
-
const side = Vector.cross(up, front).normalize();
|
|
3010
|
-
// down vector. Bottom when viewed from the front. (like y-axis)
|
|
3011
|
-
const down = Vector.cross(front, side);
|
|
3012
|
-
|
|
3013
|
-
// side vector and down vector are no longer used as-is.
|
|
3014
|
-
// Create a vector representing the direction of rotation
|
|
3015
|
-
// in the form cos(direction)*side + sin(direction)*down.
|
|
3016
|
-
// Make the current side vector into this.
|
|
3017
|
-
const directionAngle = Math.atan2(dy, dx);
|
|
3018
|
-
down.mult(Math.sin(directionAngle));
|
|
3019
|
-
side.mult(Math.cos(directionAngle)).add(down);
|
|
3020
|
-
// The amount of rotation is the size of the vector (dx, dy).
|
|
3021
|
-
const rotAngle = Math.sqrt(dx * dx + dy * dy);
|
|
3022
|
-
// The vector that is orthogonal to both the front vector and
|
|
3023
|
-
// the rotation direction vector is the rotation axis vector.
|
|
3024
|
-
const axis = Vector.cross(front, side);
|
|
3025
|
-
|
|
3026
|
-
// update camRadius
|
|
3027
|
-
camRadius *= Math.pow(10, dRadius);
|
|
3028
|
-
// prevent zooming through the center:
|
|
3029
|
-
if (camRadius < this.cameraNear) {
|
|
3030
|
-
camRadius = this.cameraNear;
|
|
3031
|
-
}
|
|
3032
|
-
if (camRadius > this.cameraFar) {
|
|
3033
|
-
camRadius = this.cameraFar;
|
|
3034
|
-
}
|
|
3035
|
-
|
|
3036
|
-
// If the axis vector is likened to the z-axis, the front vector is
|
|
3037
|
-
// the x-axis and the side vector is the y-axis. Rotate the up and front
|
|
3038
|
-
// vectors respectively by thinking of them as rotations around the z-axis.
|
|
3039
|
-
|
|
3040
|
-
// Calculate the components by taking the dot product and
|
|
3041
|
-
// calculate a rotation based on that.
|
|
3042
|
-
const c = Math.cos(rotAngle);
|
|
3043
|
-
const s = Math.sin(rotAngle);
|
|
3044
|
-
const dotFront = up.dot(front);
|
|
3045
|
-
const dotSide = up.dot(side);
|
|
3046
|
-
const ux = dotFront * c + dotSide * s;
|
|
3047
|
-
const uy = -dotFront * s + dotSide * c;
|
|
3048
|
-
const uz = up.dot(axis);
|
|
3049
|
-
up.x = ux * front.x + uy * side.x + uz * axis.x;
|
|
3050
|
-
up.y = ux * front.y + uy * side.y + uz * axis.y;
|
|
3051
|
-
up.z = ux * front.z + uy * side.z + uz * axis.z;
|
|
3052
|
-
// We won't be using the side vector and the front vector anymore,
|
|
3053
|
-
// so let's make the front vector into the vector from the center to the new eye.
|
|
3054
|
-
side.mult(-s);
|
|
3055
|
-
front.mult(c).add(side).mult(camRadius);
|
|
3056
|
-
|
|
3057
|
-
// it's complete. let's update camera.
|
|
3058
|
-
this.camera(
|
|
3059
|
-
front.x + this.centerX,
|
|
3060
|
-
front.y + this.centerY,
|
|
3061
|
-
front.z + this.centerZ,
|
|
3062
|
-
this.centerX, this.centerY, this.centerZ,
|
|
3063
|
-
up.x, up.y, up.z
|
|
3064
|
-
);
|
|
3065
|
-
}
|
|
3066
|
-
|
|
3067
|
-
/**
|
|
3068
|
-
* Returns true if camera is currently attached to renderer.
|
|
3069
|
-
* @private
|
|
3070
|
-
*/
|
|
3071
|
-
_isActive() {
|
|
3072
|
-
return this === this._renderer.states.curCamera;
|
|
3073
|
-
}
|
|
3074
|
-
};
|
|
3075
|
-
|
|
3076
|
-
function camera(p5, fn){
|
|
3077
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
3078
|
-
// p5.Prototype Methods
|
|
3079
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
3080
|
-
|
|
3081
|
-
/**
|
|
3082
|
-
* Sets the position and orientation of the current camera in a 3D sketch.
|
|
3083
|
-
*
|
|
3084
|
-
* `camera()` allows objects to be viewed from different angles. It has nine
|
|
3085
|
-
* parameters that are all optional.
|
|
3086
|
-
*
|
|
3087
|
-
* The first three parameters, `x`, `y`, and `z`, are the coordinates of the
|
|
3088
|
-
* camera’s position. For example, calling `camera(0, 0, 0)` places the camera
|
|
3089
|
-
* at the origin `(0, 0, 0)`. By default, the camera is placed at
|
|
3090
|
-
* `(0, 0, 800)`.
|
|
3091
|
-
*
|
|
3092
|
-
* The next three parameters, `centerX`, `centerY`, and `centerZ` are the
|
|
3093
|
-
* coordinates of the point where the camera faces. For example, calling
|
|
3094
|
-
* `camera(0, 0, 0, 10, 20, 30)` places the camera at the origin `(0, 0, 0)`
|
|
3095
|
-
* and points it at `(10, 20, 30)`. By default, the camera points at the
|
|
3096
|
-
* origin `(0, 0, 0)`.
|
|
3097
|
-
*
|
|
3098
|
-
* The last three parameters, `upX`, `upY`, and `upZ` are the components of
|
|
3099
|
-
* the "up" vector. The "up" vector orients the camera’s y-axis. For example,
|
|
3100
|
-
* calling `camera(0, 0, 0, 10, 20, 30, 0, -1, 0)` places the camera at the
|
|
3101
|
-
* origin `(0, 0, 0)`, points it at `(10, 20, 30)`, and sets the "up" vector
|
|
3102
|
-
* to `(0, -1, 0)` which is like holding it upside-down. By default, the "up"
|
|
3103
|
-
* vector is `(0, 1, 0)`.
|
|
3104
|
-
*
|
|
3105
|
-
* Note: `camera()` can only be used in WebGL mode.
|
|
3106
|
-
*
|
|
3107
|
-
* @method camera
|
|
3108
|
-
* @for p5
|
|
3109
|
-
* @param {Number} [x] x-coordinate of the camera. Defaults to 0.
|
|
3110
|
-
* @param {Number} [y] y-coordinate of the camera. Defaults to 0.
|
|
3111
|
-
* @param {Number} [z] z-coordinate of the camera. Defaults to 800.
|
|
3112
|
-
* @param {Number} [centerX] x-coordinate of the point the camera faces. Defaults to 0.
|
|
3113
|
-
* @param {Number} [centerY] y-coordinate of the point the camera faces. Defaults to 0.
|
|
3114
|
-
* @param {Number} [centerZ] z-coordinate of the point the camera faces. Defaults to 0.
|
|
3115
|
-
* @param {Number} [upX] x-component of the camera’s "up" vector. Defaults to 0.
|
|
3116
|
-
* @param {Number} [upY] y-component of the camera’s "up" vector. Defaults to 1.
|
|
3117
|
-
* @param {Number} [upZ] z-component of the camera’s "up" vector. Defaults to 0.
|
|
3118
|
-
* @chainable
|
|
3119
|
-
*
|
|
3120
|
-
* @example
|
|
3121
|
-
* <div>
|
|
3122
|
-
* <code>
|
|
3123
|
-
* function setup() {
|
|
3124
|
-
* createCanvas(100, 100, WEBGL);
|
|
3125
|
-
*
|
|
3126
|
-
* describe('A white cube on a gray background.');
|
|
3127
|
-
* }
|
|
3128
|
-
*
|
|
3129
|
-
* function draw() {
|
|
3130
|
-
* background(200);
|
|
3131
|
-
*
|
|
3132
|
-
* // Move the camera to the top-right.
|
|
3133
|
-
* camera(200, -400, 800);
|
|
3134
|
-
*
|
|
3135
|
-
* // Draw the box.
|
|
3136
|
-
* box();
|
|
3137
|
-
* }
|
|
3138
|
-
* </code>
|
|
3139
|
-
* </div>
|
|
3140
|
-
*
|
|
3141
|
-
* <div>
|
|
3142
|
-
* <code>
|
|
3143
|
-
* function setup() {
|
|
3144
|
-
* createCanvas(100, 100, WEBGL);
|
|
3145
|
-
*
|
|
3146
|
-
* describe('A white cube apperas to sway left and right on a gray background.');
|
|
3147
|
-
* }
|
|
3148
|
-
*
|
|
3149
|
-
* function draw() {
|
|
3150
|
-
* background(200);
|
|
3151
|
-
*
|
|
3152
|
-
* // Calculate the camera's x-coordinate.
|
|
3153
|
-
* let x = 400 * cos(frameCount * 0.01);
|
|
3154
|
-
*
|
|
3155
|
-
* // Orbit the camera around the box.
|
|
3156
|
-
* camera(x, -400, 800);
|
|
3157
|
-
*
|
|
3158
|
-
* // Draw the box.
|
|
3159
|
-
* box();
|
|
3160
|
-
* }
|
|
3161
|
-
* </code>
|
|
3162
|
-
* </div>
|
|
3163
|
-
*
|
|
3164
|
-
* <div>
|
|
3165
|
-
* <code>
|
|
3166
|
-
* // Adjust the range sliders to change the camera's position.
|
|
3167
|
-
*
|
|
3168
|
-
* let xSlider;
|
|
3169
|
-
* let ySlider;
|
|
3170
|
-
* let zSlider;
|
|
3171
|
-
*
|
|
3172
|
-
* function setup() {
|
|
3173
|
-
* createCanvas(100, 100, WEBGL);
|
|
3174
|
-
*
|
|
3175
|
-
* // Create slider objects to set the camera's coordinates.
|
|
3176
|
-
* xSlider = createSlider(-400, 400, 400);
|
|
3177
|
-
* xSlider.position(0, 100);
|
|
3178
|
-
* xSlider.size(100);
|
|
3179
|
-
* ySlider = createSlider(-400, 400, -200);
|
|
3180
|
-
* ySlider.position(0, 120);
|
|
3181
|
-
* ySlider.size(100);
|
|
3182
|
-
* zSlider = createSlider(0, 1600, 800);
|
|
3183
|
-
* zSlider.position(0, 140);
|
|
3184
|
-
* zSlider.size(100);
|
|
3185
|
-
*
|
|
3186
|
-
* describe(
|
|
3187
|
-
* 'A white cube drawn against a gray background. Three range sliders appear beneath the image. The camera position changes when the user moves the sliders.'
|
|
3188
|
-
* );
|
|
3189
|
-
* }
|
|
3190
|
-
*
|
|
3191
|
-
* function draw() {
|
|
3192
|
-
* background(200);
|
|
3193
|
-
*
|
|
3194
|
-
* // Get the camera's coordinates from the sliders.
|
|
3195
|
-
* let x = xSlider.value();
|
|
3196
|
-
* let y = ySlider.value();
|
|
3197
|
-
* let z = zSlider.value();
|
|
3198
|
-
*
|
|
3199
|
-
* // Move the camera.
|
|
3200
|
-
* camera(x, y, z);
|
|
3201
|
-
*
|
|
3202
|
-
* // Draw the box.
|
|
3203
|
-
* box();
|
|
3204
|
-
* }
|
|
3205
|
-
* </code>
|
|
3206
|
-
* </div>
|
|
3207
|
-
*/
|
|
3208
|
-
fn.camera = function (...args) {
|
|
3209
|
-
this._assert3d('camera');
|
|
3210
|
-
// p5._validateParameters('camera', args);
|
|
3211
|
-
this._renderer.camera(...args);
|
|
3212
|
-
return this;
|
|
3213
|
-
};
|
|
3214
|
-
|
|
3215
|
-
/**
|
|
3216
|
-
* Sets a perspective projection for the current camera in a 3D sketch.
|
|
3217
|
-
*
|
|
3218
|
-
* In a perspective projection, shapes that are further from the camera appear
|
|
3219
|
-
* smaller than shapes that are near the camera. This technique, called
|
|
3220
|
-
* foreshortening, creates realistic 3D scenes. It’s applied by default in
|
|
3221
|
-
* WebGL mode.
|
|
3222
|
-
*
|
|
3223
|
-
* `perspective()` changes the camera’s perspective by changing its viewing
|
|
3224
|
-
* frustum. The frustum is the volume of space that’s visible to the camera.
|
|
3225
|
-
* Its shape is a pyramid with its top cut off. The camera is placed where
|
|
3226
|
-
* the top of the pyramid should be and views everything between the frustum’s
|
|
3227
|
-
* top (near) plane and its bottom (far) plane.
|
|
3228
|
-
*
|
|
3229
|
-
* The first parameter, `fovy`, is the camera’s vertical field of view. It’s
|
|
3230
|
-
* an angle that describes how tall or narrow a view the camera has. For
|
|
3231
|
-
* example, calling `perspective(0.5)` sets the camera’s vertical field of
|
|
3232
|
-
* view to 0.5 radians. By default, `fovy` is calculated based on the sketch’s
|
|
3233
|
-
* height and the camera’s default z-coordinate, which is 800. The formula for
|
|
3234
|
-
* the default `fovy` is `2 * atan(height / 2 / 800)`.
|
|
3235
|
-
*
|
|
3236
|
-
* The second parameter, `aspect`, is the camera’s aspect ratio. It’s a number
|
|
3237
|
-
* that describes the ratio of the top plane’s width to its height. For
|
|
3238
|
-
* example, calling `perspective(0.5, 1.5)` sets the camera’s field of view to
|
|
3239
|
-
* 0.5 radians and aspect ratio to 1.5, which would make shapes appear thinner
|
|
3240
|
-
* on a square canvas. By default, aspect is set to `width / height`.
|
|
3241
|
-
*
|
|
3242
|
-
* The third parameter, `near`, is the distance from the camera to the near
|
|
3243
|
-
* plane. For example, calling `perspective(0.5, 1.5, 100)` sets the camera’s
|
|
3244
|
-
* field of view to 0.5 radians, its aspect ratio to 1.5, and places the near
|
|
3245
|
-
* plane 100 pixels from the camera. Any shapes drawn less than 100 pixels
|
|
3246
|
-
* from the camera won’t be visible. By default, near is set to `0.1 * 800`,
|
|
3247
|
-
* which is 1/10th the default distance between the camera and the origin.
|
|
3248
|
-
*
|
|
3249
|
-
* The fourth parameter, `far`, is the distance from the camera to the far
|
|
3250
|
-
* plane. For example, calling `perspective(0.5, 1.5, 100, 10000)` sets the
|
|
3251
|
-
* camera’s field of view to 0.5 radians, its aspect ratio to 1.5, places the
|
|
3252
|
-
* near plane 100 pixels from the camera, and places the far plane 10,000
|
|
3253
|
-
* pixels from the camera. Any shapes drawn more than 10,000 pixels from the
|
|
3254
|
-
* camera won’t be visible. By default, far is set to `10 * 800`, which is 10
|
|
3255
|
-
* times the default distance between the camera and the origin.
|
|
3256
|
-
*
|
|
3257
|
-
* Note: `perspective()` can only be used in WebGL mode.
|
|
3258
|
-
*
|
|
3259
|
-
* @method perspective
|
|
3260
|
-
* @for p5
|
|
3261
|
-
* @param {Number} [fovy] camera frustum vertical field of view. Defaults to
|
|
3262
|
-
* `2 * atan(height / 2 / 800)`.
|
|
3263
|
-
* @param {Number} [aspect] camera frustum aspect ratio. Defaults to
|
|
3264
|
-
* `width / height`.
|
|
3265
|
-
* @param {Number} [near] distance from the camera to the near clipping plane.
|
|
3266
|
-
* Defaults to `0.1 * 800`.
|
|
3267
|
-
* @param {Number} [far] distance from the camera to the far clipping plane.
|
|
3268
|
-
* Defaults to `10 * 800`.
|
|
3269
|
-
* @chainable
|
|
3270
|
-
*
|
|
3271
|
-
* @example
|
|
3272
|
-
* <div>
|
|
3273
|
-
* <code>
|
|
3274
|
-
* // Double-click to squeeze the box.
|
|
3275
|
-
*
|
|
3276
|
-
* let isSqueezed = false;
|
|
3277
|
-
*
|
|
3278
|
-
* function setup() {
|
|
3279
|
-
* createCanvas(100, 100, WEBGL);
|
|
3280
|
-
*
|
|
3281
|
-
* describe('A white rectangular prism on a gray background. The box appears to become thinner when the user double-clicks.');
|
|
3282
|
-
* }
|
|
3283
|
-
*
|
|
3284
|
-
* function draw() {
|
|
3285
|
-
* background(200);
|
|
3286
|
-
*
|
|
3287
|
-
* // Place the camera at the top-right.
|
|
3288
|
-
* camera(400, -400, 800);
|
|
3289
|
-
*
|
|
3290
|
-
* if (isSqueezed === true) {
|
|
3291
|
-
* // Set fovy to 0.2.
|
|
3292
|
-
* // Set aspect to 1.5.
|
|
3293
|
-
* perspective(0.2, 1.5);
|
|
3294
|
-
* }
|
|
3295
|
-
*
|
|
3296
|
-
* // Draw the box.
|
|
3297
|
-
* box();
|
|
3298
|
-
* }
|
|
3299
|
-
*
|
|
3300
|
-
* // Change the camera's perspective when the user double-clicks.
|
|
3301
|
-
* function doubleClicked() {
|
|
3302
|
-
* isSqueezed = true;
|
|
3303
|
-
* }
|
|
3304
|
-
* </code>
|
|
3305
|
-
* </div>
|
|
3306
|
-
*
|
|
3307
|
-
* <div>
|
|
3308
|
-
* <code>
|
|
3309
|
-
* function setup() {
|
|
3310
|
-
* createCanvas(100, 100, WEBGL);
|
|
3311
|
-
*
|
|
3312
|
-
* describe('A white rectangular prism on a gray background. The prism moves away from the camera until it disappears.');
|
|
3313
|
-
* }
|
|
3314
|
-
*
|
|
3315
|
-
* function draw() {
|
|
3316
|
-
* background(200);
|
|
3317
|
-
*
|
|
3318
|
-
* // Place the camera at the top-right.
|
|
3319
|
-
* camera(400, -400, 800);
|
|
3320
|
-
*
|
|
3321
|
-
* // Set fovy to 0.2.
|
|
3322
|
-
* // Set aspect to 1.5.
|
|
3323
|
-
* // Set near to 600.
|
|
3324
|
-
* // Set far to 1200.
|
|
3325
|
-
* perspective(0.2, 1.5, 600, 1200);
|
|
3326
|
-
*
|
|
3327
|
-
* // Move the origin away from the camera.
|
|
3328
|
-
* let x = -frameCount;
|
|
3329
|
-
* let y = frameCount;
|
|
3330
|
-
* let z = -2 * frameCount;
|
|
3331
|
-
* translate(x, y, z);
|
|
3332
|
-
*
|
|
3333
|
-
* // Draw the box.
|
|
3334
|
-
* box();
|
|
3335
|
-
* }
|
|
3336
|
-
* </code>
|
|
3337
|
-
* </div>
|
|
3338
|
-
*/
|
|
3339
|
-
fn.perspective = function (...args) {
|
|
3340
|
-
this._assert3d('perspective');
|
|
3341
|
-
// p5._validateParameters('perspective', args);
|
|
3342
|
-
this._renderer.perspective(...args);
|
|
3343
|
-
return this;
|
|
3344
|
-
};
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
/**
|
|
3348
|
-
* Enables or disables perspective for lines in 3D sketches.
|
|
3349
|
-
*
|
|
3350
|
-
* In WebGL mode, lines can be drawn with a thinner stroke when they’re
|
|
3351
|
-
* further from the camera. Doing so gives them a more realistic appearance.
|
|
3352
|
-
*
|
|
3353
|
-
* By default, lines are drawn differently based on the type of perspective
|
|
3354
|
-
* being used:
|
|
3355
|
-
* - `perspective()` and `frustum()` simulate a realistic perspective. In
|
|
3356
|
-
* these modes, stroke weight is affected by the line’s distance from the
|
|
3357
|
-
* camera. Doing so results in a more natural appearance. `perspective()` is
|
|
3358
|
-
* the default mode for 3D sketches.
|
|
3359
|
-
* - `ortho()` doesn’t simulate a realistic perspective. In this mode, stroke
|
|
3360
|
-
* weights are consistent regardless of the line’s distance from the camera.
|
|
3361
|
-
* Doing so results in a more predictable and consistent appearance.
|
|
3362
|
-
*
|
|
3363
|
-
* `linePerspective()` can override the default line drawing mode.
|
|
3364
|
-
*
|
|
3365
|
-
* The parameter, `enable`, is optional. It’s a `Boolean` value that sets the
|
|
3366
|
-
* way lines are drawn. If `true` is passed, as in `linePerspective(true)`,
|
|
3367
|
-
* then lines will appear thinner when they are further from the camera. If
|
|
3368
|
-
* `false` is passed, as in `linePerspective(false)`, then lines will have
|
|
3369
|
-
* consistent stroke weights regardless of their distance from the camera. By
|
|
3370
|
-
* default, `linePerspective()` is enabled.
|
|
3371
|
-
*
|
|
3372
|
-
* Calling `linePerspective()` without passing an argument returns `true` if
|
|
3373
|
-
* it's enabled and `false` if not.
|
|
3374
|
-
*
|
|
3375
|
-
* Note: `linePerspective()` can only be used in WebGL mode.
|
|
3376
|
-
*
|
|
3377
|
-
* @method linePerspective
|
|
3378
|
-
* @for p5
|
|
3379
|
-
* @param {Boolean} enable whether to enable line perspective.
|
|
3380
|
-
*
|
|
3381
|
-
* @example
|
|
3382
|
-
* <div>
|
|
3383
|
-
* <code>
|
|
3384
|
-
* // Double-click the canvas to toggle the line perspective.
|
|
3385
|
-
*
|
|
3386
|
-
* function setup() {
|
|
3387
|
-
* createCanvas(100, 100, WEBGL);
|
|
3388
|
-
*
|
|
3389
|
-
* describe(
|
|
3390
|
-
* 'A white cube with black edges on a gray background. Its edges toggle between thick and thin when the user double-clicks.'
|
|
3391
|
-
* );
|
|
3392
|
-
* }
|
|
3393
|
-
*
|
|
3394
|
-
* function draw() {
|
|
3395
|
-
* background(200);
|
|
3396
|
-
*
|
|
3397
|
-
* // Translate the origin toward the camera.
|
|
3398
|
-
* translate(-10, 10, 600);
|
|
3399
|
-
*
|
|
3400
|
-
* // Rotate the coordinate system.
|
|
3401
|
-
* rotateY(-0.1);
|
|
3402
|
-
* rotateX(-0.1);
|
|
3403
|
-
*
|
|
3404
|
-
* // Draw the row of boxes.
|
|
3405
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
3406
|
-
* translate(0, 0, -40);
|
|
3407
|
-
* box(10);
|
|
3408
|
-
* }
|
|
3409
|
-
* }
|
|
3410
|
-
*
|
|
3411
|
-
* // Toggle the line perspective when the user double-clicks.
|
|
3412
|
-
* function doubleClicked() {
|
|
3413
|
-
* let isEnabled = linePerspective();
|
|
3414
|
-
* linePerspective(!isEnabled);
|
|
3415
|
-
* }
|
|
3416
|
-
* </code>
|
|
3417
|
-
* </div>
|
|
3418
|
-
*
|
|
3419
|
-
* <div>
|
|
3420
|
-
* <code>
|
|
3421
|
-
* // Double-click the canvas to toggle the line perspective.
|
|
3422
|
-
*
|
|
3423
|
-
* function setup() {
|
|
3424
|
-
* createCanvas(100, 100, WEBGL);
|
|
3425
|
-
*
|
|
3426
|
-
* describe(
|
|
3427
|
-
* 'A row of cubes with black edges on a gray background. Their edges toggle between thick and thin when the user double-clicks.'
|
|
3428
|
-
* );
|
|
3429
|
-
* }
|
|
3430
|
-
*
|
|
3431
|
-
* function draw() {
|
|
3432
|
-
* background(200);
|
|
3433
|
-
*
|
|
3434
|
-
* // Use an orthographic projection.
|
|
3435
|
-
* ortho();
|
|
3436
|
-
*
|
|
3437
|
-
* // Translate the origin toward the camera.
|
|
3438
|
-
* translate(-10, 10, 600);
|
|
3439
|
-
*
|
|
3440
|
-
* // Rotate the coordinate system.
|
|
3441
|
-
* rotateY(-0.1);
|
|
3442
|
-
* rotateX(-0.1);
|
|
3443
|
-
*
|
|
3444
|
-
* // Draw the row of boxes.
|
|
3445
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
3446
|
-
* translate(0, 0, -40);
|
|
3447
|
-
* box(10);
|
|
3448
|
-
* }
|
|
3449
|
-
* }
|
|
3450
|
-
*
|
|
3451
|
-
* // Toggle the line perspective when the user double-clicks.
|
|
3452
|
-
* function doubleClicked() {
|
|
3453
|
-
* let isEnabled = linePerspective();
|
|
3454
|
-
* linePerspective(!isEnabled);
|
|
3455
|
-
* }
|
|
3456
|
-
* </code>
|
|
3457
|
-
* </div>
|
|
3458
|
-
*/
|
|
3459
|
-
/**
|
|
3460
|
-
* @method linePerspective
|
|
3461
|
-
* @return {boolean} whether line perspective is enabled.
|
|
3462
|
-
*/
|
|
3463
|
-
fn.linePerspective = function (enable) {
|
|
3464
|
-
// p5._validateParameters('linePerspective', arguments);
|
|
3465
|
-
if (!(this._renderer instanceof RendererGL)) {
|
|
3466
|
-
throw new Error('linePerspective() must be called in WebGL mode.');
|
|
3467
|
-
}
|
|
3468
|
-
return this._renderer.linePerspective(enable);
|
|
3469
|
-
};
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
/**
|
|
3473
|
-
* Sets an orthographic projection for the current camera in a 3D sketch.
|
|
3474
|
-
*
|
|
3475
|
-
* In an orthographic projection, shapes with the same size always appear the
|
|
3476
|
-
* same size, regardless of whether they are near or far from the camera.
|
|
3477
|
-
*
|
|
3478
|
-
* `ortho()` changes the camera’s perspective by changing its viewing frustum
|
|
3479
|
-
* from a truncated pyramid to a rectangular prism. The camera is placed in
|
|
3480
|
-
* front of the frustum and views everything between the frustum’s near plane
|
|
3481
|
-
* and its far plane. `ortho()` has six optional parameters to define the
|
|
3482
|
-
* frustum.
|
|
3483
|
-
*
|
|
3484
|
-
* The first four parameters, `left`, `right`, `bottom`, and `top`, set the
|
|
3485
|
-
* coordinates of the frustum’s sides, bottom, and top. For example, calling
|
|
3486
|
-
* `ortho(-100, 100, 200, -200)` creates a frustum that’s 200 pixels wide and
|
|
3487
|
-
* 400 pixels tall. By default, these coordinates are set based on the
|
|
3488
|
-
* sketch’s width and height, as in
|
|
3489
|
-
* `ortho(-width / 2, width / 2, -height / 2, height / 2)`.
|
|
3490
|
-
*
|
|
3491
|
-
* The last two parameters, `near` and `far`, set the distance of the
|
|
3492
|
-
* frustum’s near and far plane from the camera. For example, calling
|
|
3493
|
-
* `ortho(-100, 100, 200, 200, 50, 1000)` creates a frustum that’s 200 pixels
|
|
3494
|
-
* wide, 400 pixels tall, starts 50 pixels from the camera, and ends 1,000
|
|
3495
|
-
* pixels from the camera. By default, `near` and `far` are set to 0 and
|
|
3496
|
-
* `max(width, height) + 800`, respectively.
|
|
3497
|
-
*
|
|
3498
|
-
* Note: `ortho()` can only be used in WebGL mode.
|
|
3499
|
-
*
|
|
3500
|
-
* @method ortho
|
|
3501
|
-
* @for p5
|
|
3502
|
-
* @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 2`.
|
|
3503
|
-
* @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 2`.
|
|
3504
|
-
* @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 2`.
|
|
3505
|
-
* @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 2`.
|
|
3506
|
-
* @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to 0.
|
|
3507
|
-
* @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `max(width, height) + 800`.
|
|
3508
|
-
* @chainable
|
|
3509
|
-
*
|
|
3510
|
-
* @example
|
|
3511
|
-
* <div>
|
|
3512
|
-
* <code>
|
|
3513
|
-
* function setup() {
|
|
3514
|
-
* createCanvas(100, 100, WEBGL);
|
|
3515
|
-
*
|
|
3516
|
-
* describe('A row of tiny, white cubes on a gray background. All the cubes appear the same size.');
|
|
3517
|
-
* }
|
|
3518
|
-
*
|
|
3519
|
-
* function draw() {
|
|
3520
|
-
* background(200);
|
|
3521
|
-
*
|
|
3522
|
-
* // Apply an orthographic projection.
|
|
3523
|
-
* ortho();
|
|
3524
|
-
*
|
|
3525
|
-
* // Translate the origin toward the camera.
|
|
3526
|
-
* translate(-10, 10, 600);
|
|
3527
|
-
*
|
|
3528
|
-
* // Rotate the coordinate system.
|
|
3529
|
-
* rotateY(-0.1);
|
|
3530
|
-
* rotateX(-0.1);
|
|
3531
|
-
*
|
|
3532
|
-
* // Draw the row of boxes.
|
|
3533
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
3534
|
-
* translate(0, 0, -40);
|
|
3535
|
-
* box(10);
|
|
3536
|
-
* }
|
|
3537
|
-
* }
|
|
3538
|
-
* </code>
|
|
3539
|
-
* </div>
|
|
3540
|
-
*
|
|
3541
|
-
* <div>
|
|
3542
|
-
* <code>
|
|
3543
|
-
* function setup() {
|
|
3544
|
-
* createCanvas(100, 100, WEBGL);
|
|
3545
|
-
*
|
|
3546
|
-
* describe('A white cube on a gray background.');
|
|
3547
|
-
* }
|
|
3548
|
-
*
|
|
3549
|
-
* function draw() {
|
|
3550
|
-
* background(200);
|
|
3551
|
-
*
|
|
3552
|
-
* // Apply an orthographic projection.
|
|
3553
|
-
* // Center the frustum.
|
|
3554
|
-
* // Set its width and height to 20.
|
|
3555
|
-
* // Place its near plane 300 pixels from the camera.
|
|
3556
|
-
* // Place its far plane 350 pixels from the camera.
|
|
3557
|
-
* ortho(-10, 10, -10, 10, 300, 350);
|
|
3558
|
-
*
|
|
3559
|
-
* // Translate the origin toward the camera.
|
|
3560
|
-
* translate(-10, 10, 600);
|
|
3561
|
-
*
|
|
3562
|
-
* // Rotate the coordinate system.
|
|
3563
|
-
* rotateY(-0.1);
|
|
3564
|
-
* rotateX(-0.1);
|
|
3565
|
-
*
|
|
3566
|
-
* // Draw the row of boxes.
|
|
3567
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
3568
|
-
* translate(0, 0, -40);
|
|
3569
|
-
* box(10);
|
|
3570
|
-
* }
|
|
3571
|
-
* }
|
|
3572
|
-
* </code>
|
|
3573
|
-
* </div>
|
|
3574
|
-
*/
|
|
3575
|
-
fn.ortho = function (...args) {
|
|
3576
|
-
this._assert3d('ortho');
|
|
3577
|
-
// p5._validateParameters('ortho', args);
|
|
3578
|
-
this._renderer.ortho(...args);
|
|
3579
|
-
return this;
|
|
3580
|
-
};
|
|
3581
|
-
|
|
3582
|
-
/**
|
|
3583
|
-
* Sets the frustum of the current camera in a 3D sketch.
|
|
3584
|
-
*
|
|
3585
|
-
* In a frustum projection, shapes that are further from the camera appear
|
|
3586
|
-
* smaller than shapes that are near the camera. This technique, called
|
|
3587
|
-
* foreshortening, creates realistic 3D scenes.
|
|
3588
|
-
*
|
|
3589
|
-
* `frustum()` changes the default camera’s perspective by changing its
|
|
3590
|
-
* viewing frustum. The frustum is the volume of space that’s visible to the
|
|
3591
|
-
* camera. The frustum’s shape is a pyramid with its top cut off. The camera
|
|
3592
|
-
* is placed where the top of the pyramid should be and points towards the
|
|
3593
|
-
* base of the pyramid. It views everything within the frustum.
|
|
3594
|
-
*
|
|
3595
|
-
* The first four parameters, `left`, `right`, `bottom`, and `top`, set the
|
|
3596
|
-
* coordinates of the frustum’s sides, bottom, and top. For example, calling
|
|
3597
|
-
* `frustum(-100, 100, 200, -200)` creates a frustum that’s 200 pixels wide
|
|
3598
|
-
* and 400 pixels tall. By default, these coordinates are set based on the
|
|
3599
|
-
* sketch’s width and height, as in
|
|
3600
|
-
* `ortho(-width / 20, width / 20, height / 20, -height / 20)`.
|
|
3601
|
-
*
|
|
3602
|
-
* The last two parameters, `near` and `far`, set the distance of the
|
|
3603
|
-
* frustum’s near and far plane from the camera. For example, calling
|
|
3604
|
-
* `ortho(-100, 100, 200, -200, 50, 1000)` creates a frustum that’s 200 pixels
|
|
3605
|
-
* wide, 400 pixels tall, starts 50 pixels from the camera, and ends 1,000
|
|
3606
|
-
* pixels from the camera. By default, near is set to `0.1 * 800`, which is
|
|
3607
|
-
* 1/10th the default distance between the camera and the origin. `far` is set
|
|
3608
|
-
* to `10 * 800`, which is 10 times the default distance between the camera
|
|
3609
|
-
* and the origin.
|
|
3610
|
-
*
|
|
3611
|
-
* Note: `frustum()` can only be used in WebGL mode.
|
|
3612
|
-
*
|
|
3613
|
-
* @method frustum
|
|
3614
|
-
* @for p5
|
|
3615
|
-
* @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 20`.
|
|
3616
|
-
* @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 20`.
|
|
3617
|
-
* @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 20`.
|
|
3618
|
-
* @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 20`.
|
|
3619
|
-
* @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to `0.1 * 800`.
|
|
3620
|
-
* @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `10 * 800`.
|
|
3621
|
-
* @chainable
|
|
3622
|
-
*
|
|
3623
|
-
* @example
|
|
3624
|
-
* <div>
|
|
3625
|
-
* <code>
|
|
3626
|
-
* function setup() {
|
|
3627
|
-
* createCanvas(100, 100, WEBGL);
|
|
3628
|
-
*
|
|
3629
|
-
* describe('A row of white cubes on a gray background.');
|
|
3630
|
-
* }
|
|
3631
|
-
*
|
|
3632
|
-
* function draw() {
|
|
3633
|
-
* background(200);
|
|
3634
|
-
*
|
|
3635
|
-
* // Apply the default frustum projection.
|
|
3636
|
-
* frustum();
|
|
3637
|
-
*
|
|
3638
|
-
* // Translate the origin toward the camera.
|
|
3639
|
-
* translate(-10, 10, 600);
|
|
3640
|
-
*
|
|
3641
|
-
* // Rotate the coordinate system.
|
|
3642
|
-
* rotateY(-0.1);
|
|
3643
|
-
* rotateX(-0.1);
|
|
3644
|
-
*
|
|
3645
|
-
* // Draw the row of boxes.
|
|
3646
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
3647
|
-
* translate(0, 0, -40);
|
|
3648
|
-
* box(10);
|
|
3649
|
-
* }
|
|
3650
|
-
* }
|
|
3651
|
-
* </code>
|
|
3652
|
-
* </div>
|
|
3653
|
-
*
|
|
3654
|
-
* <div>
|
|
3655
|
-
* <code>
|
|
3656
|
-
* function setup() {
|
|
3657
|
-
* createCanvas(100, 100, WEBGL);
|
|
3658
|
-
* describe('A white cube on a gray background.');
|
|
3659
|
-
* }
|
|
3660
|
-
*
|
|
3661
|
-
* function draw() {
|
|
3662
|
-
* background(200);
|
|
3663
|
-
*
|
|
3664
|
-
* // Adjust the frustum.
|
|
3665
|
-
* // Center it.
|
|
3666
|
-
* // Set its width and height to 20 pixels.
|
|
3667
|
-
* // Place its near plane 300 pixels from the camera.
|
|
3668
|
-
* // Place its far plane 350 pixels from the camera.
|
|
3669
|
-
* frustum(-10, 10, -10, 10, 300, 350);
|
|
3670
|
-
*
|
|
3671
|
-
* // Translate the origin toward the camera.
|
|
3672
|
-
* translate(-10, 10, 600);
|
|
3673
|
-
*
|
|
3674
|
-
* // Rotate the coordinate system.
|
|
3675
|
-
* rotateY(-0.1);
|
|
3676
|
-
* rotateX(-0.1);
|
|
3677
|
-
*
|
|
3678
|
-
* // Draw the row of boxes.
|
|
3679
|
-
* for (let i = 0; i < 6; i += 1) {
|
|
3680
|
-
* translate(0, 0, -40);
|
|
3681
|
-
* box(10);
|
|
3682
|
-
* }
|
|
3683
|
-
* }
|
|
3684
|
-
* </code>
|
|
3685
|
-
* </div>
|
|
3686
|
-
*/
|
|
3687
|
-
fn.frustum = function (...args) {
|
|
3688
|
-
this._assert3d('frustum');
|
|
3689
|
-
// p5._validateParameters('frustum', args);
|
|
3690
|
-
this._renderer.frustum(...args);
|
|
3691
|
-
return this;
|
|
3692
|
-
};
|
|
3693
|
-
|
|
3694
|
-
/**
|
|
3695
|
-
* Creates a new <a href="#/p5.Camera">p5.Camera</a> object and sets it
|
|
3696
|
-
* as the current (active) camera.
|
|
3697
|
-
*
|
|
3698
|
-
* The new camera is initialized with a default position `(0, 0, 800)` and a
|
|
3699
|
-
* default perspective projection. Its properties can be controlled with
|
|
3700
|
-
* <a href="#/p5.Camera">p5.Camera</a> methods such as
|
|
3701
|
-
* `myCamera.lookAt(0, 0, 0)`.
|
|
3702
|
-
*
|
|
3703
|
-
* Note: Every 3D sketch starts with a default camera initialized.
|
|
3704
|
-
* This camera can be controlled with the functions
|
|
3705
|
-
* <a href="#/p5/camera">camera()</a>,
|
|
3706
|
-
* <a href="#/p5/perspective">perspective()</a>,
|
|
3707
|
-
* <a href="#/p5/ortho">ortho()</a>, and
|
|
3708
|
-
* <a href="#/p5/frustum">frustum()</a> if it's the only camera in the scene.
|
|
3709
|
-
*
|
|
3710
|
-
* Note: `createCamera()` can only be used in WebGL mode.
|
|
3711
|
-
*
|
|
3712
|
-
* @method createCamera
|
|
3713
|
-
* @return {p5.Camera} the new camera.
|
|
3714
|
-
* @for p5
|
|
3715
|
-
*
|
|
3716
|
-
* @example
|
|
3717
|
-
* <div>
|
|
3718
|
-
* <code>
|
|
3719
|
-
* // Double-click to toggle between cameras.
|
|
3720
|
-
*
|
|
3721
|
-
* let cam1;
|
|
3722
|
-
* let cam2;
|
|
3723
|
-
* let usingCam1 = true;
|
|
3724
|
-
*
|
|
3725
|
-
* function setup() {
|
|
3726
|
-
* createCanvas(100, 100, WEBGL);
|
|
3727
|
-
*
|
|
3728
|
-
* // Create the first camera.
|
|
3729
|
-
* // Keep its default settings.
|
|
3730
|
-
* cam1 = createCamera();
|
|
3731
|
-
*
|
|
3732
|
-
* // Create the second camera.
|
|
3733
|
-
* // Place it at the top-left.
|
|
3734
|
-
* // Point it at the origin.
|
|
3735
|
-
* cam2 = createCamera();
|
|
3736
|
-
* cam2.setPosition(400, -400, 800);
|
|
3737
|
-
* cam2.lookAt(0, 0, 0);
|
|
3738
|
-
*
|
|
3739
|
-
* // Set the current camera to cam1.
|
|
3740
|
-
* setCamera(cam1);
|
|
3741
|
-
*
|
|
3742
|
-
* describe('A white cube on a gray background. The camera toggles between frontal and aerial views when the user double-clicks.');
|
|
3743
|
-
* }
|
|
3744
|
-
*
|
|
3745
|
-
* function draw() {
|
|
3746
|
-
* background(200);
|
|
3747
|
-
*
|
|
3748
|
-
* // Draw the box.
|
|
3749
|
-
* box();
|
|
3750
|
-
* }
|
|
3751
|
-
*
|
|
3752
|
-
* // Toggle the current camera when the user double-clicks.
|
|
3753
|
-
* function doubleClicked() {
|
|
3754
|
-
* if (usingCam1 === true) {
|
|
3755
|
-
* setCamera(cam2);
|
|
3756
|
-
* usingCam1 = false;
|
|
3757
|
-
* } else {
|
|
3758
|
-
* setCamera(cam1);
|
|
3759
|
-
* usingCam1 = true;
|
|
3760
|
-
* }
|
|
3761
|
-
* }
|
|
3762
|
-
* </code>
|
|
3763
|
-
* </div>
|
|
3764
|
-
*/
|
|
3765
|
-
fn.createCamera = function () {
|
|
3766
|
-
this._assert3d('createCamera');
|
|
3767
|
-
|
|
3768
|
-
return this._renderer.createCamera();
|
|
3769
|
-
};
|
|
3770
|
-
|
|
3771
|
-
/**
|
|
3772
|
-
* Sets the current (active) camera of a 3D sketch.
|
|
3773
|
-
*
|
|
3774
|
-
* `setCamera()` allows for switching between multiple cameras created with
|
|
3775
|
-
* <a href="#/p5/createCamera">createCamera()</a>.
|
|
3776
|
-
*
|
|
3777
|
-
* Note: `setCamera()` can only be used in WebGL mode.
|
|
3778
|
-
*
|
|
3779
|
-
* @method setCamera
|
|
3780
|
-
* @param {p5.Camera} cam camera that should be made active.
|
|
3781
|
-
* @for p5
|
|
3782
|
-
*
|
|
3783
|
-
* @example
|
|
3784
|
-
* <div>
|
|
3785
|
-
* <code>
|
|
3786
|
-
* // Double-click to toggle between cameras.
|
|
3787
|
-
*
|
|
3788
|
-
* let cam1;
|
|
3789
|
-
* let cam2;
|
|
3790
|
-
* let usingCam1 = true;
|
|
3791
|
-
*
|
|
3792
|
-
* function setup() {
|
|
3793
|
-
* createCanvas(100, 100, WEBGL);
|
|
3794
|
-
*
|
|
3795
|
-
* // Create the first camera.
|
|
3796
|
-
* // Keep its default settings.
|
|
3797
|
-
* cam1 = createCamera();
|
|
3798
|
-
*
|
|
3799
|
-
* // Create the second camera.
|
|
3800
|
-
* // Place it at the top-left.
|
|
3801
|
-
* // Point it at the origin.
|
|
3802
|
-
* cam2 = createCamera();
|
|
3803
|
-
* cam2.setPosition(400, -400, 800);
|
|
3804
|
-
* cam2.lookAt(0, 0, 0);
|
|
3805
|
-
*
|
|
3806
|
-
* // Set the current camera to cam1.
|
|
3807
|
-
* setCamera(cam1);
|
|
3808
|
-
*
|
|
3809
|
-
* describe('A white cube on a gray background. The camera toggles between frontal and aerial views when the user double-clicks.');
|
|
3810
|
-
* }
|
|
3811
|
-
*
|
|
3812
|
-
* function draw() {
|
|
3813
|
-
* background(200);
|
|
3814
|
-
*
|
|
3815
|
-
* // Draw the box.
|
|
3816
|
-
* box();
|
|
3817
|
-
* }
|
|
3818
|
-
*
|
|
3819
|
-
* // Toggle the current camera when the user double-clicks.
|
|
3820
|
-
* function doubleClicked() {
|
|
3821
|
-
* if (usingCam1 === true) {
|
|
3822
|
-
* setCamera(cam2);
|
|
3823
|
-
* usingCam1 = false;
|
|
3824
|
-
* } else {
|
|
3825
|
-
* setCamera(cam1);
|
|
3826
|
-
* usingCam1 = true;
|
|
3827
|
-
* }
|
|
3828
|
-
* }
|
|
3829
|
-
* </code>
|
|
3830
|
-
* </div>
|
|
3831
|
-
*/
|
|
3832
|
-
fn.setCamera = function (cam) {
|
|
3833
|
-
this._renderer.setCamera(cam);
|
|
3834
|
-
};
|
|
3835
|
-
|
|
3836
|
-
/**
|
|
3837
|
-
* A class to describe a camera for viewing a 3D sketch.
|
|
3838
|
-
*
|
|
3839
|
-
* Each `p5.Camera` object represents a camera that views a section of 3D
|
|
3840
|
-
* space. It stores information about the camera’s position, orientation, and
|
|
3841
|
-
* projection.
|
|
3842
|
-
*
|
|
3843
|
-
* In WebGL mode, the default camera is a `p5.Camera` object that can be
|
|
3844
|
-
* controlled with the <a href="#/p5/camera">camera()</a>,
|
|
3845
|
-
* <a href="#/p5/perspective">perspective()</a>,
|
|
3846
|
-
* <a href="#/p5/ortho">ortho()</a>, and
|
|
3847
|
-
* <a href="#/p5/frustum">frustum()</a> functions. Additional cameras can be
|
|
3848
|
-
* created with <a href="#/p5/createCamera">createCamera()</a> and activated
|
|
3849
|
-
* with <a href="#/p5/setCamera">setCamera()</a>.
|
|
3850
|
-
*
|
|
3851
|
-
* Note: `p5.Camera`’s methods operate in two coordinate systems:
|
|
3852
|
-
* - The “world” coordinate system describes positions in terms of their
|
|
3853
|
-
* relationship to the origin along the x-, y-, and z-axes. For example,
|
|
3854
|
-
* calling `myCamera.setPosition()` places the camera in 3D space using
|
|
3855
|
-
* "world" coordinates.
|
|
3856
|
-
* - The "local" coordinate system describes positions from the camera's point
|
|
3857
|
-
* of view: left-right, up-down, and forward-backward. For example, calling
|
|
3858
|
-
* `myCamera.move()` moves the camera along its own axes.
|
|
3859
|
-
*
|
|
3860
|
-
* @class p5.Camera
|
|
3861
|
-
* @constructor
|
|
3862
|
-
* @param {rendererGL} rendererGL instance of WebGL renderer
|
|
3863
|
-
*
|
|
3864
|
-
* @example
|
|
3865
|
-
* <div>
|
|
3866
|
-
* <code>
|
|
3867
|
-
* let cam;
|
|
3868
|
-
* let delta = 0.001;
|
|
3869
|
-
*
|
|
3870
|
-
* function setup() {
|
|
3871
|
-
* createCanvas(100, 100, WEBGL);
|
|
3872
|
-
*
|
|
3873
|
-
* // Create a p5.Camera object.
|
|
3874
|
-
* cam = createCamera();
|
|
3875
|
-
*
|
|
3876
|
-
* // Set the camera
|
|
3877
|
-
* setCamera(cam);
|
|
3878
|
-
*
|
|
3879
|
-
* // Place the camera at the top-center.
|
|
3880
|
-
* cam.setPosition(0, -400, 800);
|
|
3881
|
-
*
|
|
3882
|
-
* // Point the camera at the origin.
|
|
3883
|
-
* cam.lookAt(0, 0, 0);
|
|
3884
|
-
*
|
|
3885
|
-
* describe(
|
|
3886
|
-
* 'A white cube on a gray background. The cube goes in and out of view as the camera pans left and right.'
|
|
3887
|
-
* );
|
|
3888
|
-
* }
|
|
3889
|
-
*
|
|
3890
|
-
* function draw() {
|
|
3891
|
-
* background(200);
|
|
3892
|
-
*
|
|
3893
|
-
* // Turn the camera left and right, called "panning".
|
|
3894
|
-
* cam.pan(delta);
|
|
3895
|
-
*
|
|
3896
|
-
* // Switch directions every 120 frames.
|
|
3897
|
-
* if (frameCount % 120 === 0) {
|
|
3898
|
-
* delta *= -1;
|
|
3899
|
-
* }
|
|
3900
|
-
*
|
|
3901
|
-
* // Draw the box.
|
|
3902
|
-
* box();
|
|
3903
|
-
* }
|
|
3904
|
-
* </code>
|
|
3905
|
-
* </div>
|
|
3906
|
-
*
|
|
3907
|
-
* <div>
|
|
3908
|
-
* <code>
|
|
3909
|
-
* // Double-click to toggle between cameras.
|
|
3910
|
-
*
|
|
3911
|
-
* let cam1;
|
|
3912
|
-
* let cam2;
|
|
3913
|
-
* let isDefaultCamera = true;
|
|
3914
|
-
*
|
|
3915
|
-
* function setup() {
|
|
3916
|
-
* createCanvas(100, 100, WEBGL);
|
|
3917
|
-
*
|
|
3918
|
-
* // Create the first camera.
|
|
3919
|
-
* // Keep its default settings.
|
|
3920
|
-
* cam1 = createCamera();
|
|
3921
|
-
*
|
|
3922
|
-
* // Create the second camera.
|
|
3923
|
-
* // Place it at the top-left.
|
|
3924
|
-
* // Point it at the origin.
|
|
3925
|
-
* cam2 = createCamera();
|
|
3926
|
-
* cam2.setPosition(400, -400, 800);
|
|
3927
|
-
* cam2.lookAt(0, 0, 0);
|
|
3928
|
-
*
|
|
3929
|
-
* // Set the current camera to cam1.
|
|
3930
|
-
* setCamera(cam1);
|
|
3931
|
-
*
|
|
3932
|
-
* describe(
|
|
3933
|
-
* 'A white cube on a gray background. The camera toggles between frontal and aerial views when the user double-clicks.'
|
|
3934
|
-
* );
|
|
3935
|
-
* }
|
|
3936
|
-
*
|
|
3937
|
-
* function draw() {
|
|
3938
|
-
* background(200);
|
|
3939
|
-
*
|
|
3940
|
-
* // Draw the box.
|
|
3941
|
-
* box();
|
|
3942
|
-
* }
|
|
3943
|
-
*
|
|
3944
|
-
* // Toggle the current camera when the user double-clicks.
|
|
3945
|
-
* function doubleClicked() {
|
|
3946
|
-
* if (isDefaultCamera === true) {
|
|
3947
|
-
* setCamera(cam2);
|
|
3948
|
-
* isDefaultCamera = false;
|
|
3949
|
-
* } else {
|
|
3950
|
-
* setCamera(cam1);
|
|
3951
|
-
* isDefaultCamera = true;
|
|
3952
|
-
* }
|
|
3953
|
-
* }
|
|
3954
|
-
* </code>
|
|
3955
|
-
* </div>
|
|
3956
|
-
*/
|
|
3957
|
-
p5.Camera = Camera;
|
|
3958
|
-
|
|
3959
|
-
RendererGL.prototype.camera = function(...args) {
|
|
3960
|
-
this.states.curCamera.camera(...args);
|
|
3961
|
-
}
|
|
3962
|
-
|
|
3963
|
-
RendererGL.prototype.perspective = function(...args) {
|
|
3964
|
-
this.states.curCamera.perspective(...args);
|
|
3965
|
-
}
|
|
3966
|
-
|
|
3967
|
-
RendererGL.prototype.linePerspective = function(enable) {
|
|
3968
|
-
if (enable !== undefined) {
|
|
3969
|
-
// Set the line perspective if enable is provided
|
|
3970
|
-
this.states.curCamera.useLinePerspective = enable;
|
|
3971
|
-
} else {
|
|
3972
|
-
// If no argument is provided, return the current value
|
|
3973
|
-
return this.states.curCamera.useLinePerspective;
|
|
3974
|
-
}
|
|
3975
|
-
}
|
|
3976
|
-
|
|
3977
|
-
RendererGL.prototype.ortho = function(...args) {
|
|
3978
|
-
this.states.curCamera.ortho(...args);
|
|
3979
|
-
}
|
|
3980
|
-
|
|
3981
|
-
RendererGL.prototype.frustum = function(...args) {
|
|
3982
|
-
this.states.curCamera.frustum(...args);
|
|
3983
|
-
}
|
|
3984
|
-
|
|
3985
|
-
RendererGL.prototype.createCamera = function() {
|
|
3986
|
-
// compute default camera settings, then set a default camera
|
|
3987
|
-
const _cam = new Camera(this);
|
|
3988
|
-
_cam._computeCameraDefaultSettings();
|
|
3989
|
-
_cam._setDefaultCamera();
|
|
3990
|
-
|
|
3991
|
-
return _cam;
|
|
3992
|
-
}
|
|
3993
|
-
|
|
3994
|
-
RendererGL.prototype.setCamera = function(cam) {
|
|
3995
|
-
this.states.setValue('curCamera', cam);
|
|
3996
|
-
|
|
3997
|
-
// set the projection matrix (which is not normally updated each frame)
|
|
3998
|
-
this.states.setValue('uPMatrix', this.states.uPMatrix.clone());
|
|
3999
|
-
this.states.uPMatrix.set(cam.projMatrix);
|
|
4000
|
-
this.states.setValue('uViewMatrix', this.states.uViewMatrix.clone());
|
|
4001
|
-
this.states.uViewMatrix.set(cam.cameraMatrix);
|
|
4002
|
-
}
|
|
4003
|
-
}
|
|
4004
|
-
|
|
4005
|
-
export default camera;
|
|
4006
|
-
export { Camera };
|
|
4007
|
-
|
|
4008
|
-
if(typeof p5 !== 'undefined'){
|
|
4009
|
-
camera(p5, p5.prototype);
|
|
4010
|
-
}
|