babylon.physicsImpostor.ts 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. module BABYLON {
  2. export interface PhysicsImpostorParameters {
  3. mass: number;
  4. friction?: number;
  5. restitution?: number;
  6. nativeOptions?: any;
  7. ignoreParent?: boolean;
  8. disableBidirectionalTransformation?: boolean;
  9. }
  10. export interface IPhysicsEnabledObject {
  11. position: Vector3;
  12. rotationQuaternion: Nullable<Quaternion>;
  13. scaling: Vector3;
  14. rotation?: Vector3;
  15. parent?: any;
  16. getBoundingInfo(): BoundingInfo;
  17. computeWorldMatrix(force: boolean): Matrix;
  18. getWorldMatrix?(): Matrix;
  19. getChildMeshes?(directDescendantsOnly?: boolean): Array<AbstractMesh>;
  20. getVerticesData(kind: string): Nullable<Array<number> | Float32Array>;
  21. getIndices?(): Nullable<IndicesArray>;
  22. getScene?(): Scene;
  23. getAbsolutePosition(): Vector3;
  24. getAbsolutePivotPoint(): Vector3;
  25. rotate(axis: Vector3, amount: number, space?: Space): TransformNode;
  26. translate(axis: Vector3, distance: number, space?: Space): TransformNode;
  27. setAbsolutePosition(absolutePosition: Vector3): TransformNode;
  28. getClassName(): string;
  29. }
  30. export class PhysicsImpostor {
  31. public static DEFAULT_OBJECT_SIZE: Vector3 = new Vector3(1, 1, 1);
  32. public static IDENTITY_QUATERNION = Quaternion.Identity();
  33. private _physicsEngine: Nullable<PhysicsEngine>;
  34. //The native cannon/oimo/energy physics body object.
  35. private _physicsBody: any;
  36. private _bodyUpdateRequired: boolean = false;
  37. private _onBeforePhysicsStepCallbacks = new Array<(impostor: PhysicsImpostor) => void>();
  38. private _onAfterPhysicsStepCallbacks = new Array<(impostor: PhysicsImpostor) => void>();
  39. private _onPhysicsCollideCallbacks: Array<{ callback: (collider: PhysicsImpostor, collidedAgainst: PhysicsImpostor) => void, otherImpostors: Array<PhysicsImpostor> }> = []
  40. private _deltaPosition: Vector3 = Vector3.Zero();
  41. private _deltaRotation: Quaternion;
  42. private _deltaRotationConjugated: Quaternion;
  43. //If set, this is this impostor's parent
  44. private _parent: Nullable<PhysicsImpostor>;
  45. private _isDisposed = false;
  46. private static _tmpVecs: Vector3[] = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
  47. private static _tmpQuat: Quaternion = Quaternion.Identity();
  48. get isDisposed(): boolean {
  49. return this._isDisposed;
  50. }
  51. get mass(): number {
  52. return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getBodyMass(this) : 0;
  53. }
  54. set mass(value: number) {
  55. this.setMass(value);
  56. }
  57. get friction(): number {
  58. return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getBodyFriction(this) : 0;
  59. }
  60. set friction(value: number) {
  61. if (!this._physicsEngine) {
  62. return;
  63. }
  64. this._physicsEngine.getPhysicsPlugin().setBodyFriction(this, value);
  65. }
  66. get restitution(): number {
  67. return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getBodyRestitution(this) : 0;
  68. }
  69. set restitution(value: number) {
  70. if (!this._physicsEngine) {
  71. return;
  72. }
  73. this._physicsEngine.getPhysicsPlugin().setBodyRestitution(this, value);
  74. }
  75. //set by the physics engine when adding this impostor to the array.
  76. public uniqueId: number;
  77. private _joints: Array<{
  78. joint: PhysicsJoint,
  79. otherImpostor: PhysicsImpostor
  80. }>;
  81. constructor(public object: IPhysicsEnabledObject, public type: number, private _options: PhysicsImpostorParameters = { mass: 0 }, private _scene?: Scene) {
  82. //sanity check!
  83. if (!this.object) {
  84. Tools.Error("No object was provided. A physics object is obligatory");
  85. return;
  86. }
  87. //legacy support for old syntax.
  88. if (!this._scene && object.getScene) {
  89. this._scene = object.getScene()
  90. }
  91. if (!this._scene) {
  92. return;
  93. }
  94. this._physicsEngine = this._scene.getPhysicsEngine();
  95. if (!this._physicsEngine) {
  96. Tools.Error("Physics not enabled. Please use scene.enablePhysics(...) before creating impostors.")
  97. } else {
  98. //set the object's quaternion, if not set
  99. if (!this.object.rotationQuaternion) {
  100. if (this.object.rotation) {
  101. this.object.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.object.rotation.y, this.object.rotation.x, this.object.rotation.z);
  102. } else {
  103. this.object.rotationQuaternion = new Quaternion();
  104. }
  105. }
  106. //default options params
  107. this._options.mass = (_options.mass === void 0) ? 0 : _options.mass
  108. this._options.friction = (_options.friction === void 0) ? 0.2 : _options.friction
  109. this._options.restitution = (_options.restitution === void 0) ? 0.2 : _options.restitution
  110. this._joints = [];
  111. //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
  112. if (!this.object.parent || this._options.ignoreParent) {
  113. this._init();
  114. } else if (this.object.parent.physicsImpostor) {
  115. Tools.Warn("You must affect impostors to children before affecting impostor to parent.");
  116. }
  117. }
  118. }
  119. /**
  120. * This function will completly initialize this impostor.
  121. * It will create a new body - but only if this mesh has no parent.
  122. * If it has, this impostor will not be used other than to define the impostor
  123. * of the child mesh.
  124. */
  125. public _init() {
  126. if (!this._physicsEngine) {
  127. return;
  128. }
  129. this._physicsEngine.removeImpostor(this);
  130. this.physicsBody = null;
  131. this._parent = this._parent || this._getPhysicsParent();
  132. if (!this._isDisposed && (!this.parent || this._options.ignoreParent)) {
  133. this._physicsEngine.addImpostor(this);
  134. }
  135. }
  136. private _getPhysicsParent(): Nullable<PhysicsImpostor> {
  137. if (this.object.parent instanceof AbstractMesh) {
  138. var parentMesh: AbstractMesh = <AbstractMesh>this.object.parent;
  139. return parentMesh.physicsImpostor;
  140. }
  141. return null;
  142. }
  143. /**
  144. * Should a new body be generated.
  145. */
  146. public isBodyInitRequired(): boolean {
  147. return this._bodyUpdateRequired || (!this._physicsBody && !this._parent);
  148. }
  149. public setScalingUpdated(updated: boolean) {
  150. this.forceUpdate();
  151. }
  152. /**
  153. * Force a regeneration of this or the parent's impostor's body.
  154. * Use under cautious - This will remove all joints already implemented.
  155. */
  156. public forceUpdate() {
  157. this._init();
  158. if (this.parent && !this._options.ignoreParent) {
  159. this.parent.forceUpdate();
  160. }
  161. }
  162. /*public get mesh(): AbstractMesh {
  163. return this._mesh;
  164. }*/
  165. /**
  166. * Gets the body that holds this impostor. Either its own, or its parent.
  167. */
  168. public get physicsBody(): any {
  169. return (this._parent && !this._options.ignoreParent) ? this._parent.physicsBody : this._physicsBody;
  170. }
  171. public get parent(): Nullable<PhysicsImpostor> {
  172. return !this._options.ignoreParent && this._parent ? this._parent : null;
  173. }
  174. public set parent(value: Nullable<PhysicsImpostor>) {
  175. this._parent = value;
  176. }
  177. /**
  178. * Set the physics body. Used mainly by the physics engine/plugin
  179. */
  180. public set physicsBody(physicsBody: any) {
  181. if (this._physicsBody && this._physicsEngine) {
  182. this._physicsEngine.getPhysicsPlugin().removePhysicsBody(this);
  183. }
  184. this._physicsBody = physicsBody;
  185. this.resetUpdateFlags();
  186. }
  187. public resetUpdateFlags() {
  188. this._bodyUpdateRequired = false;
  189. }
  190. public getObjectExtendSize(): Vector3 {
  191. if (this.object.getBoundingInfo) {
  192. let q = this.object.rotationQuaternion;
  193. //reset rotation
  194. this.object.rotationQuaternion = PhysicsImpostor.IDENTITY_QUATERNION;
  195. //calculate the world matrix with no rotation
  196. this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
  197. let boundingInfo = this.object.getBoundingInfo();
  198. let size = boundingInfo.boundingBox.extendSizeWorld.scale(2)
  199. //bring back the rotation
  200. this.object.rotationQuaternion = q;
  201. //calculate the world matrix with the new rotation
  202. this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
  203. return size;
  204. } else {
  205. return PhysicsImpostor.DEFAULT_OBJECT_SIZE;
  206. }
  207. }
  208. public getObjectCenter(): Vector3 {
  209. if (this.object.getBoundingInfo) {
  210. let boundingInfo = this.object.getBoundingInfo();
  211. return boundingInfo.boundingBox.centerWorld;
  212. } else {
  213. return this.object.position;
  214. }
  215. }
  216. /**
  217. * Get a specific parametes from the options parameter.
  218. */
  219. public getParam(paramName: string) {
  220. return (<any>this._options)[paramName];
  221. }
  222. /**
  223. * Sets a specific parameter in the options given to the physics plugin
  224. */
  225. public setParam(paramName: string, value: number) {
  226. (<any>this._options)[paramName] = value;
  227. this._bodyUpdateRequired = true;
  228. }
  229. /**
  230. * Specifically change the body's mass option. Won't recreate the physics body object
  231. */
  232. public setMass(mass: number) {
  233. if (this.getParam("mass") !== mass) {
  234. this.setParam("mass", mass);
  235. }
  236. if (this._physicsEngine) {
  237. this._physicsEngine.getPhysicsPlugin().setBodyMass(this, mass);
  238. }
  239. }
  240. public getLinearVelocity(): Nullable<Vector3> {
  241. return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getLinearVelocity(this) : Vector3.Zero();
  242. }
  243. public setLinearVelocity(velocity: Nullable<Vector3>) {
  244. if (this._physicsEngine) {
  245. this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
  246. }
  247. }
  248. public getAngularVelocity(): Nullable<Vector3> {
  249. return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getAngularVelocity(this) : Vector3.Zero();
  250. }
  251. public setAngularVelocity(velocity: Nullable<Vector3>) {
  252. if (this._physicsEngine) {
  253. this._physicsEngine.getPhysicsPlugin().setAngularVelocity(this, velocity);
  254. }
  255. }
  256. /**
  257. * Execute a function with the physics plugin native code.
  258. * Provide a function the will have two variables - the world object and the physics body object.
  259. */
  260. public executeNativeFunction(func: (world: any, physicsBody: any) => void) {
  261. if (this._physicsEngine) {
  262. func(this._physicsEngine.getPhysicsPlugin().world, this.physicsBody);
  263. }
  264. }
  265. /**
  266. * Register a function that will be executed before the physics world is stepping forward.
  267. */
  268. public registerBeforePhysicsStep(func: (impostor: PhysicsImpostor) => void): void {
  269. this._onBeforePhysicsStepCallbacks.push(func);
  270. }
  271. public unregisterBeforePhysicsStep(func: (impostor: PhysicsImpostor) => void): void {
  272. var index = this._onBeforePhysicsStepCallbacks.indexOf(func);
  273. if (index > -1) {
  274. this._onBeforePhysicsStepCallbacks.splice(index, 1);
  275. } else {
  276. Tools.Warn("Function to remove was not found");
  277. }
  278. }
  279. /**
  280. * Register a function that will be executed after the physics step
  281. */
  282. public registerAfterPhysicsStep(func: (impostor: PhysicsImpostor) => void): void {
  283. this._onAfterPhysicsStepCallbacks.push(func);
  284. }
  285. public unregisterAfterPhysicsStep(func: (impostor: PhysicsImpostor) => void): void {
  286. var index = this._onAfterPhysicsStepCallbacks.indexOf(func);
  287. if (index > -1) {
  288. this._onAfterPhysicsStepCallbacks.splice(index, 1);
  289. } else {
  290. Tools.Warn("Function to remove was not found");
  291. }
  292. }
  293. /**
  294. * register a function that will be executed when this impostor collides against a different body.
  295. */
  296. public registerOnPhysicsCollide(collideAgainst: PhysicsImpostor | Array<PhysicsImpostor>, func: (collider: PhysicsImpostor, collidedAgainst: PhysicsImpostor) => void): void {
  297. var collidedAgainstList: Array<PhysicsImpostor> = collideAgainst instanceof Array ? <Array<PhysicsImpostor>>collideAgainst : [<PhysicsImpostor>collideAgainst]
  298. this._onPhysicsCollideCallbacks.push({ callback: func, otherImpostors: collidedAgainstList });
  299. }
  300. public unregisterOnPhysicsCollide(collideAgainst: PhysicsImpostor | Array<PhysicsImpostor>, func: (collider: PhysicsImpostor, collidedAgainst: PhysicsImpostor | Array<PhysicsImpostor>) => void): void {
  301. var collidedAgainstList: Array<PhysicsImpostor> = collideAgainst instanceof Array ? <Array<PhysicsImpostor>>collideAgainst : [<PhysicsImpostor>collideAgainst]
  302. var index = -1;
  303. let found = this._onPhysicsCollideCallbacks.some((cbDef, idx) => {
  304. if (cbDef.callback === func && cbDef.otherImpostors.length === collidedAgainstList.length) {
  305. // chcek the arrays match
  306. let sameList = cbDef.otherImpostors.every((impostor) => {
  307. return collidedAgainstList.indexOf(impostor) > -1;
  308. });
  309. if (sameList) {
  310. index = idx;
  311. }
  312. return sameList;
  313. }
  314. return false;
  315. });
  316. if (found) {
  317. this._onPhysicsCollideCallbacks.splice(index, 1);
  318. } else {
  319. Tools.Warn("Function to remove was not found");
  320. }
  321. }
  322. //temp variables for parent rotation calculations
  323. //private _mats: Array<Matrix> = [new Matrix(), new Matrix()];
  324. private _tmpQuat: Quaternion = new Quaternion();
  325. private _tmpQuat2: Quaternion = new Quaternion();
  326. public getParentsRotation() {
  327. let parent = this.object.parent;
  328. this._tmpQuat.copyFromFloats(0, 0, 0, 1);
  329. while (parent) {
  330. if (parent.rotationQuaternion) {
  331. this._tmpQuat2.copyFrom(parent.rotationQuaternion);
  332. } else {
  333. Quaternion.RotationYawPitchRollToRef(parent.rotation.y, parent.rotation.x, parent.rotation.z, this._tmpQuat2)
  334. }
  335. this._tmpQuat.multiplyToRef(this._tmpQuat2, this._tmpQuat);
  336. parent = parent.parent;
  337. }
  338. return this._tmpQuat;
  339. }
  340. /**
  341. * this function is executed by the physics engine.
  342. */
  343. public beforeStep = () => {
  344. if (!this._physicsEngine) {
  345. return;
  346. }
  347. this.object.translate(this._deltaPosition, -1);
  348. this._deltaRotationConjugated && this.object.rotationQuaternion && this.object.rotationQuaternion.multiplyToRef(this._deltaRotationConjugated, this.object.rotationQuaternion);
  349. this.object.computeWorldMatrix(false);
  350. if (this.object.parent && this.object.rotationQuaternion) {
  351. this.getParentsRotation();
  352. this._tmpQuat.multiplyToRef(this.object.rotationQuaternion, this._tmpQuat);
  353. } else {
  354. this._tmpQuat.copyFrom(this.object.rotationQuaternion || new Quaternion());
  355. }
  356. if (!this._options.disableBidirectionalTransformation) {
  357. this.object.rotationQuaternion && this._physicsEngine.getPhysicsPlugin().setPhysicsBodyTransformation(this, /*bInfo.boundingBox.centerWorld*/ this.object.getAbsolutePivotPoint(), this._tmpQuat);
  358. }
  359. this._onBeforePhysicsStepCallbacks.forEach((func) => {
  360. func(this);
  361. });
  362. }
  363. /**
  364. * this function is executed by the physics engine.
  365. */
  366. public afterStep = () => {
  367. if (!this._physicsEngine) {
  368. return;
  369. }
  370. this._onAfterPhysicsStepCallbacks.forEach((func) => {
  371. func(this);
  372. });
  373. this._physicsEngine.getPhysicsPlugin().setTransformationFromPhysicsBody(this);
  374. // object has now its world rotation. needs to be converted to local.
  375. if (this.object.parent && this.object.rotationQuaternion) {
  376. this.getParentsRotation();
  377. this._tmpQuat.conjugateInPlace();
  378. this._tmpQuat.multiplyToRef(this.object.rotationQuaternion, this.object.rotationQuaternion);
  379. }
  380. // take the position set and make it the absolute position of this object.
  381. this.object.setAbsolutePosition(this.object.position);
  382. this._deltaRotation && this.object.rotationQuaternion && this.object.rotationQuaternion.multiplyToRef(this._deltaRotation, this.object.rotationQuaternion);
  383. this.object.translate(this._deltaPosition, 1);
  384. }
  385. /**
  386. * Legacy collision detection event support
  387. */
  388. public onCollideEvent: Nullable<(collider: PhysicsImpostor, collidedWith: PhysicsImpostor) => void> = null;
  389. //event and body object due to cannon's event-based architecture.
  390. public onCollide = (e: { body: any }) => {
  391. if (!this._onPhysicsCollideCallbacks.length && !this.onCollideEvent) {
  392. return;
  393. }
  394. if (!this._physicsEngine) {
  395. return;
  396. }
  397. var otherImpostor = this._physicsEngine.getImpostorWithPhysicsBody(e.body);
  398. if (otherImpostor) {
  399. // Legacy collision detection event support
  400. if (this.onCollideEvent) {
  401. this.onCollideEvent(this, otherImpostor);
  402. }
  403. this._onPhysicsCollideCallbacks.filter((obj) => {
  404. return obj.otherImpostors.indexOf((<PhysicsImpostor>otherImpostor)) !== -1
  405. }).forEach((obj) => {
  406. obj.callback(this, <PhysicsImpostor>otherImpostor);
  407. })
  408. }
  409. }
  410. /**
  411. * Apply a force
  412. */
  413. public applyForce(force: Vector3, contactPoint: Vector3): PhysicsImpostor {
  414. if (this._physicsEngine) {
  415. this._physicsEngine.getPhysicsPlugin().applyForce(this, force, contactPoint);
  416. }
  417. return this;
  418. }
  419. /**
  420. * Apply an impulse
  421. */
  422. public applyImpulse(force: Vector3, contactPoint: Vector3): PhysicsImpostor {
  423. if (this._physicsEngine) {
  424. this._physicsEngine.getPhysicsPlugin().applyImpulse(this, force, contactPoint);
  425. }
  426. return this;
  427. }
  428. /**
  429. * A help function to create a joint.
  430. */
  431. public createJoint(otherImpostor: PhysicsImpostor, jointType: number, jointData: PhysicsJointData): PhysicsImpostor {
  432. var joint = new PhysicsJoint(jointType, jointData);
  433. this.addJoint(otherImpostor, joint);
  434. return this;
  435. }
  436. /**
  437. * Add a joint to this impostor with a different impostor.
  438. */
  439. public addJoint(otherImpostor: PhysicsImpostor, joint: PhysicsJoint): PhysicsImpostor {
  440. this._joints.push({
  441. otherImpostor: otherImpostor,
  442. joint: joint
  443. });
  444. if (this._physicsEngine) {
  445. this._physicsEngine.addJoint(this, otherImpostor, joint);
  446. }
  447. return this;
  448. }
  449. /**
  450. * Will keep this body still, in a sleep mode.
  451. */
  452. public sleep(): PhysicsImpostor {
  453. if (this._physicsEngine) {
  454. this._physicsEngine.getPhysicsPlugin().sleepBody(this);
  455. }
  456. return this;
  457. }
  458. /**
  459. * Wake the body up.
  460. */
  461. public wakeUp(): PhysicsImpostor {
  462. if (this._physicsEngine) {
  463. this._physicsEngine.getPhysicsPlugin().wakeUpBody(this);
  464. }
  465. return this;
  466. }
  467. public clone(newObject: IPhysicsEnabledObject): Nullable<PhysicsImpostor> {
  468. if (!newObject) return null;
  469. return new PhysicsImpostor(newObject, this.type, this._options, this._scene);
  470. }
  471. public dispose(/*disposeChildren: boolean = true*/) {
  472. //no dispose if no physics engine is available.
  473. if (!this._physicsEngine) {
  474. return;
  475. }
  476. this._joints.forEach((j) => {
  477. if (this._physicsEngine) {
  478. this._physicsEngine.removeJoint(this, j.otherImpostor, j.joint);
  479. }
  480. })
  481. //dispose the physics body
  482. this._physicsEngine.removeImpostor(this);
  483. if (this.parent) {
  484. this.parent.forceUpdate();
  485. } else {
  486. /*this._object.getChildMeshes().forEach(function(mesh) {
  487. if (mesh.physicsImpostor) {
  488. if (disposeChildren) {
  489. mesh.physicsImpostor.dispose();
  490. mesh.physicsImpostor = null;
  491. }
  492. }
  493. })*/
  494. }
  495. this._isDisposed = true;
  496. }
  497. public setDeltaPosition(position: Vector3) {
  498. this._deltaPosition.copyFrom(position);
  499. }
  500. public setDeltaRotation(rotation: Quaternion) {
  501. if (!this._deltaRotation) {
  502. this._deltaRotation = new Quaternion();
  503. }
  504. this._deltaRotation.copyFrom(rotation);
  505. this._deltaRotationConjugated = this._deltaRotation.conjugate();
  506. }
  507. public getBoxSizeToRef(result: Vector3): PhysicsImpostor {
  508. if (this._physicsEngine) {
  509. this._physicsEngine.getPhysicsPlugin().getBoxSizeToRef(this, result);
  510. }
  511. return this;
  512. }
  513. public getRadius(): number {
  514. return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getRadius(this) : 0;
  515. }
  516. /**
  517. * Sync a bone with this impostor
  518. * @param bone The bone to sync to the impostor.
  519. * @param boneMesh The mesh that the bone is influencing.
  520. * @param jointPivot The pivot of the joint / bone in local space.
  521. * @param distToJoint Optional distance from the impostor to the joint.
  522. * @param adjustRotation Optional quaternion for adjusting the local rotation of the bone.
  523. */
  524. public syncBoneWithImpostor(bone: Bone, boneMesh: AbstractMesh, jointPivot: Vector3, distToJoint?: number, adjustRotation?: Quaternion) {
  525. var tempVec = PhysicsImpostor._tmpVecs[0];
  526. var mesh = <AbstractMesh>this.object;
  527. if (mesh.rotationQuaternion) {
  528. if (adjustRotation) {
  529. var tempQuat = PhysicsImpostor._tmpQuat;
  530. mesh.rotationQuaternion.multiplyToRef(adjustRotation, tempQuat);
  531. bone.setRotationQuaternion(tempQuat, Space.WORLD, boneMesh);
  532. } else {
  533. bone.setRotationQuaternion(mesh.rotationQuaternion, Space.WORLD, boneMesh);
  534. }
  535. }
  536. tempVec.x = 0;
  537. tempVec.y = 0;
  538. tempVec.z = 0;
  539. if (jointPivot) {
  540. tempVec.x = jointPivot.x;
  541. tempVec.y = jointPivot.y;
  542. tempVec.z = jointPivot.z;
  543. bone.getDirectionToRef(tempVec, boneMesh, tempVec);
  544. if (distToJoint === undefined || distToJoint === null) {
  545. distToJoint = jointPivot.length();
  546. }
  547. tempVec.x *= distToJoint;
  548. tempVec.y *= distToJoint;
  549. tempVec.z *= distToJoint;
  550. }
  551. if (bone.getParent()) {
  552. tempVec.addInPlace(mesh.getAbsolutePosition());
  553. bone.setAbsolutePosition(tempVec, boneMesh);
  554. } else {
  555. boneMesh.setAbsolutePosition(mesh.getAbsolutePosition());
  556. boneMesh.position.x -= tempVec.x;
  557. boneMesh.position.y -= tempVec.y;
  558. boneMesh.position.z -= tempVec.z;
  559. }
  560. }
  561. /**
  562. * Sync impostor to a bone
  563. * @param bone The bone that the impostor will be synced to.
  564. * @param boneMesh The mesh that the bone is influencing.
  565. * @param jointPivot The pivot of the joint / bone in local space.
  566. * @param distToJoint Optional distance from the impostor to the joint.
  567. * @param adjustRotation Optional quaternion for adjusting the local rotation of the bone.
  568. * @param boneAxis Optional vector3 axis the bone is aligned with
  569. */
  570. public syncImpostorWithBone(bone: Bone, boneMesh: AbstractMesh, jointPivot: Vector3, distToJoint?: number, adjustRotation?: Quaternion, boneAxis?: Vector3) {
  571. var mesh = <AbstractMesh>this.object;
  572. if (mesh.rotationQuaternion) {
  573. if (adjustRotation) {
  574. var tempQuat = PhysicsImpostor._tmpQuat;
  575. bone.getRotationQuaternionToRef(Space.WORLD, boneMesh, tempQuat);
  576. tempQuat.multiplyToRef(adjustRotation, mesh.rotationQuaternion);
  577. } else {
  578. bone.getRotationQuaternionToRef(Space.WORLD, boneMesh, mesh.rotationQuaternion);
  579. }
  580. }
  581. var pos = PhysicsImpostor._tmpVecs[0];
  582. var boneDir = PhysicsImpostor._tmpVecs[1];
  583. if (!boneAxis) {
  584. boneAxis = PhysicsImpostor._tmpVecs[2];
  585. boneAxis.x = 0;
  586. boneAxis.y = 1;
  587. boneAxis.z = 0;
  588. }
  589. bone.getDirectionToRef(boneAxis, boneMesh, boneDir);
  590. bone.getAbsolutePositionToRef(boneMesh, pos);
  591. if ((distToJoint === undefined || distToJoint === null) && jointPivot) {
  592. distToJoint = jointPivot.length();
  593. }
  594. if (distToJoint !== undefined && distToJoint !== null) {
  595. pos.x += boneDir.x * distToJoint;
  596. pos.y += boneDir.y * distToJoint;
  597. pos.z += boneDir.z * distToJoint;
  598. }
  599. mesh.setAbsolutePosition(pos);
  600. }
  601. //Impostor types
  602. public static NoImpostor = 0;
  603. public static SphereImpostor = 1;
  604. public static BoxImpostor = 2;
  605. public static PlaneImpostor = 3;
  606. public static MeshImpostor = 4;
  607. public static CylinderImpostor = 7;
  608. public static ParticleImpostor = 8;
  609. public static HeightmapImpostor = 9;
  610. }
  611. }