Refactored physics for rig. Fixed kick physics.

This commit is contained in:
Michael Mainguy 2023-09-21 17:49:36 -05:00
parent ad3c8db41d
commit 05e32d7c4b
3 changed files with 73 additions and 31 deletions

View File

@ -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(

View File

@ -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) {

View File

@ -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));
}