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

(fix): Update recalculateBoundingBox in Cognite3DViewer #4715

Merged
merged 12 commits into from
Aug 29, 2024
120 changes: 92 additions & 28 deletions viewer/packages/api/src/public/migration/Cognite3DViewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,45 @@ export class Cognite3DViewer {
return this._boundingBoxes.sceneBoundingBox;
}

/**
* Get the union of bounding box of all visual objects in the Cognite3DViewer.
* @returns The visual bounding box of the Cognite3DViewer.
* @beta
*/
getVisualSceneBoundingBox(): THREE.Box3 {
const boundingBox = new THREE.Box3();
boundingBox.makeEmpty();

if (this.isDisposed) {
return boundingBox;
}
const temporaryBox = new THREE.Box3();
for (const model of this.models) {
if (!model.visible) {
continue;
}
model.getModelBoundingBox(temporaryBox, true);
if (temporaryBox.isEmpty()) {
continue;
}
boundingBox.union(temporaryBox);
}
for (const customObject of this._sceneHandler.customObjects) {
if (!customObject.object.visible) {
continue;
}
customObject.getBoundingBox(temporaryBox);
if (temporaryBox.isEmpty()) {
continue;
}
if (!customObject.isPartOfBoundingBox) {
continue;
}
boundingBox.union(temporaryBox);
}
return boundingBox;
}

/**
* Attempts to load the camera settings from the settings stored for the
* provided model. See {@link https://docs.cognite.com/api/v1/#operation/get3DRevision}
Expand Down Expand Up @@ -1257,6 +1296,9 @@ export class Cognite3DViewer {
*/
fitCameraToModel(model: CogniteModel, duration?: number): void {
const boundingBox = model.getModelBoundingBox(new THREE.Box3(), true);
if (boundingBox.isEmpty()) {
return;
}
this._activeCameraManager.fitCameraToBoundingBox(boundingBox, duration);
}

Expand All @@ -1268,7 +1310,6 @@ export class Cognite3DViewer {
*/
fitCameraToModels(models?: CogniteModel[], duration?: number, restrictToMostGeometry = false): void {
const cogniteModels = models ?? this.models;

if (cogniteModels.length < 1) {
return;
}
Expand All @@ -1281,9 +1322,18 @@ export class Cognite3DViewer {
this.fitCameraToBoundingBox(boundingBox, duration);
}

/**
* Move camera to a place where a all objects in the scene are visible.
* @param duration The duration of the animation moving the camera. Set this to 0 (zero) to disable animation.
*/
fitCameraToVisualSceneBoundingBox(duration?: number): void {
const boundingBox = this.getVisualSceneBoundingBox();
this.fitCameraToBoundingBox(boundingBox, duration);
}

/**
* Move camera to a place where the content of a bounding box is visible to the camera.
* @param box The bounding box in world space.
* @param boundingBox The bounding box in world space.
* @param duration The duration of the animation moving the camera. Set this to 0 (zero) to disable animation.
* @param radiusFactor The ratio of the distance from camera to center of box and radius of the box.
* @example
Expand All @@ -1300,8 +1350,11 @@ export class Cognite3DViewer {
* viewer.fitCameraToBoundingBox(boundingBox, 500, 2);
* ```
*/
fitCameraToBoundingBox(box: THREE.Box3, duration?: number, radiusFactor: number = 2): void {
this._activeCameraManager.fitCameraToBoundingBox(box, duration, radiusFactor);
fitCameraToBoundingBox(boundingBox: THREE.Box3, duration?: number, radiusFactor: number = 2): void {
if (boundingBox.isEmpty()) {
return;
}
this._activeCameraManager.fitCameraToBoundingBox(boundingBox, duration, radiusFactor);
}

/**
Expand Down Expand Up @@ -1880,34 +1933,45 @@ export class Cognite3DViewer {
nearFarPlaneBoundingBox.makeEmpty();
sceneBoundingBox.makeEmpty();

this._models.forEach(model => {
model.getModelBoundingBox(temporaryBox);
if (temporaryBox.isEmpty()) {
return;
}
nearFarPlaneBoundingBox.union(temporaryBox);
for (let pass = 0; pass < 2; pass++) {
// On the first pass, use visible models only
// If no bounding box is found, use all models on the second pass
// By this way, a bounding box is forced to be calculated
for (const model of this.models) {
if (pass === 0 && !model.visible) {
continue;
}
model.getModelBoundingBox(temporaryBox);
if (temporaryBox.isEmpty()) {
continue;
}
nearFarPlaneBoundingBox.union(temporaryBox);

// The getModelBoundingBox is using restrictToMostGeometry = true
model.getModelBoundingBox(temporaryBox, true);
if (temporaryBox.isEmpty()) {
return;
}
sceneBoundingBox.union(temporaryBox);
});
this._sceneHandler.customObjects.forEach(customObject => {
if (!customObject.object.visible) {
return;
// The getModelBoundingBox is using restrictToMostGeometry = true
model.getModelBoundingBox(temporaryBox, true);
if (temporaryBox.isEmpty()) {
continue;
}
sceneBoundingBox.union(temporaryBox);
}
customObject.getBoundingBox(temporaryBox);
if (temporaryBox.isEmpty()) {
return;
for (const customObject of this._sceneHandler.customObjects) {
if (!customObject.object.visible) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to have the pass === 0-check here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't have that from before. It always used the visible object in these cases.

continue;
}
customObject.getBoundingBox(temporaryBox);
if (temporaryBox.isEmpty()) {
continue;
}
nearFarPlaneBoundingBox.union(temporaryBox);
if (!customObject.isPartOfBoundingBox) {
continue;
}
sceneBoundingBox.union(temporaryBox);
}
nearFarPlaneBoundingBox.union(temporaryBox);
if (!customObject.isPartOfBoundingBox) {
return;
if (!sceneBoundingBox.isEmpty()) {
break;
}
sceneBoundingBox.union(temporaryBox);
});
}
}

/** @private */
Expand Down
5 changes: 4 additions & 1 deletion viewer/reveal.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,10 @@ export class Cognite3DViewer {
get domElement(): HTMLElement;
enter360Image(image360: Image360, revision?: Image360Revision): Promise<void>;
exit360Image(): void;
fitCameraToBoundingBox(box: THREE.Box3, duration?: number, radiusFactor?: number): void;
fitCameraToBoundingBox(boundingBox: THREE.Box3, duration?: number, radiusFactor?: number): void;
fitCameraToModel(model: CogniteModel, duration?: number): void;
fitCameraToModels(models?: CogniteModel[], duration?: number, restrictToMostGeometry?: boolean): void;
fitCameraToVisualSceneBoundingBox(duration?: number): void;
get360AnnotationIntersectionFromPixel(offsetX: number, offsetY: number): Promise<null | Image360AnnotationIntersection>;
get360ImageCollections(): Image360Collection[];
getActive360ImageInfo(): Image360WithCollection | undefined;
Expand All @@ -457,6 +458,8 @@ export class Cognite3DViewer {
getScreenshot(width?: number, height?: number, includeUI?: boolean): Promise<string>;
getVersion(): string;
getViewState(): ViewerState;
// @beta
getVisualSceneBoundingBox(): THREE.Box3;
loadCameraFromModel(model: CogniteModel): void;
get models(): CogniteModel[];
// (undocumented)
Expand Down
Loading