CannonShape.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import * as RE from 'rogue-engine';
  2. import * as CANNON from 'cannon-es';
  3. import * as THREE from 'three';
  4. import CannonBody from '../CannonBody.re';
  5. export default class CannonShape extends RE.Component {
  6. shape: CANNON.Shape;
  7. body: CANNON.Body | undefined;
  8. bodyComponent: CannonBody | undefined;
  9. localPos: THREE.Vector3 = new THREE.Vector3();
  10. worldPos = new THREE.Vector3();
  11. oldPos = new THREE.Vector3();
  12. localRot = new THREE.Quaternion();
  13. worldQuaternion = new THREE.Quaternion();
  14. private matrixA = new THREE.Matrix4();
  15. private matrixB = new THREE.Matrix4();
  16. private matrixC = new THREE.Matrix4();
  17. static findByShape(shape: CANNON.Shape) {
  18. let shapeComponent: undefined | CannonShape;
  19. RE.traverseComponents(component => {
  20. if (shapeComponent) return;
  21. if (component instanceof CannonShape && component.shape === shape) {
  22. shapeComponent = component;
  23. }
  24. });
  25. return shapeComponent;
  26. }
  27. awake() {
  28. this.createShape();
  29. }
  30. start() {
  31. if (!this.shape) return;
  32. this.bodyComponent = this.getBodyComponent(this.object3d);
  33. if (!this.bodyComponent) return;
  34. if (!this.bodyComponent.body) return;
  35. this.body = this.bodyComponent.body;
  36. const bodyIsShape = this.object3d === this.bodyComponent.object3d;
  37. this.object3d.getWorldPosition(this.worldPos);
  38. this.localPos.copy(this.worldPos);
  39. this.bodyComponent.object3d.updateWorldMatrix(true, true);
  40. this.bodyComponent.object3d.worldToLocal(this.localPos);
  41. let position = new CANNON.Vec3(
  42. this.localPos.x,
  43. this.localPos.y,
  44. this.localPos.z,
  45. );
  46. this.object3d.updateWorldMatrix(true, true);
  47. this.object3d.getWorldQuaternion(this.worldQuaternion);
  48. this.matrixA.makeRotationFromQuaternion(this.worldQuaternion);
  49. this.object3d.updateWorldMatrix(true, true);
  50. this.matrixB.copy(this.bodyComponent.object3d.matrixWorld).invert();
  51. this.matrixC.extractRotation(this.matrixB);
  52. this.matrixA.premultiply(this.matrixC);
  53. this.localRot.setFromRotationMatrix(this.matrixA);
  54. let rotation = new CANNON.Quaternion(
  55. this.localRot.x,
  56. this.localRot.y,
  57. this.localRot.z,
  58. this.localRot.w,
  59. );
  60. if (bodyIsShape) {
  61. this.body.addShape(this.shape);
  62. } else {
  63. this.body.addShape(this.shape, position, rotation);
  64. }
  65. }
  66. update() {
  67. if (!this.shape) return;
  68. if (!this.shape.body) return;
  69. if (this.shape.body.type === CANNON.BODY_TYPES.STATIC || this.shape.body.mass === 0) return
  70. const shapeIndex = this.shape.body?.shapes.indexOf(this.shape);
  71. if (shapeIndex === undefined) return;
  72. this.oldPos.copy(this.worldPos);
  73. this.object3d.getWorldPosition(this.worldPos);
  74. if (this.oldPos.equals(this.worldPos)) return;
  75. this.localPos.copy(this.worldPos);
  76. this.bodyComponent?.object3d.updateWorldMatrix(true, true);
  77. this.bodyComponent?.object3d.worldToLocal(this.localPos);
  78. this.shape.body?.shapeOffsets[shapeIndex].set(
  79. this.localPos.x,
  80. this.localPos.y,
  81. this.localPos.z
  82. );
  83. this.shape.updateBoundingSphereRadius();
  84. this.shape.body?.updateAABB();
  85. }
  86. onDisabled() {
  87. this.body?.removeShape(this.shape);
  88. }
  89. onBeforeObjectRemoved() {
  90. this.body?.removeShape(this.shape);
  91. }
  92. private getBodyComponent(object3d: THREE.Object3D): CannonBody | undefined {
  93. const bodyComponent = RE.getComponent(CannonBody, object3d);
  94. if (bodyComponent) {
  95. return bodyComponent;
  96. }
  97. if (!object3d.parent) return;
  98. return this.getBodyComponent(object3d.parent as THREE.Object3D);
  99. }
  100. protected createShape(): void {};
  101. }