Skip to content

Commit 6664d5e

Browse files
authored
New option to compute the z-index of HTML objects logarithmicly (#79)
* Implement logarithmic depth for z-index calculation * Add the logarithmicDepth option to HtmlContent
1 parent 729cdc1 commit 6664d5e

2 files changed

Lines changed: 20 additions & 6 deletions

File tree

libs/soba/misc/src/lib/html/html-content.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ export interface NgtsHTMLContentOptions {
123123
* Defaults to the canvas container or `events.connected` element.
124124
*/
125125
parent?: HTMLElement | ElementRef<HTMLElement>;
126+
/**
127+
* Computes z-index with a logarithmic scale, which prevents
128+
* near objects from all having the same z-index when
129+
* camera.far is very large.
130+
*/
131+
logarithmicDepth?: boolean;
126132
}
127133

128134
const defaultHtmlContentOptions: NgtsHTMLContentOptions = {
@@ -354,7 +360,7 @@ export class NgtsHTMLContent extends NgtHTML {
354360
occlusionGeometry,
355361
isRaycastOcclusion,
356362
{ camera, size, viewport, raycaster, scene },
357-
{ calculatePosition, eps, zIndexRange, sprite, distanceFactor },
363+
{ calculatePosition, eps, zIndexRange, logarithmicDepth, sprite, distanceFactor },
358364
{ transform, occlude, scale },
359365
] = [
360366
this.host.nativeElement,
@@ -432,7 +438,7 @@ export class NgtsHTMLContent extends NgtHTML {
432438
: [halfRange - 1, 0]
433439
: zIndexRange;
434440

435-
renderer.setStyle(hostEl, 'z-index', `${objectZIndex(group, camera, zRange)}`);
441+
renderer.setStyle(hostEl, 'z-index', `${objectZIndex(group, camera, zRange, logarithmicDepth)}`);
436442

437443
if (transform) {
438444
const [widthHalf, heightHalf] = [size.width / 2, size.height / 2];

libs/soba/misc/src/lib/html/utils.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,27 @@ export function objectScale(el: THREE.Object3D, camera: THREE.Camera) {
119119
* @param el - The object to calculate z-index for
120120
* @param camera - The camera reference (must be Perspective or Orthographic)
121121
* @param zIndexRange - `[max, min]` range to map distance to
122+
* @param logarithmicDepth - Computes the z-index logarithmicly to enable a wider camera range
122123
* @returns Calculated z-index, or `undefined` for unsupported camera types
123124
*/
124-
export function objectZIndex(el: THREE.Object3D, camera: THREE.Camera, zIndexRange: Array<number>) {
125+
export function objectZIndex(el: THREE.Object3D, camera: THREE.Camera, zIndexRange: Array<number>, logarithmicDepth = false) {
125126
if (
126127
is.three<THREE.PerspectiveCamera>(camera, 'isPerspectiveCamera') ||
127128
is.three<THREE.OrthographicCamera>(camera, 'isOrthographicCamera')
128129
) {
129130
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
130131
const cameraPos = v2.setFromMatrixPosition(camera.matrixWorld);
131132
const dist = objectPos.distanceTo(cameraPos);
132-
const A = (zIndexRange[1] - zIndexRange[0]) / (camera.far - camera.near);
133-
const B = zIndexRange[1] - A * camera.far;
134-
return Math.round(A * dist + B);
133+
if (logarithmicDepth) {
134+
const safeNear = Math.max(camera.near, 1e-6);
135+
const safeDist = Math.max(dist, 1e-6);
136+
const depth = Math.log(safeDist / safeNear) / Math.log(camera.far / safeNear);
137+
return Math.round(zIndexRange[0] + depth * (zIndexRange[1] - zIndexRange[0]));
138+
} else {
139+
const A = (zIndexRange[1] - zIndexRange[0]) / (camera.far - camera.near);
140+
const B = zIndexRange[1] - A * camera.far;
141+
return Math.round(A * dist + B);
142+
}
135143
}
136144
return undefined;
137145
}

0 commit comments

Comments
 (0)