engine

ver.2

by Rebecca Chen

HTML

<div id="info">Physics Engine<br>version 2
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>

CSS

#info {
  position: absolute;
  top: 0px;
  width: 100%;
  padding: 10px;
  text-align: center;
  color: #ffff00
}

body {
  overflow: hidden;
}

JavaScript

class Ball {
	constructor (mass = 1, radius=2, friction = 0) {
  	this.type = 'ball';
    this.mass = mass;  // may need to differentiate basketball & bowling ball
  	this.radius = radius;
    this.friction = friction;  // for contact
    
    // for dynamics calculation
    this.pos = new THREE.Vector3();
    this.vel = new THREE.Vector3();
    this.force = new THREE.Vector3();

		this.obj = new THREE.Object3D();
    let mesh = new THREE.Mesh (new THREE.CircleGeometry(radius), new THREE.MeshBasicMaterial({wireframe:true}))
    this.obj.add (mesh)
    scene.add (this.obj)
  }
  
  update(dt) {

		// after GLOBAL collision & contact
    
  	this.vel.add (this.force.clone().multiplyScalar(dt))
    this.pos.add (this.vel.clone().multiplyScalar(dt))

 		this.obj.position.copy (this.pos);
  }

	// useless API
  moveTo(x,y) {
  	this.pos.set (x,y,0)
  }
}

class Plane {
	constructor (width=150) {
  	this.type = 'plane'
  	this.normal = new THREE.Vector3(0,1,0)
    this.pc = new THREE.Vector3()
    this.obj = new THREE.Object3D();
		this.width = width;  // for display purpose, should be infinite
    
		let mesh = new THREE.Mesh (new THREE.PlaneGeometry(width,2), new THREE.MeshBasicMaterial({color:0xff00ff, wireframe:true}))
    mesh.position.y = -1
    let tip = new THREE.Mesh (new THREE.CylinderGeometry (0,2,4), new THREE.MeshBasicMaterial({color:0xffff00}))
    tip.position.y = 2
    this.obj.add (tip)
    this.obj.add (mesh);
		scene.add (this.obj);
  }
  
  moveTo (x,y) {
  	this.pc.set (x, y, 0)
    this.obj.position.copy (this.pc);
  }
  
  rotateTo (theta) {  // abs CCW angle
  	this.obj.rotation.z = theta;
    this.normal.applyEuler (new THREE.Euler (0,0,theta))
  }
}

/*
function contact () {

	// check all existing contacts ...
  // (or remove them all)
  // (and reestablish them anew every time)
	for (let i = 0; i < balls.length; i++) {
  	for (let j = 0; j < planes.length; j++) {
			// if bi is close to pj
      let bi = balls[i]
      let pj = planes[j]
   ...