Refactored physics to reduce duplicate code.

This commit is contained in:
Michael Mainguy 2023-07-31 20:45:44 -05:00
parent cdefd3bb70
commit 89623b5007
6 changed files with 78 additions and 47 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 MiB

View File

@ -40,7 +40,7 @@ export class App {
constructor() {
const config = AppConfig.config;
log.setLevel('warn');
log.setLevel('debug');
const canvas = document.createElement("canvas");
canvas.style.width = "100%";
canvas.style.height = "100%";
@ -125,7 +125,6 @@ export class App {
this.scene.gamepadManager.onGamepadConnectedObservable.add((gamepad) => {
try {
const dualshock = (gamepad as DualShockPad);
dualshock.onButtonDownObservable.add((button: any) => {
const buttonEvent = DualshockEventMapper.mapButtonEvent(button, 1);
if (buttonEvent.objectName) {

View File

@ -1,9 +1,7 @@
import {
AbstractMesh,
HavokPlugin,
PhysicsAggregate,
PhysicsMotionType,
PhysicsShapeType,
Scene,
TransformNode,
Vector3,
@ -44,9 +42,7 @@ export class Base {
this.controller = controller;
this.scene = scene;
this.scene.onAfterRenderObservable.add(() => {
}, -1, false, this);
this.scene.onBeforeRenderObservable.add(() => {
if (this?.grabbedMesh?.physicsBody) {
@ -106,7 +102,16 @@ export class Base {
}
private grab(mesh) {
private setupTransformNode(mesh: TransformNode) {
const transformNode = new TransformNode("grabAnchor, this.scene");
transformNode.id = "grabAnchor";
transformNode.position = mesh.position.clone();
transformNode.rotationQuaternion = mesh.rotationQuaternion.clone();
transformNode.setParent(this.controller.motionController.rootMesh);
return transformNode;
}
private grab(mesh: AbstractMesh) {
if (this.xr.pointerSelection.getMeshUnderPointer) {
mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
@ -130,12 +135,9 @@ export class Base {
if ("toolbox" != mesh?.parent?.parent?.id) {
if (mesh.physicsBody) {
const transformNode = new TransformNode("grabAnchor, this.scene");
transformNode.id = "grabAnchor";
transformNode.position = mesh.position.clone();
transformNode.rotationQuaternion = mesh.rotationQuaternion.clone();
transformNode.setParent(this.controller.motionController.rootMesh);
mesh.physicsBody.setMotionType(PhysicsMotionType.STATIC);
const transformNode = this.setupTransformNode(mesh);
mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED);
//mesh.setParent(transformNode);
this.grabbedMeshParentId = transformNode.id;
} else {
@ -143,18 +145,7 @@ export class Base {
}
this.grabbedMesh = mesh;
} else {
const config = AppConfig.config;
const newMesh = this.diagramManager.createCopy(mesh);
newMesh.position = mesh.absolutePosition.clone();
if (mesh.absoluteRotationQuaternion) {
newMesh.rotation = mesh.absoluteRotationQuaternion.toEulerAngles().clone();
} else {
newMesh.rotation = mesh.absoluteRotation.clone();
}
newMesh.scaling = config.createSnapVal;
newMesh.material = mesh.material;
newMesh.metadata = mesh.metadata;
const transformNode = new TransformNode("grabAnchor, this.scene");
transformNode.id = "grabAnchor";
transformNode.position = newMesh.position.clone();
@ -163,14 +154,11 @@ export class Base {
} else {
transformNode.rotation = newMesh.rotation.clone();
}
transformNode.setParent(this.controller.motionController.rootMesh);
//newMesh?.physicsBody?.setMotionType(PhysicsMotionType.STATIC);
//mesh.setParent(transformNode);
this.grabbedMeshParentId = transformNode.id;
const aggregate = new PhysicsAggregate(newMesh,
PhysicsShapeType.BOX, {mass: 10, restitution: .1, friction: .9}, this.scene);
aggregate.body.setMotionType(PhysicsMotionType.STATIC);
MeshConverter
.applyPhysics(newMesh, this.scene)
.setMotionType(PhysicsMotionType.ANIMATED);
//newMesh && newMesh.setParent(this.controller.motionController.rootMesh);
@ -199,10 +187,6 @@ export class Base {
}
private reparent(mesh: AbstractMesh) {
const config = AppConfig.config;
const snappedRotation = config.snapRotateVal(mesh.absoluteRotationQuaternion.toEulerAngles().clone());
const snappedPosition = config.snapGridVal(mesh.absolutePosition.clone());
if (this.previousParentId) {
const parent = this.scene.getMeshById(this.previousParentId);
if (parent) {
@ -211,21 +195,28 @@ export class Base {
//@note: this is not implemented yet
} else {
//mesh.setParent(null);
mesh.rotation = snappedRotation;
mesh.position = snappedPosition;
this.applyTransform(mesh)
mesh?.physicsBody?.setMotionType(PhysicsMotionType.DYNAMIC);
}
} else {
const parent = this.scene.getTransformNodeById(this.grabbedMeshParentId);
if (parent) {
parent.rotation = snappedRotation;
parent.position = snappedPosition;
this.applyTransform(parent);
this.grabbedMeshParentId = null;
parent.dispose();
}
}
}
private applyTransform(mesh: TransformNode) {
const config = AppConfig.config;
const snappedRotation = config.snapRotateVal(mesh.absoluteRotationQuaternion.toEulerAngles().clone());
const snappedPosition = config.snapGridVal(mesh.absolutePosition.clone());
mesh.rotation = snappedRotation;
mesh.position = snappedPosition;
}
private drop() {
const mesh = this.grabbedMesh;
if (!mesh) {
@ -258,11 +249,7 @@ export class Base {
//body.setLinearVelocity(this.lastPosition.subtract(body.transformNode.absolutePosition).scale(20));
this.logger.debug(this.lastPosition.subtract(body.transformNode.absolutePosition).scale(20));
}
}
}
private initGrip(grip: WebXRControllerComponent) {

View File

@ -1,5 +1,6 @@
import {Color3, Vector3} from "@babylonjs/core";
import {BmenuState} from "../menus/MenuState";
export enum DiagramEventType {
ADD,
REMOVE,
@ -11,6 +12,8 @@ export enum DiagramEventType {
}
export type DiagramEvent = {
type: DiagramEventType;
menustate?: BmenuState;

View File

@ -6,9 +6,7 @@ import {
InstancedMesh,
Mesh,
Observable,
PhysicsAggregate,
PhysicsMotionType,
PhysicsShapeType,
PlaySoundAction,
Scene,
WebXRExperienceHelper
@ -19,6 +17,7 @@ import {MeshConverter} from "./meshConverter";
import log from "loglevel";
import {Controllers} from "../controllers/controllers";
import {DiaSounds} from "../util/diaSounds";
import {AppConfig} from "../util/appConfig";
export class DiagramManager {
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
@ -72,8 +71,17 @@ export class DiagramManager {
newMesh = new InstancedMesh("new", (mesh as InstancedMesh).sourceMesh);
}
newMesh.actionManager = this.actionManager;
return newMesh;
newMesh.position = mesh.absolutePosition.clone();
if (mesh.absoluteRotationQuaternion) {
newMesh.rotation = mesh.absoluteRotationQuaternion.toEulerAngles().clone();
} else {
this.logger.error("no rotation quaternion");
}
newMesh.scaling = AppConfig.config.createSnapVal;
newMesh.material = mesh.material;
newMesh.metadata = mesh.metadata;
return newMesh;
}
private onRemoteEvent(event: DiagramEntity) {
@ -91,8 +99,8 @@ export class DiagramManager {
if (event.parent) {
mesh.parent = this.scene.getMeshById(event.parent);
}
const body = new PhysicsAggregate(mesh, PhysicsShapeType.BOX, {mass: 10, restitution: .1}, this.scene);
body.body.setMotionType(PhysicsMotionType.DYNAMIC);
MeshConverter.applyPhysics(mesh, this.scene)
.setMotionType(PhysicsMotionType.DYNAMIC);
}

View File

@ -6,6 +6,9 @@ import {
InstancedMesh,
Mesh,
MeshBuilder,
PhysicsAggregate,
PhysicsBody,
PhysicsShapeType,
Scene,
StandardMaterial
} from "@babylonjs/core";
@ -110,6 +113,37 @@ export class MeshConverter {
}
public static applyPhysics(mesh: AbstractMesh, scene: Scene): PhysicsBody {
if (!mesh?.metadata?.template || !scene) {
this.logger.error("applyPhysics: mesh or scene is null");
return null;
}
if (mesh.physicsBody) {
return mesh.physicsBody;
}
let shapeType = PhysicsShapeType.BOX;
switch (mesh.metadata.template) {
case "#sphere-template":
shapeType = PhysicsShapeType.SPHERE;
break;
case "#cylinder-template":
shapeType = PhysicsShapeType.CYLINDER;
break;
case "#cone-template":
shapeType = PhysicsShapeType.CONVEX_HULL;
break;
}
const aggregate = new PhysicsAggregate(mesh,
shapeType, {mass: 20, restitution: .2, friction: .9}, scene);
aggregate.body.setLinearDamping(.9);
aggregate.body.setAngularDamping(.5);
return aggregate.body;
}
public static updateTextNode(mesh: AbstractMesh, text: string) {
if (!mesh) {
this.logger.error("updateTextNode: mesh is null");