laya.cannonPhysics.js 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  1. (function (exports, Laya) {
  2. 'use strict';
  3. class CannonCollision {
  4. constructor() {
  5. this._lastUpdateFrame = -2147483648;
  6. this._updateFrame = -2147483648;
  7. this._isTrigger = false;
  8. this.contacts = [];
  9. }
  10. _setUpdateFrame(farme) {
  11. this._lastUpdateFrame = this._updateFrame;
  12. this._updateFrame = farme;
  13. }
  14. }
  15. class CannonContactPoint {
  16. constructor() {
  17. this._idCounter = 0;
  18. this.colliderA = null;
  19. this.colliderB = null;
  20. this.distance = 0;
  21. this.normal = new Laya.Vector3();
  22. this.positionOnA = new Laya.Vector3();
  23. this.positionOnB = new Laya.Vector3();
  24. this._id = ++this._idCounter;
  25. }
  26. }
  27. class CannonHitResult {
  28. constructor() {
  29. this.succeeded = false;
  30. this.collider = null;
  31. this.point = new Laya.Vector3();
  32. this.normal = new Laya.Vector3();
  33. this.hitFraction = 0;
  34. }
  35. }
  36. class CannonCollisionTool {
  37. constructor() {
  38. this._hitResultsPoolIndex = 0;
  39. this._hitResultsPool = [];
  40. this._contactPonintsPoolIndex = 0;
  41. this._contactPointsPool = [];
  42. this._collisionsPool = [];
  43. this._collisions = {};
  44. }
  45. getHitResult() {
  46. var hitResult = this._hitResultsPool[this._hitResultsPoolIndex++];
  47. if (!hitResult) {
  48. hitResult = new CannonHitResult();
  49. this._hitResultsPool.push(hitResult);
  50. }
  51. return hitResult;
  52. }
  53. recoverAllHitResultsPool() {
  54. this._hitResultsPoolIndex = 0;
  55. }
  56. getContactPoints() {
  57. var contactPoint = this._contactPointsPool[this._contactPonintsPoolIndex++];
  58. if (!contactPoint) {
  59. contactPoint = new CannonContactPoint();
  60. this._contactPointsPool.push(contactPoint);
  61. }
  62. return contactPoint;
  63. }
  64. recoverAllContactPointsPool() {
  65. this._contactPonintsPoolIndex = 0;
  66. }
  67. getCollision(physicComponentA, physicComponentB) {
  68. var collision;
  69. var idA = physicComponentA.id;
  70. var idB = physicComponentB.id;
  71. var subCollisionFirst = this._collisions[idA];
  72. if (subCollisionFirst)
  73. collision = subCollisionFirst[idB];
  74. if (!collision) {
  75. if (!subCollisionFirst) {
  76. subCollisionFirst = {};
  77. this._collisions[idA] = subCollisionFirst;
  78. }
  79. collision = this._collisionsPool.length === 0 ? new CannonCollision() : this._collisionsPool.pop();
  80. collision._colliderA = physicComponentA;
  81. collision._colliderB = physicComponentB;
  82. subCollisionFirst[idB] = collision;
  83. }
  84. return collision;
  85. }
  86. recoverCollision(collision) {
  87. var idA = collision._colliderA.id;
  88. var idB = collision._colliderB.id;
  89. this._collisions[idA][idB] = null;
  90. this._collisionsPool.push(collision);
  91. }
  92. garbageCollection() {
  93. this._hitResultsPoolIndex = 0;
  94. this._hitResultsPool.length = 0;
  95. this._contactPonintsPoolIndex = 0;
  96. this._contactPointsPool.length = 0;
  97. this._collisionsPool.length = 0;
  98. for (var subCollisionsKey in this._collisionsPool) {
  99. var subCollisions = this._collisionsPool[subCollisionsKey];
  100. var wholeDelete = true;
  101. for (var collisionKey in subCollisions) {
  102. if (subCollisions[collisionKey])
  103. wholeDelete = false;
  104. else
  105. delete subCollisions[collisionKey];
  106. }
  107. if (wholeDelete)
  108. delete this._collisionsPool[subCollisionsKey];
  109. }
  110. }
  111. }
  112. class CannonColliderShape {
  113. constructor() {
  114. this._scale = new Laya.Vector3(1, 1, 1);
  115. this._centerMatrix = new Laya.Matrix4x4();
  116. this._attatched = false;
  117. this._indexInCompound = -1;
  118. this._compoundParent = null;
  119. this._attatchedCollisionObject = null;
  120. this._referenceCount = 0;
  121. this._localOffset = new Laya.Vector3(0, 0, 0);
  122. this._localRotation = new Laya.Quaternion(0, 0, 0, 1);
  123. this.needsCustomCollisionCallback = false;
  124. }
  125. static __init__() {
  126. CannonColliderShape._btScale = new CANNON.Vec3();
  127. CannonColliderShape._btVector30 = new CANNON.Vec3();
  128. CannonColliderShape._btQuaternion0 = new CANNON.Quaternion();
  129. }
  130. static _createAffineTransformation(trans, rot, outE) {
  131. var x = rot.x, y = rot.y, z = rot.z, w = rot.w, x2 = x + x, y2 = y + y, z2 = z + z;
  132. var xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2;
  133. var wx = w * x2, wy = w * y2, wz = w * z2;
  134. outE[0] = (1 - (yy + zz));
  135. outE[1] = (xy + wz);
  136. outE[2] = (xz - wy);
  137. outE[3] = 0;
  138. outE[4] = (xy - wz);
  139. outE[5] = (1 - (xx + zz));
  140. outE[6] = (yz + wx);
  141. outE[7] = 0;
  142. outE[8] = (xz + wy);
  143. outE[9] = (yz - wx);
  144. outE[10] = (1 - (xx + yy));
  145. outE[11] = 0;
  146. outE[12] = trans.x;
  147. outE[13] = trans.y;
  148. outE[14] = trans.z;
  149. outE[15] = 1;
  150. }
  151. get type() {
  152. return this._type;
  153. }
  154. get localOffset() {
  155. return this._localOffset;
  156. }
  157. set localOffset(value) {
  158. value.cloneTo(this._localOffset);
  159. }
  160. get localRotation() {
  161. return this._localRotation;
  162. }
  163. set localRotation(value) {
  164. this._localRotation = value;
  165. if (this._compoundParent)
  166. this._compoundParent._updateChildTransform(this);
  167. }
  168. _setScale(value) {
  169. }
  170. _addReference() {
  171. this._referenceCount++;
  172. }
  173. _removeReference() {
  174. this._referenceCount--;
  175. }
  176. updateLocalTransformations() {
  177. if (this._compoundParent) {
  178. var offset = CannonColliderShape._tempVector30;
  179. Laya.Vector3.multiply(this.localOffset, this._scale, offset);
  180. CannonColliderShape._createAffineTransformation(offset, this.localRotation, this._centerMatrix.elements);
  181. }
  182. else {
  183. CannonColliderShape._createAffineTransformation(this.localOffset, this.localRotation, this._centerMatrix.elements);
  184. }
  185. }
  186. cloneTo(destObject) {
  187. var destColliderShape = destObject;
  188. this._localOffset.cloneTo(destColliderShape.localOffset);
  189. this._localRotation.cloneTo(destColliderShape.localRotation);
  190. destColliderShape.localOffset = destColliderShape.localOffset;
  191. destColliderShape.localRotation = destColliderShape.localRotation;
  192. }
  193. clone() {
  194. return null;
  195. }
  196. destroy() {
  197. if (this._btShape) {
  198. this._btShape = null;
  199. }
  200. }
  201. }
  202. CannonColliderShape.SHAPEORIENTATION_UPX = 0;
  203. CannonColliderShape.SHAPEORIENTATION_UPY = 1;
  204. CannonColliderShape.SHAPEORIENTATION_UPZ = 2;
  205. CannonColliderShape.SHAPETYPES_BOX = 0;
  206. CannonColliderShape.SHAPETYPES_SPHERE = 1;
  207. CannonColliderShape.SHAPETYPES_CYLINDER = 2;
  208. CannonColliderShape.SHAPETYPES_CAPSULE = 3;
  209. CannonColliderShape.SHAPETYPES_CONVEXHULL = 4;
  210. CannonColliderShape.SHAPETYPES_COMPOUND = 5;
  211. CannonColliderShape.SHAPETYPES_STATICPLANE = 6;
  212. CannonColliderShape.SHAPETYPES_CONE = 7;
  213. CannonColliderShape._tempVector30 = new Laya.Vector3();
  214. class CannonBoxColliderShape extends CannonColliderShape {
  215. constructor(sizeX = 1.0, sizeY = 1.0, sizeZ = 1.0) {
  216. super();
  217. this._sizeX = sizeX;
  218. this._sizeY = sizeY;
  219. this._sizeZ = sizeZ;
  220. this._type = CannonColliderShape.SHAPETYPES_BOX;
  221. var btsize = new CANNON.Vec3(sizeX / 2, sizeY / 2, sizeZ / 2);
  222. this._btShape = new CANNON.Box(btsize);
  223. }
  224. static __init__() {
  225. CannonBoxColliderShape._btSize = new CANNON.Vec3();
  226. }
  227. get sizeX() {
  228. return this._sizeX;
  229. }
  230. get sizeY() {
  231. return this._sizeY;
  232. }
  233. get sizeZ() {
  234. return this._sizeZ;
  235. }
  236. _setScale(scale) {
  237. this._scale.setValue(scale.x, scale.y, scale.z);
  238. this._btShape.halfExtents.set(this.sizeX / 2 * scale.x, this.sizeY / 2 * scale.y, this.sizeZ / 2 * scale.z);
  239. this._btShape.updateConvexPolyhedronRepresentation();
  240. this._btShape.updateBoundingSphereRadius();
  241. }
  242. clone() {
  243. var dest = new CannonBoxColliderShape(this._sizeX, this._sizeY, this._sizeZ);
  244. this.cloneTo(dest);
  245. return dest;
  246. }
  247. }
  248. class CannonSphereColliderShape extends CannonColliderShape {
  249. constructor(radius = 0.5) {
  250. super();
  251. this._radius = radius;
  252. this._type = CannonColliderShape.SHAPETYPES_SPHERE;
  253. this._btShape = new CANNON.Sphere(radius);
  254. }
  255. get radius() {
  256. return this._radius;
  257. }
  258. _setScale(scale) {
  259. var max = Math.max(scale.x, scale.y, scale.z);
  260. this._scale.setValue(max, max, max);
  261. this._btShape.radius = max * this.radius;
  262. this._btShape.updateBoundingSphereRadius();
  263. }
  264. clone() {
  265. var dest = new CannonSphereColliderShape(this._radius);
  266. this.cloneTo(dest);
  267. return dest;
  268. }
  269. }
  270. class CannonPhysicsComponent extends Laya.Component {
  271. constructor(collisionGroup, canCollideWith) {
  272. super();
  273. this._restitution = 0.0;
  274. this._friction = 0.5;
  275. this._collisionGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_DEFAULTFILTER;
  276. this._canCollideWith = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER;
  277. this._colliderShape = null;
  278. this._transformFlag = 2147483647;
  279. this._controlBySimulation = false;
  280. this._enableProcessCollisions = true;
  281. this._inPhysicUpdateListIndex = -1;
  282. this.canScaleShape = true;
  283. this._collisionGroup = collisionGroup;
  284. this._canCollideWith = canCollideWith;
  285. CannonPhysicsComponent._physicObjectsMap[this.id] = this;
  286. }
  287. static __init__() {
  288. CannonPhysicsComponent._btVector30 = new CANNON.Vec3(0, 0, 0);
  289. CannonPhysicsComponent._btQuaternion0 = new CANNON.Quaternion(0, 0, 0, 1);
  290. }
  291. static _creatShape(shapeData) {
  292. var colliderShape;
  293. switch (shapeData.type) {
  294. case "BoxColliderShape":
  295. var sizeData = shapeData.size;
  296. colliderShape = sizeData ? new CannonBoxColliderShape(sizeData[0], sizeData[1], sizeData[2]) : new CannonBoxColliderShape();
  297. break;
  298. case "SphereColliderShape":
  299. colliderShape = new CannonSphereColliderShape(shapeData.radius);
  300. break;
  301. default:
  302. throw "unknown shape type.";
  303. }
  304. if (shapeData.center) {
  305. var localOffset = colliderShape.localOffset;
  306. localOffset.fromArray(shapeData.center);
  307. colliderShape.localOffset = localOffset;
  308. }
  309. return colliderShape;
  310. }
  311. static physicQuaternionMultiply(lx, ly, lz, lw, right, out) {
  312. var rx = right.x;
  313. var ry = right.y;
  314. var rz = right.z;
  315. var rw = right.w;
  316. var a = (ly * rz - lz * ry);
  317. var b = (lz * rx - lx * rz);
  318. var c = (lx * ry - ly * rx);
  319. var d = (lx * rx + ly * ry + lz * rz);
  320. out.x = (lx * rw + rx * lw) + a;
  321. out.y = (ly * rw + ry * lw) + b;
  322. out.z = (lz * rw + rz * lw) + c;
  323. out.w = lw * rw - d;
  324. }
  325. get restitution() {
  326. return this._restitution;
  327. }
  328. set restitution(value) {
  329. this._restitution = value;
  330. this._btColliderObject && (this._btColliderObject.material.restitution = value);
  331. }
  332. get friction() {
  333. return this._friction;
  334. }
  335. set friction(value) {
  336. this._friction = value;
  337. this._btColliderObject && (this._btColliderObject.material.friction = value);
  338. }
  339. get colliderShape() {
  340. return this._colliderShape;
  341. }
  342. set colliderShape(value) {
  343. var lastColliderShape = this._colliderShape;
  344. if (lastColliderShape) {
  345. lastColliderShape._attatched = false;
  346. lastColliderShape._attatchedCollisionObject = null;
  347. }
  348. this._colliderShape = value;
  349. if (value) {
  350. if (value._attatched) {
  351. throw "PhysicsComponent: this shape has attatched to other entity.";
  352. }
  353. else {
  354. value._attatched = true;
  355. value._attatchedCollisionObject = this;
  356. }
  357. if (this._btColliderObject) {
  358. if (value.type != CannonColliderShape.SHAPETYPES_COMPOUND) {
  359. this._btColliderObject.shapes.length = 0;
  360. this._btColliderObject.shapeOffsets.length = 0;
  361. this._btColliderObject.shapeOrientations.length = 0;
  362. var localOffset = value.localOffset;
  363. var scale = value._scale;
  364. var vecs = new CANNON.Vec3(localOffset.x * scale.x, localOffset.y * scale.y, localOffset.z * scale.z);
  365. this._btColliderObject.addShape(this._colliderShape._btShape, vecs);
  366. this._btColliderObject.updateBoundingRadius();
  367. }
  368. else {
  369. value.bindRigidBody(this);
  370. }
  371. var canInSimulation = this._simulation && this._enabled;
  372. (canInSimulation && lastColliderShape) && (this._removeFromSimulation());
  373. this._onShapeChange(value);
  374. if (canInSimulation) {
  375. this._derivePhysicsTransformation(true);
  376. this._addToSimulation();
  377. }
  378. }
  379. }
  380. else {
  381. if (this._simulation && this._enabled)
  382. lastColliderShape && this._removeFromSimulation();
  383. }
  384. }
  385. get simulation() {
  386. return this._simulation;
  387. }
  388. get collisionGroup() {
  389. return this._collisionGroup;
  390. }
  391. set collisionGroup(value) {
  392. if (this._collisionGroup !== value) {
  393. this._collisionGroup = value;
  394. this._btColliderObject.collisionFilterGroup = value;
  395. if (this._simulation && this._colliderShape && this._enabled) {
  396. this._removeFromSimulation();
  397. this._addToSimulation();
  398. }
  399. }
  400. }
  401. get canCollideWith() {
  402. return this._canCollideWith;
  403. }
  404. set canCollideWith(value) {
  405. if (this._canCollideWith !== value) {
  406. this._canCollideWith = value;
  407. this._btColliderObject.collisionFilterMask = value;
  408. if (this._simulation && this._colliderShape && this._enabled) {
  409. this._removeFromSimulation();
  410. this._addToSimulation();
  411. }
  412. }
  413. }
  414. _parseShape(shapesData) {
  415. var shapeCount = shapesData.length;
  416. if (shapeCount === 1) {
  417. var shape = CannonPhysicsComponent._creatShape(shapesData[0]);
  418. this.colliderShape = shape;
  419. }
  420. }
  421. _onScaleChange(scale) {
  422. this._colliderShape._setScale(scale);
  423. }
  424. _onEnable() {
  425. this._simulation = this.owner._scene._cannonPhysicsSimulation;
  426. if (this._colliderShape) {
  427. this._derivePhysicsTransformation(true);
  428. this._addToSimulation();
  429. }
  430. }
  431. _onDisable() {
  432. if (this._colliderShape) {
  433. this._removeFromSimulation();
  434. (this._inPhysicUpdateListIndex !== -1) && (this._simulation._physicsUpdateList.remove(this));
  435. }
  436. this._simulation = null;
  437. }
  438. _onDestroy() {
  439. delete CannonPhysicsComponent._physicObjectsMap[this.id];
  440. this._btColliderObject = null;
  441. this._colliderShape.destroy();
  442. super._onDestroy();
  443. this._btColliderObject = null;
  444. this._colliderShape = null;
  445. this._simulation = null;
  446. this.owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
  447. }
  448. _isValid() {
  449. return this._simulation && this._colliderShape && this._enabled;
  450. }
  451. _parse(data) {
  452. (data.collisionGroup != null) && (this.collisionGroup = data.collisionGroup);
  453. (data.canCollideWith != null) && (this.canCollideWith = data.canCollideWith);
  454. }
  455. _setTransformFlag(type, value) {
  456. if (value)
  457. this._transformFlag |= type;
  458. else
  459. this._transformFlag &= ~type;
  460. }
  461. _getTransformFlag(type) {
  462. return (this._transformFlag & type) != 0;
  463. }
  464. _addToSimulation() {
  465. }
  466. _removeFromSimulation() {
  467. }
  468. _derivePhysicsTransformation(force) {
  469. var btColliderObject = this._btColliderObject;
  470. this._innerDerivePhysicsTransformation(btColliderObject, force);
  471. }
  472. _innerDerivePhysicsTransformation(physicTransformOut, force) {
  473. var transform = this.owner._transform;
  474. if (force || this._getTransformFlag(Laya.Transform3D.TRANSFORM_WORLDPOSITION)) {
  475. var shapeOffset = this._colliderShape.localOffset;
  476. var position = transform.position;
  477. var btPosition = CannonPhysicsComponent._btVector30;
  478. if (shapeOffset.x !== 0 || shapeOffset.y !== 0 || shapeOffset.z !== 0) {
  479. var physicPosition = CannonPhysicsComponent._tempVector30;
  480. var worldMat = transform.worldMatrix;
  481. Laya.Vector3.transformCoordinate(shapeOffset, worldMat, physicPosition);
  482. btPosition.set(physicPosition.x, physicPosition.y, physicPosition.z);
  483. }
  484. else {
  485. btPosition.set(position.x, position.y, position.z);
  486. }
  487. physicTransformOut.position.set(btPosition.x, btPosition.y, btPosition.z);
  488. this._setTransformFlag(Laya.Transform3D.TRANSFORM_WORLDPOSITION, false);
  489. }
  490. if (force || this._getTransformFlag(Laya.Transform3D.TRANSFORM_WORLDQUATERNION)) {
  491. var shapeRotation = this._colliderShape.localRotation;
  492. var btRotation = CannonPhysicsComponent._btQuaternion0;
  493. var rotation = transform.rotation;
  494. if (shapeRotation.x !== 0 || shapeRotation.y !== 0 || shapeRotation.z !== 0 || shapeRotation.w !== 1) {
  495. var physicRotation = CannonPhysicsComponent._tempQuaternion0;
  496. CannonPhysicsComponent.physicQuaternionMultiply(rotation.x, rotation.y, rotation.z, rotation.w, shapeRotation, physicRotation);
  497. btRotation.set(physicRotation.x, physicRotation.y, physicRotation.z, physicRotation.w);
  498. }
  499. else {
  500. btRotation.set(rotation.x, rotation.y, rotation.z, rotation.w);
  501. }
  502. physicTransformOut.quaternion.set(btRotation.x, btRotation.y, btRotation.z, btRotation.w);
  503. this._setTransformFlag(Laya.Transform3D.TRANSFORM_WORLDQUATERNION, false);
  504. }
  505. if (force || this._getTransformFlag(Laya.Transform3D.TRANSFORM_WORLDSCALE)) {
  506. this._onScaleChange(transform.getWorldLossyScale());
  507. this._setTransformFlag(Laya.Transform3D.TRANSFORM_WORLDSCALE, false);
  508. }
  509. }
  510. _updateTransformComponent(physicsTransform) {
  511. var colliderShape = this._colliderShape;
  512. var localOffset = colliderShape.localOffset;
  513. var localRotation = colliderShape.localRotation;
  514. var transform = this.owner._transform;
  515. var position = transform.position;
  516. var rotation = transform.rotation;
  517. var btPosition = physicsTransform.position;
  518. var btRotation = physicsTransform.quaternion;
  519. var btRotX = btRotation.x;
  520. var btRotY = btRotation.y;
  521. var btRotZ = btRotation.z;
  522. var btRotW = btRotation.w;
  523. if (localRotation.x !== 0 || localRotation.y !== 0 || localRotation.z !== 0 || localRotation.w !== 1) {
  524. var invertShapeRotaion = CannonPhysicsComponent._tempQuaternion0;
  525. localRotation.invert(invertShapeRotaion);
  526. CannonPhysicsComponent.physicQuaternionMultiply(btRotX, btRotY, btRotZ, btRotW, invertShapeRotaion, rotation);
  527. }
  528. else {
  529. rotation.x = btRotX;
  530. rotation.y = btRotY;
  531. rotation.z = btRotZ;
  532. rotation.w = btRotW;
  533. }
  534. transform.rotation = rotation;
  535. if (localOffset.x !== 0 || localOffset.y !== 0 || localOffset.z !== 0) {
  536. var rotShapePosition = CannonPhysicsComponent._tempVector30;
  537. rotShapePosition.x = localOffset.x;
  538. rotShapePosition.y = localOffset.y;
  539. rotShapePosition.z = localOffset.z;
  540. Laya.Vector3.transformQuat(rotShapePosition, rotation, rotShapePosition);
  541. position.x = btPosition.x - rotShapePosition.x;
  542. position.y = btPosition.y - rotShapePosition.z;
  543. position.z = btPosition.z - rotShapePosition.y;
  544. }
  545. else {
  546. position.x = btPosition.x;
  547. position.y = btPosition.y;
  548. position.z = btPosition.z;
  549. }
  550. transform.position = position;
  551. }
  552. _onShapeChange(colShape) {
  553. }
  554. _onAdded() {
  555. this.enabled = this._enabled;
  556. this.restitution = this._restitution;
  557. this.friction = this._friction;
  558. this.owner.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
  559. }
  560. _onTransformChanged(flag) {
  561. if (CannonPhysicsComponent._addUpdateList || !this._controlBySimulation) {
  562. flag &= Laya.Transform3D.TRANSFORM_WORLDPOSITION | Laya.Transform3D.TRANSFORM_WORLDQUATERNION | Laya.Transform3D.TRANSFORM_WORLDSCALE;
  563. if (flag) {
  564. this._transformFlag |= flag;
  565. if (this._isValid() && this._inPhysicUpdateListIndex === -1)
  566. this._simulation._physicsUpdateList.add(this);
  567. }
  568. }
  569. }
  570. _cloneTo(dest) {
  571. var destPhysicsComponent = dest;
  572. destPhysicsComponent.restitution = this._restitution;
  573. destPhysicsComponent.friction = this._friction;
  574. destPhysicsComponent.collisionGroup = this._collisionGroup;
  575. destPhysicsComponent.canCollideWith = this._canCollideWith;
  576. destPhysicsComponent.canScaleShape = this.canScaleShape;
  577. (this._colliderShape) && (destPhysicsComponent.colliderShape = this._colliderShape.clone());
  578. }
  579. }
  580. CannonPhysicsComponent.ACTIVATIONSTATE_ACTIVE_TAG = 1;
  581. CannonPhysicsComponent.ACTIVATIONSTATE_ISLAND_SLEEPING = 2;
  582. CannonPhysicsComponent.ACTIVATIONSTATE_WANTS_DEACTIVATION = 3;
  583. CannonPhysicsComponent.ACTIVATIONSTATE_DISABLE_DEACTIVATION = 4;
  584. CannonPhysicsComponent.ACTIVATIONSTATE_DISABLE_SIMULATION = 5;
  585. CannonPhysicsComponent.COLLISIONFLAGS_STATIC_OBJECT = 1;
  586. CannonPhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT = 2;
  587. CannonPhysicsComponent.COLLISIONFLAGS_NO_CONTACT_RESPONSE = 4;
  588. CannonPhysicsComponent.COLLISIONFLAGS_CUSTOM_MATERIAL_CALLBACK = 8;
  589. CannonPhysicsComponent.COLLISIONFLAGS_CHARACTER_OBJECT = 16;
  590. CannonPhysicsComponent.COLLISIONFLAGS_DISABLE_VISUALIZE_OBJECT = 32;
  591. CannonPhysicsComponent.COLLISIONFLAGS_DISABLE_SPU_COLLISION_PROCESSING = 64;
  592. CannonPhysicsComponent._tempVector30 = new Laya.Vector3();
  593. CannonPhysicsComponent._tempQuaternion0 = new Laya.Quaternion();
  594. CannonPhysicsComponent._tempQuaternion1 = new Laya.Quaternion();
  595. CannonPhysicsComponent._tempMatrix4x40 = new Laya.Matrix4x4();
  596. CannonPhysicsComponent._physicObjectsMap = {};
  597. CannonPhysicsComponent._addUpdateList = true;
  598. class CannonPhysicsTriggerComponent extends CannonPhysicsComponent {
  599. constructor(collisionGroup, canCollideWith) {
  600. super(collisionGroup, canCollideWith);
  601. this._isTrigger = false;
  602. }
  603. get isTrigger() {
  604. return this._isTrigger;
  605. }
  606. set isTrigger(value) {
  607. this._isTrigger = value;
  608. if (this._btColliderObject) {
  609. this._btColliderObject.isTrigger = value;
  610. if (value) {
  611. var flag = this._btColliderObject.type;
  612. this._btColliderObject.collisionResponse = false;
  613. if ((flag & CANNON.Body.STATIC) === 0)
  614. this._btColliderObject.type |= CANNON.Body.STATIC;
  615. }
  616. else {
  617. this._btColliderObject.collisionResponse = true;
  618. if ((flag & CANNON.Body.STATIC) !== 0)
  619. this._btColliderObject.type ^= CANNON.Body.STATIC;
  620. }
  621. }
  622. }
  623. _onAdded() {
  624. super._onAdded();
  625. this.isTrigger = this._isTrigger;
  626. }
  627. _cloneTo(dest) {
  628. super._cloneTo(dest);
  629. dest.isTrigger = this._isTrigger;
  630. }
  631. }
  632. class CannonPhysicsCollider extends CannonPhysicsTriggerComponent {
  633. constructor(collisionGroup = -1, canCollideWith = -1) {
  634. super(collisionGroup, canCollideWith);
  635. this._enableProcessCollisions = false;
  636. }
  637. _addToSimulation() {
  638. this._simulation._addPhysicsCollider(this);
  639. }
  640. _removeFromSimulation() {
  641. this._simulation._removePhysicsCollider(this);
  642. }
  643. _parse(data) {
  644. (data.friction != null) && (this.friction = data.friction);
  645. (data.restitution != null) && (this.restitution = data.restitution);
  646. (data.isTrigger != null) && (this.isTrigger = data.isTrigger);
  647. super._parse(data);
  648. this._parseShape(data.shapes);
  649. }
  650. _onAdded() {
  651. this._btColliderObject = new CANNON.Body();
  652. this._btColliderObject.material = new CANNON.Material();
  653. this._btColliderObject.layaID = this._id;
  654. this._btColliderObject.type = CANNON.Body.STATIC;
  655. this._btColliderObject.collisionFilterGroup = this._collisionGroup;
  656. this._btColliderObject.collisionFilterMask = this._canCollideWith;
  657. super._onAdded();
  658. }
  659. }
  660. class CannonPhysicsSettings {
  661. constructor() {
  662. this.flags = 0;
  663. this.maxSubSteps = 3;
  664. this.fixedTimeStep = 1.0 / 60.0;
  665. this.contactEquationRelaxation = 10;
  666. this.contactEquationStiffness = 1e6;
  667. }
  668. }
  669. class CannonPhysicsUpdateList extends Laya.SingletonList {
  670. constructor() {
  671. super();
  672. }
  673. add(element) {
  674. var index = element._inPhysicUpdateListIndex;
  675. if (index !== -1)
  676. throw "PhysicsUpdateList:element has in PhysicsUpdateList.";
  677. this._add(element);
  678. element._inPhysicUpdateListIndex = this.length++;
  679. }
  680. remove(element) {
  681. var index = element._inPhysicUpdateListIndex;
  682. this.length--;
  683. if (index !== this.length) {
  684. var end = this.elements[this.length];
  685. this.elements[index] = end;
  686. end._inPhysicUpdateListIndex = index;
  687. }
  688. element._inPhysicUpdateListIndex = -1;
  689. }
  690. }
  691. class CannonPhysicsSimulation {
  692. constructor(configuration, flags = 0) {
  693. this._gravity = new Laya.Vector3(0, -10, 0);
  694. this._btClosestRayResultCallback = new CANNON.RaycastResult();
  695. this._btRayoption = {};
  696. this._collisionsUtils = new CannonCollisionTool();
  697. this._previousFrameCollisions = [];
  698. this._currentFrameCollisions = [];
  699. this._physicsUpdateList = new CannonPhysicsUpdateList();
  700. this._updatedRigidbodies = 0;
  701. this.maxSubSteps = 1;
  702. this.fixedTimeStep = 1.0 / 60.0;
  703. this.maxSubSteps = configuration.maxSubSteps;
  704. this.fixedTimeStep = configuration.fixedTimeStep;
  705. this._btDiscreteDynamicsWorld = new CANNON.World();
  706. this._btBroadphase = new CANNON.NaiveBroadphase();
  707. this._btDiscreteDynamicsWorld.broadphase = this._btBroadphase;
  708. this._btDiscreteDynamicsWorld.defaultContactMaterial.contactEquationRelaxation = configuration.contactEquationRelaxation;
  709. this._btDiscreteDynamicsWorld.defaultContactMaterial.contactEquationStiffness = configuration.contactEquationStiffness;
  710. this.gravity = this._gravity;
  711. }
  712. static __init__() {
  713. CannonPhysicsSimulation._btTempVector30 = new CANNON.Vec3(0, 0, 0);
  714. CannonPhysicsSimulation._btTempVector31 = new CANNON.Vec3(0, 0, 0);
  715. }
  716. static createConstraint() {
  717. }
  718. get continuousCollisionDetection() {
  719. return false;
  720. }
  721. set continuousCollisionDetection(value) {
  722. throw "Simulation:Cannon physical engine does not support this feature";
  723. }
  724. get gravity() {
  725. if (!this._btDiscreteDynamicsWorld)
  726. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  727. return this._gravity;
  728. }
  729. set gravity(value) {
  730. if (!this._btDiscreteDynamicsWorld)
  731. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  732. this._gravity = value;
  733. this._btDiscreteDynamicsWorld.gravity.set(value.x, value.y, value.z);
  734. }
  735. get solverIterations() {
  736. if (!(this._btDiscreteDynamicsWorld && this._btDiscreteDynamicsWorld.solver))
  737. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  738. return this._iterations;
  739. }
  740. set solverIterations(value) {
  741. if (!(this._btDiscreteDynamicsWorld && this._btDiscreteDynamicsWorld.solver))
  742. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  743. this._btDiscreteDynamicsWorld.solver.iterations = value;
  744. this._iterations = value;
  745. }
  746. get speculativeContactRestitution() {
  747. return false;
  748. }
  749. set speculativeContactRestitution(value) {
  750. }
  751. _simulate(deltaTime) {
  752. this._updatedRigidbodies = 0;
  753. if (this._btDiscreteDynamicsWorld) {
  754. this._btDiscreteDynamicsWorld.callBackBody.length = 0;
  755. this._btDiscreteDynamicsWorld.allContacts.length = 0;
  756. this._btDiscreteDynamicsWorld.step(this.fixedTimeStep, deltaTime, this.maxSubSteps);
  757. }
  758. var callBackBody = this._btDiscreteDynamicsWorld.callBackBody;
  759. for (var i = 0, n = callBackBody.length; i < n; i++) {
  760. var cannonBody = callBackBody[i];
  761. var rigidbody = CannonPhysicsComponent._physicObjectsMap[cannonBody.layaID];
  762. rigidbody._simulation._updatedRigidbodies++;
  763. rigidbody._updateTransformComponent(rigidbody._btColliderObject);
  764. }
  765. }
  766. _destroy() {
  767. this._btDiscreteDynamicsWorld = null;
  768. this._btBroadphase = null;
  769. }
  770. _addPhysicsCollider(component) {
  771. this._btDiscreteDynamicsWorld.addBody(component._btColliderObject);
  772. }
  773. _removePhysicsCollider(component) {
  774. this._btDiscreteDynamicsWorld.removeBody(component._btColliderObject);
  775. }
  776. _addRigidBody(rigidBody) {
  777. if (!this._btDiscreteDynamicsWorld)
  778. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  779. this._btDiscreteDynamicsWorld.addBody(rigidBody._btColliderObject);
  780. }
  781. _removeRigidBody(rigidBody) {
  782. if (!this._btDiscreteDynamicsWorld)
  783. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  784. this._btDiscreteDynamicsWorld.removeBody(rigidBody._btColliderObject);
  785. }
  786. raycastFromTo(from, to, out = null, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  787. var rayResultCall = this._btClosestRayResultCallback;
  788. rayResultCall.hasHit = false;
  789. var rayOptions = this._btRayoption;
  790. var rayFrom = CannonPhysicsSimulation._btTempVector30;
  791. var rayTo = CannonPhysicsSimulation._btTempVector31;
  792. rayFrom.set(from.x, from.y, from.z);
  793. rayTo.set(to.x, to.y, to.z);
  794. rayOptions.skipBackfaces = true;
  795. rayOptions.collisionFilterMask = collisionMask;
  796. rayOptions.collisionFilterGroup = collisonGroup;
  797. rayOptions.result = rayResultCall;
  798. this._btDiscreteDynamicsWorld.raycastClosest(rayFrom, rayTo, rayOptions, rayResultCall);
  799. if (rayResultCall.hasHit) {
  800. if (out) {
  801. out.succeeded = true;
  802. out.collider = CannonPhysicsComponent._physicObjectsMap[rayResultCall.body.layaID];
  803. var point = out.point;
  804. var normal = out.normal;
  805. var resultPoint = rayResultCall.hitPointWorld;
  806. var resultNormal = rayResultCall.hitNormalWorld;
  807. point.setValue(resultPoint.x, resultPoint.y, resultPoint.z);
  808. normal.setValue(resultNormal.x, resultNormal.y, resultNormal.z);
  809. }
  810. return true;
  811. }
  812. else {
  813. out.succeeded = false;
  814. }
  815. return false;
  816. }
  817. raycastAllFromTo(from, to, out, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  818. var rayOptions = this._btRayoption;
  819. var rayFrom = CannonPhysicsSimulation._btTempVector30;
  820. var rayTo = CannonPhysicsSimulation._btTempVector31;
  821. rayFrom.set(from.x, from.y, from.z);
  822. rayTo.set(to.x, to.y, to.z);
  823. rayOptions.skipBackfaces = true;
  824. rayOptions.collisionFilterMask = collisionMask;
  825. rayOptions.collisionFilterGroup = collisonGroup;
  826. out.length = 0;
  827. this._btDiscreteDynamicsWorld.raycastAll(rayFrom, rayTo, rayOptions, function (result) {
  828. var hitResult = this._collisionsUtils.getHitResult();
  829. out.push(hitResult);
  830. hitResult.succeeded = true;
  831. hitResult.collider = CannonPhysicsComponent._physicObjectsMap[result.body.layaID];
  832. var point = hitResult.point;
  833. var normal = hitResult.normal;
  834. var resultPoint = result.hitPointWorld;
  835. var resultNormal = result.hitNormalWorld;
  836. point.setValue(resultPoint.x, resultPoint.y, resultPoint.z);
  837. normal.setValue(resultNormal.x, resultNormal.y, resultNormal.z);
  838. });
  839. if (out.length != 0)
  840. return true;
  841. else
  842. return false;
  843. }
  844. rayCast(ray, outHitResult = null, distance = 2147483647, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  845. var from = ray.origin;
  846. var to = CannonPhysicsSimulation._tempVector30;
  847. Laya.Vector3.normalize(ray.direction, to);
  848. Laya.Vector3.scale(to, distance, to);
  849. Laya.Vector3.add(from, to, to);
  850. return this.raycastFromTo(from, to, outHitResult, collisonGroup, collisionMask);
  851. }
  852. rayCastAll(ray, out, distance = 2147483647, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  853. var from = ray.origin;
  854. var to = CannonPhysicsSimulation._tempVector30;
  855. Laya.Vector3.normalize(ray.direction, to);
  856. Laya.Vector3.scale(to, distance, to);
  857. Laya.Vector3.add(from, to, to);
  858. return this.raycastAllFromTo(from, to, out, collisonGroup, collisionMask);
  859. }
  860. _updatePhysicsTransformFromRender() {
  861. var elements = this._physicsUpdateList.elements;
  862. for (var i = 0, n = this._physicsUpdateList.length; i < n; i++) {
  863. var physicCollider = elements[i];
  864. physicCollider._derivePhysicsTransformation(false);
  865. physicCollider._inPhysicUpdateListIndex = -1;
  866. }
  867. this._physicsUpdateList.length = 0;
  868. }
  869. _updateCollisions() {
  870. this._collisionsUtils.recoverAllContactPointsPool();
  871. var previous = this._currentFrameCollisions;
  872. this._currentFrameCollisions = this._previousFrameCollisions;
  873. this._currentFrameCollisions.length = 0;
  874. this._previousFrameCollisions = previous;
  875. var loopCount = Laya.Stat.loopCount;
  876. var allContacts = this._btDiscreteDynamicsWorld.allContacts;
  877. var numManifolds = allContacts.length;
  878. for (var i = 0; i < numManifolds; i++) {
  879. var contactEquation = allContacts[i];
  880. var componentA = CannonPhysicsComponent._physicObjectsMap[contactEquation.bi.layaID];
  881. var componentB = CannonPhysicsComponent._physicObjectsMap[contactEquation.bj.layaID];
  882. var collision = null;
  883. var isFirstCollision;
  884. var contacts = null;
  885. var isTrigger = componentA.isTrigger || componentB.isTrigger;
  886. if (isTrigger && (componentA.owner._needProcessTriggers || componentB.owner._needProcessTriggers)) {
  887. collision = this._collisionsUtils.getCollision(componentA, componentB);
  888. contacts = collision.contacts;
  889. isFirstCollision = collision._updateFrame !== loopCount;
  890. if (isFirstCollision) {
  891. collision._isTrigger = true;
  892. contacts.length = 0;
  893. }
  894. }
  895. else if (componentA.owner._needProcessCollisions || componentB.owner._needProcessCollisions) {
  896. if (componentA._enableProcessCollisions || componentB._enableProcessCollisions) {
  897. var contactPoint = this._collisionsUtils.getContactPoints();
  898. contactPoint.colliderA = componentA;
  899. contactPoint.colliderB = componentB;
  900. var normal = contactPoint.normal;
  901. var positionOnA = contactPoint.positionOnA;
  902. var positionOnB = contactPoint.positionOnB;
  903. var connectNormal = contactEquation.ni;
  904. var connectOnA = contactEquation.ri;
  905. var connectOnB = contactEquation.rj;
  906. normal.setValue(connectNormal.x, connectNormal.y, connectNormal.z);
  907. positionOnA.setValue(connectOnA.x, connectOnA.y, connectOnA.z);
  908. positionOnB.setValue(connectOnB.x, connectOnB.y, -connectOnB.z);
  909. collision = this._collisionsUtils.getCollision(componentA, componentB);
  910. contacts = collision.contacts;
  911. isFirstCollision = collision._updateFrame !== loopCount;
  912. if (isFirstCollision) {
  913. collision._isTrigger = false;
  914. contacts.length = 0;
  915. }
  916. contacts.push(contactPoint);
  917. }
  918. }
  919. if (collision && isFirstCollision) {
  920. this._currentFrameCollisions.push(collision);
  921. collision._setUpdateFrame(loopCount);
  922. }
  923. }
  924. }
  925. _eventScripts() {
  926. var loopCount = Laya.Stat.loopCount;
  927. for (var i = 0, n = this._currentFrameCollisions.length; i < n; i++) {
  928. var curFrameCol = this._currentFrameCollisions[i];
  929. var colliderA = curFrameCol._colliderA;
  930. var colliderB = curFrameCol._colliderB;
  931. if (colliderA.destroyed || colliderB.destroyed)
  932. continue;
  933. if (loopCount - curFrameCol._lastUpdateFrame === 1) {
  934. var ownerA = colliderA.owner;
  935. var scriptsA = ownerA._scripts;
  936. if (scriptsA) {
  937. if (curFrameCol._isTrigger) {
  938. if (ownerA._needProcessTriggers) {
  939. for (var j = 0, m = scriptsA.length; j < m; j++)
  940. scriptsA[j].onTriggerStay(colliderB);
  941. }
  942. }
  943. else {
  944. if (ownerA._needProcessCollisions) {
  945. for (j = 0, m = scriptsA.length; j < m; j++) {
  946. curFrameCol.other = colliderB;
  947. scriptsA[j].onCollisionStay(curFrameCol);
  948. }
  949. }
  950. }
  951. }
  952. var ownerB = colliderB.owner;
  953. var scriptsB = ownerB._scripts;
  954. if (scriptsB) {
  955. if (curFrameCol._isTrigger) {
  956. if (ownerB._needProcessTriggers) {
  957. for (j = 0, m = scriptsB.length; j < m; j++)
  958. scriptsB[j].onTriggerStay(colliderA);
  959. }
  960. }
  961. else {
  962. if (ownerB._needProcessCollisions) {
  963. for (j = 0, m = scriptsB.length; j < m; j++) {
  964. curFrameCol.other = colliderA;
  965. scriptsB[j].onCollisionStay(curFrameCol);
  966. }
  967. }
  968. }
  969. }
  970. }
  971. else {
  972. ownerA = colliderA.owner;
  973. scriptsA = ownerA._scripts;
  974. if (scriptsA) {
  975. if (curFrameCol._isTrigger) {
  976. if (ownerA._needProcessTriggers) {
  977. for (j = 0, m = scriptsA.length; j < m; j++)
  978. scriptsA[j].onTriggerEnter(colliderB);
  979. }
  980. }
  981. else {
  982. if (ownerA._needProcessCollisions) {
  983. for (j = 0, m = scriptsA.length; j < m; j++) {
  984. curFrameCol.other = colliderB;
  985. scriptsA[j].onCollisionEnter(curFrameCol);
  986. }
  987. }
  988. }
  989. }
  990. ownerB = colliderB.owner;
  991. scriptsB = ownerB._scripts;
  992. if (scriptsB) {
  993. if (curFrameCol._isTrigger) {
  994. if (ownerB._needProcessTriggers) {
  995. for (j = 0, m = scriptsB.length; j < m; j++)
  996. scriptsB[j].onTriggerEnter(colliderA);
  997. }
  998. }
  999. else {
  1000. if (ownerB._needProcessCollisions) {
  1001. for (j = 0, m = scriptsB.length; j < m; j++) {
  1002. curFrameCol.other = colliderA;
  1003. scriptsB[j].onCollisionEnter(curFrameCol);
  1004. }
  1005. }
  1006. }
  1007. }
  1008. }
  1009. }
  1010. for (i = 0, n = this._previousFrameCollisions.length; i < n; i++) {
  1011. var preFrameCol = this._previousFrameCollisions[i];
  1012. var preColliderA = preFrameCol._colliderA;
  1013. var preColliderB = preFrameCol._colliderB;
  1014. if (preColliderA.destroyed || preColliderB.destroyed)
  1015. continue;
  1016. if (loopCount - preFrameCol._updateFrame === 1) {
  1017. this._collisionsUtils.recoverCollision(preFrameCol);
  1018. ownerA = preColliderA.owner;
  1019. scriptsA = ownerA._scripts;
  1020. if (scriptsA) {
  1021. if (preFrameCol._isTrigger) {
  1022. if (ownerA._needProcessTriggers) {
  1023. for (j = 0, m = scriptsA.length; j < m; j++)
  1024. scriptsA[j].onTriggerExit(preColliderB);
  1025. }
  1026. }
  1027. else {
  1028. if (ownerA._needProcessCollisions) {
  1029. for (j = 0, m = scriptsA.length; j < m; j++) {
  1030. preFrameCol.other = preColliderB;
  1031. scriptsA[j].onCollisionExit(preFrameCol);
  1032. }
  1033. }
  1034. }
  1035. }
  1036. ownerB = preColliderB.owner;
  1037. scriptsB = ownerB._scripts;
  1038. if (scriptsB) {
  1039. if (preFrameCol._isTrigger) {
  1040. if (ownerB._needProcessTriggers) {
  1041. for (j = 0, m = scriptsB.length; j < m; j++)
  1042. scriptsB[j].onTriggerExit(preColliderA);
  1043. }
  1044. }
  1045. else {
  1046. if (ownerB._needProcessCollisions) {
  1047. for (j = 0, m = scriptsB.length; j < m; j++) {
  1048. preFrameCol.other = preColliderA;
  1049. scriptsB[j].onCollisionExit(preFrameCol);
  1050. }
  1051. }
  1052. }
  1053. }
  1054. }
  1055. }
  1056. }
  1057. clearForces() {
  1058. if (!this._btDiscreteDynamicsWorld)
  1059. throw "Cannot perform this action when the physics engine is set to CollisionsOnly";
  1060. }
  1061. }
  1062. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_NONE = 0x0;
  1063. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_COLLISIONSONLY = 0x1;
  1064. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_SOFTBODYSUPPORT = 0x2;
  1065. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_MULTITHREADED = 0x4;
  1066. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_USEHARDWAREWHENPOSSIBLE = 0x8;
  1067. CannonPhysicsSimulation.SOLVERMODE_RANDMIZE_ORDER = 1;
  1068. CannonPhysicsSimulation.SOLVERMODE_FRICTION_SEPARATE = 2;
  1069. CannonPhysicsSimulation.SOLVERMODE_USE_WARMSTARTING = 4;
  1070. CannonPhysicsSimulation.SOLVERMODE_USE_2_FRICTION_DIRECTIONS = 16;
  1071. CannonPhysicsSimulation.SOLVERMODE_ENABLE_FRICTION_DIRECTION_CACHING = 32;
  1072. CannonPhysicsSimulation.SOLVERMODE_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64;
  1073. CannonPhysicsSimulation.SOLVERMODE_CACHE_FRIENDLY = 128;
  1074. CannonPhysicsSimulation.SOLVERMODE_SIMD = 256;
  1075. CannonPhysicsSimulation.SOLVERMODE_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512;
  1076. CannonPhysicsSimulation.SOLVERMODE_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024;
  1077. CannonPhysicsSimulation._tempVector30 = new Laya.Vector3();
  1078. CannonPhysicsSimulation.disableSimulation = false;
  1079. class CannonRigidbody3D extends CannonPhysicsCollider {
  1080. constructor(collisionGroup = -1, canCollideWith = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  1081. super(collisionGroup, canCollideWith);
  1082. this._isKinematic = false;
  1083. this._mass = 1.0;
  1084. this._gravity = new Laya.Vector3(0, -10, 0);
  1085. this._angularDamping = 0.0;
  1086. this._linearDamping = 0.0;
  1087. this._totalTorque = new Laya.Vector3(0, 0, 0);
  1088. this._totalForce = new Laya.Vector3(0, 0, 0);
  1089. this._linearVelocity = new Laya.Vector3();
  1090. this._angularVelocity = new Laya.Vector3();
  1091. this._controlBySimulation = true;
  1092. }
  1093. static __init__() {
  1094. CannonRigidbody3D._btTempVector30 = new CANNON.Vec3();
  1095. CannonRigidbody3D._btTempVector31 = new CANNON.Vec3();
  1096. }
  1097. get mass() {
  1098. return this._mass;
  1099. }
  1100. set mass(value) {
  1101. value = Math.max(value, 1e-07);
  1102. this._mass = value;
  1103. (this._isKinematic) || (this._updateMass(value));
  1104. }
  1105. get isKinematic() {
  1106. return this._isKinematic;
  1107. }
  1108. set isKinematic(value) {
  1109. this._isKinematic = value;
  1110. this._controlBySimulation = !value;
  1111. var canInSimulation = !!(this._simulation && this._enabled && this._colliderShape);
  1112. canInSimulation && this._removeFromSimulation();
  1113. var natColObj = this._btColliderObject;
  1114. var flags = natColObj.type;
  1115. if (value) {
  1116. flags = flags | CANNON.Body.KINEMATIC;
  1117. natColObj.type = flags;
  1118. this._enableProcessCollisions = false;
  1119. this._updateMass(0);
  1120. }
  1121. else {
  1122. if ((flags & CANNON.Body.KINEMATIC) > 0)
  1123. flags = flags ^ CANNON.Body.KINEMATIC;
  1124. natColObj.allowSleep = true;
  1125. natColObj.type = flags;
  1126. this._enableProcessCollisions = true;
  1127. this._updateMass(this._mass);
  1128. }
  1129. natColObj.velocity.set(0.0, 0.0, 0.0);
  1130. natColObj.angularVelocity.set(0.0, 0.0, 0.0);
  1131. canInSimulation && this._addToSimulation();
  1132. }
  1133. get linearDamping() {
  1134. return this._linearDamping;
  1135. }
  1136. set linearDamping(value) {
  1137. this._linearDamping = value;
  1138. if (this._btColliderObject)
  1139. this._btColliderObject.linearDamping = value;
  1140. }
  1141. get angularDamping() {
  1142. return this._angularDamping;
  1143. }
  1144. set angularDamping(value) {
  1145. this._angularDamping = value;
  1146. if (this._btColliderObject)
  1147. this._btColliderObject.angularDamping = value;
  1148. }
  1149. get totalForce() {
  1150. if (this._btColliderObject) {
  1151. var btTotalForce = this.btColliderObject.force;
  1152. this.totalForce.setValue(btTotalForce.x, btTotalForce.y, btTotalForce.z);
  1153. return this._totalForce;
  1154. }
  1155. return null;
  1156. }
  1157. get linearVelocity() {
  1158. if (this._btColliderObject) {
  1159. var phylinear = this.btColliderObject.velocity;
  1160. this._linearVelocity.setValue(phylinear.x, phylinear.y, phylinear.z);
  1161. }
  1162. return this._linearVelocity;
  1163. }
  1164. set linearVelocity(value) {
  1165. this._linearVelocity = value;
  1166. if (this._btColliderObject) {
  1167. var btValue = this.btColliderObject.velocity;
  1168. (this.isSleeping) && (this.wakeUp());
  1169. btValue.set(value.x, value.y, value.z);
  1170. this.btColliderObject.velocity = btValue;
  1171. }
  1172. }
  1173. get angularVelocity() {
  1174. if (this._btColliderObject) {
  1175. var phtqua = this._btColliderObject.angularVelocity;
  1176. this.angularVelocity.setValue(phtqua.x, phtqua.y, phtqua.z);
  1177. }
  1178. return this._angularVelocity;
  1179. }
  1180. set angularVelocity(value) {
  1181. this._angularVelocity = value;
  1182. if (this._btColliderObject) {
  1183. var btValue = this.btColliderObject.angularVelocity;
  1184. (this.isSleeping) && (this.wakeUp());
  1185. btValue.set(value.x, value.y, value.z);
  1186. this.btColliderObject.velocity = btValue;
  1187. }
  1188. }
  1189. get totalTorque() {
  1190. if (this._btColliderObject) {
  1191. var btTotalTorque = this._btColliderObject.torque;
  1192. this._totalTorque.setValue(btTotalTorque.x, btTotalTorque.y, btTotalTorque.z);
  1193. return this._totalTorque;
  1194. }
  1195. return null;
  1196. }
  1197. get isSleeping() {
  1198. if (this._btColliderObject)
  1199. return this._btColliderObject.sleepState != CANNON.Body.AWAKE;
  1200. return false;
  1201. }
  1202. get sleepLinearVelocity() {
  1203. return this._btColliderObject.sleepSpeedLimit;
  1204. }
  1205. set sleepLinearVelocity(value) {
  1206. this._btColliderObject.sleepSpeedLimit = value;
  1207. }
  1208. get btColliderObject() {
  1209. return this._btColliderObject;
  1210. }
  1211. _updateMass(mass) {
  1212. if (this._btColliderObject && this._colliderShape) {
  1213. this._btColliderObject.mass = mass;
  1214. this._btColliderObject.updateMassProperties();
  1215. this._btColliderObject.updateSolveMassProperties();
  1216. }
  1217. }
  1218. _onScaleChange(scale) {
  1219. super._onScaleChange(scale);
  1220. this._updateMass(this._isKinematic ? 0 : this._mass);
  1221. }
  1222. _derivePhysicsTransformation(force) {
  1223. this._innerDerivePhysicsTransformation(this.btColliderObject, force);
  1224. }
  1225. _onAdded() {
  1226. var btRigid = new CANNON.Body();
  1227. btRigid.material = new CANNON.Material();
  1228. btRigid.layaID = this.id;
  1229. btRigid.collisionFilterGroup = this.collisionGroup;
  1230. btRigid.collisionFilterMask = this._canCollideWith;
  1231. this._btColliderObject = btRigid;
  1232. super._onAdded();
  1233. this.mass = this._mass;
  1234. this.linearDamping = this._linearDamping;
  1235. this.angularDamping = this._angularDamping;
  1236. this.isKinematic = this._isKinematic;
  1237. if (!this.isKinematic)
  1238. this._btColliderObject.type = CANNON.Body.DYNAMIC;
  1239. else
  1240. this._btColliderObject.type = CANNON.Body.KINEMATIC;
  1241. }
  1242. _onShapeChange(colShape) {
  1243. super._onShapeChange(colShape);
  1244. if (this._isKinematic) {
  1245. this._updateMass(0);
  1246. }
  1247. else {
  1248. this._updateMass(this._mass);
  1249. }
  1250. }
  1251. _parse(data) {
  1252. (data.friction != null) && (this.friction = data.friction);
  1253. (data.restitution != null) && (this.restitution = data.restitution);
  1254. (data.isTrigger != null) && (this.isTrigger = data.isTrigger);
  1255. (data.mass != null) && (this.mass = data.mass);
  1256. (data.isKinematic != null) && (this.isKinematic = data.isKinematic);
  1257. (data.linearDamping != null) && (this.linearDamping = data.linearDamping);
  1258. (data.angularDamping != null) && (this.angularDamping = data.angularDamping);
  1259. super._parse(data);
  1260. this._parseShape(data.shapes);
  1261. }
  1262. _onDestroy() {
  1263. super._onDestroy();
  1264. this._gravity = null;
  1265. this._totalTorque = null;
  1266. this._linearVelocity = null;
  1267. this._angularVelocity = null;
  1268. }
  1269. _addToSimulation() {
  1270. this._simulation._addRigidBody(this);
  1271. }
  1272. _removeFromSimulation() {
  1273. this._simulation._removeRigidBody(this);
  1274. }
  1275. _cloneTo(dest) {
  1276. super._cloneTo(dest);
  1277. var destRigidbody3D = dest;
  1278. destRigidbody3D.isKinematic = this._isKinematic;
  1279. destRigidbody3D.mass = this._mass;
  1280. destRigidbody3D.angularDamping = this._angularDamping;
  1281. destRigidbody3D.linearDamping = this._linearDamping;
  1282. destRigidbody3D.linearVelocity = this._linearVelocity;
  1283. destRigidbody3D.angularVelocity = this._angularVelocity;
  1284. }
  1285. applyForce(force, localOffset = null) {
  1286. if (this._btColliderObject == null)
  1287. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1288. var btForce = CannonRigidbody3D._btTempVector30;
  1289. btForce.set(force.x, force.y, force.z);
  1290. var btOffset = CannonRigidbody3D._btTempVector31;
  1291. if (localOffset)
  1292. btOffset.set(localOffset.x, localOffset.y, localOffset.z);
  1293. else
  1294. btOffset.set(0.0, 0.0, 0.0);
  1295. this.btColliderObject.applyLocalForce(btForce, btOffset);
  1296. }
  1297. applyTorque(torque) {
  1298. if (this._btColliderObject == null)
  1299. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1300. var btTorque = CannonRigidbody3D._btTempVector30;
  1301. btTorque.set(torque.x, torque.y, torque.z);
  1302. var oriTorque = this.btColliderObject.torque;
  1303. oriTorque.set(oriTorque.x + btTorque.x, oriTorque.y + btTorque.y, oriTorque.z + btTorque.z);
  1304. this.btColliderObject.torque = oriTorque;
  1305. }
  1306. applyImpulse(impulse, localOffset = null) {
  1307. if (this._btColliderObject == null)
  1308. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1309. if (this._btColliderObject == null)
  1310. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1311. var btForce = CannonRigidbody3D._btTempVector30;
  1312. btForce.set(impulse.x, impulse.y, impulse.z);
  1313. var btOffset = CannonRigidbody3D._btTempVector31;
  1314. if (localOffset)
  1315. btOffset.set(localOffset.x, localOffset.y, localOffset.z);
  1316. else
  1317. btOffset.set(0.0, 0.0, 0.0);
  1318. this.btColliderObject.applyImpulse(btForce, btOffset);
  1319. }
  1320. wakeUp() {
  1321. this._btColliderObject && this._btColliderObject.wakeUp();
  1322. }
  1323. clearForces() {
  1324. var rigidBody = this._btColliderObject;
  1325. if (rigidBody == null)
  1326. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1327. rigidBody.velocity.set(0.0, 0.0, 0.0);
  1328. rigidBody.velocity = rigidBody.velocity;
  1329. rigidBody.angularVelocity.set(0.0, 0.0, 0.0);
  1330. rigidBody.angularVelocity = rigidBody.angularVelocity;
  1331. }
  1332. }
  1333. CannonRigidbody3D.TYPE_STATIC = 0;
  1334. CannonRigidbody3D.TYPE_DYNAMIC = 1;
  1335. CannonRigidbody3D.TYPE_KINEMATIC = 2;
  1336. CannonRigidbody3D._BT_DISABLE_WORLD_GRAVITY = 1;
  1337. CannonRigidbody3D._BT_ENABLE_GYROPSCOPIC_FORCE = 2;
  1338. class CannonCompoundColliderShape extends CannonColliderShape {
  1339. constructor() {
  1340. super();
  1341. this._childColliderShapes = [];
  1342. this._type = CannonColliderShape.SHAPETYPES_COMPOUND;
  1343. }
  1344. static __init__() {
  1345. }
  1346. _clearChildShape(shape) {
  1347. shape._attatched = false;
  1348. shape._compoundParent = null;
  1349. shape._indexInCompound = -1;
  1350. }
  1351. _addReference() {
  1352. this._referenceCount++;
  1353. }
  1354. _removeReference() {
  1355. this._referenceCount--;
  1356. }
  1357. addChildShape(shape, localOffset = null) {
  1358. if (shape._attatched)
  1359. throw "CompoundColliderShape: this shape has attatched to other entity.";
  1360. shape._attatched = true;
  1361. shape._compoundParent = this;
  1362. shape._indexInCompound = this._childColliderShapes.length;
  1363. this._childColliderShapes.push(shape);
  1364. shape.localOffset = localOffset;
  1365. if (this.physicColliderObject) {
  1366. CannonCompoundColliderShape._tempCannonQue.set(0, 0, 0, 1);
  1367. CannonCompoundColliderShape._tempCannonVec.set(localOffset.x * this._scale.x, localOffset.y * this._scale.y, localOffset.z * this._scale.z);
  1368. this.physicColliderObject._btColliderObject.addShape(shape._btShape, CannonCompoundColliderShape._tempCannonVec, CANNON.Vec3.ZERO);
  1369. }
  1370. }
  1371. removeChildShape(shape) {
  1372. if (shape._compoundParent === this) {
  1373. var index = shape._indexInCompound;
  1374. this._clearChildShape(shape);
  1375. var endShape = this._childColliderShapes[this._childColliderShapes.length - 1];
  1376. endShape._indexInCompound = index;
  1377. this._childColliderShapes[index] = endShape;
  1378. this._childColliderShapes.pop();
  1379. if (this.physicColliderObject)
  1380. this.bindRigidBody(this.physicColliderObject);
  1381. }
  1382. }
  1383. bindRigidBody(rigidbody) {
  1384. this.physicColliderObject = rigidbody;
  1385. var body = rigidbody._btColliderObject;
  1386. body.shapes.length = 0;
  1387. body.shapeOffsets.length = 0;
  1388. body.shapeOrientations.length = 0;
  1389. var origoffset;
  1390. for (var i = 0, n = this._childColliderShapes.length; i != n; i++) {
  1391. var shape = this._childColliderShapes[i];
  1392. body.shapes.push(shape._btShape);
  1393. origoffset = shape.localOffset;
  1394. body.shapeOffsets.push(new CANNON.Vec3(origoffset.x * this._scale.x, origoffset.y * this._scale.y, origoffset.z * this._scale.z));
  1395. body.shapeOrientations.push(CannonCompoundColliderShape._tempCannonQue);
  1396. }
  1397. body.updateMassProperties();
  1398. body.updateBoundingRadius();
  1399. body.aabbNeedsUpdate = true;
  1400. }
  1401. _setScale(scale) {
  1402. this._scale.setValue(scale.x, scale.y, scale.z);
  1403. var body = this.physicColliderObject._btColliderObject;
  1404. var length = this.getChildShapeCount();
  1405. var shapeoffsets = body.shapeOffsets;
  1406. for (var i = 0; i < length; i++) {
  1407. var offset = shapeoffsets[i];
  1408. var shape = this._childColliderShapes[i];
  1409. shape._setScale(scale);
  1410. var orioffset = shape.localOffset;
  1411. offset.set(orioffset.x * scale.x, orioffset.y * scale.y, orioffset.z * scale.z);
  1412. }
  1413. body.updateMassProperties();
  1414. body.updateBoundingRadius();
  1415. body.aabbNeedsUpdate = true;
  1416. }
  1417. getChildShapeCount() {
  1418. return this._childColliderShapes.length;
  1419. }
  1420. cloneTo(destObject) {
  1421. var destCompoundColliderShape = destObject;
  1422. for (var i = 0, n = this._childColliderShapes.length; i < n; i++)
  1423. destCompoundColliderShape.addChildShape(this._childColliderShapes[i].clone());
  1424. }
  1425. clone() {
  1426. var dest = new CannonCompoundColliderShape();
  1427. this.cloneTo(dest);
  1428. return dest;
  1429. }
  1430. destroy() {
  1431. super.destroy();
  1432. for (var i = 0, n = this._childColliderShapes.length; i < n; i++) {
  1433. var childShape = this._childColliderShapes[i];
  1434. if (childShape._referenceCount === 0)
  1435. childShape.destroy();
  1436. }
  1437. }
  1438. }
  1439. CannonCompoundColliderShape._tempCannonQue = new CANNON.Quaternion(0, 0, 0, 1);
  1440. CannonCompoundColliderShape._tempCannonVec = new CANNON.Vec3(0, 0, 0);
  1441. exports.CannonBoxColliderShape = CannonBoxColliderShape;
  1442. exports.CannonColliderShape = CannonColliderShape;
  1443. exports.CannonCollision = CannonCollision;
  1444. exports.CannonCollisionTool = CannonCollisionTool;
  1445. exports.CannonCompoundColliderShape = CannonCompoundColliderShape;
  1446. exports.CannonContactPoint = CannonContactPoint;
  1447. exports.CannonHitResult = CannonHitResult;
  1448. exports.CannonPhysicsCollider = CannonPhysicsCollider;
  1449. exports.CannonPhysicsComponent = CannonPhysicsComponent;
  1450. exports.CannonPhysicsSettings = CannonPhysicsSettings;
  1451. exports.CannonPhysicsSimulation = CannonPhysicsSimulation;
  1452. exports.CannonPhysicsTriggerComponent = CannonPhysicsTriggerComponent;
  1453. exports.CannonPhysicsUpdateList = CannonPhysicsUpdateList;
  1454. exports.CannonRigidbody3D = CannonRigidbody3D;
  1455. exports.CannonSphereColliderShape = CannonSphereColliderShape;
  1456. }(window.Laya = window.Laya || {}, Laya));