Ball on swing simulation
by PhilQ
HTML
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"OrbitControls": "https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js"
}
}
</script>
<canvas id="canvas1"></canvas>
CSS
*, ::before, ::after { margin:0; padding:0; box-sizing:border-box; }
body {
background: #1f2227;
}
canvas {
display: block;
margin: 150px auto 0;
background: #1a1d21;
}
JavaScript
import * as THREE from 'three';
var upload,
canvas,
context,
width = 600,
height = 500,
this_time,
last_time,
frame_time,
duration = 0,
is_running = true
;
var PI = Math.PI;
var TWO_PI = 2*Math.PI;
var gravity = new THREE.Vector3(0, 9.807/0.1, 0);
var orb;
class ball {
constructor(params) {
this.r = params.r;
this.position = params.position;
this.velocity = params.velocity;
this.acceleration = params.acceleration;
this.anchor = params.anchor;
this.anchorDistanceMax = params.anchorDistanceMax;
this.anchorDistanceMaxSq = Math.pow(this.anchorDistanceMax, 2);
this.anchorSphere = new THREE.Sphere( this.anchor, this.anchorDistanceMax );
this.mass = params.mass ? params.mass : 1;
this.invMass = 1 / this.mass;
this.new_position = this.position.clone();
this._intersection = new THREE.Vector3();
this._v1 = new THREE.Vector3();
this._v2 = new THREE.Vector3();
this._dp = new THREE.Vector3();
this._ray = new THREE.Ray();
}
applyForce(force) {
this.acceleration.addScaledVector(force, this.invMass);
}
update(dt) {
// Accelerate
this.velocity.addScaledVector( this.acceleration, dt );
// Move
this._dp.copy( this.velocity ).multiplyScalar( dt );
// New position starting point
this.new_position.copy( this.position );
// Move until anchor line is at maximum (if needed)
if (
this._ray
.set( this.position, this.velocity.clone().normalize() )
.intersectSphere( this.anchorSphere, this._intersection )
) {
this._v1.copy( this._intersection ).sub( this.position );
if ( this._v1.lengthSq() >= this._dp.lengthSq() ) {
// Within or at max
this.new_position.add( this._dp );
this._dp.set(0, 0, 0);
} else {
//TODO? Bounce when reaching max: reflect velocity on anchor line normal?
// Surpassing max
this.new_position.copy( this._intersection );
this._dp.sub( this._v1 );
}
}
if ( this._dp.lengthSq() > 0 ) {
// Convert velocity to angular velocity
// See:...