UNPKG

mylingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

341 lines (299 loc) 9.71 kB
import cubeShape from "./cannon/shapes/cubeShape" import { Object3D, Vector3 } from "three" import type { Body } from "cannon-es" import { Cancellable } from "@lincode/promiselikes" import { assertExhaustive } from "@lincode/utils" import { Point3d } from "@lincode/math" import SimpleObjectManager from "../SimpleObjectManager" import IPhysicsObjectManager, { PhysicsGroupIndex, PhysicsOptions, PhysicsShape } from "../../../interface/IPhysicsObjectManager" import StaticObjectManager from "../StaticObjectManager" import bvhContactMap from "./bvh/bvhContactMap" import { cannonContactBodies, cannonContactMap } from "./cannon/cannonLoop" import MeshItem from "../MeshItem" import characterCameraPlaced from "../CharacterCamera/characterCameraPlaced" import PhysicsUpdate from "./PhysicsUpdate" export default class PhysicsObjectManager<T extends Object3D = Object3D> extends SimpleObjectManager<T> implements IPhysicsObjectManager { protected _mAV?: Point3d private getMAV() { return (this._mAV ??= new Point3d(Infinity, Infinity, Infinity)) } public get maxAngularVelocityX() { return this._mAV?.x ?? Infinity } public set maxAngularVelocityX(val) { this.getMAV().x = val } public get maxAngularVelocityY() { return this._mAV?.y ?? Infinity } public set maxAngularVelocityY(val) { this.getMAV().y = val } public get maxAngularVelocityZ() { return this._mAV?.z ?? Infinity } public set maxAngularVelocityZ(val) { this.getMAV().z = val } protected _mV?: Point3d private getMV() { return (this._mV ??= new Point3d(Infinity, Infinity, Infinity)) } public get maxVelocityX() { return this._mV?.x ?? Infinity } public set maxVelocityX(val) { this.getMV().x = val } public get maxVelocityY() { return this._mV?.y ?? Infinity } public set maxVelocityY(val) { this.getMV().y = val } public get maxVelocityZ() { return this._mV?.z ?? Infinity } public set maxVelocityZ(val) { this.getMV().z = val } protected cannonBody?: Body public applyForce(x: number, y: number, z: number) { setTimeout(() => this.cannonBody?.applyForce({ x, y, z } as any)) } public applyImpulse(x: number, y: number, z: number) { setTimeout(() => this.cannonBody?.applyImpulse({ x, y, z } as any)) } public applyLocalForce(x: number, y: number, z: number) { setTimeout(() => this.cannonBody?.applyLocalForce({ x, y, z } as any)) } public applyLocalImpulse(x: number, y: number, z: number) { setTimeout(() => this.cannonBody?.applyLocalImpulse({ x, y, z } as any)) } public applyTorque(x: number, y: number, z: number) { setTimeout(() => this.cannonBody?.applyTorque({ x, y, z } as any)) } public get velocity(): Point3d { if (this.bvhVelocity) return this.bvhVelocity if (this.cannonBody) return this.cannonBody.velocity return new Point3d(0, 0, 0) } public set velocity(val) { if (this.bvhVelocity) Object.assign(this.bvhVelocity, val) else if (this.cannonBody) Object.assign(this.cannonBody.velocity, val) } protected positionUpdate?: PhysicsUpdate protected rotationUpdate?: PhysicsUpdate private refreshCannon() { this.positionUpdate && (this.physics = this._physics ?? false) } protected _noTumble?: boolean public get noTumble() { return this._noTumble } public set noTumble(val) { this._noTumble = val this.refreshCannon() } protected _slippery?: boolean public get slippery() { return this._slippery } public set slippery(val) { this._slippery = val this.refreshCannon() } protected _mass?: number public get mass() { return this._mass } public set mass(val) { this._mass = val this.refreshCannon() } protected _physicsGroup?: PhysicsGroupIndex public get physicsGroup() { return this._physicsGroup } public set physicsGroup(val) { this._physicsGroup = val this.refreshCannon() } protected _ignorePhysicsGroups?: Array<PhysicsGroupIndex> public get ignorePhysicsGroups() { return this._ignorePhysicsGroups } public set ignorePhysicsGroups(val) { this._ignorePhysicsGroups = val this.refreshCannon() } protected _physicsShape?: PhysicsShape public get physicsShape() { return (this._physicsShape ??= cubeShape) } public set physicsShape(val) { this._physicsShape = val this.refreshCannon() } protected bvhVelocity?: Vector3 protected bvhOnGround?: boolean protected bvhRadius?: number protected bvhHalfHeight?: number protected bvhMap?: boolean protected bvhCharacter?: boolean protected initPhysics(val: PhysicsOptions, handle: Cancellable) { if (!val || handle.done) return switch (val) { case true: case "2d": import("./enableCannon").then((module) => module.default.call(this, handle) ) break case "map": this.bvhMap = true import("./enableBVHMap").then((module) => module.default.call(this, handle, false) ) break case "map-debug": this.bvhMap = true import("./enableBVHMap").then((module) => module.default.call(this, handle, true) ) break case "character": this.bvhCharacter = true import("./enableBVHCharacter").then((module) => module.default.call(this, handle) ) break default: assertExhaustive(val) } } protected _physics?: PhysicsOptions public get physics() { return this._physics ?? false } public set physics(val) { this._physics = val this.initPhysics( val, this.cancelHandle("physics", () => new Cancellable())! ) } protected _gravity?: boolean public get gravity() { return this._gravity ?? true } public set gravity(val) { this._gravity = val } public override intersects(target: StaticObjectManager): boolean { if (this.done) return false if (target.done) return false if (this === target) return false if (target instanceof PhysicsObjectManager) { if ( (this.bvhMap && target.bvhCharacter) || (this.bvhCharacter && target.bvhMap) ) return ( bvhContactMap.get(this)?.has(target) || bvhContactMap.get(target)?.has(this) || false ) if (this.cannonBody && target.cannonBody) { cannonContactBodies.add(this.cannonBody) cannonContactBodies.add(target.cannonBody) return ( cannonContactMap .get(this.cannonBody) ?.has(target.cannonBody) || cannonContactMap .get(target.cannonBody) ?.has(this.cannonBody) || false ) } } return super.intersects(target) } public override get x() { return super.x } public override set x(val) { super.x = val this.positionUpdate?.updateX() } public override get y() { return super.y } public override set y(val) { super.y = val this.positionUpdate?.updateY() } public override get z() { return super.z } public override set z(val) { super.z = val this.positionUpdate?.updateZ() } public override get rotationX() { return super.rotationX } public override set rotationX(val) { super.rotationX = val this.rotationUpdate?.updateX() } public override get rotationY() { return super.rotationY } public override set rotationY(val) { super.rotationY = val this.rotationUpdate?.updateY() } public override get rotationZ() { return super.rotationZ } public override set rotationZ(val) { super.rotationZ = val this.rotationUpdate?.updateZ() } public override lookAt(target: MeshItem | Point3d): void public override lookAt(x: number, y: number | undefined, z: number): void public override lookAt(a0: any, a1?: any, a2?: any) { super.lookAt(a0, a1, a2) this.rotationUpdate?.updateXYZ() } public override placeAt(object: MeshItem | Point3d | string) { super.placeAt(object) this.positionUpdate?.updateXYZ() this.rotationUpdate?.updateXYZ() characterCameraPlaced.add(this) } public override lerpTo(x: number, y: number, z: number, alpha: number) { super.lerpTo(x, y, z, alpha, () => this.positionUpdate?.updateXYZ()) } public override moveTo( x: number, y: number | undefined, z: number, speed: number ) { super.moveTo(x, y, z, speed, (y) => y === undefined ? this.positionUpdate?.updateXZ() : this.positionUpdate?.updateXYZ() ) } }