init
This commit is contained in:
195
.opencode/skills/threejs/references/04-cameras.md
Normal file
195
.opencode/skills/threejs/references/04-cameras.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# Cameras
|
||||
|
||||
Define viewpoint and projection for rendering.
|
||||
|
||||
## Perspective Camera
|
||||
|
||||
Realistic camera with field of view (most common):
|
||||
|
||||
```javascript
|
||||
const camera = new THREE.PerspectiveCamera(
|
||||
fov, // field of view in degrees (typically 45-75)
|
||||
aspect, // width / height
|
||||
near, // near clipping plane (typically 0.1)
|
||||
far // far clipping plane (typically 1000)
|
||||
);
|
||||
|
||||
camera.position.set(0, 5, 10);
|
||||
camera.lookAt(0, 0, 0);
|
||||
|
||||
// Update after changing parameters
|
||||
camera.fov = 60;
|
||||
camera.updateProjectionMatrix();
|
||||
```
|
||||
|
||||
## Orthographic Camera
|
||||
|
||||
No perspective distortion (parallel projection):
|
||||
|
||||
```javascript
|
||||
const frustumSize = 10;
|
||||
const aspect = window.innerWidth / window.innerHeight;
|
||||
const camera = new THREE.OrthographicCamera(
|
||||
frustumSize * aspect / -2, // left
|
||||
frustumSize * aspect / 2, // right
|
||||
frustumSize / 2, // top
|
||||
frustumSize / -2, // bottom
|
||||
0.1, // near
|
||||
1000 // far
|
||||
);
|
||||
|
||||
// Useful for: 2D games, CAD, isometric views
|
||||
```
|
||||
|
||||
## Camera Controls (Addons)
|
||||
|
||||
### OrbitControls (Most Common)
|
||||
```javascript
|
||||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||||
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.target.set(0, 0, 0);
|
||||
controls.enableDamping = true; // smooth motion
|
||||
controls.dampingFactor = 0.05;
|
||||
controls.minDistance = 5;
|
||||
controls.maxDistance = 50;
|
||||
controls.maxPolarAngle = Math.PI / 2; // prevent going below ground
|
||||
|
||||
// In animation loop
|
||||
function animate() {
|
||||
controls.update(); // required if enableDamping = true
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
```
|
||||
|
||||
### FirstPersonControls
|
||||
```javascript
|
||||
import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js';
|
||||
|
||||
const controls = new FirstPersonControls(camera, renderer.domElement);
|
||||
controls.movementSpeed = 10;
|
||||
controls.lookSpeed = 0.1;
|
||||
|
||||
const clock = new THREE.Clock();
|
||||
function animate() {
|
||||
const delta = clock.getDelta();
|
||||
controls.update(delta);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
```
|
||||
|
||||
### FlyControls
|
||||
```javascript
|
||||
import { FlyControls } from 'three/addons/controls/FlyControls.js';
|
||||
|
||||
const controls = new FlyControls(camera, renderer.domElement);
|
||||
controls.movementSpeed = 10;
|
||||
controls.rollSpeed = Math.PI / 24;
|
||||
controls.dragToLook = true;
|
||||
```
|
||||
|
||||
### TransformControls
|
||||
```javascript
|
||||
import { TransformControls } from 'three/addons/controls/TransformControls.js';
|
||||
|
||||
const controls = new TransformControls(camera, renderer.domElement);
|
||||
controls.attach(mesh);
|
||||
scene.add(controls);
|
||||
|
||||
// Switch modes
|
||||
controls.setMode('translate'); // or 'rotate', 'scale'
|
||||
|
||||
// Events
|
||||
controls.addEventListener('change', () => renderer.render(scene, camera));
|
||||
controls.addEventListener('dragging-changed', (event) => {
|
||||
orbitControls.enabled = !event.value;
|
||||
});
|
||||
```
|
||||
|
||||
## Camera Methods
|
||||
|
||||
```javascript
|
||||
// Position and orientation
|
||||
camera.position.set(x, y, z);
|
||||
camera.lookAt(x, y, z); // or lookAt(vector3) or lookAt(object.position)
|
||||
camera.up.set(0, 1, 0); // define "up" direction
|
||||
|
||||
// Get world direction
|
||||
const direction = new THREE.Vector3();
|
||||
camera.getWorldDirection(direction);
|
||||
|
||||
// Screen to world conversion
|
||||
const mouse = new THREE.Vector2(x, y); // normalized device coords (-1 to 1)
|
||||
const raycaster = new THREE.Raycaster();
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
|
||||
// World to screen
|
||||
const vector = new THREE.Vector3(x, y, z);
|
||||
vector.project(camera); // now in normalized device coords
|
||||
```
|
||||
|
||||
## Layers
|
||||
|
||||
Selective rendering with layers:
|
||||
|
||||
```javascript
|
||||
// Set object layers
|
||||
mesh.layers.set(1);
|
||||
|
||||
// Set camera layers
|
||||
camera.layers.enable(0); // render layer 0
|
||||
camera.layers.enable(1); // render layer 1
|
||||
camera.layers.disable(2); // don't render layer 2
|
||||
|
||||
// Objects on disabled layers won't be rendered
|
||||
```
|
||||
|
||||
## Frustum Culling
|
||||
|
||||
Automatic optimization (objects outside view are not rendered):
|
||||
|
||||
```javascript
|
||||
// Manually check if object is in view
|
||||
const frustum = new THREE.Frustum();
|
||||
const matrix = new THREE.Matrix4().multiplyMatrices(
|
||||
camera.projectionMatrix,
|
||||
camera.matrixWorldInverse
|
||||
);
|
||||
frustum.setFromProjectionMatrix(matrix);
|
||||
|
||||
if (frustum.containsPoint(object.position)) {
|
||||
// Object is visible
|
||||
}
|
||||
```
|
||||
|
||||
## Multiple Cameras
|
||||
|
||||
```javascript
|
||||
const mainCamera = new THREE.PerspectiveCamera(...);
|
||||
const minimapCamera = new THREE.OrthographicCamera(...);
|
||||
|
||||
// Render with different viewports
|
||||
renderer.setViewport(0, 0, width, height);
|
||||
renderer.render(scene, mainCamera);
|
||||
|
||||
renderer.setViewport(width - 200, height - 200, 200, 200);
|
||||
renderer.render(scene, minimapCamera);
|
||||
```
|
||||
|
||||
## Resize Handling
|
||||
|
||||
```javascript
|
||||
window.addEventListener('resize', () => {
|
||||
// Perspective camera
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
// Orthographic camera
|
||||
const aspect = window.innerWidth / window.innerHeight;
|
||||
camera.left = -frustumSize * aspect / 2;
|
||||
camera.right = frustumSize * aspect / 2;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user