MCP 3D Printer Server

by DMontgomery40
Verified
import Node from '../core/Node.js'; import { varyingProperty } from '../core/PropertyNode.js'; import { instancedBufferAttribute, instancedDynamicBufferAttribute } from './BufferAttributeNode.js'; import { normalLocal, transformNormal } from './Normal.js'; import { positionLocal } from './Position.js'; import { nodeProxy, vec3, mat4 } from '../tsl/TSLBase.js'; import { NodeUpdateType } from '../core/constants.js'; import { buffer } from '../accessors/BufferNode.js'; import { instanceIndex } from '../core/IndexNode.js'; import { InstancedInterleavedBuffer } from '../../core/InstancedInterleavedBuffer.js'; import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js'; import { DynamicDrawUsage } from '../../constants.js'; /** @module InstanceNode **/ /** * This node implements the vertex shader logic which is required * when rendering 3D objects via instancing. The code makes sure * vertex positions, normals and colors can be modified via instanced * data. * * @augments Node */ class InstanceNode extends Node { static get type() { return 'InstanceNode'; } /** * Constructs a new instance node. * * @param {Number} count - The number of instances. * @param {InstancedBufferAttribute} instanceMatrix - Instanced buffer attribute representing the instance transformations. * @param {InstancedBufferAttribute} instanceColor - Instanced buffer attribute representing the instance colors. */ constructor( count, instanceMatrix, instanceColor ) { super( 'void' ); /** * The number of instances. * * @type {Number} */ this.count = count; /** * Instanced buffer attribute representing the transformation of instances. * * @type {InstancedBufferAttribute} */ this.instanceMatrix = instanceMatrix; /** * Instanced buffer attribute representing the color of instances. * * @type {InstancedBufferAttribute} */ this.instanceColor = instanceColor; /** * The node that represents the instance matrix data. * * @type {Node} */ this.instanceMatrixNode = null; /** * The node that represents the instance color data. * * @type {Node} */ this.instanceColorNode = null; /** * The update type is set to `frame` since an update * of instanced buffer data must be checked per frame. * * @type {String} * @default 'frame' */ this.updateType = NodeUpdateType.FRAME; /** * A reference to a buffer that is used by `instanceMatrixNode`. * * @type {InstancedInterleavedBuffer} */ this.buffer = null; /** * A reference to a buffer that is used by `instanceColorNode`. * * @type {InstancedBufferAttribute} */ this.bufferColor = null; } /** * Setups the internal buffers and nodes and assigns the transformed vertex data * to predefined node variables for accumulation. That follows the same patterns * like with morph and skinning nodes. * * @param {NodeBuilder} builder - The current node builder. */ setup( builder ) { const { count, instanceMatrix, instanceColor } = this; let { instanceMatrixNode, instanceColorNode } = this; if ( instanceMatrixNode === null ) { // Both WebGPU and WebGL backends have UBO max limited to 64kb. Matrix count number bigger than 1000 ( 16 * 4 * 1000 = 64kb ) will fallback to attribute. if ( count <= 1000 ) { instanceMatrixNode = buffer( instanceMatrix.array, 'mat4', Math.max( count, 1 ) ).element( instanceIndex ); } else { const buffer = new InstancedInterleavedBuffer( instanceMatrix.array, 16, 1 ); this.buffer = buffer; const bufferFn = instanceMatrix.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; const instanceBuffers = [ // F.Signature -> bufferAttribute( array, type, stride, offset ) bufferFn( buffer, 'vec4', 16, 0 ), bufferFn( buffer, 'vec4', 16, 4 ), bufferFn( buffer, 'vec4', 16, 8 ), bufferFn( buffer, 'vec4', 16, 12 ) ]; instanceMatrixNode = mat4( ...instanceBuffers ); } this.instanceMatrixNode = instanceMatrixNode; } if ( instanceColor && instanceColorNode === null ) { const buffer = new InstancedBufferAttribute( instanceColor.array, 3 ); const bufferFn = instanceColor.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; this.bufferColor = buffer; instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) ); this.instanceColorNode = instanceColorNode; } // POSITION const instancePosition = instanceMatrixNode.mul( positionLocal ).xyz; positionLocal.assign( instancePosition ); // NORMAL if ( builder.hasGeometryAttribute( 'normal' ) ) { const instanceNormal = transformNormal( normalLocal, instanceMatrixNode ); // ASSIGNS normalLocal.assign( instanceNormal ); } // COLOR if ( this.instanceColorNode !== null ) { varyingProperty( 'vec3', 'vInstanceColor' ).assign( this.instanceColorNode ); } } /** * Checks if the internal buffers required an update. * * @param {NodeFrame} frame - The current node frame. */ update( /*frame*/ ) { if ( this.instanceMatrix.usage !== DynamicDrawUsage && this.buffer !== null && this.instanceMatrix.version !== this.buffer.version ) { this.buffer.version = this.instanceMatrix.version; } if ( this.instanceColor && this.instanceColor.usage !== DynamicDrawUsage && this.bufferColor !== null && this.instanceColor.version !== this.bufferColor.version ) { this.bufferColor.version = this.instanceColor.version; } } } export default InstanceNode; /** * TSL function for creating an instance node. * * @function * @param {Number} count - The number of instances. * @param {InstancedBufferAttribute} instanceMatrix - Instanced buffer attribute representing the instance transformations. * @param {InstancedBufferAttribute} instanceColor - Instanced buffer attribute representing the instance colors. * @returns {InstanceNode} */ export const instance = /*@__PURE__*/ nodeProxy( InstanceNode );