@guinetik/gcanvas 1.0.0
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/.github/workflows/release.yaml +70 -0
- package/.jshintrc +4 -0
- package/.vscode/settings.json +22 -0
- package/CLAUDE.md +310 -0
- package/blackhole.jpg +0 -0
- package/demo.png +0 -0
- package/demos/CNAME +1 -0
- package/demos/animations.html +31 -0
- package/demos/basic.html +38 -0
- package/demos/baskara.html +31 -0
- package/demos/bezier.html +35 -0
- package/demos/beziersignature.html +29 -0
- package/demos/blackhole.html +28 -0
- package/demos/blob.html +35 -0
- package/demos/demos.css +289 -0
- package/demos/easing.html +28 -0
- package/demos/events.html +195 -0
- package/demos/fluent.html +647 -0
- package/demos/fractals.html +36 -0
- package/demos/genart.html +26 -0
- package/demos/gendream.html +26 -0
- package/demos/group.html +36 -0
- package/demos/home.html +587 -0
- package/demos/index.html +364 -0
- package/demos/isometric.html +34 -0
- package/demos/js/animations.js +452 -0
- package/demos/js/basic.js +204 -0
- package/demos/js/baskara.js +751 -0
- package/demos/js/bezier.js +692 -0
- package/demos/js/beziersignature.js +241 -0
- package/demos/js/blackhole/accretiondisk.obj.js +379 -0
- package/demos/js/blackhole/blackhole.obj.js +318 -0
- package/demos/js/blackhole/index.js +409 -0
- package/demos/js/blackhole/particle.js +56 -0
- package/demos/js/blackhole/starfield.obj.js +218 -0
- package/demos/js/blob.js +2263 -0
- package/demos/js/easing.js +477 -0
- package/demos/js/fluent.js +183 -0
- package/demos/js/fractals.js +931 -0
- package/demos/js/fractalworker.js +93 -0
- package/demos/js/genart.js +268 -0
- package/demos/js/gendream.js +209 -0
- package/demos/js/group.js +140 -0
- package/demos/js/info-toggle.js +25 -0
- package/demos/js/isometric.js +863 -0
- package/demos/js/kerr.js +1556 -0
- package/demos/js/lavalamp.js +590 -0
- package/demos/js/layout.js +354 -0
- package/demos/js/mondrian.js +285 -0
- package/demos/js/opacity.js +275 -0
- package/demos/js/painter.js +484 -0
- package/demos/js/particles-showcase.js +514 -0
- package/demos/js/particles.js +299 -0
- package/demos/js/patterns.js +397 -0
- package/demos/js/penrose/artifact.js +69 -0
- package/demos/js/penrose/blackhole.js +121 -0
- package/demos/js/penrose/constants.js +73 -0
- package/demos/js/penrose/game.js +943 -0
- package/demos/js/penrose/lore.js +278 -0
- package/demos/js/penrose/penrosescene.js +892 -0
- package/demos/js/penrose/ship.js +216 -0
- package/demos/js/penrose/sounds.js +211 -0
- package/demos/js/penrose/voidparticle.js +55 -0
- package/demos/js/penrose/voidscene.js +258 -0
- package/demos/js/penrose/voidship.js +144 -0
- package/demos/js/penrose/wormhole.js +46 -0
- package/demos/js/pipeline.js +555 -0
- package/demos/js/scene.js +304 -0
- package/demos/js/scenes.js +320 -0
- package/demos/js/schrodinger.js +410 -0
- package/demos/js/schwarzschild.js +1023 -0
- package/demos/js/shapes.js +628 -0
- package/demos/js/space/alien.js +171 -0
- package/demos/js/space/boom.js +98 -0
- package/demos/js/space/boss.js +353 -0
- package/demos/js/space/buff.js +73 -0
- package/demos/js/space/bullet.js +102 -0
- package/demos/js/space/constants.js +85 -0
- package/demos/js/space/game.js +1884 -0
- package/demos/js/space/hud.js +112 -0
- package/demos/js/space/laserbeam.js +179 -0
- package/demos/js/space/lightning.js +277 -0
- package/demos/js/space/minion.js +192 -0
- package/demos/js/space/missile.js +212 -0
- package/demos/js/space/player.js +430 -0
- package/demos/js/space/powerup.js +90 -0
- package/demos/js/space/starfield.js +58 -0
- package/demos/js/space/starpower.js +90 -0
- package/demos/js/spacetime.js +559 -0
- package/demos/js/svgtween.js +204 -0
- package/demos/js/tde/accretiondisk.js +418 -0
- package/demos/js/tde/blackhole.js +219 -0
- package/demos/js/tde/blackholescene.js +209 -0
- package/demos/js/tde/config.js +59 -0
- package/demos/js/tde/index.js +695 -0
- package/demos/js/tde/jets.js +290 -0
- package/demos/js/tde/lensedstarfield.js +147 -0
- package/demos/js/tde/tdestar.js +317 -0
- package/demos/js/tde/tidalstream.js +356 -0
- package/demos/js/tde_old/blackhole.obj.js +354 -0
- package/demos/js/tde_old/debris.obj.js +791 -0
- package/demos/js/tde_old/flare.obj.js +239 -0
- package/demos/js/tde_old/index.js +448 -0
- package/demos/js/tde_old/star.obj.js +812 -0
- package/demos/js/tiles.js +312 -0
- package/demos/js/tweendemo.js +79 -0
- package/demos/js/visibility.js +102 -0
- package/demos/kerr.html +28 -0
- package/demos/lavalamp.html +27 -0
- package/demos/layouts.html +37 -0
- package/demos/logo.svg +4 -0
- package/demos/loop.html +84 -0
- package/demos/mondrian.html +32 -0
- package/demos/og_image.png +0 -0
- package/demos/opacity.html +36 -0
- package/demos/painter.html +39 -0
- package/demos/particles-showcase.html +28 -0
- package/demos/particles.html +24 -0
- package/demos/patterns.html +33 -0
- package/demos/penrose-game.html +31 -0
- package/demos/pipeline.html +737 -0
- package/demos/scene.html +33 -0
- package/demos/scenes.html +96 -0
- package/demos/schrodinger.html +27 -0
- package/demos/schwarzschild.html +27 -0
- package/demos/shapes.html +16 -0
- package/demos/space.html +85 -0
- package/demos/spacetime.html +27 -0
- package/demos/svgtween.html +29 -0
- package/demos/tde.html +28 -0
- package/demos/tiles.html +28 -0
- package/demos/transforms.html +400 -0
- package/demos/tween.html +45 -0
- package/demos/visibility.html +33 -0
- package/disk_example.png +0 -0
- package/docs/README.md +222 -0
- package/docs/concepts/architecture-overview.md +204 -0
- package/docs/concepts/lifecycle.md +255 -0
- package/docs/concepts/rendering-pipeline.md +279 -0
- package/docs/concepts/tde-zorder.md +106 -0
- package/docs/concepts/two-layer-architecture.md +229 -0
- package/docs/getting-started/first-game.md +354 -0
- package/docs/getting-started/hello-world.md +269 -0
- package/docs/getting-started/installation.md +157 -0
- package/docs/modules/collision/README.md +453 -0
- package/docs/modules/fluent/README.md +1075 -0
- package/docs/modules/game/README.md +303 -0
- package/docs/modules/isometric-camera.md +210 -0
- package/docs/modules/isometric.md +275 -0
- package/docs/modules/painter/README.md +328 -0
- package/docs/modules/particle/README.md +559 -0
- package/docs/modules/shapes/README.md +221 -0
- package/docs/modules/shapes/base/euclidian.md +123 -0
- package/docs/modules/shapes/base/geometry2d.md +204 -0
- package/docs/modules/shapes/base/renderable.md +215 -0
- package/docs/modules/shapes/base/shape.md +262 -0
- package/docs/modules/shapes/base/transformable.md +243 -0
- package/docs/modules/shapes/hierarchy.md +218 -0
- package/docs/modules/state/README.md +577 -0
- package/docs/modules/util/README.md +99 -0
- package/docs/modules/util/camera3d.md +412 -0
- package/docs/modules/util/scene3d.md +395 -0
- package/index.html +17 -0
- package/jsdoc.json +50 -0
- package/package.json +55 -0
- package/readme.md +599 -0
- package/scripts/build-demo.js +69 -0
- package/scripts/bundle4llm.js +276 -0
- package/scripts/clearconsole.js +48 -0
- package/src/collision/collision-system.js +332 -0
- package/src/collision/collision.js +303 -0
- package/src/collision/index.js +10 -0
- package/src/fluent/fluent-game.js +430 -0
- package/src/fluent/fluent-go.js +1060 -0
- package/src/fluent/fluent-layer.js +152 -0
- package/src/fluent/fluent-scene.js +291 -0
- package/src/fluent/index.js +98 -0
- package/src/fluent/sketch.js +380 -0
- package/src/game/game.js +467 -0
- package/src/game/index.js +49 -0
- package/src/game/objects/go.js +220 -0
- package/src/game/objects/imagego.js +30 -0
- package/src/game/objects/index.js +54 -0
- package/src/game/objects/isometric-scene.js +260 -0
- package/src/game/objects/layoutscene.js +549 -0
- package/src/game/objects/scene.js +175 -0
- package/src/game/objects/scene3d.js +118 -0
- package/src/game/objects/text.js +221 -0
- package/src/game/objects/wrapper.js +232 -0
- package/src/game/pipeline.js +243 -0
- package/src/game/ui/button.js +396 -0
- package/src/game/ui/cursor.js +93 -0
- package/src/game/ui/fps.js +91 -0
- package/src/game/ui/index.js +5 -0
- package/src/game/ui/togglebutton.js +93 -0
- package/src/game/ui/tooltip.js +249 -0
- package/src/index.js +25 -0
- package/src/io/events.js +20 -0
- package/src/io/index.js +86 -0
- package/src/io/input.js +70 -0
- package/src/io/keys.js +152 -0
- package/src/io/mouse.js +61 -0
- package/src/io/touch.js +39 -0
- package/src/logger/debugtab.js +138 -0
- package/src/logger/index.js +3 -0
- package/src/logger/loggable.js +47 -0
- package/src/logger/logger.js +113 -0
- package/src/math/complex.js +37 -0
- package/src/math/constants.js +1 -0
- package/src/math/fractal.js +1271 -0
- package/src/math/gr.js +201 -0
- package/src/math/heat.js +202 -0
- package/src/math/index.js +12 -0
- package/src/math/noise.js +433 -0
- package/src/math/orbital.js +191 -0
- package/src/math/patterns.js +1339 -0
- package/src/math/penrose.js +259 -0
- package/src/math/quantum.js +115 -0
- package/src/math/random.js +195 -0
- package/src/math/tensor.js +1009 -0
- package/src/mixins/anchor.js +131 -0
- package/src/mixins/draggable.js +72 -0
- package/src/mixins/index.js +2 -0
- package/src/motion/bezier.js +132 -0
- package/src/motion/bounce.js +58 -0
- package/src/motion/easing.js +349 -0
- package/src/motion/float.js +130 -0
- package/src/motion/follow.js +125 -0
- package/src/motion/hop.js +52 -0
- package/src/motion/index.js +82 -0
- package/src/motion/motion.js +1124 -0
- package/src/motion/orbit.js +49 -0
- package/src/motion/oscillate.js +39 -0
- package/src/motion/parabolic.js +141 -0
- package/src/motion/patrol.js +147 -0
- package/src/motion/pendulum.js +48 -0
- package/src/motion/pulse.js +88 -0
- package/src/motion/shake.js +83 -0
- package/src/motion/spiral.js +144 -0
- package/src/motion/spring.js +150 -0
- package/src/motion/swing.js +47 -0
- package/src/motion/tween.js +92 -0
- package/src/motion/tweenetik.js +139 -0
- package/src/motion/waypoint.js +210 -0
- package/src/painter/index.js +8 -0
- package/src/painter/painter.colors.js +331 -0
- package/src/painter/painter.effects.js +230 -0
- package/src/painter/painter.img.js +229 -0
- package/src/painter/painter.js +295 -0
- package/src/painter/painter.lines.js +189 -0
- package/src/painter/painter.opacity.js +41 -0
- package/src/painter/painter.shapes.js +277 -0
- package/src/painter/painter.text.js +273 -0
- package/src/particle/emitter.js +124 -0
- package/src/particle/index.js +11 -0
- package/src/particle/particle-system.js +322 -0
- package/src/particle/particle.js +71 -0
- package/src/particle/updaters.js +170 -0
- package/src/shapes/arc.js +43 -0
- package/src/shapes/arrow.js +33 -0
- package/src/shapes/bezier.js +42 -0
- package/src/shapes/circle.js +62 -0
- package/src/shapes/clouds.js +56 -0
- package/src/shapes/cone.js +219 -0
- package/src/shapes/cross.js +70 -0
- package/src/shapes/cube.js +244 -0
- package/src/shapes/cylinder.js +254 -0
- package/src/shapes/diamond.js +48 -0
- package/src/shapes/euclidian.js +111 -0
- package/src/shapes/figure.js +115 -0
- package/src/shapes/geometry.js +220 -0
- package/src/shapes/group.js +375 -0
- package/src/shapes/heart.js +42 -0
- package/src/shapes/hexagon.js +26 -0
- package/src/shapes/image.js +192 -0
- package/src/shapes/index.js +111 -0
- package/src/shapes/line.js +29 -0
- package/src/shapes/pattern.js +90 -0
- package/src/shapes/pin.js +44 -0
- package/src/shapes/poly.js +31 -0
- package/src/shapes/prism.js +226 -0
- package/src/shapes/rect.js +35 -0
- package/src/shapes/renderable.js +333 -0
- package/src/shapes/ring.js +26 -0
- package/src/shapes/roundrect.js +95 -0
- package/src/shapes/shape.js +117 -0
- package/src/shapes/slice.js +26 -0
- package/src/shapes/sphere.js +314 -0
- package/src/shapes/sphere3d.js +537 -0
- package/src/shapes/square.js +15 -0
- package/src/shapes/star.js +99 -0
- package/src/shapes/svg.js +408 -0
- package/src/shapes/text.js +553 -0
- package/src/shapes/traceable.js +83 -0
- package/src/shapes/transform.js +357 -0
- package/src/shapes/transformable.js +172 -0
- package/src/shapes/triangle.js +26 -0
- package/src/sound/index.js +17 -0
- package/src/sound/sound.js +473 -0
- package/src/sound/synth.analyzer.js +149 -0
- package/src/sound/synth.effects.js +207 -0
- package/src/sound/synth.envelope.js +59 -0
- package/src/sound/synth.js +229 -0
- package/src/sound/synth.musical.js +160 -0
- package/src/sound/synth.noise.js +85 -0
- package/src/sound/synth.oscillators.js +293 -0
- package/src/state/index.js +10 -0
- package/src/state/state-machine.js +371 -0
- package/src/util/camera3d.js +438 -0
- package/src/util/index.js +6 -0
- package/src/util/isometric-camera.js +235 -0
- package/src/util/layout.js +317 -0
- package/src/util/position.js +147 -0
- package/src/util/tasks.js +47 -0
- package/src/util/zindex.js +287 -0
- package/src/webgl/index.js +9 -0
- package/src/webgl/shaders/sphere-shaders.js +994 -0
- package/src/webgl/webgl-renderer.js +388 -0
- package/tde.png +0 -0
- package/test/math/orbital.test.js +61 -0
- package/test/math/tensor.test.js +114 -0
- package/test/particle/emitter.test.js +204 -0
- package/test/particle/particle-system.test.js +310 -0
- package/test/particle/particle.test.js +116 -0
- package/test/particle/updaters.test.js +386 -0
- package/test/setup.js +120 -0
- package/test/shapes/euclidian.test.js +44 -0
- package/test/shapes/geometry.test.js +86 -0
- package/test/shapes/group.test.js +86 -0
- package/test/shapes/rectangle.test.js +64 -0
- package/test/shapes/transform.test.js +379 -0
- package/test/util/camera3d.test.js +428 -0
- package/test/util/scene3d.test.js +352 -0
- package/types/collision.d.ts +249 -0
- package/types/common.d.ts +155 -0
- package/types/game.d.ts +497 -0
- package/types/index.d.ts +309 -0
- package/types/io.d.ts +188 -0
- package/types/logger.d.ts +127 -0
- package/types/math.d.ts +268 -0
- package/types/mixins.d.ts +92 -0
- package/types/motion.d.ts +678 -0
- package/types/painter.d.ts +378 -0
- package/types/shapes.d.ts +864 -0
- package/types/sound.d.ts +672 -0
- package/types/state.d.ts +251 -0
- package/types/util.d.ts +253 -0
- package/vite.config.js +50 -0
- package/vitest.config.js +13 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# Camera3D
|
|
2
|
+
|
|
3
|
+
> Pseudo-3D projection with perspective, rotation, and interactive mouse/touch controls.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Camera3D provides 3D to 2D projection for creating pseudo-3D effects on a 2D canvas. It handles:
|
|
8
|
+
|
|
9
|
+
- **Perspective projection** with configurable distance
|
|
10
|
+
- **3-axis rotation** (X, Y, Z)
|
|
11
|
+
- **Mouse/touch drag rotation** with sensitivity control
|
|
12
|
+
- **Auto-rotation** for ambient effects
|
|
13
|
+
- **Double-click reset** to initial orientation
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { Camera3D } from 'gcanvas';
|
|
19
|
+
|
|
20
|
+
// Create camera with initial rotation
|
|
21
|
+
const camera = new Camera3D({
|
|
22
|
+
rotationX: 0.3, // Tilt down slightly
|
|
23
|
+
rotationY: 0, // No horizontal rotation
|
|
24
|
+
perspective: 800, // Perspective distance
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Enable mouse drag rotation
|
|
28
|
+
camera.enableMouseControl(canvas);
|
|
29
|
+
|
|
30
|
+
// In render loop - project 3D points to 2D
|
|
31
|
+
const { x, y, scale, z } = camera.project(x3d, y3d, z3d);
|
|
32
|
+
|
|
33
|
+
// Draw at projected position (relative to screen center)
|
|
34
|
+
ctx.save();
|
|
35
|
+
ctx.translate(canvas.width / 2, canvas.height / 2);
|
|
36
|
+
ctx.fillRect(x, y, 10 * scale, 10 * scale);
|
|
37
|
+
ctx.restore();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Constructor Options
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
const camera = new Camera3D({
|
|
44
|
+
// Rotation (radians)
|
|
45
|
+
rotationX: 0, // Vertical tilt (up/down)
|
|
46
|
+
rotationY: 0, // Horizontal spin (left/right)
|
|
47
|
+
rotationZ: 0, // Roll
|
|
48
|
+
|
|
49
|
+
// Perspective
|
|
50
|
+
perspective: 800, // Higher = less distortion
|
|
51
|
+
|
|
52
|
+
// Mouse control
|
|
53
|
+
sensitivity: 0.005, // Drag sensitivity
|
|
54
|
+
clampX: true, // Limit vertical rotation
|
|
55
|
+
minRotationX: -1.5, // Min X rotation
|
|
56
|
+
maxRotationX: 1.5, // Max X rotation
|
|
57
|
+
|
|
58
|
+
// Auto-rotation
|
|
59
|
+
autoRotate: false, // Enable auto-rotation
|
|
60
|
+
autoRotateSpeed: 0.5, // Radians per second
|
|
61
|
+
autoRotateAxis: 'y', // Axis: 'x', 'y', or 'z'
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
| Option | Type | Default | Description |
|
|
66
|
+
|--------|------|---------|-------------|
|
|
67
|
+
| `rotationX` | `number` | `0` | Initial X rotation (radians) |
|
|
68
|
+
| `rotationY` | `number` | `0` | Initial Y rotation (radians) |
|
|
69
|
+
| `rotationZ` | `number` | `0` | Initial Z rotation (radians) |
|
|
70
|
+
| `perspective` | `number` | `800` | Perspective distance |
|
|
71
|
+
| `sensitivity` | `number` | `0.005` | Mouse drag sensitivity |
|
|
72
|
+
| `clampX` | `boolean` | `true` | Clamp vertical rotation |
|
|
73
|
+
| `minRotationX` | `number` | `-1.5` | Min X rotation limit |
|
|
74
|
+
| `maxRotationX` | `number` | `1.5` | Max X rotation limit |
|
|
75
|
+
| `autoRotate` | `boolean` | `false` | Enable auto-rotation |
|
|
76
|
+
| `autoRotateSpeed` | `number` | `0.5` | Auto-rotation speed |
|
|
77
|
+
| `autoRotateAxis` | `string` | `'y'` | Auto-rotation axis |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Core Methods
|
|
82
|
+
|
|
83
|
+
### project(x, y, z)
|
|
84
|
+
|
|
85
|
+
Project a 3D point to 2D screen coordinates.
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
const point3d = { x: 100, y: 50, z: -200 };
|
|
89
|
+
const projected = camera.project(point3d.x, point3d.y, point3d.z);
|
|
90
|
+
|
|
91
|
+
// Result:
|
|
92
|
+
// {
|
|
93
|
+
// x: 120, // Screen X (relative to origin)
|
|
94
|
+
// y: 45, // Screen Y (relative to origin)
|
|
95
|
+
// z: -180, // Depth (for sorting)
|
|
96
|
+
// scale: 0.8 // Size multiplier (perspective)
|
|
97
|
+
// }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### projectAll(points)
|
|
101
|
+
|
|
102
|
+
Project multiple points at once.
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
const points3d = [
|
|
106
|
+
{ x: 0, y: 0, z: -100 },
|
|
107
|
+
{ x: 100, y: 0, z: 0 },
|
|
108
|
+
{ x: 0, y: 100, z: 100 },
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
const projected = camera.projectAll(points3d);
|
|
112
|
+
// Returns array of projected points
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### update(dt)
|
|
116
|
+
|
|
117
|
+
Update camera for auto-rotation (call in game loop).
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
update(dt) {
|
|
121
|
+
super.update(dt);
|
|
122
|
+
this.camera.update(dt); // Updates auto-rotation
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Mouse/Touch Control
|
|
129
|
+
|
|
130
|
+
### enableMouseControl(canvas, options)
|
|
131
|
+
|
|
132
|
+
Enable interactive rotation via mouse drag or touch.
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
camera.enableMouseControl(canvas);
|
|
136
|
+
|
|
137
|
+
// With options
|
|
138
|
+
camera.enableMouseControl(canvas, {
|
|
139
|
+
invertX: false, // Invert horizontal drag
|
|
140
|
+
invertY: false, // Invert vertical drag
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Features:
|
|
145
|
+
- **Drag** to rotate camera
|
|
146
|
+
- **Double-click** to reset to initial rotation
|
|
147
|
+
- **Touch** support for mobile devices
|
|
148
|
+
- Auto-pauses auto-rotation during drag
|
|
149
|
+
|
|
150
|
+
### disableMouseControl()
|
|
151
|
+
|
|
152
|
+
Remove mouse/touch controls.
|
|
153
|
+
|
|
154
|
+
```js
|
|
155
|
+
camera.disableMouseControl();
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### isDragging()
|
|
159
|
+
|
|
160
|
+
Check if user is currently dragging.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
if (!camera.isDragging()) {
|
|
164
|
+
// Do something when not interacting
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Rotation Control
|
|
171
|
+
|
|
172
|
+
### setRotation(x, y, z)
|
|
173
|
+
|
|
174
|
+
Set rotation angles directly.
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
camera.setRotation(0.5, -0.3, 0);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### rotate(dx, dy, dz)
|
|
181
|
+
|
|
182
|
+
Add to current rotation.
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
camera.rotate(0.01, 0.02, 0); // Incremental rotation
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### reset()
|
|
189
|
+
|
|
190
|
+
Reset to initial rotation values.
|
|
191
|
+
|
|
192
|
+
```js
|
|
193
|
+
camera.reset();
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### lookAt(x, y, z)
|
|
197
|
+
|
|
198
|
+
Set rotation to face a point.
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
camera.lookAt(100, 50, 200); // Look toward point
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Properties
|
|
207
|
+
|
|
208
|
+
| Property | Type | Description |
|
|
209
|
+
|----------|------|-------------|
|
|
210
|
+
| `rotationX` | `number` | Current X rotation |
|
|
211
|
+
| `rotationY` | `number` | Current Y rotation |
|
|
212
|
+
| `rotationZ` | `number` | Current Z rotation |
|
|
213
|
+
| `perspective` | `number` | Perspective distance |
|
|
214
|
+
| `autoRotate` | `boolean` | Is auto-rotating |
|
|
215
|
+
| `autoRotateSpeed` | `number` | Auto-rotation speed |
|
|
216
|
+
| `sensitivity` | `number` | Mouse sensitivity |
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Usage Patterns
|
|
221
|
+
|
|
222
|
+
### With Scene3D
|
|
223
|
+
|
|
224
|
+
The most common usage - let Scene3D handle projection automatically:
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
import { Camera3D, Scene3D, GameObject } from 'gcanvas';
|
|
228
|
+
|
|
229
|
+
class MyDemo extends Game {
|
|
230
|
+
init() {
|
|
231
|
+
super.init();
|
|
232
|
+
|
|
233
|
+
this.camera = new Camera3D({
|
|
234
|
+
rotationX: 0.2,
|
|
235
|
+
perspective: 800,
|
|
236
|
+
});
|
|
237
|
+
this.camera.enableMouseControl(this.canvas);
|
|
238
|
+
|
|
239
|
+
this.scene3d = new Scene3D(this, {
|
|
240
|
+
x: this.width / 2,
|
|
241
|
+
y: this.height / 2,
|
|
242
|
+
camera: this.camera,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Add objects - Scene3D handles projection
|
|
246
|
+
const obj = new MyObject(this);
|
|
247
|
+
obj.z = 100; // Set z coordinate
|
|
248
|
+
this.scene3d.add(obj);
|
|
249
|
+
|
|
250
|
+
this.pipeline.add(this.scene3d);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
update(dt) {
|
|
254
|
+
super.update(dt);
|
|
255
|
+
this.camera.update(dt);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### With ParticleSystem
|
|
261
|
+
|
|
262
|
+
For 3D particle effects:
|
|
263
|
+
|
|
264
|
+
```js
|
|
265
|
+
import { Camera3D, ParticleSystem, ParticleEmitter, Updaters } from 'gcanvas';
|
|
266
|
+
|
|
267
|
+
const camera = new Camera3D({ rotationX: 0.3 });
|
|
268
|
+
camera.enableMouseControl(canvas);
|
|
269
|
+
|
|
270
|
+
const particles = new ParticleSystem(game, {
|
|
271
|
+
camera: camera,
|
|
272
|
+
depthSort: true,
|
|
273
|
+
updaters: [Updaters.velocity, Updaters.lifetime],
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
particles.addEmitter("3d-burst", new ParticleEmitter({
|
|
277
|
+
position: { x: 0, y: 0, z: 0 },
|
|
278
|
+
spread: { x: 50, y: 50, z: 50 }, // 3D spread
|
|
279
|
+
velocitySpread: { x: 100, y: 100, z: 100 },
|
|
280
|
+
}));
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Manual Projection
|
|
284
|
+
|
|
285
|
+
For direct control over rendering:
|
|
286
|
+
|
|
287
|
+
```js
|
|
288
|
+
render() {
|
|
289
|
+
super.render();
|
|
290
|
+
|
|
291
|
+
const cx = this.width / 2;
|
|
292
|
+
const cy = this.height / 2;
|
|
293
|
+
|
|
294
|
+
Painter.useCtx((ctx) => {
|
|
295
|
+
ctx.save();
|
|
296
|
+
ctx.translate(cx, cy);
|
|
297
|
+
|
|
298
|
+
// Project and draw each point
|
|
299
|
+
for (const point of this.points3d) {
|
|
300
|
+
const p = this.camera.project(point.x, point.y, point.z);
|
|
301
|
+
|
|
302
|
+
// Skip points behind camera
|
|
303
|
+
if (p.z < -this.camera.perspective + 10) continue;
|
|
304
|
+
|
|
305
|
+
// Draw with perspective scaling
|
|
306
|
+
const size = 10 * p.scale;
|
|
307
|
+
ctx.fillStyle = 'white';
|
|
308
|
+
ctx.beginPath();
|
|
309
|
+
ctx.arc(p.x, p.y, size, 0, Math.PI * 2);
|
|
310
|
+
ctx.fill();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
ctx.restore();
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Depth Sorting
|
|
319
|
+
|
|
320
|
+
Sort objects back-to-front for correct overlap:
|
|
321
|
+
|
|
322
|
+
```js
|
|
323
|
+
// Build render list with z values
|
|
324
|
+
const renderList = this.objects.map(obj => {
|
|
325
|
+
const p = this.camera.project(obj.x, obj.y, obj.z);
|
|
326
|
+
return { obj, ...p };
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Sort back-to-front (higher z = further back)
|
|
330
|
+
renderList.sort((a, b) => b.z - a.z);
|
|
331
|
+
|
|
332
|
+
// Render in order
|
|
333
|
+
for (const item of renderList) {
|
|
334
|
+
// Draw at item.x, item.y with item.scale
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Understanding Perspective
|
|
341
|
+
|
|
342
|
+
The `perspective` value controls distortion:
|
|
343
|
+
|
|
344
|
+
| Value | Effect |
|
|
345
|
+
|-------|--------|
|
|
346
|
+
| **Low (200-400)** | Strong perspective, dramatic depth |
|
|
347
|
+
| **Medium (600-1000)** | Natural looking, balanced |
|
|
348
|
+
| **High (1500+)** | Flat, orthographic-like |
|
|
349
|
+
|
|
350
|
+
```js
|
|
351
|
+
// Dramatic perspective
|
|
352
|
+
new Camera3D({ perspective: 300 });
|
|
353
|
+
|
|
354
|
+
// Subtle perspective
|
|
355
|
+
new Camera3D({ perspective: 1200 });
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Understanding Rotation
|
|
361
|
+
|
|
362
|
+
| Axis | Effect | Positive Direction |
|
|
363
|
+
|------|--------|-------------------|
|
|
364
|
+
| **X** | Vertical tilt | Tilt forward (look down) |
|
|
365
|
+
| **Y** | Horizontal spin | Rotate right |
|
|
366
|
+
| **Z** | Roll | Clockwise roll |
|
|
367
|
+
|
|
368
|
+
```js
|
|
369
|
+
// Looking down at a table
|
|
370
|
+
new Camera3D({ rotationX: 0.8, rotationY: 0 });
|
|
371
|
+
|
|
372
|
+
// Side view
|
|
373
|
+
new Camera3D({ rotationX: 0, rotationY: 1.57 });
|
|
374
|
+
|
|
375
|
+
// Tilted view
|
|
376
|
+
new Camera3D({ rotationX: 0.3, rotationY: -0.5 });
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Coordinate System
|
|
382
|
+
|
|
383
|
+
Camera3D uses a right-handed coordinate system:
|
|
384
|
+
|
|
385
|
+
```
|
|
386
|
+
+Y (up)
|
|
387
|
+
│
|
|
388
|
+
│
|
|
389
|
+
│
|
|
390
|
+
└──────── +X (right)
|
|
391
|
+
/
|
|
392
|
+
/
|
|
393
|
+
+Z (toward viewer)
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
- **X**: Positive is right
|
|
397
|
+
- **Y**: Positive is up
|
|
398
|
+
- **Z**: Positive is toward the viewer
|
|
399
|
+
|
|
400
|
+
Points with larger Z values appear in front; smaller Z values appear behind.
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Related
|
|
405
|
+
|
|
406
|
+
- [Scene3D](./scene3d.md) - Scene with automatic camera projection
|
|
407
|
+
- [Particle Module](../particle/README.md) - 3D particle effects
|
|
408
|
+
|
|
409
|
+
## See Also
|
|
410
|
+
|
|
411
|
+
- [Game Module](../game/README.md) - Game loop integration
|
|
412
|
+
- [Painter Module](../painter/README.md) - Direct canvas drawing
|