Buckets:
| import { WebGLCoordinateSystem } from '../../constants.js'; | |
| import TempNode from '../core/TempNode.js'; | |
| import { addMethodChaining, Fn, int, nodeProxy } from '../tsl/TSLCore.js'; | |
| const _vectorOperators = { | |
| '==': 'equal', | |
| '!=': 'notEqual', | |
| '<': 'lessThan', | |
| '>': 'greaterThan', | |
| '<=': 'lessThanEqual', | |
| '>=': 'greaterThanEqual', | |
| '%': 'mod' | |
| }; | |
| /** | |
| * This node represents basic mathematical and logical operations like addition, | |
| * subtraction or comparisons (e.g. `equal()`). | |
| * | |
| * @augments TempNode | |
| */ | |
| class OperatorNode extends TempNode { | |
| static get type() { | |
| return 'OperatorNode'; | |
| } | |
| /** | |
| * Constructs a new operator node. | |
| * | |
| * @param {string} op - The operator. | |
| * @param {Node} aNode - The first input. | |
| * @param {Node} bNode - The second input. | |
| * @param {...Node} params - Additional input parameters. | |
| */ | |
| constructor( op, aNode, bNode, ...params ) { | |
| super(); | |
| if ( params.length > 0 ) { | |
| let finalOp = new OperatorNode( op, aNode, bNode ); | |
| for ( let i = 0; i < params.length - 1; i ++ ) { | |
| finalOp = new OperatorNode( op, finalOp, params[ i ] ); | |
| } | |
| aNode = finalOp; | |
| bNode = params[ params.length - 1 ]; | |
| } | |
| /** | |
| * The operator. | |
| * | |
| * @type {string} | |
| */ | |
| this.op = op; | |
| /** | |
| * The first input. | |
| * | |
| * @type {Node} | |
| */ | |
| this.aNode = aNode; | |
| /** | |
| * The second input. | |
| * | |
| * @type {Node} | |
| */ | |
| this.bNode = bNode; | |
| /** | |
| * This flag can be used for type testing. | |
| * | |
| * @type {boolean} | |
| * @readonly | |
| * @default true | |
| */ | |
| this.isOperatorNode = true; | |
| } | |
| /** | |
| * Returns the operator method name. | |
| * | |
| * @param {NodeBuilder} builder - The current node builder. | |
| * @param {string} output - The output type. | |
| * @returns {string} The operator method name. | |
| */ | |
| getOperatorMethod( builder, output ) { | |
| return builder.getMethod( _vectorOperators[ this.op ], output ); | |
| } | |
| /** | |
| * This method is overwritten since the node type is inferred from the operator | |
| * and the input node types. | |
| * | |
| * @param {NodeBuilder} builder - The current node builder. | |
| * @return {string} The node type. | |
| */ | |
| getNodeType( builder ) { | |
| const op = this.op; | |
| const aNode = this.aNode; | |
| const bNode = this.bNode; | |
| const typeA = aNode.getNodeType( builder ); | |
| const typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; | |
| if ( typeA === 'void' || typeB === 'void' ) { | |
| return 'void'; | |
| } else if ( op === '%' ) { | |
| return typeA; | |
| } else if ( op === '~' || op === '&' || op === '|' || op === '^' || op === '>>' || op === '<<' ) { | |
| return builder.getIntegerType( typeA ); | |
| } else if ( op === '!' || op === '&&' || op === '||' || op === '^^' ) { | |
| return 'bool'; | |
| } else if ( op === '==' || op === '!=' || op === '<' || op === '>' || op === '<=' || op === '>=' ) { | |
| const typeLength = Math.max( builder.getTypeLength( typeA ), builder.getTypeLength( typeB ) ); | |
| return typeLength > 1 ? `bvec${ typeLength }` : 'bool'; | |
| } else { | |
| // Handle matrix operations | |
| if ( builder.isMatrix( typeA ) ) { | |
| if ( typeB === 'float' ) { | |
| return typeA; // matrix * scalar = matrix | |
| } else if ( builder.isVector( typeB ) ) { | |
| return builder.getVectorFromMatrix( typeA ); // matrix * vector | |
| } else if ( builder.isMatrix( typeB ) ) { | |
| return typeA; // matrix * matrix | |
| } | |
| } else if ( builder.isMatrix( typeB ) ) { | |
| if ( typeA === 'float' ) { | |
| return typeB; // scalar * matrix = matrix | |
| } else if ( builder.isVector( typeA ) ) { | |
| return builder.getVectorFromMatrix( typeB ); // vector * matrix | |
| } | |
| } | |
| // Handle non-matrix cases | |
| if ( builder.getTypeLength( typeB ) > builder.getTypeLength( typeA ) ) { | |
| // anytype x anytype: use the greater length vector | |
| return typeB; | |
| } | |
| return typeA; | |
| } | |
| } | |
| generate( builder, output ) { | |
| const op = this.op; | |
| const aNode = this.aNode; | |
| const bNode = this.bNode; | |
| const type = this.getNodeType( builder ); | |
| let typeA = null; | |
| let typeB = null; | |
| if ( type !== 'void' ) { | |
| typeA = aNode.getNodeType( builder ); | |
| typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; | |
| if ( op === '<' || op === '>' || op === '<=' || op === '>=' || op === '==' || op === '!=' ) { | |
| if ( builder.isVector( typeA ) ) { | |
| typeB = typeA; | |
| } else if ( builder.isVector( typeB ) ) { | |
| typeA = typeB; | |
| } else if ( typeA !== typeB ) { | |
| typeA = typeB = 'float'; | |
| } | |
| } else if ( op === '>>' || op === '<<' ) { | |
| typeA = type; | |
| typeB = builder.changeComponentType( typeB, 'uint' ); | |
| } else if ( op === '%' ) { | |
| typeA = type; | |
| typeB = builder.isInteger( typeA ) && builder.isInteger( typeB ) ? typeB : typeA; | |
| } else if ( builder.isMatrix( typeA ) ) { | |
| if ( typeB === 'float' ) { | |
| // Keep matrix type for typeA, but ensure typeB stays float | |
| typeB = 'float'; | |
| } else if ( builder.isVector( typeB ) ) { | |
| // matrix x vector | |
| typeB = builder.getVectorFromMatrix( typeA ); | |
| } else if ( builder.isMatrix( typeB ) ) { | |
| // matrix x matrix - keep both types | |
| } else { | |
| typeA = typeB = type; | |
| } | |
| } else if ( builder.isMatrix( typeB ) ) { | |
| if ( typeA === 'float' ) { | |
| // Keep matrix type for typeB, but ensure typeA stays float | |
| typeA = 'float'; | |
| } else if ( builder.isVector( typeA ) ) { | |
| // vector x matrix | |
| typeA = builder.getVectorFromMatrix( typeB ); | |
| } else { | |
| typeA = typeB = type; | |
| } | |
| } else { | |
| // anytype x anytype | |
| typeA = typeB = type; | |
| } | |
| } else { | |
| typeA = typeB = type; | |
| } | |
| const a = aNode.build( builder, typeA ); | |
| const b = typeof bNode !== 'undefined' ? bNode.build( builder, typeB ) : null; | |
| const fnOpSnippet = builder.getFunctionOperator( op ); | |
| if ( output !== 'void' ) { | |
| const isGLSL = builder.renderer.coordinateSystem === WebGLCoordinateSystem; | |
| if ( op === '==' || op === '!=' || op === '<' || op === '>' || op === '<=' || op === '>=' ) { | |
| if ( isGLSL ) { | |
| if ( builder.isVector( typeA ) ) { | |
| return builder.format( `${ this.getOperatorMethod( builder, output ) }( ${ a }, ${ b } )`, type, output ); | |
| } else { | |
| return builder.format( `( ${ a } ${ op } ${ b } )`, type, output ); | |
| } | |
| } else { | |
| // WGSL | |
| return builder.format( `( ${ a } ${ op } ${ b } )`, type, output ); | |
| } | |
| } else if ( op === '%' ) { | |
| if ( builder.isInteger( typeB ) ) { | |
| return builder.format( `( ${ a } % ${ b } )`, type, output ); | |
| } else { | |
| return builder.format( `${ this.getOperatorMethod( builder, type ) }( ${ a }, ${ b } )`, type, output ); | |
| } | |
| } else if ( op === '!' || op === '~' ) { | |
| return builder.format( `(${op}${a})`, typeA, output ); | |
| } else if ( fnOpSnippet ) { | |
| return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); | |
| } else { | |
| // Handle matrix operations | |
| if ( builder.isMatrix( typeA ) && typeB === 'float' ) { | |
| return builder.format( `( ${ b } ${ op } ${ a } )`, type, output ); | |
| } else if ( typeA === 'float' && builder.isMatrix( typeB ) ) { | |
| return builder.format( `${ a } ${ op } ${ b }`, type, output ); | |
| } else { | |
| let snippet = `( ${ a } ${ op } ${ b } )`; | |
| if ( ! isGLSL && type === 'bool' && builder.isVector( typeA ) && builder.isVector( typeB ) ) { | |
| snippet = `all${ snippet }`; | |
| } | |
| return builder.format( snippet, type, output ); | |
| } | |
| } | |
| } else if ( typeA !== 'void' ) { | |
| if ( fnOpSnippet ) { | |
| return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); | |
| } else { | |
| if ( builder.isMatrix( typeA ) && typeB === 'float' ) { | |
| return builder.format( `${ b } ${ op } ${ a }`, type, output ); | |
| } else { | |
| return builder.format( `${ a } ${ op } ${ b }`, type, output ); | |
| } | |
| } | |
| } | |
| } | |
| serialize( data ) { | |
| super.serialize( data ); | |
| data.op = this.op; | |
| } | |
| deserialize( data ) { | |
| super.deserialize( data ); | |
| this.op = data.op; | |
| } | |
| } | |
| export default OperatorNode; | |
| /** | |
| * Returns the addition of two or more value. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @param {...Node} params - Additional input parameters. | |
| * @returns {OperatorNode} | |
| */ | |
| export const add = /*@__PURE__*/ nodeProxy( OperatorNode, '+' ).setParameterLength( 2, Infinity ).setName( 'add' ); | |
| /** | |
| * Returns the subtraction of two or more value. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @param {...Node} params - Additional input parameters. | |
| * @returns {OperatorNode} | |
| */ | |
| export const sub = /*@__PURE__*/ nodeProxy( OperatorNode, '-' ).setParameterLength( 2, Infinity ).setName( 'sub' ); | |
| /** | |
| * Returns the multiplication of two or more value. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @param {...Node} params - Additional input parameters. | |
| * @returns {OperatorNode} | |
| */ | |
| export const mul = /*@__PURE__*/ nodeProxy( OperatorNode, '*' ).setParameterLength( 2, Infinity ).setName( 'mul' ); | |
| /** | |
| * Returns the division of two or more value. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @param {...Node} params - Additional input parameters. | |
| * @returns {OperatorNode} | |
| */ | |
| export const div = /*@__PURE__*/ nodeProxy( OperatorNode, '/' ).setParameterLength( 2, Infinity ).setName( 'div' ); | |
| /** | |
| * Computes the remainder of dividing the first node by the second one. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const mod = /*@__PURE__*/ nodeProxy( OperatorNode, '%' ).setParameterLength( 2 ).setName( 'mod' ); | |
| /** | |
| * Checks if two nodes are equal. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const equal = /*@__PURE__*/ nodeProxy( OperatorNode, '==' ).setParameterLength( 2 ).setName( 'equal' ); | |
| /** | |
| * Checks if two nodes are not equal. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const notEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '!=' ).setParameterLength( 2 ).setName( 'notEqual' ); | |
| /** | |
| * Checks if the first node is less than the second. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const lessThan = /*@__PURE__*/ nodeProxy( OperatorNode, '<' ).setParameterLength( 2 ).setName( 'lessThan' ); | |
| /** | |
| * Checks if the first node is greater than the second. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const greaterThan = /*@__PURE__*/ nodeProxy( OperatorNode, '>' ).setParameterLength( 2 ).setName( 'greaterThan' ); | |
| /** | |
| * Checks if the first node is less than or equal to the second. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const lessThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '<=' ).setParameterLength( 2 ).setName( 'lessThanEqual' ); | |
| /** | |
| * Checks if the first node is greater than or equal to the second. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const greaterThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '>=' ).setParameterLength( 2 ).setName( 'greaterThanEqual' ); | |
| /** | |
| * Performs a logical AND operation on multiple nodes. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {...Node} nodes - The input nodes to be combined using AND. | |
| * @returns {OperatorNode} | |
| */ | |
| export const and = /*@__PURE__*/ nodeProxy( OperatorNode, '&&' ).setParameterLength( 2, Infinity ).setName( 'and' ); | |
| /** | |
| * Performs a logical OR operation on multiple nodes. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {...Node} nodes - The input nodes to be combined using OR. | |
| * @returns {OperatorNode} | |
| */ | |
| export const or = /*@__PURE__*/ nodeProxy( OperatorNode, '||' ).setParameterLength( 2, Infinity ).setName( 'or' ); | |
| /** | |
| * Performs logical NOT on a node. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} value - The value. | |
| * @returns {OperatorNode} | |
| */ | |
| export const not = /*@__PURE__*/ nodeProxy( OperatorNode, '!' ).setParameterLength( 1 ).setName( 'not' ); | |
| /** | |
| * Performs logical XOR on two nodes. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const xor = /*@__PURE__*/ nodeProxy( OperatorNode, '^^' ).setParameterLength( 2 ).setName( 'xor' ); | |
| /** | |
| * Performs bitwise AND on two nodes. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const bitAnd = /*@__PURE__*/ nodeProxy( OperatorNode, '&' ).setParameterLength( 2 ).setName( 'bitAnd' ); | |
| /** | |
| * Performs bitwise NOT on a node. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const bitNot = /*@__PURE__*/ nodeProxy( OperatorNode, '~' ).setParameterLength( 2 ).setName( 'bitNot' ); | |
| /** | |
| * Performs bitwise OR on two nodes. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const bitOr = /*@__PURE__*/ nodeProxy( OperatorNode, '|' ).setParameterLength( 2 ).setName( 'bitOr' ); | |
| /** | |
| * Performs bitwise XOR on two nodes. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const bitXor = /*@__PURE__*/ nodeProxy( OperatorNode, '^' ).setParameterLength( 2 ).setName( 'bitXor' ); | |
| /** | |
| * Shifts a node to the left. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The node to shift. | |
| * @param {Node} b - The value to shift. | |
| * @returns {OperatorNode} | |
| */ | |
| export const shiftLeft = /*@__PURE__*/ nodeProxy( OperatorNode, '<<' ).setParameterLength( 2 ).setName( 'shiftLeft' ); | |
| /** | |
| * Shifts a node to the right. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The node to shift. | |
| * @param {Node} b - The value to shift. | |
| * @returns {OperatorNode} | |
| */ | |
| export const shiftRight = /*@__PURE__*/ nodeProxy( OperatorNode, '>>' ).setParameterLength( 2 ).setName( 'shiftRight' ); | |
| /** | |
| * Increments a node by 1. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The node to increment. | |
| * @returns {OperatorNode} | |
| */ | |
| export const incrementBefore = Fn( ( [ a ] ) => { | |
| a.addAssign( 1 ); | |
| return a; | |
| } ); | |
| /** | |
| * Decrements a node by 1. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The node to decrement. | |
| * @returns {OperatorNode} | |
| */ | |
| export const decrementBefore = Fn( ( [ a ] ) => { | |
| a.subAssign( 1 ); | |
| return a; | |
| } ); | |
| /** | |
| * Increments a node by 1 and returns the previous value. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The node to increment. | |
| * @returns {OperatorNode} | |
| */ | |
| export const increment = /*@__PURE__*/ Fn( ( [ a ] ) => { | |
| const temp = int( a ).toConst(); | |
| a.addAssign( 1 ); | |
| return temp; | |
| } ); | |
| /** | |
| * Decrements a node by 1 and returns the previous value. | |
| * | |
| * @tsl | |
| * @function | |
| * @param {Node} a - The node to decrement. | |
| * @returns {OperatorNode} | |
| */ | |
| export const decrement = /*@__PURE__*/ Fn( ( [ a ] ) => { | |
| const temp = int( a ).toConst(); | |
| a.subAssign( 1 ); | |
| return temp; | |
| } ); | |
| addMethodChaining( 'add', add ); | |
| addMethodChaining( 'sub', sub ); | |
| addMethodChaining( 'mul', mul ); | |
| addMethodChaining( 'div', div ); | |
| addMethodChaining( 'mod', mod ); | |
| addMethodChaining( 'equal', equal ); | |
| addMethodChaining( 'notEqual', notEqual ); | |
| addMethodChaining( 'lessThan', lessThan ); | |
| addMethodChaining( 'greaterThan', greaterThan ); | |
| addMethodChaining( 'lessThanEqual', lessThanEqual ); | |
| addMethodChaining( 'greaterThanEqual', greaterThanEqual ); | |
| addMethodChaining( 'and', and ); | |
| addMethodChaining( 'or', or ); | |
| addMethodChaining( 'not', not ); | |
| addMethodChaining( 'xor', xor ); | |
| addMethodChaining( 'bitAnd', bitAnd ); | |
| addMethodChaining( 'bitNot', bitNot ); | |
| addMethodChaining( 'bitOr', bitOr ); | |
| addMethodChaining( 'bitXor', bitXor ); | |
| addMethodChaining( 'shiftLeft', shiftLeft ); | |
| addMethodChaining( 'shiftRight', shiftRight ); | |
| addMethodChaining( 'incrementBefore', incrementBefore ); | |
| addMethodChaining( 'decrementBefore', decrementBefore ); | |
| addMethodChaining( 'increment', increment ); | |
| addMethodChaining( 'decrement', decrement ); | |
| /** | |
| * @tsl | |
| * @function | |
| * @deprecated since r168. Use {@link mod} instead. | |
| * | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const remainder = ( a, b ) => { // @deprecated, r168 | |
| console.warn( 'THREE.TSL: "remainder()" is deprecated. Use "mod( int( ... ) )" instead.' ); | |
| return mod( a, b ); | |
| }; | |
| /** | |
| * @tsl | |
| * @function | |
| * @deprecated since r175. Use {@link mod} instead. | |
| * | |
| * @param {Node} a - The first input. | |
| * @param {Node} b - The second input. | |
| * @returns {OperatorNode} | |
| */ | |
| export const modInt = ( a, b ) => { // @deprecated, r175 | |
| console.warn( 'THREE.TSL: "modInt()" is deprecated. Use "mod( int( ... ) )" instead.' ); | |
| return mod( int( a ), int( b ) ); | |
| }; | |
| addMethodChaining( 'remainder', remainder ); | |
| addMethodChaining( 'modInt', modInt ); | |
Xet Storage Details
- Size:
- 17.4 kB
- Xet hash:
- 2f3b4a381134477ba94ceb675c1123b9122ca20448b823dd7c6bd37c19ee5194
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.