@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
144 lines (129 loc) • 5.46 kB
text/typescript
import {DirectionalLight, LightProbe, Object3D, Texture, WebGLRenderer} from 'three';
import {XREstimatedLight} from 'three/examples/jsm/webxr/XREstimatedLight';
// import {BaseCopNodeType} from '../../../engine/nodes/cop/_Base';
// import {TypedNode} from '../../../engine/nodes/_Base';
// import {NodeContext} from '../../../engine/poly/NodeContext';
import {PolyScene} from '../../../engine/scene/PolyScene';
import {coreObjectClassFactory} from '../../geometry/CoreObjectFactory';
const ATTRIB_NAME = {
IS_ESTIMATED_LIGHT: 'CoreWebXRAREstimatedLight_isEstimatedLight',
IS_DEFAULT_LIGHTS_PARENT: 'CoreWebXRAREstimatedLight_defaultLightsParent',
// DEFAULT_ENVIRONMENT_COP_NODE_ID: 'CoreWebXRAREstimatedLight_defaultEnvCopNodeId',
APPLY_ENV: 'CoreWebXRAREstimatedLight_applyEnv',
APPLY_LIGHT_PROBE: 'CoreWebXRAREstimatedLight_applyLightProbe',
APPLY_DIR_LIGHT: 'CoreWebXRAREstimatedLight_applyDirLight',
// DIR_LIGHT_INTENSITY: 'CoreWebXRAREstimatedLight_dirLightIntensity',
};
export class CoreWebXRAREstimatedLightController {
static ATTRIB_NAME = ATTRIB_NAME;
initialize(scene: PolyScene, renderer: WebGLRenderer) {
this._estimatedLightSourceObject = undefined;
scene.threejsScene().traverse((object) => {
if (this._estimatedLightSourceObject) {
return;
}
const coreObjectClass = coreObjectClassFactory(object);
const isEstimatedLight = coreObjectClass.attribValue(object, ATTRIB_NAME.IS_ESTIMATED_LIGHT) as
| boolean
| null;
if (isEstimatedLight == true) {
this._estimatedLightSourceObject = object;
this._initEstimatedLight(scene, renderer);
}
});
}
private _estimatedLightSourceObject: Object3D | undefined;
private _estimatedLight: XREstimatedLight | undefined;
// const estimatedLight = new XREstimatedLight(renderer);
private async _initEstimatedLight(scene: PolyScene, renderer: WebGLRenderer) {
if (!this._estimatedLightSourceObject) {
return;
}
// default lights
const estimatedLightSourceObject = this._estimatedLightSourceObject;
const defaultLightsParent = this._estimatedLightSourceObject.children.find((child) => {
const coreObjectClass = coreObjectClassFactory(child);
coreObjectClass.attribValue(child, ATTRIB_NAME.IS_DEFAULT_LIGHTS_PARENT);
});
// default envs
// const defaultEnvNodeId = CoreObject.attribValue(
// this._estimatedLightSourceObject,
// ATTRIB_NAME.DEFAULT_ENVIRONMENT_COP_NODE_ID
// ) as number | null;
// const defaultEnvGraphNode = defaultEnvNodeId ? scene.graph.nodeFromId(defaultEnvNodeId) : undefined;
// let defaultEnvTexture: Texture | undefined;
// if (
// defaultEnvGraphNode != null &&
// defaultEnvGraphNode instanceof TypedNode &&
// defaultEnvGraphNode.context() == NodeContext.COP
// ) {
// const defaultEnvNode = defaultEnvGraphNode as BaseCopNodeType;
// const container = await defaultEnvNode.compute();
// defaultEnvTexture = container.texture();
// }
const coreObjectClass = coreObjectClassFactory(estimatedLightSourceObject);
// lights customisation
const applyEnv =
(coreObjectClass.attribValue(estimatedLightSourceObject, ATTRIB_NAME.APPLY_ENV) as boolean | null) || false;
const applyLightProbe =
(coreObjectClass.attribValue(estimatedLightSourceObject, ATTRIB_NAME.APPLY_LIGHT_PROBE) as
| boolean
| null) || false;
const applyDirLight =
(coreObjectClass.attribValue(estimatedLightSourceObject, ATTRIB_NAME.APPLY_DIR_LIGHT) as boolean | null) ||
false;
// const dirLightIntensity =
// (CoreObject.attribValue(estimatedLightSourceObject, ATTRIB_NAME.DIR_LIGHT_INTENSITY) as number | null) || 1;
// estimation init
if (this._estimatedLight) {
this._estimatedLightSourceObject.remove(this._estimatedLight);
}
// estimation init
this._estimatedLight = new XREstimatedLight(renderer);
this._estimatedLightSourceObject.add(this._estimatedLight);
const threejsScene = scene.threejsScene();
let previousEnv: Texture | null = null;
const estimatedLight = this._estimatedLight;
this._estimatedLight.addEventListener('estimationstart', () => {
// Swap the default light out for the estimated one one we start getting some estimated values.
estimatedLightSourceObject.add(estimatedLight);
if (defaultLightsParent) {
estimatedLightSourceObject.remove(defaultLightsParent);
}
// remove/tweak lights
estimatedLight.traverse((child) => {
if (child instanceof LightProbe) {
if (applyLightProbe == false) {
child.removeFromParent();
}
}
if (child instanceof DirectionalLight) {
if (applyDirLight == false) {
child.removeFromParent();
}
}
});
// The estimated lighting also provides an environment cubemap, which we can apply here.
if (applyEnv && estimatedLight.environment) {
previousEnv = threejsScene.environment;
threejsScene.environment = estimatedLight.environment;
}
});
estimatedLight.addEventListener('estimationend', () => {
// Swap the lights back when we stop receiving estimated values.
if (defaultLightsParent) {
estimatedLightSourceObject.add(defaultLightsParent);
}
estimatedLightSourceObject.remove(estimatedLight);
// Revert back to the default environment.
threejsScene.environment = previousEnv;
// estimatedLight.dispose()
});
}
dispose() {
if (this._estimatedLight) {
this._estimatedLightSourceObject?.remove(this._estimatedLight);
this._estimatedLight = undefined;
}
}
}