ModelExperimentalSkin.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 ModelExperimentalSceneGraph}.
  6. * Skins should only be initialized after all of the {@link ModelExperimentalNode}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 {ModelExperimentalSceneGraph} options.sceneGraph The scene graph this skin belongs to.
  12. *
  13. * @alias ModelExperimentalSkin
  14. * @constructor
  15. *
  16. * @private
  17. */
  18. export default function ModelExperimentalSkin(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(ModelExperimentalSkin.prototype, {
  33. /**
  34. * The internal skin this runtime skin represents.
  35. *
  36. * @memberof ModelExperimentalSkin.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. * @type {ModelExperimentalSceneGraph}
  51. * @readonly
  52. *
  53. * @private
  54. */
  55. sceneGraph: {
  56. get: function () {
  57. return this._sceneGraph;
  58. },
  59. },
  60. /**
  61. * The inverse bind matrices of the skin.
  62. *
  63. * @memberof ModelExperimentalSkin.prototype
  64. * @type {Matrix4[]}
  65. * @readonly
  66. *
  67. * @private
  68. */
  69. inverseBindMatrices: {
  70. get: function () {
  71. return this._inverseBindMatrices;
  72. },
  73. },
  74. /**
  75. * The joints of the skin.
  76. *
  77. * @memberof ModelExperimentalSkin.prototype
  78. * @type {ModelExperimentalNode[]}
  79. * @readonly
  80. *
  81. * @private
  82. */
  83. joints: {
  84. get: function () {
  85. return this._joints;
  86. },
  87. },
  88. /**
  89. * The joint matrices for the skin, where each joint matrix is computed as
  90. * jointMatrix = jointWorldTransform * inverseBindMatrix.
  91. *
  92. * Each node that references this skin is responsible for pre-multiplying its inverse
  93. * world transform to the joint matrices for its own use.
  94. *
  95. * @memberof ModelExperimentalSkin.prototype
  96. * @type {Matrix4[]}
  97. * @readonly
  98. *
  99. * @private
  100. */
  101. jointMatrices: {
  102. get: function () {
  103. return this._jointMatrices;
  104. },
  105. },
  106. });
  107. function initialize(runtimeSkin) {
  108. const skin = runtimeSkin.skin;
  109. const inverseBindMatrices = skin.inverseBindMatrices;
  110. runtimeSkin._inverseBindMatrices = inverseBindMatrices;
  111. const joints = skin.joints;
  112. const length = joints.length;
  113. const runtimeNodes = runtimeSkin.sceneGraph._runtimeNodes;
  114. const runtimeJoints = runtimeSkin.joints;
  115. const runtimeJointMatrices = runtimeSkin._jointMatrices;
  116. for (let i = 0; i < length; i++) {
  117. const jointIndex = joints[i].index;
  118. const runtimeNode = runtimeNodes[jointIndex];
  119. runtimeJoints.push(runtimeNode);
  120. const inverseBindMatrix = inverseBindMatrices[i];
  121. const jointMatrix = computeJointMatrix(
  122. runtimeNode,
  123. inverseBindMatrix,
  124. new Matrix4()
  125. );
  126. runtimeJointMatrices.push(jointMatrix);
  127. }
  128. }
  129. function computeJointMatrix(joint, inverseBindMatrix, result) {
  130. const jointWorldTransform = Matrix4.multiplyTransformation(
  131. joint.transformToRoot,
  132. joint.transform,
  133. result
  134. );
  135. result = Matrix4.multiplyTransformation(
  136. jointWorldTransform,
  137. inverseBindMatrix,
  138. result
  139. );
  140. return result;
  141. }
  142. /**
  143. * Updates the joint matrices for the skin.
  144. *
  145. * @private
  146. */
  147. ModelExperimentalSkin.prototype.updateJointMatrices = function () {
  148. const jointMatrices = this._jointMatrices;
  149. const length = jointMatrices.length;
  150. for (let i = 0; i < length; i++) {
  151. const joint = this.joints[i];
  152. const inverseBindMatrix = this.inverseBindMatrices[i];
  153. jointMatrices[i] = computeJointMatrix(
  154. joint,
  155. inverseBindMatrix,
  156. jointMatrices[i]
  157. );
  158. }
  159. };