11import {
22 AdditiveBlending ,
3+ BufferGeometry ,
4+ Camera ,
35 Color ,
6+ Geometry ,
47 LessEqualDepth ,
8+ Material ,
59 NearestFilter ,
610 NoBlending ,
11+ PerspectiveCamera ,
712 RawShaderMaterial ,
8- Texture
13+ Scene ,
14+ Texture ,
15+ Vector3 ,
16+ WebGLRenderer ,
917} from 'three' ;
1018import {
1119 DEFAULT_MAX_POINT_SIZE ,
1220 DEFAULT_MIN_POINT_SIZE ,
1321 DEFAULT_RGB_BRIGHTNESS ,
1422 DEFAULT_RGB_CONTRAST ,
1523 DEFAULT_RGB_GAMMA ,
24+ PERSPECTIVE_CAMERA ,
1625} from '../constants' ;
26+ import { PointCloudOctree } from '../point-cloud-octree' ;
27+ import { PointCloudOctreeNode } from '../point-cloud-octree-node' ;
28+ import { byLevelAndIndex } from '../utils/utils' ;
1729import { DEFAULT_CLASSIFICATION } from './classification' ;
1830import { ClipMode , IClipBox } from './clipping' ;
1931import { PointColorType , PointOpacityType , PointShape , PointSizeType , TreeType } from './enums' ;
@@ -41,7 +53,6 @@ export interface IPointCloudMaterialUniforms {
4153 clipBoxes : IUniform < Float32Array > ;
4254 depthMap : IUniform < Texture | null > ;
4355 diffuse : IUniform < [ number , number , number ] > ;
44- far : IUniform < number > ;
4556 fov : IUniform < number > ;
4657 gradient : IUniform < Texture > ;
4758 heightMax : IUniform < number > ;
@@ -53,7 +64,6 @@ export interface IPointCloudMaterialUniforms {
5364 level : IUniform < number > ;
5465 maxSize : IUniform < number > ;
5566 minSize : IUniform < number > ;
56- near : IUniform < number > ;
5767 octreeSize : IUniform < number > ;
5868 opacity : IUniform < number > ;
5969 pcIndex : IUniform < number > ;
@@ -126,11 +136,14 @@ const CLIP_MODE_DEFS = {
126136} ;
127137
128138export class PointCloudMaterial extends RawShaderMaterial {
139+ private static helperVec3 = new Vector3 ( ) ;
140+
129141 lights = false ;
130142 fog = false ;
131143 numClipBoxes : number = 0 ;
132144 clipBoxes : IClipBox [ ] = [ ] ;
133145 visibleNodesTexture : Texture | undefined ;
146+ private visibleNodeTextureOffsets = new Map < string , number > ( ) ;
134147
135148 private _gradient = SPECTRAL ;
136149 private gradientTexture : Texture | undefined = generateGradientTexture ( this . _gradient ) ;
@@ -149,7 +162,6 @@ export class PointCloudMaterial extends RawShaderMaterial {
149162 clipBoxes : makeUniform ( 'Matrix4fv' , [ ] as any ) ,
150163 depthMap : makeUniform ( 't' , null ) ,
151164 diffuse : makeUniform ( 'fv' , [ 1 , 1 , 1 ] as [ number , number , number ] ) ,
152- far : makeUniform ( 'f' , 1.0 ) ,
153165 fov : makeUniform ( 'f' , 1.0 ) ,
154166 gradient : makeUniform ( 't' , this . gradientTexture || new Texture ( ) ) ,
155167 heightMax : makeUniform ( 'f' , 1.0 ) ,
@@ -162,7 +174,6 @@ export class PointCloudMaterial extends RawShaderMaterial {
162174 level : makeUniform ( 'f' , 0.0 ) ,
163175 maxSize : makeUniform ( 'f' , DEFAULT_MAX_POINT_SIZE ) ,
164176 minSize : makeUniform ( 'f' , DEFAULT_MIN_POINT_SIZE ) ,
165- near : makeUniform ( 'f' , 0.1 ) ,
166177 octreeSize : makeUniform ( 'f' , 0 ) ,
167178 opacity : makeUniform ( 'f' , 1.0 ) ,
168179 pcIndex : makeUniform ( 'f' , 0 ) ,
@@ -190,7 +201,6 @@ export class PointCloudMaterial extends RawShaderMaterial {
190201
191202 @uniform ( 'bbSize' ) bbSize ! : [ number , number , number ] ;
192203 @uniform ( 'depthMap' ) depthMap ! : Texture | undefined ;
193- @uniform ( 'far' ) far ! : number ;
194204 @uniform ( 'fov' ) fov ! : number ;
195205 @uniform ( 'heightMax' ) heightMax ! : number ;
196206 @uniform ( 'heightMin' ) heightMin ! : number ;
@@ -200,7 +210,7 @@ export class PointCloudMaterial extends RawShaderMaterial {
200210 @uniform ( 'intensityRange' ) intensityRange ! : [ number , number ] ;
201211 @uniform ( 'maxSize' ) maxSize ! : number ;
202212 @uniform ( 'minSize' ) minSize ! : number ;
203- @uniform ( 'near ' ) near ! : number ;
213+ @uniform ( 'octreeSize ' ) octreeSize ! : number ;
204214 @uniform ( 'opacity' , true ) opacity ! : number ;
205215 @uniform ( 'rgbBrightness' , true ) rgbBrightness ! : number ;
206216 @uniform ( 'rgbContrast' , true ) rgbContrast ! : number ;
@@ -280,6 +290,8 @@ export class PointCloudMaterial extends RawShaderMaterial {
280290 this . visibleNodesTexture = undefined ;
281291 }
282292
293+ this . clearVisibleNodeTextureOffsets ( ) ;
294+
283295 if ( this . classificationTexture ) {
284296 this . classificationTexture . dispose ( ) ;
285297 this . classificationTexture = undefined ;
@@ -291,6 +303,10 @@ export class PointCloudMaterial extends RawShaderMaterial {
291303 }
292304 }
293305
306+ clearVisibleNodeTextureOffsets ( ) : void {
307+ this . visibleNodeTextureOffsets . clear ( ) ;
308+ }
309+
294310 updateShaderSource ( ) : void {
295311 this . vertexShader = this . applyDefines ( require ( './shaders/pointcloud.vert' ) . default ) ;
296312 this . fragmentShader = this . applyDefines ( require ( './shaders/pointcloud.frag' ) . default ) ;
@@ -477,6 +493,107 @@ export class PointCloudMaterial extends RawShaderMaterial {
477493 uObj . value = value ;
478494 }
479495 }
496+
497+ updateMaterial (
498+ octree : PointCloudOctree ,
499+ visibleNodes : PointCloudOctreeNode [ ] ,
500+ camera : Camera ,
501+ renderer : WebGLRenderer ,
502+ ) : void {
503+ const pixelRatio = renderer . getPixelRatio ( ) ;
504+
505+ if ( camera . type === PERSPECTIVE_CAMERA ) {
506+ this . fov = ( camera as PerspectiveCamera ) . fov * ( Math . PI / 180 ) ;
507+ } else {
508+ this . fov = Math . PI / 2 ; // will result in slope = 1 in the shader
509+ }
510+ this . screenWidth = renderer . domElement . clientWidth * pixelRatio ;
511+ this . screenHeight = renderer . domElement . clientHeight * pixelRatio ;
512+
513+ const maxScale = Math . max ( octree . scale . x , octree . scale . y , octree . scale . z ) ;
514+ this . spacing = octree . pcoGeometry . spacing * maxScale ;
515+ this . octreeSize = octree . pcoGeometry . boundingBox . getSize ( PointCloudMaterial . helperVec3 ) . x ;
516+
517+ if (
518+ this . pointSizeType === PointSizeType . ADAPTIVE ||
519+ this . pointColorType === PointColorType . LOD
520+ ) {
521+ this . updateVisibilityTextureData ( visibleNodes ) ;
522+ }
523+ }
524+
525+ private updateVisibilityTextureData ( nodes : PointCloudOctreeNode [ ] ) {
526+ nodes . sort ( byLevelAndIndex ) ;
527+
528+ const data = new Uint8Array ( nodes . length * 4 ) ;
529+ const offsetsToChild = new Array ( nodes . length ) . fill ( Infinity ) ;
530+
531+ this . visibleNodeTextureOffsets . clear ( ) ;
532+
533+ for ( let i = 0 ; i < nodes . length ; i ++ ) {
534+ const node = nodes [ i ] ;
535+
536+ this . visibleNodeTextureOffsets . set ( node . name , i ) ;
537+
538+ if ( i > 0 ) {
539+ const parentName = node . name . slice ( 0 , - 1 ) ;
540+ const parentOffset = this . visibleNodeTextureOffsets . get ( parentName ) ! ;
541+ const parentOffsetToChild = i - parentOffset ;
542+
543+ offsetsToChild [ parentOffset ] = Math . min ( offsetsToChild [ parentOffset ] , parentOffsetToChild ) ;
544+
545+ // tslint:disable:no-bitwise
546+ const offset = parentOffset * 4 ;
547+ data [ offset ] = data [ offset ] | ( 1 << node . index ) ;
548+ data [ offset + 1 ] = offsetsToChild [ parentOffset ] >> 8 ;
549+ data [ offset + 2 ] = offsetsToChild [ parentOffset ] % 256 ;
550+ // tslint:enable:no-bitwise
551+ }
552+
553+ data [ i * 4 + 3 ] = node . name . length ;
554+ }
555+
556+ const texture = this . visibleNodesTexture ;
557+ if ( texture ) {
558+ texture . image . data . set ( data ) ;
559+ texture . needsUpdate = true ;
560+ }
561+ }
562+
563+ static makeOnBeforeRender (
564+ octree : PointCloudOctree ,
565+ node : PointCloudOctreeNode ,
566+ pcIndex ?: number ,
567+ ) {
568+ return (
569+ _renderer : WebGLRenderer ,
570+ _scene : Scene ,
571+ _camera : Camera ,
572+ _geometry : Geometry | BufferGeometry ,
573+ material : Material ,
574+ ) => {
575+ const pointCloudMaterial = material as PointCloudMaterial ;
576+ const materialUniforms = pointCloudMaterial . uniforms ;
577+
578+ materialUniforms . level . value = node . level ;
579+ materialUniforms . isLeafNode . value = node . isLeafNode ;
580+
581+ const vnStart = pointCloudMaterial . visibleNodeTextureOffsets . get ( node . name ) ;
582+ if ( vnStart !== undefined ) {
583+ materialUniforms . vnStart . value = vnStart ;
584+ }
585+
586+ materialUniforms . pcIndex . value =
587+ pcIndex !== undefined ? pcIndex : octree . visibleNodes . indexOf ( node ) ;
588+
589+ // Note: when changing uniforms in onBeforeRender, the flag uniformsNeedUpdate has to be
590+ // set to true to instruct ThreeJS to upload them. See also
591+ // https://github.com/mrdoob/three.js/issues/9870#issuecomment-368750182.
592+
593+ // Remove the cast to any after updating to Three.JS >= r113
594+ ( material as any ) /*ShaderMaterial*/ . uniformsNeedUpdate = true ;
595+ } ;
596+ }
480597}
481598
482599function makeUniform < T > ( type : string , value : T ) : IUniform < T > {
0 commit comments