FBXModel.hx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package h3d.prim;
  2. using hxd.fmt.fbx.Data;
  3. import h3d.Buffer.BufferOffset;
  4. import h3d.col.Point;
  5. class FBXModel extends MeshPrimitive {
  6. public var geom(default, null) : hxd.fmt.fbx.Geometry;
  7. public var skin : h3d.anim.Skin;
  8. public var multiMaterial : Bool;
  9. var bounds : h3d.col.Bounds;
  10. var curMaterial : Int;
  11. var groupIndexes : Array<Indexes>;
  12. public function new(g) {
  13. this.geom = g;
  14. curMaterial = -1;
  15. }
  16. public function getVerticesCount() {
  17. return Std.int(geom.getVertices().length / 3);
  18. }
  19. override function getBounds() {
  20. if( bounds != null )
  21. return bounds;
  22. bounds = new h3d.col.Bounds();
  23. var verts = geom.getVertices();
  24. var gt = geom.getGeomTranslate();
  25. if( gt == null ) gt = new Point();
  26. if( verts.length > 0 ) {
  27. bounds.xMin = bounds.xMax = verts[0] + gt.x;
  28. bounds.yMin = bounds.yMax = verts[1] + gt.y;
  29. bounds.zMin = bounds.zMax = verts[2] + gt.z;
  30. }
  31. var pos = 3;
  32. for( i in 1...Std.int(verts.length / 3) ) {
  33. var x = verts[pos++] + gt.x;
  34. var y = verts[pos++] + gt.y;
  35. var z = verts[pos++] + gt.z;
  36. if( x > bounds.xMax ) bounds.xMax = x;
  37. if( x < bounds.xMin ) bounds.xMin = x;
  38. if( y > bounds.yMax ) bounds.yMax = y;
  39. if( y < bounds.yMin ) bounds.yMin = y;
  40. if( z > bounds.zMax ) bounds.zMax = z;
  41. if( z < bounds.zMin ) bounds.zMin = z;
  42. }
  43. return bounds;
  44. }
  45. override function render( engine : h3d.Engine ) {
  46. if( curMaterial < 0 ) {
  47. super.render(engine);
  48. return;
  49. }
  50. if( indexes == null || indexes.isDisposed() )
  51. alloc(engine);
  52. var idx = indexes;
  53. indexes = groupIndexes[curMaterial];
  54. if( indexes != null ) super.render(engine);
  55. indexes = idx;
  56. curMaterial = -1;
  57. }
  58. override function selectMaterial( material : Int ) {
  59. curMaterial = material;
  60. }
  61. override function dispose() {
  62. super.dispose();
  63. if( groupIndexes != null ) {
  64. for( i in groupIndexes )
  65. if( i != null )
  66. i.dispose();
  67. groupIndexes = null;
  68. }
  69. }
  70. override function alloc( engine : h3d.Engine ) {
  71. dispose();
  72. var verts = geom.getVertices();
  73. var norms = geom.getNormals();
  74. var tuvs = geom.getUVs()[0];
  75. var colors = geom.getColors();
  76. var mats = multiMaterial ? geom.getMaterials() : null;
  77. var gt = geom.getGeomTranslate();
  78. if( gt == null ) gt = new Point();
  79. var idx = new hxd.IndexBuffer();
  80. var midx = new Array<hxd.IndexBuffer>();
  81. var pbuf = new hxd.FloatBuffer(), nbuf = (norms == null ? null : new hxd.FloatBuffer()), sbuf = (skin == null ? null : new hxd.BytesBuffer()), tbuf = (tuvs == null ? null : new hxd.FloatBuffer());
  82. var cbuf = (colors == null ? null : new hxd.FloatBuffer());
  83. // skin split
  84. var sidx = null, stri = 0;
  85. if( skin != null && skin.isSplit() ) {
  86. if( multiMaterial ) throw "Multimaterial not supported with skin split";
  87. sidx = [for( _ in skin.splitJoints ) new hxd.IndexBuffer()];
  88. }
  89. // triangulize indexes : format is A,B,...,-X : negative values mark the end of the polygon
  90. var count = 0, pos = 0, matPos = 0;
  91. var index = geom.getPolygons();
  92. for( i in index ) {
  93. count++;
  94. if( i < 0 ) {
  95. index[pos] = -i - 1;
  96. var start = pos - count + 1;
  97. for( n in 0...count ) {
  98. var k = n + start;
  99. var vidx = index[k];
  100. var x = verts[vidx * 3] + gt.x;
  101. var y = verts[vidx * 3 + 1] + gt.y;
  102. var z = verts[vidx * 3 + 2] + gt.z;
  103. pbuf.push(x);
  104. pbuf.push(y);
  105. pbuf.push(z);
  106. if( nbuf != null ) {
  107. nbuf.push(norms[k*3]);
  108. nbuf.push(norms[k*3 + 1]);
  109. nbuf.push(norms[k*3 + 2]);
  110. }
  111. if( tbuf != null ) {
  112. var iuv = tuvs.index[k];
  113. tbuf.push(tuvs.values[iuv*2]);
  114. tbuf.push(1 - tuvs.values[iuv * 2 + 1]);
  115. }
  116. if( sbuf != null ) {
  117. var p = vidx * skin.bonesPerVertex;
  118. var idx = 0;
  119. for( i in 0...skin.bonesPerVertex ) {
  120. sbuf.writeFloat(skin.vertexWeights[p + i]);
  121. idx = (skin.vertexJoints[p + i] << (8*i)) | idx;
  122. }
  123. sbuf.writeInt32(idx);
  124. }
  125. if( cbuf != null ) {
  126. var icol = colors.index[k];
  127. cbuf.push(colors.values[icol * 4]);
  128. cbuf.push(colors.values[icol * 4 + 1]);
  129. cbuf.push(colors.values[icol * 4 + 2]);
  130. }
  131. }
  132. // polygons are actually triangle fans
  133. for( n in 0...count - 2 ) {
  134. idx.push(start + n);
  135. idx.push(start + count - 1);
  136. idx.push(start + n + 1);
  137. }
  138. // by-skin-group index
  139. if( skin != null && skin.isSplit() ) {
  140. for( n in 0...count - 2 ) {
  141. var idx = sidx[skin.triangleGroups[stri++]];
  142. idx.push(start + n);
  143. idx.push(start + count - 1);
  144. idx.push(start + n + 1);
  145. }
  146. }
  147. // by-material index
  148. if( mats != null ) {
  149. var mid = mats[matPos++];
  150. var idx = midx[mid];
  151. if( idx == null ) {
  152. idx = new hxd.IndexBuffer();
  153. midx[mid] = idx;
  154. }
  155. for( n in 0...count - 2 ) {
  156. idx.push(start + n);
  157. idx.push(start + count - 1);
  158. idx.push(start + n + 1);
  159. }
  160. }
  161. index[pos] = i; // restore
  162. count = 0;
  163. }
  164. pos++;
  165. }
  166. addBuffer("position", h3d.Buffer.ofFloats(pbuf, 3));
  167. if( nbuf != null ) addBuffer("normal", h3d.Buffer.ofFloats(nbuf, 3));
  168. if( tbuf != null ) addBuffer("uv", h3d.Buffer.ofFloats(tbuf, 2));
  169. if( sbuf != null ) {
  170. var nverts = Std.int(sbuf.length / ((skin.bonesPerVertex + 1) * 4));
  171. var skinBuf = new h3d.Buffer(nverts, skin.bonesPerVertex + 1);
  172. skinBuf.uploadBytes(sbuf.getBytes(), 0, nverts);
  173. addBuffer("weights", skinBuf, 0);
  174. addBuffer("indexes", skinBuf, skin.bonesPerVertex);
  175. }
  176. if( cbuf != null ) addBuffer("color", h3d.Buffer.ofFloats(cbuf, 3));
  177. indexes = h3d.Indexes.alloc(idx);
  178. if( mats != null ) {
  179. groupIndexes = [];
  180. for( i in midx )
  181. groupIndexes.push(i == null ? null : h3d.Indexes.alloc(i));
  182. }
  183. if( sidx != null ) {
  184. groupIndexes = [];
  185. for( i in sidx )
  186. groupIndexes.push(i == null ? null : h3d.Indexes.alloc(i));
  187. }
  188. }
  189. }