immersive2/src/diagram/functions/diagramShapePhysics.ts

77 lines
2.4 KiB
TypeScript

import {AbstractMesh, PhysicsAggregate, PhysicsBody, PhysicsMotionType, PhysicsShapeType, Scene} from "@babylonjs/core";
import log from "loglevel";
import {isDiagramEntity} from "./isDiagramEntity";
const MASS_FACTOR = 10;
export function applyPhysics(
mesh: AbstractMesh,
scene: Scene,
motionType?: PhysicsMotionType) {
const logger = log.getLogger('DiagramShapePhysics');
if (!isDiagramEntity(mesh)) {
logger.error("applyPhysics: mesh.metadata.template is null", mesh);
return;
}
if (mesh.metadata.template == '#connection-template') {
return;
}
if (!scene) {
logger.error("applyPhysics: mesh or scene is null");
return;
}
if (mesh.physicsBody) {
mesh.physicsBody.dispose();
}
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 mass = mesh.scaling.x * mesh.scaling.y * mesh.scaling.z * MASS_FACTOR;
const aggregate = new PhysicsAggregate(mesh,
shapeType, {mass: mass, restitution: .02, friction: .9}, scene);
const body = aggregate.body;
applyMotionType(motionType, body, mesh);
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) {
body
.setMotionType(motionType);
} else {
if (mesh.parent) {
body
.setMotionType(PhysicsMotionType.ANIMATED);
} else {
body
.setMotionType(PhysicsMotionType.DYNAMIC);
}
}
}