public void applyMorph(VisualParamEx vpx, Avatar av, float weight) { weight = Utils.Clamp(weight, 0.0f, 1.0f); float value = Utils.Lerp(vpx.MinValue, vpx.MaxValue, weight); // don't do anything for less than 1% change if (value > -0.001 && value < 0.001) return; // Morphs are mesh deforms if (vpx.pType == VisualParamEx.ParamType.TYPE_MORPH) { // Its a morph GLMesh mesh; if (_meshes.TryGetValue(vpx.morphmesh, out mesh)) { foreach (LindenMesh.Morph morph in mesh.Morphs) //optimise me to a dictionary { if (morph.Name == vpx.Name) { if (mesh.Name == "skirtMesh" && _showSkirt == false) return; // Logger.Log(String.Format("Applying morph {0} ID {2} weight {1} mesh {3}",morph.Name,weight,vpx.ParamID,mesh.Name),Helpers.LogLevel.Debug); mesh.morphmesh(morph, value); } } } } // Driver type // A driver drives multiple slave visual paramaters if (vpx.pType == VisualParamEx.ParamType.TYPE_DRIVER) { foreach (VisualParamEx.driven child in vpx.childparams) { /***** BEGIN UNGRACEFULL CODE STEALING ******/ // driven ________ // ^ /| |\ ^ // | / | | \ | // | / | | \ | // | / | | \ | // | / | | \ | //-------|----|-------|----|-------> driver // | min1 max1 max2 min2 if (child.hasMinMax == false) { applyMorph(av, child.id, weight); continue; } float driven_weight = vpx.DefaultValue; float driven_max = VisualParamEx.allParams[child.id].MaxValue; float driven_min = VisualParamEx.allParams[child.id].MinValue; float input_weight = weight; float min_weight = vpx.MinValue; float max_weight = vpx.MaxValue; if (input_weight <= child.min1) { if (child.min1 == child.max1 && child.min1 <= min_weight) { driven_weight = driven_max; } else { driven_weight = driven_min; } } else if (input_weight <= child.max1) { float t = (input_weight - child.min1) / (child.max1 - child.min1); driven_weight = driven_min + t * (driven_max - driven_min); } else if (input_weight <= child.max2) { driven_weight = driven_max; } else if (input_weight <= child.min2) { float t = (input_weight - child.max2) / (child.min2 - child.max2); driven_weight = driven_max + t * (driven_min - driven_max); } else { if (child.max2 >= max_weight) { driven_weight = driven_max; } else { driven_weight = driven_min; } } /***** END UNGRACEFULL CODE STEALING ******/ applyMorph(av, child.id, driven_weight); } return; } //Is this a bone deform? if (vpx.pType == VisualParamEx.ParamType.TYPE_BONEDEFORM) { // scale="0 0 .3" /> // value_min="-1" // value_max="1" foreach (KeyValuePair<string, BoneDeform> kvp in vpx.BoneDeforms) { skel.scalebone(kvp.Key, Vector3.One + (kvp.Value.scale * value)); skel.offsetbone(kvp.Key, kvp.Value.offset * value); } } }
public static void loadlindenmeshes2(string LODfilename) { // Already have mashes loaded? if (lindenMeshesLoaded) return; attachment_points.Clear(); string basedir = Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar + "character" + System.IO.Path.DirectorySeparatorChar; XmlDocument lad = new XmlDocument(); lad.Load(basedir + LODfilename); //Firstly read the skeleton section this contains attachment point info and the bone deform info for visual params // And load the skeleton file in to the bones class XmlNodeList skeleton = lad.GetElementsByTagName("skeleton"); string skeletonfilename = skeleton[0].Attributes.GetNamedItem("file_name").Value; Bone.loadbones(skeletonfilename); // Next read all the skeleton child nodes, we have attachment points and bone deform params // attachment points are an offset and rotation from a bone location // the name of the bone they reference is the joint paramater // params in the skeleton nodes are bone deforms, eg leg length changes the scale of the leg bones foreach (XmlNode skeletonnode in skeleton[0].ChildNodes) { if (skeletonnode.Name == "attachment_point") { attachment_point point = new attachment_point(skeletonnode); attachment_points.Add(point.id, point); } } // Parse all visual paramaters in one go // we can dedue type on the fly XmlNodeList paramss = lad.GetElementsByTagName("param"); foreach (XmlNode paramNode in paramss) { VisualParamEx vp = new VisualParamEx(paramNode); } //Now we parse the mesh nodes, mesh nodes reference a particular LLM file with a LOD XmlNodeList meshes = lad.GetElementsByTagName("mesh"); foreach (XmlNode meshNode in meshes) { string type = meshNode.Attributes.GetNamedItem("type").Value; int lod = Int32.Parse(meshNode.Attributes.GetNamedItem("lod").Value); string fileName = meshNode.Attributes.GetNamedItem("file_name").Value; GLMesh mesh = null; lock (_defaultmeshes) mesh = (_defaultmeshes.ContainsKey(type) ? _defaultmeshes[type] : new GLMesh(type)); // Set up the texture elemenets for each mesh // And hack the eyeball position switch (mesh.Name) { case "lowerBodyMesh": mesh.teFaceID = (int)AvatarTextureIndex.LowerBaked; break; case "upperBodyMesh": mesh.teFaceID = (int)AvatarTextureIndex.UpperBaked; break; case "headMesh": mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked; break; case "hairMesh": mesh.teFaceID = (int)AvatarTextureIndex.HairBaked; break; case "eyelashMesh": mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked; break; case "eyeBallRightMesh": mesh.teFaceID = (int)AvatarTextureIndex.EyesBaked; break; case "eyeBallLeftMesh": mesh.teFaceID = (int)AvatarTextureIndex.EyesBaked; break; case "skirtMesh": mesh.teFaceID = (int)AvatarTextureIndex.SkirtBaked; break; default: mesh.teFaceID = 0; break; } if (lod == 0) mesh.LoadMesh(basedir + fileName); else mesh.LoadLODMesh(lod, basedir + fileName); if (lod == 0) { switch (mesh.Name) { case "eyeBallLeftMesh": lock (Bone.mBones) mesh.setMeshPos(Bone.mBones["mEyeLeft"].getTotalOffset()); break; case "eyeBallRightMesh": lock (Bone.mBones) mesh.setMeshPos(Bone.mBones["mEyeRight"].getTotalOffset()); break; case "eyelashMesh": lock (Bone.mBones) mesh.setMeshPos(Bone.mBones["mHead"].getTotalOffset()); break; case "hairMesh": //mesh.setMeshPos(Bone.mBones["mHead"].getTotalOffset()); break; default: break; } } lock (_defaultmeshes) _defaultmeshes[type] = mesh; } lindenMeshesLoaded = true; }
public static void loadlindenmeshes2(string LODfilename) { // Already have mashes loaded? if (lindenMeshesLoaded) return; attachment_points.Clear(); //on android, Directory.GetCurrentDirectory() returns "/" which means root folder of the system. no folder or file can be added into "/" //I change character folder path as follow string basedir = Utility.GetCharacterDir(); UnityEngine.Debug.Log("avatar_lad.xml is in " + basedir); XmlDocument lad = new XmlDocument(); string path = basedir + LODfilename; if (!File.Exists(path)) { UnityEngine.Debug.Log(path + " doesn't exist! So we quit"); UnityEngine.Application.Quit(); } if (path.Contains("://")) { UnityEngine.WWW www = new UnityEngine.WWW(path); while(!www.isDone) ; lad.LoadXml(www.text); } else lad.Load(path); UnityEngine.Debug.Log("Successfully loaded avatar_lad.xml"); //Firstly read the skeleton section this contains attachment point info and the bone deform info for visual params // And load the skeleton file in to the bones class XmlNodeList skeleton = lad.GetElementsByTagName("skeleton"); string skeletonfilename = skeleton[0].Attributes.GetNamedItem("file_name").Value; Bone.loadbones(skeletonfilename); // Next read all the skeleton child nodes, we have attachment points and bone deform params // attachment points are an offset and rotation from a bone location // the name of the bone they reference is the joint paramater // params in the skeleton nodes are bone deforms, eg leg length changes the scale of the leg bones foreach (XmlNode skeletonnode in skeleton[0].ChildNodes) { if (skeletonnode.Name == "attachment_point") { attachment_point point = new attachment_point(skeletonnode); attachment_points.Add(point.id, point); } } // Parse all visual paramaters in one go // we can dedue type on the fly XmlNodeList paramss = lad.GetElementsByTagName("param"); foreach (XmlNode paramNode in paramss) { VisualParamEx vp = new VisualParamEx(paramNode); } //Now we parse the mesh nodes, mesh nodes reference a particular LLM file with a LOD XmlNodeList meshes = lad.GetElementsByTagName("mesh"); foreach (XmlNode meshNode in meshes) { string type = meshNode.Attributes.GetNamedItem("type").Value; int lod = Int32.Parse(meshNode.Attributes.GetNamedItem("lod").Value); string fileName = meshNode.Attributes.GetNamedItem("file_name").Value; GLMesh mesh = null; lock (_defaultmeshes) mesh = (_defaultmeshes.ContainsKey(type) ? _defaultmeshes[type] : new GLMesh(type)); // Set up the texture elemenets for each mesh // And hack the eyeball position switch (mesh.Name) { case "lowerBodyMesh": mesh.teFaceID = (int)AvatarTextureIndex.LowerBaked; break; case "upperBodyMesh": mesh.teFaceID = (int)AvatarTextureIndex.UpperBaked; break; case "headMesh": mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked; break; case "hairMesh": mesh.teFaceID = (int)AvatarTextureIndex.HairBaked; break; case "eyelashMesh": mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked; break; case "eyeBallRightMesh": mesh.teFaceID = (int)AvatarTextureIndex.EyesBaked; break; case "eyeBallLeftMesh": mesh.teFaceID = (int)AvatarTextureIndex.EyesBaked; break; case "skirtMesh": mesh.teFaceID = (int)AvatarTextureIndex.SkirtBaked; break; default: mesh.teFaceID = 0; break; } if (lod == 0) mesh.LoadMesh(basedir + fileName); else mesh.LoadLODMesh(lod, basedir + fileName); if (lod == 0) { switch (mesh.Name) { case "eyeBallLeftMesh": lock (Bone.mBones) mesh.setMeshPos(Bone.mBones["mEyeLeft"].getTotalOffset()); break; case "eyeBallRightMesh": lock (Bone.mBones) mesh.setMeshPos(Bone.mBones["mEyeRight"].getTotalOffset()); break; case "eyelashMesh": lock (Bone.mBones) mesh.setMeshPos(Bone.mBones["mHead"].getTotalOffset()); break; case "hairMesh": //mesh.setMeshPos(Bone.mBones["mHead"].getTotalOffset()); break; default: break; } } lock (_defaultmeshes) _defaultmeshes[type] = mesh; } lindenMeshesLoaded = true; }
public static void loadlindenmeshes2(string LODfilename) { // Already have mashes loaded? if (lindenMeshesLoaded) return; attachment_points.Clear(); string basedir = Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar + "character" + System.IO.Path.DirectorySeparatorChar; XmlDocument lad = new XmlDocument(); lad.Load(basedir + LODfilename); //Firstly read the skeleton section this contains attachment point info and the bone deform info for visual params // And load the skeleton file in to the bones class XmlNodeList skeleton = lad.GetElementsByTagName("skeleton"); string skeletonfilename = skeleton[0].Attributes.GetNamedItem("file_name").Value; Bone.loadbones(skeletonfilename); // Next read all the skeleton child nodes, we have attachment points and bone deform params // attachment points are an offset and rotation from a bone location // the name of the bone they reference is the joint paramater // params in the skeleton nodes are bone deforms, eg leg length changes the scale of the leg bones foreach (XmlNode skeletonnode in skeleton[0].ChildNodes) { if (skeletonnode.Name == "attachment_point") { attachment_point point = new attachment_point(skeletonnode); attachment_points.Add(point.id, point); } if (skeletonnode.Name == "param") { //Bone deform param VisualParamEx vp = new VisualParamEx(skeletonnode, VisualParamEx.ParamType.TYPE_BONEDEFORM); } } //Now we parse the mesh nodes, mesh nodes reference a particular LLM file with a LOD //and also list VisualParams for the various mesh morphs that can be applied XmlNodeList meshes = lad.GetElementsByTagName("mesh"); foreach (XmlNode meshNode in meshes) { string type = meshNode.Attributes.GetNamedItem("type").Value; int lod = Int32.Parse(meshNode.Attributes.GetNamedItem("lod").Value); string fileName = meshNode.Attributes.GetNamedItem("file_name").Value; GLMesh mesh = (_defaultmeshes.ContainsKey(type) ? _defaultmeshes[type] : new GLMesh(type)); if (meshNode.HasChildNodes) { foreach (XmlNode paramnode in meshNode.ChildNodes) { if (paramnode.Name == "param") { VisualParamEx vp = new VisualParamEx(paramnode, VisualParamEx.ParamType.TYPE_MORPH); mesh._evp.Add(vp.ParamID, vp); //Not sure we really need this may optimise out later vp.morphmesh = mesh.Name; } } } // Set up the texture elemenets for each mesh // And hack the eyeball position switch (mesh.Name) { case "lowerBodyMesh": mesh.teFaceID = (int)AvatarTextureIndex.LowerBaked; break; case "upperBodyMesh": mesh.teFaceID = (int)AvatarTextureIndex.UpperBaked; break; case "headMesh": mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked; break; case "hairMesh": mesh.teFaceID = (int)AvatarTextureIndex.HairBaked; break; case "eyelashMesh": mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked; break; case "eyeBallRightMesh": mesh.setMeshPos(Bone.mBones["mEyeLeft"].getTotalOffset()); //mesh.setMeshRot(Bone.getRotation("mEyeLeft")); mesh.teFaceID = (int)AvatarTextureIndex.EyesBaked; break; case "eyeBallLeftMesh": mesh.setMeshPos(Bone.mBones["mEyeRight"].getTotalOffset()); //mesh.setMeshRot(Bone.getRotation("mEyeRight")); mesh.teFaceID = (int)AvatarTextureIndex.EyesBaked; break; case "skirtMesh": mesh.teFaceID = (int)AvatarTextureIndex.SkirtBaked; break; default: mesh.teFaceID = 0; break; } if (lod == 0) mesh.LoadMesh(basedir + fileName); else mesh.LoadLODMesh(lod, basedir + fileName); _defaultmeshes[type] = mesh; } // Next are the textureing params, skipping for the moment XmlNodeList colors = lad.GetElementsByTagName("global_color"); { foreach (XmlNode globalcolornode in colors) { foreach (XmlNode node in globalcolornode.ChildNodes) { if (node.Name == "param") { VisualParamEx vp = new VisualParamEx(node, VisualParamEx.ParamType.TYPE_COLOR); } } } } // Get layer paramaters, a bit of a verbose way to do it but we probably want to get access // to some of the other data not just the <param> tag XmlNodeList layer_sets = lad.GetElementsByTagName("layer_set"); { foreach (XmlNode layer_set in layer_sets) { foreach (XmlNode layer in layer_set.ChildNodes) { foreach (XmlNode layernode in layer.ChildNodes) { if (layernode.Name == "param") { VisualParamEx vp = new VisualParamEx(layernode, VisualParamEx.ParamType.TYPE_COLOR); } } } } } // Next are the driver parameters, these are parameters that change multiple real parameters XmlNodeList drivers = lad.GetElementsByTagName("driver_parameters"); foreach (XmlNode node in drivers[0].ChildNodes) //lazy { if (node.Name == "param") { VisualParamEx vp = new VisualParamEx(node, VisualParamEx.ParamType.TYPE_DRIVER); } } lindenMeshesLoaded = true; }