tsmathlib
Version:
Typescript Version Math/Physics/CG Library
144 lines (118 loc) • 4.11 kB
text/typescript
/*
* @Author: Xu.Wang
* @Date: 2020-04-07 01:29:25
* @Last Modified by: Xu.Wang
* @Last Modified time: 2020-04-15 23:43:07
*/
import { Transform } from './transform'
import { Vector3, TS_MAX_NUM } from '../math'
import { BoundingBox } from './bounding_box'
import { Ray } from './ray'
export class SurfaceRayIntersection3 {
isIntersecting: boolean = false
distance: number = TS_MAX_NUM
point: Vector3
normal: Vector3
constructor(
_point: Vector3 = new Vector3(),
_normal: Vector3 = new Vector3()
) {
this.point = _point
this.normal = _normal
}
}
export abstract class Surface {
private _transform: Transform
private _isNormalFlipped: boolean
constructor(transform: Transform, isNormalFlipped: boolean) {
this._transform = transform
this._isNormalFlipped = isNormalFlipped
}
transform(): Transform {
return this._transform
}
setTransform(t: Transform) {
this._transform = t
}
setIsNormalFlipped(i: boolean) {
this._isNormalFlipped = i
}
isNormalFlipped(): boolean {
return this._isNormalFlipped
}
// ! Returns the closest point from the given point \p otherPoint to the
// ! surface in local frame.
abstract closestPointLocal(otherPoint: Vector3): Vector3
// ! Returns the bounding box of this surface object in local frame.
abstract boundingBoxLocal(): BoundingBox
// ! Returns the closest intersection point for given \p ray in local frame.
abstract closestIntersectionLocal(ray: Ray): SurfaceRayIntersection3
// ! Returns the normal to the closest point on the surface from the given
// ! point \p otherPoint in local frame.
abstract closestNormalLocal(otherPoint: Vector3): Vector3
closestPoint(otherPoint: Vector3): Vector3 {
return this._transform.toWorldByPoint(
this.closestPointLocal(this._transform.toLocalByPoint(otherPoint))
)
}
boundingBox(): BoundingBox {
return this._transform.toWorldByBbox(this.boundingBoxLocal())
}
intersects(ray: Ray): boolean {
return this.intersectsLocal(this._transform.toLocalByRay(ray))
}
closestDistance(otherPoint: Vector3): number {
return this.closestDistanceLocal(this._transform.toLocalByPoint(otherPoint))
}
closestIntersection(ray: Ray): SurfaceRayIntersection3 {
let result = this.closestIntersectionLocal(
this._transform.toLocalByRay(ray)
)
result.point = this._transform.toWorldByPoint(result.point)
result.normal = this._transform.toWorldDirection(result.normal)
let sign = this._isNormalFlipped ? -1.0 : 1.0
result.normal = result.normal.mul(sign)
return result
}
closestNormal(otherPoint: Vector3): Vector3 {
let result = this._transform.toWorldDirection(
this.closestNormalLocal(this._transform.toLocalByPoint(otherPoint))
)
let sign = this._isNormalFlipped ? -1.0 : 1.0
result = result.mul(sign)
return result
}
// ! Returns true if the given \p ray intersects with this surface object
// ! in local frame.
intersectsLocal(rayLocal: Ray): boolean {
let result = this.closestIntersectionLocal(rayLocal)
return result.isIntersecting
}
updateQueryEngine() {
console.log('Update Query Engine')
}
isBounded(): boolean {
return true
}
isValidGeometry(): boolean {
return true
}
// ! Returns true if \p otherPoint is inside by given \p depth the volume
// ! defined by the surface in local frame.
isInside(otherPoint: Vector3): boolean {
return (
this._isNormalFlipped ===
!this.isInsideLocal(this._transform.toLocalByPoint(otherPoint))
)
}
// ! Returns the closest distance from the given point \p otherPoint to the
// ! point on the surface in local frame.
closestDistanceLocal(otherPointLocal: Vector3): number {
return otherPointLocal.distanceTo(this.closestPointLocal(otherPointLocal))
}
isInsideLocal(otherPointLocal: Vector3): boolean {
let cpLocal = this.closestPointLocal(otherPointLocal)
let normalLocal = this.closestNormalLocal(otherPointLocal)
return otherPointLocal.sub(cpLocal).dot(normalLocal) < 0.0
}
}