import { DisplacementFeature , hasDisplacementFeature } from "@here/harp-materials" ; import { assert } from "@here/harp-utils" ; import * as THREE from "three" ; import { DisplacedBufferAttribute } from "./DisplacedBufferAttribute" ; import { DisplacedBufferGeometry , DisplacementRange } from "./DisplacedBufferGeometry" ; function isDisplacementMaterial ( material ) { const isDisplacementFeature = hasDisplacementFeature ( material ) ; assert ( isDisplacementFeature , "Material does not support displacement maps." ) ; return isDisplacementFeature ; } function isDataTextureMap ( map ? ) { if ( ! map ) { return false ; } const isDataTexture = map instanceof THREE . DataTexture ; assert ( isDataTexture , "Material does not support displacement maps." ) ; return isDataTexture ; } internal export class DisplacedMesh extends THREE . Mesh { private static displacedPositions ? : DisplacedBufferAttribute ; private static getDisplacedPositionAttribute ( geometry , displacementMap ) { if ( ! DisplacedMesh . displacedPositions ) { DisplacedMesh . displacedPositions = new DisplacedBufferAttribute ( geometry . attributes . position , geometry . attributes . normal , geometry . attributes . uv , displacementMap ) ; } else { DisplacedMesh . displacedPositions . reset ( geometry . attributes . position , geometry . attributes . normal , geometry . attributes . uv , displacementMap ) ; } return DisplacedMesh . displacedPositions ; } displacedGeometry ? : DisplacedBufferGeometry ; param geometry param material param m_getDisplacementRange param m_raycastStrategy constructor ( geometry , material , private readonly m_getDisplacementRange , private readonly m_raycastStrategy ? ) { super ( geometry , material ) ; } raycast ( raycaster , intersects ) { const firstMaterial = this . firstMaterial ; if ( ! isDisplacementMaterial ( firstMaterial ) || ! isDataTextureMap ( firstMaterial . displacementMap ) ) { super . raycast ( raycaster , intersects ) ; return ; } const displacementMap = firstMaterial . displacementMap ; const displacementRange = { ... this . m_getDisplacementRange ( ) } ; assert ( this . geometry instanceof THREE . BufferGeometry , "Unsupported geometry type." ) ; const geometry = this . geometry as THREE . BufferGeometry ; if ( this . displacedGeometry ) { this . displacedGeometry . reset ( geometry , displacementMap , displacementRange ) ; } else { this . displacedGeometry = new DisplacedBufferGeometry ( geometry , displacementMap , displacementRange , DisplacedMesh . getDisplacedPositionAttribute ( geometry , displacementMap ) ) ; } this . geometry = this . displacedGeometry ; if ( this . m_raycastStrategy ) { this . m_raycastStrategy ( this , raycaster , intersects ) ; } else { super . raycast ( raycaster , intersects ) ; } super . geometry = this . displacedGeometry . originalGeometry ; } private get firstMaterial ( ) : THREE . Material { return Array . isArray ( this . material ) ? this . material [ 0 ] : this . material ; } }