three
Version:
JavaScript 3D library
123 lines (69 loc) • 3.1 kB
JavaScript
import Node, { addNodeClass } from '../core/Node.js';
import { getValueType } from '../core/NodeUtils.js';
import { attribute } from '../core/AttributeNode.js';
import { nodeProxy, float } from '../shadernode/ShaderNode.js';
import { MathUtils, InstancedBufferAttribute } from 'three';
class RangeNode extends Node {
constructor( minNode = float(), maxNode = float() ) {
super();
this.minNode = minNode;
this.maxNode = maxNode;
}
getVectorLength( builder ) {
const minLength = builder.getTypeLength( getValueType( this.minNode.value ) );
const maxLength = builder.getTypeLength( getValueType( this.maxNode.value ) );
return minLength > maxLength ? minLength : maxLength;
}
getNodeType( builder ) {
return builder.object.isInstancedMesh === true ? builder.getTypeFromLength( this.getVectorLength( builder ) ) : 'float';
}
construct( builder ) {
const object = builder.object;
let output = null;
if ( object.isInstancedMesh === true ) {
const geometry = builder.geometry;
let min = this.minNode.value;
let max = this.maxNode.value;
const minLength = builder.getTypeLength( getValueType( min ) );
const maxLength = builder.getTypeLength( getValueType( max ) );
if ( minLength > maxLength && maxLength > 1 ) max = new min.constructor().fromArray( min.toArray() );
else if ( minLength > maxLength && maxLength === 1 ) max = new min.constructor().setScalar( max );
else if ( maxLength > minLength && minLength > 1 ) min = new max.constructor().fromArray( min.toArray() );
else if ( maxLength > minLength && minLength === 1 ) min = new max.constructor().setScalar( min );
const vectorLength = this.getVectorLength( builder );
const attributeName = 'node' + this.id;
const length = vectorLength * object.count;
const array = new Float32Array( length );
const attributeGeometry = geometry.getAttribute( attributeName );
if ( attributeGeometry === undefined || attributeGeometry.array.length < length ) {
if ( vectorLength === 1 ) {
for ( let i = 0; i < length; i ++ ) {
array[ i ] = MathUtils.lerp( min, max, Math.random() );
}
} else if ( min.isColor ) {
for ( let i = 0; i < length; i += 3 ) {
array[ i ] = MathUtils.lerp( min.r, max.r, Math.random() );
array[ i + 1 ] = MathUtils.lerp( min.g, max.g, Math.random() );
array[ i + 2 ] = MathUtils.lerp( min.b, max.b, Math.random() );
}
} else {
for ( let i = 0; i < length; i ++ ) {
const index = i % vectorLength;
const minValue = min.getComponent( index );
const maxValue = max.getComponent( index );
array[ i ] = MathUtils.lerp( minValue, maxValue, Math.random() );
}
}
geometry.setAttribute( attributeName, new InstancedBufferAttribute( array, vectorLength ) );
geometry.dispose();
}
output = attribute( attributeName, builder.getTypeFromLength( vectorLength ) );
} else {
output = float( 0 );
}
return output;
}
}
export default RangeNode;
export const range = nodeProxy( RangeNode );
addNodeClass( RangeNode );