ソースを参照

early work to display normals

ncannasse 11 年 前
コミット
e203a68ba1

+ 75 - 16
h3d/prim/FBXModel.hx

@@ -11,6 +11,7 @@ class FBXModel extends MeshPrimitive {
 	var bounds : h3d.col.Bounds;
 	var curMaterial : Int;
 	var groupIndexes : Array<Indexes>;
+	var viewNormals : Bool;
 
 	public function new(g) {
 		this.geom = g;
@@ -76,6 +77,13 @@ class FBXModel extends MeshPrimitive {
 		}
 	}
 
+	override function buildNormalsDisplay() {
+		var m = new FBXModel(geom);
+		m.viewNormals = true;
+		if( geom.getNormals() == null ) throw "Missing normals";
+		return m;
+	}
+
 	override function alloc( engine : h3d.Engine ) {
 		dispose();
 
@@ -93,6 +101,11 @@ class FBXModel extends MeshPrimitive {
 		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());
 		var cbuf = (colors == null ? null : new hxd.FloatBuffer());
 
+		if( viewNormals ) {
+			tbuf = new hxd.FloatBuffer();
+			cbuf = null;
+		}
+
 		// skin split
 		var sidx = null, stri = 0;
 		if( skin != null && skin.isSplit() ) {
@@ -120,25 +133,53 @@ class FBXModel extends MeshPrimitive {
 					pbuf.push(z);
 
 					if( nbuf != null ) {
-						nbuf.push(norms[k*3]);
-						nbuf.push(norms[k*3 + 1]);
-						nbuf.push(norms[k*3 + 2]);
+						var nx = norms[k * 3];
+						var ny = norms[k * 3 + 1];
+						var nz = norms[k * 3 + 2];
+						nbuf.push(nx);
+						nbuf.push(ny);
+						nbuf.push(nz);
+
+						if( viewNormals ) {
+							for( i in 0...3 ) {
+								pbuf.push(x);
+								pbuf.push(y);
+								pbuf.push(z);
+
+								nbuf.push(nx);
+								nbuf.push(ny);
+								nbuf.push(nz);
+							}
+						}
 					}
 
 					if( tbuf != null ) {
-						var iuv = tuvs.index[k];
-						tbuf.push(tuvs.values[iuv*2]);
-						tbuf.push(1 - tuvs.values[iuv * 2 + 1]);
+						if( viewNormals ) {
+							tbuf.push(0);
+							tbuf.push(0);
+							tbuf.push(1);
+							tbuf.push(0);
+							tbuf.push(0);
+							tbuf.push(1);
+							tbuf.push(1);
+							tbuf.push(1);
+						} else {
+							var iuv = tuvs.index[k];
+							tbuf.push(tuvs.values[iuv*2]);
+							tbuf.push(1 - tuvs.values[iuv * 2 + 1]);
+						}
 					}
 
 					if( sbuf != null ) {
 						var p = vidx * skin.bonesPerVertex;
-						var idx = 0;
-						for( i in 0...skin.bonesPerVertex ) {
-							sbuf.writeFloat(skin.vertexWeights[p + i]);
-							idx = (skin.vertexJoints[p + i] << (8*i)) | idx;
+						for( i in 0...(viewNormals ? 4 : 1) ) {
+							var idx = 0;
+							for( i in 0...skin.bonesPerVertex ) {
+								sbuf.writeFloat(skin.vertexWeights[p + i]);
+								idx = (skin.vertexJoints[p + i] << (8*i)) | idx;
+							}
+							sbuf.writeInt32(idx);
 						}
-						sbuf.writeInt32(idx);
 					}
 
 					if( cbuf != null ) {
@@ -148,11 +189,29 @@ class FBXModel extends MeshPrimitive {
 						cbuf.push(colors.values[icol * 4 + 2]);
 					}
 				}
-				// polygons are actually triangle fans
-				for( n in 0...count - 2 ) {
-					idx.push(start + n);
-					idx.push(start + count - 1);
-					idx.push(start + n + 1);
+
+
+				if( viewNormals ) {
+					for( n in 0...count - 2 ) {
+						inline function addQuad(k) {
+							idx.push(k * 4);
+							idx.push(k * 4 + 1);
+							idx.push(k * 4 + 2);
+							idx.push(k * 4 + 1);
+							idx.push(k * 4 + 3);
+							idx.push(k * 4 + 2);
+						}
+						addQuad(start + n);
+						addQuad(start + count - 1);
+						addQuad(start + n + 1);
+					}
+				} else {
+					// polygons are actually triangle fans
+					for( n in 0...count - 2 ) {
+						idx.push(start + n);
+						idx.push(start + count - 1);
+						idx.push(start + n + 1);
+					}
 				}
 				// by-skin-group index
 				if( skin != null && skin.isSplit() ) {

+ 5 - 15
h3d/prim/MeshPrimitive.hx

@@ -1,27 +1,17 @@
 package h3d.prim;
 
-private typedef Cache = #if flash haxe.ds.UnsafeStringMap<h3d.Buffer.BufferOffset> #else Map<Int,h3d.Buffer.BufferOffset> #end
-
 class MeshPrimitive extends Primitive {
 
-	var bufferCache : Cache;
+	var bufferCache : Map<Int,h3d.Buffer.BufferOffset>;
 
 	function allocBuffer( engine : h3d.Engine, name : String ) {
 		return null;
 	}
 
-	// TODO : in HxSL 3, we might instead allocate unique ID per name
-	static inline function hash( name : String ) {
-		var id = 0;
-		for( i in 0...name.length )
-			id = id * 223 + name.charCodeAt(i);
-		return id & 0x0FFFFFFF;
-	}
-
 	function addBuffer( name : String, buf, offset = 0 ) {
 		if( bufferCache == null )
-			bufferCache = new Cache();
-		var id = #if flash name #else hash(name) #end;
+			bufferCache = new Map();
+		var id = hxsl.Globals.allocID(name);
 		var old = bufferCache.get(id);
 		if( old != null ) old.dispose();
 		bufferCache.set(id, new h3d.Buffer.BufferOffset(buf, offset));
@@ -37,10 +27,10 @@ class MeshPrimitive extends Primitive {
 
 	function getBuffers( engine : h3d.Engine ) {
 		if( bufferCache == null )
-			bufferCache = new Cache();
+			bufferCache = new Map();
 		var buffers = null, prev = null;
 		for( name in @:privateAccess engine.driver.getShaderInputNames() ) {
-			var id = #if flash name #else hash(name) #end;
+			var id = hxsl.Globals.allocID(name);
 			var b = bufferCache.get(id);
 			if( b == null ) {
 				b = allocBuffer(engine, name);

+ 5 - 0
h3d/prim/Primitive.hx

@@ -21,6 +21,11 @@ class Primitive {
 	public function selectMaterial( material : Int ) {
 	}
 
+	public function buildNormalsDisplay() : Primitive {
+		throw "not implemented";
+		return null;
+	}
+
 	public function render( engine : h3d.Engine ) {
 		if( buffer == null || buffer.isDisposed() ) alloc(engine);
 		if( indexes == null ) {

+ 29 - 0
h3d/shader/NormalDisplayShader.hx

@@ -0,0 +1,29 @@
+package h3d.shader;
+
+class NormalDisplayShader extends hxsl.Shader {
+
+	static var SRC = {
+
+		@input var input : {
+			var position : Vec3;
+			var normal : Vec3;
+			var uv : Vec2;
+		}
+
+		var transformedNormal : Vec3;
+		var transformedPosition : Vec3;
+
+		@param var normalLength : Float;
+
+		function vertex() {
+			transformedPosition += (transformedNormal * input.uv.x + transformedNormal.zyx * input.uv.y * 0.03) * normalLength;
+		}
+
+	};
+
+	public function new( length = 0.2 ) {
+		super();
+		normalLength = length;
+	}
+
+}

+ 21 - 4
tools/fbx/Viewer.hx

@@ -12,6 +12,7 @@ typedef Props = {
 	slowDown:Bool,
 	loop:Bool,
 	lights:Bool,
+	normals:Bool,
 }
 
 typedef Campos = {
@@ -56,7 +57,7 @@ class Viewer extends hxd.App {
 		freeMove = false;
 		rightClick = false;
 
-		props = { curFbxFile : "", camPos : { x:10, y:0, z:0, tx:0, ty:0, tz:0 }, smoothing:true, showAxis:true, showBones:false, showBox:false, slowDown:false, loop:true, lights : true }
+		props = { curFbxFile : "", camPos : { x:10, y:0, z:0, tx:0, ty:0, tz:0 }, smoothing:true, showAxis:true, showBones:false, showBox:false, slowDown:false, loop:true, lights : true, normals : false }
 		props = hxd.Save.load(props);
 
 		tf = new flash.text.TextField();
@@ -210,9 +211,12 @@ class Viewer extends hxd.App {
 				s3d.addChild(axis);
 			else
 				s3d.removeChild(axis);
-		case "N".code:
+		case "M".code:
 			props.smoothing = !props.smoothing;
 			setMaterial();
+		case "N".code:
+			props.normals = !props.normals;
+			setMaterial();
 		case "B".code:
 			props.showBox = !props.showBox;
 			if( props.showBox && box != null )
@@ -387,16 +391,28 @@ class Viewer extends hxd.App {
 		box.z = c.z;
 	}
 
+	@:debug
 	function setMaterial( ?o : h3d.scene.Object ) {
 		if( o == null )
 			o = obj;
 		if( o.isMesh() ) {
 			var m = o.toMesh();
-			m.material.texture.filter = props.smoothing ? Linear : Nearest;
+			if( m.material.texture != null )
+				m.material.texture.filter = props.smoothing ? Linear : Nearest;
 			m.material.mainPass.enableLights = props.lights;
 			var s = Std.instance(o, h3d.scene.Skin);
 			if( s != null )
 				s.showJoints = props.showBones;
+			if( props.normals ) {
+				if( m.name != "__normals__" ) {
+					var n = new h3d.scene.Mesh(m.primitive.buildNormalsDisplay(), m);
+					n.material.color.set(0, 0, 1);
+					n.material.mainPass.culling = None;
+					n.material.mainPass.addShader(new h3d.shader.NormalDisplayShader());
+					n.name = "__normals__";
+				}
+			} else if( m.name == "__normals__" )
+				m.remove();
 		}
 		for( s in o )
 			setMaterial(s);
@@ -500,7 +516,8 @@ class Viewer extends hxd.App {
 			"[B] Bounds = "+props.showBox+(box == null ? "" : " ["+fmt(box.scaleX)+" x "+fmt(box.scaleY)+" x "+fmt(box.scaleZ)+"]"),
 			"[S] Slow Animation = "+props.slowDown,
 			"[R] Right-Hand Camera = "+rightHand,
-			"[N] Tex Smoothing = "+props.smoothing,
+			"[M] Tex Smoothing = " + props.smoothing,
+			"[N] Show normals = "+props.normals,
 			"[F] Default camera",
 			"[I] Lights = "+props.lights,
 			"[1~4] Views",