@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
116 lines (107 loc) • 4.12 kB
text/typescript
import {BaseSopOperation} from './_Base';
import {CoreGroup} from '../../../core/geometry/Group';
import {MathUtils, Object3D, PerspectiveCamera, Vector3} from 'three';
import {InputCloneMode} from '../../../engine/poly/InputCloneMode';
import {DefaultOperationParams} from '../../../core/operations/_Base';
import {CameraNodeType} from '../../poly/NodeContext';
import {PERSPECTIVE_CAMERA_DEFAULT, registerPerspectiveCamera} from '../../../core/camera/CorePerspectiveCamera';
import {CameraAttribute, CORE_CAMERA_DEFAULT, PerspectiveCameraAttribute} from '../../../core/camera/CoreCamera';
import {isBooleanTrue} from '../../../core/Type';
import {CameraHelper} from '../../../core/helpers/CameraHelper';
import {ThreejsCoreObject} from '../../../core/geometry/modules/three/ThreejsCoreObject';
import type {BaseNodeType} from '../../nodes/_Base';
import {CoreSceneObjectsFactory, GeneratorName} from '../../../core/CoreSceneObjectsFactory';
interface CreatePerspectiveCameraParams {
fov: number;
near: number;
far: number;
}
interface PerspectiveCameraSopParams extends CreatePerspectiveCameraParams, DefaultOperationParams {
position: Vector3;
rotation: Vector3;
showHelper: boolean;
matrixAutoUpdate: boolean;
name: string;
// PBR
apertureBlades: number;
fStop: number;
focusDistance: number;
apertureRotation: number;
anamorphicRatio: number;
}
interface AttributeOptions {
fov: number;
}
export class PerspectiveCameraSopOperation extends BaseSopOperation {
static override readonly DEFAULT_PARAMS: PerspectiveCameraSopParams = {
fov: PERSPECTIVE_CAMERA_DEFAULT.fov,
near: CORE_CAMERA_DEFAULT.near,
far: CORE_CAMERA_DEFAULT.far,
position: new Vector3(0, 0, 0),
rotation: new Vector3(0, 0, 0),
showHelper: false,
matrixAutoUpdate: true,
name: CameraNodeType.PERSPECTIVE,
// PBR
apertureBlades: 6,
fStop: 0.6,
focusDistance: 10,
apertureRotation: 0,
anamorphicRatio: 1,
};
static override readonly INPUT_CLONED_STATE = InputCloneMode.NEVER;
static override type(): Readonly<CameraNodeType.PERSPECTIVE> {
return CameraNodeType.PERSPECTIVE;
}
static override onRegister = registerPerspectiveCamera;
override cook(inputCoreGroups: CoreGroup[], params: PerspectiveCameraSopParams) {
const camera = PerspectiveCameraSopOperation.createCamera(params, this._node);
camera.name = params.name || CameraNodeType.PERSPECTIVE;
camera.position.copy(params.position);
camera.rotation.set(
MathUtils.degToRad(params.rotation.x),
MathUtils.degToRad(params.rotation.y),
MathUtils.degToRad(params.rotation.z)
);
// this needs to be .updateWorldMatrix and not .updateMatrix
// as otherwise the camera appears to behave find in most cases,
// except when using the sop/cameraRenderScene
camera.updateWorldMatrix(false, false);
camera.updateProjectionMatrix();
camera.matrixAutoUpdate = params.matrixAutoUpdate;
PerspectiveCameraSopOperation.setCameraAttributes(camera, params);
const pbrUpdateFunc = CoreSceneObjectsFactory.generator(GeneratorName.PERSPECTIVE_CAMERA_UPDATE);
pbrUpdateFunc({
camera,
params: {
apertureBlades: params.apertureBlades,
fStop: params.fStop,
focusDistance: params.focusDistance,
apertureRotation: params.apertureRotation,
anamorphicRatio: params.anamorphicRatio,
},
});
const objects: Object3D[] = [camera];
if (isBooleanTrue(params.showHelper)) {
const helper = new CameraHelper(camera);
helper.update();
camera.add(helper);
}
return this.createCoreGroupFromObjects(objects);
}
static createCamera(params: CreatePerspectiveCameraParams, nodeGenerator?: BaseNodeType) {
const camera = CoreSceneObjectsFactory.generator(GeneratorName.PERSPECTIVE_CAMERA)({
fov: params.fov,
aspect: 1,
near: params.near,
far: params.far,
});
if (nodeGenerator) {
ThreejsCoreObject.addAttribute(camera, CameraAttribute.NODE_ID, nodeGenerator.graphNodeId());
}
return camera;
}
static setCameraAttributes(camera: PerspectiveCamera, options: AttributeOptions) {
ThreejsCoreObject.addAttribute(camera, PerspectiveCameraAttribute.FOV, options.fov);
}
}