import { Vector3Like } from "@here/harp-geoutils" ; import { sampleBilinear } from "@here/harp-utils" ; import * as THREE from "three" ; import { VertexCache } from "./VertexCache" ; internal export class DisplacedBufferAttribute extends THREE . BufferAttribute { private static readonly MAX_CACHE_SIZE = 6 ; private m_texture ? : Float32Array ; private m_textureWidth : number = 0 ; private m_textureHeight : number = 0 ; private readonly m_cache = new VertexCache ( DisplacedBufferAttribute . MAX_CACHE_SIZE ) ; private m_lastBufferIndex ? : number ; private readonly m_lastPos = new THREE . Vector3 ( ) ; private readonly m_tmpNormal = new THREE . Vector3 ( ) ; param originalAttribute param m_normals param m_uvs param displacementMap constructor ( public originalAttribute , private m_normals , private m_uvs , displacementMap ) { super ( originalAttribute . array , originalAttribute . itemSize , originalAttribute . normalized ) ; this . resetTexture ( displacementMap ) ; } param originalAttribute param normals param uvs param displacementMap reset ( originalAttribute , normals , uvs , displacementMap ) { this . array = originalAttribute . array ; this . itemSize = originalAttribute . itemSize ; this . count = this . array . length / this . itemSize ; this . normalized = originalAttribute . normalized ; this . originalAttribute = originalAttribute ; this . m_normals = normals ; this . m_uvs = uvs ; this . m_cache . clear ( ) ; this . m_lastBufferIndex = undefined ; this . resetTexture ( displacementMap ) ; } getX ( index ) { return this . getDisplacedCoordinate ( index ) . x ; } getY ( index ) { return this . getDisplacedCoordinate ( index ) . y ; } getZ ( index ) { return this . getDisplacedCoordinate ( index ) . z ; } private resetTexture ( displacementMap ) { this . m_texture = new Float32Array ( displacementMap . image . data . buffer ) ; this . m_textureWidth = displacementMap . image . width ; this . m_textureHeight = displacementMap . image . height ; } private getDisplacedCoordinate ( bufferIndex ) { if ( bufferIndex === this . m_lastBufferIndex ) { return this . m_lastPos ; } this . m_lastBufferIndex = bufferIndex ; if ( this . m_cache . get ( bufferIndex , this . m_lastPos ) ) { return this . m_lastPos ; } this . displacePosition ( bufferIndex ) ; this . m_cache . set ( bufferIndex , this . m_lastPos ) ; return this . m_lastPos ; } private displacePosition ( bufferIndex ) { this . m_lastPos . fromBufferAttribute ( this . originalAttribute as THREE . BufferAttribute , bufferIndex ) ; const normals = this . m_normals as THREE . BufferAttribute ; this . m_tmpNormal . fromBufferAttribute ( normals , bufferIndex ) ; const uvs = this . m_uvs ; const u = THREE . MathUtils . clamp ( uvs . getX ( bufferIndex ) , 0 , 1 ) ; const v = THREE . MathUtils . clamp ( uvs . getY ( bufferIndex ) , 0 , 1 ) ; const displacement = sampleBilinear ( this . m_texture ! , this . m_textureWidth , this . m_textureHeight , u , v ) ; this . m_lastPos . add ( this . m_tmpNormal . multiplyScalar ( displacement ) ) ; } }