UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

414 lines (384 loc) 13.1 kB
import { Vector3 } from '../math/Vector3.js'; import { BufferAttribute } from './BufferAttribute.js'; import { denormalize, normalize } from '../math/MathUtils.js'; const _vector = /*@__PURE__*/new Vector3(); /** * An alternative version of a buffer attribute with interleaved data. Interleaved * attributes share a common interleaved data storage ({@link InterleavedBuffer}) and refer with * different offsets into the buffer. */ class InterleavedBufferAttribute { /** * Constructs a new interleaved buffer attribute. * * @param {InterleavedBuffer} interleavedBuffer - The buffer holding the interleaved data. * @param {number} itemSize - The item size. * @param {number} offset - The attribute offset into the buffer. * @param {boolean} [normalized=false] - Whether the data are normalized or not. */ constructor(interleavedBuffer, itemSize, offset, normalized = false) { /** * This flag can be used for type testing. * * @type {boolean} * @readonly * @default true */ this.isInterleavedBufferAttribute = true; /** * The name of the buffer attribute. * * @type {string} */ this.name = ''; /** * The buffer holding the interleaved data. * * @type {InterleavedBuffer} */ this.data = interleavedBuffer; /** * The item size, see {@link BufferAttribute#itemSize}. * * @type {number} */ this.itemSize = itemSize; /** * The attribute offset into the buffer. * * @type {number} */ this.offset = offset; /** * Whether the data are normalized or not, see {@link BufferAttribute#normalized} * * @type {InterleavedBuffer} */ this.normalized = normalized; } /** * The item count of this buffer attribute. * * @type {number} * @readonly */ get count() { return this.data.count; } /** * The array holding the interleaved buffer attribute data. * * @type {TypedArray} */ get array() { return this.data.array; } /** * Flag to indicate that this attribute has changed and should be re-sent to * the GPU. Set this to `true` when you modify the value of the array. * * @type {number} * @default false * @param {boolean} value */ set needsUpdate(value) { this.data.needsUpdate = value; } /** * Applies the given 4x4 matrix to the given attribute. Only works with * item size `3`. * * @param {Matrix4} m - The matrix to apply. * @return {InterleavedBufferAttribute} A reference to this instance. */ applyMatrix4(m) { for (let i = 0, l = this.data.count; i < l; i++) { _vector.fromBufferAttribute(this, i); _vector.applyMatrix4(m); this.setXYZ(i, _vector.x, _vector.y, _vector.z); } return this; } /** * Applies the given 3x3 normal matrix to the given attribute. Only works with * item size `3`. * * @param {Matrix3} m - The normal matrix to apply. * @return {InterleavedBufferAttribute} A reference to this instance. */ applyNormalMatrix(m) { for (let i = 0, l = this.count; i < l; i++) { _vector.fromBufferAttribute(this, i); _vector.applyNormalMatrix(m); this.setXYZ(i, _vector.x, _vector.y, _vector.z); } return this; } /** * Applies the given 4x4 matrix to the given attribute. Only works with * item size `3` and with direction vectors. * * @param {Matrix4} m - The matrix to apply. * @return {InterleavedBufferAttribute} A reference to this instance. */ transformDirection(m) { for (let i = 0, l = this.count; i < l; i++) { _vector.fromBufferAttribute(this, i); _vector.transformDirection(m); this.setXYZ(i, _vector.x, _vector.y, _vector.z); } return this; } /** * Returns the given component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} component - The component index. * @return {number} The returned value. */ getComponent(index, component) { let value = this.array[index * this.data.stride + this.offset + component]; if (this.normalized) value = denormalize(value, this.array); return value; } /** * Sets the given value to the given component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} component - The component index. * @param {number} value - The value to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setComponent(index, component, value) { if (this.normalized) value = normalize(value, this.array); this.data.array[index * this.data.stride + this.offset + component] = value; return this; } /** * Sets the x component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} x - The value to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setX(index, x) { if (this.normalized) x = normalize(x, this.array); this.data.array[index * this.data.stride + this.offset] = x; return this; } /** * Sets the y component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} y - The value to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setY(index, y) { if (this.normalized) y = normalize(y, this.array); this.data.array[index * this.data.stride + this.offset + 1] = y; return this; } /** * Sets the z component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} z - The value to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setZ(index, z) { if (this.normalized) z = normalize(z, this.array); this.data.array[index * this.data.stride + this.offset + 2] = z; return this; } /** * Sets the w component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} w - The value to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setW(index, w) { if (this.normalized) w = normalize(w, this.array); this.data.array[index * this.data.stride + this.offset + 3] = w; return this; } /** * Returns the x component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @return {number} The x component. */ getX(index) { let x = this.data.array[index * this.data.stride + this.offset]; if (this.normalized) x = denormalize(x, this.array); return x; } /** * Returns the y component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @return {number} The y component. */ getY(index) { let y = this.data.array[index * this.data.stride + this.offset + 1]; if (this.normalized) y = denormalize(y, this.array); return y; } /** * Returns the z component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @return {number} The z component. */ getZ(index) { let z = this.data.array[index * this.data.stride + this.offset + 2]; if (this.normalized) z = denormalize(z, this.array); return z; } /** * Returns the w component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @return {number} The w component. */ getW(index) { let w = this.data.array[index * this.data.stride + this.offset + 3]; if (this.normalized) w = denormalize(w, this.array); return w; } /** * Sets the x and y component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} x - The value for the x component to set. * @param {number} y - The value for the y component to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setXY(index, x, y) { index = index * this.data.stride + this.offset; if (this.normalized) { x = normalize(x, this.array); y = normalize(y, this.array); } this.data.array[index + 0] = x; this.data.array[index + 1] = y; return this; } /** * Sets the x, y and z component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} x - The value for the x component to set. * @param {number} y - The value for the y component to set. * @param {number} z - The value for the z component to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setXYZ(index, x, y, z) { index = index * this.data.stride + this.offset; if (this.normalized) { x = normalize(x, this.array); y = normalize(y, this.array); z = normalize(z, this.array); } this.data.array[index + 0] = x; this.data.array[index + 1] = y; this.data.array[index + 2] = z; return this; } /** * Sets the x, y, z and w component of the vector at the given index. * * @param {number} index - The index into the buffer attribute. * @param {number} x - The value for the x component to set. * @param {number} y - The value for the y component to set. * @param {number} z - The value for the z component to set. * @param {number} w - The value for the w component to set. * @return {InterleavedBufferAttribute} A reference to this instance. */ setXYZW(index, x, y, z, w) { index = index * this.data.stride + this.offset; if (this.normalized) { x = normalize(x, this.array); y = normalize(y, this.array); z = normalize(z, this.array); w = normalize(w, this.array); } this.data.array[index + 0] = x; this.data.array[index + 1] = y; this.data.array[index + 2] = z; this.data.array[index + 3] = w; return this; } /** * Returns a new buffer attribute with copied values from this instance. * * If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data. * * @param {Object} [data] - An object with interleaved buffers that allows to retain the interleaved property. * @return {BufferAttribute|InterleavedBufferAttribute} A clone of this instance. */ clone(data) { if (data === undefined) { console.log('THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.'); const array = []; for (let i = 0; i < this.count; i++) { const index = i * this.data.stride + this.offset; for (let j = 0; j < this.itemSize; j++) { array.push(this.data.array[index + j]); } } return new BufferAttribute(new this.array.constructor(array), this.itemSize, this.normalized); } else { if (data.interleavedBuffers === undefined) { data.interleavedBuffers = {}; } if (data.interleavedBuffers[this.data.uuid] === undefined) { data.interleavedBuffers[this.data.uuid] = this.data.clone(data); } return new InterleavedBufferAttribute(data.interleavedBuffers[this.data.uuid], this.itemSize, this.offset, this.normalized); } } /** * Serializes the buffer attribute into JSON. * * If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data. * * @param {Object} [data] - An optional value holding meta information about the serialization. * @return {Object} A JSON object representing the serialized buffer attribute. */ toJSON(data) { if (data === undefined) { console.log('THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.'); const array = []; for (let i = 0; i < this.count; i++) { const index = i * this.data.stride + this.offset; for (let j = 0; j < this.itemSize; j++) { array.push(this.data.array[index + j]); } } // de-interleave data and save it as an ordinary buffer attribute for now return { itemSize: this.itemSize, type: this.array.constructor.name, array: array, normalized: this.normalized }; } else { // save as true interleaved attribute if (data.interleavedBuffers === undefined) { data.interleavedBuffers = {}; } if (data.interleavedBuffers[this.data.uuid] === undefined) { data.interleavedBuffers[this.data.uuid] = this.data.toJSON(data); } return { isInterleavedBufferAttribute: true, itemSize: this.itemSize, data: this.data.uuid, offset: this.offset, normalized: this.normalized }; } } } export { InterleavedBufferAttribute };