import * as THREE from "three" ; import { DisplacedBufferAttribute } from "./DisplacedBufferAttribute" ; const tmpV1 = new THREE . Vector3 ( ) ; const tmpV2 = new THREE . Vector3 ( ) ; const tmpBox = new THREE . Box3 ( ) ; internal export interface DisplacementRange { min : number ; max : number ; } internal param box param displacementRange param displacementDir return export function displaceBox ( box , displacementRange , displacementDir ) { tmpBox . copy ( box ) ; const tmpNormalMin = tmpV1 . copy ( displacementDir ) ; const tmpNormalMax = tmpV2 . copy ( tmpNormalMin ) ; box . translate ( tmpNormalMin . multiplyScalar ( displacementRange . min ) ) . union ( tmpBox . translate ( tmpNormalMax . multiplyScalar ( displacementRange . max ) ) ) ; return box ; } internal export class DisplacedBufferGeometry extends THREE . BufferGeometry { private readonly m_displacedPositions : DisplacedBufferAttribute ; private readonly m_originalBoundingBox = new THREE . Box3 ( ) ; param originalGeometry param displacementMap param displacementRange param displacedPositions constructor ( public originalGeometry , displacementMap , public displacementRange , displacedPositions ? ) { super ( ) ; if ( ! displacedPositions ) { this . m_displacedPositions = new DisplacedBufferAttribute ( originalGeometry . attributes . position , originalGeometry . attributes . normal , originalGeometry . attributes . uv , displacementMap ) ; } else { this . m_displacedPositions = displacedPositions ; } this . resetAttributes ( ) ; } param geometry param displacementMap param displacementRange reset ( geometry , displacementMap , displacementRange ) { this . originalGeometry = geometry ; const positions = geometry . attributes . position ; const normals = geometry . attributes . normal ; const uvs = geometry . attributes . uv ; this . m_displacedPositions . reset ( positions , normals , uvs , displacementMap ) ; const displacementRangeChanged = this . displacementRange . min !== displacementRange . min || this . displacementRange . max !== displacementRange . max ; this . displacementRange = displacementRange ; this . resetAttributes ( ) ; this . resetBoundingVolumes ( displacementRangeChanged ) ; } computeBoundingBox ( ) { if ( this . originalGeometry . boundingBox === null ) { this . originalGeometry . computeBoundingBox ( ) ; } const origBBox = this . m_originalBoundingBox . copy ( this . originalGeometry . boundingBox ! ) ; if ( this . boundingBox === null ) { this . boundingBox = origBBox . clone ( ) ; } else { this . boundingBox . copy ( origBBox ) ; } displaceBox ( this . boundingBox , this . displacementRange , tmpV1 . fromBufferAttribute ( this . attributes . normal as THREE . BufferAttribute , 0 ) ) ; } computeBoundingSphere ( ) { if ( this . boundingBox === null ) { this . computeBoundingBox ( ) ; } if ( this . boundingSphere === null ) { this . boundingSphere = new THREE . Sphere ( ) ; } this . boundingBox ! . getBoundingSphere ( this . boundingSphere ! ) ; } private needsBoundingBoxUpdate ( displacementRangeChanged ) { return ( displacementRangeChanged || ( this . boundingBox !== null && ( ! this . originalGeometry . boundingBox || ! this . m_originalBoundingBox . equals ( this . originalGeometry . boundingBox ) ) ) ) ; } private resetBoundingVolumes ( displacementRangeChanged ) { if ( this . needsBoundingBoxUpdate ( displacementRangeChanged ) ) { this . computeBoundingBox ( ) ; if ( this . boundingSphere ) { this . computeBoundingSphere ( ) ; } } } private resetAttributes ( ) { this . index = this . originalGeometry . index ; this . groups = this . originalGeometry . groups ; this . drawRange = this . originalGeometry . drawRange ; this . attributes = { ... this . originalGeometry . attributes } ; this . attributes . position = this . m_displacedPositions ; } }