Pārlūkot izejas kodu

hmd support for lighting properties in 3DSMax (using xtra)

ncannasse 9 gadi atpakaļ
vecāks
revīzija
c5bcadbec5

+ 49 - 6
hxd/fmt/fbx/HMDOut.hx

@@ -409,6 +409,7 @@ class HMDOut extends BaseLibrary {
 					mids.push(mid);
 					continue;
 				}
+				var hasHeapsProps = false;
 				var mat = new Material();
 				mid = d.materials.length;
 				mids.push(mid);
@@ -417,15 +418,51 @@ class HMDOut extends BaseLibrary {
 
 				mat.name = m.getName();
 				mat.culling = Back; // don't use FBX Culling infos (OFF by default)
-				mat.blendMode = None;
+				mat.blendMode = null;
+				mat.flags = Material.DEFAULT_FLAGS;
 
 				// if there's a slight amount of opacity on the material
 				// it's usually meant to perform additive blending on 3DSMax
-				for( p in m.getAll("Properties70.P") )
-					if( p.props[0].toString() == "Opacity" ) {
-						var v = p.props[4].toFloat();
-						if( v < 1 && v > 0.98 ) mat.blendMode = Add;
+				for( p in m.getAll("Properties70.P") ) {
+					var pval = p.props[4];
+					switch( p.props[0].toString() ) {
+					case "Opacity":
+						var v = pval.toFloat();
+						if( v < 1 && v > 0.98 && mat.blendMode == null ) mat.blendMode = Add;
+					case pname:
+						if( StringTools.startsWith(pname, "3dsMax|heaps|_") ) {
+							hasHeapsProps = true;
+							switch( pname.substr(14) ) {
+							case "blend":
+								mat.blendMode = ([null, None, Alpha, Add, SoftAdd] : Array<h2d.BlendMode>)[pval.toInt() - 1];
+							case "shadows":
+								switch( pval.toInt() ) {
+								case 2:
+									mat.flags.unset(CastShadows);
+									mat.flags.unset(ReceiveShadows);
+								case 3:
+									mat.flags.unset(CastShadows);
+								case 4:
+									mat.flags.unset(ReceiveShadows);
+								}
+							case "lighting":
+								if( pval.toInt() == 0 ) mat.flags.unset(HasLighting);
+							case "twoSided":
+								if( pval.toInt() == 1 ) mat.culling = None;
+							case "killAlpha":
+								if( pval.toInt() == 1 ) mat.killAlpha = 1;
+							case "killAlphaThreshold":
+								if( mat.killAlpha != null ) mat.killAlpha = pval.toFloat();
+							case "decal":
+								if( pval.toInt() == 1 ) mat.flags.set(IsVolumeDecal);
+							case "wrap":
+								if( pval.toInt() == 1 ) mat.flags.set(TextureWrap);
+							case name:
+								throw "Unknown heaps property " + name;
+							}
+						}
 					}
+				}
 
 				// get texture
 				var texture = getSpecChild(m, "DiffuseColor");
@@ -456,11 +493,17 @@ class HMDOut extends BaseLibrary {
 					if( path != "" ) {
 						if( texture != null && path.toLowerCase() == texture.get("FileName").props[0].toString().toLowerCase() ) {
 							// if that's the same file, we're doing alpha blending
-							mat.blendMode = Alpha;
+							if( mat.blendMode == null ) mat.blendMode = Alpha;
 						} else
 							throw "TODO : alpha texture";
 					}
 				}
+
+				if( hasHeapsProps ) {
+					if( mat.props == null ) mat.props = [];
+					mat.props.push(HasMaterialFlags);
+				}
+				if( mat.blendMode == null ) mat.blendMode = None;
 			}
 
 			var g = getChild(o.model, "Geometry");

+ 20 - 0
hxd/fmt/hmd/Data.hx

@@ -40,6 +40,7 @@ typedef Index<T> = Int;
 
 enum Property<T> {
 	CameraFOVY( v : Float ) : Property<Float>;
+	HasMaterialFlags;
 }
 
 typedef Properties = Null<Array<Property<Dynamic>>>;
@@ -117,13 +118,32 @@ class Geometry {
 	}
 }
 
+enum MaterialFlag {
+	HasLighting;
+	CastShadows;
+	ReceiveShadows;
+	TextureWrap;
+	IsVolumeDecal;
+}
+
 class Material {
+
+	public static var DEFAULT_FLAGS = {
+		var f = new haxe.EnumFlags();
+		f.set(HasLighting);
+		f.set(CastShadows);
+		f.set(ReceiveShadows);
+		f;
+	}
+
 	public var name : String;
 	public var props : Properties;
 	public var diffuseTexture : Null<String>;
 	public var blendMode : h3d.mat.BlendMode;
 	public var culling : h3d.mat.Data.Face;
 	public var killAlpha : Null<Float>;
+	public var flags : haxe.EnumFlags<MaterialFlag>;
+
 	public function new() {
 	}
 }

+ 11 - 2
hxd/fmt/hmd/Dump.hx

@@ -20,8 +20,13 @@ class Dump {
 
 	function addProps( props : Properties ) {
 		if( props == null ) return;
-		for( p in props )
-			add(Type.enumConstructor(p) + " : " + [for( p in Type.enumParameters(p) ) Std.string(p)].join(", "));
+		for( p in props ) {
+			var params = Type.enumParameters(p);
+			if( params.length == 0 )
+				add(Type.enumConstructor(p));
+			else
+				add(Type.enumConstructor(p) + " : " + [for( p in params ) Std.string(p)].join(", "));
+		}
 	}
 
 	public function dump( h : Data ) : String {
@@ -49,6 +54,7 @@ class Dump {
 			prefix = "";
 		}
 		if( h.geometries.length > 0 ) add('');
+		var flags = MaterialFlag.createAll();
 		for( k in 0...h.materials.length ) {
 			var m = h.materials[k];
 			add('@$k MATERIAL');
@@ -59,6 +65,9 @@ class Dump {
 			if( m.diffuseTexture != null ) add('Texture : ${m.diffuseTexture}');
 			if( m.killAlpha != null ) add('KillAlpha : ${m.killAlpha}');
 			addProps(m.props);
+			for( f in flags )
+				if( m.flags.has(f) )
+					add(f);
 			prefix = "";
 		}
 		if( h.materials.length > 0 ) add('');

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

@@ -253,7 +253,7 @@ class Library {
 		return p;
 	}
 
-	function makeMaterial( mid : Int, loadTexture : String -> h3d.mat.Texture ) {
+	function makeMaterial( model : Model, mid : Int, loadTexture : String -> h3d.mat.Texture ) {
 		var m = header.materials[mid];
 		var mat = new h3d.mat.MeshMaterial();
 		mat.name = m.name;
@@ -268,6 +268,17 @@ class Library {
 			t.killAlpha = true;
 			t.killAlphaThreshold = m.killAlpha;
 		}
+		if( m.props != null && m.props.indexOf(HasMaterialFlags) >= 0 ) {
+			if( m.flags.has(HasLighting) ) mat.mainPass.enableLights = true;
+			if( m.flags.has(CastShadows) ) mat.castShadows = true;
+			if( m.flags.has(ReceiveShadows) ) mat.receiveShadows = true;
+			if( m.flags.has(IsVolumeDecal) ) {
+				var s = h3d.mat.Defaults.makeVolumeDecal(header.geometries[model.geometry].bounds);
+				mat.mainPass.addShader(s);
+			}
+			if( m.flags.has(TextureWrap) )
+				mat.texture.wrap = Repeat;
+		}
 		return mat;
 	}
 
@@ -338,11 +349,11 @@ class Library {
 				if( m.skin != null ) {
 					var skinData = makeSkin(m.skin);
 					skinData.primitive = prim;
-					obj = new h3d.scene.Skin(skinData, [for( m in m.materials ) makeMaterial(m, loadTexture)]);
+					obj = new h3d.scene.Skin(skinData, [for( mat in m.materials ) makeMaterial(m, mat, loadTexture)]);
 				} else if( m.materials.length == 1 )
-					obj = new h3d.scene.Mesh(prim, makeMaterial(m.materials[0],loadTexture));
+					obj = new h3d.scene.Mesh(prim, makeMaterial(m, m.materials[0],loadTexture));
 				else
-					obj = new h3d.scene.MultiMaterial(prim, [for( m in m.materials ) makeMaterial(m,loadTexture)]);
+					obj = new h3d.scene.MultiMaterial(prim, [for( mat in m.materials ) makeMaterial(m, mat, loadTexture)]);
 			}
 			obj.name = m.name;
 			obj.defaultTransform = m.position.toMatrix();

+ 4 - 0
hxd/fmt/hmd/Reader.hx

@@ -17,6 +17,8 @@ class Reader {
 		switch( i.readByte() ) {
 		case 0:
 			return CameraFOVY(i.readFloat());
+		case 1:
+			return HasMaterialFlags;
 		case unk:
 			throw "Unknown property #" + unk;
 		}
@@ -141,6 +143,8 @@ class Reader {
 			m.culling = CULLING[i.readByte()];
 			m.killAlpha = i.readFloat();
 			if( m.killAlpha == 1 ) m.killAlpha = null;
+			if( m.props != null && m.props.indexOf(HasMaterialFlags) >= 0 )
+				m.flags = haxe.EnumFlags.ofInt(i.readInt32());
 			d.materials.push(m);
 		}
 

+ 3 - 0
hxd/fmt/hmd/Writer.hx

@@ -15,6 +15,7 @@ class Writer {
 		switch( p ) {
 		case CameraFOVY(v):
 			out.writeFloat(v);
+		case HasMaterialFlags:
 		}
 	}
 
@@ -133,6 +134,8 @@ class Writer {
 			out.writeByte(m.blendMode.getIndex());
 			out.writeByte(m.culling.getIndex());
 			writeFloat(m.killAlpha == null ? 1 : m.killAlpha);
+			if( m.props != null && m.props.indexOf(HasMaterialFlags) >= 0 )
+				out.writeInt32(m.flags.toInt());
 		}
 
 		out.writeInt32(d.models.length);

+ 14 - 22
tools/fbx/Viewer.hx

@@ -139,8 +139,6 @@ class Viewer extends hxd.App {
 		axis.lineTo(0, 0, len);
 
 		light = new h3d.scene.DirLight(new h3d.Vector(-4, -3, -10), s3d);
-		var shadows = Std.instance(s3d.renderer.getPass("shadow"), h3d.pass.ShadowMap);
-		shadows.power = 10;
 
 		if( props.curFile != null )
 			loadFile(props.curFile, false);
@@ -329,7 +327,6 @@ class Viewer extends hxd.App {
 		var mat = new h3d.mat.MeshMaterial(t);
 		loadTexture(textureName, mat);
 		mat.mainPass.getShader(h3d.shader.Texture).killAlpha = true;
-		mat.mainPass.culling = Both;
 		mat.mainPass.blend(SrcAlpha, OneMinusSrcAlpha);
 		for( p in matData.getAll("Properties70.P") )
 			if( p.props[0].toString() == "TransparencyFactor" && p.props[4].toFloat() < 0.999 ) {
@@ -349,8 +346,7 @@ class Viewer extends hxd.App {
 			if( texBasePath.join("/") != fileBasePath.join("/") ) {
 				fileBasePath.push(texFile);
 				loadTexture(fileBasePath.join("/"), mat, handleAlpha);
-			} else
-				mat.mainPass.culling = None;
+			}
 		}
 		if( textureName.split(".").pop().toLowerCase() == "png" && handleAlpha ) {
 			var loader = new flash.net.URLLoader();
@@ -368,8 +364,6 @@ class Viewer extends hxd.App {
 				}
 				t.resize(size.width, size.height);
 				t.uploadPixels(new hxd.Pixels(size.width,size.height,pixels,BGRA));
-				mat.mainPass.culling = None;
-				if( !t.flags.has(IsNPOT) ) t.wrap = Repeat;
 			});
 			loader.load(new flash.net.URLRequest(textureName));
 		} else {
@@ -379,8 +373,6 @@ class Viewer extends hxd.App {
 				var bmp = flash.Lib.as(loader.content, flash.display.Bitmap).bitmapData;
 				t.resize(bmp.width, bmp.height);
 				t.uploadBitmap(hxd.BitmapData.fromNative(bmp));
-				mat.mainPass.culling = None;
-				if( !t.flags.has(IsNPOT) ) t.wrap = Repeat;
 			});
 			loader.load(new flash.net.URLRequest(textureName));
 		}
@@ -452,13 +444,6 @@ class Viewer extends hxd.App {
 				return t;
 			});
 
-			for( m in obj.getMaterials() ) {
-				var t = m.mainPass.getShader(h3d.shader.Texture);
-				m.mainPass.culling = None;
-				if( t != null) t.killAlpha = true;
-				if( m.mainPass.blendDst == Zero ) m.mainPass.blend(SrcAlpha, OneMinusSrcAlpha);
-			}
-
 		} else {
 
 			curFbx = new hxd.fmt.fbx.Library();
@@ -491,10 +476,6 @@ class Viewer extends hxd.App {
 
 		setMaterial();
 		setAnim();
-
-		for( m in obj.getMaterials() )
-			m.shadows = true;
-
 		showChecker(props.checker);
 
 		save();
@@ -580,8 +561,20 @@ class Viewer extends hxd.App {
 	}
 
 	function setMaterial( ?o : h3d.scene.Object ) {
-		if( o == null )
+		if( o == null ) {
 			o = obj;
+
+			var v = props.lights ? 1 : 0;
+			light.color.set(v, v, v, 1);
+			var v = props.lights ? 0.5 : 1;
+			s3d.lightSystem.ambientLight.set(v, v, v, 1);
+
+			var shadows = Std.instance(s3d.renderer.getPass("shadow"), h3d.pass.ShadowMap);
+			shadows.power = 10;
+			var v = props.lights ? 0.2 : 1;
+			shadows.color.set(v, v, v, 1);
+		}
+
 		if( o.isMesh() ) {
 			var m = o.toMesh();
 			var materials = [m.material];
@@ -591,7 +584,6 @@ class Viewer extends hxd.App {
 				if( m == null ) continue;
 				if( m.texture != null )
 					m.texture.filter = props.smoothing ? Linear : Nearest;
-				m.mainPass.enableLights = props.lights;
 			}
 			var s = Std.instance(o, h3d.scene.Skin);
 			if( s != null )

+ 31 - 0
tools/xtra/xtraExporter.ms

@@ -90,3 +90,34 @@ macroScript XtraExport Category:"Shiro" tooltip:"Add Extra Infos" buttontext:"XT
 )
 
 
+plugin material heapsMaterial
+name:"Heaps Material"
+classID:#(0x304e3c9e, 0x1ec538a1)
+extends:Standard version:1
+(
+  parameters heaps rollout:params (
+	  _blend type:#integer default:1 ui:ui_blend
+	  _lighting type:#boolean default:true ui:ui_lighting
+	  _shadows type:#integer default:1 ui:ui_shadows
+	  _killAlpha type:#boolean default:false ui:ui_killAlpha
+	  _killAlphaThreshold type:#float default:1 ui:ui_killAlphaThreshold
+	  _twoSided type:#boolean default:false ui:ui_twoSided
+	  _decal type:#boolean default:false ui:ui_decal
+	  _wrap type:#boolean default:false ui:ui_wrap
+  )
+  
+  rollout params "Heaps Parameters"
+  (
+	  dropdownlist ui_blend "Blend Mode" items:#("Auto","None","Alpha","Add","SoftAdd") width:80
+	  dropdownlist ui_shadows "Shadows" items:#("Active","None","Receive","Cast") width:80 offset:[100,-45]
+	  checkbox ui_lighting "Use Lighting"
+	  checkbox ui_twoSided "Two Sided"
+	  checkbox ui_killAlpha "Kill Alpha"
+	  spinner ui_killAlphaThreshold "Threshold" type:#float align:#left range:[0,1,0] fieldWidth:30 offset:[100,-19]
+	  checkbox ui_wrap "Texture Wrap"
+	  checkbox ui_decal "Volume Decal"
+  )
+  on create do
+  (
+  )
+)