private void SetData(ParamMorph value) { if(value == data) return; data = value; UpdateUI(); }
public void ImportOld(string filename, ModelFile model) { var importer = new DaeIMImpoter(); Root = importer.Import(filename); var skins = Root.Instances.OfType<SkinDeclaraion> ().ToArray(); var morphs = Root.Instances.OfType<MorphingDeclaraion>().ToArray(); var geoms = Root.Instances.OfType<Geometry> ().ToArray(); Vertices = new Dictionary<ModelVertex, int>(); Indices = new List<int>(); //Skins = new Dictionary<int, ModelSkin>(); if(morphs.Length > 0) { var geom = morphs.First().Source as Geometry; var mesh = geom.Get<Mesh>("Data"); var posch = mesh.Channels.FirstOrDefault(i => i.Semantic == GeometrySemantic.Position); var nrmch = mesh.Channels.FirstOrDefault(i => i.Semantic == GeometrySemantic.Normal); var texch = mesh.Channels.FirstOrDefault(i => i.Semantic == GeometrySemantic.TexCoord); var pos = posch.GetDataAsList<SlimDX.Vector3>(); var nrm = nrmch.GetDataAsList<SlimDX.Vector3>(); var tex = texch.GetDataAsList<SlimDX.Vector2>(); var posface = posch.GetIndicesAsList(mesh); var nrmface = nrmch.GetIndicesAsList(mesh); var texface = texch.GetIndicesAsList(mesh); var numidx = posface.Count; for(int i= 0; i < numidx; ++i) { var p = pos[posface[i]]; var n = nrm[nrmface[i]]; var t = tex[texface[i]]; var v = new ModelVertex() { P = new Vector3(p.X, p.Y, p.Z), N = new Vector3(n.X, n.Y, n.Z), T = new Vector2(t.X, t.Y), }; int index; if(!Vertices.TryGetValue(v, out index)) Vertices.Add(v, index= Vertices.Count); Indices.Add(index); } var prims = new List<ModelPrimitive>(); var start = 0; foreach(var i in mesh.Primitives) { var prim = new ModelPrimitive(); prim.Indices = Indices.Skip(start).Take(i.Count).Select(j => (ushort)j).ToList(); prim.NumIndices = Indices.Count; start +=Indices.Count; prims.Add(prim); } model.Mesh.Skins = Vertices.Keys .Select(i => model.Mesh.Skins[FindClosest(model.Mesh.Vertices, i.P)]) .ToList(); model.Mesh.Vertices = Vertices.Keys.ToList(); model.Mesh.NumVerts = model.Mesh.Vertices.Count; model.Mesh.Primitives = prims; model.Mesh.NumPrims = prims.Count; // モーフィング model.Params = model.Params.Where(i => !(i is ParamMorph)).ToList(); foreach(var i in morphs.First().Channels) { var mmesh = i.Geometry.Get<Mesh>("Data"); var mposch = mmesh.Channels.FirstOrDefault(j => j.Semantic == GeometrySemantic.Position); var mpos = mposch.GetDataAsList<SlimDX.Vector3>(); var mposidx = mposch.GetIndicesAsList(mmesh); var dic = new Dictionary<int, MorphVertex>(); var mnrm = new SlimDX.Vector3[mpos.Count]; // 法線計算 for(int j= 0; j < mposidx.Count; j+=3) { var a = mpos[mposidx[j+0]]; var b = mpos[mposidx[j+1]]; var c = mpos[mposidx[j+2]]; var ab = SlimDX.Vector3.Normalize(SlimDX.Vector3.Subtract(b, a)); var ac = SlimDX.Vector3.Normalize(SlimDX.Vector3.Subtract(c, a)); var n = SlimDX.Vector3.Normalize(SlimDX.Vector3.Cross(ab, ac)); mnrm[mposidx[j+0]] = SlimDX.Vector3.Add(mnrm[mposidx[j+0]], n); mnrm[mposidx[j+1]] = SlimDX.Vector3.Add(mnrm[mposidx[j+1]], n); mnrm[mposidx[j+2]] = SlimDX.Vector3.Add(mnrm[mposidx[j+2]], n); } for(int j= 0; j < mnrm.Length; ++j) mnrm[j] = SlimDX.Vector3.Normalize(mnrm[j]); for(int j= 0; j < mposidx.Count; ++j) { var ii = (ushort)Indices[j]; var v = model.Mesh.Vertices[ii]; var p = mpos[mposidx[j]]; var n = mnrm[mposidx[j]]; p.X -=v.P.X; p.Y -=v.P.Y; p.Z -=v.P.Z; n.X -=v.N.X; n.Y -=v.N.Y; n.Z -=v.N.Z; dic[ii] = new MorphVertex(ii, p.X, p.Y, p.Z, n.X, n.Y, n.Z); } var morph = new ParamMorph() { Name = i.Geometry.Name, Vertices = dic.OrderBy(j => j.Key).Select(j => j.Value).ToList(), NumVertices = dic.Count, }; model.Params.Insert(0, morph); } } else { throw new Exception(); } ModelFile.ToFile(model.FileName, model); System.Diagnostics.Debug.Print("終了"); }
public void ReplaceModel(ModelFile model, ModelFile refmodel) { var vertices= Vertices.Keys.ToList(); Closest = vertices.Select(i => FindClosest(refmodel.Mesh.Vertices, i.P)).ToList(); // スキンの生成 var sv = new List<ModelSkin>(); foreach(var i in Closest) sv.Add(refmodel.Mesh.Skins[i]); sv = Closest.Select(i => refmodel.Mesh.Skins[i]).ToList(); // モーフィングの作成 var rr = MorphMax - MorphMin; var morphs = new List<ParamMorph>(); foreach(var i in refmodel.Params.OfType<ParamMorph>()) // 元のモーフィングを列挙 { var dic = i.Vertices.ToDictionary(j => j.Index); var newmorph= new ParamMorph() { Vertices= new List<MorphVertex>() }; System.Diagnostics.Debug.Print("Morph:{0}", i.Name); morphs.Add(newmorph); for(int j= 0; j < vertices.Count; ++j) { var v1 = vertices[j]; // 新しい頂点 var v0 = refmodel.Mesh.Vertices[Closest[j]]; // 元の頂点で一番近いもの var x = v1.P.X - v0.P.X; var y = v1.P.Y - v0.P.Y; var z = v1.P.Z - v0.P.Z; var d = (float)Math.Sqrt(x*x + y*y + z*z); // 両頂点の距離 // 一定以上離れていたら、モーフィングを引き継がない if(d > MorphMax) { //System.Diagnostics.Debug.Print(" V {0} too far {1:F5}", // j.ToString().PadLeft(4), d); continue; } MorphVertex mv; // 元の頂点のモーフィングを検索 if(!dic.TryGetValue((ushort)Closest[j], out mv)) { //System.Diagnostics.Debug.Print(" V {0} => {1} not found", // j.ToString().PadLeft(4), Closest[j].ToString().PadLeft(4)); continue; } // 距離により影響度を算出(MorphMin:1.0 ... MorphMax:0.0) var r = d <= MorphMin ? 1.0f : 1 - (d - MorphMin) / rr; //r *=MorphScale; //var n0 = new Vector3(v0.N.X + mv.NX, v0.N.Y + mv.NY, v0.N.Z + mv.NZ); // 元の頂点のモーフィング後頂点 //System.Diagnostics.Debug.Print(" V {0} => {1} dist={2:F5} weight{3:F5}", // j.ToString().PadLeft(4), Closest[j].ToString().PadLeft(4), d, r); // モーフィング頂点の作成 newmorph.Vertices.Add(new MorphVertex() { Index = (ushort)j, X = mv.X * r, Y = mv.Y * r, Z = mv.Z * r, NX = mv.NX * r, NY = mv.NY * r, NZ = mv.NZ * r, //NX = (n0.X - v1.N.X) * r, //NY = (n0.Y - v1.N.Y) * r, //NZ = (n0.Z - v1.N.Z) * r, }); } System.Diagnostics.Debug.Print("Old={0} New={1}", i.Vertices.Count, newmorph.Vertices.Count); newmorph.Name = i.Name; newmorph.NumVertices= newmorph.Vertices.Count; } // モデルの更新 model.Mesh.Vertices = vertices; model.Mesh.NumVerts = vertices.Count; model.Mesh.Primitives = Primitives; model.Mesh.NumPrims = Primitives.Count; model.Mesh.Skins = sv; model.Params = model.Params.Where(i => !(i is ParamMorph)).ToList(); model.Params.InsertRange(0, morphs.Cast<Param>()); }