181 lines
6.8 KiB
TypeScript
181 lines
6.8 KiB
TypeScript
import {
|
|
Angle,
|
|
Camera,
|
|
Color3,
|
|
Mesh,
|
|
MeshBuilder,
|
|
PhysicsAggregate,
|
|
PhysicsBody,
|
|
PhysicsMotionType,
|
|
PhysicsShapeType,
|
|
Quaternion,
|
|
Scene,
|
|
StandardMaterial,
|
|
Vector3,
|
|
WebXRDefaultExperience
|
|
} from "@babylonjs/core";
|
|
import {Right} from "./right";
|
|
import {Left} from "./left";
|
|
import {EditMenu} from "../menus/editMenu";
|
|
import {Controllers} from "./controllers";
|
|
import log from "loglevel";
|
|
import {DiagramManager} from "../diagram/diagramManager";
|
|
|
|
|
|
export class Rigplatform {
|
|
private velocityIndex = 2;
|
|
private readonly velocityArray = [0.01, 0.1, 1, 2, 5];
|
|
public bMenu: EditMenu;
|
|
private readonly scene: Scene;
|
|
public static instance: Rigplatform;
|
|
private static xr: WebXRDefaultExperience;
|
|
private yRotation: number = 0;
|
|
public body: PhysicsBody;
|
|
public rigMesh: Mesh;
|
|
private camera: Camera;
|
|
private turning: boolean = false;
|
|
private velocity: Vector3 = Vector3.Zero();
|
|
private logger = log.getLogger('Rigplatform');
|
|
private readonly diagramManager: DiagramManager;
|
|
|
|
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
|
|
|
|
this.scene = scene;
|
|
this.diagramManager = diagramManager;
|
|
Rigplatform.xr = xr;
|
|
Rigplatform.instance = this;
|
|
this.bMenu = new EditMenu(scene, xr.baseExperience, this.diagramManager);
|
|
this.camera = scene.activeCamera;
|
|
|
|
this.rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .02, depth: 2}, scene);
|
|
for (const cam of scene.cameras) {
|
|
cam.parent = this.rigMesh;
|
|
}
|
|
const rigMaterial = new StandardMaterial("rigMaterial", scene);
|
|
rigMaterial.diffuseColor = Color3.Blue();
|
|
this.rigMesh.material = rigMaterial;
|
|
this.rigMesh.setAbsolutePosition(new Vector3(0, .1, -3));
|
|
this.rigMesh.visibility = 0;
|
|
const rigAggregate =
|
|
new PhysicsAggregate(
|
|
this.rigMesh,
|
|
PhysicsShapeType.CYLINDER,
|
|
{friction: 1, center: Vector3.Zero(), radius: .5, mass: 10, restitution: .01},
|
|
scene);
|
|
rigAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC);
|
|
rigAggregate.body.setGravityFactor(.001);
|
|
this.fixRotation();
|
|
this.body = rigAggregate.body;
|
|
this.initializeControllers();
|
|
scene.onActiveCameraChanged.add((s) => {
|
|
this.camera = s.activeCamera;
|
|
this.camera.parent = this.rigMesh;
|
|
});
|
|
this.registerVelocityObserver();
|
|
}
|
|
private registerVelocityObserver() {
|
|
this.scene.onBeforeRenderObservable.add(() => {
|
|
const vel = this.velocity.applyRotationQuaternion(this.scene.activeCamera.absoluteRotation);
|
|
if (vel.length() > 0) {
|
|
this.logger.debug('Velocity', this.velocity, vel, this.scene.activeCamera.absoluteRotation);
|
|
}
|
|
this.body.setLinearVelocity(vel);
|
|
});
|
|
}
|
|
public forwardback(val: number) {
|
|
this.velocity.z = (val * this.velocityArray[this.velocityIndex])*-1;
|
|
}
|
|
public leftright(val: number) {
|
|
this.velocity.x = (val * this.velocityArray[this.velocityIndex]);
|
|
}
|
|
public updown(val: number) {
|
|
this.velocity.y = (val * this.velocityArray[this.velocityIndex])*-1;
|
|
}
|
|
public turn(val: number) {
|
|
const snap = true;
|
|
if (snap) {
|
|
if (!this.turning) {
|
|
if (Math.abs(val) > .1) {
|
|
this.turning = true;
|
|
this.yRotation += Angle.FromDegrees(Math.sign(val) * 22.5).radians();
|
|
}
|
|
} else {
|
|
if (Math.abs(val) < .1) {
|
|
this.turning = false;
|
|
}
|
|
}
|
|
} else {
|
|
if (Math.abs(val) > .1) {
|
|
this.body.setAngularVelocity(Vector3.Up().scale(val));
|
|
} else {
|
|
this.body.setAngularVelocity(Vector3.Zero());
|
|
}
|
|
}
|
|
}
|
|
|
|
private initializeControllers() {
|
|
Rigplatform.xr.input.onControllerAddedObservable.add((source) => {
|
|
let controller;
|
|
switch (source.inputSource.handedness) {
|
|
case "right":
|
|
Right.instance = new Right(source, this.scene, Rigplatform.xr, this.diagramManager);
|
|
Controllers.controllerObserver.add((event: { type: string, value: number }) => {
|
|
switch (event.type) {
|
|
case "increaseVelocity":
|
|
if (this.velocityIndex < this.velocityArray.length - 1) {
|
|
this.velocityIndex++;
|
|
} else {
|
|
this.velocityIndex = 0;
|
|
}
|
|
break;
|
|
case "decreaseVelocity":
|
|
if (this.velocityIndex > 0) {
|
|
this.velocityIndex--;
|
|
} else {
|
|
this.velocityIndex = this.velocityArray.length-1;
|
|
}
|
|
break;
|
|
case "turn":
|
|
this.turn(event.value);
|
|
break;
|
|
case "forwardback":
|
|
this.forwardback(event.value);
|
|
break;
|
|
case "leftright":
|
|
this.leftright(event.value);
|
|
break;
|
|
case "updown":
|
|
this.updown(event.value);
|
|
break;
|
|
case "stop":
|
|
log.warn("Rigplatform", "stop is no longer implemented");
|
|
break;
|
|
case "menu":
|
|
this.bMenu.toggle();
|
|
break;
|
|
}
|
|
});
|
|
break;
|
|
case "left":
|
|
Left.instance = new Left(source, this.scene, Rigplatform.xr, this.diagramManager);
|
|
break;
|
|
|
|
}
|
|
Rigplatform.xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
|
|
if (controller) {
|
|
controller.setRig(this);
|
|
}
|
|
});
|
|
}
|
|
private fixRotation() {
|
|
this.scene.registerBeforeRender(() => {
|
|
const q = this.rigMesh.rotationQuaternion;
|
|
this.body.setAngularVelocity(Vector3.Zero());
|
|
if (q) {
|
|
const e = q.toEulerAngles();
|
|
e.y += this.yRotation;
|
|
q.copyFrom(Quaternion.FromEulerAngles(0, e.y, 0));
|
|
}
|
|
});
|
|
}
|
|
} |