123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- import * as RE from 'rogue-engine';
- import * as CANNON from 'cannon-es';
- import * as THREE from 'three';
- import CannonBody from '../CannonBody.re';
- export default class CannonShape extends RE.Component {
- shape: CANNON.Shape;
- body: CANNON.Body | undefined;
- bodyComponent: CannonBody | undefined;
- localPos: THREE.Vector3 = new THREE.Vector3();
- worldPos = new THREE.Vector3();
- oldPos = new THREE.Vector3();
- localRot = new THREE.Quaternion();
- worldQuaternion = new THREE.Quaternion();
- private matrixA = new THREE.Matrix4();
- private matrixB = new THREE.Matrix4();
- private matrixC = new THREE.Matrix4();
- static findByShape(shape: CANNON.Shape) {
- let shapeComponent: undefined | CannonShape;
- RE.traverseComponents(component => {
- if (shapeComponent) return;
- if (component instanceof CannonShape && component.shape === shape) {
- shapeComponent = component;
- }
- });
- return shapeComponent;
- }
- awake() {
- this.createShape();
- }
- start() {
- if (!this.shape) return;
- this.bodyComponent = this.getBodyComponent(this.object3d);
- if (!this.bodyComponent) return;
- if (!this.bodyComponent.body) return;
- this.body = this.bodyComponent.body;
- const bodyIsShape = this.object3d === this.bodyComponent.object3d;
- this.object3d.getWorldPosition(this.worldPos);
- this.localPos.copy(this.worldPos);
- this.bodyComponent.object3d.updateWorldMatrix(true, true);
- this.bodyComponent.object3d.worldToLocal(this.localPos);
- let position = new CANNON.Vec3(
- this.localPos.x,
- this.localPos.y,
- this.localPos.z,
- );
- this.object3d.updateWorldMatrix(true, true);
- this.object3d.getWorldQuaternion(this.worldQuaternion);
- this.matrixA.makeRotationFromQuaternion(this.worldQuaternion);
- this.object3d.updateWorldMatrix(true, true);
- this.matrixB.copy(this.bodyComponent.object3d.matrixWorld).invert();
- this.matrixC.extractRotation(this.matrixB);
- this.matrixA.premultiply(this.matrixC);
- this.localRot.setFromRotationMatrix(this.matrixA);
- let rotation = new CANNON.Quaternion(
- this.localRot.x,
- this.localRot.y,
- this.localRot.z,
- this.localRot.w,
- );
- if (bodyIsShape) {
- this.body.addShape(this.shape);
- } else {
- this.body.addShape(this.shape, position, rotation);
- }
- }
- update() {
- if (!this.shape) return;
- if (!this.shape.body) return;
- if (this.shape.body.type === CANNON.BODY_TYPES.STATIC || this.shape.body.mass === 0) return
- const shapeIndex = this.shape.body?.shapes.indexOf(this.shape);
-
- if (shapeIndex === undefined) return;
- this.oldPos.copy(this.worldPos);
- this.object3d.getWorldPosition(this.worldPos);
- if (this.oldPos.equals(this.worldPos)) return;
- this.localPos.copy(this.worldPos);
- this.bodyComponent?.object3d.updateWorldMatrix(true, true);
- this.bodyComponent?.object3d.worldToLocal(this.localPos);
- this.shape.body?.shapeOffsets[shapeIndex].set(
- this.localPos.x,
- this.localPos.y,
- this.localPos.z
- );
- this.shape.updateBoundingSphereRadius();
- this.shape.body?.updateAABB();
- }
- onDisabled() {
- this.body?.removeShape(this.shape);
- }
- onBeforeObjectRemoved() {
- this.body?.removeShape(this.shape);
- }
- private getBodyComponent(object3d: THREE.Object3D): CannonBody | undefined {
- const bodyComponent = RE.getComponent(CannonBody, object3d);
- if (bodyComponent) {
- return bodyComponent;
- }
- if (!object3d.parent) return;
- return this.getBodyComponent(object3d.parent as THREE.Object3D);
- }
- protected createShape(): void {};
- }
|