DefaultScene static method to be upper case...added webGPU support (disabled as there appears to be a bug).

This commit is contained in:
Michael Mainguy 2024-04-17 08:18:35 -05:00
parent 8bb77873cc
commit 469d4a5116
21 changed files with 86 additions and 51 deletions

View File

@ -55,7 +55,7 @@ export class Base {
this.logger.setLevel(this.logger.levels.DEBUG); this.logger.setLevel(this.logger.levels.DEBUG);
this.controller = controller; this.controller = controller;
this.controllers = diagramManager.controllers; this.controllers = diagramManager.controllers;
this.scene = DefaultScene.scene; this.scene = DefaultScene.Scene;
this.xr = xr; this.xr = xr;
this.diagramManager = diagramManager; this.diagramManager = diagramManager;
this.scene.onBeforeRenderObservable.add(beforeRenderObserver, -1, false, this); this.scene.onBeforeRenderObservable.add(beforeRenderObserver, -1, false, this);

View File

@ -3,7 +3,7 @@ import {DefaultScene} from "../../defaultScene";
export function beforeRenderObserver() { export function beforeRenderObserver() {
if (this?.grabbedMesh?.physicsBody) { if (this?.grabbedMesh?.physicsBody) {
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
const hk = (scene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin); const hk = (scene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin);
this.lastPosition = this?.grabbedMesh?.physicsBody?.transformNode.absolutePosition.clone(); this.lastPosition = this?.grabbedMesh?.physicsBody?.transformNode.absolutePosition.clone();
if (this.grabbedMeshParentId) { if (this.grabbedMeshParentId) {

View File

@ -14,7 +14,7 @@ import {buildStandardMaterial} from "../../materials/functions/buildStandardMate
import {DefaultScene} from "../../defaultScene"; import {DefaultScene} from "../../defaultScene";
export function buildRig(xr: WebXRDefaultExperience): Mesh { export function buildRig(xr: WebXRDefaultExperience): Mesh {
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
const rigMesh = MeshBuilder.CreateCylinder("platform", {diameter: .5, height: .01}, scene); const rigMesh = MeshBuilder.CreateCylinder("platform", {diameter: .5, height: .01}, scene);
const cameratransform = new TransformNode("cameraTransform", scene); const cameratransform = new TransformNode("cameraTransform", scene);
cameratransform.parent = rigMesh; cameratransform.parent = rigMesh;

View File

@ -1,10 +1,12 @@
import {AbstractMesh, TransformNode} from "@babylonjs/core"; import {AbstractMesh, TransformNode} from "@babylonjs/core";
import {DiagramManager} from "../../diagram/diagramManager"; import {DiagramManager} from "../../diagram/diagramManager";
import {DefaultScene} from "../../defaultScene";
export function grabAndClone(diagramManager: DiagramManager, mesh: AbstractMesh, parent: AbstractMesh): export function grabAndClone(diagramManager: DiagramManager, mesh: AbstractMesh, parent: AbstractMesh):
{ transformNode: TransformNode, newMesh: AbstractMesh } { { transformNode: TransformNode, newMesh: AbstractMesh } {
const scene = DefaultScene.Scene;
const newMesh = diagramManager.createCopy(mesh); const newMesh = diagramManager.createCopy(mesh);
const transformNode = new TransformNode("grabAnchor, this.scene"); const transformNode = new TransformNode("grabAnchor", scene);
transformNode.id = "grabAnchor"; transformNode.id = "grabAnchor";
transformNode.position = newMesh.position.clone(); transformNode.position = newMesh.position.clone();
if (newMesh.rotationQuaternion) { if (newMesh.rotationQuaternion) {

View File

@ -18,7 +18,7 @@ export class Left extends Base {
constructor(controller: constructor(controller:
WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) { WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
super(controller, xr, diagramManager); super(controller, xr, diagramManager);
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
this.controller.onMotionControllerInitObservable.add((init) => { this.controller.onMotionControllerInitObservable.add((init) => {
if (init.components['xr-standard-thumbstick']) { if (init.components['xr-standard-thumbstick']) {
init.components['xr-standard-thumbstick'] init.components['xr-standard-thumbstick']

View File

@ -42,7 +42,7 @@ export class Right extends Base {
) { ) {
super(controller, xr, diagramManager); super(controller, xr, diagramManager);
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
this.controller.onMotionControllerInitObservable.add((init) => { this.controller.onMotionControllerInitObservable.add((init) => {
this.initTrigger(init.components['xr-standard-trigger']); this.initTrigger(init.components['xr-standard-trigger']);

View File

@ -40,7 +40,7 @@ export class Rigplatform {
xr: WebXRDefaultExperience, xr: WebXRDefaultExperience,
diagramManager: DiagramManager diagramManager: DiagramManager
) { ) {
this.scene = DefaultScene.scene; this.scene = DefaultScene.Scene;
this.diagramManager = diagramManager; this.diagramManager = diagramManager;
this.controllers = diagramManager.controllers; this.controllers = diagramManager.controllers;
this.xr = xr; this.xr = xr;

View File

@ -1,27 +1,38 @@
import {Scene} from "@babylonjs/core"; import {Engine, Scene} from "@babylonjs/core";
import log from "loglevel"; import log from "loglevel";
const logger = log.getLogger('DefaultScene'); const logger = log.getLogger('DefaultScene');
export class DefaultScene { export class DefaultScene {
private static _scene: Scene; private static _Scene: Scene;
public static get scene(): Scene { public static get Scene(): Scene {
return DefaultScene._scene; if (!DefaultScene._Scene) {
logger.error('default scene not yet created');
if (Engine.LastCreatedScene) {
logger.warn('using last created scene, this may not be what you want, proceed with caution');
DefaultScene._Scene = Engine.LastCreatedScene;
return DefaultScene._Scene;
} else {
return null;
}
} else {
return DefaultScene._Scene;
}
} }
static create(scene: Scene) { public static set Scene(scene: Scene) {
if (DefaultScene._scene) { if (DefaultScene._Scene) {
logger.error('default scene already created, disposing and recreating'); logger.error('default scene already created, disposing and recreating');
if (DefaultScene._scene.isDisposed) { if (DefaultScene._Scene.isDisposed) {
logger.warn('default scene is already disposed'); logger.warn('default scene is already disposed');
} else { } else {
DefaultScene._scene.dispose(); DefaultScene._Scene.dispose();
logger.info('default scene disposed'); logger.info('default scene disposed');
} }
DefaultScene._scene = null; DefaultScene._Scene = null;
} }
DefaultScene._scene = scene; DefaultScene._Scene = scene;
logger.info('default scene created'); logger.info('default scene created');
} }
} }

View File

@ -154,7 +154,7 @@ export class DiagramConnection {
} }
private beforeRender = () => { private beforeRender = () => {
this.tick++;
if (this.tick % 5 == 0) { if (this.tick % 5 == 0) {
this.recalculate(); this.recalculate();
this.setPoints(); this.setPoints();

View File

@ -29,7 +29,7 @@ export class DiagramManager {
constructor() { constructor() {
this._scene = DefaultScene.scene; this._scene = DefaultScene.Scene;
this._config = new AppConfig(); this._config = new AppConfig();
this._controllers = new Controllers(); this._controllers = new Controllers();
this.inputTextView = new InputTextView(this._controllers); this.inputTextView = new InputTextView(this._controllers);

View File

@ -5,7 +5,7 @@ import {DefaultScene} from "../../defaultScene";
export function buildEntityActionManager(controllers: Controllers) { export function buildEntityActionManager(controllers: Controllers) {
const logger = log.getLogger('buildEntityActionManager'); const logger = log.getLogger('buildEntityActionManager');
const actionManager = new ActionManager(DefaultScene.scene); const actionManager = new ActionManager(DefaultScene.Scene);
/*actionManager.registerAction( /*actionManager.registerAction(
new PlaySoundAction(ActionManager.OnPointerOverTrigger, sounds.tick));*/ new PlaySoundAction(ActionManager.OnPointerOverTrigger, sounds.tick));*/
actionManager.registerAction( actionManager.registerAction(

View File

@ -24,7 +24,7 @@ export class InputTextView {
constructor(controllers: Controllers) { constructor(controllers: Controllers) {
this.controllers = controllers; this.controllers = controllers;
this.scene = DefaultScene.scene; this.scene = DefaultScene.Scene;
this.inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene); this.inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene);
this.handle = new Handle(this.inputMesh); this.handle = new Handle(this.inputMesh);

View File

@ -10,7 +10,7 @@ export abstract class AbstractMenu {
protected controllers: Controllers; protected controllers: Controllers;
protected constructor(xr: WebXRDefaultExperience, controllers: Controllers) { protected constructor(xr: WebXRDefaultExperience, controllers: Controllers) {
this.scene = DefaultScene.scene; this.scene = DefaultScene.Scene;
this.xr = xr; this.xr = xr;
this.controllers = controllers; this.controllers = controllers;
} }

View File

@ -18,7 +18,7 @@ export class Spinner {
private particleSystem: ParticleSystem; private particleSystem: ParticleSystem;
constructor() { constructor() {
this._scene = DefaultScene.scene; this._scene = DefaultScene.Scene;
this.build(); this.build();
} }

View File

@ -28,7 +28,7 @@ export class Toolbox {
private axes: AxesViewer; private axes: AxesViewer;
constructor() { constructor() {
this.scene = DefaultScene.scene; this.scene = DefaultScene.Scene;
this.addPanel = new StackPanel3D(); this.addPanel = new StackPanel3D();
this.manager = new GUI3DManager(this.scene); this.manager = new GUI3DManager(this.scene);
this.manager.addControl(this.addPanel); this.manager.addControl(this.addPanel);

View File

@ -26,7 +26,7 @@ export class CustomEnvironment {
private readonly _groundMeshObservable: Observable<GroundMesh> = new Observable<GroundMesh>(); private readonly _groundMeshObservable: Observable<GroundMesh> = new Observable<GroundMesh>();
constructor(name: string = "default", config: AppConfig) { constructor(name: string = "default", config: AppConfig) {
this.scene = DefaultScene.scene; this.scene = DefaultScene.Scene;
this.name = name; this.name = name;
const loading = document.querySelector('#loadingGrid'); const loading = document.querySelector('#loadingGrid');
if (loading) { if (loading) {
@ -121,7 +121,7 @@ export class CustomEnvironment {
} }
async function createPoints(divisions: number = 10, scale: number = 80) { async function createPoints(divisions: number = 10, scale: number = 80) {
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
const half = .5; const half = .5;
const increment = 1 / divisions; const increment = 1 / divisions;
let x = -half; let x = -half;
@ -156,7 +156,7 @@ async function createPoints(divisions: number = 10, scale: number = 80) {
} }
function createGridMaterial(lineColor: Color3, mainColor: Color3): Material { function createGridMaterial(lineColor: Color3, mainColor: Color3): Material {
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
const material = new GridMaterial("gridMaterial", scene); const material = new GridMaterial("gridMaterial", scene);
material.minorUnitVisibility = .1; material.minorUnitVisibility = .1;
material.gridRatio = .1; material.gridRatio = .1;

View File

@ -1,7 +1,7 @@
import {DefaultScene} from "../../defaultScene"; import {DefaultScene} from "../../defaultScene";
export function exportGltf() { export function exportGltf() {
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
import("@babylonjs/serializers").then((serializers) => { import("@babylonjs/serializers").then((serializers) => {
serializers.GLTF2Export.GLBAsync(scene, 'diagram.glb', { serializers.GLTF2Export.GLBAsync(scene, 'diagram.glb', {
shouldExportNode: function (node) { shouldExportNode: function (node) {

View File

@ -25,10 +25,12 @@ export async function groundMeshObserver(ground: AbstractMesh,
} }
}, },
optionalFeatures: true, optionalFeatures: true,
pointerSelectionOptions: { pointerSelectionOptions: {
enablePointerSelectionOnAllControllers: true enablePointerSelectionOnAllControllers: true
} }
}); });
//xr.baseExperience.featuresManager.enableFeature(WebXRFeatureName.LAYERS, "latest", { preferMultiviewOnInit: true }, true, false);
const enterButton = (document.querySelector('#enterXR') as HTMLAnchorElement); const enterButton = (document.querySelector('#enterXR') as HTMLAnchorElement);
if (enterButton) { if (enterButton) {
const vrSupported = await xr.baseExperience.sessionManager.isSessionSupportedAsync('immersive-vr'); const vrSupported = await xr.baseExperience.sessionManager.isSessionSupportedAsync('immersive-vr');

View File

@ -1,7 +1,7 @@
import {DefaultScene} from "../../defaultScene"; import {DefaultScene} from "../../defaultScene";
export function addSceneInspector() { export function addSceneInspector() {
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
window.addEventListener("keydown", (ev) => { window.addEventListener("keydown", (ev) => {
if (ev.key == "z") { if (ev.key == "z") {
//voiceManager.startRecording(); //voiceManager.startRecording();

View File

@ -1,4 +1,4 @@
import {AbstractMesh, DynamicTexture, Material, MeshBuilder, StandardMaterial} from "@babylonjs/core"; import {AbstractMesh, Color3, DynamicTexture, Material, MeshBuilder, StandardMaterial} from "@babylonjs/core";
import log from "loglevel"; import log from "loglevel";
@ -46,9 +46,12 @@ export function updateTextNode(mesh: AbstractMesh, text: string) {
height: DTHeight height: DTHeight
}, mesh.getScene(), false); }, mesh.getScene(), false);
const mat = new StandardMaterial("mat", mesh.getScene()); const mat = new StandardMaterial("mat", mesh.getScene());
mat.diffuseTexture = dynamicTexture; mat.diffuseColor = Color3.Black();
mat.disableLighting = true;
mat.backFaceCulling = true;
mat.emissiveTexture = dynamicTexture;
//mat.emissiveColor = Color3.White(); //mat.emissiveColor = Color3.White();
dynamicTexture.drawText(text, null, null, font, "#000000", "#ffffff", true); dynamicTexture.drawText(text, null, null, font, "#ffffff", "#000000", true);
//Create plane and set dynamic texture as material //Create plane and set dynamic texture as material
//const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene()); //const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
const plane1 = createPlane(mat, mesh, text, planeWidth, height); const plane1 = createPlane(mat, mesh, text, planeWidth, height);

View File

@ -1,4 +1,4 @@
import {Color3, Engine, FreeCamera, Scene, Vector3} from "@babylonjs/core"; import {Color3, Engine, FreeCamera, Scene, Vector3, WebGPUEngine} from "@babylonjs/core";
import '@babylonjs/loaders'; import '@babylonjs/loaders';
import {DiagramManager} from "./diagram/diagramManager"; import {DiagramManager} from "./diagram/diagramManager";
import log, {Logger} from "loglevel"; import log, {Logger} from "loglevel";
@ -12,30 +12,22 @@ import {buildQuestLink} from "./util/functions/buildQuestLink";
import {exportGltf} from "./util/functions/exportGltf"; import {exportGltf} from "./util/functions/exportGltf";
import {DefaultScene} from "./defaultScene"; import {DefaultScene} from "./defaultScene";
const webGpu = false;
export class VrApp { export class VrApp {
private engine: Engine; private engine: WebGPUEngine | Engine;
//preTasks = [havokModule]; //preTasks = [havokModule];
private logger: Logger = log.getLogger('App'); private logger: Logger = log.getLogger('App');
constructor() { constructor() {
const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement); this.initializeEngine().then(() => {
this.engine = new Engine(canvas, true); this.logger.info('Engine initialized');
this.engine.setHardwareScalingLevel(1 / window.devicePixelRatio); });
window.onresize = () => {
this.engine.resize();
}
const scene = new Scene(this.engine);
scene.ambientColor = new Color3(.1, .1, .1);
DefaultScene.create(scene);
log.resetLevel();
log.setDefaultLevel('error');
this.logger.debug('App', 'gameCanvas created');
} }
public async initialize() { public async initialize() {
const scene = DefaultScene.scene; const scene = DefaultScene.Scene;
const spinner = new Spinner(); const spinner = new Spinner();
spinner.show(); spinner.show();
@ -90,16 +82,41 @@ export class VrApp {
} }
private async initializeEngine() {
const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement);
if (webGpu) {
this.engine = new WebGPUEngine(canvas);
await (this.engine as WebGPUEngine).initAsync();
} else {
this.engine = new Engine(canvas, true);
}
//this.engine.setHardwareScalingLevel(1 / window.devicePixelRatio);
//window.onresize = () => {
// this.engine.resize();
// }
/*window.setInterval(() => {
console.log(this.engine.performanceMonitor.instantaneousFPS.toFixed(2) + " fps");
}, 1000);*/
const scene = new Scene(this.engine);
scene.ambientColor = new Color3(.1, .1, .1);
DefaultScene.Scene = scene;
log.resetLevel();
log.setDefaultLevel('error');
this.logger.debug('App', 'gameCanvas created');
await this.initialize();
}
public async start() { public async start() {
} }
} }
const vrApp = new VrApp(); const vrApp = new VrApp();
vrApp.initialize().then(() => {
buildQuestLink(); buildQuestLink();
});