babylon.morphTarget.ts 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. module BABYLON {
  2. /**
  3. * Defines a target to use with MorphTargetManager
  4. * @see http://doc.babylonjs.com/how_to/how_to_use_morphtargets
  5. */
  6. export class MorphTarget implements IAnimatable {
  7. /**
  8. * Gets or sets the list of animations
  9. */
  10. public animations = new Array<Animation>();
  11. private _scene: Nullable<Scene>;
  12. private _positions: Nullable<FloatArray> = null;
  13. private _normals: Nullable<FloatArray> = null;
  14. private _tangents: Nullable<FloatArray> = null;
  15. private _influence: number;
  16. /**
  17. * Observable raised when the influence changes
  18. */
  19. public onInfluenceChanged = new Observable<boolean>();
  20. /** @hidden */
  21. public _onDataLayoutChanged = new Observable<void>();
  22. /**
  23. * Gets or sets the influence of this target (ie. its weight in the overall morphing)
  24. */
  25. public get influence(): number {
  26. return this._influence;
  27. }
  28. public set influence(influence: number) {
  29. if (this._influence === influence) {
  30. return;
  31. }
  32. var previous = this._influence;
  33. this._influence = influence;
  34. if (this.onInfluenceChanged.hasObservers) {
  35. this.onInfluenceChanged.notifyObservers(previous === 0 || influence === 0);
  36. }
  37. }
  38. /**
  39. * Gets or sets the id of the morph Target
  40. */
  41. @serialize()
  42. public id: string;
  43. private _animationPropertiesOverride: Nullable<AnimationPropertiesOverride> = null;
  44. /**
  45. * Gets or sets the animation properties override
  46. */
  47. public get animationPropertiesOverride(): Nullable<AnimationPropertiesOverride> {
  48. if (!this._animationPropertiesOverride && this._scene) {
  49. return this._scene.animationPropertiesOverride;
  50. }
  51. return this._animationPropertiesOverride;
  52. }
  53. public set animationPropertiesOverride(value: Nullable<AnimationPropertiesOverride>) {
  54. this._animationPropertiesOverride = value;
  55. }
  56. /**
  57. * Creates a new MorphTarget
  58. * @param name defines the name of the target
  59. * @param influence defines the influence to use
  60. */
  61. public constructor(
  62. /** defines the name of the target */
  63. public name: string, influence = 0, scene: Nullable<Scene> = null) {
  64. this._scene = scene || Engine.LastCreatedScene;
  65. this.influence = influence;
  66. }
  67. /**
  68. * Gets a boolean defining if the target contains position data
  69. */
  70. public get hasPositions(): boolean {
  71. return !!this._positions;
  72. }
  73. /**
  74. * Gets a boolean defining if the target contains normal data
  75. */
  76. public get hasNormals(): boolean {
  77. return !!this._normals;
  78. }
  79. /**
  80. * Gets a boolean defining if the target contains tangent data
  81. */
  82. public get hasTangents(): boolean {
  83. return !!this._tangents;
  84. }
  85. /**
  86. * Affects position data to this target
  87. * @param data defines the position data to use
  88. */
  89. public setPositions(data: Nullable<FloatArray>) {
  90. const hadPositions = this.hasPositions;
  91. this._positions = data;
  92. if (hadPositions !== this.hasPositions) {
  93. this._onDataLayoutChanged.notifyObservers(undefined);
  94. }
  95. }
  96. /**
  97. * Gets the position data stored in this target
  98. * @returns a FloatArray containing the position data (or null if not present)
  99. */
  100. public getPositions(): Nullable<FloatArray> {
  101. return this._positions;
  102. }
  103. /**
  104. * Affects normal data to this target
  105. * @param data defines the normal data to use
  106. */
  107. public setNormals(data: Nullable<FloatArray>) {
  108. const hadNormals = this.hasNormals;
  109. this._normals = data;
  110. if (hadNormals !== this.hasNormals) {
  111. this._onDataLayoutChanged.notifyObservers(undefined);
  112. }
  113. }
  114. /**
  115. * Gets the normal data stored in this target
  116. * @returns a FloatArray containing the normal data (or null if not present)
  117. */
  118. public getNormals(): Nullable<FloatArray> {
  119. return this._normals;
  120. }
  121. /**
  122. * Affects tangent data to this target
  123. * @param data defines the tangent data to use
  124. */
  125. public setTangents(data: Nullable<FloatArray>) {
  126. const hadTangents = this.hasTangents;
  127. this._tangents = data;
  128. if (hadTangents !== this.hasTangents) {
  129. this._onDataLayoutChanged.notifyObservers(undefined);
  130. }
  131. }
  132. /**
  133. * Gets the tangent data stored in this target
  134. * @returns a FloatArray containing the tangent data (or null if not present)
  135. */
  136. public getTangents(): Nullable<FloatArray> {
  137. return this._tangents;
  138. }
  139. /**
  140. * Serializes the current target into a Serialization object
  141. * @returns the serialized object
  142. */
  143. public serialize(): any {
  144. var serializationObject: any = {};
  145. serializationObject.name = this.name;
  146. serializationObject.influence = this.influence;
  147. serializationObject.positions = Array.prototype.slice.call(this.getPositions());
  148. if (this.id != null) {
  149. serializationObject.id = this.id;
  150. }
  151. if (this.hasNormals) {
  152. serializationObject.normals = Array.prototype.slice.call(this.getNormals());
  153. }
  154. if (this.hasTangents) {
  155. serializationObject.tangents = Array.prototype.slice.call(this.getTangents());
  156. }
  157. // Animations
  158. Animation.AppendSerializedAnimations(this, serializationObject);
  159. return serializationObject;
  160. }
  161. /**
  162. * Returns the string "MorphTarget"
  163. * @returns "MorphTarget"
  164. */
  165. public getClassName(): string {
  166. return "MorphTarget";
  167. }
  168. // Statics
  169. /**
  170. * Creates a new target from serialized data
  171. * @param serializationObject defines the serialized data to use
  172. * @returns a new MorphTarget
  173. */
  174. public static Parse(serializationObject: any): MorphTarget {
  175. var result = new MorphTarget(serializationObject.name , serializationObject.influence);
  176. result.setPositions(serializationObject.positions);
  177. if (serializationObject.id) {
  178. result.id = serializationObject.id;
  179. }
  180. if (serializationObject.normals) {
  181. result.setNormals(serializationObject.normals);
  182. }
  183. if (serializationObject.tangents) {
  184. result.setTangents(serializationObject.tangents);
  185. }
  186. // Animations
  187. if (serializationObject.animations) {
  188. for (var animationIndex = 0; animationIndex < serializationObject.animations.length; animationIndex++) {
  189. var parsedAnimation = serializationObject.animations[animationIndex];
  190. result.animations.push(Animation.Parse(parsedAnimation));
  191. }
  192. }
  193. return result;
  194. }
  195. /**
  196. * Creates a MorphTarget from mesh data
  197. * @param mesh defines the source mesh
  198. * @param name defines the name to use for the new target
  199. * @param influence defines the influence to attach to the target
  200. * @returns a new MorphTarget
  201. */
  202. public static FromMesh(mesh: AbstractMesh, name?: string, influence?: number): MorphTarget {
  203. if (!name) {
  204. name = mesh.name;
  205. }
  206. var result = new MorphTarget(name, influence, mesh.getScene());
  207. result.setPositions(<FloatArray>mesh.getVerticesData(VertexBuffer.PositionKind));
  208. if (mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
  209. result.setNormals(<FloatArray>mesh.getVerticesData(VertexBuffer.NormalKind));
  210. }
  211. if (mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
  212. result.setTangents(<FloatArray>mesh.getVerticesData(VertexBuffer.TangentKind));
  213. }
  214. return result;
  215. }
  216. }
  217. }