瀏覽代碼

Merge branch 'master' of github.com:ncannasse/h3d

ncannasse 11 年之前
父節點
當前提交
f4ec2bd234

+ 4 - 0
h3d/Indexes.hx

@@ -22,6 +22,10 @@ class Indexes {
 		mem.driver.uploadIndexBuffer(this.ibuf, pos, count, indexes, bufferPos);
 	}
 
+	public function uploadBytes( bytes : haxe.io.Bytes, dataPos : Int, indices : Int ) {
+		mem.driver.uploadIndexBytes(this.ibuf, 0, indices, bytes, dataPos);
+	}
+
 	public function dispose() {
 		if( ibuf != null )
 			mem.deleteIndexes(this);

+ 6 - 4
h3d/Quat.hx

@@ -186,11 +186,13 @@ class Quat {
 		return m;
 	}
 
-	public function toEuler() {
+	// Buggy, for instance with single Z rotation outside of [-pi/2,pi/2] range
+	public function __toEuler() {
+		var q = x * y + z * w;
 		return new Vector(
-			hxd.Math.atan2(2 * (x * w + y * z), 1 - 2 * (x * x + z * z)),
-			hxd.Math.atan2(2 * (y * w - x * z), 1 - 2 * (y * y - z * z)),
-			(2 * (x * y + z * w)).asin()
+			hxd.Math.atan2(2 * (x * w - y * z), 1 - 2 * (x * x + z * z)),
+			hxd.Math.atan2(2 * (y * w - x * z), 1 - 2 * (y * y + z * z)),
+			(2 * q).asin()
 		);
 	}
 

+ 1 - 0
h3d/mat/Material.hx

@@ -5,6 +5,7 @@ import h3d.mat.Pass;
 class Material {
 
 	var passes : Pass;
+	public var name : String;
 	public var mainPass(get, never) : Pass;
 	public var shadows(get, set) : Bool;
 	public var castShadows(default, set) : Bool;

+ 51 - 0
h3d/prim/H3DModel.hx

@@ -0,0 +1,51 @@
+package h3d.prim;
+
+class H3DModel extends MeshPrimitive {
+
+	var data : hxd.fmt.h3d.Data.Geometry;
+	var dataPosition : Int;
+	var entry : hxd.res.FileEntry;
+
+	public function new(data, dataPos, entry) {
+		this.data = data;
+		this.dataPosition = dataPos;
+		this.entry = entry;
+	}
+
+	override function alloc(engine:h3d.Engine) {
+		dispose();
+		buffer = new h3d.Buffer(data.vertexCount, data.vertexStride);
+
+		entry.open();
+
+		entry.skip(dataPosition + data.vertexPosition);
+		var size = data.vertexCount * data.vertexStride * 4;
+		var bytes = hxd.impl.Tmp.getBytes(size);
+		entry.read(bytes, 0, size);
+		buffer.uploadBytes(bytes, 0, data.vertexCount);
+		hxd.impl.Tmp.saveBytes(bytes);
+
+		indexes = new h3d.Indexes(data.indexCount);
+
+		entry.skip(data.indexPosition - (data.vertexPosition + size));
+		var bytes = hxd.impl.Tmp.getBytes(data.indexCount * 2);
+		entry.read(bytes, 0, data.indexCount * 2);
+		indexes.uploadBytes(bytes, 0, data.indexCount);
+		hxd.impl.Tmp.saveBytes(bytes);
+
+		entry.close();
+
+		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;
+		}
+	}
+
+}

+ 54 - 0
h3d/prim/MultiPrimitive.hx

@@ -0,0 +1,54 @@
+package h3d.prim;
+
+class MultiPrimitive extends Primitive {
+
+	var primitives : Array<Primitive>;
+	var bounds : h3d.col.Bounds;
+	var current : Int = -1;
+
+	public function new(primitives) {
+		this.primitives = primitives;
+	}
+
+	override function triCount() {
+		var t = 0;
+		for( p in primitives )
+			t += p.triCount();
+		return t;
+	}
+
+	override function getBounds() : h3d.col.Bounds {
+		if( bounds != null ) return bounds;
+		bounds = new h3d.col.Bounds();
+		for( p in primitives )
+			bounds.add(p.getBounds());
+		return bounds;
+	}
+
+	override function alloc( engine : h3d.Engine ) {
+		for( p in primitives )
+			p.alloc(engine);
+	}
+
+	override function selectMaterial( material : Int ) {
+		current = material;
+	}
+
+	override function buildNormalsDisplay() : Primitive {
+		return new MultiPrimitive([for( p in primitives ) p.buildNormalsDisplay()]);
+	}
+
+	override function render( engine : h3d.Engine ) {
+		if( current < 0 )
+			for( p in primitives )
+				p.render(engine);
+		else
+			primitives[current].render(engine);
+	}
+
+	override function dispose() {
+		for( p in primitives )
+			p.dispose();
+	}
+
+}

+ 12 - 0
h3d/scene/Mesh.hx

@@ -36,6 +36,18 @@ class Mesh extends Object {
 		ctx.emit(material, this);
 	}
 
+	override function getMaterialByName( name : String ) {
+		if( material != null && material.name == name )
+			return material;
+		return super.getMaterialByName(name);
+	}
+
+	override function getMaterials( ?a : Array<h3d.mat.Material> ) {
+		if( a == null ) a = [];
+		if( material != null ) a.push(material);
+		return super.getMaterials(a);
+	}
+
 	override function dispose() {
 		if( primitive != null ) primitive.dispose();
 		super.dispose();

+ 17 - 0
h3d/scene/MultiMaterial.hx

@@ -25,6 +25,23 @@ class MultiMaterial extends Mesh {
 		}
 	}
 
+	override function getMaterialByName( name : String ) {
+		for( m in materials )
+			if( m.name == name )
+				return m;
+		return super.getMaterialByName(name);
+	}
+
+	override function getMaterials( ?a : Array<h3d.mat.Material> ) {
+		if( a == null ) a = [];
+		for( m in materials )
+			if( m != null )
+				a.push(m);
+		for( o in childs )
+			o.getMaterials(a);
+		return a;
+	}
+
 	override function draw( ctx : RenderContext ) {
 		if( materials.length > 1 )
 			primitive.selectMaterial(ctx.drawPass.index);

+ 15 - 4
h3d/scene/Object.hx

@@ -76,6 +76,21 @@ class Object {
 		return k;
 	}
 
+	public function getMaterialByName( name : String ) {
+		for( o in childs ) {
+			var m = o.getMaterialByName(name);
+			if( m != null ) return m;
+		}
+		return null;
+	}
+
+	public function getMaterials( ?a : Array<h3d.mat.Material> ) {
+		if( a == null ) a = [];
+		for( o in childs )
+			o.getMaterials(a);
+		return a;
+	}
+
 	/**
 		Transform a point from the local object coordinates to the global ones. The point is modified and returned.
 	**/
@@ -370,10 +385,6 @@ class Object {
 		posChanged = true;
 	}
 
-	public function getRotation() {
-		return qRot.toEuler();
-	}
-
 	public function getRotationQuat() {
 		return qRot;
 	}

+ 11 - 0
hxd/fmt/fbx/BaseLibrary.hx

@@ -66,6 +66,17 @@ class DefaultMatrixes {
 		return m;
 	}
 
+	public function toQuaternion(leftHand) {
+		var m = new h3d.Matrix();
+		m.identity();
+		if( rotate != null ) m.rotate(rotate.x, rotate.y, rotate.z);
+		if( preRot != null ) m.rotate(preRot.x, preRot.y, preRot.z);
+		if( leftHand ) rightHandToLeft(m);
+		var q = new h3d.Quat();
+		q.initRotateMatrix(m);
+		return q;
+	}
+
 }
 
 class BaseLibrary {

+ 8 - 7
hxd/fmt/fbx/H3DOut.hx

@@ -24,7 +24,7 @@ class H3DOut extends BaseLibrary {
 		if( colors != null )
 			g.vertexFormat.push(new GeometryFormat("color", DVec3));
 
-		var stride = 3 + (normals == null ? 2 : 0) + uvs.length * 2 + (colors == null ? 0 : 3);
+		var stride = 3 + (normals == null ? 0 : 3) + uvs.length * 2 + (colors == null ? 0 : 3);
 		g.vertexStride = stride;
 		g.vertexCount = 0;
 
@@ -138,7 +138,7 @@ class H3DOut extends BaseLibrary {
 		}
 
 		var root = buildHierarchy().root;
-		if( root.childs.length == 1 ) {
+		if( root.childs.length == 1 && !root.isMesh ) {
 			root = root.childs[0];
 			root.parent = null;
 		}
@@ -174,10 +174,12 @@ class H3DOut extends BaseLibrary {
 			p.sx = m.scale == null ? 1 : m.scale.x;
 			p.sy = m.scale == null ? 1 : m.scale.y;
 			p.sz = m.scale == null ? 1 : m.scale.z;
-			// TODO : rotate in left hand and handle pre-rot
-			p.rx = 0;
-			p.ry = 0;
-			p.rz = 0;
+
+			var q = m.toQuaternion(true);
+			q.normalize();
+			p.qx = q.x;
+			p.qy = q.y;
+			p.qz = q.z;
 			model.position = p;
 			d.models.push(model);
 
@@ -261,7 +263,6 @@ class H3DOut extends BaseLibrary {
 				model.materials.push(mids[i]);
 			}
 		}
-
 		d.data = dataOut.getBytes();
 		return d;
 	}

+ 26 - 3
hxd/fmt/h3d/Data.hx

@@ -15,14 +15,36 @@ class Position {
 	public var x : Float;
 	public var y : Float;
 	public var z : Float;
-	public var rx : Float;
-	public var ry : Float;
-	public var rz : Float;
+	public var qx : Float;
+	public var qy : Float;
+	public var qz : Float;
 	public var sx : Float;
 	public var sy : Float;
 	public var sz : Float;
 	public function new() {
 	}
+
+	public function loadQuaternion( q : h3d.Quat ) {
+		var qw = 1 - (qx * qx + qy * qy + qz * qz);
+		q.x = qx;
+		q.y = qy;
+		q.z = qz;
+		q.w = qw < 0 ? -Math.sqrt( -qw) : Math.sqrt(qw);
+	}
+
+	public function toMatrix() {
+		var m = new h3d.Matrix();
+		var q = QTMP;
+		loadQuaternion(q);
+		q.saveToMatrix(m);
+		// prepend scale
+		m._11 *= sx; m._12 *= sx; m._13 *= sx;
+		m._21 *= sy; m._22 *= sy; m._23 *= sy;
+		m._31 *= sz; m._32 *= sz; m._33 *= sz;
+		m.translate(x, y, z);
+		return m;
+	}
+	static var QTMP = new h3d.Quat();
 }
 
 class GeometryFormat {
@@ -71,6 +93,7 @@ class Data {
 	public var geometries : Array<Geometry>;
 	public var materials : Array<Material>;
 	public var models : Array<Model>;
+	public var dataPosition : Int;
 	public var data : haxe.io.Bytes;
 
 	public function new() {

+ 49 - 2
hxd/fmt/h3d/Library.hx

@@ -4,17 +4,64 @@ class Library {
 
 	var entry : hxd.res.FileEntry;
 	var header : Data;
+	var cachedPrimitives : Array<h3d.prim.Primitive>;
 
 	public function new(entry, header) {
 		this.entry = entry;
 		this.header = header;
+		cachedPrimitives = [];
+	}
+
+	function makePrimitive( id : Int ) {
+		var p = cachedPrimitives[id];
+		if( p != null ) return p;
+		p = new h3d.prim.H3DModel(header.geometries[id], header.dataPosition, entry);
+		cachedPrimitives[id] = p;
+		return p;
+	}
+
+	function makeMaterial( mid : Int, loadTexture : String -> h3d.mat.Texture ) {
+		var m = header.materials[mid];
+		var mat = new h3d.mat.MeshMaterial();
+		mat.name = m.name;
+		if( m.diffuseTexture != null ) {
+			mat.texture = loadTexture(m.diffuseTexture);
+			if( mat.texture == null ) mat.texture = h3d.mat.Texture.fromColor(0xFF00FF);
+		}
+		mat.blendMode = m.blendMode;
+		mat.mainPass.culling = m.culling;
+		if( m.killAlpha != null ) {
+			var t = mat.mainPass.getShader(h3d.shader.Texture);
+			t.killAlpha = true;
+			t.killAlphaThreshold = m.killAlpha;
+		}
+		return mat;
 	}
 
 	public function makeObject( ?loadTexture : String -> h3d.mat.Texture ) : h3d.scene.Object {
 		if( loadTexture == null )
 			loadTexture = function(_) return h3d.mat.Texture.fromColor(0xFF00FF);
-		throw "TODO";
-		return null;
+		if( header.models.length == 0 )
+			throw "This file does not contain any model";
+		var objs = [];
+		for( m in header.models ) {
+			var obj : h3d.scene.Object;
+			if( m.geometries == null ) {
+				obj = new h3d.scene.Object();
+			} else {
+				var prim = m.geometries.length == 1 ? makePrimitive(m.geometries[0]) : new h3d.prim.MultiPrimitive([for( g in m.geometries ) makePrimitive(g)]);
+				if( m.materials.length == 1 )
+					obj = new h3d.scene.Mesh(prim, makeMaterial(m.materials[0],loadTexture));
+				else
+					obj = new h3d.scene.MultiMaterial(prim, [for( m in m.materials ) makeMaterial(m,loadTexture)]);
+			}
+			obj.name = m.name;
+			obj.defaultTransform = m.position.toMatrix();
+			objs.push(obj);
+			if( objs.length > 1 )
+				objs[m.parent].addChild(obj);
+		}
+		return objs[0];
 	}
 
 	public function loadAnimation( mode : h3d.anim.Mode, ?name : String ) : h3d.anim.Animation {

+ 8 - 3
hxd/fmt/h3d/Reader.hx

@@ -22,9 +22,9 @@ class Reader {
 		p.x = i.readFloat();
 		p.y = i.readFloat();
 		p.z = i.readFloat();
-		p.rx = i.readFloat();
-		p.ry = i.readFloat();
-		p.rz = i.readFloat();
+		p.qx = i.readFloat();
+		p.qy = i.readFloat();
+		p.qz = i.readFloat();
 		p.sx = i.readFloat();
 		p.sy = i.readFloat();
 		p.sz = i.readFloat();
@@ -43,6 +43,8 @@ class Reader {
 		}
 		d.version = i.readByte();
 		d.geometries = [];
+		d.dataPosition = i.readInt32();
+
 		for( k in 0...i.readInt32() ) {
 			var g = new Geometry();
 			g.vertexCount = i.readInt32();
@@ -51,6 +53,7 @@ class Reader {
 			g.vertexPosition = i.readInt32();
 			g.indexCount = i.readInt32();
 			g.indexPosition = i.readInt32();
+			d.geometries.push(g);
 		}
 
 		d.materials = [];
@@ -62,6 +65,7 @@ class Reader {
 			m.culling = CULLING[i.readByte()];
 			m.killAlpha = i.readFloat();
 			if( m.killAlpha == 1 ) m.killAlpha = null;
+			d.materials.push(m);
 		}
 
 		d.models = [];
@@ -70,6 +74,7 @@ class Reader {
 			m.name = readName();
 			m.parent = i.readInt32();
 			m.position = readPosition();
+			d.models.push(m);
 			var count = i.readByte();
 			if( count == 0 ) continue;
 			m.geometries = [];

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

@@ -26,9 +26,9 @@ class Writer {
 		out.writeFloat(p.x);
 		out.writeFloat(p.y);
 		out.writeFloat(p.z);
-		out.writeFloat(p.rx);
-		out.writeFloat(p.ry);
-		out.writeFloat(p.rz);
+		out.writeFloat(p.qx);
+		out.writeFloat(p.qy);
+		out.writeFloat(p.qz);
 		out.writeFloat(p.sx);
 		out.writeFloat(p.sy);
 		out.writeFloat(p.sz);
@@ -79,7 +79,7 @@ class Writer {
 
 		out.writeString("H3D");
 		out.writeByte(d.version);
-		out.writeInt32(bytes.length);
+		out.writeInt32(bytes.length + 12);
 		out.write(bytes);
 		out.writeInt32(d.data.length);
 		out.write(d.data);

+ 1 - 1
hxd/res/FileTree.hx

@@ -120,7 +120,7 @@ class FileTree {
 			Context.registerModuleDependency(currentModule, fullPath);
 		case "fbx" if( options.createH3D ):
 			var tmp = options.tmpDir + name + ".h3d";
-			if( getTime(tmp) < getTime(fullPath) ) {
+			if( getTime(tmp) < getTime(fullPath) || true ) {
 				Sys.println("Converting " + relPath);
 				var fbx = new hxd.fmt.fbx.H3DOut();
 				fbx.loadTextFile(sys.io.File.getContent(fullPath));

+ 6 - 6
samples/skin/Main.hx

@@ -4,19 +4,19 @@ class Main extends hxd.App {
 
 	override function init() {
 		var prim = hxd.Res.Model.toH3d();
-		var obj = prim.makeObject();
+		var obj = prim.makeObject(loadTexture);
 		obj.scale(0.1);
 		s3d.addChild(obj);
 		s3d.camera.pos.set( -2, -3, 2);
 		s3d.camera.target.z += 1;
 
-		obj.playAnimation(prim.loadAnimation(LinearAnim));
+		//obj.playAnimation(prim.loadAnimation(LinearAnim));
 
 		// add lights
 		var dir = new DirLight(new h3d.Vector( -1, 3, -10), s3d);
-		for( s in obj ) {
-			var m = s.toMesh().material;
-			m.mainPass.getShader(h3d.shader.Texture).killAlpha = true;
+		for( m in obj.getMaterials() ) {
+			var t = m.mainPass.getShader(h3d.shader.Texture);
+			if( t != null ) t.killAlpha = true;
 			m.mainPass.enableLights = true;
 			m.shadows = true;
 		}
@@ -28,7 +28,7 @@ class Main extends hxd.App {
 	}
 
 	function loadTexture( name : String ) {
-		name = name.split("\\").pop();
+		name = name.split("/").pop();
 		return hxd.Res.load(name).toTexture();
 	}