Browse Source

Merge b3d

Nicolas Cannasse 11 years ago
parent
commit
6f32ffd51f
5 changed files with 490 additions and 6 deletions
  1. 27 0
      h3d/scene/VolumeDecal.hx
  2. 2 2
      hxd/res/AwdModel.hx
  3. 69 0
      hxd/res/fmt/AwdData.hx
  4. 374 0
      hxd/res/fmt/AwdReader.hx
  5. 18 4
      tools/fbx/Viewer.hx

+ 27 - 0
h3d/scene/VolumeDecal.hx

@@ -0,0 +1,27 @@
+package h3d.scene;
+
+class VolumeDecal extends h3d.scene.Mesh {
+
+	static var prim : h3d.prim.Polygon = null;
+	static function getVolumePrim() {
+		if( prim != null ) return prim;
+		prim = new h3d.prim.Cube();
+		prim.translate( -0.5, -0.5, -0.5);
+		prim.addNormals();
+		prim.addUVs();
+		return prim;
+	}
+	
+	public function new(texture, ?parent) {
+		super(getVolumePrim(), new h3d.mat.MeshMaterial(texture), parent);
+		material.depthWrite = false;
+	}
+	
+	override function sync( ctx : RenderContext ) {
+		// should be done in decals pass
+//		infos.screenToLocal.multiply(ctx.camera.getInverseViewProj(), getInvPos());
+//		material.volumeDecal = infos;
+		super.sync(ctx);
+	}
+	
+}

+ 2 - 2
hxd/res/AwdModel.hx

@@ -1,9 +1,9 @@
 package hxd.res;
 
 class AwdModel extends Resource {
-	
+
 	public function load() {
-		return false;
+		return new hxd.res.fmt.AwdReader().read(entry.getBytes());		
 	}
 	
 }

+ 69 - 0
hxd/res/fmt/AwdData.hx

@@ -0,0 +1,69 @@
+package hxd.res.fmt;
+
+class Block {
+	public var id : Int;
+	public var attributes : Null<Map<String,Dynamic>>;
+	public var name : Null<String>;
+	
+	public function new(id) {
+		this.id = id;
+	}
+
+	public inline function to<T:Block>( k : Class<T> ) : T {
+		return Std.instance(this, k);
+	}
+	
+	function toString() {
+		return Type.getClass(this) + "#" + id + (name == null ? "" : "(" + name + ")");
+	}
+}
+
+class SceneElement extends Block {
+	public var parent : SceneElement;
+	public var transform : h3d.Matrix;
+}
+
+class Instance extends SceneElement {
+	public var geometry : TriangleGeometry;
+	public var materials : Array<SimpleMaterial>;
+}
+
+class Joint extends Block {
+	public var parent : Joint;
+	public var bindPos : h3d.Matrix;
+}
+
+class Skeleton extends Block {
+	public var joints : Map<Int,Joint>;
+	public function new(id) {
+		super(id);
+		joints = new Map();
+	}
+}
+
+class BitmapTexture extends Block {
+	public var data : haxe.io.Bytes;
+	public var url : String;
+}
+
+class SimpleMaterial extends Block {
+	public var color : Int;
+	public var texture : BitmapTexture;
+	public function new(id) {
+		super(id);
+		color = 0xFFFFFFFF;
+	}
+}
+
+class TriangleGeometry extends Block {
+	public var subMeshes : Array<SubMesh>;
+}
+
+class SubMesh {
+	public var vertexData : haxe.io.Bytes;
+	public var indexes : haxe.io.Bytes;
+	public var uvs : haxe.io.Bytes;
+	public function new() {
+	}
+}
+

+ 374 - 0
hxd/res/fmt/AwdReader.hx

@@ -0,0 +1,374 @@
+package hxd.res.fmt;
+import hxd.res.fmt.AwdData;
+
+class AwdReader {
+	
+	static inline var TTRIANGLE_GEOM = 1;
+	static inline var TINSTANCE = 23;
+	static inline var TSKELETON = 101;
+	static inline var TSIMPLE_MATERIAL = 81;
+	static inline var TBITMAP_TEXURE = 82;
+	
+	var i : haxe.io.BytesInput;
+	var blocks : Map<Int,Block>;
+
+	public function new() {
+	}
+	
+	public function read( bytes ) {
+		blocks = new Map();
+		i = new haxe.io.BytesInput(bytes);
+		var h = readHeader();
+		var size = h.size;
+		if( i.length - size != 12 ) throw "truncated file";
+		var uBytes = null;
+		switch( h.compress ) {
+		case 0:
+		case 1:
+			var tmp = hxd.impl.Tmp.getBytes(size);
+			i.readFullBytes(tmp, 0, size);
+			uBytes = haxe.zip.Uncompress.run(tmp, 1 << 15);
+			hxd.impl.Tmp.saveBytes(tmp);
+			i = new haxe.io.BytesInput(uBytes);
+		case 2:
+			throw "LZMA not supported";
+		default:
+			throw "assert";
+		}
+		while( i.position < i.length )
+			readBlock();
+		if( uBytes != null )
+			hxd.impl.Tmp.saveBytes(uBytes);
+		return blocks;
+	}
+	
+	function readHeader() {
+		if( i.readString(3) != "AWD" ) throw "assert";
+		var major = i.readByte();
+		var minor = i.readByte();
+		var flags = i.readUInt16();
+		var compress = i.readByte();
+		var size = i.readInt32();
+		return { compress : compress, size : size };
+	}
+	
+	function readMatrix() {
+		var m = new h3d.Matrix();
+		m._11 = readFloat();
+		m._12 = readFloat();
+		m._13 = readFloat();
+		m._14 = readFloat();
+		m._21 = readFloat();
+		m._22 = readFloat();
+		m._23 = readFloat();
+		m._24 = readFloat();
+		m._31 = readFloat();
+		m._32 = readFloat();
+		m._33 = readFloat();
+		m._34 = readFloat();
+		m._41 = readFloat();
+		m._42 = readFloat();
+		m._43 = readFloat();
+		m._44 = readFloat();
+		return m;
+	}
+	
+	function readMatrix3x4() {
+		var m = new h3d.Matrix();
+		m._11 = readFloat();
+		m._12 = readFloat();
+		m._13 = readFloat();
+		m._14 = 0;
+		m._21 = readFloat();
+		m._22 = readFloat();
+		m._23 = readFloat();
+		m._24 = 0;
+		m._31 = readFloat();
+		m._32 = readFloat();
+		m._33 = readFloat();
+		m._34 = 0;
+		m._41 = readFloat();
+		m._42 = readFloat();
+		m._43 = readFloat();
+		m._44 = 1;
+		return m;
+	}
+	
+	inline function readBool() {
+		return i.readByte() != 0;
+	}
+	
+	function readString() {
+		return i.readString(i.readUInt16());
+	}
+	
+	function readName() {
+		var len = i.readUInt16();
+		return len == 0 ? null : i.readString(len);
+	}
+	
+	inline function readID() {
+		return i.readInt32();
+	}
+	
+	inline function readList<T>( decode : Void -> T ) : Array<T> {
+		return [for( i in 0...i.readInt32() ) decode()];
+	}
+	
+	inline function readFloat() {
+		return i.readFloat();
+	}
+	
+	function readAttrs() {
+		var count = i.readInt32();
+		if( count == 0 )
+			return null;
+		var a = new Map<String,Dynamic>();
+		for( k in 0...count ) {
+			var ns = i.readByte();
+			var name = readString();
+			var len = i.readInt32();
+			var value : Dynamic = switch( i.readByte() ) {
+			case 1: i.readInt8();
+			case 2: i.readInt16();
+			case 3, 6: i.readInt32();
+			case 4: i.readByte();
+			case 5: i.readUInt16();
+			case 11: i.readFloat();
+			case 12: i.readDouble();
+			case 21: readBool();
+			case 22: i.readInt32(); // color
+			case 23: readID(); // block
+			case 31: i.readString(len);
+			case 32: i.read(len);
+			case 41: new h3d.Vector(readFloat(), readFloat());
+			case 42: new h3d.Vector(readFloat(), readFloat(), readFloat());
+			case 43: new h3d.Vector(readFloat(), readFloat(), readFloat(), readFloat());
+			case 51: // m3x2
+				var m = new h3d.Matrix();
+				m._11 = readFloat();
+				m._12 = readFloat();
+				m._13 = readFloat();
+				m._14 = 0;
+				m._21 = readFloat();
+				m._22 = readFloat();
+				m._23 = readFloat();
+				m._24 = 0;
+				m._31 = 0;
+				m._32 = 0;
+				m._33 = 0;
+				m._34 = 0;
+				m._41 = 0;
+				m._42 = 0;
+				m._43 = 0;
+				m._44 = 1;
+				m;
+			case 52: // m3x3
+				var m = new h3d.Matrix();
+				m._11 = readFloat();
+				m._12 = readFloat();
+				m._13 = readFloat();
+				m._14 = 0;
+				m._21 = readFloat();
+				m._22 = readFloat();
+				m._23 = readFloat();
+				m._24 = 0;
+				m._31 = readFloat();
+				m._32 = readFloat();
+				m._33 = readFloat();
+				m._34 = 0;
+				m._41 = 0;
+				m._42 = 0;
+				m._43 = 0;
+				m._44 = 1;
+				m;
+			case 53: readMatrix3x4();
+			case 54: readMatrix();
+			case unk:
+				i.read(len);
+				"?" + unk;
+			}
+			a.set(name, value);
+		};
+		return a;
+	}
+	
+	function readSkelJoint( joints:Map<Int,Joint> ) {
+		var j = new Joint(i.readUInt16());
+		var pid = i.readUInt16();
+		if( pid > 0 ) {
+			var p = joints.get(pid);
+			if( p == null ) throw "Missing parent joint #" + pid;
+			j.parent = p;
+		}
+		j.name = readName();
+		j.bindPos = readMatrix3x4();
+		if( i.readInt32() != 0 ) throw "assert";
+		j.attributes = readAttrs();
+		return j;
+	}
+	
+	inline function numAttribs( decode : Int -> Int -> Void ) {
+		var totalLen = i.readInt32();
+		if( totalLen == 0 ) return;
+		var end = i.position + totalLen;
+		while( i.position < end ) {
+			var aid = i.readUInt16();
+			var len = i.readInt32();
+			var pos = i.position;
+			decode(aid,len);
+			var delta = i.position - (pos + len);
+			if( delta > 0 ) throw "Invalid delta " + delta + " for attribute #" + aid;
+		}
+	}
+	
+	function getBlock < T:Block > ( id : Int, c : Class<T> ) : T {
+		if( id == 0 )
+			return null;
+		var b = blocks.get(id);
+		if( b == null ) throw "Block #" + id + " not found";
+		var v = b.to(c);
+		if( v == null ) throw "Block " + b + " should be " + c;
+		return v;
+	}
+	
+	function readSubMesh() {
+		var s = new SubMesh();
+		var len = i.readInt32();
+		numAttribs(function(id, len) {
+			
+		});
+		var end = i.position + len;
+		while( i.position < end ) {
+			var stype = i.readByte();
+			var dtype = i.readByte();
+			var len = i.readInt32();
+			switch( [stype, dtype] ) {
+			case [1, 7]:
+				s.vertexData = i.read(len);
+			case [2, 5]:
+				s.indexes = i.read(len);
+			case [3, 7]:
+				s.uvs = i.read(len);
+			default:
+				throw "Unsupported stream " + stype + "/" + dtype+" ["+len+"]";
+			}
+		}
+		readAttrs();
+		return null;
+	}
+	
+	function readBlock() {
+		var id = readID();
+		var ns = i.readByte();
+		var tid = i.readByte();
+		var flags = i.readByte();
+		var size = i.readInt32();
+		var startPos = i.position;
+		var skip = false;
+		var hasNumAttr = true;
+		var block : Block;
+	
+		inline function noAttribute() {
+			if( hasNumAttr ) {
+				if( i.readInt32() != 0 ) throw "unexpected numattr";
+				hasNumAttr = false;
+			}
+		}
+		
+		if( ns != 0 ) {
+			block = null;
+			skip = true;
+		} else switch( tid ) {
+		case TTRIANGLE_GEOM:
+			var g = new TriangleGeometry(id);
+			g.name = readName();
+			var subGeom = i.readUInt16();
+			numAttribs(function(id, len) {
+				switch( id ) {
+				default:
+					throw "Unknown attrib #" + id + "[" + len + "]";
+				}
+			});
+			var subMeshes = [for( i in 0...subGeom ) readSubMesh()];
+			hasNumAttr = false;
+			block = g;
+		case TINSTANCE:
+			var inst = new Instance(id);
+			inst.parent = getBlock(readID(), SceneElement);
+			inst.transform = readMatrix3x4();
+			inst.name = readName();
+			inst.geometry = getBlock(readID(), TriangleGeometry);
+			inst.materials = [for( i in 0...i.readUInt16() ) getBlock(readID(), SimpleMaterial)];
+			numAttribs(function(id, len) {
+				switch( id ) {
+				case 5:
+					var castShadows = readBool();
+				default:
+					throw "Unknown attrib #" + id + "[" + len + "]";
+				}
+			});
+			hasNumAttr = false;
+			block = inst;
+		case TSKELETON:
+			var b = new Skeleton(id);
+			b.name = readName();
+			var njoints = i.readUInt16();
+			noAttribute();
+			for( i in 0...njoints ) {
+				var j = readSkelJoint(b.joints);
+				b.joints.set(j.id, j);
+			}
+			hasNumAttr = false;
+			block = b;
+		case TBITMAP_TEXURE:
+			var b = new BitmapTexture(id);
+			b.name = readName();
+			switch( i.readByte() ) {
+			case 0: b.url = i.readString(i.readInt32());
+			case 1: b.data = i.read(i.readInt32());
+			case unk: throw "assert " + unk;
+			};
+			block = b;
+		case TSIMPLE_MATERIAL:
+			var m = new SimpleMaterial(id);
+			m.name = readName();
+			var t = i.readByte();
+			var s = i.readByte();
+			numAttribs(function(id,len) {
+				switch( id ) {
+				case 1:
+					m.color = i.readInt32();
+				case 2:
+					m.texture = getBlock(readID(), BitmapTexture);
+				default:
+					throw "Unknown attrib #" + id+"["+len+"]";
+				}
+			});
+			hasNumAttr = false;
+			block = m;
+		default:
+			#if debug
+			trace("Unknown Block #" + tid);
+			#end
+			skip = true;
+			block = null;
+		}
+
+		if( skip ) {
+			var tmp = hxd.impl.Tmp.getBytes(size);
+			i.readFullBytes(tmp, 0, size);
+			hxd.impl.Tmp.saveBytes(tmp);
+		} else {
+
+			// do not support custom attributes
+			noAttribute();
+			block.attributes = readAttrs();
+			blocks.set(block.id, block);
+			
+			var delta = i.position - (startPos + size);
+			if( delta != 0 ) throw "Invalid delta " + delta + " for type " + tid;
+		}
+	}
+	
+}

+ 18 - 4
tools/fbx/Viewer.hx

@@ -80,6 +80,7 @@ class Viewer {
 	var pMouse : flash.geom.Point;
 	var axis : Axis;
 	var box : h3d.scene.Object;
+	var alib : h3d.fbx.Library;
 	
 	function new() {
 		time = 0;
@@ -171,6 +172,8 @@ class Viewer {
 			else if ( c == 52 )		props.view = 4;
 			else if( c == K.F1 )
 				askLoad();
+			else if( c == K.F2 )
+				askLoad(true);
 			else if( c == K.S && k.ctrlKey ) {
 				if( curFbx == null ) return;
 				var data = FbxTree.toXml(curFbx.getRoot());
@@ -321,12 +324,22 @@ class Viewer {
 		}
 	}
 	
-	function askLoad() {
+	function askLoad( ?anim ) {
 		var f = new flash.net.FileReference();
 		f.addEventListener(flash.events.Event.COMPLETE, function(_) {
 			haxe.Log.clear();
-			props.curFbxFile = f.name;
-			loadData(f.data.readUTFBytes(f.data.length));
+			var content = f.data.readUTFBytes(f.data.length);
+			if( anim ) {
+				alib = new h3d.fbx.Library();
+				var fbx = h3d.fbx.Parser.parse(content);
+				alib.load(fbx);
+				if( !rightHand )
+					alib.leftHandConvert();
+				setSkin();
+			} else {
+				props.curFbxFile = f.name;
+				loadData(content);
+			}
 		});
 		f.addEventListener(flash.events.Event.SELECT, function(_) f.load());
 		f.browse([new flash.net.FileFilter("FBX File", "*.fbx")]);
@@ -402,7 +415,7 @@ class Viewer {
 	}
 	
 	function setSkin() {
-		var anim = curFbx.loadAnimation(animMode);
+		var anim = curFbx.loadAnimation(animMode, null, null, alib);
 		if( anim != null ) {
 			anim = scene.playAnimation(anim);
 			if( !props.loop ) {
@@ -499,6 +512,7 @@ class Viewer {
 		
 		tf_keys.text = [
 			"[F1] Load model",
+			"[F2] Load animation",
 			"[A] Animation = " + animMode,
 			"[L] Loop = "+props.loop,
 			"[Y] Axis = "+props.showAxis,