@loaders.gl/math
Advanced tools
Comparing version 4.2.0-alpha.4 to 4.2.0-alpha.5
import { makeAttributeIterator } from "../iterators/attribute-iterator.js"; | ||
import { assert } from "../utils/assert.js"; | ||
export function computeBoundingBox() { | ||
let positions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; | ||
const min = [Number(Infinity), Number(Infinity), Number(Infinity)]; | ||
const max = [-Infinity, -Infinity, -Infinity]; | ||
for (const position of makeAttributeIterator(positions)) { | ||
const x = position[0]; | ||
const y = position[1]; | ||
const z = position[2]; | ||
if (x < min[0]) min[0] = x; | ||
if (y < min[1]) min[1] = y; | ||
if (z < min[2]) min[2] = z; | ||
if (x > max[0]) max[0] = x; | ||
if (y > max[1]) max[1] = y; | ||
if (z > max[2]) max[2] = z; | ||
} | ||
const boundingBox = { | ||
min, | ||
max | ||
}; | ||
validateBoundingBox(boundingBox); | ||
return boundingBox; | ||
/** | ||
* Getting bounding box geometry according to positions parameters | ||
* @param positions | ||
* @returns Bounding Box | ||
*/ | ||
export function computeBoundingBox(positions = []) { | ||
const min = [Number(Infinity), Number(Infinity), Number(Infinity)]; | ||
const max = [-Infinity, -Infinity, -Infinity]; | ||
// @ts-ignore | ||
for (const position of makeAttributeIterator(positions)) { | ||
const x = position[0]; | ||
const y = position[1]; | ||
const z = position[2]; | ||
if (x < min[0]) | ||
min[0] = x; | ||
if (y < min[1]) | ||
min[1] = y; | ||
if (z < min[2]) | ||
min[2] = z; | ||
if (x > max[0]) | ||
max[0] = x; | ||
if (y > max[1]) | ||
max[1] = y; | ||
if (z > max[2]) | ||
max[2] = z; | ||
} | ||
const boundingBox = { min, max }; | ||
validateBoundingBox(boundingBox); | ||
return boundingBox; | ||
} | ||
function validateBoundingBox(boundingBox) { | ||
assert(Number.isFinite(boundingBox.min[0]) && Number.isFinite(boundingBox.min[1]) && Number.isFinite(boundingBox.min[2]) && Number.isFinite(boundingBox.max[0]) && Number.isFinite(boundingBox.max[1]) && Number.isFinite(boundingBox.max[2])); | ||
assert(Number.isFinite(boundingBox.min[0]) && | ||
Number.isFinite(boundingBox.min[1]) && | ||
Number.isFinite(boundingBox.min[2]) && | ||
Number.isFinite(boundingBox.max[0]) && | ||
Number.isFinite(boundingBox.max[1]) && | ||
Number.isFinite(boundingBox.max[2])); | ||
} | ||
//# sourceMappingURL=compute-bounding-box.js.map |
@@ -0,2 +1,30 @@ | ||
"use strict"; | ||
/* eslint-disable */ | ||
/** | ||
import {getPositions} from './get-attribute-from-geometry'; | ||
//# sourceMappingURL=compute-bounding-sphere.js.map | ||
export function computeBoundingSphere(geometry: any, boundingBox: object, vector: Vector3 ) { | ||
const positions = getPositions(geometry); | ||
const center = getBoundingBox(center); | ||
box.setFromBufferAttribute(position); | ||
box.getCenter(center); | ||
// hoping to find a boundingSphere with a radius smaller than the | ||
// boundingSphere of the boundingBox: sqrt(3) smaller in the best case | ||
var maxRadiusSq = 0; | ||
for (const position of makeAttributeIterator(positions)) { | ||
vector.x = position[0]; | ||
vector.y = position[1]; | ||
vector.z = position[2]; | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); | ||
} | ||
const radius = Math.sqrt(maxRadiusSq); | ||
assert(Number.isFinite(radius)); | ||
return {center, radius}; | ||
} | ||
*/ |
@@ -0,2 +1,146 @@ | ||
"use strict"; | ||
/* | ||
export function computeTangents({indices, positions, normals, uvs}) { | ||
var index = geometry.index; | ||
var attributes = geometry.attributes; | ||
//# sourceMappingURL=compute-tangents.js.map | ||
// based on http://www.terathon.com/code/tangent.html | ||
// (per vertex tangents) | ||
if ( | ||
index === null || | ||
attributes.position === undefined || | ||
attributes.normal === undefined || | ||
attributes.uv === undefined | ||
) { | ||
console.warn( | ||
'THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' | ||
); | ||
return; | ||
} | ||
var nVertices = positions.length / 3; | ||
var tangents = new Float32Array(4 * nVertices); // size: 4 | ||
var tan1 = [], | ||
tan2 = []; | ||
for (var k = 0; k < nVertices; k++) { | ||
tan1[k] = new THREE.Vector3(); | ||
tan2[k] = new THREE.Vector3(); | ||
} | ||
var vA = new THREE.Vector3(), | ||
vB = new THREE.Vector3(), | ||
vC = new THREE.Vector3(), | ||
uvA = new THREE.Vector2(), | ||
uvB = new THREE.Vector2(), | ||
uvC = new THREE.Vector2(), | ||
sdir = new THREE.Vector3(), | ||
tdir = new THREE.Vector3(); | ||
function handleTriangle(a, b, c) { | ||
vA.fromArray(positions, a * 3); | ||
vB.fromArray(positions, b * 3); | ||
vC.fromArray(positions, c * 3); | ||
uvA.fromArray(uvs, a * 2); | ||
uvB.fromArray(uvs, b * 2); | ||
uvC.fromArray(uvs, c * 2); | ||
var x1 = vB.x - vA.x; | ||
var x2 = vC.x - vA.x; | ||
var y1 = vB.y - vA.y; | ||
var y2 = vC.y - vA.y; | ||
var z1 = vB.z - vA.z; | ||
var z2 = vC.z - vA.z; | ||
var s1 = uvB.x - uvA.x; | ||
var s2 = uvC.x - uvA.x; | ||
var t1 = uvB.y - uvA.y; | ||
var t2 = uvC.y - uvA.y; | ||
var r = 1.0 / (s1 * t2 - s2 * t1); | ||
sdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); | ||
tdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); | ||
tan1[a].add(sdir); | ||
tan1[b].add(sdir); | ||
tan1[c].add(sdir); | ||
tan2[a].add(tdir); | ||
tan2[b].add(tdir); | ||
tan2[c].add(tdir); | ||
} | ||
var groups = geometry.groups; | ||
if (groups.length === 0) { | ||
groups = [ | ||
{ | ||
start: 0, | ||
count: indices.length | ||
} | ||
]; | ||
} | ||
for (var j = 0, jl = groups.length; j < jl; ++j) { | ||
var group = groups[j]; | ||
var start = group.start; | ||
var count = group.count; | ||
for (var i = start, il = start + count; i < il; i += 3) { | ||
handleTriangle(indices[i + 0], indices[i + 1], indices[i + 2]); | ||
} | ||
} | ||
var tmp = new THREE.Vector3(), | ||
tmp2 = new THREE.Vector3(); | ||
var n = new THREE.Vector3(), | ||
n2 = new THREE.Vector3(); | ||
var w, t, test; | ||
function handleVertex(v) { | ||
n.fromArray(normals, v * 3); | ||
n2.copy(n); | ||
t = tan1[v]; | ||
// Gram-Schmidt orthogonalize | ||
tmp.copy(t); | ||
tmp.sub(n.multiplyScalar(n.dot(t))).normalize(); | ||
// Calculate handedness | ||
tmp2.crossVectors(n2, t); | ||
test = tmp2.dot(tan2[v]); | ||
w = test < 0.0 ? -1.0 : 1.0; | ||
tangents[v * 4] = tmp.x; | ||
tangents[v * 4 + 1] = tmp.y; | ||
tangents[v * 4 + 2] = tmp.z; | ||
tangents[v * 4 + 3] = w; | ||
} | ||
for (var j = 0, jl = groups.length; j < jl; ++j) { | ||
var group = groups[j]; | ||
var start = group.start; | ||
var count = group.count; | ||
for (var i = start, il = start + count; i < il; i += 3) { | ||
handleVertex(indices[i + 0]); | ||
handleVertex(indices[i + 1]); | ||
handleVertex(indices[i + 2]); | ||
} | ||
} | ||
} | ||
*/ |
@@ -7,36 +7,39 @@ import { Vector3 } from '@math.gl/core'; | ||
import { getPositions } from "./get-attribute-from-geometry.js"; | ||
/** | ||
* Computes vertex normals for a geometry | ||
* @param param0 | ||
* @returns | ||
*/ | ||
// eslint-disable-next-line max-statements | ||
export function computeVertexNormals(geometry) { | ||
assert(getPrimitiveModeType(geometry.mode) === GL.TRIANGLES, 'TRIANGLES required'); | ||
const { | ||
values: positions | ||
} = getPositions(geometry); | ||
const normals = new Float32Array(positions.length); | ||
const vectorA = new Vector3(); | ||
const vectorB = new Vector3(); | ||
const vectorC = new Vector3(); | ||
const vectorCB = new Vector3(); | ||
const vectorAB = new Vector3(); | ||
for (const primitive of makePrimitiveIterator(geometry)) { | ||
vectorA.fromArray(positions, primitive.i1 * 3); | ||
vectorB.fromArray(positions, primitive.i2 * 3 + 3); | ||
vectorC.fromArray(positions, primitive.i3 * 3 + 6); | ||
vectorCB.subVectors(vectorC, vectorB); | ||
vectorAB.subVectors(vectorA, vectorB); | ||
const normal = vectorCB.cross(vectorAB); | ||
normal.normalize(); | ||
const { | ||
primitiveIndex | ||
} = primitive; | ||
normals[primitiveIndex * 9 + 0] = normal.x; | ||
normals[primitiveIndex * 9 + 1] = normal.y; | ||
normals[primitiveIndex * 9 + 2] = normal.z; | ||
normals[primitiveIndex * 9 + 3] = normal.x; | ||
normals[primitiveIndex * 9 + 4] = normal.y; | ||
normals[primitiveIndex * 9 + 5] = normal.z; | ||
normals[primitiveIndex * 9 + 6] = normal.x; | ||
normals[primitiveIndex * 9 + 7] = normal.y; | ||
normals[primitiveIndex * 9 + 8] = normal.z; | ||
} | ||
return normals; | ||
// Only support GL.TRIANGLES, GL.TRIANGLE_STRIP, GL.TRIANGLE_FAN | ||
assert(getPrimitiveModeType(geometry.mode) === GL.TRIANGLES, 'TRIANGLES required'); | ||
const { values: positions } = getPositions(geometry); | ||
const normals = new Float32Array(positions.length); | ||
const vectorA = new Vector3(); | ||
const vectorB = new Vector3(); | ||
const vectorC = new Vector3(); | ||
const vectorCB = new Vector3(); | ||
const vectorAB = new Vector3(); | ||
for (const primitive of makePrimitiveIterator(geometry)) { | ||
vectorA.fromArray(positions, primitive.i1 * 3); | ||
vectorB.fromArray(positions, primitive.i2 * 3 + 3); | ||
vectorC.fromArray(positions, primitive.i3 * 3 + 6); | ||
vectorCB.subVectors(vectorC, vectorB); | ||
vectorAB.subVectors(vectorA, vectorB); | ||
const normal = vectorCB.cross(vectorAB); | ||
normal.normalize(); | ||
// @ts-ignore | ||
const { primitiveIndex } = primitive; | ||
normals[primitiveIndex * 9 + 0] = normal.x; | ||
normals[primitiveIndex * 9 + 1] = normal.y; | ||
normals[primitiveIndex * 9 + 2] = normal.z; | ||
normals[primitiveIndex * 9 + 3] = normal.x; | ||
normals[primitiveIndex * 9 + 4] = normal.y; | ||
normals[primitiveIndex * 9 + 5] = normal.z; | ||
normals[primitiveIndex * 9 + 6] = normal.x; | ||
normals[primitiveIndex * 9 + 7] = normal.y; | ||
normals[primitiveIndex * 9 + 8] = normal.z; | ||
} | ||
return normals; | ||
} | ||
//# sourceMappingURL=compute-vertex-normals.js.map |
@@ -1,27 +0,29 @@ | ||
export function convertBuffersToNonIndexed(_ref) { | ||
let { | ||
indices, | ||
attributes | ||
} = _ref; | ||
const geometry2 = new BufferGeometry(); | ||
for (const name in attributes) { | ||
const attribute = attributes[name]; | ||
const array = attribute.array; | ||
const itemSize = attribute.itemSize; | ||
const array2 = new array.constructor(indices.length * itemSize); | ||
let index = 0, | ||
index2 = 0; | ||
for (var i = 0, l = indices.length; i < l; i++) { | ||
index = indices[i] * itemSize; | ||
for (var j = 0; j < itemSize; j++) { | ||
array2[index2++] = array[index++]; | ||
} | ||
/* eslint-disable */ | ||
// @ts-nocheck | ||
/** | ||
* Converts indices of geometry. | ||
* | ||
* @param param0 | ||
* @returns no indexed geometry | ||
*/ | ||
export function convertBuffersToNonIndexed({ indices, attributes }) { | ||
const geometry2 = new BufferGeometry(); | ||
for (const name in attributes) { | ||
const attribute = attributes[name]; | ||
const array = attribute.array; | ||
const itemSize = attribute.itemSize; | ||
const array2 = new array.constructor(indices.length * itemSize); | ||
let index = 0, index2 = 0; | ||
for (var i = 0, l = indices.length; i < l; i++) { | ||
index = indices[i] * itemSize; | ||
for (var j = 0; j < itemSize; j++) { | ||
array2[index2++] = array[index++]; | ||
} | ||
} | ||
geometry2.addAttribute(name, new BufferAttribute(array2, itemSize)); | ||
} | ||
geometry2.addAttribute(name, new BufferAttribute(array2, itemSize)); | ||
} | ||
for (const group of this.groups) { | ||
geometry2.addGroup(group.start, group.count, group.materialIndex); | ||
} | ||
return geometry2; | ||
for (const group of this.groups) { | ||
geometry2.addGroup(group.start, group.count, group.materialIndex); | ||
} | ||
return geometry2; | ||
} | ||
//# sourceMappingURL=convert-to-non-indexed.js.map |
import isGeometry from "../is-geometry.js"; | ||
import { assert } from "../utils/assert.js"; | ||
/** | ||
* analyze positions of geometry | ||
* | ||
* @param geometry | ||
* @returns Position| New geometry |assert | ||
*/ | ||
export function getPositions(geometry) { | ||
if (isGeometry(geometry)) { | ||
const { | ||
attributes | ||
} = geometry; | ||
const position = attributes.POSITION || attributes.positions; | ||
assert(position); | ||
return position; | ||
} | ||
if (ArrayBuffer.isView(geometry)) { | ||
return { | ||
values: geometry, | ||
size: 3 | ||
}; | ||
} | ||
if (geometry) { | ||
assert(geometry.values); | ||
return geometry; | ||
} | ||
return assert(false); | ||
// If geometry, extract positions | ||
if (isGeometry(geometry)) { | ||
const { attributes } = geometry; | ||
const position = attributes.POSITION || attributes.positions; | ||
assert(position); | ||
return position; | ||
} | ||
// If arraybuffer, assume 3 components | ||
if (ArrayBuffer.isView(geometry)) { | ||
return { values: geometry, size: 3 }; | ||
} | ||
// Else assume accessor object | ||
if (geometry) { | ||
assert(geometry.values); | ||
return geometry; | ||
} | ||
return assert(false); | ||
} | ||
//# sourceMappingURL=get-attribute-from-geometry.js.map |
@@ -1,13 +0,16 @@ | ||
export function normalize() { | ||
let normals = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
let vector = arguments.length > 1 ? arguments[1] : undefined; | ||
normals = this.attributes.normal; | ||
for (let i = 0, il = normals.count; i < il; i++) { | ||
vector.x = normals.getX(i); | ||
vector.y = normals.getY(i); | ||
vector.z = normals.getZ(i); | ||
vector.normalize(); | ||
normals.setXYZ(i, vector.x, vector.y, vector.z); | ||
} | ||
/** | ||
* Setting X, Y, Z for Vector | ||
* @param normals | ||
* @param vector | ||
*/ | ||
export function normalize(normals = {}, vector) { | ||
//@ts-ignore | ||
normals = this.attributes.normal; | ||
for (let i = 0, il = normals.count; i < il; i++) { | ||
vector.x = normals.getX(i); | ||
vector.y = normals.getY(i); | ||
vector.z = normals.getZ(i); | ||
vector.normalize(); | ||
normals.setXYZ(i, vector.x, vector.y, vector.z); | ||
} | ||
} | ||
//# sourceMappingURL=normalize.js.map |
@@ -1,17 +0,26 @@ | ||
export function decodeRGB565(rgb565) { | ||
let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0, 0, 0]; | ||
const r5 = rgb565 >> 11 & 31; | ||
const g6 = rgb565 >> 5 & 63; | ||
const b5 = rgb565 & 31; | ||
target[0] = r5 << 3; | ||
target[1] = g6 << 2; | ||
target[2] = b5 << 3; | ||
return target; | ||
/** | ||
* Decode color values | ||
* @param rgb565 | ||
* @param target | ||
* @returns target | ||
*/ | ||
export function decodeRGB565(rgb565, target = [0, 0, 0]) { | ||
const r5 = (rgb565 >> 11) & 31; | ||
const g6 = (rgb565 >> 5) & 63; | ||
const b5 = rgb565 & 31; | ||
target[0] = r5 << 3; | ||
target[1] = g6 << 2; | ||
target[2] = b5 << 3; | ||
return target; | ||
} | ||
/** | ||
* Encode color values | ||
* @param rgb | ||
* @returns color | ||
*/ | ||
export function encodeRGB565(rgb) { | ||
const r5 = Math.floor(rgb[0] / 8) + 4; | ||
const g6 = Math.floor(rgb[1] / 4) + 2; | ||
const b5 = Math.floor(rgb[2] / 8) + 4; | ||
return r5 + (g6 << 5) + (b5 << 11); | ||
const r5 = Math.floor(rgb[0] / 8) + 4; | ||
const g6 = Math.floor(rgb[1] / 4) + 2; | ||
const b5 = Math.floor(rgb[2] / 8) + 4; | ||
return r5 + (g6 << 5) + (b5 << 11); | ||
} | ||
//# sourceMappingURL=rgb565.js.map |
@@ -0,1 +1,4 @@ | ||
// This file is derived from the Cesium code base under Apache 2 license | ||
// See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md | ||
// Attribute compression and decompression functions. | ||
import { Vector2, Vector3, clamp, _MathUtils } from '@math.gl/core'; | ||
@@ -10,151 +13,324 @@ import { assert } from "../utils/assert.js"; | ||
const uint8ForceArray = new Uint8Array(1); | ||
/** | ||
* Force a value to Uint8 | ||
* | ||
* @param value | ||
* @returns | ||
*/ | ||
function forceUint8(value) { | ||
uint8ForceArray[0] = value; | ||
return uint8ForceArray[0]; | ||
uint8ForceArray[0] = value; | ||
return uint8ForceArray[0]; | ||
} | ||
function fromSNorm(value) { | ||
let rangeMaximum = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 255; | ||
return clamp(value, 0.0, rangeMaximum) / rangeMaximum * 2.0 - 1.0; | ||
/** | ||
* Converts a SNORM value in the range [0, rangeMaximum] to a scalar in the range [-1.0, 1.0]. | ||
* | ||
* @param value SNORM value in the range [0, rangeMaximum] | ||
* @param [rangeMaximum=255] The maximum value in the SNORM range, 255 by default. | ||
* @returns Scalar in the range [-1.0, 1.0]. | ||
* | ||
* @see CesiumMath.toSNorm | ||
*/ | ||
function fromSNorm(value, rangeMaximum = 255) { | ||
return (clamp(value, 0.0, rangeMaximum) / rangeMaximum) * 2.0 - 1.0; | ||
} | ||
function toSNorm(value) { | ||
let rangeMaximum = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 255; | ||
return Math.round((clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMaximum); | ||
/** | ||
* Converts a scalar value in the range [-1.0, 1.0] to a SNORM in the range [0, rangeMaximum]. | ||
* | ||
* @param value The scalar value in the range [-1.0, 1.0] | ||
* @param [rangeMaximum=255] The maximum value in the mapped range, 255 by default. | ||
* @returns A SNORM value, where 0 maps to -1.0 and rangeMaximum maps to 1.0. | ||
* | ||
* @see CesiumMath.fromSNorm | ||
*/ | ||
function toSNorm(value, rangeMaximum = 255) { | ||
return Math.round((clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMaximum); | ||
} | ||
/** | ||
* Returns 1.0 if the given value is positive or zero, and -1.0 if it is negative. | ||
* This is similar to `Math.sign` except that returns 1.0 instead of | ||
* 0.0 when the input value is 0.0. | ||
* | ||
* @param value The value to return the sign of. | ||
* @returns The sign of value. | ||
*/ | ||
function signNotZero(value) { | ||
return value < 0.0 ? -1.0 : 1.0; | ||
return value < 0.0 ? -1.0 : 1.0; | ||
} | ||
/** | ||
* Encodes a normalized vector into 2 SNORM values in the range of [0-rangeMax] following the 'oct' encoding. | ||
* | ||
* Oct encoding is a compact representation of unit length vectors. | ||
* The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors", | ||
* Cigolle et al 2014: {@link http://jcgt.org/published/0003/02/01/} | ||
* | ||
* @param vector The normalized vector to be compressed into 2 component 'oct' encoding. | ||
* @param result The 2 component oct-encoded unit length vector. | ||
* @param rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits. | ||
* @returns The 2 component oct-encoded unit length vector. | ||
* | ||
* @exception vector must be normalized. | ||
* | ||
* @see octDecodeInRange | ||
*/ | ||
export function octEncodeInRange(vector, rangeMax, result) { | ||
assert(vector); | ||
assert(result); | ||
const vector3 = scratchVector3.from(vector); | ||
assert(Math.abs(vector3.magnitudeSquared() - 1.0) <= _MathUtils.EPSILON6); | ||
result.x = vector.x / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z)); | ||
result.y = vector.y / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z)); | ||
if (vector.z < 0) { | ||
const x = result.x; | ||
const y = result.y; | ||
result.x = (1.0 - Math.abs(y)) * signNotZero(x); | ||
result.y = (1.0 - Math.abs(x)) * signNotZero(y); | ||
} | ||
result.x = toSNorm(result.x, rangeMax); | ||
result.y = toSNorm(result.y, rangeMax); | ||
return result; | ||
assert(vector); | ||
assert(result); | ||
const vector3 = scratchVector3.from(vector); | ||
assert(Math.abs(vector3.magnitudeSquared() - 1.0) <= _MathUtils.EPSILON6); | ||
result.x = vector.x / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z)); | ||
result.y = vector.y / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z)); | ||
if (vector.z < 0) { | ||
const x = result.x; | ||
const y = result.y; | ||
result.x = (1.0 - Math.abs(y)) * signNotZero(x); | ||
result.y = (1.0 - Math.abs(x)) * signNotZero(y); | ||
} | ||
result.x = toSNorm(result.x, rangeMax); | ||
result.y = toSNorm(result.y, rangeMax); | ||
return result; | ||
} | ||
/** | ||
* Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding. | ||
* | ||
* @param vector The normalized vector to be compressed into 2 byte 'oct' encoding. | ||
* @param result The 2 byte oct-encoded unit length vector. | ||
* @returns he 2 byte oct-encoded unit length vector. | ||
* | ||
* @exception vector must be normalized. | ||
* | ||
* @see octEncodeInRange | ||
* @see octDecode | ||
*/ | ||
export function octEncode(vector, result) { | ||
return octEncodeInRange(vector, 255, result); | ||
return octEncodeInRange(vector, 255, result); | ||
} | ||
/** | ||
* Encodes a normalized vector into 4-byte vector | ||
* @param vector The normalized vector to be compressed into 4 byte 'oct' encoding. | ||
* @param result The 4 byte oct-encoded unit length vector. | ||
* @returns The 4 byte oct-encoded unit length vector. | ||
* | ||
* @exception vector must be normalized. | ||
* | ||
* @see octEncodeInRange | ||
* @see octDecodeFromVector4 | ||
*/ | ||
export function octEncodeToVector4(vector, result) { | ||
octEncodeInRange(vector, 65535, octEncodeScratch); | ||
result.x = forceUint8(octEncodeScratch.x * RIGHT_SHIFT); | ||
result.y = forceUint8(octEncodeScratch.x); | ||
result.z = forceUint8(octEncodeScratch.y * RIGHT_SHIFT); | ||
result.w = forceUint8(octEncodeScratch.y); | ||
return result; | ||
octEncodeInRange(vector, 65535, octEncodeScratch); | ||
result.x = forceUint8(octEncodeScratch.x * RIGHT_SHIFT); | ||
result.y = forceUint8(octEncodeScratch.x); | ||
result.z = forceUint8(octEncodeScratch.y * RIGHT_SHIFT); | ||
result.w = forceUint8(octEncodeScratch.y); | ||
return result; | ||
} | ||
/** | ||
* Decodes a unit-length vector in 'oct' encoding to a normalized 3-component vector. | ||
* | ||
* @param x The x component of the oct-encoded unit length vector. | ||
* @param y The y component of the oct-encoded unit length vector. | ||
* @param rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits. | ||
* @param result The decoded and normalized vector | ||
* @returns The decoded and normalized vector. | ||
* | ||
* @exception x and y must be unsigned normalized integers between 0 and rangeMax. | ||
* | ||
* @see octEncodeInRange | ||
*/ | ||
export function octDecodeInRange(x, y, rangeMax, result) { | ||
assert(result); | ||
if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) { | ||
throw new Error(`x and y must be unsigned normalized integers between 0 and ${rangeMax}`); | ||
} | ||
result.x = fromSNorm(x, rangeMax); | ||
result.y = fromSNorm(y, rangeMax); | ||
result.z = 1.0 - (Math.abs(result.x) + Math.abs(result.y)); | ||
if (result.z < 0.0) { | ||
const oldVX = result.x; | ||
result.x = (1.0 - Math.abs(result.y)) * signNotZero(oldVX); | ||
result.y = (1.0 - Math.abs(oldVX)) * signNotZero(result.y); | ||
} | ||
return result.normalize(); | ||
assert(result); | ||
if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) { | ||
throw new Error(`x and y must be unsigned normalized integers between 0 and ${rangeMax}`); | ||
} | ||
result.x = fromSNorm(x, rangeMax); | ||
result.y = fromSNorm(y, rangeMax); | ||
result.z = 1.0 - (Math.abs(result.x) + Math.abs(result.y)); | ||
if (result.z < 0.0) { | ||
const oldVX = result.x; | ||
result.x = (1.0 - Math.abs(result.y)) * signNotZero(oldVX); | ||
result.y = (1.0 - Math.abs(oldVX)) * signNotZero(result.y); | ||
} | ||
return result.normalize(); | ||
} | ||
/** | ||
* Decodes a unit-length vector in 2 byte 'oct' encoding to a normalized 3-component vector. | ||
* | ||
* @param x The x component of the oct-encoded unit length vector. | ||
* @param y The y component of the oct-encoded unit length vector. | ||
* @param result The decoded and normalized vector. | ||
* @returns he decoded and normalized vector. | ||
* | ||
* @exception x and y must be an unsigned normalized integer between 0 and 255. | ||
* | ||
* @see octDecodeInRange | ||
*/ | ||
export function octDecode(x, y, result) { | ||
return octDecodeInRange(x, y, 255, result); | ||
return octDecodeInRange(x, y, 255, result); | ||
} | ||
/** | ||
* Decodes a unit-length vector in 4 byte 'oct' encoding to a normalized 3-component vector. | ||
* | ||
* @param encoded The oct-encoded unit length vector. | ||
* @param esult The decoded and normalized vector. | ||
* @returns The decoded and normalized vector. | ||
* | ||
* @exception x, y, z, and w must be unsigned normalized integers between 0 and 255. | ||
* | ||
* @see octDecodeInRange | ||
* @see octEncodeToVector4 | ||
*/ | ||
export function octDecodeFromVector4(encoded, result) { | ||
assert(encoded); | ||
assert(result); | ||
const x = encoded.x; | ||
const y = encoded.y; | ||
const z = encoded.z; | ||
const w = encoded.w; | ||
if (x < 0 || x > 255 || y < 0 || y > 255 || z < 0 || z > 255 || w < 0 || w > 255) { | ||
throw new Error('x, y, z, and w must be unsigned normalized integers between 0 and 255'); | ||
} | ||
const xOct16 = x * LEFT_SHIFT + y; | ||
const yOct16 = z * LEFT_SHIFT + w; | ||
return octDecodeInRange(xOct16, yOct16, 65535, result); | ||
assert(encoded); | ||
assert(result); | ||
const x = encoded.x; | ||
const y = encoded.y; | ||
const z = encoded.z; | ||
const w = encoded.w; | ||
if (x < 0 || x > 255 || y < 0 || y > 255 || z < 0 || z > 255 || w < 0 || w > 255) { | ||
throw new Error('x, y, z, and w must be unsigned normalized integers between 0 and 255'); | ||
} | ||
const xOct16 = x * LEFT_SHIFT + y; | ||
const yOct16 = z * LEFT_SHIFT + w; | ||
return octDecodeInRange(xOct16, yOct16, 65535, result); | ||
} | ||
/** | ||
* Packs an oct encoded vector into a single floating-point number. | ||
* | ||
* @param encoded The oct encoded vector. | ||
* @returns The oct encoded vector packed into a single float. | ||
* | ||
*/ | ||
export function octPackFloat(encoded) { | ||
const vector2 = scratchVector2.from(encoded); | ||
return 256.0 * vector2.x + vector2.y; | ||
const vector2 = scratchVector2.from(encoded); | ||
return 256.0 * vector2.x + vector2.y; | ||
} | ||
/** | ||
* Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding and | ||
* stores those values in a single float-point number. | ||
* | ||
* @param vector The normalized vector to be compressed into 2 byte 'oct' encoding. | ||
* @returns The 2 byte oct-encoded unit length vector. | ||
* | ||
* @exception vector must be normalized. | ||
*/ | ||
export function octEncodeFloat(vector) { | ||
octEncode(vector, scratchEncodeVector2); | ||
return octPackFloat(scratchEncodeVector2); | ||
octEncode(vector, scratchEncodeVector2); | ||
return octPackFloat(scratchEncodeVector2); | ||
} | ||
/** | ||
* Decodes a unit-length vector in 'oct' encoding packed in a floating-point number to a normalized 3-component vector. | ||
* | ||
* @param value The oct-encoded unit length vector stored as a single floating-point number. | ||
* @param result The decoded and normalized vector | ||
* @returns The decoded and normalized vector. | ||
* | ||
*/ | ||
export function octDecodeFloat(value, result) { | ||
assert(Number.isFinite(value)); | ||
const temp = value / 256.0; | ||
const x = Math.floor(temp); | ||
const y = (temp - x) * 256.0; | ||
return octDecode(x, y, result); | ||
assert(Number.isFinite(value)); | ||
const temp = value / 256.0; | ||
const x = Math.floor(temp); | ||
const y = (temp - x) * 256.0; | ||
return octDecode(x, y, result); | ||
} | ||
/** | ||
* Encodes three normalized vectors into 6 SNORM values in the range of [0-255] following the 'oct' encoding and | ||
* packs those into two floating-point numbers. | ||
* | ||
* @param v1 A normalized vector to be compressed. | ||
* @param v2 A normalized vector to be compressed. | ||
* @param v3 A normalized vector to be compressed. | ||
* @param result The 'oct' encoded vectors packed into two floating-point numbers. | ||
* @returns The 'oct' encoded vectors packed into two floating-point numbers. | ||
* | ||
*/ | ||
export function octPack(v1, v2, v3, result) { | ||
assert(v1); | ||
assert(v2); | ||
assert(v3); | ||
assert(result); | ||
const encoded1 = octEncodeFloat(v1); | ||
const encoded2 = octEncodeFloat(v2); | ||
const encoded3 = octEncode(v3, scratchEncodeVector2); | ||
result.x = 65536.0 * encoded3.x + encoded1; | ||
result.y = 65536.0 * encoded3.y + encoded2; | ||
return result; | ||
assert(v1); | ||
assert(v2); | ||
assert(v3); | ||
assert(result); | ||
const encoded1 = octEncodeFloat(v1); | ||
const encoded2 = octEncodeFloat(v2); | ||
const encoded3 = octEncode(v3, scratchEncodeVector2); | ||
result.x = 65536.0 * encoded3.x + encoded1; | ||
result.y = 65536.0 * encoded3.y + encoded2; | ||
return result; | ||
} | ||
/** | ||
* Decodes three unit-length vectors in 'oct' encoding packed into a floating-point number to a normalized 3-component vector. | ||
* | ||
* @param packed The three oct-encoded unit length vectors stored as two floating-point number. | ||
* @param v1 One decoded and normalized vector. | ||
* @param v2 One decoded and normalized vector. | ||
* @param v3 One decoded and normalized vector. | ||
*/ | ||
export function octUnpack(packed, v1, v2, v3) { | ||
let temp = packed.x / 65536.0; | ||
const x = Math.floor(temp); | ||
const encodedFloat1 = (temp - x) * 65536.0; | ||
temp = packed.y / 65536.0; | ||
const y = Math.floor(temp); | ||
const encodedFloat2 = (temp - y) * 65536.0; | ||
octDecodeFloat(encodedFloat1, v1); | ||
octDecodeFloat(encodedFloat2, v2); | ||
octDecode(x, y, v3); | ||
let temp = packed.x / 65536.0; | ||
const x = Math.floor(temp); | ||
const encodedFloat1 = (temp - x) * 65536.0; | ||
temp = packed.y / 65536.0; | ||
const y = Math.floor(temp); | ||
const encodedFloat2 = (temp - y) * 65536.0; | ||
octDecodeFloat(encodedFloat1, v1); | ||
octDecodeFloat(encodedFloat2, v2); | ||
octDecode(x, y, v3); | ||
} | ||
/** | ||
* Pack texture coordinates into a single float. The texture coordinates will only preserve 12 bits of precision. | ||
* | ||
* @param textureCoordinates The texture coordinates to compress. Both coordinates must be in the range 0.0-1.0. | ||
* @returns The packed texture coordinates. | ||
* | ||
*/ | ||
export function compressTextureCoordinates(textureCoordinates) { | ||
const x = textureCoordinates.x * 4095.0 | 0; | ||
const y = textureCoordinates.y * 4095.0 | 0; | ||
return 4096.0 * x + y; | ||
// Move x and y to the range 0-4095; | ||
const x = (textureCoordinates.x * 4095.0) | 0; | ||
const y = (textureCoordinates.y * 4095.0) | 0; | ||
return 4096.0 * x + y; | ||
} | ||
/** | ||
* Decompresses texture coordinates that were packed into a single float. | ||
* | ||
* @param compressed The compressed texture coordinates. | ||
* @param result The decompressed texture coordinates. | ||
* @returns The modified result parameter. | ||
* | ||
*/ | ||
export function decompressTextureCoordinates(compressed, result) { | ||
const temp = compressed / 4096.0; | ||
const xZeroTo4095 = Math.floor(temp); | ||
result.x = xZeroTo4095 / 4095.0; | ||
result.y = (compressed - xZeroTo4095 * 4096) / 4095; | ||
return result; | ||
const temp = compressed / 4096.0; | ||
const xZeroTo4095 = Math.floor(temp); | ||
result.x = xZeroTo4095 / 4095.0; | ||
result.y = (compressed - xZeroTo4095 * 4096) / 4095; | ||
return result; | ||
} | ||
/** | ||
* Decodes delta and ZigZag encoded vertices. This modifies the buffers in place. | ||
* | ||
* @param uBuffer The buffer view of u values. | ||
* @param vBuffer The buffer view of v values. | ||
* @param [heightBuffer] The buffer view of height values. | ||
* | ||
* @link https://github.com/AnalyticalGraphicsInc/quantized-mesh|quantized-mesh-1.0 terrain format | ||
*/ | ||
export function zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer) { | ||
assert(uBuffer); | ||
assert(vBuffer); | ||
assert(uBuffer.length === vBuffer.length); | ||
if (heightBuffer) { | ||
assert(uBuffer.length === heightBuffer.length); | ||
} | ||
function zigZagDecode(value) { | ||
return value >> 1 ^ -(value & 1); | ||
} | ||
let u = 0; | ||
let v = 0; | ||
let height = 0; | ||
for (let i = 0; i < uBuffer.length; ++i) { | ||
u += zigZagDecode(uBuffer[i]); | ||
v += zigZagDecode(vBuffer[i]); | ||
uBuffer[i] = u; | ||
vBuffer[i] = v; | ||
assert(uBuffer); | ||
assert(vBuffer); | ||
assert(uBuffer.length === vBuffer.length); | ||
if (heightBuffer) { | ||
height += zigZagDecode(heightBuffer[i]); | ||
heightBuffer[i] = height; | ||
assert(uBuffer.length === heightBuffer.length); | ||
} | ||
} | ||
function zigZagDecode(value) { | ||
return (value >> 1) ^ -(value & 1); | ||
} | ||
let u = 0; | ||
let v = 0; | ||
let height = 0; | ||
for (let i = 0; i < uBuffer.length; ++i) { | ||
u += zigZagDecode(uBuffer[i]); | ||
v += zigZagDecode(vBuffer[i]); | ||
uBuffer[i] = u; | ||
vBuffer[i] = v; | ||
if (heightBuffer) { | ||
height += zigZagDecode(heightBuffer[i]); | ||
heightBuffer[i] = height; | ||
} | ||
} | ||
} | ||
//# sourceMappingURL=attribute-compression.js.map |
@@ -0,29 +1,31 @@ | ||
// Subset of WebGL constants | ||
export const GL_PRIMITIVE = { | ||
POINTS: 0x0000, | ||
LINES: 0x0001, | ||
TRIANGLES: 0x0004 | ||
POINTS: 0x0000, // Points. single points. | ||
LINES: 0x0001, // Lines. Each vertex connects to the one after it. | ||
TRIANGLES: 0x0004 // Triangles. Each set of three vertices creates a separate triangle. | ||
}; | ||
// Primitive modes | ||
export const GL_PRIMITIVE_MODE = { | ||
POINTS: 0x0000, | ||
LINES: 0x0001, | ||
LINE_LOOP: 0x0002, | ||
LINE_STRIP: 0x0003, | ||
TRIANGLES: 0x0004, | ||
TRIANGLE_STRIP: 0x0005, | ||
TRIANGLE_FAN: 0x0006 | ||
POINTS: 0x0000, // Points. single points. | ||
LINES: 0x0001, // Lines. Each vertex connects to the one after it. | ||
LINE_LOOP: 0x0002, // Lines. Each set of two vertices is treated as a separate line segment. | ||
LINE_STRIP: 0x0003, // Lines/ a connected group of line segments from the first vertex to the last | ||
TRIANGLES: 0x0004, // Triangles. Each set of three vertices creates a separate triangle. | ||
TRIANGLE_STRIP: 0x0005, // Triangles. A connected group of triangles. | ||
TRIANGLE_FAN: 0x0006 // Triangles. A connected group of triangles. | ||
// Each vertex connects to the previous and the first vertex in the fan. | ||
}; | ||
export const GL_TYPE = { | ||
BYTE: 5120, | ||
UNSIGNED_BYTE: 5121, | ||
SHORT: 5122, | ||
UNSIGNED_SHORT: 5123, | ||
INT: 5124, | ||
UNSIGNED_INT: 5125, | ||
FLOAT: 5126, | ||
DOUBLE: 5130 | ||
BYTE: 5120, | ||
UNSIGNED_BYTE: 5121, | ||
SHORT: 5122, | ||
UNSIGNED_SHORT: 5123, | ||
INT: 5124, | ||
UNSIGNED_INT: 5125, | ||
FLOAT: 5126, | ||
DOUBLE: 5130 | ||
}; | ||
export const GL = { | ||
...GL_PRIMITIVE_MODE, | ||
...GL_TYPE | ||
...GL_PRIMITIVE_MODE, | ||
...GL_TYPE | ||
}; | ||
//# sourceMappingURL=constants.js.map |
import { GL_TYPE as GL } from "../constants.js"; | ||
const GL_TYPE_TO_ARRAY_TYPE = { | ||
[GL.DOUBLE]: Float64Array, | ||
[GL.FLOAT]: Float32Array, | ||
[GL.UNSIGNED_SHORT]: Uint16Array, | ||
[GL.UNSIGNED_INT]: Uint32Array, | ||
[GL.UNSIGNED_BYTE]: Uint8Array, | ||
[GL.BYTE]: Int8Array, | ||
[GL.SHORT]: Int16Array, | ||
[GL.INT]: Int32Array | ||
[GL.DOUBLE]: Float64Array, | ||
[GL.FLOAT]: Float32Array, | ||
[GL.UNSIGNED_SHORT]: Uint16Array, | ||
[GL.UNSIGNED_INT]: Uint32Array, | ||
[GL.UNSIGNED_BYTE]: Uint8Array, | ||
[GL.BYTE]: Int8Array, | ||
[GL.SHORT]: Int16Array, | ||
[GL.INT]: Int32Array | ||
}; | ||
const NAME_TO_GL_TYPE = { | ||
DOUBLE: GL.DOUBLE, | ||
FLOAT: GL.FLOAT, | ||
UNSIGNED_SHORT: GL.UNSIGNED_SHORT, | ||
UNSIGNED_INT: GL.UNSIGNED_INT, | ||
UNSIGNED_BYTE: GL.UNSIGNED_BYTE, | ||
BYTE: GL.BYTE, | ||
SHORT: GL.SHORT, | ||
INT: GL.INT | ||
DOUBLE: GL.DOUBLE, | ||
FLOAT: GL.FLOAT, | ||
UNSIGNED_SHORT: GL.UNSIGNED_SHORT, | ||
UNSIGNED_INT: GL.UNSIGNED_INT, | ||
UNSIGNED_BYTE: GL.UNSIGNED_BYTE, | ||
BYTE: GL.BYTE, | ||
SHORT: GL.SHORT, | ||
INT: GL.INT | ||
}; | ||
const ERR_TYPE_CONVERSION = 'Failed to convert GL type'; | ||
// Converts TYPED ARRAYS to corresponding GL constant | ||
// Used to auto deduce gl parameter types | ||
export default class GLType { | ||
static fromTypedArray(arrayOrType) { | ||
arrayOrType = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType; | ||
for (const glType in GL_TYPE_TO_ARRAY_TYPE) { | ||
const ArrayType = GL_TYPE_TO_ARRAY_TYPE[glType]; | ||
if (ArrayType === arrayOrType) { | ||
// Signature: fromTypedArray(new Uint8Array()) | ||
// Signature: fromTypedArray(Uint8Array) | ||
/** | ||
* Returns the size, in bytes, of the corresponding datatype | ||
* @param arrayOrType | ||
* @returns glType a a string | ||
*/ | ||
static fromTypedArray(arrayOrType) { | ||
// If typed array, look up constructor | ||
arrayOrType = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType; | ||
for (const glType in GL_TYPE_TO_ARRAY_TYPE) { | ||
const ArrayType = GL_TYPE_TO_ARRAY_TYPE[glType]; | ||
if (ArrayType === arrayOrType) { | ||
return glType; | ||
} | ||
} | ||
throw new Error(ERR_TYPE_CONVERSION); | ||
} | ||
/** | ||
* Extracts name for glType from array NAME_TO_GL_TYPE | ||
* @param name | ||
* @returns glType as a number | ||
*/ | ||
static fromName(name) { | ||
const glType = NAME_TO_GL_TYPE[name]; | ||
if (!glType) { | ||
throw new Error(ERR_TYPE_CONVERSION); | ||
} | ||
return glType; | ||
} | ||
} | ||
throw new Error(ERR_TYPE_CONVERSION); | ||
} | ||
static fromName(name) { | ||
const glType = NAME_TO_GL_TYPE[name]; | ||
if (!glType) { | ||
throw new Error(ERR_TYPE_CONVERSION); | ||
// Converts GL constant to corresponding typed array type | ||
// eslint-disable-next-line complexity | ||
static getArrayType(glType) { | ||
switch (glType) { | ||
/*eslint-disable*/ | ||
// @ts-ignore | ||
case GL.UNSIGNED_SHORT_5_6_5: | ||
// @ts-ignore | ||
case GL.UNSIGNED_SHORT_4_4_4_4: | ||
// @ts-ignore | ||
case GL.UNSIGNED_SHORT_5_5_5_1: | ||
/* eslint-enable*/ | ||
return Uint16Array; | ||
default: | ||
const ArrayType = GL_TYPE_TO_ARRAY_TYPE[glType]; | ||
if (!ArrayType) { | ||
throw new Error(ERR_TYPE_CONVERSION); | ||
} | ||
return ArrayType; | ||
} | ||
} | ||
return glType; | ||
} | ||
static getArrayType(glType) { | ||
switch (glType) { | ||
case GL.UNSIGNED_SHORT_5_6_5: | ||
case GL.UNSIGNED_SHORT_4_4_4_4: | ||
case GL.UNSIGNED_SHORT_5_5_5_1: | ||
return Uint16Array; | ||
default: | ||
const ArrayType = GL_TYPE_TO_ARRAY_TYPE[glType]; | ||
if (!ArrayType) { | ||
throw new Error(ERR_TYPE_CONVERSION); | ||
/** | ||
* Returns the size in bytes of one element of the provided WebGL type | ||
* @param glType | ||
* @returns size of glType | ||
*/ | ||
static getByteSize(glType) { | ||
const ArrayType = GLType.getArrayType(glType); | ||
return ArrayType.BYTES_PER_ELEMENT; | ||
} | ||
/** | ||
* Returns `true` if `glType` is a valid WebGL data type. | ||
* @param glType | ||
* @returns boolean | ||
*/ | ||
static validate(glType) { | ||
return Boolean(GLType.getArrayType(glType)); | ||
} | ||
/** | ||
* Creates a typed view of an array of bytes | ||
* @param glType The type of typed array (ArrayBuffer view) to create | ||
* @param buffer The buffer storage to use for the view. | ||
* @param byteOffset The offset, in bytes, to the first element in the view | ||
* @param length The number of elements in the view. Defaults to buffer length | ||
* @returns A typed array view of the buffer | ||
*/ | ||
static createTypedArray(glType, buffer, byteOffset = 0, length) { | ||
if (length === undefined) { | ||
length = (buffer.byteLength - byteOffset) / GLType.getByteSize(glType); | ||
} | ||
return ArrayType; | ||
const ArrayType = GLType.getArrayType(glType); | ||
return new ArrayType(buffer, byteOffset, length); | ||
} | ||
} | ||
static getByteSize(glType) { | ||
const ArrayType = GLType.getArrayType(glType); | ||
return ArrayType.BYTES_PER_ELEMENT; | ||
} | ||
static validate(glType) { | ||
return Boolean(GLType.getArrayType(glType)); | ||
} | ||
static createTypedArray(glType, buffer) { | ||
let byteOffset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; | ||
let length = arguments.length > 3 ? arguments[3] : undefined; | ||
if (length === undefined) { | ||
length = (buffer.byteLength - byteOffset) / GLType.getByteSize(glType); | ||
} | ||
const ArrayType = GLType.getArrayType(glType); | ||
return new ArrayType(buffer, byteOffset, length); | ||
} | ||
} | ||
//# sourceMappingURL=gl-type.js.map |
@@ -0,4 +1,11 @@ | ||
/** | ||
* Checking if it is geometry | ||
* @param geometry | ||
*/ | ||
export default function isGeometry(geometry) { | ||
return geometry && typeof geometry === 'object' && geometry.mode && geometry.attributes && typeof geometry.attributes === 'object'; | ||
return (geometry && | ||
typeof geometry === 'object' && | ||
geometry.mode && | ||
geometry.attributes && | ||
typeof geometry.attributes === 'object'); | ||
} | ||
//# sourceMappingURL=is-geometry.js.map |
@@ -0,11 +1,15 @@ | ||
/** | ||
* Iterates over a single attribute | ||
* NOTE: For performance, re-yields the same modified element | ||
* @param param0 | ||
*/ | ||
export function* makeAttributeIterator(values, size) { | ||
const ArrayType = values.constructor; | ||
const element = new ArrayType(size); | ||
for (let i = 0; i < values.length; i += size) { | ||
for (let j = 0; j < size; j++) { | ||
element[j] = element[i + j]; | ||
const ArrayType = values.constructor; | ||
const element = new ArrayType(size); | ||
for (let i = 0; i < values.length; i += size) { | ||
for (let j = 0; j < size; j++) { | ||
element[j] = element[i + j]; | ||
} | ||
yield element; | ||
} | ||
yield element; | ||
} | ||
} | ||
//# sourceMappingURL=attribute-iterator.js.map |
import { GL } from "../constants.js"; | ||
import { getPrimitiveModeType } from "../primitives/modes.js"; | ||
import { assert } from '@loaders.gl/loader-utils'; | ||
export function makePrimitiveIterator(indices) { | ||
let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
let mode = arguments.length > 2 ? arguments[2] : undefined; | ||
let start = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; | ||
let end = arguments.length > 4 ? arguments[4] : undefined; | ||
return function* () { | ||
/** | ||
* Will iterate over each primitive, expanding (dereferencing) indices | ||
* @param indices | ||
* @param attributes | ||
* @param mode | ||
* @param start | ||
* @param end | ||
*/ | ||
// eslint-disable-next-line complexity | ||
export function* makePrimitiveIterator(indices, attributes = {}, mode, start = 0, end) { | ||
// support indices being an object with a values array | ||
if (indices) { | ||
indices = indices.values || indices.value || indices; | ||
indices = indices.values || indices.value || indices; | ||
} | ||
// Autodeduce length from indices | ||
if (end === undefined) { | ||
end = indices ? indices.length : start; | ||
end = indices ? indices.length : start; | ||
} | ||
// iteration info | ||
const info = { | ||
attributes, | ||
type: getPrimitiveModeType(mode), | ||
i1: 0, | ||
i2: 0, | ||
i3: 0 | ||
attributes, | ||
type: getPrimitiveModeType(mode), | ||
i1: 0, | ||
i2: 0, | ||
i3: 0 | ||
}; | ||
let i = start; | ||
// @ts-ignore | ||
while (i < end) { | ||
switch (mode) { | ||
case GL.POINTS: | ||
info.i1 = i; | ||
i += 1; | ||
break; | ||
case GL.LINES: | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 2; | ||
break; | ||
case GL.LINE_STRIP: | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 1; | ||
break; | ||
case GL.LINE_LOOP: | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 1; | ||
break; | ||
case GL.TRIANGLES: | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
info.i3 = i + 2; | ||
i += 3; | ||
break; | ||
case GL.TRIANGLE_STRIP: | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 1; | ||
break; | ||
case GL.TRIANGLE_FAN: | ||
info.i1 = 1; | ||
info.i2 = i; | ||
info.i3 = i + 1; | ||
i += 1; | ||
break; | ||
default: | ||
assert(false); | ||
} | ||
if (indices) { | ||
if ('i1' in info) { | ||
info.i1 = indices[info.i1]; | ||
info.i2 = indices[info.i2]; | ||
info.i3 = indices[info.i3]; | ||
switch (mode) { | ||
case GL.POINTS: // draw single points. | ||
info.i1 = i; | ||
i += 1; | ||
break; | ||
case GL.LINES: // draw lines. Each set of two vertices is treated as a separate line segment. | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 2; | ||
break; | ||
case GL.LINE_STRIP: // draw lines. Each vertex connects to the one after it. | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 1; | ||
break; | ||
case GL.LINE_LOOP: // draw a connected group of line segments from the first vertex to the last | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 1; | ||
break; | ||
case GL.TRIANGLES: // draw triangles. Each set of three vertices creates a separate triangle. | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
info.i3 = i + 2; | ||
i += 3; | ||
break; | ||
case GL.TRIANGLE_STRIP: // draw a connected group of triangles. | ||
info.i1 = i; | ||
info.i2 = i + 1; | ||
i += 1; | ||
break; | ||
case GL.TRIANGLE_FAN: // draw a connected group of triangles. | ||
info.i1 = 1; | ||
info.i2 = i; | ||
info.i3 = i + 1; | ||
i += 1; | ||
break; | ||
default: | ||
assert(false); | ||
} | ||
} | ||
yield info; | ||
// if indices are present, lookup actual vertices in indices | ||
if (indices) { | ||
if ('i1' in info) { | ||
info.i1 = indices[info.i1]; | ||
info.i2 = indices[info.i2]; | ||
info.i3 = indices[info.i3]; | ||
} | ||
} | ||
// @ts-ignore | ||
yield info; | ||
} | ||
}(); | ||
} | ||
//# sourceMappingURL=primitive-iterator.js.map |
import { GL } from "../constants.js"; | ||
/** | ||
* Different methods of working with geometries depending on glType | ||
/** | ||
/** | ||
* @param mode | ||
* @returns draw points | lines | triangles | ||
*/ | ||
export function getPrimitiveModeType(mode) { | ||
switch (mode) { | ||
case GL.POINTS: | ||
return GL.POINTS; | ||
case GL.LINES: | ||
case GL.LINE_STRIP: | ||
case GL.LINE_LOOP: | ||
return GL.LINES; | ||
case GL.TRIANGLES: | ||
case GL.TRIANGLE_STRIP: | ||
case GL.TRIANGLE_FAN: | ||
return GL.TRIANGLES; | ||
default: | ||
throw new Error('Unknown primitive mode'); | ||
} | ||
switch (mode) { | ||
case GL.POINTS: // draw single points. | ||
return GL.POINTS; | ||
case GL.LINES: // draw lines. Each set of two vertices is treated as a separate line segment. | ||
case GL.LINE_STRIP: // draw lines. Each vertex connects to the one after it. | ||
case GL.LINE_LOOP: // draw a connected group of line segments from the first vertex to the last | ||
return GL.LINES; | ||
case GL.TRIANGLES: | ||
case GL.TRIANGLE_STRIP: | ||
case GL.TRIANGLE_FAN: // draw a connected group of triangles. | ||
return GL.TRIANGLES; | ||
default: | ||
throw new Error('Unknown primitive mode'); | ||
} | ||
} | ||
/** | ||
* @param mode | ||
* @returns true | false | ||
*/ | ||
export function isPrimitiveModeExpandable(mode) { | ||
switch (mode) { | ||
case GL.LINE_STRIP: | ||
case GL.LINE_LOOP: | ||
case GL.TRIANGLE_STRIP: | ||
case GL.TRIANGLE_FAN: | ||
return true; | ||
default: | ||
return false; | ||
} | ||
switch (mode) { | ||
case GL.LINE_STRIP: // draw lines. Each vertex connects to the one after it. | ||
case GL.LINE_LOOP: // draw a connected group of line segments from the first vertex to the last | ||
case GL.TRIANGLE_STRIP: // draw a connected group of triangles. | ||
case GL.TRIANGLE_FAN: // draw a connected group of triangles. | ||
return true; | ||
default: | ||
return false; | ||
} | ||
} | ||
/** | ||
* Returns new length depends on glType | ||
* @param mode | ||
* @param length | ||
* @returns new length | ||
*/ | ||
export function getPrimitiveModeExpandedLength(mode, length) { | ||
switch (mode) { | ||
case GL.POINTS: | ||
return length; | ||
case GL.LINES: | ||
return length; | ||
case GL.LINE_STRIP: | ||
return length; | ||
case GL.LINE_LOOP: | ||
return length + 1; | ||
case GL.TRIANGLES: | ||
return length; | ||
case GL.TRIANGLE_STRIP: | ||
case GL.TRIANGLE_FAN: | ||
return (length - 2) * 3; | ||
default: | ||
throw new Error('Unknown length'); | ||
} | ||
switch (mode) { | ||
case GL.POINTS: // draw single points. | ||
return length; | ||
case GL.LINES: // draw lines. Each set of two vertices is treated as a separate line segment. | ||
return length; | ||
case GL.LINE_STRIP: // draw lines. Each vertex connects to the one after it. | ||
return length; | ||
case GL.LINE_LOOP: // draw a connected group of line segments from the first vertex to the last | ||
return length + 1; | ||
case GL.TRIANGLES: // draw triangles. Each set of three vertices creates a separate triangle. | ||
return length; | ||
case GL.TRIANGLE_STRIP: // draw a connected group of triangles. | ||
case GL.TRIANGLE_FAN: // draw a connected group of triangles. | ||
return (length - 2) * 3; | ||
default: | ||
throw new Error('Unknown length'); | ||
} | ||
} | ||
//# sourceMappingURL=modes.js.map |
@@ -1,18 +0,21 @@ | ||
export function concatTypedArrays() { | ||
let arrays = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; | ||
let byteLength = 0; | ||
for (let i = 0; i < arrays.length; ++i) { | ||
byteLength += arrays[i].byteLength; | ||
} | ||
const buffer = new Uint8Array(byteLength); | ||
let byteOffset = 0; | ||
for (let i = 0; i < arrays.length; ++i) { | ||
const data = new Uint8Array(arrays[i].buffer); | ||
byteLength = data.length; | ||
for (let j = 0; j < byteLength; ++j) { | ||
buffer[byteOffset++] = data[j]; | ||
/** | ||
* Concats typed arrays | ||
* @param arrays | ||
* @returns new Uint8Array | ||
*/ | ||
export function concatTypedArrays(arrays = []) { | ||
let byteLength = 0; | ||
for (let i = 0; i < arrays.length; ++i) { | ||
byteLength += arrays[i].byteLength; | ||
} | ||
} | ||
return buffer; | ||
const buffer = new Uint8Array(byteLength); | ||
let byteOffset = 0; | ||
for (let i = 0; i < arrays.length; ++i) { | ||
const data = new Uint8Array(arrays[i].buffer); | ||
byteLength = data.length; | ||
for (let j = 0; j < byteLength; ++j) { | ||
buffer[byteOffset++] = data[j]; | ||
} | ||
} | ||
return buffer; | ||
} | ||
//# sourceMappingURL=typed-array-utils.js.map |
@@ -0,6 +1,10 @@ | ||
/** | ||
* Throws error message | ||
* @param condition checks if an attribute equal to condition | ||
* @param message error message | ||
*/ | ||
export function assert(condition, message) { | ||
if (!condition) { | ||
throw new Error(`math.gl assertion failed. ${message}`); | ||
} | ||
if (!condition) { | ||
throw new Error(`math.gl assertion failed. ${message}`); | ||
} | ||
} | ||
//# sourceMappingURL=assert.js.map |
@@ -0,4 +1,7 @@ | ||
/** | ||
* Handle UVs if they are out of range [0,1]. | ||
* @param n | ||
*/ | ||
export function emod(n) { | ||
return (n % 1 + 1) % 1; | ||
return ((n % 1) + 1) % 1; | ||
} | ||
//# sourceMappingURL=coordinates.js.map |
export type TypedArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor; | ||
export { GL } from './geometry/constants'; | ||
export { GL_TYPE } from './geometry/constants'; | ||
export { default as GLType } from './geometry/gl/gl-type'; | ||
export { default as isGeometry } from './geometry/is-geometry'; | ||
export { makeAttributeIterator } from './geometry/iterators/attribute-iterator'; | ||
export { makePrimitiveIterator } from './geometry/iterators/primitive-iterator'; | ||
export { computeVertexNormals } from './geometry/attributes/compute-vertex-normals'; | ||
export { encodeRGB565, decodeRGB565 } from './geometry/colors/rgb565'; | ||
export { concatTypedArrays } from './geometry/typed-arrays/typed-array-utils'; | ||
export { octEncodeInRange, octEncode, octEncodeToVector4, octDecodeInRange, octDecode, octDecodeFromVector4, octPackFloat, octEncodeFloat, octDecodeFloat, octPack, octUnpack, compressTextureCoordinates, decompressTextureCoordinates, zigZagDeltaDecode } from './geometry/compression/attribute-compression'; | ||
export { emod } from './geometry/utils/coordinates'; | ||
export { GL } from "./geometry/constants.js"; | ||
export { GL_TYPE } from "./geometry/constants.js"; | ||
export { default as GLType } from "./geometry/gl/gl-type.js"; | ||
export { default as isGeometry } from "./geometry/is-geometry.js"; | ||
export { makeAttributeIterator } from "./geometry/iterators/attribute-iterator.js"; | ||
export { makePrimitiveIterator } from "./geometry/iterators/primitive-iterator.js"; | ||
export { computeVertexNormals } from "./geometry/attributes/compute-vertex-normals.js"; | ||
export { encodeRGB565, decodeRGB565 } from "./geometry/colors/rgb565.js"; | ||
export { concatTypedArrays } from "./geometry/typed-arrays/typed-array-utils.js"; | ||
export { octEncodeInRange, octEncode, octEncodeToVector4, octDecodeInRange, octDecode, octDecodeFromVector4, octPackFloat, octEncodeFloat, octDecodeFloat, octPack, octUnpack, compressTextureCoordinates, decompressTextureCoordinates, zigZagDeltaDecode } from "./geometry/compression/attribute-compression.js"; | ||
export { emod } from "./geometry/utils/coordinates.js"; | ||
//# sourceMappingURL=index.d.ts.map |
export { GL } from "./geometry/constants.js"; | ||
// GL support | ||
export { GL_TYPE } from "./geometry/constants.js"; | ||
export { default as GLType } from "./geometry/gl/gl-type.js"; | ||
// Geometry | ||
export { default as isGeometry } from "./geometry/is-geometry.js"; | ||
// Iterators | ||
export { makeAttributeIterator } from "./geometry/iterators/attribute-iterator.js"; | ||
export { makePrimitiveIterator } from "./geometry/iterators/primitive-iterator.js"; | ||
// Helper methods | ||
export { computeVertexNormals } from "./geometry/attributes/compute-vertex-normals.js"; | ||
export { encodeRGB565, decodeRGB565 } from "./geometry/colors/rgb565.js"; | ||
// Typed array utils | ||
export { concatTypedArrays } from "./geometry/typed-arrays/typed-array-utils.js"; | ||
// Compression | ||
export { octEncodeInRange, octEncode, octEncodeToVector4, octDecodeInRange, octDecode, octDecodeFromVector4, octPackFloat, octEncodeFloat, octDecodeFloat, octPack, octUnpack, compressTextureCoordinates, decompressTextureCoordinates, zigZagDeltaDecode } from "./geometry/compression/attribute-compression.js"; | ||
export { emod } from "./geometry/utils/coordinates.js"; | ||
//# sourceMappingURL=index.js.map |
@@ -0,6 +1,8 @@ | ||
// Replacement for the external assert method to reduce bundle size | ||
// Note: We don't use the second "message" argument in calling code, | ||
// so no need to support it here | ||
export function assert(condition, message) { | ||
if (!condition) { | ||
throw new Error(message || '3d-tile loader: assertion failed.'); | ||
} | ||
if (!condition) { | ||
throw new Error(message || '3d-tile loader: assertion failed.'); | ||
} | ||
} | ||
//# sourceMappingURL=assert.js.map |
{ | ||
"name": "@loaders.gl/math", | ||
"version": "4.2.0-alpha.4", | ||
"version": "4.2.0-alpha.5", | ||
"description": "Experimental math classes for loaders.gl", | ||
@@ -42,7 +42,10 @@ "license": "MIT", | ||
"dependencies": { | ||
"@loaders.gl/images": "4.2.0-alpha.4", | ||
"@loaders.gl/loader-utils": "4.2.0-alpha.4", | ||
"@loaders.gl/images": "4.2.0-alpha.5", | ||
"@loaders.gl/loader-utils": "4.2.0-alpha.5", | ||
"@math.gl/core": "^4.0.0" | ||
}, | ||
"gitHead": "6c52dee5c3f005648a394cc4aee7fc37005c8e83" | ||
"peerDependencies": { | ||
"@loaders.gl/core": "^4.0.0" | ||
}, | ||
"gitHead": "32d95a81971f104e4dfeb88ab57065f05321a76a" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
3075
155882
4
85
+ Added@loaders.gl/core@4.2.1(transitive)
+ Added@loaders.gl/images@4.2.0-alpha.5(transitive)
+ Added@loaders.gl/loader-utils@4.2.0-alpha.54.2.1(transitive)
+ Added@loaders.gl/schema@4.2.1(transitive)
+ Added@loaders.gl/worker-utils@4.2.0-alpha.54.2.1(transitive)
+ Added@probe.gl/env@4.0.9(transitive)
+ Added@probe.gl/log@4.0.9(transitive)
+ Added@types/geojson@7946.0.14(transitive)
- Removed@babel/runtime@7.24.5(transitive)
- Removed@loaders.gl/images@4.2.0-alpha.4(transitive)
- Removed@loaders.gl/loader-utils@4.2.0-alpha.4(transitive)
- Removed@loaders.gl/worker-utils@4.2.0-alpha.4(transitive)
- Removedregenerator-runtime@0.14.1(transitive)