UNPKG

@polygonjs/polygonjs

Version:

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

146 lines (125 loc) 4.27 kB
import {ParamConfig} from '../../engine/nodes/utils/params/ParamsConfig'; import {Constructor, Number3} from '../../types/GlobalTypes'; // import {ColorConversion} from '../Color'; import {DefaultOperationParams} from '../operations/_Base'; import { Color, Group, BackSide, BufferGeometry, Float32BufferAttribute, Line, LineBasicMaterial, Mesh, MeshBasicMaterial, RectAreaLight, } from 'three'; export interface AreaLightParams extends DefaultOperationParams { color: Color; intensity: number; width: number; height: number; showHelper: boolean; name: string; } export const DEFAULT_AREA_LIGHT_PARAMS: AreaLightParams = { color: new Color(1, 1, 1), intensity: 1, width: 1, height: 1, showHelper: false, name: 'areaLight', }; const DEFAULT = DEFAULT_AREA_LIGHT_PARAMS; export function AreaLightParamConfig<TBase extends Constructor>(Base: TBase) { return class Mixin extends Base { light = ParamConfig.FOLDER(); /** @param light color */ color = ParamConfig.COLOR(DEFAULT.color.toArray() as Number3, { // conversion: ColorConversion.SRGB_TO_LINEAR, }); /** @param light intensity */ intensity = ParamConfig.FLOAT(DEFAULT.intensity, { range: [0, 10], rangeLocked: [true, false], }); /** @param grid width */ width = ParamConfig.FLOAT(DEFAULT.width, { range: [0, 10], rangeLocked: [true, false], }); /** @param grid height */ height = ParamConfig.FLOAT(DEFAULT.height, { range: [0, 10], rangeLocked: [true, false], }); // helper /** @param toggle on to show helper */ showHelper = ParamConfig.BOOLEAN(DEFAULT.showHelper); /** @param light name */ name = ParamConfig.STRING('`$OS`'); }; } /** * This helper must be added as a child of the light */ function createLineGeo() { const geometry = new BufferGeometry(); const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0].map((i) => i * 0.5); geometry.setAttribute('position', new Float32BufferAttribute(positions, 3)); geometry.computeBoundingSphere(); return geometry; } function createMeshGeo() { const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0].map((i) => i * 0.5); const geometry = new BufferGeometry(); geometry.setAttribute('position', new Float32BufferAttribute(positions, 3)); geometry.computeBoundingSphere(); return geometry; } // inherits from Group and not Line, to ensure that .copy can pass the recursive argument export class CoreRectAreaLightHelper extends Group { public _childMesh = new Mesh(createMeshGeo(), new MeshBasicMaterial({side: BackSide, fog: false})); public _childLine = new Line(createLineGeo(), new LineBasicMaterial()); constructor(public light: RectAreaLight, public readonly nodeName: string) { super(); this.matrixAutoUpdate = false; this._childMesh.matrixAutoUpdate = false; this._childLine.matrixAutoUpdate = false; this.name = `CoreRectAreaLightHelper_${this.nodeName}`; this._childMesh.name = `CoreRectAreaLightHelperChildMesh_${this.nodeName}`; this._childLine.name = `CoreRectAreaLightHelperChildLine_${this.nodeName}`; this.add(this._childMesh); this.add(this._childLine); } update() { this.scale.set(1 * this.light.width, 1 * this.light.height, 1); this.updateMatrix(); this._childLine.material.color.copy(this.light.color).multiplyScalar(this.light.intensity); // prevent hue shift const c = this._childLine.material.color; const max = Math.max(c.r, c.g, c.b); if (max > 1) c.multiplyScalar(1 / max); this._childMesh.material.color.copy(this._childLine.material.color); // ignore world scale on light this.matrixWorld.extractRotation(this.light.matrixWorld).scale(this.scale).copyPosition(this.light.matrixWorld); this._childMesh.matrixWorld.copy(this.matrixWorld); } override copy(source: this, recursive?: boolean): this { super.copy(source, false); return this as this; } dispose() { this._childLine.geometry.dispose(); this._childLine.material.dispose(); this._childMesh.geometry.dispose(); this._childMesh.material.dispose(); } override clone(recursive?: boolean): this { const cloned = new CoreRectAreaLightHelper(this.light, this.nodeName) as this; cloned.updateMatrixWorld(); cloned.copy(this, false); cloned.update(); return cloned; } }