ncannasse 11 лет назад
Родитель
Сommit
ea0b88641e
5 измененных файлов с 195 добавлено и 20 удалено
  1. 1 7
      h3d/prim/HMDModel.hx
  2. 28 6
      hxd/fmt/hmd/Data.hx
  3. 164 4
      hxd/fmt/hmd/Library.hx
  4. 1 2
      hxd/fmt/hmd/Reader.hx
  5. 1 1
      hxd/fmt/hmd/Writer.hx

+ 1 - 7
h3d/prim/HMDModel.hx

@@ -55,13 +55,7 @@ class HMDModel extends MeshPrimitive {
 		var pos = 0;
 		for( f in data.vertexFormat ) {
 			addBuffer(f.name, buffer, pos);
-			var stride = switch( f.format ) {
-			case DVec4: 4;
-			case DVec3: 3;
-			case DVec2: 2;
-			case DFloat, DBytes4: 1;
-			}
-			pos += stride;
+			pos += f.format.getSize();
 		}
 	}
 

+ 28 - 6
hxd/fmt/hmd/Data.hx

@@ -1,11 +1,27 @@
 package hxd.fmt.hmd;
 
-enum GeometryDataFormat {
-	DFloat;
-	DVec2;
-	DVec3;
-	DVec4;
-	DBytes4;
+@:enum abstract GeometryDataFormat(Int) {
+
+	public var DFloat = 1;
+	public var DVec2 = 2;
+	public var DVec3 = 3;
+	public var DVec4 = 4;
+	public var DBytes4 = 9;
+
+	inline function new(v) {
+		this = v;
+	}
+
+	public inline function getSize() {
+		return this & 7;
+	}
+
+	public inline function toInt() {
+		return this;
+	}
+	public static inline function fromInt( v : Int ) : GeometryDataFormat {
+		return new GeometryDataFormat(v);
+	}
 }
 
 typedef DataPosition = Int;
@@ -61,11 +77,17 @@ class Geometry {
 	public var vertexStride : Int;
 	public var vertexFormat : Array<GeometryFormat>;
 	public var vertexPosition : DataPosition;
+	public var indexCount(get, never) : Int;
 	public var indexCounts : Array<Int>;
 	public var indexPosition : DataPosition;
 	public var bounds : h3d.col.Bounds;
 	public function new() {
 	}
+	function get_indexCount() {
+		var k = 0;
+		for( i in indexCounts ) k += i;
+		return k;
+	}
 }
 
 class Material {

+ 164 - 4
hxd/fmt/hmd/Library.hx

@@ -1,10 +1,30 @@
 package hxd.fmt.hmd;
 import hxd.fmt.hmd.Data;
 
+private class FormatMap {
+	public var size : Int;
+	public var offset : Int;
+	public var def : h3d.Vector;
+	public var next : FormatMap;
+	public function new(size, offset, def, next) {
+		this.size = size;
+		this.offset = offset;
+		this.def = def;
+		this.next = next;
+	}
+}
+
+class GeometryBuffer {
+	public var vertexes : haxe.ds.Vector<Float>;
+	public var indexes : haxe.ds.Vector<Int>;
+	public function new() {
+	}
+}
+
 class Library {
 
+	public var header : Data;
 	var entry : hxd.res.FileEntry;
-	var header : Data;
 	var cachedPrimitives : Array<h3d.prim.Primitive>;
 	var cachedAnimations : Map<String, h3d.anim.Animation>;
 	var cachedSkin : Map<String, h3d.anim.Skin>;
@@ -17,6 +37,146 @@ class Library {
 		cachedSkin = new Map();
 	}
 
+	@:noDebug
+	public function getBuffers( geom : Geometry, format : Array<GeometryFormat>, ?defaults : Array<h3d.Vector>, ?material : Int ) {
+
+		if( material == 0 && geom.indexCounts.length == 1 )
+			material = null;
+
+		var map = null, stride = 0;
+		for( i in 0...format.length ) {
+			var i = format.length - 1 - i;
+			var f = format[i];
+			var size  = f.format.getSize();
+			var offset = 0;
+			var found = false;
+			for( f2 in geom.vertexFormat ) {
+				if( f2.name == f.name ) {
+					if( f2.format.getSize() < size )
+						throw 'Requested ${f.name} data has only ${f2.format.getSize()} regs instead of $size';
+					found = true;
+					break;
+				}
+				offset += f2.format.getSize();
+			}
+			if( found ) {
+				map = new FormatMap(size, offset, null, map);
+			} else {
+				var def = defaults == null ? null : defaults[i];
+				if( def == null )
+					throw 'Missing required ${f.name}';
+				map = new FormatMap(size, 0, def, map);
+			}
+			stride += size;
+		}
+
+		var vsize = geom.vertexCount * geom.vertexStride * 4;
+		var vbuf = hxd.impl.Tmp.getBytes(vsize);
+		entry.open();
+		entry.skip(header.dataPosition + geom.vertexPosition);
+		entry.read(vbuf, 0, vsize);
+
+		entry.skip(geom.indexPosition - (geom.vertexPosition + vsize));
+
+		var isize;
+		if( material == null )
+			isize = geom.indexCount * 2;
+		else {
+			var ipos = 0;
+			for( i in 0...material )
+				ipos += geom.indexCounts[i];
+			entry.skip(ipos * 2);
+			isize = geom.indexCounts[material] * 2;
+		}
+		var ibuf = hxd.impl.Tmp.getBytes(isize);
+		entry.read(ibuf, 0, isize);
+
+		var buf = new GeometryBuffer();
+		if( material == null ) {
+			buf.vertexes = new haxe.ds.Vector(stride * geom.vertexCount);
+			buf.indexes = new haxe.ds.Vector(geom.indexCount);
+			var w = 0;
+			for( vid in 0...geom.vertexCount ) {
+				var m = map;
+				while( m != null ) {
+					if( m.def == null ) {
+						var r = vid * geom.vertexStride;
+						for( i in 0...m.size )
+							buf.vertexes[w++] = vbuf.getFloat((r + m.offset + i) << 2);
+					} else {
+						switch( m.size ) {
+						case 1:
+							buf.vertexes[w++] = m.def.x;
+						case 2:
+							buf.vertexes[w++] = m.def.x;
+							buf.vertexes[w++] = m.def.y;
+						case 3:
+							buf.vertexes[w++] = m.def.x;
+							buf.vertexes[w++] = m.def.y;
+							buf.vertexes[w++] = m.def.z;
+						default:
+							buf.vertexes[w++] = m.def.x;
+							buf.vertexes[w++] = m.def.y;
+							buf.vertexes[w++] = m.def.z;
+							buf.vertexes[w++] = m.def.w;
+						}
+					}
+					m = m.next;
+				}
+			}
+			var r = 0;
+			for( i in 0...buf.indexes.length )
+				buf.indexes[i] = ibuf.get(r++) | (ibuf.get(r++) << 8);
+		} else {
+			var icount = geom.indexCounts[material];
+			var vmap = new haxe.ds.Vector(geom.vertexCount);
+			var vertexes = new hxd.FloatBuffer();
+			buf.indexes = new haxe.ds.Vector(icount);
+			var r = 0, vcount = 0;
+			for( i in 0...buf.indexes.length ) {
+				var vid = ibuf.get(r++) | (ibuf.get(r++) << 8);
+				var rid = vmap[vid];
+				if( rid == 0 ) {
+					rid = ++vcount;
+					vmap[vid] = rid;
+					var m = map;
+					while( m != null ) {
+						if( m.def == null ) {
+							var r = vid * geom.vertexStride;
+							for( i in 0...m.size )
+								vertexes.push(vbuf.getFloat((r + m.offset + i) << 2));
+						} else {
+							switch( m.size ) {
+							case 1:
+								vertexes.push(m.def.x);
+							case 2:
+								vertexes.push(m.def.x);
+								vertexes.push(m.def.y);
+							case 3:
+								vertexes.push(m.def.x);
+								vertexes.push(m.def.y);
+								vertexes.push(m.def.z);
+							default:
+								vertexes.push(m.def.x);
+								vertexes.push(m.def.y);
+								vertexes.push(m.def.z);
+								vertexes.push(m.def.w);
+							}
+						}
+						m = m.next;
+					}
+				}
+				buf.indexes[i] = rid - 1;
+			}
+			buf.vertexes = haxe.ds.Vector.fromData(vertexes.getNative());
+		}
+
+		entry.close();
+		hxd.impl.Tmp.saveBytes(ibuf);
+		hxd.impl.Tmp.saveBytes(vbuf);
+		return buf;
+	}
+
 	function makePrimitive( id : Int ) {
 		var p = cachedPrimitives[id];
 		if( p != null ) return p;
@@ -94,9 +254,9 @@ class Library {
 			} else {
 				var prim = makePrimitive(m.geometry);
 				if( m.skin != null ) {
-					var sk = new h3d.scene.Skin(makeSkin(m.skin), [for( m in m.materials ) makeMaterial(m, loadTexture)]);
-					sk.primitive = prim;
-					obj = sk;
+					var skinData = makeSkin(m.skin);
+					skinData.primitive = prim;
+					obj = new h3d.scene.Skin(skinData, [for( m in m.materials ) makeMaterial(m, loadTexture)]);
 				} else if( m.materials.length == 1 )
 					obj = new h3d.scene.Mesh(prim, makeMaterial(m.materials[0],loadTexture));
 				else

+ 1 - 2
hxd/fmt/hmd/Reader.hx

@@ -3,7 +3,6 @@ import hxd.fmt.hmd.Data;
 
 class Reader {
 
-	static var FORMATS = Type.allEnums(GeometryDataFormat);
 	static var BLEND = Type.allEnums(h2d.BlendMode);
 	static var CULLING = Type.allEnums(h3d.mat.Data.Face);
 
@@ -98,7 +97,7 @@ class Reader {
 			var g = new Geometry();
 			g.vertexCount = i.readInt32();
 			g.vertexStride = i.readByte();
-			g.vertexFormat = [for( k in 0...i.readByte() ) new GeometryFormat(readName(), FORMATS[i.readByte()])];
+			g.vertexFormat = [for( k in 0...i.readByte() ) new GeometryFormat(readName(), GeometryDataFormat.fromInt(i.readByte()))];
 			g.vertexPosition = i.readInt32();
 			g.indexCounts = [for( k in 0...i.readByte() ) i.readInt32()];
 			g.indexPosition = i.readInt32();

+ 1 - 1
hxd/fmt/hmd/Writer.hx

@@ -79,7 +79,7 @@ class Writer {
 			out.writeByte(g.vertexFormat.length);
 			for( f in g.vertexFormat ) {
 				writeName(f.name);
-				out.writeByte(f.format.getIndex());
+				out.writeByte(f.format.toInt());
 			}
 			out.writeInt32(g.vertexPosition);
 			out.writeByte(g.indexCounts.length);