OimoPhysics.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. ( function () {
  2. import { World, Vec3, OBoxGeometry, OSphereGeometry, ShapeConfig, RigidBodyConfig, RigidBodyType, RigidBody, Shape } from '../libs/OimoPhysics/index.js';
  3. async function OimoPhysics() {
  4. const frameRate = 60;
  5. const world = new World(2, new Vec3(0, -9.8, 0)); //
  6. function getShape(geometry) {
  7. const parameters = geometry.parameters; // TODO change type to is*
  8. if (geometry.type === 'BoxGeometry') {
  9. const sx = parameters.width !== undefined ? parameters.width / 2 : 0.5;
  10. const sy = parameters.height !== undefined ? parameters.height / 2 : 0.5;
  11. const sz = parameters.depth !== undefined ? parameters.depth / 2 : 0.5;
  12. return new OBoxGeometry(new Vec3(sx, sy, sz));
  13. } else if (geometry.type === 'SphereGeometry' || geometry.type === 'IcosahedronGeometry') {
  14. const radius = parameters.radius !== undefined ? parameters.radius : 1;
  15. return new OSphereGeometry(radius);
  16. }
  17. return null;
  18. }
  19. const meshes = [];
  20. const meshMap = new WeakMap();
  21. function addMesh(mesh, mass = 0) {
  22. const shape = getShape(mesh.geometry);
  23. if (shape !== null) {
  24. if (mesh.isInstancedMesh) {
  25. handleInstancedMesh(mesh, mass, shape);
  26. } else if (mesh.isMesh) {
  27. handleMesh(mesh, mass, shape);
  28. }
  29. }
  30. }
  31. function handleMesh(mesh, mass, shape) {
  32. const shapeConfig = new ShapeConfig();
  33. shapeConfig.geometry = shape;
  34. const bodyConfig = new RigidBodyConfig();
  35. bodyConfig.type = mass === 0 ? RigidBodyType.STATIC : RigidBodyType.DYNAMIC;
  36. bodyConfig.position = new Vec3(mesh.position.x, mesh.position.y, mesh.position.z);
  37. const body = new RigidBody(bodyConfig);
  38. body.addShape(new Shape(shapeConfig));
  39. world.addRigidBody(body);
  40. if (mass > 0) {
  41. meshes.push(mesh);
  42. meshMap.set(mesh, body);
  43. }
  44. }
  45. function handleInstancedMesh(mesh, mass, shape) {
  46. const array = mesh.instanceMatrix.array;
  47. const bodies = [];
  48. for (let i = 0; i < mesh.count; i++) {
  49. const index = i * 16;
  50. const shapeConfig = new ShapeConfig();
  51. shapeConfig.geometry = shape;
  52. const bodyConfig = new RigidBodyConfig();
  53. bodyConfig.type = mass === 0 ? RigidBodyType.STATIC : RigidBodyType.DYNAMIC;
  54. bodyConfig.position = new Vec3(array[index + 12], array[index + 13], array[index + 14]);
  55. const body = new RigidBody(bodyConfig);
  56. body.addShape(new Shape(shapeConfig));
  57. world.addRigidBody(body);
  58. bodies.push(body);
  59. }
  60. if (mass > 0) {
  61. meshes.push(mesh);
  62. meshMap.set(mesh, bodies);
  63. }
  64. } //
  65. function setMeshPosition(mesh, position, index = 0) {
  66. if (mesh.isInstancedMesh) {
  67. const bodies = meshMap.get(mesh);
  68. const body = bodies[index];
  69. body.setPosition(new Vec3(position.x, position.y, position.z));
  70. } else if (mesh.isMesh) {
  71. const body = meshMap.get(mesh);
  72. body.setPosition(new Vec3(position.x, position.y, position.z));
  73. }
  74. } //
  75. let lastTime = 0;
  76. function step() {
  77. const time = performance.now();
  78. if (lastTime > 0) {
  79. // console.time( 'world.step' );
  80. world.step(1 / frameRate); // console.timeEnd( 'world.step' );
  81. }
  82. lastTime = time; //
  83. for (let i = 0, l = meshes.length; i < l; i++) {
  84. const mesh = meshes[i];
  85. if (mesh.isInstancedMesh) {
  86. const array = mesh.instanceMatrix.array;
  87. const bodies = meshMap.get(mesh);
  88. for (let j = 0; j < bodies.length; j++) {
  89. const body = bodies[j];
  90. compose(body.getPosition(), body.getOrientation(), array, j * 16);
  91. }
  92. mesh.instanceMatrix.needsUpdate = true;
  93. } else if (mesh.isMesh) {
  94. const body = meshMap.get(mesh);
  95. mesh.position.copy(body.getPosition());
  96. mesh.quaternion.copy(body.getOrientation());
  97. }
  98. }
  99. } // animate
  100. setInterval(step, 1000 / frameRate);
  101. return {
  102. addMesh: addMesh,
  103. setMeshPosition: setMeshPosition // addCompoundMesh
  104. };
  105. }
  106. function compose(position, quaternion, array, index) {
  107. const x = quaternion.x,
  108. y = quaternion.y,
  109. z = quaternion.z,
  110. w = quaternion.w;
  111. const x2 = x + x,
  112. y2 = y + y,
  113. z2 = z + z;
  114. const xx = x * x2,
  115. xy = x * y2,
  116. xz = x * z2;
  117. const yy = y * y2,
  118. yz = y * z2,
  119. zz = z * z2;
  120. const wx = w * x2,
  121. wy = w * y2,
  122. wz = w * z2;
  123. array[index + 0] = 1 - (yy + zz);
  124. array[index + 1] = xy + wz;
  125. array[index + 2] = xz - wy;
  126. array[index + 3] = 0;
  127. array[index + 4] = xy - wz;
  128. array[index + 5] = 1 - (xx + zz);
  129. array[index + 6] = yz + wx;
  130. array[index + 7] = 0;
  131. array[index + 8] = xz + wy;
  132. array[index + 9] = yz - wx;
  133. array[index + 10] = 1 - (xx + yy);
  134. array[index + 11] = 0;
  135. array[index + 12] = position.x;
  136. array[index + 13] = position.y;
  137. array[index + 14] = position.z;
  138. array[index + 15] = 1;
  139. }
  140. THREE.OimoPhysics = OimoPhysics;
  141. } )();