Forráskód Böngészése

added hxd.BufferFormat, apply it to HMD and World

Nicolas Cannasse 2 éve
szülő
commit
b37db188a1

+ 9 - 10
h3d/prim/HMDModel.hx

@@ -59,11 +59,11 @@ class HMDModel extends MeshPrimitive {
 
 
 	override function alloc(engine:h3d.Engine) {
 	override function alloc(engine:h3d.Engine) {
 		dispose();
 		dispose();
-		buffer = new h3d.Buffer(data.vertexCount, data.vertexStride);
+		buffer = new h3d.Buffer(data.vertexCount, data.vertexFormat.stride);
 
 
 		var entry = lib.resource.entry;
 		var entry = lib.resource.entry;
 
 
-		var size = data.vertexCount * data.vertexStride * 4;
+		var size = data.vertexCount * data.vertexFormat.stride * 4;
 		var bytes = entry.fetchBytes(dataPosition + data.vertexPosition, size);
 		var bytes = entry.fetchBytes(dataPosition + data.vertexPosition, size);
 		buffer.uploadBytes(bytes, 0, data.vertexCount);
 		buffer.uploadBytes(bytes, 0, data.vertexCount);
 
 
@@ -81,9 +81,9 @@ class HMDModel extends MeshPrimitive {
 		indexes.uploadBytes(bytes, 0, indexCount);
 		indexes.uploadBytes(bytes, 0, indexCount);
 
 
 		var pos = 0;
 		var pos = 0;
-		for( f in data.vertexFormat ) {
+		for( f in data.vertexFormat.getInputs() ) {
 			addBuffer(f.name, buffer, pos);
 			addBuffer(f.name, buffer, pos);
-			pos += f.format.getSize();
+			pos += f.type.getSize();
 		}
 		}
 
 
 		if( normalsRecomputed != null )
 		if( normalsRecomputed != null )
@@ -103,14 +103,13 @@ class HMDModel extends MeshPrimitive {
 
 
 	public function recomputeNormals( ?name : String ) {
 	public function recomputeNormals( ?name : String ) {
 
 
-		for( f in data.vertexFormat )
-			if( f.name == name )
-				return;
+		if( name != null && data.vertexFormat.hasInput("name") )
+			return;
 
 
 		if( name == null ) name = "normal";
 		if( name == null ) name = "normal";
 
 
 
 
-		var pos = lib.getBuffers(data, [new hxd.fmt.hmd.Data.GeometryFormat("position", DVec3)]);
+		var pos = lib.getBuffers(data, hxd.BufferFormat.POS3D);
 		var ids = new Array();
 		var ids = new Array();
 		var pts : Array<h3d.col.Point> = [];
 		var pts : Array<h3d.col.Point> = [];
 		var mpts = new Map();
 		var mpts = new Map();
@@ -164,7 +163,7 @@ class HMDModel extends MeshPrimitive {
 	}
 	}
 
 
 	public function addTangents() {
 	public function addTangents() {
-		var pos = lib.getBuffers(data, [new hxd.fmt.hmd.Data.GeometryFormat("position", DVec3)]);
+		var pos = lib.getBuffers(data, hxd.BufferFormat.POS3D);
 		var ids = new Array();
 		var ids = new Array();
 		var pts : Array<h3d.col.Point> = [];
 		var pts : Array<h3d.col.Point> = [];
 		for( i in 0...data.vertexCount ) {
 		for( i in 0...data.vertexCount ) {
@@ -216,7 +215,7 @@ class HMDModel extends MeshPrimitive {
 	}
 	}
 
 
 	function initCollider( poly : h3d.col.PolygonBuffer ) {
 	function initCollider( poly : h3d.col.PolygonBuffer ) {
-		var buf= lib.getBuffers(data, [new hxd.fmt.hmd.Data.GeometryFormat("position", DVec3)]);
+		var buf= lib.getBuffers(data, hxd.BufferFormat.POS3D);
 		poly.setData(buf.vertexes, buf.indexes);
 		poly.setData(buf.vertexes, buf.indexes);
 		if( collider == null ) {
 		if( collider == null ) {
 			var sphere = data.bounds.toSphere();
 			var sphere = data.bounds.toSphere();

+ 14 - 18
h3d/scene/World.hx

@@ -118,7 +118,7 @@ enum OptAlgorithm {
 
 
 class WorldModel {
 class WorldModel {
 	public var r : hxd.res.Model;
 	public var r : hxd.res.Model;
-	public var stride : Int;
+	public var format : hxd.BufferFormat;
 	public var buf : hxd.FloatBuffer;
 	public var buf : hxd.FloatBuffer;
 	public var idx : hxd.IndexBuffer;
 	public var idx : hxd.IndexBuffer;
 	public var geometries : Array<WorldModelGeometry>;
 	public var geometries : Array<WorldModelGeometry>;
@@ -135,6 +135,7 @@ class WorldModel {
 		switch( algo ) {
 		switch( algo ) {
 		case None:
 		case None:
 		case TopDown:
 		case TopDown:
+			var stride = format.stride;
 			var vertexCount = Std.int(buf.length/stride);
 			var vertexCount = Std.int(buf.length/stride);
 			var vertexRemap = new haxe.ds.Vector(vertexCount);
 			var vertexRemap = new haxe.ds.Vector(vertexCount);
 			var indexRemap = new hxd.IndexBuffer(idx.length);
 			var indexRemap = new hxd.IndexBuffer(idx.length);
@@ -246,17 +247,14 @@ class World extends Object {
 
 
 	function buildFormat() {
 	function buildFormat() {
 		var r = {
 		var r = {
-			fmt : [
-				new hxd.fmt.hmd.Data.GeometryFormat("position", DVec3),
-				new hxd.fmt.hmd.Data.GeometryFormat("normal", DVec3),
-			],
+			fmt : hxd.BufferFormat.POS3D_NORMAL,
 			defaults : [],
 			defaults : [],
 		};
 		};
 		if(enableNormalMaps) {
 		if(enableNormalMaps) {
-			r.defaults[r.fmt.length] = new h3d.Vector(1,0,0);
-			r.fmt.push(new hxd.fmt.hmd.Data.GeometryFormat("tangent", DVec3));
+			r.defaults[2] = new h3d.Vector(1,0,0);
+			r.fmt = r.fmt.append("tangent", DVec3);
 		}
 		}
-		r.fmt.push(new hxd.fmt.hmd.Data.GeometryFormat("uv", DVec2));
+		r.fmt = r.fmt.append("uv", DVec2);
 		return r;
 		return r;
 	}
 	}
 
 
@@ -400,9 +398,7 @@ class World extends Object {
 		var format = buildFormat();
 		var format = buildFormat();
 
 
 		var model = new WorldModel(r);
 		var model = new WorldModel(r);
-		model.stride = 0;
-		for( f in format.fmt )
-			model.stride += f.format.getSize();
+		model.format = format.fmt;
 
 
 		var startVertex = 0, startIndex = 0;
 		var startVertex = 0, startIndex = 0;
 		for( m in models ) {
 		for( m in models ) {
@@ -429,7 +425,7 @@ class World extends Object {
 				var data = lib.getBuffers(geom, format.fmt, format.defaults, mid);
 				var data = lib.getBuffers(geom, format.fmt, format.defaults, mid);
 
 
 				var m = new WorldModelGeometry(wmat);
 				var m = new WorldModelGeometry(wmat);
-				m.vertexCount = Std.int(data.vertexes.length / model.stride);
+				m.vertexCount = Std.int(data.vertexes.length / model.format.stride);
 				m.indexCount = data.indexes.length;
 				m.indexCount = data.indexes.length;
 				m.startVertex = startVertex;
 				m.startVertex = startVertex;
 				m.startIndex = startIndex;
 				m.startIndex = startIndex;
@@ -437,7 +433,7 @@ class World extends Object {
 
 
 				var vl = data.vertexes;
 				var vl = data.vertexes;
 				var p = 0;
 				var p = 0;
-				var extra = model.stride - 8;
+				var extra = model.format.stride - 8;
 				if(enableNormalMaps)
 				if(enableNormalMaps)
 					extra -= 3;
 					extra -= 3;
 
 
@@ -537,7 +533,7 @@ class World extends Object {
 			for( g in model.geometries ) {
 			for( g in model.geometries ) {
 				var b = c.buffers.get(g.m.bits);
 				var b = c.buffers.get(g.m.bits);
 				if( b == null ) {
 				if( b == null ) {
-					var bp = new h3d.prim.BigPrimitive(getStride(model), true);
+					var bp = new h3d.prim.BigPrimitive(getFormat(model).stride, true);
 					bp.hasTangents = enableNormalMaps;
 					bp.hasTangents = enableNormalMaps;
 					b = new h3d.scene.Mesh(bp, c.root);
 					b = new h3d.scene.Mesh(bp, c.root);
 					b.name = g.m.name;
 					b.name = g.m.name;
@@ -550,10 +546,10 @@ class World extends Object {
 					var m = e.transform;
 					var m = e.transform;
 					var scale = m._33;
 					var scale = m._33;
 					var rotZ = hxd.Math.atan2(m._12 / scale, m._11 / scale);
 					var rotZ = hxd.Math.atan2(m._12 / scale, m._11 / scale);
-					p.addSub(model.buf, model.idx, g.startVertex, Std.int(g.startIndex / 3), g.vertexCount, Std.int(g.indexCount / 3), m.tx, m.ty, m.tz, rotZ, scale, model.stride, 0., 0., 1., null);
+					p.addSub(model.buf, model.idx, g.startVertex, Std.int(g.startIndex / 3), g.vertexCount, Std.int(g.indexCount / 3), m.tx, m.ty, m.tz, rotZ, scale, model.format.stride, 0., 0., 1., null);
 				}
 				}
 				else
 				else
-					p.addSub(model.buf, model.idx, g.startVertex, Std.int(g.startIndex / 3), g.vertexCount, Std.int(g.indexCount / 3), 0., 0., 0., 0., 0., model.stride, 0., 0., 1., e.transform);
+					p.addSub(model.buf, model.idx, g.startVertex, Std.int(g.startIndex / 3), g.vertexCount, Std.int(g.indexCount / 3), 0., 0., 0., 0., 0., model.format.stride, 0., 0., 1., e.transform);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -631,8 +627,8 @@ class World extends Object {
 			cleanChunk(c);
 			cleanChunk(c);
 	}
 	}
 
 
-	function getStride( model : WorldModel ) {
-		return model.stride;
+	function getFormat( model : WorldModel ) {
+		return model.format;
 	}
 	}
 
 
 	public function add( model : WorldModel, x : Float, y : Float, z : Float, scale = 1., rotation = 0. ) {
 	public function add( model : WorldModel, x : Float, y : Float, z : Float, scale = 1., rotation = 0. ) {

+ 121 - 0
hxd/BufferFormat.hx

@@ -0,0 +1,121 @@
+package hxd;
+
+enum abstract InputFormat(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 function toString() {
+		return switch( new InputFormat(this) ) {
+		case DFloat: "DFloat";
+		case DVec2: "DVec2";
+		case DVec3: "DVec3";
+		case DVec4: "DVec4";
+		case DBytes4: "DBytes4";
+		}
+	}
+
+	static inline function fromInt( v : Int ) : InputFormat {
+		return new InputFormat(v);
+	}
+}
+
+@:structInit
+class BufferInput {
+	public var name(default,null) : String;
+	public var type(default,null) : InputFormat;
+	public inline function new( name : String, type : InputFormat ) {
+		this.name = name;
+		this.type = type;
+	}
+}
+
+class BufferFormat {
+
+	static var _UID = 0;
+	public var uid : Int;
+	public var stride(default,null) : Int;
+	var inputs : Array<BufferInput>;
+
+	function new( inputs : Array<BufferInput> ) {
+		uid = _UID++;
+		stride = 0;
+		this.inputs = inputs.copy();
+		for( i in inputs )
+			stride += i.type.getSize();
+	}
+
+	public function hasInput( name : String, ?type : InputFormat ) {
+		for( i in inputs )
+			if( i.name == name )
+				return type == null || type == i.type;
+		return false;
+	}
+
+	public function append( name : String, type : InputFormat ) {
+		var inputs = inputs.copy();
+		inputs.push({ name : name, type : type });
+		return make(inputs);
+	}
+
+	public inline function getInputs() {
+		return inputs.iterator();
+	}
+
+	/**
+		Alias for XY_UV_RGBA
+	**/
+	public static var H2D(get,never) : BufferFormat;
+	public static var XY_UV_RGBA(get,null) : BufferFormat;
+	public static var XY_UV(get,null) : BufferFormat;
+	public static var POS3D(get,null) : BufferFormat;
+	public static var POS3D_NORMAL(get,null) : BufferFormat;
+	public static var POS3D_UV(get,null) : BufferFormat;
+	public static var POS3D_NORMAL_UV(get,null) : BufferFormat;
+
+	static inline function get_H2D() return XY_UV_RGBA;
+	static function get_XY_UV_RGBA() {
+		if( XY_UV_RGBA == null ) XY_UV_RGBA = make([{ name : "position", type : DVec2 },{ name : "uv", type : DVec2 },{ name : "color", type : DVec4 }]);
+		return XY_UV_RGBA;
+	}
+	static function get_XY_UV() {
+		if( XY_UV == null ) XY_UV = make([{ name : "position", type : DVec2 },{ name : "uv", type : DVec2 }]);
+		return XY_UV;
+	}
+	static function get_POS3D() {
+		if( POS3D == null ) POS3D = make([{ name : "position", type : DVec3 }]);
+		return POS3D;
+	}
+	static function get_POS3D_NORMAL() {
+		if( POS3D_NORMAL == null ) POS3D_NORMAL = make([{ name : "position", type : DVec3 },{ name : "normal", type : DVec3 }]);
+		return POS3D_NORMAL;
+	}
+	static function get_POS3D_NORMAL_UV() {
+		if( POS3D_NORMAL_UV == null ) POS3D_NORMAL_UV = make([{ name : "position", type : DVec3 },{ name : "normal", type : DVec3 },{ name : "uv", type : DVec2 }]);
+		return POS3D_NORMAL_UV;
+	}
+	static function get_POS3D_UV() {
+		if( POS3D_UV == null ) POS3D_UV = make([{ name : "position", type : DVec3 },{ name : "uv", type : DVec2 }]);
+		return POS3D_UV;
+	}
+
+	public static function make( inputs ) {
+		return new BufferFormat(inputs);
+	}
+
+}

+ 14 - 17
hxd/fmt/fbx/HMDOut.hx

@@ -129,11 +129,11 @@ class HMDOut extends BaseLibrary {
 	}
 	}
 
 
 	function updateNormals( g : Geometry, vbuf : hxd.FloatBuffer, idx : Array<Array<Int>> ) {
 	function updateNormals( g : Geometry, vbuf : hxd.FloatBuffer, idx : Array<Array<Int>> ) {
-		var stride = g.vertexStride;
+		var stride = g.vertexFormat.stride;
 		var normalPos = 0;
 		var normalPos = 0;
-		for( f in g.vertexFormat ) {
+		for( f in g.vertexFormat.getInputs() ) {
 			if( f.name == "logicNormal" ) break;
 			if( f.name == "logicNormal" ) break;
-			normalPos += f.format.getSize();
+			normalPos += f.type.getSize();
 		}
 		}
 
 
 		var points : Array<h3d.col.Point> = [];
 		var points : Array<h3d.col.Point> = [];
@@ -165,7 +165,7 @@ class HMDOut extends BaseLibrary {
 			for( i in idx )
 			for( i in idx )
 				realIdx.push(pmap[i]);
 				realIdx.push(pmap[i]);
 		}
 		}
-			
+
 
 
 		var poly = new h3d.prim.Polygon(points, realIdx);
 		var poly = new h3d.prim.Polygon(points, realIdx);
 		poly.addNormals();
 		poly.addNormals();
@@ -203,32 +203,28 @@ class HMDOut extends BaseLibrary {
 		var tangents = genTangents ? buildTangents(geom) : null;
 		var tangents = genTangents ? buildTangents(geom) : null;
 
 
 		// build format
 		// build format
-		g.vertexFormat = [
+		var format = [
 			new GeometryFormat("position", DVec3),
 			new GeometryFormat("position", DVec3),
 		];
 		];
 		if( normals != null )
 		if( normals != null )
-			g.vertexFormat.push(new GeometryFormat("normal", DVec3));
+			format.push(new GeometryFormat("normal", DVec3));
 		if( tangents != null )
 		if( tangents != null )
-			g.vertexFormat.push(new GeometryFormat("tangent", DVec3));
+			format.push(new GeometryFormat("tangent", DVec3));
 		for( i in 0...uvs.length )
 		for( i in 0...uvs.length )
-			g.vertexFormat.push(new GeometryFormat("uv" + (i == 0 ? "" : "" + (i + 1)), DVec2));
+			format.push(new GeometryFormat("uv" + (i == 0 ? "" : "" + (i + 1)), DVec2));
 		if( colors != null )
 		if( colors != null )
-			g.vertexFormat.push(new GeometryFormat("color", DVec3));
+			format.push(new GeometryFormat("color", DVec3));
 
 
 		if( skin != null ) {
 		if( skin != null ) {
 			if(fourBonesByVertex)
 			if(fourBonesByVertex)
 				g.props = [FourBonesByVertex];
 				g.props = [FourBonesByVertex];
-			g.vertexFormat.push(new GeometryFormat("weights", DVec3));  // Only 3 weights are necessary even in fourBonesByVertex since they sum-up to 1
-			g.vertexFormat.push(new GeometryFormat("indexes", DBytes4));
+			format.push(new GeometryFormat("weights", DVec3));  // Only 3 weights are necessary even in fourBonesByVertex since they sum-up to 1
+			format.push(new GeometryFormat("indexes", DBytes4));
 		}
 		}
 
 
 		if( generateNormals )
 		if( generateNormals )
-			g.vertexFormat.push(new GeometryFormat("logicNormal", DVec3));
-
-		var stride = 0;
-		for( f in g.vertexFormat )
-			stride += f.format.getSize();
-		g.vertexStride = stride;
+			format.push(new GeometryFormat("logicNormal", DVec3));
+		g.vertexFormat = hxd.BufferFormat.make(format);
 		g.vertexCount = 0;
 		g.vertexCount = 0;
 
 
 		// build geometry
 		// build geometry
@@ -242,6 +238,7 @@ class HMDOut extends BaseLibrary {
 		}
 		}
 
 
 		g.bounds = new h3d.col.Bounds();
 		g.bounds = new h3d.col.Bounds();
+		var stride = g.vertexFormat.stride;
 		var tmpBuf = new hxd.impl.TypedArray.Float32Array(stride);
 		var tmpBuf = new hxd.impl.TypedArray.Float32Array(stride);
 		var vertexRemap = new Array<Int>();
 		var vertexRemap = new Array<Int>();
 		var index = geom.getPolygons();
 		var index = geom.getPolygons();

+ 3 - 45
hxd/fmt/hmd/Data.hx

@@ -1,39 +1,7 @@
 package hxd.fmt.hmd;
 package hxd.fmt.hmd;
 
 
-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 function toString() {
-		return switch( new GeometryDataFormat(this) ) {
-		case DFloat: "DFloat";
-		case DVec2: "DVec2";
-		case DVec3: "DVec3";
-		case DVec4: "DVec4";
-		case DBytes4: "DBytes4";
-		}
-	}
-
-	public static inline function fromInt( v : Int ) : GeometryDataFormat {
-		return new GeometryDataFormat(v);
-	}
-}
+typedef GeometryDataFormat = hxd.BufferFormat.InputFormat;
+typedef GeometryFormat = hxd.BufferFormat.BufferInput;
 
 
 typedef DataPosition = Int;
 typedef DataPosition = Int;
 typedef Index<T> = Int;
 typedef Index<T> = Int;
@@ -92,20 +60,10 @@ class Position {
 	static var QTMP = new h3d.Quat();
 	static var QTMP = new h3d.Quat();
 }
 }
 
 
-class GeometryFormat {
-	public var name : String;
-	public var format : GeometryDataFormat;
-	public function new(name, format) {
-		this.name = name;
-		this.format = format;
-	}
-}
-
 class Geometry {
 class Geometry {
 	public var props : Properties;
 	public var props : Properties;
 	public var vertexCount : Int;
 	public var vertexCount : Int;
-	public var vertexStride : Int;
-	public var vertexFormat : Array<GeometryFormat>;
+	public var vertexFormat : hxd.BufferFormat;
 	public var vertexPosition : DataPosition;
 	public var vertexPosition : DataPosition;
 	public var indexCount(get, never) : Int;
 	public var indexCount(get, never) : Int;
 	public var indexCounts : Array<Int>;
 	public var indexCounts : Array<Int>;

+ 4 - 6
hxd/fmt/hmd/Dump.hx

@@ -47,13 +47,13 @@ class Dump {
 			add('@$k GEOMETRY');
 			add('@$k GEOMETRY');
 			prefix += "\t";
 			prefix += "\t";
 			add('Vertex Count : ${g.vertexCount}');
 			add('Vertex Count : ${g.vertexCount}');
-			add('Vertex Stride : ${g.vertexStride}');
+			add('Vertex Stride : ${g.vertexFormat.stride}');
 			add('Index Count : ${g.indexCount} ${g.indexCounts.length > 1 ? g.indexCounts.toString() : ''}');
 			add('Index Count : ${g.indexCount} ${g.indexCounts.length > 1 ? g.indexCounts.toString() : ''}');
 			add('Bounds : center=${g.bounds.getCenter()} size=${g.bounds.getSize()}');
 			add('Bounds : center=${g.bounds.getCenter()} size=${g.bounds.getSize()}');
 			add('Format :');
 			add('Format :');
 			addProps(g.props);
 			addProps(g.props);
-			for( f in g.vertexFormat )
-				add('\t${f.name} ${f.format.toString().substr(1)}');
+			for( f in g.vertexFormat.getInputs() )
+				add('\t${f.name} ${f.type.toString().substr(1)}');
 			prefix = "";
 			prefix = "";
 		}
 		}
 		if( h.geometries.length > 0 ) add('');
 		if( h.geometries.length > 0 ) add('');
@@ -169,9 +169,7 @@ class Dump {
 
 
 		for( k in 0...h.geometries.length ) {
 		for( k in 0...h.geometries.length ) {
 			var g = h.geometries[k];
 			var g = h.geometries[k];
-			var stride = 0;
-			for( f in g.vertexFormat )
-				stride += f.format.getSize();
+			var stride = g.vertexFormat.stride;
 			add('@$k GEOMETRY');
 			add('@$k GEOMETRY');
 			prefix += '\t';
 			prefix += '\t';
 			d.position = g.vertexPosition;
 			d.position = g.vertexPosition;

+ 20 - 24
hxd/fmt/hmd/Library.hx

@@ -63,18 +63,16 @@ class Library {
 		}
 		}
 		if( stride > 11 )
 		if( stride > 11 )
 			throw "Unsupported stride";
 			throw "Unsupported stride";
-		return { format : format, defs : defs };
+		return { format : hxd.BufferFormat.make(format), defs : defs };
 	}
 	}
 
 
-	public function load( format : Array<GeometryFormat>, ?defaults : Array<h3d.Vector>, modelIndex = -1 ) {
+	public function load( format : hxd.BufferFormat, ?defaults : Array<h3d.Vector>, modelIndex = -1 ) {
 		var vtmp = new h3d.Vector();
 		var vtmp = new h3d.Vector();
 		var models = modelIndex < 0 ? header.models : [header.models[modelIndex]];
 		var models = modelIndex < 0 ? header.models : [header.models[modelIndex]];
 		var outVertex = new hxd.FloatBuffer();
 		var outVertex = new hxd.FloatBuffer();
 		var outIndex = new hxd.IndexBuffer();
 		var outIndex = new hxd.IndexBuffer();
-		var stride = 0;
+		var stride = format.stride;
 		var mid = -1;
 		var mid = -1;
-		for( f in format )
-			stride += f.format.getSize();
 		for( m in models ) {
 		for( m in models ) {
 			var geom = header.geometries[m.geometry];
 			var geom = header.geometries[m.geometry];
 			if( geom == null ) continue;
 			if( geom == null ) continue;
@@ -104,39 +102,39 @@ class Library {
 	}
 	}
 
 
 	@:noDebug
 	@:noDebug
-	public function getBuffers( geom : Geometry, format : Array<GeometryFormat>, ?defaults : Array<h3d.Vector>, ?material : Int ) {
+	public function getBuffers( geom : Geometry, format : hxd.BufferFormat, ?defaults : Array<h3d.Vector>, ?material : Int ) {
 
 
 		if( material == 0 && geom.indexCounts.length == 1 )
 		if( material == 0 && geom.indexCounts.length == 1 )
 			material = null;
 			material = null;
 
 
 		var map = null, stride = 0;
 		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();
+		for( i in 0...@:privateAccess format.inputs.length ) {
+			var i = @:privateAccess format.inputs.length - 1 - i;
+			var input = @:privateAccess format.inputs[i];
+			var size  = input.type.getSize();
 			var offset = 0;
 			var offset = 0;
 			var found = false;
 			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';
+			for( f2 in geom.vertexFormat.getInputs() ) {
+				if( f2.name == input.name ) {
+					if( f2.type.getSize() < size )
+						throw 'Requested ${input.name} data has only ${f2.type.getSize()} regs instead of $size';
 					found = true;
 					found = true;
 					break;
 					break;
 				}
 				}
-				offset += f2.format.getSize();
+				offset += f2.type.getSize();
 			}
 			}
 			if( found ) {
 			if( found ) {
 				map = new FormatMap(size, offset, null, map);
 				map = new FormatMap(size, offset, null, map);
 			} else {
 			} else {
 				var def = defaults == null ? null : defaults[i];
 				var def = defaults == null ? null : defaults[i];
 				if( def == null )
 				if( def == null )
-					throw 'Missing required ${f.name}';
+					throw 'Missing required ${input.name}';
 				map = new FormatMap(size, 0, def, map);
 				map = new FormatMap(size, 0, def, map);
 			}
 			}
 			stride += size;
 			stride += size;
 		}
 		}
 
 
-		var vsize = geom.vertexCount * geom.vertexStride * 4;
+		var vsize = geom.vertexCount * geom.vertexFormat.stride * 4;
 		var vbuf = haxe.io.Bytes.alloc(vsize);
 		var vbuf = haxe.io.Bytes.alloc(vsize);
 		var entry = resource.entry;
 		var entry = resource.entry;
 
 
@@ -168,7 +166,7 @@ class Library {
 				var m = map;
 				var m = map;
 				while( m != null ) {
 				while( m != null ) {
 					if( m.def == null ) {
 					if( m.def == null ) {
-						var r = vid * geom.vertexStride;
+						var r = vid * geom.vertexFormat.stride;
 						for( i in 0...m.size )
 						for( i in 0...m.size )
 							buf.vertexes[w++] = vbuf.getFloat((r + m.offset + i) << 2);
 							buf.vertexes[w++] = vbuf.getFloat((r + m.offset + i) << 2);
 					} else {
 					} else {
@@ -215,7 +213,7 @@ class Library {
 					var m = map;
 					var m = map;
 					while( m != null ) {
 					while( m != null ) {
 						if( m.def == null ) {
 						if( m.def == null ) {
-							var r = vid * geom.vertexStride;
+							var r = vid * geom.vertexFormat.stride;
 							for( i in 0...m.size )
 							for( i in 0...m.size )
 								vertexes.push(vbuf.getFloat((r + m.offset + i) << 2));
 								vertexes.push(vbuf.getFloat((r + m.offset + i) << 2));
 						} else {
 						} else {
@@ -593,14 +591,12 @@ class Library {
 		@:privateAccess skin.vertexCount = geom.vertexCount;
 		@:privateAccess skin.vertexCount = geom.vertexCount;
 
 
 		// Only 3 weights are necessary even in fourBonesByVertex since they sum-up to 1
 		// Only 3 weights are necessary even in fourBonesByVertex since they sum-up to 1
-		var format = [
+		var format = hxd.BufferFormat.make([
 			new hxd.fmt.hmd.Data.GeometryFormat("position",DVec3),
 			new hxd.fmt.hmd.Data.GeometryFormat("position",DVec3),
 			new hxd.fmt.hmd.Data.GeometryFormat("weights",DVec3),
 			new hxd.fmt.hmd.Data.GeometryFormat("weights",DVec3),
-			new hxd.fmt.hmd.Data.GeometryFormat("indexes",DBytes4)];
+			new hxd.fmt.hmd.Data.GeometryFormat("indexes",DBytes4)]);
 		var data = getBuffers(geom, format);
 		var data = getBuffers(geom, format);
-		var formatStride = 0;
-		for(f in format)
-			formatStride += f.format.getSize();
+		var formatStride = format.stride;
 
 
 		skin.vertexWeights = new haxe.ds.Vector(skin.vertexCount * bonesPerVertex);
 		skin.vertexWeights = new haxe.ds.Vector(skin.vertexCount * bonesPerVertex);
 		skin.vertexJoints = new haxe.ds.Vector(skin.vertexCount * bonesPerVertex);
 		skin.vertexJoints = new haxe.ds.Vector(skin.vertexCount * bonesPerVertex);

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

@@ -146,8 +146,9 @@ class Reader {
 			var g = new Geometry();
 			var g = new Geometry();
 			g.props = readProps();
 			g.props = readProps();
 			g.vertexCount = i.readInt32();
 			g.vertexCount = i.readInt32();
-			g.vertexStride = i.readByte();
-			g.vertexFormat = [for( k in 0...i.readByte() ) new GeometryFormat(readCachedName(), GeometryDataFormat.fromInt(i.readByte()))];
+			var stride = i.readByte();
+			g.vertexFormat = hxd.BufferFormat.make([for( k in 0...i.readByte() ) new GeometryFormat(readCachedName(), @:privateAccess GeometryDataFormat.fromInt(i.readByte()))]);
+			if( stride != g.vertexFormat.stride ) throw "assert";
 			g.vertexPosition = i.readInt32();
 			g.vertexPosition = i.readInt32();
 			var subCount = i.readByte();
 			var subCount = i.readByte();
 			if( subCount == 0xFF ) subCount = i.readInt32();
 			if( subCount == 0xFF ) subCount = i.readInt32();

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

@@ -114,11 +114,11 @@ class Writer {
 		for( g in d.geometries ) {
 		for( g in d.geometries ) {
 			writeProps(g.props);
 			writeProps(g.props);
 			out.writeInt32(g.vertexCount);
 			out.writeInt32(g.vertexCount);
-			out.writeByte(g.vertexStride);
-			out.writeByte(g.vertexFormat.length);
-			for( f in g.vertexFormat ) {
+			out.writeByte(g.vertexFormat.stride);
+			out.writeByte(@:privateAccess g.vertexFormat.inputs.length);
+			for( f in g.vertexFormat.getInputs() ) {
 				writeName(f.name);
 				writeName(f.name);
-				out.writeByte(f.format.toInt());
+				out.writeByte(f.type.toInt());
 			}
 			}
 			out.writeInt32(g.vertexPosition);
 			out.writeInt32(g.vertexPosition);
 			if( g.indexCounts.length >= 0xFF ) {
 			if( g.indexCounts.length >= 0xFF ) {