@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
262 lines (261 loc) • 8.87 kB
JavaScript
"use strict";
import { TypedViewer } from "./_Base";
import { CoreCameraPostProcessController } from "../../core/camera/CoreCameraPostProcessController";
import { CoreCameraCSSRendererController } from "../../core/camera/CoreCameraCSSRendererController";
import { CoreCameraRenderSceneController } from "../../core/camera/CoreCameraRenderSceneController";
import { CoreStylesheetLoader } from "../../core/loader/Stylesheet";
import { MapboxMapsController } from "../../core/thirdParty/Mapbox/MapboxMapsController";
import { MapboxRaycaster } from "../../core/thirdParty/Mapbox/MapboxRaycaster";
import { ThreeMeshBVHHelper } from "../../core/geometry/bvh/ThreeMeshBVHHelper";
const CSS_CLASS = "CoreMapboxViewer";
const CSS_URL = "https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css";
export class MapboxViewer extends TypedViewer {
constructor(options) {
super(options);
this.options = options;
// private _disposeEvents() {
// window.removeEventListener('resize', this._onResizeBound, false);
// }
this._onResizeBound = this.onResize.bind(this);
// private _startAnimate() {
// // if (this.isXR()) {
// // const renderer = this._renderer as WebGLRenderer;
// // if (!renderer) {
// // return;
// // }
// // const webXRController = this.scene().webXR;
// // const xrCallback: XRFrameRequestCallback = (timestamp, frame) => {
// // webXRController.activeXRController()?.process(frame);
// // this._animateWebXR();
// // };
// // renderer.setAnimationLoop(xrCallback);
// // } else {
// this._animateWeb();
// // }
// }
// private _cancelAnimate() {
// // if (this.isXR()) {
// // (this._renderer as WebGLRenderer)?.setAnimationLoop(null);
// // } else {
// this._cancelAnimateCommon();
// // }
// }
// private _animateWebBound: () => void = this._animateWeb.bind(this);
// private _animateWeb() {
// if (!this._doRender) {
// return;
// }
// this._requestAnimationFrameId = requestAnimationFrame(this._animateWebBound);
// this.__animateCommon__();
// }
// private _animateWebXR() {
// this.__animateCommon__();
// }
this._animateCommonBound = this.__animateCommon__.bind(this);
this._canvasContainer = document.createElement("div");
this._canvasContainer.id = `mapbox_container_id_${Math.random()}`.replace(".", "_");
this._canvasContainer.style.height = "100%";
CoreStylesheetLoader.loadUrl(CSS_URL);
const data = MapboxMapsController.createMap({
camera: options.camera,
container: this._canvasContainer,
scene: options.scene,
renderFunc: this._animateCommonBound,
viewer: this
});
this._map = data.map;
this._map.on("resize", this._onResizeBound);
}
// private _layersController: MapboxLayersController;
static _canvasIdPrefix() {
return "MapboxViewer";
}
rendererConfig() {
return void 0;
}
createRaycaster() {
const raycaster = new MapboxRaycaster();
ThreeMeshBVHHelper.updateRaycaster(raycaster);
return raycaster;
}
setRenderer(renderer) {
this._renderer = renderer;
this._setupFunctions(renderer, this.options);
}
renderer() {
return this._renderer;
}
canvas() {
return this._map.getCanvas();
}
_setupFunctions(renderer, options) {
var _a;
const camera = this.camera();
const scene = this.scene();
const canvas = this.canvas();
const threejsScene = scene.threejsScene();
const rendererScene = CoreCameraRenderSceneController.renderScene({ camera, scene });
const renderScene = rendererScene || threejsScene;
this._effectComposer = CoreCameraPostProcessController.createComposer({
camera,
scene,
renderScene,
renderer,
viewer: this
});
const effectComposer = this._effectComposer;
this._cssRendererConfig = CoreCameraCSSRendererController.cssRendererConfig({ scene, camera, canvas });
const cssRenderer = (_a = this._cssRendererConfig) == null ? void 0 : _a.cssRenderer;
this._renderCSSFunc = cssRenderer ? () => cssRenderer.render(renderScene, camera) : void 0;
if (effectComposer) {
this._renderFunc = (delta) => effectComposer.render(delta);
} else {
this._renderFunc = () => renderer.render(renderScene, camera);
}
this._mountCSSRenderer();
}
/**
* mounts the viewer onto an element
*
*
*/
mount(element) {
var _a, _b;
super.mount(element);
(_a = this._domElement) == null ? void 0 : _a.appendChild(this._canvasContainer);
(_b = this._domElement) == null ? void 0 : _b.classList.add(CSS_CLASS);
this._setEvents();
}
_mountCSSRenderer() {
var _a;
const canvas = this._map.getCanvas();
const cssRendererNode = (_a = this._cssRendererConfig) == null ? void 0 : _a.cssRendererNode;
if (cssRendererNode) {
cssRendererNode.mountRenderer(canvas);
}
}
_build() {
this.activate();
}
/**
* disposes the viewer
*
*
*/
// override dispose() {
// const canvas = this.canvas();
// // dispose cssRenderer
// const cssRendererNode = this._cssRendererConfig?.cssRendererNode;
// if (cssRendererNode) {
// cssRendererNode.unmountRenderer(canvas);
// }
// this._cssRendererConfig = undefined;
// // dispose webXR
// this._webXRConfig?.unmountFunction();
// this._markerTrackingConfig?.unmountFunction();
// // dispose effectComposer
// this._effectComposer = undefined;
// this.setAutoRender(false);
// this._cancelAnimate();
// // this.controlsController().dispose();
// this._disposeEvents();
// // if I dispose the renderer here,
// // this prevents env maps from displaying
// // when the viewer is switched
// // TODO: consider disposing the renderer only if it is not a default one,
// // as this may satisfy most cases
// //this._renderer?.dispose();
// super.dispose();
// }
_setEvents() {
this.eventsController().init();
this.webglController().init();
}
onResize() {
var _a, _b;
const canvas = this._map.getCanvas();
const rect = canvas.getBoundingClientRect();
this._size.set(rect.width, rect.height);
if (!this._renderer) {
return;
}
const devicePixelRatio = globalThis.devicePixelRatio;
this._renderer.setSize(this._size.x * devicePixelRatio, this._size.y * devicePixelRatio, false);
this.camerasController().computeSizeAndAspect(globalThis.devicePixelRatio);
(_a = this._cssRendererConfig) == null ? void 0 : _a.cssRenderer.setSize(this._size.x, this._size.y);
(_b = this._effectComposer) == null ? void 0 : _b.setSize(this._size.x, this._size.y);
this.camerasController().updateCameraAspect();
this._runOnResizeCallbacks();
}
// private _initDisplay() {
// if (!this._canvas) {
// console.warn('no canvas found for viewer');
// return;
// }
// if (!this._renderer) {
// return;
// }
// const pixelRatio = this._renderer.getPixelRatio();
// this.camerasController().computeSizeAndAspect(pixelRatio);
// this.audioController().update();
// this._startAnimate();
// }
/**
* setAutoRender to false will stop the rendering. This can be useful if you know that nothing has changed in the scene, or if the renderer is currently not visible.
*
*
*/
// override setAutoRender(state = true) {
// super.setAutoRender(state);
// // if this._requestAnimationFrameId is already defined,
// // calling this a second time would start another requestAnimationFrame
// // and we would therefore render at twice the rate
// if (this._doRender && this._requestAnimationFrameId == null) {
// this._startAnimate();
// }
// if (!this._doRender) {
// this._cancelAnimate();
// }
// }
isXR() {
return false;
}
__animateCommon__() {
const delta = this._scene.timeController.updateClockDelta();
this._tickAndRender(delta);
}
// private _cancelAnimateCommon() {
// this._doRender = false;
// if (this._requestAnimationFrameId != null) {
// cancelAnimationFrame(this._requestAnimationFrameId);
// this._requestAnimationFrameId = undefined;
// }
// if (this._canvas) {
// // this._cameraNode.renderController().deleteRenderer(this._canvas);
// }
// }
/**
* returns the current renderer
*
*
*/
// renderer() {
// return this._renderer;
// // if (this._canvas) {
// // // return this._cameraNode.renderController().renderer(this._canvas);
// // }
// }
// effectComposer() {
// return this._effectComposer;
// }
preCompile() {
if (!this._renderer) {
return;
}
this._renderer.compile(this._scene.threejsScene(), this._camera);
}
markAsReady() {
this.preCompile();
this.setAutoRender(true);
}
}