-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: add box3, plane3, planes3, sphere3
- Loading branch information
Showing
31 changed files
with
669 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { Vector3 } from '../vec3/Vector3'; | ||
import { box3ContainsPoint } from './box3ContainsPoint'; | ||
import type { RawBox3 } from './RawBox3'; | ||
|
||
/** | ||
* A 3D box. | ||
*/ | ||
export class Box3 { | ||
public min: Vector3; | ||
public max: Vector3; | ||
|
||
public constructor( min: Vector3 = Vector3.zero, max: Vector3 = Vector3.zero ) { | ||
this.min = min; | ||
this.max = max; | ||
} | ||
|
||
/** | ||
* Itself but {@link RawBox3} form. | ||
*/ | ||
public get raw(): RawBox3 { | ||
return [ this.min.elements, this.max.elements ]; | ||
} | ||
|
||
/** | ||
* Test if given point is contained in the box or not. | ||
* | ||
* @param point A point | ||
*/ | ||
public containsPoint( point: Vector3 ): boolean { | ||
return box3ContainsPoint( this.raw, point.elements ); | ||
} | ||
|
||
/** | ||
* Convert {@link RawBox3} to class form. | ||
* @param box A {@link RawBox3} | ||
*/ | ||
public static fromRaw( box: RawBox3 ): Box3 { | ||
return new Box3( new Vector3( box[ 0 ] ), new Vector3( box[ 1 ] ) ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import type { RawVector3 } from '../vec3/RawVector3'; | ||
|
||
export type RawBox3 = [ min: RawVector3, max: RawVector3 ]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { RawBox3 } from './RawBox3'; | ||
import type { RawVector3 } from '../vec3/RawVector3'; | ||
|
||
/** | ||
* Test if given point is contained in given box or not. | ||
* @param box A box | ||
* @param point A point | ||
*/ | ||
export function box3ContainsPoint( box: RawBox3, point: RawVector3 ): boolean { | ||
return ( | ||
box[ 0 ][ 0 ] <= point[ 0 ] && | ||
box[ 1 ][ 0 ] >= point[ 0 ] && | ||
box[ 0 ][ 1 ] <= point[ 1 ] && | ||
box[ 1 ][ 1 ] >= point[ 1 ] && | ||
box[ 0 ][ 2 ] <= point[ 2 ] && | ||
box[ 1 ][ 2 ] >= point[ 2 ] | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './Box3'; | ||
export * from './box3ContainsPoint'; | ||
export * from './RawBox3'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { box3ContainsPoint } from '../box3ContainsPoint'; | ||
import type { RawBox3 } from '../RawBox3'; | ||
|
||
const box222: RawBox3 = [ [ -1.0, -1.0, -1.0 ], [ 1.0, 1.0, 1.0 ] ]; | ||
|
||
describe( 'planesContainPoint', () => { | ||
it( 'returns true if point is inside of the box', () => { | ||
const subject = box3ContainsPoint( box222, [ 0.0, 0.5, 0.5 ] ); | ||
expect( subject ).toBe( true ); | ||
} ); | ||
|
||
it( 'returns false if point is outside of the box', () => { | ||
const subject = box3ContainsPoint( box222, [ -2.0, 0.0, 0.0 ] ); | ||
expect( subject ).toBe( false ); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { Matrix3 } from '../mat3/Matrix3'; | ||
import { Matrix4 } from '../mat4/Matrix4'; | ||
import { Vector3 } from '../vec3/Vector3'; | ||
import { plane3ApplyMatrix4 } from './plane3ApplyMatrix4'; | ||
import { plane3DistanceToPoint } from './plane3DistanceToPoint'; | ||
import { plane3Normalize } from './plane3Normalize'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
|
||
/** | ||
* A 3D plane. | ||
*/ | ||
export class Plane3 { | ||
public normal: Vector3; | ||
public distance: number; | ||
|
||
/** | ||
* Itself but {@link RawPlane3} form. | ||
*/ | ||
public get raw(): RawPlane3 { | ||
return [ this.normal.elements, this.distance ]; | ||
} | ||
|
||
/** | ||
* Normalized plane? | ||
* This normalizes the normal and also divide distance by its original normal length. | ||
*/ | ||
public get normalized(): Plane3 { | ||
return Plane3.fromRaw( plane3Normalize( this.raw ) ); | ||
} | ||
|
||
public constructor( normal: Vector3 = Vector3.pz, distance = 0.0 ) { | ||
this.normal = normal; | ||
this.distance = distance; | ||
} | ||
|
||
/** | ||
* Apply given matrix4 to given plane. | ||
* | ||
* @param matrix A matrix4 which will be applied to the plane | ||
* @param normalMatrix A normalMatrix made out of {@link matrix}. Optional | ||
*/ | ||
public applyMatrix4( matrix: Matrix4, normalMatrix?: Matrix3 ): Plane3 { | ||
return Plane3.fromRaw( | ||
plane3ApplyMatrix4( | ||
this.raw, | ||
matrix.elements, | ||
normalMatrix?.elements ?? matrix.normalMatrix.elements, | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Return a signed distance from given plane to the given point. | ||
* | ||
* @param point A point | ||
*/ | ||
public distanceToPoint( point: Vector3 ): number { | ||
return plane3DistanceToPoint( this.raw, point.elements ); | ||
} | ||
|
||
/** | ||
* Convert {@link RawPlane3} to class form. | ||
* @param plane A {@link RawPlane3} | ||
*/ | ||
public static fromRaw( plane: RawPlane3 ): Plane3 { | ||
return new Plane3( new Vector3( plane[ 0 ] ), plane[ 1 ] ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { Box3 } from '../box3/Box3'; | ||
import { Matrix4 } from '../mat4/Matrix4'; | ||
import { Plane3 } from './Plane3'; | ||
import { Sphere3 } from '../sphere3/Sphere3'; | ||
import { Vector3 } from '../vec3/Vector3'; | ||
import { planes3ContainPoint } from './planes3ContainPoint'; | ||
import { planes3FromBox3 } from './planes3FromBox3'; | ||
import { planes3FromProjectionMatrix } from './planes3FromProjectionMatrix'; | ||
import { planes3IntersectBox3 } from './planes3IntersectBox3'; | ||
import { planes3IntersectSphere3 } from './planes3IntersectSphere3'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
|
||
/** | ||
* A set of {@link Plane3}. | ||
*/ | ||
export class Planes3 { | ||
public planes: Plane3[]; | ||
|
||
/** | ||
* Itself but {@link RawPlane3}[] form. | ||
*/ | ||
public get raw(): RawPlane3[] { | ||
return this.planes.map( ( plane ) => plane.raw ); | ||
} | ||
|
||
public constructor( planes: Plane3[] ) { | ||
this.planes = planes; | ||
} | ||
|
||
/** | ||
* Test if given point is contained in the planes or not. | ||
* | ||
* @param point A point | ||
*/ | ||
public containPoint( point: Vector3 ): boolean { | ||
return planes3ContainPoint( this.raw, point.elements ); | ||
} | ||
|
||
/** | ||
* Test if given box intersects with the planes or not. | ||
* | ||
* @param box A box3 | ||
*/ | ||
public intersectBox3( box: Box3 ): boolean { | ||
return planes3IntersectBox3( this.raw, box.raw ); | ||
} | ||
|
||
/** | ||
* Test if given sphere intersects with the planes or not. | ||
* | ||
* It does not do strict intersection test but still should work well with frustum cull use cases. | ||
* See the test case for more details. | ||
* | ||
* @param sphere A sphere3 | ||
*/ | ||
public intersectSphere3( sphere: Sphere3 ): boolean { | ||
return planes3IntersectSphere3( this.raw, sphere.raw ); | ||
} | ||
|
||
/** | ||
* Convert {@link RawPlane3}[] to class form. | ||
* | ||
* @param planes A {@link RawPlane3}[] | ||
*/ | ||
public static fromRaw( planes: RawPlane3[] ): Planes3 { | ||
return new Planes3( planes.map( ( plane ) => Plane3.fromRaw( plane ) ) ); | ||
} | ||
|
||
/** | ||
* Generate a set of plane3 out of a {@link RawBox3}. | ||
* | ||
* @param box A box | ||
*/ | ||
public static fromBox3( box: Box3 ): Planes3 { | ||
return Planes3.fromRaw( planes3FromBox3( box.raw ) ); | ||
} | ||
|
||
/** | ||
* Create frustum planes out of given projection matrix. | ||
* | ||
* @param matrix A projection matrix | ||
*/ | ||
public static fromProjectionMatrix( matrix: Matrix4 ): Planes3 { | ||
return Planes3.fromRaw( planes3FromProjectionMatrix( matrix.elements ) ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import type { RawVector3 } from '../vec3/RawVector3'; | ||
|
||
export type RawPlane3 = [ normal: RawVector3, distance: number ]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export * from './Plane3'; | ||
export * from './plane3ApplyMatrix4'; | ||
export * from './plane3DistanceToPoint'; | ||
export * from './plane3Normalize'; | ||
export * from './Planes3'; | ||
export * from './planes3ContainPoint'; | ||
export * from './planes3FromBox3'; | ||
export * from './planes3FromProjectionMatrix'; | ||
export * from './planes3IntersectBox3'; | ||
export * from './planes3IntersectSphere3'; | ||
export * from './RawPlane3'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { vec3ApplyMatrix3 } from '../vec3/vec3ApplyMatrix3'; | ||
import { vec3ApplyMatrix4 } from '../vec3/vec3ApplyMatrix4'; | ||
import { vecDot } from '../vec/vecDot'; | ||
import { vecNormalize } from '../vec/vecNormalize'; | ||
import { vecScale } from '../vec/vecScale'; | ||
import type { RawMatrix3 } from '../mat3/RawMatrix3'; | ||
import type { RawMatrix4 } from '../mat4/RawMatrix4'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
|
||
/** | ||
* Apply given matrix4 to given plane. | ||
* | ||
* @param plane A plane | ||
* @param matrix A matrix4 which will be applied to the plane | ||
* @param normalMatrix A normalMatrix made out of {@link matrix} | ||
*/ | ||
export function plane3ApplyMatrix4( | ||
[ normal, distance ]: RawPlane3, | ||
matrix: RawMatrix4, | ||
normalMatrix: RawMatrix3, | ||
): RawPlane3 { | ||
// normalなんだからnormalMatrix当てればヨシ! | ||
const newNormal = vecNormalize( vec3ApplyMatrix3( normal, normalMatrix ) ); | ||
|
||
// とりあえず一点観測してあとでdot取り直しちゃおうぜ! | ||
const coplanar = vecScale( normal, -distance ); | ||
const refPoint = vec3ApplyMatrix4( coplanar, matrix ); | ||
const newDistance = -vecDot( refPoint, normal ); | ||
|
||
return [ newNormal, newDistance ]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { vecDot } from '../vec/vecDot'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
import type { RawVector3 } from '../vec3/RawVector3'; | ||
|
||
/** | ||
* Return a signed distance from given plane to the given point. | ||
* Make sure the `normal` is normalized. | ||
*/ | ||
export function plane3DistanceToPoint( | ||
[ normal, distance ]: RawPlane3, | ||
point: RawVector3, | ||
): number { | ||
return vecDot( normal, point ) + distance; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { vecLength } from '../vec/vecLength'; | ||
import { vecScale } from '../vec/vecScale'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
|
||
/** | ||
* Normalize a given plane? | ||
* This normalizes the normal and also divide distance by its original normal length. | ||
* | ||
* I don't come up with any use cases other than {@link planesFromProjectionMatrix}. | ||
* | ||
* @param plane The plane you want to normalize | ||
*/ | ||
export function plane3Normalize( [ normal, distance ]: RawPlane3 ): RawPlane3 { | ||
const invL = 1.0 / vecLength( normal ); | ||
return [ vecScale( normal, invL ), distance * invL ]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { plane3DistanceToPoint } from './plane3DistanceToPoint'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
import type { RawVector3 } from '../vec3/RawVector3'; | ||
|
||
/** | ||
* Test if given point is contained in given planes or not. | ||
* | ||
* @param planes A list of planes | ||
* @param point A point | ||
*/ | ||
export function planes3ContainPoint( planes: RawPlane3[], point: RawVector3 ): boolean { | ||
return planes.every( ( plane ) => plane3DistanceToPoint( plane, point ) >= 0.0 ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { RawBox3 } from '../box3/RawBox3'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
|
||
/** | ||
* Generate a set of plane3 out of a {@link RawBox3}. | ||
* | ||
* @param box A box | ||
*/ | ||
export function planes3FromBox3( box: RawBox3 ): RawPlane3[] { | ||
return [ | ||
[ [ 1.0, 0.0, 0.0 ], -box[ 0 ][ 0 ] ], // xn | ||
[ [ -1.0, 0.0, 0.0 ], box[ 1 ][ 0 ] ], // xp | ||
[ [ 0.0, 1.0, 0.0 ], -box[ 0 ][ 1 ] ], // yn | ||
[ [ 0.0, -1.0, 0.0 ], box[ 1 ][ 1 ] ], // yp | ||
[ [ 0.0, 0.0, 1.0 ], -box[ 0 ][ 2 ] ], // yn | ||
[ [ 0.0, 0.0, -1.0 ], box[ 1 ][ 2 ] ], // yp | ||
]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { plane3Normalize } from './plane3Normalize'; | ||
import type { RawMatrix4 } from '../mat4/RawMatrix4'; | ||
import type { RawPlane3 } from './RawPlane3'; | ||
|
||
/** | ||
* Create frustum planes out of given projection matrix. | ||
* | ||
* @param m A projection matrix | ||
*/ | ||
export function planes3FromProjectionMatrix( m: RawMatrix4 ): RawPlane3[] { | ||
const | ||
m11 = m[ 0 ], m12 = m[ 4 ], m13 = m[ 8 ], m14 = m[ 12 ], | ||
m21 = m[ 1 ], m22 = m[ 5 ], m23 = m[ 9 ], m24 = m[ 13 ], | ||
m31 = m[ 2 ], m32 = m[ 6 ], m33 = m[ 10 ], m34 = m[ 14 ], | ||
m41 = m[ 3 ], m42 = m[ 7 ], m43 = m[ 11 ], m44 = m[ 15 ]; | ||
|
||
return [ | ||
plane3Normalize( [ [ m41 - m11, m42 - m12, m43 - m13 ], m44 - m14 ] ), // xp | ||
plane3Normalize( [ [ m41 + m11, m42 + m12, m43 + m13 ], m44 + m14 ] ), // xn | ||
plane3Normalize( [ [ m41 - m21, m42 - m22, m43 - m23 ], m44 - m24 ] ), // yp | ||
plane3Normalize( [ [ m41 + m21, m42 + m22, m43 + m23 ], m44 + m24 ] ), // yn | ||
plane3Normalize( [ [ m41 - m31, m42 - m32, m43 - m33 ], m44 - m34 ] ), // zn | ||
plane3Normalize( [ [ m41 + m31, m42 + m32, m43 + m33 ], m44 + m34 ] ), // zp | ||
]; | ||
} |
Oops, something went wrong.