shaku
Version:
A simple and effective JavaScript game development framework that knows its place!
207 lines (188 loc) • 4.93 kB
JavaScript
/**
* A plane in 3D space.
* Based on code from THREE.js.
*
* |-- copyright and license --|
* @module Shaku
* @file shaku\src\utils\plane.js
* @author Ronen Ness (ronenness@gmail.com | http://ronenness.com)
* @copyright (c) 2021 Ronen Ness
* @license MIT
* |-- end copyright and license --|
*
*/
'use strict';
const Line = require("./line");
const Sphere = require("./sphere");
const Vector3 = require("./vector3");
/**
* A plane in 3D space.
*/
class Plane
{
/**
* Create the plane.
* @param {Vector3} normal Plane normal vector.
* @param {Number} constant Plane constant.
*/
constructor(normal = new Vector3(1, 0, 0), constant = 0)
{
this.normal = normal;
this.constant = constant;
}
/**
* Set the plane components.
* @param {Vector3} normal Plane normal.
* @param {Number} constant Plane constant.
* @returns {Plane} Self.
*/
set( normal, constant )
{
this.normal.copy( normal );
this.constant = constant;
return this;
}
/**
* Set the plane components.
* @param {Number} x Plane normal X.
* @param {Number} y Plane normal Y.
* @param {Number} z Plane normal Z.
* @param {Number} w Plane constant.
* @returns {Plane} Self.
*/
setComponents(x, y, z, w)
{
this.normal.set( x, y, z );
this.constant = w;
return this;
}
/**
* Set plane from normal and coplanar point vectors.
* @param {Vector3} normal Plane normal.
* @param {Vector3} point Coplanar point.
* @returns {Plane} Self.
*/
setFromNormalAndCoplanarPoint(normal, point)
{
this.normal.copy(normal);
this.constant = -(point.dot( this.normal ));
return this;
}
/**
* Copy values from another plane.
* @param {Plane} plane Plane to copy.
* @returns {Plane} Self.
*/
copy(plane)
{
this.normal.copy( plane.normal );
this.constant = plane.constant;
return this;
}
/**
* Normalize the plane.
* @returns {Plane} self.
*/
normalizeSelf()
{
// Note: will lead to a divide by zero if the plane is invalid.
const inverseNormalLength = 1.0 / this.normal.length();
this.normal.mulSelf(inverseNormalLength);
this.constant *= inverseNormalLength;
return this;
}
/**
* Normalize a clone of this plane.
* @returns {Plane} Normalized clone.
*/
normalized()
{
return this.clone().normalizeSelf();
}
/**
* Negate this plane.
* @returns {Plane} Self.
*/
negateSelf()
{
this.constant *= -1;
this.normal.mulSelf(-1);
return this;
}
/**
* Calculate distance to point.
* @param {Vector3} point Point to calculate distance to.
* @returns {Number} Distance to point.
*/
distanceToPoint(point)
{
return this.normal.dot(point) + this.constant;
}
/**
* Calculate distance to sphere.
* @param {Sphere} sphere Sphere to calculate distance to.
* @returns {Number} Distance to sphere.
*/
distanceToSphere(sphere)
{
return this.distanceToPoint(sphere.center) - sphere.radius;
}
/**
* Check if this plane collide with a line.
* @param {Line} line Line to check.
* @returns {Boolean} True if collide, false otherwise.
*/
collideLine( line )
{
// Note: this tests if a line collide the plane, not whether it (or its end-points) are coplanar with it.
const startSign = this.distanceToPoint( line.start );
const endSign = this.distanceToPoint( line.end );
return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
}
/**
* Check if this plane collide with a sphere.
* @param {Sphere} sphere Sphere to check.
* @returns {Boolean} True if collide, false otherwise.
*/
collideSphere(sphere)
{
return sphere.collidePlane( this );
}
/**
* Coplanar a point.
* @returns {Vector3} Coplanar point as a new vector.
*/
coplanarPoint()
{
return this.normal.mul(-this.constant);
}
/**
* Translate this plane.
* @param {Vector3} offset Offset to translate to.
* @returns {Plane} Self.
*/
translateSelf(offset)
{
this.constant -= offset.dot( this.normal );
return this;
}
/**
* Check if this plane equals another plane.
* @param {Plane} plane Other plane to compare to.
* @returns {Boolean} True if equal, false otherwise.
*/
equals(plane)
{
return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
}
/**
* Clone this plane.
* @returns {Plane} Cloned plane.
*/
clone()
{
return new this.constructor().copy(this);
}
}
// export the plane object
module.exports = Plane;