Skip to content


 Zabbix
 Grafana
 Prometheus
 Threejs and TypeScript
 SocketIO and TypeScript
 Blender Topological Earth
 Sweet Home 3D
 Design Patterns Python
 Design Patterns TypeScript
   
 Course Coupon Codes
Three.js and TypeScript
Kindle Edition
$9.99 $14.99 Paperback 
$29.99 $34.99




Design Patterns in TypeScript
Kindle Edition
$9.99 $14.99 Paperback
$19.99 $24.99




Design Patterns in Python
Kindle Edition
$9.99 $14.99 Paperback
$19.99 $24.99




Vector3 Lerp

Video Lecture

Vector3 Lerp Vector3 Lerp Vector3 Lerp

Description

Sometimes you only need a simple positional transform to occur over time. The tween library works very well, but it could be over engineering if you don't actually need all the features that it offers.

If you only want to move an object from A to B and, and nothing else then you can use the Vector3 .lerp and .lerpVectors methods.

(method) Vector3.lerp(v1: THREE.Vector3, alpha: number): THREE.Vector3

(method) Vector3.lerpVectors(v1: THREE.Vector3, v2: THREE.Vector3, alpha: number): THREE.Vector3

eg,

cube.position.lerp(new THREE.Vector3(1, 2, 3), 0.05)

v1 : Is the vector to lerp towards.

alpha : Is the percent distance along the line from the current vector to the v1.

v2 : If using .lerpVectors, then you can set an alternate start vector3 to lerp from rather that the current vector3.

Calling .lerp during an animation loop will appear to mimic a Tween using a TWEEN.Easing.Cubic.Out

Calling .lerpVectors is useful if you want to slide an object along an arbitrary line depending on the alpha value. Amongst other things.

Set alpha to low number such as 0.1, and the vector will appear to lerp more slowly, slowing down as it get closer to the target vector.

Set alpha to 1.0, and the tween will happen instantly in one render cycle.

Double click on the floor in the example to see a slower lerp. Then experiment with the alphas to see a faster lerp and slide a second cube along a line between the first cube and the starting position.

Lesson Script

./src/client/client.ts

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module'
import { GUI } from 'three/examples/jsm/libs/dat.gui.module'

const scene = new THREE.Scene()
scene.add(new THREE.AxesHelper(5))

const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
)
camera.position.set(0.8, 1.4, 1.0)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

const floor = new THREE.Mesh(
    new THREE.PlaneBufferGeometry(20, 20, 10, 10),
    new THREE.MeshBasicMaterial({ color: 0xaec6cf, wireframe: true })
)
floor.rotateX(-Math.PI / 2)
scene.add(floor)

const geometry: THREE.BoxGeometry = new THREE.BoxGeometry()

//the cube used for .lerp
const cube1: THREE.Mesh = new THREE.Mesh(
    geometry,
    new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true })
)
cube1.position.y = 0.5
scene.add(cube1)

//the cube used for .lerpVectors
const cube2: THREE.Mesh = new THREE.Mesh(
    geometry,
    new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true })
)
cube2.position.y = 0.5
scene.add(cube2)

window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    render()
}

const raycaster = new THREE.Raycaster()

const v1 = new THREE.Vector3(0, 0.5, 0)
const v2 = new THREE.Vector3(0, 0.5, 0)

renderer.domElement.addEventListener('dblclick', onDoubleClick, false)
function onDoubleClick(event: MouseEvent) {
    const mouse = {
        x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,
        y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1,
    }
    raycaster.setFromCamera(mouse, camera)

    const intersects = raycaster.intersectObject(floor, false)

    if (intersects.length > 0) {
        v1.copy(intersects[0].point)
        v1.y += 0.5 //raise it so it appears to sit on grid
        //console.log(v1)
    }
}

const stats = Stats()
document.body.appendChild(stats.dom)

const data = {
    lerpAlpha: 0.1,
    lerpVectorsAlpha: 1.0,
}

const gui = new GUI()
const lerpFolder = gui.addFolder('.lerp')
lerpFolder.add(data, 'lerpAlpha', 0.01, 1.0, 0.01)
lerpFolder.open()
const lerpVectorsFolder = gui.addFolder('.lerpVectors')
lerpVectorsFolder.add(data, 'lerpVectorsAlpha', 0, 1.0, 0.01)
lerpVectorsFolder.open()

function animate() {
    requestAnimationFrame(animate)

    controls.update()

    cube1.position.lerp(v1, data.lerpAlpha)

    cube2.position.lerpVectors(v1, v2, data.lerpVectorsAlpha)

    controls.target.copy(cube1.position)

    render()

    stats.update()
}

function render() {
    renderer.render(scene, camera)
}

animate()

Vector3.lerp (Official)