@itwin/core-common
Version:
iTwin.js components common to frontend and backend
98 lines • 3.36 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Rendering
*/
import { Vector3d } from "@itwin/core-geometry";
const scratchUInt16 = new Uint16Array(1);
function clamp(val, minVal, maxVal) {
return val < minVal ? minVal : (val > maxVal ? maxVal : val);
}
function clampUint8(val) {
return roundUint16(0.5 + (clamp(val, -1, 1) * 0.5 + 0.5) * 255);
}
function roundUint16(val) {
scratchUInt16[0] = val;
return scratchUInt16[0];
}
function signNotZero(val) {
return val < 0.0 ? -1.0 : 1.0;
}
/** Represents a 3d normal vector compressed into a single 16-bit integer using [oct-encoding](http://jcgt.org/published/0003/02/01/paper.pdf).
* These are chiefly used to reduce the space required to store normal vectors for [RenderGraphic]($frontend)s.
* @public
*/
export class OctEncodedNormal {
/** The encoded normal. */
value;
/** Construct directly from a 16-bit encoded value.
* @see [[encode]] to compute the encoded value.
* @see [[fromVector]] to construct from a vector.
*/
constructor(val) {
this.value = roundUint16(val);
}
/** Compute the encoded 16-bit value of the supplied normalized vector. */
static encode(vec) {
return this.encodeXYZ(vec.x, vec.y, vec.z);
}
/** Compute the encoded 16-bit value of the supplied normalized vector components. */
static encodeXYZ(nx, ny, nz) {
const denom = Math.abs(nx) + Math.abs(ny) + Math.abs(nz);
let rx = nx / denom;
let ry = ny / denom;
if (nz < 0) {
const x = rx;
const y = ry;
rx = (1 - Math.abs(y)) * signNotZero(x);
ry = (1 - Math.abs(x)) * signNotZero(y);
}
return clampUint8(ry) << 8 | clampUint8(rx);
}
/** Create an OctEncodedNormal from a normalized vector. */
static fromVector(val) {
return new OctEncodedNormal(this.encode(val));
}
/** Decode this oct-encoded normal into a normalized vector. */
decode() {
return OctEncodedNormal.decodeValue(this.value);
}
/** Decode a 16-bit encoded value into a normalized vector. */
static decodeValue(val, result) {
let ex = val & 0xff;
let ey = val >> 8;
ex = ex / 255.0 * 2.0 - 1.0;
ey = ey / 255.0 * 2.0 - 1.0;
const ez = 1 - (Math.abs(ex) + Math.abs(ey));
let n;
if (result === undefined) {
n = new Vector3d(ex, ey, ez);
}
else {
n = result;
n.x = ex;
n.y = ey;
n.z = ez;
}
if (n.z < 0) {
const x = n.x;
const y = n.y;
n.x = (1 - Math.abs(y)) * signNotZero(x);
n.y = (1 - Math.abs(x)) * signNotZero(y);
}
n.normalizeInPlace();
return n;
}
}
/** @internal */
export class OctEncodedNormalPair {
first;
second;
constructor(first, second) {
this.first = first;
this.second = second;
}
}
//# sourceMappingURL=OctEncodedNormal.js.map