Skip to content

Commit

Permalink
chore: refactor to make point sorting self-contained
Browse files Browse the repository at this point in the history
  • Loading branch information
haakonflatval-cognite committed Jun 17, 2024
1 parent f0a4842 commit fb7dd6f
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 22 deletions.
1 change: 0 additions & 1 deletion viewer/packages/3d-overlays/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ export { Overlay3DIcon } from './src/Overlay3DIcon';
export { Overlay3D } from './src/Overlay3D';
export { OverlayCollection, OverlayInfo, DefaultOverlay3DContentType } from './src/OverlayCollection';
export { IconOctree } from './src/IconOctree';
export { TextOverlay } from './src/TextOverlay';
27 changes: 27 additions & 0 deletions viewer/packages/3d-overlays/src/CameraChangeThrottler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*!
* Copyright 2024 Cognite AS
*/
import throttle from 'lodash/throttle';
import { Camera, Matrix4 } from 'three';

export type Callback = () => void;

export class CameraChangeThrottler {
private readonly _prevCameraMatrix: Matrix4 = new Matrix4();

public call: (camera: Camera, callback: Callback) => void;

constructor(wait: number = 500) {
this.call = throttle((camera: Camera, callback: Callback) => this._call(camera, callback), wait);
}

private _call(camera: Camera, callback: Callback) {
if (camera.matrix.equals(this._prevCameraMatrix)) {
return;
}

callback();

this._prevCameraMatrix.copy(camera.matrix);
}
}
35 changes: 24 additions & 11 deletions viewer/packages/3d-overlays/src/Overlay3DCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
* Copyright 2023 Cognite AS
*/

import { CanvasTexture, Color, Texture, Object3D, Camera, Vector2, Raycaster } from 'three';
import { CanvasTexture, Color, Texture, Object3D, Camera, Vector2, Raycaster, WebGLRenderer, Scene } from 'three';
import { Overlay3DIcon } from './Overlay3DIcon';
import { Overlay3D } from './Overlay3D';
import { OverlayPointsObject } from './OverlayPointsObject';
import { IconOctree } from './IconOctree';
import { DefaultOverlay3DContentType, OverlayCollection, OverlayInfo } from './OverlayCollection';
import minBy from 'lodash/minBy';
import { CameraChangeThrottler } from './CameraChangeThrottler';

/**
* Constructor options for the Overlay3DCollection
Expand Down Expand Up @@ -54,6 +55,7 @@ export class Overlay3DCollection<MetadataType = DefaultOverlay3DContentType>
//@ts-ignore Will be removed when clustering is added.
private _octree: IconOctree<MetadataType>;
private readonly _rayCaster = new Raycaster();
private readonly _cameraChangeDebouncer = new CameraChangeThrottler();

constructor(overlayInfos: OverlayInfo<MetadataType>[], options?: Overlay3DCollectionOptions) {
super();
Expand All @@ -66,17 +68,20 @@ export class Overlay3DCollection<MetadataType = DefaultOverlay3DContentType>
mask: options?.overlayTextureMask ?? (options?.overlayTexture ? undefined : defaultOverlayTextures.mask)
};

this._overlayPoints = new OverlayPointsObject(overlayInfos ? overlayInfos.length : this.DefaultMaxPoints, {
spriteTexture: this._sharedTextures.color,
maskTexture: this._sharedTextures.mask,
minPixelSize: this.MinPixelSize,
maxPixelSize: options?.maxPointSize ?? this.MaxPixelSize,
radius: this._iconRadius
});

this._overlays = this.initializeOverlay3DIcons(overlayInfos ?? []);
this._overlayPoints = new OverlayPointsObject(
overlayInfos ? overlayInfos.length : this.DefaultMaxPoints,
{
spriteTexture: this._sharedTextures.color,
maskTexture: this._sharedTextures.mask,
minPixelSize: this.MinPixelSize,
maxPixelSize: options?.maxPointSize ?? this.MaxPixelSize,
radius: this._iconRadius
},
(...args) => this.onBeforeRenderDelegate(...args)
);

this._overlays = this.initializeOverlay3DIcons(overlayInfos);
this.add(this._overlayPoints);

this.updatePointsObject();

this._octree = this.rebuildOctree();
Expand Down Expand Up @@ -112,6 +117,14 @@ export class Overlay3DCollection<MetadataType = DefaultOverlay3DContentType>
return newIcons;
}

private readonly onBeforeRenderDelegate: Object3D['onBeforeRender'] = (
_renderer: WebGLRenderer,
_scene: Scene,
camera: Camera
) => {
this._cameraChangeDebouncer.call(camera, () => this.sortOverlaysRelativeToCamera(camera));
};

private sortOverlaysRelativeToCamera(camera: Camera): void {
this._overlays = this._overlays.sort((a, b) => {
return b.getPosition().distanceToSquared(camera.position) - a.getPosition().distanceToSquared(camera.position);
Expand Down
12 changes: 10 additions & 2 deletions viewer/packages/3d-overlays/src/OverlayPointsObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Group,
LessEqualDepth,
Matrix4,
Object3D,
Points,
RawShaderMaterial,
ShaderMaterial,
Expand Down Expand Up @@ -43,9 +44,14 @@ export class OverlayPointsObject extends Group {
private readonly _colorBuffer: Float32Array;
private readonly _colorAttribute: BufferAttribute;
private readonly _points: { frontPoints: Points; backPoints: Points };
private readonly _onBeforeRender?: Object3D['onBeforeRender'];
private _modelTransform: Matrix4;

constructor(maxNumberOfPoints: number, materialParameters: OverlayPointsParameters) {
constructor(
maxNumberOfPoints: number,
materialParameters: OverlayPointsParameters,
onBeforeRender?: Object3D['onBeforeRender']
) {
super();
const geometry = new BufferGeometry();
this._positionBuffer = new Float32Array(maxNumberOfPoints * 3);
Expand Down Expand Up @@ -101,6 +107,7 @@ export class OverlayPointsObject extends Group {
this._geometry = geometry;
this._frontMaterial = frontMaterial;
this._points = { frontPoints, backPoints };
this._onBeforeRender = onBeforeRender;
}

public setPoints(points: Vector3[], colors?: Color[]): void {
Expand Down Expand Up @@ -163,7 +170,8 @@ export class OverlayPointsObject extends Group {

private initializePoints(geometry: BufferGeometry, frontMaterial: ShaderMaterial): Points {
const frontPoints = createPoints(geometry, frontMaterial);
frontPoints.onBeforeRender = renderer => {
frontPoints.onBeforeRender = (renderer, ...rest) => {
this._onBeforeRender?.(renderer, ...rest);
setUniforms(renderer, frontMaterial);
};

Expand Down
28 changes: 22 additions & 6 deletions viewer/packages/tools/src/Overlay3D/Overlay3DTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import {
OverlayInfo,
DefaultOverlay3DContentType,
OverlayCollection,
Overlay3D,
TextOverlay
Overlay3D
} from '@reveal/3d-overlays';
import { TextOverlay } from './TextOverlay';
import { Cognite3DViewerToolBase } from '../Cognite3DViewerToolBase';

/**
Expand Down Expand Up @@ -86,7 +86,7 @@ export class Overlay3DTool<ContentType = DefaultOverlay3DContentType> extends Co

private _overlayCollections: Overlay3DCollection<ContentType>[] = [];
private _isVisible = true;
private _textOverlay: TextOverlay;
private readonly _textOverlay: TextOverlay;

private readonly _events = {
hover: new EventTrigger<OverlayEventHandler<ContentType>>(),
Expand Down Expand Up @@ -118,8 +118,9 @@ export class Overlay3DTool<ContentType = DefaultOverlay3DContentType> extends Co
const { _viewer: viewer } = this;

const points = new Overlay3DCollection<ContentType>(overlays ?? [], {
...options,
defaultOverlayColor: options?.defaultOverlayColor ?? this._defaultOverlayColor
defaultOverlayColor: options?.defaultOverlayColor ?? this._defaultOverlayColor,
overlayTexture: options?.overlayTexture,
overlayTextureMask: options?.overlayTextureMask
});

this._overlayCollections.push(points);
Expand Down Expand Up @@ -171,6 +172,21 @@ export class Overlay3DTool<ContentType = DefaultOverlay3DContentType> extends Co
return this._isVisible;
}

/**
* Sets whether text overlay is visible.
* Default is false.
*/
setTextOverlayVisible(visible: boolean): void {
this._textOverlay.setTextOverlayEnabled(visible);
}

/**
* Gets whether text overlay is visible.
*/
getTextOverlayVisible(): boolean {
return this._textOverlay.getTextOverlayEnabled();
}

/**
* Removes all overlays.
*/
Expand Down Expand Up @@ -284,7 +300,7 @@ export class Overlay3DTool<ContentType = DefaultOverlay3DContentType> extends Co
const intersections: [Overlay3D<ContentType>, THREE.Vector3][] = [];

for (const points of this._overlayCollections) {
const intersection = points.intersectOverlays(normalizedCoordinates);
const intersection = points.intersectOverlays(normalizedCoordinates, camera);
if (intersection !== undefined) {
intersections.push([intersection, intersection.getPosition().clone()]);
}
Expand Down
5 changes: 3 additions & 2 deletions viewer/reveal.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AnnotationsAssetRef } from '@cognite/sdk';
import { AnnotationsCogniteAnnotationTypesImagesAssetLink } from '@cognite/sdk';
import { AnnotationStatus } from '@cognite/sdk';
import { Box3 } from 'three';
import { Camera } from 'three';
import { CogniteClient } from '@cognite/sdk';
import { CogniteInternalId } from '@cognite/sdk';
import { Color } from 'three';
Expand Down Expand Up @@ -1573,11 +1574,11 @@ export interface Overlay3D<ContentType> {

// @public
export class Overlay3DCollection<MetadataType = DefaultOverlay3DContentType> extends Object3D implements OverlayCollection<MetadataType> {
constructor(overlayInfos: OverlayInfo<MetadataType>[], cameraManager: CameraManager, options?: Overlay3DCollectionOptions);
constructor(overlayInfos: OverlayInfo<MetadataType>[], options?: Overlay3DCollectionOptions);
addOverlays(overlayInfos: OverlayInfo<MetadataType>[]): Overlay3D<MetadataType>[];
dispose(): void;
getOverlays(): Overlay3D<MetadataType>[];
intersectOverlays(normalizedCoordinates: Vector2): Overlay3D<MetadataType> | undefined;
intersectOverlays(normalizedCoordinates: Vector2, camera: Camera): Overlay3D<MetadataType> | undefined;
removeAllOverlays(): void;
removeOverlays(overlays: Overlay3D<MetadataType>[]): void;
setVisibility(visibility: boolean): void;
Expand Down

0 comments on commit fb7dd6f

Please sign in to comment.