Skin.hx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package h3d.scene;
  2. class Joint extends Object {
  3. public var skin : Skin;
  4. public var index : Int;
  5. public function new(skin, j : h3d.anim.Skin.Joint ) {
  6. super(null);
  7. name = j.name;
  8. this.skin = skin;
  9. // fake parent
  10. this.parent = skin;
  11. this.index = j.index;
  12. }
  13. @:access(h3d.scene.Skin)
  14. override function syncPos() {
  15. // check if one of our parents has changed
  16. // we don't have a posChanged flag since the Joint
  17. // is not actualy part of the hierarchy
  18. var p = parent;
  19. while( p != null ) {
  20. if( p.posChanged ) {
  21. // save the inverse absPos that was used to build the joints absPos
  22. if( skin.jointsAbsPosInv == null ) {
  23. skin.jointsAbsPosInv = new h3d.Matrix();
  24. skin.jointsAbsPosInv.zero();
  25. }
  26. if( skin.jointsAbsPosInv._44 == 0 )
  27. skin.jointsAbsPosInv.inverse3x4(parent.absPos);
  28. parent.syncPos();
  29. lastFrame = -1;
  30. break;
  31. }
  32. p = p.parent;
  33. }
  34. if( lastFrame != skin.lastFrame ) {
  35. lastFrame = skin.lastFrame;
  36. absPos.loadFrom(skin.currentAbsPose[index]);
  37. if( skin.jointsAbsPosInv != null && skin.jointsAbsPosInv._44 != 0 ) {
  38. absPos.multiply3x4(absPos, skin.jointsAbsPosInv);
  39. absPos.multiply3x4(absPos, parent.absPos);
  40. }
  41. }
  42. }
  43. }
  44. class Skin extends MultiMaterial {
  45. var skinData : h3d.anim.Skin;
  46. var currentRelPose : Array<h3d.Matrix>;
  47. var currentAbsPose : Array<h3d.Matrix>;
  48. var currentPalette : Array<h3d.Matrix>;
  49. var splitPalette : Array<Array<h3d.Matrix>>;
  50. var jointsUpdated : Bool;
  51. var jointsAbsPosInv : h3d.Matrix;
  52. var paletteChanged : Bool;
  53. var skinShader : h3d.shader.Skin;
  54. public var showJoints : Bool;
  55. public var syncIfHidden : Bool = true;
  56. public function new(s, ?mat, ?parent) {
  57. super(null, mat, parent);
  58. if( s != null )
  59. setSkinData(s);
  60. }
  61. override function clone( ?o : Object ) {
  62. var s = o == null ? new Skin(null,materials.copy()) : cast o;
  63. super.clone(s);
  64. s.setSkinData(skinData);
  65. s.currentRelPose = currentRelPose.copy(); // copy current pose
  66. return s;
  67. }
  68. override function getBounds( ?b : h3d.col.Bounds, rec = false ) {
  69. b = super.getBounds(b, rec);
  70. var tmp = primitive.getBounds().clone();
  71. var b0 = skinData.allJoints[0];
  72. // not sure if that's the good joint
  73. if( b0 != null && b0.parent == null ) {
  74. var mtmp = absPos.clone();
  75. var r = currentRelPose[b0.index];
  76. if( r != null )
  77. mtmp.multiply3x4(r, mtmp);
  78. else
  79. mtmp.multiply3x4(b0.defMat, mtmp);
  80. if( b0.transPos != null )
  81. mtmp.multiply3x4(b0.transPos, mtmp);
  82. tmp.transform3x4(mtmp);
  83. } else
  84. tmp.transform3x4(absPos);
  85. b.add(tmp);
  86. return b;
  87. }
  88. override function getObjectByName( name : String ) {
  89. var o = super.getObjectByName(name);
  90. if( o != null ) return o;
  91. // create a fake object targeted at the bone, not persistant but matrixes are shared
  92. if( skinData != null ) {
  93. var j = skinData.namedJoints.get(name);
  94. if( j != null )
  95. return new Joint(this, j);
  96. }
  97. return null;
  98. }
  99. override function calcAbsPos() {
  100. super.calcAbsPos();
  101. // if we update our absolute position, rebuild the matrixes
  102. jointsUpdated = true;
  103. }
  104. public function setSkinData( s ) {
  105. skinData = s;
  106. jointsUpdated = true;
  107. primitive = s.primitive;
  108. skinShader = new h3d.shader.Skin();
  109. for( m in materials )
  110. if( m != null )
  111. m.mainPass.addShader(skinShader);
  112. currentRelPose = [];
  113. currentAbsPose = [];
  114. currentPalette = [];
  115. paletteChanged = true;
  116. for( j in skinData.allJoints )
  117. currentAbsPose.push(h3d.Matrix.I());
  118. for( i in 0...skinData.boundJoints.length )
  119. currentPalette.push(h3d.Matrix.I());
  120. if( skinData.splitJoints != null ) {
  121. splitPalette = [];
  122. for( a in skinData.splitJoints )
  123. splitPalette.push([for( j in a ) currentPalette[j.bindIndex]]);
  124. } else
  125. splitPalette = null;
  126. }
  127. override function sync( ctx : RenderContext ) {
  128. if( !(visible || syncIfHidden) )
  129. return;
  130. if( jointsUpdated || posChanged ) {
  131. super.sync(ctx);
  132. for( j in skinData.allJoints ) {
  133. var id = j.index;
  134. var m = currentAbsPose[id];
  135. var r = currentRelPose[id];
  136. if( r == null ) r = j.defMat;
  137. if( j.parent == null )
  138. m.multiply3x4(r, absPos);
  139. else
  140. m.multiply3x4(r, currentAbsPose[j.parent.index]);
  141. var bid = j.bindIndex;
  142. if( bid >= 0 )
  143. currentPalette[bid].multiply3x4(j.transPos, m);
  144. }
  145. paletteChanged = true;
  146. if( jointsAbsPosInv != null ) jointsAbsPosInv._44 = 0; // mark as invalid
  147. jointsUpdated = false;
  148. } else
  149. super.sync(ctx);
  150. }
  151. override function draw( ctx : RenderContext ) {
  152. if( splitPalette == null ) {
  153. if( paletteChanged ) {
  154. paletteChanged = false;
  155. skinShader.bonesMatrixes = currentPalette;
  156. }
  157. super.draw(ctx);
  158. } else {
  159. var i = ctx.drawPass.index;
  160. skinShader.bonesMatrixes = splitPalette[i];
  161. primitive.selectMaterial(i);
  162. super.draw(ctx);
  163. }
  164. if( showJoints )
  165. throw "TODO"; //ctx.addPass(drawJoints);
  166. }
  167. function drawJoints( ctx : RenderContext ) {
  168. /*
  169. for( j in skinData.allJoints ) {
  170. var m = currentAbsPose[j.index];
  171. var mp = j.parent == null ? absPos : currentAbsPose[j.parent.index];
  172. ctx.engine.line(mp._41, mp._42, mp._43, m._41, m._42, m._43, j.parent == null ? 0xFF0000FF : 0xFFFFFF00);
  173. var dz = new h3d.Vector(0, 0.01, 0);
  174. dz.transform(m);
  175. ctx.engine.line(m._41, m._42, m._43, dz.x, dz.y, dz.z, 0xFF00FF00);
  176. ctx.engine.point(m._41, m._42, m._43, j.bindIndex < 0 ? 0xFF0000FF : 0xFFFF0000);
  177. }
  178. */
  179. }
  180. }