diff --git a/package-lock.json b/package-lock.json index c81f936..6d5a9d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,14 +8,14 @@ "name": "immersive", "version": "0.0.1", "dependencies": { - "@babylonjs/core": "^7.1.0", - "@babylonjs/gui": "^7.1.0", - "@babylonjs/havok": "1.3.1", - "@babylonjs/inspector": "^7.1.0", - "@babylonjs/loaders": "^7.1.0", - "@babylonjs/materials": "^7.1.0", - "@babylonjs/procedural-textures": "^7.1.0", - "@babylonjs/serializers": "^7.1.0", + "@babylonjs/core": "^7.3.1", + "@babylonjs/gui": "^7.3.1", + "@babylonjs/havok": "1.3.4", + "@babylonjs/inspector": "^7.3.1", + "@babylonjs/loaders": "^7.3.1", + "@babylonjs/materials": "^7.3.1", + "@babylonjs/procedural-textures": "^7.3.1", + "@babylonjs/serializers": "^7.3.1", "@picovoice/cobra-web": "^2.0.3", "@picovoice/eagle-web": "^1.0.0", "@picovoice/web-voice-processor": "^4.0.9", @@ -26,7 +26,7 @@ "@types/react": "^18.2.72", "@types/react-dom": "^18.2.22", "axios": "^1.6.8", - "babylon-html": "^0.0.2", + "babylon-html": "0.0.3", "dom-to-image-more": "^3.3.0", "earcut": "^2.2.4", "events": "^3.3.0", @@ -55,8 +55,7 @@ } }, "../babylon-html": { - "version": "0.0.2", - "extraneous": true, + "version": "0.0.3", "license": "MIT", "dependencies": { "@babylonjs/core": "^7.1.0", @@ -70,14 +69,14 @@ } }, "node_modules/@babylonjs/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-7.1.0.tgz", - "integrity": "sha512-nz1CmflajMPnjdnwYrj72s4D/Q8IkOW4DBbwMfUNLFSCondfFXS3sZBgHeCAHpimR5n4e27YwvJ66MkQJsSraQ==" + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-7.3.1.tgz", + "integrity": "sha512-jahsEq0gFEIt/DzQvbIOtfikuAIplEtVT1tOURzJa3b+HMnSQBXj0p9w556HTRVCUj5bghP3Py8VHYMfwDaZRg==" }, "node_modules/@babylonjs/gui": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-7.1.0.tgz", - "integrity": "sha512-tY6MGtigjZwv+9rqtGTsyBZL9sHSPjgVq+JEWHUsACH0ffNkKsQxtKSDc5bryzNQpo1rzTMHqEeU+DnqNSVe1Q==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-7.3.1.tgz", + "integrity": "sha512-ElIkJV832nYAEi4hbFD/pqNtj4rnIVfFIBsIp+D+ANxj+BulXsXX9119st8iLoEow0d2tEocXe7Wksx7TYkZCQ==", "peerDependencies": { "@babylonjs/core": "^7.0.0" } @@ -95,17 +94,17 @@ } }, "node_modules/@babylonjs/havok": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@babylonjs/havok/-/havok-1.3.1.tgz", - "integrity": "sha512-ctaAQ2RN7hzE2vukGiA27//08YE4RNqH4RN26fCd8q0q7Qn+pXg4P61ZgakWYox/YS4VqHrB3ovZUDtPt2Scxg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@babylonjs/havok/-/havok-1.3.4.tgz", + "integrity": "sha512-mCz+w7vlSjPHLfGkCvt2oTRY2qFWXem6x/B6bolNW8lgsOn1SebeZ/lx6Q6nobNbOtWqs5jt4ESEb+ctzutvMw==", "dependencies": { "@types/emscripten": "^1.39.6" } }, "node_modules/@babylonjs/inspector": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-7.1.0.tgz", - "integrity": "sha512-Hs9pk1LstJMnD4xXpHFlQVqXPtH/hhUcNSPaZlz8iesFrHJEXF4Mlao+ozwbl2WzDbMzmmex5nc1lw2HEBdhww==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-7.3.1.tgz", + "integrity": "sha512-RjifJ9Na69Xxf56kHdYuGzVXK1I8yl3/hhpF5TIUcL7N8BPmAhM+rp+94YIBRlz/uceC2tXm0FJvfvb6Ydu4zQ==", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.1.0", "@fortawesome/free-regular-svg-icons": "^6.0.0", @@ -123,34 +122,34 @@ } }, "node_modules/@babylonjs/loaders": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-7.1.0.tgz", - "integrity": "sha512-6gLbFiUsiqsQDRWLl4TL5pMKiemSAB/E61SHpp8xkBalxZUiKroSbZt3Irxc7CHIq8SE5CYfPUPYjs6BmpTgqw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-7.3.1.tgz", + "integrity": "sha512-SWI2r9NyRWTPYQ5MWJ2rCH3KN++8sCz44BSS5xayVj0IB4m+LuxnuchH4cdFAnbul56gXmL7mkZLG1sR154GHg==", "peerDependencies": { "@babylonjs/core": "^7.0.0", "babylonjs-gltf2interface": "^7.0.0" } }, "node_modules/@babylonjs/materials": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-7.1.0.tgz", - "integrity": "sha512-tHzpV6xUqpAgF9rPudDXetk1tIPbhggrybfIpvoWwbKlffIPQw4URsA+IBG04U5owWsicdhvTLQWP1WEwfbMQg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-7.3.1.tgz", + "integrity": "sha512-0jACK6543/KDyOG5DNY10DM73JUHaB7n5au/pRVKV371pAbU224h1l5J+d6gRZCY3mhtE2MEi1N0PKQF8VRI8w==", "peerDependencies": { "@babylonjs/core": "^7.0.0" } }, "node_modules/@babylonjs/procedural-textures": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babylonjs/procedural-textures/-/procedural-textures-7.1.0.tgz", - "integrity": "sha512-ajjaXEQJpWNQQzWZdUJJzN4NBtI96lxbrhmBUpPdfQwAhX2LRG0tbKWKXd66QHh82f/FG+daIA2BCL7M4f2MMw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babylonjs/procedural-textures/-/procedural-textures-7.3.1.tgz", + "integrity": "sha512-TFwj3RoCGe/HldI7QM85QGW3eZZcl1RfwNCt8CATM6d9Juj9mWtwKVd7A0A6b0uXRsx97YY59d5zw6kcy52DmA==", "peerDependencies": { "@babylonjs/core": "^7.0.0" } }, "node_modules/@babylonjs/serializers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-7.1.0.tgz", - "integrity": "sha512-ToYutpqvqFVic+mhFkza6rLeE31sXXpixhdpu2bE+MRP13FoxNKfPD4np/DGBP7zUWmXIi2yRm6sZ7cGs8jp1g==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-7.3.1.tgz", + "integrity": "sha512-xU6SBD1JdoRfjZPS14NqszFAE2p+RzW3KocESVXPYmU5L/C/7Z6YYMUCT2r8hmQ4ANqrwa7Fp+qcGzbeFBFl5Q==", "peerDependencies": { "@babylonjs/core": "^7.0.0", "babylonjs-gltf2interface": "^7.0.0" @@ -1108,13 +1107,8 @@ } }, "node_modules/babylon-html": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/babylon-html/-/babylon-html-0.0.2.tgz", - "integrity": "sha512-bcdLgMmnjvLrysZq5VFzc71TkDT0b6coCv3ZoFzTxJDhXtZF96FFaRMba9rxMHp1TM3rX9u6yW8N/sJodA/qVg==", - "dependencies": { - "@babylonjs/core": "^7.1.0", - "dom-to-image-more": "^3.3.0" - } + "resolved": "../babylon-html", + "link": true }, "node_modules/babylonjs-gltf2interface": { "version": "7.1.0", diff --git a/package.json b/package.json index 50339a4..1aa7020 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,14 @@ "havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps" }, "dependencies": { - "@babylonjs/core": "^7.1.0", - "@babylonjs/gui": "^7.1.0", - "@babylonjs/havok": "1.3.1", - "@babylonjs/inspector": "^7.1.0", - "@babylonjs/loaders": "^7.1.0", - "@babylonjs/materials": "^7.1.0", - "@babylonjs/procedural-textures": "^7.1.0", - "@babylonjs/serializers": "^7.1.0", + "@babylonjs/core": "^7.3.1", + "@babylonjs/gui": "^7.3.1", + "@babylonjs/havok": "1.3.4", + "@babylonjs/inspector": "^7.3.1", + "@babylonjs/loaders": "^7.3.1", + "@babylonjs/materials": "^7.3.1", + "@babylonjs/procedural-textures": "^7.3.1", + "@babylonjs/serializers": "^7.3.1", "@picovoice/cobra-web": "^2.0.3", "@picovoice/eagle-web": "^1.0.0", "@picovoice/web-voice-processor": "^4.0.9", @@ -34,7 +34,7 @@ "@types/react": "^18.2.72", "@types/react-dom": "^18.2.22", "axios": "^1.6.8", - "babylon-html": "^0.0.2", + "babylon-html": "0.0.3", "dom-to-image-more": "^3.3.0", "earcut": "^2.2.4", "events": "^3.3.0", diff --git a/src/controllers/base.ts b/src/controllers/base.ts index da52550..3e8f1bc 100644 --- a/src/controllers/base.ts +++ b/src/controllers/base.ts @@ -3,6 +3,7 @@ import { Mesh, PhysicsMotionType, Scene, + TransformNode, Vector3, WebXRControllerComponent, WebXRDefaultExperience, @@ -31,7 +32,7 @@ import {DefaultScene} from "../defaultScene"; const CLICK_TIME = 300; export class Base { static stickVector = Vector3.Zero(); - protected controller: WebXRInputSource; + protected xrInputSource: WebXRInputSource; protected speedFactor = 4; protected readonly scene: Scene; protected grabbedMesh: AbstractMesh = null; @@ -47,25 +48,34 @@ export class Base { private lastPosition: Vector3 = null; protected controllers: Controllers; private clickMenu: ClickMenu; + private pickPoint: Vector3 = new Vector3(); constructor(controller: WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) { this.logger = log.getLogger('Base'); this.logger.setLevel(this.logger.levels.DEBUG); - this.controller = controller; + this.xrInputSource = controller; this.controllers = diagramManager.controllers; this.scene = DefaultScene.Scene; this.xr = xr; + this.scene.onPointerObservable.add((pointerInfo) => { + if (pointerInfo.pickInfo.pickedMesh?.metadata?.template) { + const mesh = pointerInfo.pickInfo.pickedMesh; + const pos = mesh.absolutePosition; + this.pickPoint.copyFrom(pointerInfo.pickInfo.pickedPoint); + } + + }); this.diagramManager = diagramManager; this.scene.onBeforeRenderObservable.add(beforeRenderObserver, -1, false, this); - this.controller.onMotionControllerInitObservable.add(motionControllerObserver, -1, false, this); + this.xrInputSource.onMotionControllerInitObservable.add(motionControllerObserver, -1, false, this); this.controllers.controllerObserver.add((event) => { this.logger.debug(event); switch (event.type) { case ControllerEventType.PULSE: - if (event.gripId == this?.controller?.grip?.id) { - this.controller?.motionController?.pulse(.25, 30) + if (event.gripId == this?.xrInputSource?.grip?.id) { + this.xrInputSource?.motionController?.pulse(.25, 30) .then(() => { this.logger.debug("pulse done"); }); @@ -83,14 +93,14 @@ export class Base { public disable() { this.scene.preventDefaultOnPointerDown = true; - this.controller.motionController.rootMesh.setEnabled(false) - this.controller.pointer.setEnabled(false); + this.xrInputSource.motionController.rootMesh.setEnabled(false) + this.xrInputSource.pointer.setEnabled(false); } public enable() { this.scene.preventDefaultOnPointerDown = false; - this.controller.motionController.rootMesh.setEnabled(true); - this.controller.pointer.setEnabled(true) + this.xrInputSource.motionController.rootMesh.setEnabled(true); + this.xrInputSource.pointer.setEnabled(true) } protected initClicker(trigger: WebXRControllerComponent) { @@ -120,7 +130,7 @@ export class Base { } private grab(cloneEntity: boolean = false) { - let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId); + let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.xrInputSource.uniqueId); if (!mesh) { return; @@ -129,7 +139,7 @@ export class Base { displayDebug(mesh); if (!isDiagramEntity(mesh)) { if (handleWasGrabbed(mesh)) { - mesh && mesh.setParent(this.controller.motionController.rootMesh); + mesh && mesh.setParent(this.xrInputSource.motionController.rootMesh); this.grabbedMesh = mesh; } else { if (mesh?.parent?.parent?.metadata?.grabbable) { @@ -156,16 +166,16 @@ export class Base { if ((!mesh.metadata?.grabClone || player) && !cloneEntity) { if (mesh.physicsBody) { - const transformNode = setupTransformNode(mesh, this.controller.motionController.rootMesh); + const transformNode = setupTransformNode(mesh, this.xrInputSource.motionController.rootMesh); mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED); this.grabbedMeshParentId = transformNode.id; } else { - mesh.setParent(this.controller.motionController.rootMesh); + mesh.setParent(this.xrInputSource.motionController.rootMesh); } this.grabbedMesh = mesh; } else { this.logger.debug("cloning " + mesh?.id); - const clone = grabAndClone(this.diagramManager, mesh, this.controller.motionController.rootMesh); + const clone = grabAndClone(this.diagramManager, mesh, this.xrInputSource.motionController.rootMesh); clone.newMesh.metadata.grabClone = false; clone.newMesh.metadata.tool = false; this.grabbedMeshParentId = clone.transformNode.id; @@ -196,8 +206,14 @@ export class Base { reparent(mesh, this.previousParentId, this.grabbedMeshParentId); this.grabbedMeshParentId = null; if (!mesh.physicsBody) { - mesh.position = snapGridVal(mesh.position, this.diagramManager._config.current.gridSnap); - mesh.rotation = snapRotateVal(mesh.rotation, this.diagramManager._config.current.rotateSnap); + const transform = new TransformNode('temp', this.scene); + transform.rotation = mesh.rotation; + transform.position = this.pickPoint; + mesh.setParent(transform); + transform.position = snapGridVal(transform.position, this.diagramManager._config.current.gridSnap).clone(); + transform.rotation = snapRotateVal(transform.rotation, this.diagramManager._config.current.rotateSnap); + mesh.setParent(null); + } this.previousParentId = null; this.previousScaling = null; @@ -224,7 +240,7 @@ export class Base { } private click() { - let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId); + let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.xrInputSource.uniqueId); if (pointable(mesh)) { this.logger.debug("click on " + mesh.id); @@ -234,7 +250,7 @@ export class Base { this.clickMenu = null; } } else { - this.clickMenu = new ClickMenu(mesh, this.diagramManager, this.controller.grip); + this.clickMenu = new ClickMenu(mesh, this.diagramManager, this.xrInputSource.grip); } } else { diff --git a/src/controllers/left.ts b/src/controllers/left.ts index 3a834b2..ed5206c 100644 --- a/src/controllers/left.ts +++ b/src/controllers/left.ts @@ -19,7 +19,7 @@ export class Left extends Base { WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) { super(controller, xr, diagramManager); const scene = DefaultScene.Scene; - this.controller.onMotionControllerInitObservable.add((init) => { + this.xrInputSource.onMotionControllerInitObservable.add((init) => { if (init.components['xr-standard-thumbstick']) { init.components['xr-standard-thumbstick'] .onAxisValueChangedObservable.add((value) => { @@ -66,7 +66,7 @@ export class Left extends Base { this.controllers.controllerObserver.notifyObservers({ type: ControllerEventType.TRIGGER, value: button.value, - controller: this.controller + controller: this.xrInputSource }); }, -1, false, this); } diff --git a/src/controllers/right.ts b/src/controllers/right.ts index 4d78707..45b1828 100644 --- a/src/controllers/right.ts +++ b/src/controllers/right.ts @@ -44,7 +44,7 @@ export class Right extends Base { super(controller, xr, diagramManager); const scene = DefaultScene.Scene; - this.controller.onMotionControllerInitObservable.add((init) => { + this.xrInputSource.onMotionControllerInitObservable.add((init) => { this.initTrigger(init.components['xr-standard-trigger']); if (init.components['a-button']) { const transform = new TransformNode('a-button', scene); @@ -70,7 +70,7 @@ export class Right extends Base { this.controllers.controllerObserver.notifyObservers({ type: ControllerEventType.TRIGGER, value: button.value, - controller: this.controller + controller: this.xrInputSource }); }, -1, false, this); } diff --git a/src/diagram/diagramConnection.ts b/src/diagram/diagramConnection.ts index afdb074..4b1044d 100644 --- a/src/diagram/diagramConnection.ts +++ b/src/diagram/diagramConnection.ts @@ -55,7 +55,6 @@ export class DiagramConnection { private toAnchor: TransformNode; private fromAnchor: TransformNode; private transformNode: TransformNode; - private points: Vector3[] = []; private _mesh: AbstractMesh; @@ -129,7 +128,6 @@ export class DiagramConnection { private buildConnection() { this.logger.debug(`buildConnection from ${this._from} to ${this._to}`); this._mesh = MeshBuilder.CreateCylinder(this.id + "_connection", {diameter: .025, height: 1}, this.scene); - this.transformNode = new TransformNode(this.id + "_transform", this.scene); this.transformNode.metadata = {exportable: true}; this._mesh.setParent(this.transformNode); @@ -154,7 +152,6 @@ export class DiagramConnection { } private beforeRender = () => { - if (this.tick % 5 == 0) { this.recalculate(); this.setPoints(); diff --git a/src/objects/handle.ts b/src/objects/handle.ts index c5bbe87..e0572db 100644 --- a/src/objects/handle.ts +++ b/src/objects/handle.ts @@ -1,5 +1,5 @@ -import {AbstractMesh, InstancedMesh, Mesh, MeshBuilder, Scene, TransformNode, Vector3} from "@babylonjs/core"; -import {buildStandardMaterial} from "../materials/functions/buildStandardMaterial"; +import {AbstractMesh, InstancedMesh, Mesh, Scene, TransformNode, Vector3} from "@babylonjs/core"; +import {HtmlMeshBuilder} from "babylon-html"; export class Handle { public mesh: AbstractMesh; @@ -86,13 +86,18 @@ function getHandleMesh(name: string, scene: Scene): InstancedMesh { instance.setParent(scene.getMeshByName("platform")); return instance; } - const handle = MeshBuilder.CreateCapsule("base-handle-mesh", { + /*const handle = MeshBuilder.CreateCapsule("base-handle-mesh", { radius: .04, orientation: Vector3.Right(), height: .3 + }, scene);*/ + const handle = HtmlMeshBuilder.CreatePlaneSync("base-handle-mesh", { + html: + `