UNPKG

@polygonjs/polygonjs

Version:

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

161 lines (151 loc) 6.05 kB
/** * Creates a plane with a distorted reflection, to simulate an ocean surface * * @remarks * * Without any input, this node creates a very large plane. * If you would like the ocean to be restricted to a smaller area, such as a disk, * you can plug in an input geometry. Just make sure that this geometry should be facing the z axis, * as it will currently be rotated internally to face the y axis. Note that this behavior may change in the future * to be made more intuitive. * */ import {TypedSopNode} from './_Base'; import {CoreGroup} from '../../../core/geometry/Group'; import {DEFAULT_PARAMS, DEFAULT_OCEAN_PARAMS} from '../../operations/sop/OceanPlane'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import {Number3} from '../../../types/GlobalTypes'; import {Poly} from '../../Poly'; import {Object3D, Mesh} from 'three'; import {isBooleanTrue} from '../../../core/Type'; import {Water, WaterOptions} from '../../../modules/core/objects/Water'; import {replaceChild} from '../../poly/PolyOnObjectsAddRemoveHooksController'; const DEFAULT = DEFAULT_PARAMS; class OceanPlaneSopParamsConfig extends NodeParamsConfig { main = ParamConfig.FOLDER(); /** @param reflection direction */ direction = ParamConfig.VECTOR3(DEFAULT.direction.toArray()); /** @param sun direction */ sunDirection = ParamConfig.VECTOR3(DEFAULT.sunDirection.toArray()); /** @param sun color */ sunColor = ParamConfig.COLOR(DEFAULT.sunColor.toArray() as Number3); /** @param water color */ waterColor = ParamConfig.COLOR(DEFAULT.waterColor.toArray() as Number3); /** @param reflection color */ reflectionColor = ParamConfig.COLOR(DEFAULT.reflectionColor.toArray() as Number3); /** @param reflection fresnel */ reflectionFresnel = ParamConfig.FLOAT(DEFAULT.reflectionFresnel); /** @param waves Height */ wavesHeight = ParamConfig.FLOAT(DEFAULT.wavesHeight, { range: [0, 10], rangeLocked: [false, false], }); /** @param distortion scale */ distortionScale = ParamConfig.FLOAT(DEFAULT.distortionScale, { range: [0, 1], rangeLocked: [true, false], }); /** @param distortion speed */ timeScale = ParamConfig.FLOAT(DEFAULT.timeScale, { range: [0, 2], rangeLocked: [true, false], }); /** @param size */ size = ParamConfig.FLOAT(DEFAULT.size, { range: [0, 100], rangeLocked: [true, false], }); advanced = ParamConfig.FOLDER(); /** @param render reflection */ renderReflection = ParamConfig.BOOLEAN(DEFAULT.renderReflection); /** @param normal Bias - adjusts this if the reflections are too grainy */ normalBias = ParamConfig.FLOAT(DEFAULT.normalBias, { range: [0, 0.1], rangeLocked: [false, false], }); /** @param multisamples */ multisamples = ParamConfig.INTEGER(DEFAULT.multisamples, { range: [0, 4], rangeLocked: [true, false], }); /** @param reacts to fog */ useFog = ParamConfig.BOOLEAN(DEFAULT.useFog); } const ParamsConfig = new OceanPlaneSopParamsConfig(); export class OceanPlaneSopNode extends TypedSopNode<OceanPlaneSopParamsConfig> { override paramsConfig = ParamsConfig; static override type() { return 'oceanPlane'; } override initializeNode() { this.io.inputs.setCount(1); } override cook(inputCoreGroups: CoreGroup[]) { const coreGroup = inputCoreGroups[0]; const objects = coreGroup.threejsObjectsWithGeo(); for (const object of objects) { Poly.onObjectsAddRemoveHooks.assignOnAddHookHandler(object, this); } this.setCoreGroup(coreGroup); } public override updateObjectOnAdd(object: Object3D, parent: Object3D) { const _geometry = (object as Mesh).geometry; if (!_geometry) { return; } // since the geometry is rotated in this method, // we could end up with rotating it multiple times // if we were to toggle the display flag between this node and another. // The current fix is to clone the geometry before transforming it. const clonedGeometry = _geometry.clone(); const scene = this.scene(); const renderer = scene.renderersRegister.lastRegisteredRenderer(); Water.rotateGeometry(clonedGeometry, this.pv.direction); const waterOptions: WaterOptions = { polyScene: this.scene(), scene: scene.threejsScene(), renderer, ...DEFAULT_OCEAN_PARAMS, direction: this.pv.direction, sunDirection: this.pv.sunDirection, sunColor: this.pv.sunColor, wavesHeight: this.pv.wavesHeight, waterColor: this.pv.waterColor, reflectionColor: this.pv.reflectionColor, reflectionFresnel: this.pv.reflectionFresnel, distortionScale: this.pv.distortionScale, timeScale: this.pv.timeScale, size: this.pv.size, // renderReflection: params.renderReflection, normalBias: this.pv.normalBias, multisamples: this.pv.multisamples, useFog: this.pv.useFog, }; const water = new Water(clonedGeometry, waterOptions); water.matrixAutoUpdate = false; // make sure object attributes are up to date object.matrix.decompose(object.position, object.quaternion, object.scale); water.position.copy(object.position); water.rotation.copy(object.rotation); water.scale.copy(object.scale); water.updateMatrix(); Water.compensateGeometryRotation(water, this.pv.direction); // // water.updateMatrix(); // water.matrixAutoUpdate = false; const material = water.material; material.uniforms.direction.value.copy(this.pv.direction); material.uniforms.sunDirection.value.copy(this.pv.sunDirection); material.uniforms.sunColor.value.copy(this.pv.sunColor); material.uniforms.wavesHeight.value = this.pv.wavesHeight; material.uniforms.waterColor.value.copy(this.pv.waterColor); material.uniforms.reflectionColor.value.copy(this.pv.reflectionColor); material.uniforms.reflectionFresnel.value = this.pv.reflectionFresnel; material.uniforms.distortionScale.value = this.pv.distortionScale; material.uniforms.timeScale.value = this.pv.timeScale; material.uniforms.size.value = this.pv.size; material.uniforms.normalBias.value = this.pv.normalBias; water.setReflectionActive(isBooleanTrue(this.pv.renderReflection)); replaceChild(parent, object, water); } }