UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

149 lines (135 loc) 5.22 kB
/** * Remaps an attribute * * @remarks * This is very handy when you have an attribute with values between 0 and 1, and you want to remap those values with a ramp. * */ import {Vector2} from 'three'; import {Vector3} from 'three'; import {Vector4} from 'three'; import {TypedSopNode} from './_Base'; import {CoreGroup} from '../../../core/geometry/Group'; import {AttribSize} from '../../../core/geometry/Constant'; import {TypeAssert} from '../../poly/Assert'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import {AttribValue, NumericAttribValue} from '../../../types/GlobalTypes'; import {isBooleanTrue} from '../../../core/BooleanValue'; import {CoreObjectType, ObjectContent} from '../../../core/geometry/ObjectContent'; import {pointsFromObject} from '../../../core/geometry/entities/point/CorePointUtils'; import {corePointClassFactory} from '../../../core/geometry/CoreObjectFactory'; import {CorePoint} from '../../../core/geometry/entities/point/CorePoint'; const _points: CorePoint<CoreObjectType>[] = []; class AttribRemapSopParamsConfig extends NodeParamsConfig { /** @param name of the attribute to remap */ name = ParamConfig.STRING(); /** @param ramp used to remap */ ramp = ParamConfig.RAMP(); /** @param toggle if you want to create a new attribute */ changeName = ParamConfig.BOOLEAN(0); /** @param new attribute name */ newName = ParamConfig.STRING('', {visibleIf: {changeName: 1}}); } const ParamsConfig = new AttribRemapSopParamsConfig(); export class AttribRemapSopNode extends TypedSopNode<AttribRemapSopParamsConfig> { override paramsConfig = ParamsConfig; static override type() { return 'attribRemap'; } override initializeNode() { this.io.inputs.setCount(1); } override cook(inputCoreGroups: CoreGroup[]) { const coreGroup = inputCoreGroups[0]; const objects = coreGroup.allObjects(); for (const object of objects) { this._remapAttribute(object); } this.setCoreGroup(coreGroup); } private _remapAttribute<T extends CoreObjectType>(object: ObjectContent<T>) { pointsFromObject(object, _points); if (_points.length === 0) { return; } if (this.pv.name === '') { return; } const corePointClass = corePointClassFactory(object); const attribSize = corePointClass.attribSize(object, this.pv.name); const values = _points.map((point) => point.attribValue(this.pv.name)); // let min: NumericAttribValue, max: NumericAttribValue; const remapedValues: NumericAttribValue[] = new Array(_points.length); this._get_remaped_values(attribSize, values, remapedValues); let targetName = this.pv.name; if (isBooleanTrue(this.pv.changeName)) { targetName = this.pv.newName; if (!corePointClass.hasAttribute(object, targetName)) { corePointClass.addNumericAttribute(object, targetName, attribSize, 0); } } let i = 0; for (const normalized_value of remapedValues) { _points[i].setAttribValue(targetName, normalized_value); i++; } } private _get_remaped_values(attrib_size: AttribSize, values: AttribValue[], remaped_values: NumericAttribValue[]) { switch (attrib_size) { case AttribSize.FLOAT: return this._getNormalizedFloat(values, remaped_values); case AttribSize.VECTOR2: return this._getNormalizedVector2(values, remaped_values); case AttribSize.VECTOR3: return this._getNormalizedVector3(values, remaped_values); case AttribSize.VECTOR4: return this._getNormalizedVector4(values, remaped_values); } TypeAssert.unreachable(attrib_size); } private _getNormalizedFloat(values: AttribValue[], remaped_values: NumericAttribValue[]) { const valuesf = values as number[]; const ramp_param = this.p.ramp; for (let i = 0; i < valuesf.length; i++) { const value = valuesf[i]; const remaped_value = ramp_param.valueAtPosition(value); remaped_values[i] = remaped_value; } } private _getNormalizedVector2(values: AttribValue[], remaped_values: NumericAttribValue[]) { const valuesv = values as Vector2[]; const ramp_param = this.p.ramp; for (let i = 0; i < valuesv.length; i++) { const value = valuesv[i]; const remaped_value = new Vector2(ramp_param.valueAtPosition(value.x), ramp_param.valueAtPosition(value.y)); remaped_values[i] = remaped_value; } } private _getNormalizedVector3(values: AttribValue[], remaped_values: NumericAttribValue[]) { const valuesv = values as Vector3[]; const ramp_param = this.p.ramp; for (let i = 0; i < valuesv.length; i++) { const value = valuesv[i]; const remaped_value = new Vector3( ramp_param.valueAtPosition(value.x), ramp_param.valueAtPosition(value.y), ramp_param.valueAtPosition(value.z) ); remaped_values[i] = remaped_value; } } private _getNormalizedVector4(values: AttribValue[], remaped_values: NumericAttribValue[]) { const valuesv = values as Vector4[]; const ramp_param = this.p.ramp; for (let i = 0; i < valuesv.length; i++) { const value = valuesv[i]; const remaped_value = new Vector4( ramp_param.valueAtPosition(value.x), ramp_param.valueAtPosition(value.y), ramp_param.valueAtPosition(value.z), ramp_param.valueAtPosition(value.w) ); remaped_values[i] = remaped_value; } } }