Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: fix unsafe usage of static variables #4664

Merged
merged 10 commits into from
Jul 17, 2024
Merged
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ examples/public/
documentation/.docusaurus
documentation/generated
documentation/docs/api
/react-components/stories/public/cadModel
/react-components/stories/public/cadModel

**/install-state.gz
5 changes: 3 additions & 2 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"@azure/msal-browser": "^3.0.0",
"@cognite/reveal": "link:../viewer",
"@cognite/sdk": "link:../viewer/node_modules/@cognite/sdk",
"dat.gui": "^0.7.7",
"buffer": "^6.0.3",
"dat.gui": "^0.7.7",
"lodash": "^4.17.21",
"react": "18.3.1",
"react-dom": "18.3.1",
Expand Down Expand Up @@ -63,5 +63,6 @@
"last 1 firefox version",
"last 1 safari version"
]
}
},
"packageManager": "yarn@4.3.1"
}
26 changes: 25 additions & 1 deletion examples/src/utils/CustomCameraManager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Plane, Vector3 } from "three";
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import pull from 'lodash/pull';
Expand All @@ -20,6 +21,29 @@ export class CustomCameraManager implements CameraManager {
private readonly _cameraChangedListener: Array<CameraChangeDelegate> = [];
private _stopEventHandler: DebouncedCameraStopEventTrigger;

/**
* Reusable buffers used by updateNearAndFarPlane function to avoid allocations.
*/
private readonly _updateNearAndFarPlaneBuffers = {
cameraPosition: new Vector3(),
cameraDirection: new Vector3(),
corners: new Array<Vector3>(
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3()
)
};

private readonly _calculateCameraFarBuffers = {
nearPlaneCoplanarPoint: new Vector3(),
nearPlane: new Plane()
};
haakonflatval-cognite marked this conversation as resolved.
Show resolved Hide resolved

constructor(domElement: HTMLElement, camera: THREE.PerspectiveCamera) {
this._domElement = domElement;
this._camera = camera;
Expand Down Expand Up @@ -119,7 +143,7 @@ export class CustomCameraManager implements CameraManager {

update(deltaTime: number, boundingBox: THREE.Box3): void {
this._controls.update();
CameraManagerHelper.updateCameraNearAndFar(this._camera, boundingBox);
CameraManagerHelper.updateCameraNearAndFar(this._camera, boundingBox, this._updateNearAndFarPlaneBuffers, this._calculateCameraFarBuffers);
}

dispose(): void {
Expand Down
8,362 changes: 4,600 additions & 3,762 deletions examples/yarn.lock

Large diffs are not rendered by default.

43 changes: 15 additions & 28 deletions viewer/packages/camera-manager/src/CameraManagerHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,15 @@
* Copyright 2022 Cognite AS
*/

import { Box3, PerspectiveCamera, Plane, Quaternion, Vector3 } from 'three';
import { CameraFarBuffers, NearAndFarPlaneBuffers } from '@reveal/camera-manager';
import { Box3, PerspectiveCamera, Quaternion, Vector3 } from 'three';
import range from 'lodash/range';
import { fitCameraToBoundingBox } from '@reveal/utilities';

/**
* Helper methods for implementing a camera manager.
*/
export class CameraManagerHelper {
/**
* Reusable buffers used by updateNearAndFarPlane function to avoid allocations.
*/
private static readonly _updateNearAndFarPlaneBuffers = {
cameraPosition: new Vector3(),
cameraDirection: new Vector3(),
corners: new Array<Vector3>(
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3()
)
};

private static readonly _calculateCameraFarBuffers = {
nearPlaneCoplanarPoint: new Vector3(),
nearPlane: new Plane()
};
/**
* Calculates camera target based on new camera rotation.
* @param camera Used camera instance.
Expand Down Expand Up @@ -76,9 +55,16 @@ export class CameraManagerHelper {
* Updates near and far plane of the camera based on the bounding box.
* @param camera Used camera instance.
* @param boundingBox Bounding box of all objects on the scene.
* @param nearAndFarPlaneBuffers to read from
* @param cameraFarBuffers
*/
static updateCameraNearAndFar(camera: PerspectiveCamera, boundingBox: Box3): void {
const { cameraPosition, cameraDirection, corners } = this._updateNearAndFarPlaneBuffers;
static updateCameraNearAndFar(
camera: PerspectiveCamera,
boundingBox: Box3,
nearAndFarPlaneBuffers: NearAndFarPlaneBuffers,
cameraFarBuffers: CameraFarBuffers
): void {
const { cameraPosition, cameraDirection, corners } = nearAndFarPlaneBuffers;
haakonflatval-cognite marked this conversation as resolved.
Show resolved Hide resolved
this.getBoundingBoxCorners(boundingBox, corners);
camera.getWorldPosition(cameraPosition);
camera.getWorldDirection(cameraDirection);
Expand All @@ -89,7 +75,7 @@ export class CameraManagerHelper {

// 2. Compute the far distance to the distance from camera to furthest
// corner of the bounding box that is "in front" of the near plane
const far = this.calculateCameraFar(near, cameraPosition, cameraDirection, corners);
const far = this.calculateCameraFar(near, cameraPosition, cameraDirection, corners, cameraFarBuffers);

// 3. Handle when camera is inside the model by adjusting the near value
if (boundingBox.containsPoint(cameraPosition)) {
Expand Down Expand Up @@ -120,9 +106,10 @@ export class CameraManagerHelper {
near: number,
cameraPosition: Vector3,
cameraDirection: Vector3,
corners: Array<Vector3>
corners: Array<Vector3>,
cameraFarBuffers: CameraFarBuffers
): number {
const { nearPlane, nearPlaneCoplanarPoint } = this._calculateCameraFarBuffers;
const { nearPlane, nearPlaneCoplanarPoint } = cameraFarBuffers;

nearPlaneCoplanarPoint.copy(cameraPosition).addScaledVector(cameraDirection, near);
nearPlane.setFromNormalAndCoplanarPoint(cameraDirection, nearPlaneCoplanarPoint);
Expand Down
35 changes: 33 additions & 2 deletions viewer/packages/camera-manager/src/DefaultCameraManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright 2021 Cognite AS
*/

import { Plane, Vector3 } from 'three';
import * as THREE from 'three';
import TWEEN, { type Tween } from '@tweenjs/tween.js';
import clamp from 'lodash/clamp';
Expand All @@ -15,7 +16,9 @@ import {
CameraChangeDelegate,
CameraManagerEventType,
CameraStopDelegate,
CameraEventDelegate
CameraEventDelegate,
NearAndFarPlaneBuffers,
CameraFarBuffers
} from './types';

import { CameraManager } from './CameraManager';
Expand Down Expand Up @@ -56,6 +59,29 @@ export class DefaultCameraManager implements CameraManager {
private _isDisposed = false;
private _nearAndFarNeedsUpdate = false;

/**
* Reusable buffers used by updateNearAndFarPlane function to avoid allocations.
*/
private readonly _updateNearAndFarPlaneBuffers: NearAndFarPlaneBuffers = {
cameraPosition: new Vector3(),
cameraDirection: new Vector3(),
corners: new Array<Vector3>(
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3()
)
};

private readonly _calculateCameraFarBuffers: CameraFarBuffers = {
nearPlaneCoplanarPoint: new Vector3(),
nearPlane: new Plane()
};

// The active/inactive state of this manager. Does not always match up with the controls
// as these are temporarily disabled to block onWheel input during `zoomToCursor`-mode
private _isEnabled = true;
Expand Down Expand Up @@ -427,7 +453,12 @@ export class DefaultCameraManager implements CameraManager {
return;
}
if (this.automaticNearFarPlane) {
CameraManagerHelper.updateCameraNearAndFar(camera, boundingBox);
CameraManagerHelper.updateCameraNearAndFar(
camera,
boundingBox,
this._updateNearAndFarPlaneBuffers,
this._calculateCameraFarBuffers
);
}
if (this.automaticControlsSensitivity) {
const diagonal = boundingBox.min.distanceTo(boundingBox.max);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright 2024 Cognite AS
*/

import { Box3, PerspectiveCamera, Raycaster, Vector3, Scene, Ray, Spherical, Vector2 } from 'three';
import { Box3, PerspectiveCamera, Raycaster, Vector3, Scene, Ray, Spherical, Vector2, Plane } from 'three';

import { FlexibleControls } from './FlexibleControls';
import { FlexibleControlsOptions } from './FlexibleControlsOptions';
Expand All @@ -17,7 +17,14 @@ import {
getPixelCoordinatesFromEvent
} from '@reveal/utilities';

import { CameraEventDelegate, CameraManagerCallbackData, CameraManagerEventType, CameraState } from './../types';
import {
CameraEventDelegate,
CameraFarBuffers,
CameraManagerCallbackData,
CameraManagerEventType,
CameraState,
NearAndFarPlaneBuffers
} from './../types';
import { CameraManagerHelper } from './../CameraManagerHelper';
import { CameraManager } from './../CameraManager';
import { FlexibleControlsType } from './FlexibleControlsType';
Expand Down Expand Up @@ -49,6 +56,28 @@ export class FlexibleCameraManager extends PointerEvents implements IFlexibleCam
private _nearAndFarNeedsUpdate = false;
private readonly _raycastCallback: RaycastCallback;
private readonly _haveEventListeners: boolean;
/**
* Reusable buffers used by updateNearAndFarPlane function to avoid allocations.
*/
private readonly _updateNearAndFarPlaneBuffers: NearAndFarPlaneBuffers = {
cameraPosition: new Vector3(),
cameraDirection: new Vector3(),
corners: new Array<Vector3>(
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3()
)
};

private readonly _calculateCameraFarBuffers: CameraFarBuffers = {
nearPlaneCoplanarPoint: new Vector3(),
nearPlane: new Plane()
};

//================================================
// CONSTRUCTOR
Expand Down Expand Up @@ -470,7 +499,12 @@ export class FlexibleCameraManager extends PointerEvents implements IFlexibleCam
if (!this.options.automaticNearFarPlane) {
return;
}
CameraManagerHelper.updateCameraNearAndFar(this.camera, boundingBox);
CameraManagerHelper.updateCameraNearAndFar(
this.camera,
boundingBox,
this._updateNearAndFarPlaneBuffers,
this._calculateCameraFarBuffers
);
}

private updateControlsSensitivity(boundingBox: Box3): void {
Expand Down
36 changes: 33 additions & 3 deletions viewer/packages/camera-manager/src/StationaryCameraManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* Copyright 2022 Cognite AS
*/
import { Box3, Euler, MathUtils, PerspectiveCamera, Quaternion, Vector3 } from 'three';
import { Box3, Euler, MathUtils, PerspectiveCamera, Plane, Quaternion, Vector3 } from 'three';

import TWEEN from '@tweenjs/tween.js';

Expand All @@ -13,9 +13,11 @@ import { CameraManagerHelper } from './CameraManagerHelper';
import {
CameraChangeDelegate,
CameraEventDelegate,
CameraFarBuffers,
CameraManagerEventType,
CameraState,
CameraStopDelegate
CameraStopDelegate,
NearAndFarPlaneBuffers
} from './types';
import { DebouncedCameraStopEventTrigger } from './utils/DebouncedCameraStopEventTrigger';
import { assertNever, getNormalizedPixelCoordinatesBySize, getPixelCoordinatesFromEvent } from '@reveal/utilities';
Expand All @@ -30,6 +32,29 @@ export class StationaryCameraManager implements CameraManager {
private _isDragging = false;
private _pointerEventCache: Array<PointerEvent> = [];

/**
* Reusable buffers used by updateNearAndFarPlane function to avoid allocations.
*/
private readonly _updateNearAndFarPlaneBuffers: NearAndFarPlaneBuffers = {
cameraPosition: new Vector3(),
cameraDirection: new Vector3(),
corners: new Array<Vector3>(
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3(),
new Vector3()
)
};

private readonly _calculateCameraFarBuffers: CameraFarBuffers = {
nearPlaneCoplanarPoint: new Vector3(),
nearPlane: new Plane()
};

constructor(domElement: HTMLElement, camera: PerspectiveCamera) {
this._domElement = domElement;
this._camera = camera;
Expand Down Expand Up @@ -156,7 +181,12 @@ export class StationaryCameraManager implements CameraManager {
}

update(_: number, boundingBox: Box3): void {
CameraManagerHelper.updateCameraNearAndFar(this._camera, boundingBox);
CameraManagerHelper.updateCameraNearAndFar(
this._camera,
boundingBox,
this._updateNearAndFarPlaneBuffers,
this._calculateCameraFarBuffers
);
}

dispose(): void {
Expand Down
12 changes: 12 additions & 0 deletions viewer/packages/camera-manager/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright 2021 Cognite AS
*/

import { Plane } from 'three';
import type { Box3, EventDispatcher, Quaternion, Vector3 } from 'three';

export type ControlsState = {
Expand Down Expand Up @@ -106,3 +107,14 @@ export const CAMERA_MANAGER_EVENT_TYPE_LIST = ['cameraChange', 'cameraStop'] as
* Union type of the supported camera manager event types
*/
export type CameraManagerEventType = (typeof CAMERA_MANAGER_EVENT_TYPE_LIST)[number];

export type NearAndFarPlaneBuffers = {
corners: Vector3[];
cameraPosition: Vector3;
cameraDirection: Vector3;
};
haakonflatval-cognite marked this conversation as resolved.
Show resolved Hide resolved
haakonflatval-cognite marked this conversation as resolved.
Show resolved Hide resolved

export type CameraFarBuffers = {
nearPlane: Plane;
nearPlaneCoplanarPoint: Vector3;
};
Loading