laya.cannonPhysics.js 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474
  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. this._btColliderObject.updateBoundingRadius();
  424. }
  425. _onEnable() {
  426. this._simulation = this.owner._scene._cannonPhysicsSimulation;
  427. if (this._colliderShape) {
  428. this._derivePhysicsTransformation(true);
  429. this._addToSimulation();
  430. }
  431. }
  432. _onDisable() {
  433. if (this._colliderShape) {
  434. this._removeFromSimulation();
  435. (this._inPhysicUpdateListIndex !== -1) && (this._simulation._physicsUpdateList.remove(this));
  436. }
  437. this._simulation = null;
  438. }
  439. _onDestroy() {
  440. delete CannonPhysicsComponent._physicObjectsMap[this.id];
  441. this._btColliderObject = null;
  442. this._colliderShape.destroy();
  443. super._onDestroy();
  444. this._btColliderObject = null;
  445. this._colliderShape = null;
  446. this._simulation = null;
  447. this.owner.transform.off(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
  448. }
  449. _isValid() {
  450. return this._simulation && this._colliderShape && this._enabled;
  451. }
  452. _parse(data) {
  453. (data.collisionGroup != null) && (this.collisionGroup = data.collisionGroup);
  454. (data.canCollideWith != null) && (this.canCollideWith = data.canCollideWith);
  455. }
  456. _setTransformFlag(type, value) {
  457. if (value)
  458. this._transformFlag |= type;
  459. else
  460. this._transformFlag &= ~type;
  461. }
  462. _getTransformFlag(type) {
  463. return (this._transformFlag & type) != 0;
  464. }
  465. _addToSimulation() {
  466. }
  467. _removeFromSimulation() {
  468. }
  469. _derivePhysicsTransformation(force) {
  470. var btColliderObject = this._btColliderObject;
  471. this._innerDerivePhysicsTransformation(btColliderObject, force);
  472. }
  473. _innerDerivePhysicsTransformation(physicTransformOut, force) {
  474. var transform = this.owner._transform;
  475. if (force || this._getTransformFlag(Laya.Transform3D.TRANSFORM_WORLDPOSITION)) {
  476. var shapeOffset = this._colliderShape.localOffset;
  477. var position = transform.position;
  478. var btPosition = CannonPhysicsComponent._btVector30;
  479. if (shapeOffset.x !== 0 || shapeOffset.y !== 0 || shapeOffset.z !== 0) {
  480. var physicPosition = CannonPhysicsComponent._tempVector30;
  481. var worldMat = transform.worldMatrix;
  482. Laya.Vector3.transformCoordinate(shapeOffset, worldMat, physicPosition);
  483. btPosition.set(physicPosition.x, physicPosition.y, physicPosition.z);
  484. }
  485. else {
  486. btPosition.set(position.x, position.y, position.z);
  487. }
  488. physicTransformOut.position.set(btPosition.x, btPosition.y, btPosition.z);
  489. this._setTransformFlag(Laya.Transform3D.TRANSFORM_WORLDPOSITION, false);
  490. }
  491. if (force || this._getTransformFlag(Laya.Transform3D.TRANSFORM_WORLDQUATERNION)) {
  492. var shapeRotation = this._colliderShape.localRotation;
  493. var btRotation = CannonPhysicsComponent._btQuaternion0;
  494. var rotation = transform.rotation;
  495. if (shapeRotation.x !== 0 || shapeRotation.y !== 0 || shapeRotation.z !== 0 || shapeRotation.w !== 1) {
  496. var physicRotation = CannonPhysicsComponent._tempQuaternion0;
  497. CannonPhysicsComponent.physicQuaternionMultiply(rotation.x, rotation.y, rotation.z, rotation.w, shapeRotation, physicRotation);
  498. btRotation.set(physicRotation.x, physicRotation.y, physicRotation.z, physicRotation.w);
  499. }
  500. else {
  501. btRotation.set(rotation.x, rotation.y, rotation.z, rotation.w);
  502. }
  503. physicTransformOut.quaternion.set(btRotation.x, btRotation.y, btRotation.z, btRotation.w);
  504. this._setTransformFlag(Laya.Transform3D.TRANSFORM_WORLDQUATERNION, false);
  505. }
  506. if (force || this._getTransformFlag(Laya.Transform3D.TRANSFORM_WORLDSCALE)) {
  507. this._onScaleChange(transform.getWorldLossyScale());
  508. this._setTransformFlag(Laya.Transform3D.TRANSFORM_WORLDSCALE, false);
  509. }
  510. }
  511. _updateTransformComponent(physicsTransform) {
  512. var colliderShape = this._colliderShape;
  513. var localOffset = colliderShape.localOffset;
  514. var localRotation = colliderShape.localRotation;
  515. var transform = this.owner._transform;
  516. var position = transform.position;
  517. var rotation = transform.rotation;
  518. var btPosition = physicsTransform.position;
  519. var btRotation = physicsTransform.quaternion;
  520. var btRotX = btRotation.x;
  521. var btRotY = btRotation.y;
  522. var btRotZ = btRotation.z;
  523. var btRotW = btRotation.w;
  524. if (localRotation.x !== 0 || localRotation.y !== 0 || localRotation.z !== 0 || localRotation.w !== 1) {
  525. var invertShapeRotaion = CannonPhysicsComponent._tempQuaternion0;
  526. localRotation.invert(invertShapeRotaion);
  527. CannonPhysicsComponent.physicQuaternionMultiply(btRotX, btRotY, btRotZ, btRotW, invertShapeRotaion, rotation);
  528. }
  529. else {
  530. rotation.x = btRotX;
  531. rotation.y = btRotY;
  532. rotation.z = btRotZ;
  533. rotation.w = btRotW;
  534. }
  535. transform.rotation = rotation;
  536. if (localOffset.x !== 0 || localOffset.y !== 0 || localOffset.z !== 0) {
  537. var rotShapePosition = CannonPhysicsComponent._tempVector30;
  538. rotShapePosition.x = localOffset.x;
  539. rotShapePosition.y = localOffset.y;
  540. rotShapePosition.z = localOffset.z;
  541. Laya.Vector3.transformQuat(rotShapePosition, rotation, rotShapePosition);
  542. position.x = btPosition.x - rotShapePosition.x;
  543. position.y = btPosition.y - rotShapePosition.z;
  544. position.z = btPosition.z - rotShapePosition.y;
  545. }
  546. else {
  547. position.x = btPosition.x;
  548. position.y = btPosition.y;
  549. position.z = btPosition.z;
  550. }
  551. transform.position = position;
  552. }
  553. _onShapeChange(colShape) {
  554. }
  555. _onAdded() {
  556. this.enabled = this._enabled;
  557. this.restitution = this._restitution;
  558. this.friction = this._friction;
  559. this.owner.transform.on(Laya.Event.TRANSFORM_CHANGED, this, this._onTransformChanged);
  560. }
  561. _onTransformChanged(flag) {
  562. if (CannonPhysicsComponent._addUpdateList || !this._controlBySimulation) {
  563. flag &= Laya.Transform3D.TRANSFORM_WORLDPOSITION | Laya.Transform3D.TRANSFORM_WORLDQUATERNION | Laya.Transform3D.TRANSFORM_WORLDSCALE;
  564. if (flag) {
  565. this._transformFlag |= flag;
  566. if (this._isValid() && this._inPhysicUpdateListIndex === -1)
  567. this._simulation._physicsUpdateList.add(this);
  568. }
  569. }
  570. }
  571. _cloneTo(dest) {
  572. var destPhysicsComponent = dest;
  573. destPhysicsComponent.restitution = this._restitution;
  574. destPhysicsComponent.friction = this._friction;
  575. destPhysicsComponent.collisionGroup = this._collisionGroup;
  576. destPhysicsComponent.canCollideWith = this._canCollideWith;
  577. destPhysicsComponent.canScaleShape = this.canScaleShape;
  578. (this._colliderShape) && (destPhysicsComponent.colliderShape = this._colliderShape.clone());
  579. }
  580. }
  581. CannonPhysicsComponent.ACTIVATIONSTATE_ACTIVE_TAG = 1;
  582. CannonPhysicsComponent.ACTIVATIONSTATE_ISLAND_SLEEPING = 2;
  583. CannonPhysicsComponent.ACTIVATIONSTATE_WANTS_DEACTIVATION = 3;
  584. CannonPhysicsComponent.ACTIVATIONSTATE_DISABLE_DEACTIVATION = 4;
  585. CannonPhysicsComponent.ACTIVATIONSTATE_DISABLE_SIMULATION = 5;
  586. CannonPhysicsComponent.COLLISIONFLAGS_STATIC_OBJECT = 1;
  587. CannonPhysicsComponent.COLLISIONFLAGS_KINEMATIC_OBJECT = 2;
  588. CannonPhysicsComponent.COLLISIONFLAGS_NO_CONTACT_RESPONSE = 4;
  589. CannonPhysicsComponent.COLLISIONFLAGS_CUSTOM_MATERIAL_CALLBACK = 8;
  590. CannonPhysicsComponent.COLLISIONFLAGS_CHARACTER_OBJECT = 16;
  591. CannonPhysicsComponent.COLLISIONFLAGS_DISABLE_VISUALIZE_OBJECT = 32;
  592. CannonPhysicsComponent.COLLISIONFLAGS_DISABLE_SPU_COLLISION_PROCESSING = 64;
  593. CannonPhysicsComponent._tempVector30 = new Laya.Vector3();
  594. CannonPhysicsComponent._tempQuaternion0 = new Laya.Quaternion();
  595. CannonPhysicsComponent._tempQuaternion1 = new Laya.Quaternion();
  596. CannonPhysicsComponent._tempMatrix4x40 = new Laya.Matrix4x4();
  597. CannonPhysicsComponent._physicObjectsMap = {};
  598. CannonPhysicsComponent._addUpdateList = true;
  599. class CannonPhysicsTriggerComponent extends CannonPhysicsComponent {
  600. constructor(collisionGroup, canCollideWith) {
  601. super(collisionGroup, canCollideWith);
  602. this._isTrigger = false;
  603. }
  604. get isTrigger() {
  605. return this._isTrigger;
  606. }
  607. set isTrigger(value) {
  608. this._isTrigger = value;
  609. if (this._btColliderObject) {
  610. this._btColliderObject.isTrigger = value;
  611. if (value) {
  612. var flag = this._btColliderObject.type;
  613. this._btColliderObject.collisionResponse = false;
  614. if ((flag & CANNON.Body.STATIC) === 0)
  615. this._btColliderObject.type |= CANNON.Body.STATIC;
  616. }
  617. else {
  618. this._btColliderObject.collisionResponse = true;
  619. if ((flag & CANNON.Body.STATIC) !== 0)
  620. this._btColliderObject.type ^= CANNON.Body.STATIC;
  621. }
  622. }
  623. }
  624. _onAdded() {
  625. super._onAdded();
  626. this.isTrigger = this._isTrigger;
  627. }
  628. _cloneTo(dest) {
  629. super._cloneTo(dest);
  630. dest.isTrigger = this._isTrigger;
  631. }
  632. }
  633. class CannonPhysicsCollider extends CannonPhysicsTriggerComponent {
  634. constructor(collisionGroup = -1, canCollideWith = -1) {
  635. super(collisionGroup, canCollideWith);
  636. this._enableProcessCollisions = false;
  637. }
  638. _addToSimulation() {
  639. this._simulation._addPhysicsCollider(this);
  640. }
  641. _removeFromSimulation() {
  642. this._simulation._removePhysicsCollider(this);
  643. }
  644. _parse(data) {
  645. (data.friction != null) && (this.friction = data.friction);
  646. (data.restitution != null) && (this.restitution = data.restitution);
  647. (data.isTrigger != null) && (this.isTrigger = data.isTrigger);
  648. super._parse(data);
  649. this._parseShape(data.shapes);
  650. }
  651. _onAdded() {
  652. this._btColliderObject = new CANNON.Body();
  653. this._btColliderObject.material = new CANNON.Material();
  654. this._btColliderObject.layaID = this._id;
  655. this._btColliderObject.type = CANNON.Body.STATIC;
  656. this._btColliderObject.collisionFilterGroup = this._collisionGroup;
  657. this._btColliderObject.collisionFilterMask = this._canCollideWith;
  658. super._onAdded();
  659. }
  660. }
  661. class CannonPhysicsSettings {
  662. constructor() {
  663. this.flags = 0;
  664. this.maxSubSteps = 3;
  665. this.fixedTimeStep = 1.0 / 60.0;
  666. this.contactEquationRelaxation = 10;
  667. this.contactEquationStiffness = 1e6;
  668. }
  669. }
  670. class CannonPhysicsUpdateList extends Laya.SingletonList {
  671. constructor() {
  672. super();
  673. }
  674. add(element) {
  675. var index = element._inPhysicUpdateListIndex;
  676. if (index !== -1)
  677. throw "PhysicsUpdateList:element has in PhysicsUpdateList.";
  678. this._add(element);
  679. element._inPhysicUpdateListIndex = this.length++;
  680. }
  681. remove(element) {
  682. var index = element._inPhysicUpdateListIndex;
  683. this.length--;
  684. if (index !== this.length) {
  685. var end = this.elements[this.length];
  686. this.elements[index] = end;
  687. end._inPhysicUpdateListIndex = index;
  688. }
  689. element._inPhysicUpdateListIndex = -1;
  690. }
  691. }
  692. class CannonPhysicsSimulation {
  693. constructor(configuration, flags = 0) {
  694. this._gravity = new Laya.Vector3(0, -10, 0);
  695. this._btClosestRayResultCallback = new CANNON.RaycastResult();
  696. this._btRayoption = {};
  697. this._collisionsUtils = new CannonCollisionTool();
  698. this._previousFrameCollisions = [];
  699. this._currentFrameCollisions = [];
  700. this._physicsUpdateList = new CannonPhysicsUpdateList();
  701. this._updatedRigidbodies = 0;
  702. this.maxSubSteps = 1;
  703. this.fixedTimeStep = 1.0 / 60.0;
  704. this.maxSubSteps = configuration.maxSubSteps;
  705. this.fixedTimeStep = configuration.fixedTimeStep;
  706. this._btDiscreteDynamicsWorld = new CANNON.World();
  707. this._btBroadphase = new CANNON.NaiveBroadphase();
  708. this._btDiscreteDynamicsWorld.broadphase = this._btBroadphase;
  709. this._btDiscreteDynamicsWorld.defaultContactMaterial.contactEquationRelaxation = configuration.contactEquationRelaxation;
  710. this._btDiscreteDynamicsWorld.defaultContactMaterial.contactEquationStiffness = configuration.contactEquationStiffness;
  711. this.gravity = this._gravity;
  712. }
  713. static __init__() {
  714. CannonPhysicsSimulation._btTempVector30 = new CANNON.Vec3(0, 0, 0);
  715. CannonPhysicsSimulation._btTempVector31 = new CANNON.Vec3(0, 0, 0);
  716. }
  717. static createConstraint() {
  718. }
  719. get continuousCollisionDetection() {
  720. return false;
  721. }
  722. set continuousCollisionDetection(value) {
  723. throw "Simulation:Cannon physical engine does not support this feature";
  724. }
  725. get gravity() {
  726. if (!this._btDiscreteDynamicsWorld)
  727. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  728. return this._gravity;
  729. }
  730. set gravity(value) {
  731. if (!this._btDiscreteDynamicsWorld)
  732. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  733. this._gravity = value;
  734. this._btDiscreteDynamicsWorld.gravity.set(value.x, value.y, value.z);
  735. }
  736. get solverIterations() {
  737. if (!(this._btDiscreteDynamicsWorld && this._btDiscreteDynamicsWorld.solver))
  738. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  739. return this._iterations;
  740. }
  741. set solverIterations(value) {
  742. if (!(this._btDiscreteDynamicsWorld && this._btDiscreteDynamicsWorld.solver))
  743. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  744. this._btDiscreteDynamicsWorld.solver.iterations = value;
  745. this._iterations = value;
  746. }
  747. get speculativeContactRestitution() {
  748. return false;
  749. }
  750. set speculativeContactRestitution(value) {
  751. }
  752. _simulate(deltaTime) {
  753. this._updatedRigidbodies = 0;
  754. if (this._btDiscreteDynamicsWorld) {
  755. this._btDiscreteDynamicsWorld.callBackBody.length = 0;
  756. this._btDiscreteDynamicsWorld.allContacts.length = 0;
  757. this._btDiscreteDynamicsWorld.step(this.fixedTimeStep, deltaTime, this.maxSubSteps);
  758. }
  759. var callBackBody = this._btDiscreteDynamicsWorld.callBackBody;
  760. for (var i = 0, n = callBackBody.length; i < n; i++) {
  761. var cannonBody = callBackBody[i];
  762. var rigidbody = CannonPhysicsComponent._physicObjectsMap[cannonBody.layaID];
  763. rigidbody._simulation._updatedRigidbodies++;
  764. rigidbody._updateTransformComponent(rigidbody._btColliderObject);
  765. }
  766. }
  767. _destroy() {
  768. this._btDiscreteDynamicsWorld = null;
  769. this._btBroadphase = null;
  770. }
  771. _addPhysicsCollider(component) {
  772. this._btDiscreteDynamicsWorld.addBody(component._btColliderObject);
  773. }
  774. _removePhysicsCollider(component) {
  775. this._btDiscreteDynamicsWorld.removeBody(component._btColliderObject);
  776. }
  777. _addRigidBody(rigidBody) {
  778. if (!this._btDiscreteDynamicsWorld)
  779. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  780. this._btDiscreteDynamicsWorld.addBody(rigidBody._btColliderObject);
  781. }
  782. _removeRigidBody(rigidBody) {
  783. if (!this._btDiscreteDynamicsWorld)
  784. throw "Simulation:Cannot perform this action when the physics engine is set to CollisionsOnly";
  785. this._btDiscreteDynamicsWorld.removeBody(rigidBody._btColliderObject);
  786. }
  787. raycastFromTo(from, to, out = null, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  788. var rayResultCall = this._btClosestRayResultCallback;
  789. rayResultCall.hasHit = false;
  790. var rayOptions = this._btRayoption;
  791. var rayFrom = CannonPhysicsSimulation._btTempVector30;
  792. var rayTo = CannonPhysicsSimulation._btTempVector31;
  793. rayFrom.set(from.x, from.y, from.z);
  794. rayTo.set(to.x, to.y, to.z);
  795. rayOptions.skipBackfaces = true;
  796. rayOptions.collisionFilterMask = collisionMask;
  797. rayOptions.collisionFilterGroup = collisonGroup;
  798. rayOptions.result = rayResultCall;
  799. this._btDiscreteDynamicsWorld.raycastClosest(rayFrom, rayTo, rayOptions, rayResultCall);
  800. if (rayResultCall.hasHit) {
  801. if (out) {
  802. out.succeeded = true;
  803. out.collider = CannonPhysicsComponent._physicObjectsMap[rayResultCall.body.layaID];
  804. var point = out.point;
  805. var normal = out.normal;
  806. var resultPoint = rayResultCall.hitPointWorld;
  807. var resultNormal = rayResultCall.hitNormalWorld;
  808. point.setValue(resultPoint.x, resultPoint.y, resultPoint.z);
  809. normal.setValue(resultNormal.x, resultNormal.y, resultNormal.z);
  810. }
  811. return true;
  812. }
  813. else {
  814. out.succeeded = false;
  815. }
  816. return false;
  817. }
  818. raycastAllFromTo(from, to, out, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  819. var rayOptions = this._btRayoption;
  820. var rayFrom = CannonPhysicsSimulation._btTempVector30;
  821. var rayTo = CannonPhysicsSimulation._btTempVector31;
  822. rayFrom.set(from.x, from.y, from.z);
  823. rayTo.set(to.x, to.y, to.z);
  824. rayOptions.skipBackfaces = true;
  825. rayOptions.collisionFilterMask = collisionMask;
  826. rayOptions.collisionFilterGroup = collisonGroup;
  827. out.length = 0;
  828. this._btDiscreteDynamicsWorld.raycastAll(rayFrom, rayTo, rayOptions, function (result) {
  829. var hitResult = this._collisionsUtils.getHitResult();
  830. out.push(hitResult);
  831. hitResult.succeeded = true;
  832. hitResult.collider = CannonPhysicsComponent._physicObjectsMap[result.body.layaID];
  833. var point = hitResult.point;
  834. var normal = hitResult.normal;
  835. var resultPoint = result.hitPointWorld;
  836. var resultNormal = result.hitNormalWorld;
  837. point.setValue(resultPoint.x, resultPoint.y, resultPoint.z);
  838. normal.setValue(resultNormal.x, resultNormal.y, resultNormal.z);
  839. });
  840. if (out.length != 0)
  841. return true;
  842. else
  843. return false;
  844. }
  845. rayCast(ray, outHitResult = null, distance = 2147483647, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  846. var from = ray.origin;
  847. var to = CannonPhysicsSimulation._tempVector30;
  848. Laya.Vector3.normalize(ray.direction, to);
  849. Laya.Vector3.scale(to, distance, to);
  850. Laya.Vector3.add(from, to, to);
  851. return this.raycastFromTo(from, to, outHitResult, collisonGroup, collisionMask);
  852. }
  853. rayCastAll(ray, out, distance = 2147483647, collisonGroup = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER, collisionMask = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  854. var from = ray.origin;
  855. var to = CannonPhysicsSimulation._tempVector30;
  856. Laya.Vector3.normalize(ray.direction, to);
  857. Laya.Vector3.scale(to, distance, to);
  858. Laya.Vector3.add(from, to, to);
  859. return this.raycastAllFromTo(from, to, out, collisonGroup, collisionMask);
  860. }
  861. _updatePhysicsTransformFromRender() {
  862. var elements = this._physicsUpdateList.elements;
  863. for (var i = 0, n = this._physicsUpdateList.length; i < n; i++) {
  864. var physicCollider = elements[i];
  865. physicCollider._derivePhysicsTransformation(false);
  866. physicCollider._inPhysicUpdateListIndex = -1;
  867. }
  868. this._physicsUpdateList.length = 0;
  869. }
  870. _updateCollisions() {
  871. this._collisionsUtils.recoverAllContactPointsPool();
  872. var previous = this._currentFrameCollisions;
  873. this._currentFrameCollisions = this._previousFrameCollisions;
  874. this._currentFrameCollisions.length = 0;
  875. this._previousFrameCollisions = previous;
  876. var loopCount = Laya.Stat.loopCount;
  877. var allContacts = this._btDiscreteDynamicsWorld.allContacts;
  878. var numManifolds = allContacts.length;
  879. for (var i = 0; i < numManifolds; i++) {
  880. var contactEquation = allContacts[i];
  881. var componentA = CannonPhysicsComponent._physicObjectsMap[contactEquation.bi.layaID];
  882. var componentB = CannonPhysicsComponent._physicObjectsMap[contactEquation.bj.layaID];
  883. var collision = null;
  884. var isFirstCollision;
  885. var contacts = null;
  886. var isTrigger = componentA.isTrigger || componentB.isTrigger;
  887. if (isTrigger && (componentA.owner._needProcessTriggers || componentB.owner._needProcessTriggers)) {
  888. collision = this._collisionsUtils.getCollision(componentA, componentB);
  889. contacts = collision.contacts;
  890. isFirstCollision = collision._updateFrame !== loopCount;
  891. if (isFirstCollision) {
  892. collision._isTrigger = true;
  893. contacts.length = 0;
  894. }
  895. }
  896. else if (componentA.owner._needProcessCollisions || componentB.owner._needProcessCollisions) {
  897. if (componentA._enableProcessCollisions || componentB._enableProcessCollisions) {
  898. var contactPoint = this._collisionsUtils.getContactPoints();
  899. contactPoint.colliderA = componentA;
  900. contactPoint.colliderB = componentB;
  901. var normal = contactPoint.normal;
  902. var positionOnA = contactPoint.positionOnA;
  903. var positionOnB = contactPoint.positionOnB;
  904. var connectNormal = contactEquation.ni;
  905. var connectOnA = contactEquation.ri;
  906. var connectOnB = contactEquation.rj;
  907. normal.setValue(connectNormal.x, connectNormal.y, connectNormal.z);
  908. positionOnA.setValue(connectOnA.x, connectOnA.y, connectOnA.z);
  909. positionOnB.setValue(connectOnB.x, connectOnB.y, -connectOnB.z);
  910. collision = this._collisionsUtils.getCollision(componentA, componentB);
  911. contacts = collision.contacts;
  912. isFirstCollision = collision._updateFrame !== loopCount;
  913. if (isFirstCollision) {
  914. collision._isTrigger = false;
  915. contacts.length = 0;
  916. }
  917. contacts.push(contactPoint);
  918. }
  919. }
  920. if (collision && isFirstCollision) {
  921. this._currentFrameCollisions.push(collision);
  922. collision._setUpdateFrame(loopCount);
  923. }
  924. }
  925. }
  926. _eventScripts() {
  927. var loopCount = Laya.Stat.loopCount;
  928. for (var i = 0, n = this._currentFrameCollisions.length; i < n; i++) {
  929. var curFrameCol = this._currentFrameCollisions[i];
  930. var colliderA = curFrameCol._colliderA;
  931. var colliderB = curFrameCol._colliderB;
  932. if (colliderA.destroyed || colliderB.destroyed)
  933. continue;
  934. if (loopCount - curFrameCol._lastUpdateFrame === 1) {
  935. var ownerA = colliderA.owner;
  936. var scriptsA = ownerA._scripts;
  937. if (scriptsA) {
  938. if (curFrameCol._isTrigger) {
  939. if (ownerA._needProcessTriggers) {
  940. for (var j = 0, m = scriptsA.length; j < m; j++)
  941. scriptsA[j].onTriggerStay(colliderB);
  942. }
  943. }
  944. else {
  945. if (ownerA._needProcessCollisions) {
  946. for (j = 0, m = scriptsA.length; j < m; j++) {
  947. curFrameCol.other = colliderB;
  948. scriptsA[j].onCollisionStay(curFrameCol);
  949. }
  950. }
  951. }
  952. }
  953. var ownerB = colliderB.owner;
  954. var scriptsB = ownerB._scripts;
  955. if (scriptsB) {
  956. if (curFrameCol._isTrigger) {
  957. if (ownerB._needProcessTriggers) {
  958. for (j = 0, m = scriptsB.length; j < m; j++)
  959. scriptsB[j].onTriggerStay(colliderA);
  960. }
  961. }
  962. else {
  963. if (ownerB._needProcessCollisions) {
  964. for (j = 0, m = scriptsB.length; j < m; j++) {
  965. curFrameCol.other = colliderA;
  966. scriptsB[j].onCollisionStay(curFrameCol);
  967. }
  968. }
  969. }
  970. }
  971. }
  972. else {
  973. ownerA = colliderA.owner;
  974. scriptsA = ownerA._scripts;
  975. if (scriptsA) {
  976. if (curFrameCol._isTrigger) {
  977. if (ownerA._needProcessTriggers) {
  978. for (j = 0, m = scriptsA.length; j < m; j++)
  979. scriptsA[j].onTriggerEnter(colliderB);
  980. }
  981. }
  982. else {
  983. if (ownerA._needProcessCollisions) {
  984. for (j = 0, m = scriptsA.length; j < m; j++) {
  985. curFrameCol.other = colliderB;
  986. scriptsA[j].onCollisionEnter(curFrameCol);
  987. }
  988. }
  989. }
  990. }
  991. ownerB = colliderB.owner;
  992. scriptsB = ownerB._scripts;
  993. if (scriptsB) {
  994. if (curFrameCol._isTrigger) {
  995. if (ownerB._needProcessTriggers) {
  996. for (j = 0, m = scriptsB.length; j < m; j++)
  997. scriptsB[j].onTriggerEnter(colliderA);
  998. }
  999. }
  1000. else {
  1001. if (ownerB._needProcessCollisions) {
  1002. for (j = 0, m = scriptsB.length; j < m; j++) {
  1003. curFrameCol.other = colliderA;
  1004. scriptsB[j].onCollisionEnter(curFrameCol);
  1005. }
  1006. }
  1007. }
  1008. }
  1009. }
  1010. }
  1011. for (i = 0, n = this._previousFrameCollisions.length; i < n; i++) {
  1012. var preFrameCol = this._previousFrameCollisions[i];
  1013. var preColliderA = preFrameCol._colliderA;
  1014. var preColliderB = preFrameCol._colliderB;
  1015. if (preColliderA.destroyed || preColliderB.destroyed)
  1016. continue;
  1017. if (loopCount - preFrameCol._updateFrame === 1) {
  1018. this._collisionsUtils.recoverCollision(preFrameCol);
  1019. ownerA = preColliderA.owner;
  1020. scriptsA = ownerA._scripts;
  1021. if (scriptsA) {
  1022. if (preFrameCol._isTrigger) {
  1023. if (ownerA._needProcessTriggers) {
  1024. for (j = 0, m = scriptsA.length; j < m; j++)
  1025. scriptsA[j].onTriggerExit(preColliderB);
  1026. }
  1027. }
  1028. else {
  1029. if (ownerA._needProcessCollisions) {
  1030. for (j = 0, m = scriptsA.length; j < m; j++) {
  1031. preFrameCol.other = preColliderB;
  1032. scriptsA[j].onCollisionExit(preFrameCol);
  1033. }
  1034. }
  1035. }
  1036. }
  1037. ownerB = preColliderB.owner;
  1038. scriptsB = ownerB._scripts;
  1039. if (scriptsB) {
  1040. if (preFrameCol._isTrigger) {
  1041. if (ownerB._needProcessTriggers) {
  1042. for (j = 0, m = scriptsB.length; j < m; j++)
  1043. scriptsB[j].onTriggerExit(preColliderA);
  1044. }
  1045. }
  1046. else {
  1047. if (ownerB._needProcessCollisions) {
  1048. for (j = 0, m = scriptsB.length; j < m; j++) {
  1049. preFrameCol.other = preColliderA;
  1050. scriptsB[j].onCollisionExit(preFrameCol);
  1051. }
  1052. }
  1053. }
  1054. }
  1055. }
  1056. }
  1057. }
  1058. clearForces() {
  1059. if (!this._btDiscreteDynamicsWorld)
  1060. throw "Cannot perform this action when the physics engine is set to CollisionsOnly";
  1061. }
  1062. }
  1063. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_NONE = 0x0;
  1064. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_COLLISIONSONLY = 0x1;
  1065. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_SOFTBODYSUPPORT = 0x2;
  1066. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_MULTITHREADED = 0x4;
  1067. CannonPhysicsSimulation.PHYSICSENGINEFLAGS_USEHARDWAREWHENPOSSIBLE = 0x8;
  1068. CannonPhysicsSimulation.SOLVERMODE_RANDMIZE_ORDER = 1;
  1069. CannonPhysicsSimulation.SOLVERMODE_FRICTION_SEPARATE = 2;
  1070. CannonPhysicsSimulation.SOLVERMODE_USE_WARMSTARTING = 4;
  1071. CannonPhysicsSimulation.SOLVERMODE_USE_2_FRICTION_DIRECTIONS = 16;
  1072. CannonPhysicsSimulation.SOLVERMODE_ENABLE_FRICTION_DIRECTION_CACHING = 32;
  1073. CannonPhysicsSimulation.SOLVERMODE_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64;
  1074. CannonPhysicsSimulation.SOLVERMODE_CACHE_FRIENDLY = 128;
  1075. CannonPhysicsSimulation.SOLVERMODE_SIMD = 256;
  1076. CannonPhysicsSimulation.SOLVERMODE_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512;
  1077. CannonPhysicsSimulation.SOLVERMODE_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024;
  1078. CannonPhysicsSimulation._tempVector30 = new Laya.Vector3();
  1079. CannonPhysicsSimulation.disableSimulation = false;
  1080. class CannonRigidbody3D extends CannonPhysicsCollider {
  1081. constructor(collisionGroup = -1, canCollideWith = Laya.Physics3DUtils.COLLISIONFILTERGROUP_ALLFILTER) {
  1082. super(collisionGroup, canCollideWith);
  1083. this._isKinematic = false;
  1084. this._mass = 1.0;
  1085. this._gravity = new Laya.Vector3(0, -10, 0);
  1086. this._angularDamping = 0.0;
  1087. this._linearDamping = 0.0;
  1088. this._totalTorque = new Laya.Vector3(0, 0, 0);
  1089. this._totalForce = new Laya.Vector3(0, 0, 0);
  1090. this._linearVelocity = new Laya.Vector3();
  1091. this._angularVelocity = new Laya.Vector3();
  1092. this._controlBySimulation = true;
  1093. }
  1094. static __init__() {
  1095. CannonRigidbody3D._btTempVector30 = new CANNON.Vec3();
  1096. CannonRigidbody3D._btTempVector31 = new CANNON.Vec3();
  1097. }
  1098. get mass() {
  1099. return this._mass;
  1100. }
  1101. set mass(value) {
  1102. value = Math.max(value, 1e-07);
  1103. this._mass = value;
  1104. (this._isKinematic) || (this._updateMass(value));
  1105. }
  1106. get isKinematic() {
  1107. return this._isKinematic;
  1108. }
  1109. set isKinematic(value) {
  1110. this._isKinematic = value;
  1111. this._controlBySimulation = !value;
  1112. var canInSimulation = !!(this._simulation && this._enabled && this._colliderShape);
  1113. canInSimulation && this._removeFromSimulation();
  1114. var natColObj = this._btColliderObject;
  1115. var flags = natColObj.type;
  1116. if (value) {
  1117. flags = flags | CANNON.Body.KINEMATIC;
  1118. natColObj.type = flags;
  1119. this._enableProcessCollisions = false;
  1120. this._updateMass(0);
  1121. }
  1122. else {
  1123. if ((flags & CANNON.Body.KINEMATIC) > 0)
  1124. flags = flags ^ CANNON.Body.KINEMATIC;
  1125. natColObj.allowSleep = true;
  1126. natColObj.type = flags;
  1127. this._enableProcessCollisions = true;
  1128. this._updateMass(this._mass);
  1129. }
  1130. natColObj.velocity.set(0.0, 0.0, 0.0);
  1131. natColObj.angularVelocity.set(0.0, 0.0, 0.0);
  1132. canInSimulation && this._addToSimulation();
  1133. }
  1134. get linearDamping() {
  1135. return this._linearDamping;
  1136. }
  1137. set linearDamping(value) {
  1138. this._linearDamping = value;
  1139. if (this._btColliderObject)
  1140. this._btColliderObject.linearDamping = value;
  1141. }
  1142. get angularDamping() {
  1143. return this._angularDamping;
  1144. }
  1145. set angularDamping(value) {
  1146. this._angularDamping = value;
  1147. if (this._btColliderObject)
  1148. this._btColliderObject.angularDamping = value;
  1149. }
  1150. get totalForce() {
  1151. if (this._btColliderObject) {
  1152. var btTotalForce = this.btColliderObject.force;
  1153. this.totalForce.setValue(btTotalForce.x, btTotalForce.y, btTotalForce.z);
  1154. return this._totalForce;
  1155. }
  1156. return null;
  1157. }
  1158. get linearVelocity() {
  1159. if (this._btColliderObject) {
  1160. var phylinear = this.btColliderObject.velocity;
  1161. this._linearVelocity.setValue(phylinear.x, phylinear.y, phylinear.z);
  1162. }
  1163. return this._linearVelocity;
  1164. }
  1165. set linearVelocity(value) {
  1166. this._linearVelocity = value;
  1167. if (this._btColliderObject) {
  1168. var btValue = this.btColliderObject.velocity;
  1169. (this.isSleeping) && (this.wakeUp());
  1170. btValue.set(value.x, value.y, value.z);
  1171. this.btColliderObject.velocity = btValue;
  1172. }
  1173. }
  1174. get angularVelocity() {
  1175. if (this._btColliderObject) {
  1176. var phtqua = this._btColliderObject.angularVelocity;
  1177. this.angularVelocity.setValue(phtqua.x, phtqua.y, phtqua.z);
  1178. }
  1179. return this._angularVelocity;
  1180. }
  1181. set angularVelocity(value) {
  1182. this._angularVelocity = value;
  1183. if (this._btColliderObject) {
  1184. var btValue = this.btColliderObject.angularVelocity;
  1185. (this.isSleeping) && (this.wakeUp());
  1186. btValue.set(value.x, value.y, value.z);
  1187. this.btColliderObject.angularVelocity = btValue;
  1188. }
  1189. }
  1190. get totalTorque() {
  1191. if (this._btColliderObject) {
  1192. var btTotalTorque = this._btColliderObject.torque;
  1193. this._totalTorque.setValue(btTotalTorque.x, btTotalTorque.y, btTotalTorque.z);
  1194. return this._totalTorque;
  1195. }
  1196. return null;
  1197. }
  1198. get isSleeping() {
  1199. if (this._btColliderObject)
  1200. return this._btColliderObject.sleepState != CANNON.Body.AWAKE;
  1201. return false;
  1202. }
  1203. get sleepLinearVelocity() {
  1204. return this._btColliderObject.sleepSpeedLimit;
  1205. }
  1206. set sleepLinearVelocity(value) {
  1207. this._btColliderObject.sleepSpeedLimit = value;
  1208. }
  1209. get btColliderObject() {
  1210. return this._btColliderObject;
  1211. }
  1212. _updateMass(mass) {
  1213. if (this._btColliderObject && this._colliderShape) {
  1214. this._btColliderObject.mass = mass;
  1215. this._btColliderObject.updateMassProperties();
  1216. this._btColliderObject.updateSolveMassProperties();
  1217. }
  1218. }
  1219. _onScaleChange(scale) {
  1220. super._onScaleChange(scale);
  1221. this._updateMass(this._isKinematic ? 0 : this._mass);
  1222. }
  1223. _derivePhysicsTransformation(force) {
  1224. this._innerDerivePhysicsTransformation(this.btColliderObject, force);
  1225. }
  1226. _onAdded() {
  1227. var btRigid = new CANNON.Body();
  1228. btRigid.material = new CANNON.Material();
  1229. btRigid.layaID = this.id;
  1230. btRigid.collisionFilterGroup = this.collisionGroup;
  1231. btRigid.collisionFilterMask = this._canCollideWith;
  1232. this._btColliderObject = btRigid;
  1233. super._onAdded();
  1234. this.mass = this._mass;
  1235. this.linearDamping = this._linearDamping;
  1236. this.angularDamping = this._angularDamping;
  1237. this.isKinematic = this._isKinematic;
  1238. if (!this.isKinematic)
  1239. this._btColliderObject.type = CANNON.Body.DYNAMIC;
  1240. else
  1241. this._btColliderObject.type = CANNON.Body.KINEMATIC;
  1242. }
  1243. _onShapeChange(colShape) {
  1244. super._onShapeChange(colShape);
  1245. if (this._isKinematic) {
  1246. this._updateMass(0);
  1247. }
  1248. else {
  1249. this._updateMass(this._mass);
  1250. }
  1251. }
  1252. _parse(data) {
  1253. (data.friction != null) && (this.friction = data.friction);
  1254. (data.restitution != null) && (this.restitution = data.restitution);
  1255. (data.isTrigger != null) && (this.isTrigger = data.isTrigger);
  1256. (data.mass != null) && (this.mass = data.mass);
  1257. (data.isKinematic != null) && (this.isKinematic = data.isKinematic);
  1258. (data.linearDamping != null) && (this.linearDamping = data.linearDamping);
  1259. (data.angularDamping != null) && (this.angularDamping = data.angularDamping);
  1260. super._parse(data);
  1261. this._parseShape(data.shapes);
  1262. }
  1263. _onDestroy() {
  1264. super._onDestroy();
  1265. this._gravity = null;
  1266. this._totalTorque = null;
  1267. this._linearVelocity = null;
  1268. this._angularVelocity = null;
  1269. }
  1270. _addToSimulation() {
  1271. this._simulation._addRigidBody(this);
  1272. }
  1273. _removeFromSimulation() {
  1274. this._simulation._removeRigidBody(this);
  1275. }
  1276. _cloneTo(dest) {
  1277. super._cloneTo(dest);
  1278. var destRigidbody3D = dest;
  1279. destRigidbody3D.isKinematic = this._isKinematic;
  1280. destRigidbody3D.mass = this._mass;
  1281. destRigidbody3D.angularDamping = this._angularDamping;
  1282. destRigidbody3D.linearDamping = this._linearDamping;
  1283. destRigidbody3D.linearVelocity = this._linearVelocity;
  1284. destRigidbody3D.angularVelocity = this._angularVelocity;
  1285. }
  1286. applyForce(force, localOffset = null) {
  1287. if (this._btColliderObject == null)
  1288. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1289. var btForce = CannonRigidbody3D._btTempVector30;
  1290. btForce.set(force.x, force.y, force.z);
  1291. var btOffset = CannonRigidbody3D._btTempVector31;
  1292. if (localOffset)
  1293. btOffset.set(localOffset.x, localOffset.y, localOffset.z);
  1294. else
  1295. btOffset.set(0.0, 0.0, 0.0);
  1296. this.btColliderObject.applyLocalForce(btForce, btOffset);
  1297. }
  1298. applyTorque(torque) {
  1299. if (this._btColliderObject == null)
  1300. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1301. var btTorque = CannonRigidbody3D._btTempVector30;
  1302. btTorque.set(torque.x, torque.y, torque.z);
  1303. var oriTorque = this.btColliderObject.torque;
  1304. oriTorque.set(oriTorque.x + btTorque.x, oriTorque.y + btTorque.y, oriTorque.z + btTorque.z);
  1305. this.btColliderObject.torque = oriTorque;
  1306. }
  1307. applyImpulse(impulse, localOffset = null) {
  1308. if (this._btColliderObject == null)
  1309. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1310. if (this._btColliderObject == null)
  1311. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1312. var btForce = CannonRigidbody3D._btTempVector30;
  1313. btForce.set(impulse.x, impulse.y, impulse.z);
  1314. var btOffset = CannonRigidbody3D._btTempVector31;
  1315. if (localOffset)
  1316. btOffset.set(localOffset.x, localOffset.y, localOffset.z);
  1317. else
  1318. btOffset.set(0.0, 0.0, 0.0);
  1319. this.btColliderObject.applyImpulse(btForce, btOffset);
  1320. }
  1321. wakeUp() {
  1322. this._btColliderObject && this._btColliderObject.wakeUp();
  1323. }
  1324. clearForces() {
  1325. var rigidBody = this._btColliderObject;
  1326. if (rigidBody == null)
  1327. throw "Attempted to call a Physics function that is avaliable only when the Entity has been already added to the Scene.";
  1328. rigidBody.velocity.set(0.0, 0.0, 0.0);
  1329. rigidBody.velocity = rigidBody.velocity;
  1330. rigidBody.angularVelocity.set(0.0, 0.0, 0.0);
  1331. rigidBody.angularVelocity = rigidBody.angularVelocity;
  1332. }
  1333. }
  1334. CannonRigidbody3D.TYPE_STATIC = 0;
  1335. CannonRigidbody3D.TYPE_DYNAMIC = 1;
  1336. CannonRigidbody3D.TYPE_KINEMATIC = 2;
  1337. CannonRigidbody3D._BT_DISABLE_WORLD_GRAVITY = 1;
  1338. CannonRigidbody3D._BT_ENABLE_GYROPSCOPIC_FORCE = 2;
  1339. class CannonCompoundColliderShape extends CannonColliderShape {
  1340. constructor() {
  1341. super();
  1342. this._childColliderShapes = [];
  1343. this._type = CannonColliderShape.SHAPETYPES_COMPOUND;
  1344. }
  1345. static __init__() {
  1346. }
  1347. _clearChildShape(shape) {
  1348. shape._attatched = false;
  1349. shape._compoundParent = null;
  1350. shape._indexInCompound = -1;
  1351. }
  1352. _addReference() {
  1353. this._referenceCount++;
  1354. }
  1355. _removeReference() {
  1356. this._referenceCount--;
  1357. }
  1358. addChildShape(shape, localOffset = null) {
  1359. if (shape._attatched)
  1360. throw "CompoundColliderShape: this shape has attatched to other entity.";
  1361. shape._attatched = true;
  1362. shape._compoundParent = this;
  1363. shape._indexInCompound = this._childColliderShapes.length;
  1364. this._childColliderShapes.push(shape);
  1365. shape.localOffset = localOffset;
  1366. if (this.physicColliderObject) {
  1367. CannonCompoundColliderShape._tempCannonQue.set(0, 0, 0, 1);
  1368. CannonCompoundColliderShape._tempCannonVec.set(localOffset.x * this._scale.x, localOffset.y * this._scale.y, localOffset.z * this._scale.z);
  1369. this.physicColliderObject._btColliderObject.addShape(shape._btShape, CannonCompoundColliderShape._tempCannonVec, CANNON.Vec3.ZERO);
  1370. }
  1371. }
  1372. removeChildShape(shape) {
  1373. if (shape._compoundParent === this) {
  1374. var index = shape._indexInCompound;
  1375. this._clearChildShape(shape);
  1376. var endShape = this._childColliderShapes[this._childColliderShapes.length - 1];
  1377. endShape._indexInCompound = index;
  1378. this._childColliderShapes[index] = endShape;
  1379. this._childColliderShapes.pop();
  1380. if (this.physicColliderObject)
  1381. this.bindRigidBody(this.physicColliderObject);
  1382. }
  1383. }
  1384. bindRigidBody(rigidbody) {
  1385. this.physicColliderObject = rigidbody;
  1386. var body = rigidbody._btColliderObject;
  1387. body.shapes.length = 0;
  1388. body.shapeOffsets.length = 0;
  1389. body.shapeOrientations.length = 0;
  1390. var origoffset;
  1391. for (var i = 0, n = this._childColliderShapes.length; i != n; i++) {
  1392. var shape = this._childColliderShapes[i];
  1393. body.shapes.push(shape._btShape);
  1394. origoffset = shape.localOffset;
  1395. body.shapeOffsets.push(new CANNON.Vec3(origoffset.x * this._scale.x, origoffset.y * this._scale.y, origoffset.z * this._scale.z));
  1396. body.shapeOrientations.push(CannonCompoundColliderShape._tempCannonQue);
  1397. }
  1398. body.updateMassProperties();
  1399. body.updateBoundingRadius();
  1400. body.aabbNeedsUpdate = true;
  1401. }
  1402. _setScale(scale) {
  1403. this._scale.setValue(scale.x, scale.y, scale.z);
  1404. var body = this.physicColliderObject._btColliderObject;
  1405. var length = this.getChildShapeCount();
  1406. var shapeoffsets = body.shapeOffsets;
  1407. for (var i = 0; i < length; i++) {
  1408. var offset = shapeoffsets[i];
  1409. var shape = this._childColliderShapes[i];
  1410. shape._setScale(scale);
  1411. var orioffset = shape.localOffset;
  1412. offset.set(orioffset.x * scale.x, orioffset.y * scale.y, orioffset.z * scale.z);
  1413. }
  1414. body.updateMassProperties();
  1415. body.updateBoundingRadius();
  1416. body.aabbNeedsUpdate = true;
  1417. }
  1418. getChildShapeCount() {
  1419. return this._childColliderShapes.length;
  1420. }
  1421. cloneTo(destObject) {
  1422. var destCompoundColliderShape = destObject;
  1423. for (var i = 0, n = this._childColliderShapes.length; i < n; i++)
  1424. destCompoundColliderShape.addChildShape(this._childColliderShapes[i].clone());
  1425. }
  1426. clone() {
  1427. var dest = new CannonCompoundColliderShape();
  1428. this.cloneTo(dest);
  1429. return dest;
  1430. }
  1431. destroy() {
  1432. super.destroy();
  1433. for (var i = 0, n = this._childColliderShapes.length; i < n; i++) {
  1434. var childShape = this._childColliderShapes[i];
  1435. if (childShape._referenceCount === 0)
  1436. childShape.destroy();
  1437. }
  1438. }
  1439. }
  1440. CannonCompoundColliderShape._tempCannonQue = new CANNON.Quaternion(0, 0, 0, 1);
  1441. CannonCompoundColliderShape._tempCannonVec = new CANNON.Vec3(0, 0, 0);
  1442. exports.CannonBoxColliderShape = CannonBoxColliderShape;
  1443. exports.CannonColliderShape = CannonColliderShape;
  1444. exports.CannonCollision = CannonCollision;
  1445. exports.CannonCollisionTool = CannonCollisionTool;
  1446. exports.CannonCompoundColliderShape = CannonCompoundColliderShape;
  1447. exports.CannonContactPoint = CannonContactPoint;
  1448. exports.CannonHitResult = CannonHitResult;
  1449. exports.CannonPhysicsCollider = CannonPhysicsCollider;
  1450. exports.CannonPhysicsComponent = CannonPhysicsComponent;
  1451. exports.CannonPhysicsSettings = CannonPhysicsSettings;
  1452. exports.CannonPhysicsSimulation = CannonPhysicsSimulation;
  1453. exports.CannonPhysicsTriggerComponent = CannonPhysicsTriggerComponent;
  1454. exports.CannonPhysicsUpdateList = CannonPhysicsUpdateList;
  1455. exports.CannonRigidbody3D = CannonRigidbody3D;
  1456. exports.CannonSphereColliderShape = CannonSphereColliderShape;
  1457. }(window.Laya = window.Laya || {}, Laya));