threepipe
Version:
A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.
141 lines • 6.2 kB
JavaScript
import { iObjectCommons } from './iObjectCommons';
import { Vector3 } from 'three';
export const iCameraCommons = {
setDirty: function (options) {
// console.log('target', target, this._controls, this._camera)
if (this.controls && this.controls.target && this.target !== this.controls.target) {
this.controls.target.copy(this.target);
// this.controls.update() // this should be done automatically postFrame
}
if (!this.controls || !this.controls.enabled) {
if (this.userData.autoLookAtTarget) {
this.lookAt(this.target);
}
}
this.dispatchEvent({ ...options, type: 'update' }); // does not bubble
this.dispatchEvent({ ...options, type: 'cameraUpdate', bubbleToParent: true }); // this sets dirty in the viewer
iObjectCommons.setDirty.call(this, { refreshScene: false, ...options });
},
activateMain: function (options = {}, _internal = false, _refresh = true) {
if (!_internal) {
if (options.camera === null)
return this.deactivateMain(options, _internal, _refresh);
return this.dispatchEvent({
type: 'activateMain', ...options,
camera: this,
bubbleToParent: true,
});
} // this will be used by RootScene to deactivate other cameras and activate this one
if (this.userData.__isMainCamera)
return;
this.userData.__isMainCamera = true;
this.userData.__lastScale = this.scale.clone();
this.scale.divide(this.getWorldScale(new Vector3())); // make unit scale, for near far and all
if (_refresh) {
this.refreshCameraControls(false);
}
this.setDirty({ change: 'activateMain', ...options });
// console.log({...this._camera.modelObject.position})
},
deactivateMain: function (options = {}, _internal = false, _refresh = true) {
if (!_internal)
return this.dispatchEvent({
type: 'activateMain', ...options,
camera: null,
bubbleToParent: true,
}); // this will be used by RootScene to deactivate other cameras and activate this one
if (!this.userData.__isMainCamera)
return;
this.userData.__isMainCamera = false; // or delete?
if (this.userData.__lastScale) {
this.scale.copy(this.userData.__lastScale);
delete this.userData.__lastScale;
}
if (_refresh) {
this.refreshCameraControls(false);
}
this.setDirty({ change: 'deactivateMain', ...options });
},
refreshUi: function () {
// todo
this.uiConfig?.uiRefresh?.(true, 'postFrame', 1);
},
refreshTarget: function (distanceFromTarget = 4, setDirty = true) {
if (this.controls?.enabled && this.controls.target) {
if (this.controls.target !== this.target)
this.target.copy(this.controls.target);
}
else {
// this.cameraObject.updateWorldMatrix(true, false)
this.getWorldDirection(this.target)
// .transformDirection(this.cameraObject.matrixWorldInverse)
// .multiplyScalar(distanceFromTarget).add(this._position)
.multiplyScalar(distanceFromTarget).add(this.getWorldPosition(new Vector3()));
// if (this.cameraObject.parent) this.cameraObject.parent.worldToLocal(this._target)
}
if (setDirty)
this.setDirty({ change: 'target' });
},
upgradeCamera: upgradeCamera,
copy: (superCopy) => function (camera, recursive, distanceFromTarget, worldSpace, ...args) {
if (!camera.isCamera) {
console.error('ICamera.copy: camera is not a Camera', camera);
return this;
}
superCopy.call(this, camera, recursive, ...args);
// moved to setView in ThreeViewer
// const worldPos = camera.getWorldPosition(this.position)
// camera.getWorldQuaternion(this.quaternion)
// if (this.parent) {
// this.position.copy(this.parent.worldToLocal(worldPos))
// this.quaternion.premultiply(this.parent.quaternion.clone().invert())
// }
if (camera.target?.isVector3)
this.target.copy(camera.target);
else {
const minDistance = this.controls?.minDistance ?? distanceFromTarget ?? 4;
camera.getWorldDirection(this.target).multiplyScalar(minDistance).add(this.getWorldPosition(new Vector3()));
}
if (worldSpace) { // default = false
const worldPos = camera.getWorldPosition(this.position);
// this.getWorldQuaternion(this.quaternion) // todo: do if autoLookAtTarget is false
// todo up vector
if (this.parent) {
this.position.copy(this.parent.worldToLocal(worldPos));
// this.quaternion.premultiply(this.parent.quaternion.clone().invert())
}
}
this.updateMatrixWorld(true);
this.updateProjectionMatrix();
this.refreshAspect(false);
this.setDirty();
return this;
},
};
function upgradeCamera() {
if (!this.isCamera) {
console.error('Object is not a camera', this);
return;
}
if (this.userData.__cameraSetup)
return;
this.userData.__cameraSetup = true;
iObjectCommons.upgradeObject3D.call(this);
this.copy = iCameraCommons.copy(this.copy);
if (!this.target)
this.target = new Vector3();
if (!this.refreshTarget)
this.refreshTarget = iCameraCommons.refreshTarget;
if (!this.activateMain)
this.activateMain = iCameraCommons.activateMain;
if (!this.deactivateMain)
this.deactivateMain = iCameraCommons.deactivateMain;
if (!this.refreshUi)
this.refreshUi = iCameraCommons.refreshUi;
if (!this.setDirty)
this.setDirty = iCameraCommons.setDirty;
// if (!this.controlsMode) this.controlsMode = ''
this.assetType = 'camera';
// todo uiconfig, anything else?
}
//# sourceMappingURL=iCameraCommons.js.map