From 05e32d7c4b91c2a9c58b2aad1f7bf270757ec34f Mon Sep 17 00:00:00 2001 From: Michael Mainguy Date: Thu, 21 Sep 2023 17:49:36 -0500 Subject: [PATCH] Refactored physics for rig. Fixed kick physics. --- src/controllers/functions/buildRig.ts | 16 ++++- src/controllers/rigplatform.ts | 3 - src/soccer/soccerMenu.ts | 85 +++++++++++++++++++-------- 3 files changed, 73 insertions(+), 31 deletions(-) diff --git a/src/controllers/functions/buildRig.ts b/src/controllers/functions/buildRig.ts index 04faf88..eb8d57a 100644 --- a/src/controllers/functions/buildRig.ts +++ b/src/controllers/functions/buildRig.ts @@ -7,19 +7,28 @@ import { PhysicsShapeType, Scene, StandardMaterial, + TransformNode, Vector3 } from "@babylonjs/core"; import {AppConfig} from "../../util/appConfig"; export function buildRig(scene: Scene, appConfig: AppConfig): Mesh { - const rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .1, depth: 2}, scene); + const rigMesh = MeshBuilder.CreateCylinder("platform", {diameter: .5, height: 1.6}, scene); + const cameratransform = new TransformNode("cameraTransform", scene); + cameratransform.parent = rigMesh; + cameratransform.position = new Vector3(0, -.8, 0); for (const cam of scene.cameras) { - cam.parent = rigMesh; + cam.parent = cameratransform; } + + scene.onActiveCameraChanged.add((s) => { + s.activeCamera.parent = cameratransform; + }); + const rigMaterial = new StandardMaterial("rigMaterial", scene); rigMaterial.diffuseColor = Color3.Blue(); rigMesh.material = rigMaterial; - rigMesh.setAbsolutePosition(new Vector3(0, .1, -3)); + rigMesh.setAbsolutePosition(new Vector3(0, .01, -3)); rigMesh.visibility = 0; const rigAggregate = new PhysicsAggregate( @@ -28,6 +37,7 @@ export function buildRig(scene: Scene, appConfig: AppConfig): Mesh { {friction: 0, center: Vector3.Zero(), mass: 50, restitution: .1}, scene); + /*const rightFoot = MeshBuilder.CreateBox("rightFoot", {width: .1, height: .1, depth: .2}, scene); const rightFootAggregate = new PhysicsAggregate( diff --git a/src/controllers/rigplatform.ts b/src/controllers/rigplatform.ts index bddcd82..aeb2d73 100644 --- a/src/controllers/rigplatform.ts +++ b/src/controllers/rigplatform.ts @@ -39,9 +39,6 @@ export class Rigplatform { this.rigMesh = buildRig(scene, this.diagramManager.config); this.fixRotation(); this.initializeControllers(); - scene.onActiveCameraChanged.add((s) => { - s.activeCamera.parent = this.rigMesh; - }); this.registerVelocityObserver(); } public forwardback(val: number) { diff --git a/src/soccer/soccerMenu.ts b/src/soccer/soccerMenu.ts index 8e2b6aa..65a29c1 100644 --- a/src/soccer/soccerMenu.ts +++ b/src/soccer/soccerMenu.ts @@ -1,7 +1,7 @@ -import {Color3, MeshBuilder, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core"; +import {Color3, MeshBuilder, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core"; import {AbstractMenu} from "../menus/abstractMenu"; import {ControllerEvent, ControllerEventType, Controllers} from "../controllers/controllers"; -import {GUI3DManager, PlanePanel} from "@babylonjs/gui"; +import {Control3D, GUI3DManager, PlanePanel, Slider3D} from "@babylonjs/gui"; import log, {Logger} from "loglevel"; import {Field} from "./field"; import {getFrontPosition} from "../util/functions/getFrontPosition"; @@ -46,24 +46,62 @@ export class SoccerMenu extends AbstractMenu { } + private forceFactor: number = 10; + + private buildKickLine(direction: Vector3, force: number) { + const start = this.field.ball.position.clone(); + const line = MeshBuilder.CreateLines("kickLine", {points: [start, start.add(direction.scale(force))]}, this.scene); + line.color = new Color3(1, 1, .5); + line.isPickable = false; + setTimeout(() => { + line.dispose(); + }, 2000); + + } + + makeSlider(name: string): Control3D { + const slider = new Slider3D(name, false); + slider.scaling.x = 2; + slider.minimum = 10; + slider.maximum = 30; + + slider.value = this.forceFactor; + + slider.onValueChangedObservable.add((value) => { + this.logger.debug(`slider value ${value}`); + this.forceFactor = value; + }); + return slider; + } + private playControllerEventHandler(event: ControllerEvent) { switch (event.type) { case ControllerEventType.TRIGGER: if (event.value > .8) { if (!this.startTime) { this.startTime = new Date().getTime(); - this.startPosition = event.controller.pointer.position.clone(); + const start = event.controller.grip.absolutePosition.clone(); + //transform start to this.xr.baseExperience.camera space + start.subtractInPlace(this.xr.baseExperience.camera.globalPosition); + //const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles(); + //start.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0)); + this.startPosition = start; } + + } else { if (this.startTime) { - const endPosition = event.controller.pointer.position.clone(); + const end = event.controller.grip.absolutePosition.clone(); + //transform start to this.xr.baseExperience.camera space + end.subtractInPlace(this.xr.baseExperience.camera.globalPosition); + //const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles(); + //end.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0)); if (this.startTime && this.startPosition) { const duration = new Date().getTime() - this.startTime; - this.controllers.controllerObserver.notifyObservers({ type: ControllerEventType.MOTION, startPosition: this.startPosition, - endPosition: endPosition, + endPosition: end, duration: duration }); this.startTime = null; @@ -73,10 +111,15 @@ export class SoccerMenu extends AbstractMenu { } const worldRay = this.scene.activeCamera.getForwardRay(); worldRay.origin = this.scene.activeCamera.globalPosition; - const pickInfo = this.scene.pickWithRay(worldRay, null); + const pickInfo = this.scene.pickWithRay(worldRay, function (mesh) { + return mesh.name != 'platform'; + }); if (pickInfo?.hit) { - const circle = MeshBuilder.CreateSphere("circle", {diameter: .04}, this.scene); - circle.position = pickInfo.pickedPoint; + const circle = MeshBuilder.CreateDisc("circle", {radius: .04}, this.scene); + + const normal = pickInfo.getNormal(true, false).scale(-1); + circle.position = pickInfo.pickedPoint.add(normal.scale(-.01)); + circle.lookAt(pickInfo.pickedPoint.add(normal)); setTimeout(() => { circle.dispose(); }, 1500); @@ -100,11 +143,10 @@ export class SoccerMenu extends AbstractMenu { case ControllerEventType.MOTION: const start = event.startPosition.clone(); const direction = start.subtract(event.endPosition); - const force = direction.length() * 10; + const force = direction.length() * this.forceFactor; const dir = direction.normalize(); - const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles(); - direction.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0)); - + //const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles(); + //direction.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0)); this.buildKickLine(dir, force); this.field.ball.kick(dir, force); break; @@ -116,17 +158,6 @@ export class SoccerMenu extends AbstractMenu { } } - private buildKickLine(direction: Vector3, force: number) { - const start = this.field.ball.position.clone(); - const line = MeshBuilder.CreateLines("kickLine", {points: [start, start.add(direction.scale(force))]}, this.scene); - line.color = new Color3(1, 1, .5); - line.isPickable = false; - setTimeout(() => { - line.dispose(); - }, 2000); - - } - makeButton(name: string, id: string) { const button = super.makeButton(name, id); button.onPointerClickObservable.add(this.handleClick, -1, false, this); @@ -135,14 +166,18 @@ export class SoccerMenu extends AbstractMenu { private buildMenu() { const panel = new PlanePanel(); - panel.columns = 4; this.manager.addControl(panel); + panel.columns = 10; panel.addControl(this.makeButton("Play", "play")); panel.addControl(this.makeButton("Plan", "plan")); panel.addControl(this.makeButton("Train", "Train")); panel.addControl(this.makeButton("Modify", "modify")); + const slider = panel.addControl(this.makeSlider("force")); + this.manager.rootContainer.children[0].node.position.y = .2; this.manager.controlScaling = .2; + //panel.updateLayout(); + //slider.position.x = 1; this.createHandle(this.manager.rootContainer.children[0].node); this.handle.mesh.position = getFrontPosition(3, this.scene).add(new Vector3(0, .5, 0)); }