Skip to content

Latest commit

 

History

History
192 lines (133 loc) · 4.97 KB

snippets.md

File metadata and controls

192 lines (133 loc) · 4.97 KB

📕 draw_code.001 → Snippets


Snippets

Here you will find some 'recipes' and patterns that we'll be using during the workshop.

Isometric ThreeJS Camera

In your setup, replace the perspective camera with:

const camera = new THREE.OrthographicCamera();

In the resize function, replace the perspective camera configuration with:

const aspect = viewportWidth / viewportHeight;

// Ortho zoom
const zoom = 1.0;

// Bounds
camera.left = -zoom * aspect;
camera.right = zoom * aspect;
camera.top = zoom;
camera.bottom = -zoom;

// Near/Far
camera.near = -100;
camera.far = 100;

// Set position & look at world center
camera.position.set(zoom, zoom, zoom);
camera.lookAt(new THREE.Vector3());

// Update the camera
camera.updateProjectionMatrix();

3D Coordinate System

Here's a small reference you can use to remember XYZ axes in ThreeJS.

Raycast Mouse With Infinite Ground

You can use the following to find the 3D position under the mouse by raycasting to a virtual 'ground plane' along the XZ plane.

const raycaster = new THREE.Raycaster();
const ground = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);

// Disbale 'touch-action' for better mobile support
document.body.style.touchAction = 'none';

// Listen for pointer events on the body
document.body.addEventListener('pointermove', ev => {
  const mouse = new THREE.Vector2(
    ev.clientX / window.innerWidth * 2 - 1,
    -ev.clientY / window.innerHeight * 2 + 1
  );
  raycaster.setFromCamera(mouse, camera);
  const target = new THREE.Vector3();
  const hit = raycaster.ray.intersectPlane(ground, target);
  if (hit) {
    console.log('Hit ground at', target);
  }
});

simple-input-events for unified mouse / touch

If you want, you can use the simple-input-events utility to receive mouse and touch input like so:

const createInputEvents = require('simple-input-events');

const sketch = (props) => {
  const input = createInputEvents({
    // input events happen on canvas
    target: props.canvas,
    // block page swipe events on mobile
    preventDefault: true
  }).on('move', ({ position }) => {
    // get a uv from 0..1
    const u = position[0] / props.styleWidth;
    const v = position[1] / props.styleHeight;

    // get the X and Y in working units
    // e.g. works in 'cm' or 'in' as well
    const x = props.width * u;
    const y = props.height * v;

    // ... do something with position ...
  });

  return {
    render () {
      // ... draw your scene
    },
    unload () {
      // disable mouse events
      input.disable();
    }
  }
};

Noise from 2D Coordinates

If you have 2D coordinates between N0..N1, you can get back a simplex noise signal from those coordinates that smoothly varies between -1...1.

const Random = require('canvas-sketch-util/random');

const frequency = 1;
const amplitude = 1;

const n = amplitude * Random.noise2D(x * frequency, y * frequency);

The frequency changes how chaotic the noise signal will be, and the amplitude can be used to scale the value to something smaller or larger than -1..1 range.

Tip: It's a good idea to pass normalized values in the range -1..1 into your noise functions.

0..1 to -1...1

If t is between 0 and 1 (inclusive) and you want to map it to -1 to 1 (inclusive), you can use this:

const n = t * 2 - 1;

-1..1 to 0...1

If t is between -1 and 1 (inclusive) and you want to map it to 0 to 1 (inclusive), you can use this:

const n = t * 0.5 + 0.5;

Looping Motion in -1..1 Range

To create a looping motion from -1..1 you can use Math.sin(), like so:

const motionSpeed = 0.5;
const v = Math.sin(time * motionSpeed);

You can map this value into 0..1 space and/or interpolate it to another range.

Ping-Pong Motion in 0..1 Range

When you have a defined sketch { duration } and you are using the { playhead } prop, you can use Math.sin() to get a ping-pong motion from 0..1 which slowly varies from 0, to 1, and then back to zero.

const v = Math.sin(playhead * Math.PI);

You can invert this with 1.0 - v if you need it to vary from 1, to 0, and then back to 1.

Orient Mesh from Point A to B

Let's say you have a mesh that you'd like to orient so that it faces the same direction as a unit vector, AKA a normal. You can do the following:

const quaternionFromNormal = require('three-quaternion-from-normal');

// Say we want mesh to point from A to B point
const A = new THREE.Vector3(1, 0, 0);
const B = new THREE.Vector3(2, 5, -1);

// Get normal A->B
const normal = B.clone().sub(A).normalize();

// Get orientation
const quaternion = quaternionFromNormal(normal);

// Apply orientation to mesh
mesh.quaternion.copy(quaternion);

This uses the three-quaternion-from-normal module.