ModelSkin.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import Matrix4 from "../../Core/Matrix4.js";
  2. import Check from "../../Core/Check.js";
  3. import defaultValue from "../../Core/defaultValue.js";
  4. /**
  5. * An in-memory representation of a skin that affects nodes in the {@link ModelSceneGraph}.
  6. * Skins should only be initialized after all of the {@link ModelRuntimeNode}s have been instantiated
  7. * by the scene graph.
  8. *
  9. * @param {object} options An object containing the following options:
  10. * @param {ModelComponents.Skin} options.skin The corresponding skin components from the 3D model
  11. * @param {ModelSceneGraph} options.sceneGraph The scene graph this skin belongs to.
  12. *
  13. * @alias ModelSkin
  14. * @constructor
  15. *
  16. * @private
  17. */
  18. function ModelSkin(options) {
  19. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  20. //>>includeStart('debug', pragmas.debug);
  21. Check.typeOf.object("options.skin", options.skin);
  22. Check.typeOf.object("options.sceneGraph", options.sceneGraph);
  23. //>>includeEnd('debug');
  24. this._sceneGraph = options.sceneGraph;
  25. const skin = options.skin;
  26. this._skin = skin;
  27. this._inverseBindMatrices = undefined;
  28. this._joints = [];
  29. this._jointMatrices = [];
  30. initialize(this);
  31. }
  32. Object.defineProperties(ModelSkin.prototype, {
  33. /**
  34. * The internal skin this runtime skin represents.
  35. *
  36. * @memberof ModelSkin.prototype
  37. * @type {ModelComponents.Skin}
  38. * @readonly
  39. *
  40. * @private
  41. */
  42. skin: {
  43. get: function () {
  44. return this._skin;
  45. },
  46. },
  47. /**
  48. * The scene graph this skin belongs to.
  49. *
  50. * @memberof ModelSkin.prototype
  51. * @type {ModelSceneGraph}
  52. * @readonly
  53. *
  54. * @private
  55. */
  56. sceneGraph: {
  57. get: function () {
  58. return this._sceneGraph;
  59. },
  60. },
  61. /**
  62. * The inverse bind matrices of the skin.
  63. *
  64. * @memberof ModelSkin.prototype
  65. * @type {Matrix4[]}
  66. * @readonly
  67. *
  68. * @private
  69. */
  70. inverseBindMatrices: {
  71. get: function () {
  72. return this._inverseBindMatrices;
  73. },
  74. },
  75. /**
  76. * The joints of the skin.
  77. *
  78. * @memberof ModelSkin.prototype
  79. * @type {ModelRuntimeNode[]}
  80. * @readonly
  81. *
  82. * @private
  83. */
  84. joints: {
  85. get: function () {
  86. return this._joints;
  87. },
  88. },
  89. /**
  90. * The joint matrices for the skin, where each joint matrix is computed as
  91. * jointMatrix = jointWorldTransform * inverseBindMatrix.
  92. *
  93. * Each node that references this skin is responsible for pre-multiplying its inverse
  94. * world transform to the joint matrices for its own use.
  95. *
  96. * @memberof ModelSkin.prototype
  97. * @type {Matrix4[]}
  98. * @readonly
  99. *
  100. * @private
  101. */
  102. jointMatrices: {
  103. get: function () {
  104. return this._jointMatrices;
  105. },
  106. },
  107. });
  108. function initialize(runtimeSkin) {
  109. const skin = runtimeSkin.skin;
  110. const inverseBindMatrices = skin.inverseBindMatrices;
  111. runtimeSkin._inverseBindMatrices = inverseBindMatrices;
  112. const joints = skin.joints;
  113. const length = joints.length;
  114. const runtimeNodes = runtimeSkin.sceneGraph._runtimeNodes;
  115. const runtimeJoints = runtimeSkin.joints;
  116. const runtimeJointMatrices = runtimeSkin._jointMatrices;
  117. for (let i = 0; i < length; i++) {
  118. const jointIndex = joints[i].index;
  119. const runtimeNode = runtimeNodes[jointIndex];
  120. runtimeJoints.push(runtimeNode);
  121. const inverseBindMatrix = inverseBindMatrices[i];
  122. const jointMatrix = computeJointMatrix(
  123. runtimeNode,
  124. inverseBindMatrix,
  125. new Matrix4()
  126. );
  127. runtimeJointMatrices.push(jointMatrix);
  128. }
  129. }
  130. function computeJointMatrix(joint, inverseBindMatrix, result) {
  131. const jointWorldTransform = Matrix4.multiplyTransformation(
  132. joint.transformToRoot,
  133. joint.transform,
  134. result
  135. );
  136. result = Matrix4.multiplyTransformation(
  137. jointWorldTransform,
  138. inverseBindMatrix,
  139. result
  140. );
  141. return result;
  142. }
  143. /**
  144. * Updates the joint matrices for the skin.
  145. *
  146. * @private
  147. */
  148. ModelSkin.prototype.updateJointMatrices = function () {
  149. const jointMatrices = this._jointMatrices;
  150. const length = jointMatrices.length;
  151. for (let i = 0; i < length; i++) {
  152. const joint = this.joints[i];
  153. const inverseBindMatrix = this.inverseBindMatrices[i];
  154. jointMatrices[i] = computeJointMatrix(
  155. joint,
  156. inverseBindMatrix,
  157. jointMatrices[i]
  158. );
  159. }
  160. };
  161. export default ModelSkin;