RapierBody.re.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import RAPIER from '@dimforge/rapier3d-compat';
  2. import * as RE from 'rogue-engine';
  3. import * as THREE from 'three';
  4. import RogueRapier from '../Lib/RogueRapier';
  5. export type RapierCollisionInfo = {ownCollider: RAPIER.Collider, otherCollider: RAPIER.Collider, otherBody: RapierBody};
  6. export default class RapierBody extends RE.Component {
  7. @RE.props.select() type = 0;
  8. typeOptions = ["Dynamic", "Fixed", "KinematicPositionBased", "KinematicVelocityBased"];
  9. @RE.props.num() mass = 1;
  10. private _gravityScale = 1;
  11. @RE.props.num()
  12. get gravityScale() {
  13. return this._gravityScale;
  14. }
  15. set gravityScale(value: number) {
  16. this._gravityScale = value;
  17. RE.Runtime.isRunning &&
  18. this.body && (this.body.setGravityScale(value, true));
  19. }
  20. private _angularDamping = 0;
  21. @RE.props.num()
  22. get angularDamping() {
  23. return this._angularDamping;
  24. }
  25. set angularDamping(value: number) {
  26. this._angularDamping = value;
  27. RE.Runtime.isRunning &&
  28. this.body && (this.body.setAngularDamping(value));
  29. }
  30. private _linearDamping = 0;
  31. @RE.props.num()
  32. get linearDamping() {
  33. this.body
  34. return this._linearDamping;
  35. }
  36. set linearDamping(value: number) {
  37. this._linearDamping = value;
  38. RE.Runtime.isRunning &&
  39. this.body && (this.body.setLinearDamping(value));
  40. }
  41. private _xTranslation = true;
  42. @RE.props.checkbox()
  43. get xTranslation() {
  44. return this._xTranslation;
  45. }
  46. set xTranslation(value: boolean) {
  47. this._xTranslation = value;
  48. RE.Runtime.isRunning &&
  49. this.body && (this.body.setEnabledTranslations(value, this._yTranslation, this._zTranslation, true));
  50. }
  51. private _yTranslation = true;
  52. @RE.props.checkbox()
  53. get yTranslation() {
  54. return this._yTranslation;
  55. }
  56. set yTranslation(value: boolean) {
  57. this._yTranslation = value;
  58. RE.Runtime.isRunning &&
  59. this.body && (this.body.setEnabledTranslations(this._xTranslation, value, this._zTranslation, true));
  60. }
  61. private _zTranslation = true;
  62. @RE.props.checkbox()
  63. get zTranslation() {
  64. return this._zTranslation;
  65. }
  66. set zTranslation(value: boolean) {
  67. this._zTranslation = value;
  68. RE.Runtime.isRunning &&
  69. this.body && (this.body.setEnabledTranslations(this._xTranslation, this._yTranslation, value, true));
  70. }
  71. private _xRotation = true;
  72. @RE.props.checkbox()
  73. get xRotation() {
  74. return this._xRotation;
  75. }
  76. set xRotation(value: boolean) {
  77. this._xRotation = value;
  78. RE.Runtime.isRunning &&
  79. this.body && (this.body.setEnabledRotations(value, this._yRotation, this._zRotation, true));
  80. }
  81. private _yRotation = true;
  82. @RE.props.checkbox()
  83. get yRotation() {
  84. return this._yRotation;
  85. }
  86. set yRotation(value: boolean) {
  87. this._yRotation = value;
  88. RE.Runtime.isRunning &&
  89. this.body && (this.body.setEnabledRotations(this._xRotation, value, this._zRotation, true));
  90. }
  91. private _zRotation = true;
  92. @RE.props.checkbox()
  93. get zRotation() {
  94. return this._zRotation;
  95. }
  96. set zRotation(value: boolean) {
  97. this._zRotation = value;
  98. RE.Runtime.isRunning &&
  99. this.body && (this.body.setEnabledRotations(this._xRotation, this._yRotation, value, true));
  100. }
  101. body: RAPIER.RigidBody;
  102. initialized = false;
  103. onCollisionStart: (info: RapierCollisionInfo) => void = () => {};
  104. onCollisionEnd: (info: RapierCollisionInfo) => void = () => {};
  105. private newPos = new THREE.Vector3();
  106. private newRot = new THREE.Quaternion();
  107. private matrixA = new THREE.Matrix4();
  108. private matrixB = new THREE.Matrix4();
  109. private matrixC = new THREE.Matrix4();
  110. init() {
  111. let rigidBodyDesc = this.getType();
  112. // const pos = this.object3d.position;
  113. // const rot = this.object3d.quaternion;
  114. this.object3d.getWorldPosition(this.newPos);
  115. this.object3d.getWorldQuaternion(this.newRot);
  116. rigidBodyDesc
  117. .setGravityScale(this._gravityScale)
  118. .setTranslation(this.newPos.x, this.newPos.y, this.newPos.z)
  119. .setRotation(this.newRot)
  120. .setAngularDamping(this._angularDamping)
  121. .setLinearDamping(this._linearDamping)
  122. .enabledRotations(this._xRotation, this._yRotation, this._zRotation)
  123. .enabledTranslations(this._xTranslation, this._yTranslation, this._zTranslation);
  124. rigidBodyDesc.mass = this.mass;
  125. this.body = RogueRapier.world.createRigidBody(rigidBodyDesc);
  126. this.body.userData = {object3d: this.object3d.uuid};
  127. this.initialized = true;
  128. }
  129. private getType() {
  130. if (Number(this.type) === 1) return RAPIER.RigidBodyDesc.fixed();
  131. else if (Number(this.type) === 2) return RAPIER.RigidBodyDesc.kinematicPositionBased();
  132. else if (Number(this.type) === 3) return RAPIER.RigidBodyDesc.kinematicVelocityBased();
  133. else return RAPIER.RigidBodyDesc.dynamic();
  134. }
  135. onBeforeRemoved(): void {
  136. if (this.body) {
  137. RogueRapier.world.removeRigidBody(this.body);
  138. }
  139. }
  140. onDisabled(): void {
  141. if (this.body) {
  142. RogueRapier.world.removeRigidBody(this.body);
  143. }
  144. }
  145. beforeUpdate(): void {
  146. if (!RogueRapier.initialized) return;
  147. !this.initialized && this.init();
  148. this.type !== RAPIER.RigidBodyType.Fixed &&
  149. this.updatePhysics();
  150. }
  151. updatePhysics() {
  152. this.copyBodyPosition();
  153. this.copyBodyRotation();
  154. }
  155. private copyBodyPosition() {
  156. const pos = this.body.translation();
  157. this.newPos.set(pos.x, pos.y, pos.z);
  158. this.object3d.parent?.worldToLocal(this.newPos);
  159. this.object3d.position.copy(this.newPos);
  160. }
  161. private copyBodyRotation() {
  162. const rot = this.body.rotation();
  163. this.newRot.set(rot.x, rot.y, rot.z, rot.w);
  164. this.matrixA.makeRotationFromQuaternion(this.newRot);
  165. this.object3d.updateMatrixWorld();
  166. this.matrixB.copy((this.object3d.parent as THREE.Object3D).matrixWorld).invert();
  167. this.matrixC.extractRotation(this.matrixB);
  168. this.matrixA.premultiply(this.matrixC);
  169. this.object3d.quaternion.setFromRotationMatrix(this.matrixA);
  170. }
  171. }
  172. RE.registerComponent(RapierBody);