babylon.physicsImpostor.ts 27 KB

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