refactored grabbing.

This commit is contained in:
Michael Mainguy 2023-08-23 08:57:12 -05:00
parent 88668c3d64
commit d59e75ddc9
4 changed files with 79 additions and 71 deletions

View File

@ -14,6 +14,8 @@ import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
import log from "loglevel"; import log from "loglevel";
import {Controllers} from "./controllers"; import {Controllers} from "./controllers";
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity"; import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
import {setupTransformNode} from "./functions/setupTransformNode";
import {reparent} from "./functions/reparent";
export class Base { export class Base {
static stickVector = Vector3.Zero(); static stickVector = Vector3.Zero();
@ -92,20 +94,8 @@ export class Base {
this.controller.pointer.setEnabled(true); this.controller.pointer.setEnabled(true);
} }
private setupTransformNode(mesh: TransformNode) { private grab() {
const transformNode = new TransformNode("grabAnchor, this.scene"); const mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
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);
}
if (!mesh) { if (!mesh) {
return; return;
} }
@ -123,18 +113,20 @@ export class Base {
} }
} }
this.previousParentId = mesh?.parent?.id; this.previousParentId = mesh?.parent?.id;
this.logger.warn("grabbed " + mesh?.id + " parent " + this.previousParentId);
this.previousRotation = mesh?.rotation.clone(); this.previousRotation = mesh?.rotation.clone();
this.previousScaling = mesh?.scaling.clone(); this.previousScaling = mesh?.scaling.clone();
this.previousPosition = mesh?.position.clone(); this.previousPosition = mesh?.position.clone();
if ("toolbox" != mesh?.parent?.parent?.id) { if ("toolbox" != mesh?.parent?.parent?.id) {
if (mesh.physicsBody) { if (mesh.physicsBody) {
const transformNode = this.setupTransformNode(mesh); const transformNode = setupTransformNode(mesh, this.controller.motionController.rootMesh);
mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED); mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED);
this.grabbedMeshParentId = transformNode.id; this.grabbedMeshParentId = transformNode.id;
} else { } else {
mesh.setParent(this.controller.motionController.rootMesh); mesh.setParent(this.controller.motionController.rootMesh);
} }
this.grabbedMesh = mesh; this.grabbedMesh = mesh;
} else { } else {
const newMesh = this.diagramManager.createCopy(mesh); const newMesh = this.diagramManager.createCopy(mesh);
@ -148,9 +140,6 @@ export class Base {
} }
transformNode.setParent(this.controller.motionController.rootMesh); transformNode.setParent(this.controller.motionController.rootMesh);
this.grabbedMeshParentId = transformNode.id; this.grabbedMeshParentId = transformNode.id;
//newMesh && newMesh.setParent(this.controller.motionController.rootMesh);
this.grabbedMesh = newMesh; this.grabbedMesh = newMesh;
this.previousParentId = null; this.previousParentId = null;
const event: DiagramEvent = { const event: DiagramEvent = {
@ -158,14 +147,12 @@ export class Base {
entity: toDiagramEntity(newMesh) entity: toDiagramEntity(newMesh)
} }
this.diagramManager.onDiagramEventObservable.notifyObservers(event); this.diagramManager.onDiagramEventObservable.notifyObservers(event);
} }
} }
private handleGrabbed(mesh: AbstractMesh): boolean { private toolboxHandleWasGrabbed(mesh: AbstractMesh): boolean {
if (!mesh?.metadata?.template if (!mesh?.metadata?.template
&& mesh?.id == "handle") { && mesh?.id == "handle") {
//mesh && mesh.setParent(null);
this.grabbedMesh = null; this.grabbedMesh = null;
this.previousParentId = null; this.previousParentId = null;
mesh.setParent(null); mesh.setParent(null);
@ -174,38 +161,18 @@ export class Base {
return false; return false;
} }
} }
private reparent(mesh: AbstractMesh) {
if (this.previousParentId) {
const parent = this.scene.getMeshById(this.previousParentId);
if (parent) {
//mesh && mesh.setParent(this.scene.getMeshById(this.previousParentId));
log.getLogger("Base").warn("Base", "Have not implemented snapping to parent yet");
//@note: this is not implemented yet
} else {
mesh.setParent(null);
}
} else {
const parent = this.scene.getTransformNodeById(this.grabbedMeshParentId);
if (parent) {
this.grabbedMeshParentId = null;
parent.dispose();
} else {
mesh.setParent(null);
}
}
}
private drop() { private drop() {
const mesh = this.grabbedMesh; const mesh = this.grabbedMesh;
if (!mesh) { if (!mesh) {
return; return;
} }
if (this.handleGrabbed(mesh)) { if (this.toolboxHandleWasGrabbed(mesh)) {
return; return;
} }
this.reparent(mesh); reparent(mesh, this.previousParentId, this.grabbedMeshParentId);
this.grabbedMeshParentId = null;
if (!mesh.physicsBody) { if (!mesh.physicsBody) {
mesh.position = this.diagramManager.config.snapGridVal(mesh.position, this.diagramManager.config.current.gridSnap); mesh.position = this.diagramManager.config.snapGridVal(mesh.position, this.diagramManager.config.current.gridSnap);
mesh.rotation = this.diagramManager.config.snapRotateVal(mesh.rotation, this.diagramManager.config.current.rotateSnap); mesh.rotation = this.diagramManager.config.snapRotateVal(mesh.rotation, this.diagramManager.config.current.rotateSnap);
@ -242,7 +209,7 @@ export class Base {
grip.onButtonStateChangedObservable.add(() => { grip.onButtonStateChangedObservable.add(() => {
if (grip.changes.pressed) { if (grip.changes.pressed) {
if (grip.pressed) { if (grip.pressed) {
this.grab(this.scene.meshUnderPointer); this.grab();
} else { } else {
this.drop(); this.drop();
} }

View File

@ -0,0 +1,26 @@
import {AbstractMesh} from "@babylonjs/core";
import log from "loglevel";
const logger = log.getLogger('reparent');
export function reparent(mesh: AbstractMesh, previousParentId: string, grabbedMeshParentId: string) {
if (previousParentId) {
const parent = mesh.getScene().getMeshById(previousParentId);
if (parent) {
//mesh && mesh.setParent(this.scene.getMeshById(this.previousParentId));
logger.warn('not yet implemented')
//@note: this is not implemented yet
} else {
mesh.setParent(null);
}
} else {
const parent = mesh.getScene().getTransformNodeById(grabbedMeshParentId);
if (parent) {
logger.warn('setting parent to null', grabbedMeshParentId, parent)
//this.grabbedMeshParentId = null;
parent.dispose();
} else {
mesh.setParent(null);
}
}
}

View File

@ -0,0 +1,10 @@
import {AbstractMesh, TransformNode} from "@babylonjs/core";
export function setupTransformNode(mesh: TransformNode, parent: AbstractMesh) {
const transformNode = new TransformNode("grabAnchor, this.scene");
transformNode.id = "grabAnchor";
transformNode.position = mesh.position.clone();
transformNode.rotationQuaternion = mesh.rotationQuaternion.clone();
transformNode.setParent(parent);
return transformNode;
}

View File

@ -1,9 +1,14 @@
import {DiaSounds} from "../../util/diaSounds"; import {DiaSounds} from "../../util/diaSounds";
import {AbstractMesh, PhysicsAggregate, PhysicsMotionType, PhysicsShapeType, Scene} from "@babylonjs/core"; import {AbstractMesh, PhysicsAggregate, PhysicsBody, PhysicsMotionType, PhysicsShapeType, Scene} from "@babylonjs/core";
import log from "loglevel"; import log from "loglevel";
export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene, motionType?: PhysicsMotionType) { const logger = log.getLogger('DiagramShapePhysics');
const logger = log.getLogger('DiagramShapePhysics'); const MASS_FACTOR = 10;
export function applyPhysics(sounds: DiaSounds,
mesh: AbstractMesh,
scene: Scene,
motionType?: PhysicsMotionType) {
if (!mesh?.metadata?.template) { if (!mesh?.metadata?.template) {
logger.error("applyPhysics: mesh.metadata.template is null", mesh); logger.error("applyPhysics: mesh.metadata.template is null", mesh);
return; return;
@ -15,11 +20,9 @@ export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene
logger.error("applyPhysics: mesh or scene is null"); logger.error("applyPhysics: mesh or scene is null");
return; return;
} }
if (mesh.physicsBody) { if (mesh.physicsBody) {
mesh.physicsBody.dispose(); mesh.physicsBody.dispose();
} }
let shapeType = PhysicsShapeType.BOX; let shapeType = PhysicsShapeType.BOX;
switch (mesh.metadata.template) { switch (mesh.metadata.template) {
case "#sphere-template": case "#sphere-template":
@ -31,16 +34,32 @@ export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene
case "#cone-template": case "#cone-template":
shapeType = PhysicsShapeType.CONVEX_HULL; shapeType = PhysicsShapeType.CONVEX_HULL;
break; break;
} }
let mass = mesh.scaling.x * mesh.scaling.y * mesh.scaling.z * 10; const mass = mesh.scaling.x * mesh.scaling.y * mesh.scaling.z * MASS_FACTOR;
const aggregate = new PhysicsAggregate(mesh, const aggregate = new PhysicsAggregate(mesh,
shapeType, {mass: mass, restitution: .02, friction: .9}, scene); shapeType, {mass: mass, restitution: .02, friction: .9}, scene);
const body = aggregate.body; const body = aggregate.body;
body.setLinearDamping(1.95); applyMotionType(motionType, body, mesh);
body.setAngularDamping(1.99);
body.setCollisionCallbackEnabled(true);
body.getCollisionObservable().add((event) => {
if (event.impulse < 10 && event.impulse > 1) {
const sound = sounds.bounce;
sound.setVolume(event.impulse / 10);
sound.attachToMesh(mesh);
sound.play();
}
}, -1, false);
applyPhysicsDefaults(body);
}
function applyPhysicsDefaults(body: PhysicsBody) {
body.setLinearDamping(.95);
body.setAngularDamping(.99);
body.setGravityFactor(0);
}
function applyMotionType(motionType: PhysicsMotionType, body: PhysicsBody, mesh: AbstractMesh) {
if (motionType) { if (motionType) {
body body
.setMotionType(motionType); .setMotionType(motionType);
@ -53,18 +72,4 @@ export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene
.setMotionType(PhysicsMotionType.DYNAMIC); .setMotionType(PhysicsMotionType.DYNAMIC);
} }
} }
body.setCollisionCallbackEnabled(true);
body.getCollisionObservable().add((event) => {
if (event.impulse < 10 && event.impulse > 1) {
const sound = sounds.bounce;
sound.setVolume(event.impulse / 10);
sound.attachToMesh(mesh);
sound.play();
}
}, -1, false, this);
//body.setMotionType(PhysicsMotionType.ANIMATED);
body.setLinearDamping(.95);
body.setAngularDamping(.99);
body.setGravityFactor(0);
} }