@openhps/core
Version:
Open Hybrid Positioning System - Core component
294 lines (274 loc) • 9.82 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.instancedDynamicBufferAttribute = exports.instancedBufferAttribute = exports.dynamicBufferAttribute = exports.default = exports.bufferAttribute = void 0;
var _InputNode = _interopRequireDefault(require("../core/InputNode.js"));
var _TSLCore = require("../tsl/TSLCore.js");
var _VaryingNode = require("../core/VaryingNode.js");
var _InterleavedBufferAttribute = require("../../core/InterleavedBufferAttribute.js");
var _InterleavedBuffer = require("../../core/InterleavedBuffer.js");
var _constants = require("../../constants.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* In earlier `three.js` versions it was only possible to define attribute data
* on geometry level. With `BufferAttributeNode`, it is also possible to do this
* on the node level.
* ```js
* const geometry = new THREE.PlaneGeometry();
* const positionAttribute = geometry.getAttribute( 'position' );
*
* const colors = [];
* for ( let i = 0; i < position.count; i ++ ) {
* colors.push( 1, 0, 0 );
* }
*
* material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) );
* ```
* This new approach is especially interesting when geometry data are generated via
* compute shaders. The below line converts a storage buffer into an attribute node.
* ```js
* material.positionNode = positionBuffer.toAttribute();
* ```
* @augments InputNode
*/
class BufferAttributeNode extends _InputNode.default {
static get type() {
return 'BufferAttributeNode';
}
/**
* Constructs a new buffer attribute node.
*
* @param {BufferAttribute|InterleavedBuffer|TypedArray} value - The attribute data.
* @param {?string} [bufferType=null] - The buffer type (e.g. `'vec3'`).
* @param {number} [bufferStride=0] - The buffer stride.
* @param {number} [bufferOffset=0] - The buffer offset.
*/
constructor(value, bufferType = null, bufferStride = 0, bufferOffset = 0) {
super(value, bufferType);
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isBufferNode = true;
/**
* The buffer type (e.g. `'vec3'`).
*
* @type {?string}
* @default null
*/
this.bufferType = bufferType;
/**
* The buffer stride.
*
* @type {number}
* @default 0
*/
this.bufferStride = bufferStride;
/**
* The buffer offset.
*
* @type {number}
* @default 0
*/
this.bufferOffset = bufferOffset;
/**
* The usage property. Set this to `THREE.DynamicDrawUsage` via `.setUsage()`,
* if you are planning to update the attribute data per frame.
*
* @type {number}
* @default StaticDrawUsage
*/
this.usage = _constants.StaticDrawUsage;
/**
* Whether the attribute is instanced or not.
*
* @type {boolean}
* @default false
*/
this.instanced = false;
/**
* A reference to the buffer attribute.
*
* @type {?BufferAttribute}
* @default null
*/
this.attribute = null;
/**
* `BufferAttributeNode` sets this property to `true` by default.
*
* @type {boolean}
* @default true
*/
this.global = true;
if (value && value.isBufferAttribute === true) {
this.attribute = value;
this.usage = value.usage;
this.instanced = value.isInstancedBufferAttribute;
}
}
/**
* This method is overwritten since the attribute data might be shared
* and thus the hash should be shared as well.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {string} The hash.
*/
getHash(builder) {
if (this.bufferStride === 0 && this.bufferOffset === 0) {
let bufferData = builder.globalCache.getData(this.value);
if (bufferData === undefined) {
bufferData = {
node: this
};
builder.globalCache.setData(this.value, bufferData);
}
return bufferData.node.uuid;
}
return this.uuid;
}
/**
* This method is overwritten since the node type is inferred from
* the buffer attribute.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {string} The node type.
*/
getNodeType(builder) {
if (this.bufferType === null) {
this.bufferType = builder.getTypeFromAttribute(this.attribute);
}
return this.bufferType;
}
/**
* Depending on which value was passed to the node, `setup()` behaves
* differently. If no instance of `BufferAttribute` was passed, the method
* creates an internal attribute and configures it respectively.
*
* @param {NodeBuilder} builder - The current node builder.
*/
setup(builder) {
if (this.attribute !== null) return;
const type = this.getNodeType(builder);
const array = this.value;
const itemSize = builder.getTypeLength(type);
const stride = this.bufferStride || itemSize;
const offset = this.bufferOffset;
const buffer = array.isInterleavedBuffer === true ? array : new _InterleavedBuffer.InterleavedBuffer(array, stride);
const bufferAttribute = new _InterleavedBufferAttribute.InterleavedBufferAttribute(buffer, itemSize, offset);
buffer.setUsage(this.usage);
this.attribute = bufferAttribute;
this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute
}
/**
* Generates the code snippet of the buffer attribute node.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {string} The generated code snippet.
*/
generate(builder) {
const nodeType = this.getNodeType(builder);
const nodeAttribute = builder.getBufferAttributeFromNode(this, nodeType);
const propertyName = builder.getPropertyName(nodeAttribute);
let output = null;
if (builder.shaderStage === 'vertex' || builder.shaderStage === 'compute') {
this.name = propertyName;
output = propertyName;
} else {
const nodeVarying = (0, _VaryingNode.varying)(this);
output = nodeVarying.build(builder, nodeType);
}
return output;
}
/**
* Overwrites the default implementation to return a fixed value `'bufferAttribute'`.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {string} The input type.
*/
getInputType( /*builder*/
) {
return 'bufferAttribute';
}
/**
* Sets the `usage` property to the given value.
*
* @param {number} value - The usage to set.
* @return {BufferAttributeNode} A reference to this node.
*/
setUsage(value) {
this.usage = value;
if (this.attribute && this.attribute.isBufferAttribute === true) {
this.attribute.usage = value;
}
return this;
}
/**
* Sets the `instanced` property to the given value.
*
* @param {boolean} value - The value to set.
* @return {BufferAttributeNode} A reference to this node.
*/
setInstanced(value) {
this.instanced = value;
return this;
}
}
var _default = exports.default = BufferAttributeNode;
/**
* TSL function for creating a buffer attribute node.
*
* @tsl
* @function
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
* @param {number} [stride=0] - The buffer stride.
* @param {number} [offset=0] - The buffer offset.
* @returns {BufferAttributeNode}
*/
const bufferAttribute = (array, type = null, stride = 0, offset = 0) => (0, _TSLCore.nodeObject)(new BufferAttributeNode(array, type, stride, offset));
/**
* TSL function for creating a buffer attribute node but with dynamic draw usage.
* Use this function if attribute data are updated per frame.
*
* @tsl
* @function
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
* @param {number} [stride=0] - The buffer stride.
* @param {number} [offset=0] - The buffer offset.
* @returns {BufferAttributeNode}
*/
exports.bufferAttribute = bufferAttribute;
const dynamicBufferAttribute = (array, type = null, stride = 0, offset = 0) => bufferAttribute(array, type, stride, offset).setUsage(_constants.DynamicDrawUsage);
/**
* TSL function for creating a buffer attribute node but with enabled instancing
*
* @tsl
* @function
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
* @param {number} [stride=0] - The buffer stride.
* @param {number} [offset=0] - The buffer offset.
* @returns {BufferAttributeNode}
*/
exports.dynamicBufferAttribute = dynamicBufferAttribute;
const instancedBufferAttribute = (array, type = null, stride = 0, offset = 0) => bufferAttribute(array, type, stride, offset).setInstanced(true);
/**
* TSL function for creating a buffer attribute node but with dynamic draw usage and enabled instancing
*
* @tsl
* @function
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
* @param {number} [stride=0] - The buffer stride.
* @param {number} [offset=0] - The buffer offset.
* @returns {BufferAttributeNode}
*/
exports.instancedBufferAttribute = instancedBufferAttribute;
const instancedDynamicBufferAttribute = (array, type = null, stride = 0, offset = 0) => dynamicBufferAttribute(array, type, stride, offset).setInstanced(true);
exports.instancedDynamicBufferAttribute = instancedDynamicBufferAttribute;
(0, _TSLCore.addMethodChaining)('toAttribute', bufferNode => bufferAttribute(bufferNode.value));