浏览代码

DynamicBones: rework modelDatabase and Library for save/load dynamic bones properties

lviguier 7 月之前
父节点
当前提交
669835b3f3
共有 2 个文件被更改,包括 146 次插入84 次删除
  1. 134 66
      h3d/prim/ModelDatabase.hx
  2. 12 18
      hxd/fmt/hmd/Library.hx

+ 134 - 66
h3d/prim/ModelDatabase.hx

@@ -1,5 +1,13 @@
 package h3d.prim;
 
+typedef ModelDataInput = {
+	var resourceDirectory : String;
+	var resourceName : String;
+	var objectName : String;
+	var hmd : HMDModel;
+	var skin : h3d.scene.Skin;
+}
+
 class ModelDatabase {
 
 	public static var db : Map<String, Dynamic> = new Map();
@@ -22,7 +30,6 @@ class ModelDatabase {
 		return directory == null || directory == "" ? FILE_NAME : directory + "/" + FILE_NAME;
 	}
 
-
 	function getRootData( directory : String ) {
 		if( directory == null )
 			return null;
@@ -35,16 +42,18 @@ class ModelDatabase {
 		return value;
 	}
 
-	function getModelData( directory : String, key : String ) {
+	public function getModelData( directory : String, resourceName : String, modelName : String ) {
+		var key = resourceName + "/" + modelName;
 		var rootData = getRootData(directory);
 		cleanOldModelData(rootData, key);
 		return Reflect.field(rootData, key);
 	}
 
-	function saveModelData( directory : String, key : String, data : Dynamic ) {
+	function saveModelData( directory : String, resourceName : String, modelName : String, data : Dynamic ) {
 		var file = getFilePath(directory);
 
 		var rootData = getRootData(directory);
+		var key = resourceName + "/" + modelName;
 		if (data == null || Reflect.fields(data).length == 0)
 			Reflect.deleteField(rootData, key);
 		else
@@ -63,48 +72,112 @@ class ModelDatabase {
 		#end
 	}
 
+	function getDefaultLodConfig( dir : String ) : Array<Float> {
+		var fs = Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
+		if (fs == null)
+			return baseLodConfig;
+
+		#if (sys || nodejs)
+			var c = @:privateAccess fs.convert.getConfig(defaultLodConfigs, baseLodConfig, dir, function(fullObj) {
+				if (Reflect.hasField(fullObj, "lods.screenRatio"))
+					return Reflect.field(fullObj, "lods.screenRatio");
 
-	public function loadModelProps( objectName : String, hmd : HMDModel ) {
-		var key = @:privateAccess hmd.lib.resource.name + "/" + objectName;
-		var modelData : Dynamic = getModelData(@:privateAccess hmd.lib.resource.entry.directory, key);
+				return baseLodConfig;
+			});
+			return c;
+		#else
+			return baseLodConfig;
+		#end
 
-		loadLodConfig(modelData, hmd);
-		loadDynamicBonesConfig(modelData, hmd);
 	}
 
-	public function saveModelProps( objectName : String, hmd : HMDModel ) {
-		var key = @:privateAccess hmd.lib.resource.name + "/" + objectName;
-		var data : Dynamic = getModelData(@:privateAccess hmd.lib.resource.entry.directory, key);
-		if( data == null )
-			data = {};
+	// Used to clean previous version of modelDatabase, should be removed after some time
+	function cleanOldModelData( rootData : Dynamic, key : String) {
+		var oldLodConfig = Reflect.field(rootData, LOD_CONFIG);
+		if (oldLodConfig != null) {
+			for (f in Reflect.fields(oldLodConfig)) {
+				if (key.indexOf(f) < 0)
+					continue;
 
-		saveLodConfig(data, hmd);
-		saveDynamicBonesConfig(data, hmd);
+				var c = Reflect.field(oldLodConfig, f);
 
-		saveModelData(@:privateAccess hmd.lib.resource.entry.directory, @:privateAccess hmd.lib.resource.name + "/" + objectName, data);
-	}
+				var newData = { "lodConfig" : c };
+				Reflect.setField(rootData, key, newData);
 
+				// Remove old entry
+				Reflect.deleteField(oldLodConfig, f);
+				Reflect.setField(rootData, LOD_CONFIG, oldLodConfig);
+			}
 
-	function loadLodConfig( modelData : Dynamic, hmd : HMDModel ) {
-		var lodConfigs = Reflect.field(modelData, LOD_CONFIG);
-		@:privateAccess hmd.lodConfig = lodConfigs;
+			if (oldLodConfig == null || Reflect.fields(oldLodConfig).length == 0)
+				Reflect.deleteField(rootData, LOD_CONFIG);
+		}
 	}
 
-	function loadDynamicBonesConfig( modelData : Dynamic, hmd : HMDModel ) {
-		// TODO
+
+	function loadLodConfig( input : ModelDataInput, data : Dynamic ) {
+		var c = Reflect.field(data, LOD_CONFIG);
+		if (c == null || input.hmd == null)
+			return;
+		@:privateAccess input.hmd.lodConfig = c;
 	}
 
+	function loadDynamicBonesConfig( input : ModelDataInput, data : Dynamic) {
+		var c : Array<Dynamic> = Reflect.field(data, DYN_BONES_CONFIG);
+		if (c == null || input.skin == null)
+			return;
 
-	function saveLodConfig( data : Dynamic, hmd : HMDModel ) {
+		function getJointConf(j: h3d.anim.Skin.Joint) {
+			for (jConf in c)
+				if (jConf.name == j.name)
+					return jConf;
+
+			return null;
+		}
+
+		var skinData = input.skin.getSkinData();
+		for (j in skinData.allJoints) {
+			var jConf = getJointConf(j);
+			if (jConf == null)
+				continue;
+
+			var newJ = new h3d.anim.Skin.DynamicJoint();
+			newJ.index = j.index;
+			newJ.name = j.name;
+			newJ.bindIndex = j.bindIndex;
+			newJ.splitIndex = j.splitIndex;
+			newJ.defMat = j.defMat;
+			newJ.transPos = j.transPos;
+			newJ.parent = j.parent;
+			newJ.follow = j.follow;
+			newJ.subs = j.subs;
+			newJ.worldPos = j.worldPos;
+			newJ.offsets = j.offsets;
+			newJ.offsetRay = j.offsetRay;
+			newJ.retargetAnim = j.retargetAnim;
+			newJ.damping = jConf.damping;
+			newJ.resistance = jConf.resistance;
+			newJ.slackness = jConf.slackness;
+			newJ.stiffness = jConf.stiffness;
+			skinData.allJoints[j.index] = newJ;
+
+			j.parent?.subs.remove(j);
+			j.parent?.subs.push(newJ);
+		}
+
+		input.skin.setSkinData(skinData);
+	}
+
+	function saveLodConfig( input : ModelDataInput, data : Dynamic ) @:privateAccess {
 		var isDefaultConfig = true;
-		var defaultConfig = getDefaultLodConfig(@:privateAccess hmd.lib.resource.entry.directory);
+		var defaultConfig = getDefaultLodConfig(input.resourceDirectory);
 
-		if (@:privateAccess hmd.lodConfig != null) {
-			if (defaultConfig.length != @:privateAccess hmd.lodConfig.length)
+		if (input.hmd.lodConfig != null) {
+			if (defaultConfig.length != input.hmd.lodConfig.length)
 				isDefaultConfig = false;
 
-			for (idx in 0...@:privateAccess hmd.lodConfig.length) {
-				if (defaultConfig[idx] != @:privateAccess hmd.lodConfig[idx]) {
+			for (idx in 0...input.hmd.lodConfig.length) {
+				if (defaultConfig[idx] != input.hmd.lodConfig[idx]) {
 					isDefaultConfig = false;
 					break;
 				}
@@ -113,11 +186,11 @@ class ModelDatabase {
 
 		if (!isDefaultConfig) {
 			var c = [];
-			for (idx in 0...hmd.lodCount()) @:privateAccess {
-				if (idx >= hmd.lodConfig.length)
+			for (idx in 0...input.hmd.lodCount()) {
+				if (idx >= input.hmd.lodConfig.length)
 					c[idx] = 0.;
 				else
-					c[idx] = hmd.lodConfig[idx];
+					c[idx] = input.hmd.lodConfig[idx];
 			}
 			Reflect.setField(data, LOD_CONFIG, c);
 		}
@@ -125,51 +198,46 @@ class ModelDatabase {
 			Reflect.deleteField(data, LOD_CONFIG);
 	}
 
-	function saveDynamicBonesConfig( data : Dynamic, hmd : HMDModel ) {
-		// TODO
-	}
+	function saveDynamicBonesConfig( input : ModelDataInput, data : Dynamic ) {
+		if (input.skin == null)
+			return;
 
+		var dynamicJoints = [];
+		for (j in input.skin.getSkinData().allJoints) {
+			var dynJ = Std.downcast(j, h3d.anim.Skin.DynamicJoint);
+			if (dynJ == null)
+				continue;
 
-	function getDefaultLodConfig( dir : String ) : Array<Float> {
-		var fs = Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
-		if (fs == null)
-			return baseLodConfig;
-
-		#if (sys || nodejs)
-			var c = @:privateAccess fs.convert.getConfig(defaultLodConfigs, baseLodConfig, dir, function(fullObj) {
-				if (Reflect.hasField(fullObj, "lods.screenRatio"))
-					return Reflect.field(fullObj, "lods.screenRatio");
+			dynamicJoints.push({ name: dynJ.name, slackness: dynJ.slackness, stiffness: dynJ.stiffness, resistance: dynJ.resistance, damping: dynJ.damping });
+		}
 
-				return baseLodConfig;
-			});
-			return c;
-		#else
-			return baseLodConfig;
-		#end
+		if (dynamicJoints.length == 0) {
+			Reflect.deleteField(data, DYN_BONES_CONFIG);
+			return;
+		}
 
+		Reflect.setField(data, DYN_BONES_CONFIG, dynamicJoints);
 	}
 
-	// Used to clean previous version of modelDatabase, should be removed after some time
-	function cleanOldModelData( rootData : Dynamic, key : String) {
-		var oldLodConfig = Reflect.field(rootData, LOD_CONFIG);
-		if (oldLodConfig != null) {
-			for (f in Reflect.fields(oldLodConfig)) {
-				if (key.indexOf(f) < 0)
-					continue;
 
-				var c = Reflect.field(oldLodConfig, f);
+	public function loadModelProps( input : ModelDataInput ) {
+		var data : Dynamic = getModelData(input.resourceDirectory, input.resourceName, input.objectName);
+		if (data == null)
+			return;
 
-				var newData = { "lodConfig" : c };
-				Reflect.setField(rootData, key, newData);
+		loadLodConfig(input, data);
+		loadDynamicBonesConfig(input, data);
+	}
 
-				// Remove old entry
-				Reflect.deleteField(oldLodConfig, f);
-				Reflect.setField(rootData, LOD_CONFIG, oldLodConfig);
-			}
+	public function saveModelProps( input : ModelDataInput ) {
+		var data : Dynamic = getModelData(input.resourceDirectory, input.resourceName, input.objectName);
+		if( data == null )
+			data = {};
 
-			if (oldLodConfig == null || Reflect.fields(oldLodConfig).length == 0)
-				Reflect.deleteField(rootData, LOD_CONFIG);
-		}
+		saveLodConfig(input, data);
+		saveDynamicBonesConfig(input, data);
+
+		saveModelData(input.resourceDirectory, input.resourceName, input.objectName, data);
 	}
 
 	public static var current = new ModelDatabase();

+ 12 - 18
hxd/fmt/hmd/Library.hx

@@ -300,9 +300,6 @@ class Library {
 		p.incref(); // Prevent from auto-disposing
 		cachedPrimitives[id] = p;
 
-		if ( hasLod )
-			h3d.prim.ModelDatabase.current.loadModelProps(model.name, p);
-
 		return p;
 	}
 
@@ -353,22 +350,8 @@ class Library {
 		s.boundJoints = [];
 		s.rootJoints = [];
 
-		function isDynamic(dynName : String, j : SkinJoint) {
-			if (j.name.indexOf(dynName) >= 0)
-				return true;
-
-			var parent = j.parent >= 0 ? s.allJoints[j.parent] : null;
-			while(parent != null) {
-				if (parent.name.indexOf(dynName) >= 0)
-					return true;
-				parent = parent.parent;
-			}
-
-			return false;
-		}
-
 		for( joint in skin.joints ) {
-			var j = isDynamic('DYN', joint) ? new h3d.anim.Skin.DynamicJoint() : new h3d.anim.Skin.Joint();
+			var j = new h3d.anim.Skin.Joint();
 			j.name = joint.name;
 			j.index = s.allJoints.length;
 			j.defMat = joint.position.toMatrix();
@@ -508,7 +491,18 @@ class Library {
 			objs.push(obj);
 			var p = objs[m.parent];
 			if( p != null ) p.addChild(obj);
+
+			var modelData : h3d.prim.ModelDatabase.ModelDataInput = {
+				resourceDirectory : resource.entry.directory,
+				resourceName : resource.name,
+				objectName : obj.name,
+				hmd : Std.downcast(Std.downcast(obj, h3d.scene.Mesh)?.primitive, h3d.prim.HMDModel),
+				skin : Std.downcast(obj, h3d.scene.Skin)
+			}
+
+			h3d.prim.ModelDatabase.current.loadModelProps(modelData);
 		}
+
 		var o = objs[0];
 		if( o != null ) o.modelRoot = true;
 		return o;