import RAPIER from '@dimforge/rapier3d-compat'; import * as RE from 'rogue-engine'; import * as THREE from 'three'; import RogueRapier from '../Lib/RogueRapier'; export type RapierCollisionInfo = {ownCollider: RAPIER.Collider, otherCollider: RAPIER.Collider, otherBody: RapierBody}; export default class RapierBody extends RE.Component { @RE.props.select() type = 0; typeOptions = ["Dynamic", "Fixed", "KinematicPositionBased", "KinematicVelocityBased"]; @RE.props.num() mass = 1; private _gravityScale = 1; @RE.props.num() get gravityScale() { return this._gravityScale; } set gravityScale(value: number) { this._gravityScale = value; RE.Runtime.isRunning && this.body && (this.body.setGravityScale(value, true)); } private _angularDamping = 0; @RE.props.num() get angularDamping() { return this._angularDamping; } set angularDamping(value: number) { this._angularDamping = value; RE.Runtime.isRunning && this.body && (this.body.setAngularDamping(value)); } private _linearDamping = 0; @RE.props.num() get linearDamping() { this.body return this._linearDamping; } set linearDamping(value: number) { this._linearDamping = value; RE.Runtime.isRunning && this.body && (this.body.setLinearDamping(value)); } private _xTranslation = true; @RE.props.checkbox() get xTranslation() { return this._xTranslation; } set xTranslation(value: boolean) { this._xTranslation = value; RE.Runtime.isRunning && this.body && (this.body.setEnabledTranslations(value, this._yTranslation, this._zTranslation, true)); } private _yTranslation = true; @RE.props.checkbox() get yTranslation() { return this._yTranslation; } set yTranslation(value: boolean) { this._yTranslation = value; RE.Runtime.isRunning && this.body && (this.body.setEnabledTranslations(this._xTranslation, value, this._zTranslation, true)); } private _zTranslation = true; @RE.props.checkbox() get zTranslation() { return this._zTranslation; } set zTranslation(value: boolean) { this._zTranslation = value; RE.Runtime.isRunning && this.body && (this.body.setEnabledTranslations(this._xTranslation, this._yTranslation, value, true)); } private _xRotation = true; @RE.props.checkbox() get xRotation() { return this._xRotation; } set xRotation(value: boolean) { this._xRotation = value; RE.Runtime.isRunning && this.body && (this.body.setEnabledRotations(value, this._yRotation, this._zRotation, true)); } private _yRotation = true; @RE.props.checkbox() get yRotation() { return this._yRotation; } set yRotation(value: boolean) { this._yRotation = value; RE.Runtime.isRunning && this.body && (this.body.setEnabledRotations(this._xRotation, value, this._zRotation, true)); } private _zRotation = true; @RE.props.checkbox() get zRotation() { return this._zRotation; } set zRotation(value: boolean) { this._zRotation = value; RE.Runtime.isRunning && this.body && (this.body.setEnabledRotations(this._xRotation, this._yRotation, value, true)); } body: RAPIER.RigidBody; initialized = false; onCollisionStart: (info: RapierCollisionInfo) => void = () => {}; onCollisionEnd: (info: RapierCollisionInfo) => void = () => {}; private newPos = new THREE.Vector3(); private newRot = new THREE.Quaternion(); private matrixA = new THREE.Matrix4(); private matrixB = new THREE.Matrix4(); private matrixC = new THREE.Matrix4(); init() { let rigidBodyDesc = this.getType(); // const pos = this.object3d.position; // const rot = this.object3d.quaternion; this.object3d.getWorldPosition(this.newPos); this.object3d.getWorldQuaternion(this.newRot); rigidBodyDesc .setGravityScale(this._gravityScale) .setTranslation(this.newPos.x, this.newPos.y, this.newPos.z) .setRotation(this.newRot) .setAngularDamping(this._angularDamping) .setLinearDamping(this._linearDamping) .enabledRotations(this._xRotation, this._yRotation, this._zRotation) .enabledTranslations(this._xTranslation, this._yTranslation, this._zTranslation); rigidBodyDesc.mass = this.mass; this.body = RogueRapier.world.createRigidBody(rigidBodyDesc); this.body.userData = {object3d: this.object3d.uuid}; this.initialized = true; } private getType() { if (Number(this.type) === 1) return RAPIER.RigidBodyDesc.fixed(); else if (Number(this.type) === 2) return RAPIER.RigidBodyDesc.kinematicPositionBased(); else if (Number(this.type) === 3) return RAPIER.RigidBodyDesc.kinematicVelocityBased(); else return RAPIER.RigidBodyDesc.dynamic(); } onBeforeRemoved(): void { if (this.body) { RogueRapier.world.removeRigidBody(this.body); } } onDisabled(): void { if (this.body) { RogueRapier.world.removeRigidBody(this.body); } } beforeUpdate(): void { if (!RogueRapier.initialized) return; !this.initialized && this.init(); this.type !== RAPIER.RigidBodyType.Fixed && this.updatePhysics(); } updatePhysics() { this.copyBodyPosition(); this.copyBodyRotation(); } private copyBodyPosition() { const pos = this.body.translation(); this.newPos.set(pos.x, pos.y, pos.z); this.object3d.parent?.worldToLocal(this.newPos); this.object3d.position.copy(this.newPos); } private copyBodyRotation() { const rot = this.body.rotation(); this.newRot.set(rot.x, rot.y, rot.z, rot.w); this.matrixA.makeRotationFromQuaternion(this.newRot); this.object3d.updateMatrixWorld(); this.matrixB.copy((this.object3d.parent as THREE.Object3D).matrixWorld).invert(); this.matrixC.extractRotation(this.matrixB); this.matrixA.premultiply(this.matrixC); this.object3d.quaternion.setFromRotationMatrix(this.matrixA); } } RE.registerComponent(RapierBody);