UNPKG

@polygonjs/polygonjs

Version:

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

138 lines (130 loc) 5.5 kB
import {Constructor} from '../../../../types/GlobalTypes'; import {TypedMatNode} from '../_Base'; import {BaseTextureMapController, BooleanParamOptions, NodePathOptions} from './_BaseTextureController'; import {NodeParamsConfig, ParamConfig} from '../../utils/params/ParamsConfig'; import {MeshStandardMaterial, MeshPhysicalMaterial, Material, Euler, Vector3} from 'three'; import {DefaultOperationParams} from '../../../../core/operations/_Base'; import {TypedNodePathParamValue} from '../../../../core/Walker'; import {MaterialTexturesRecord, SetParamsTextureNodesRecord} from './_BaseController'; import {degToRad, radToDeg} from 'three/src/math/MathUtils'; // import {TypedSopNode} from '../../sop/_Base'; export interface EnvMapOperationParams extends DefaultOperationParams { useEnvMap: boolean; envMap: TypedNodePathParamValue; envMapIntensity: number; envMapRotation: Vector3; } export const ENV_MAP_OPERATION_DEFAULT_PARAMS: EnvMapOperationParams = { useEnvMap: false, envMap: new TypedNodePathParamValue(''), envMapIntensity: 1, envMapRotation: new Vector3(0, 0, 0), }; const _rotationInDegrees = new Vector3(); const _euler = new Euler(); const DEFAULT_PARAMS = ENV_MAP_OPERATION_DEFAULT_PARAMS; export function EnvMapParamConfig<TBase extends Constructor>(Base: TBase) { return class Mixin extends Base { /** @param toggle if you want to use an environment map */ useEnvMap = ParamConfig.BOOLEAN(DEFAULT_PARAMS.useEnvMap, { separatorBefore: true, ...BooleanParamOptions(TextureEnvMapController), }); /** @param specify the environment map COP node */ envMap = ParamConfig.NODE_PATH('', NodePathOptions(TextureEnvMapController, 'useEnvMap')); /** @param environment intensity */ envMapIntensity = ParamConfig.FLOAT(DEFAULT_PARAMS.envMapIntensity, {visibleIf: {useEnvMap: 1}}); /** @param environment rotation */ envMapRotation = ParamConfig.VECTOR3(DEFAULT_PARAMS.envMapRotation.toArray(), { visibleIf: {useEnvMap: 1}, }); }; } type TextureEnvMapControllerCurrentMaterial = MeshStandardMaterial | MeshPhysicalMaterial; export function isValidEnvMapMaterial(material?: Material): material is TextureEnvMapControllerCurrentMaterial { if (!material) { return false; } return ( (material as MeshStandardMaterial).isMeshStandardMaterial || (material as MeshPhysicalMaterial as any).isMeshPhysicalMaterial ); } class TextureEnvMapParamsConfig extends EnvMapParamConfig(NodeParamsConfig) {} export interface TextureEnvMapControllers { envMap: TextureEnvMapController; } // abstract class TextureEnvMapBaseSopNode extends TypedSopNode<TextureEnvMapParamsConfig> {} abstract class TextureEnvMapMatNode extends TypedMatNode< TextureEnvMapControllerCurrentMaterial, TextureEnvMapParamsConfig > { controllers!: TextureEnvMapControllers; async material() { const container = await this.compute(); return container.material() as TextureEnvMapControllerCurrentMaterial | undefined; } } // export class TextureEnvMapControllerSop extends BaseTextureMapController { // constructor(protected override node: TextureEnvMapBaseSopNode) { // super(node); // } // // initializeNode() { // // this.add_hooks(this.node.p.useEnvMap, this.node.p.envMap); // // } // async updateMaterial(material?: Material) { // if (!_isValidMaterial(material)) { // return; // } // this._update(material, 'envMap', this.node.p.useEnvMap, this.node.p.envMap); // const mat = material as MeshStandardMaterial; // mat.envMapIntensity = this.node.pv.envMapIntensity; // // mat.refractionRatio = this.node.pv.refractionRatio; // TODO: consider re-allowing this for Phong and Basic materials // } // } export class TextureEnvMapController extends BaseTextureMapController { constructor(protected override node: TextureEnvMapMatNode) { super(node); } override initializeNode() { this.add_hooks(this.node.p.useEnvMap, this.node.p.envMap); } static override async update(node: TextureEnvMapMatNode) { node.controllers.envMap.update(); } override async update() { const material = await this.node.material(); if (!isValidEnvMapMaterial(material)) { return; } this.updateMaterial(material); } override async updateMaterial(material: TextureEnvMapControllerCurrentMaterial) { await this._update(material, 'envMap', this.node.p.useEnvMap, this.node.p.envMap); material.envMapIntensity = this.node.pv.envMapIntensity; _rotationInDegrees.copy(this.node.pv.envMapRotation); const x = degToRad(_rotationInDegrees.x); const y = degToRad(_rotationInDegrees.y); const z = degToRad(_rotationInDegrees.z); _euler.set(x, y, z); material.envMapRotation.copy(_euler); // mat.refractionRatio = this.node.pv.refractionRatio; // TODO: consider re-allowing this for Phong and Basic materials } override getTextures(material: TextureEnvMapControllerCurrentMaterial, record: MaterialTexturesRecord) { record.set('envMap', material.envMap); } override setParamsFromMaterial( material: TextureEnvMapControllerCurrentMaterial, record: SetParamsTextureNodesRecord ) { const mapNode = record.get('envMap'); this.node.p.useEnvMap.set(mapNode != null); if (mapNode) { this.node.p.envMap.setNode(mapNode, {relative: true}); } this.node.p.envMapIntensity.set(material.envMapIntensity); this.node.p.envMapRotation.x.set(radToDeg(material.envMapRotation.x)); this.node.p.envMapRotation.y.set(radToDeg(material.envMapRotation.y)); this.node.p.envMapRotation.z.set(radToDeg(material.envMapRotation.z)); } }