/// <summary> /// Export Animation /// </summary> /// <param name="filePath"></param> /// <param name="skeleton"></param> /// <param name="animation"></param> public void Export(string filePath, GenericSkeleton skeleton, GenericAnimation animation) { using (StreamWriter w = new StreamWriter(new FileStream(filePath, FileMode.Create))) { w.WriteLine("version 1"); if (skeleton != null) { w.WriteLine("nodes"); foreach (GenericBone bone in skeleton.Bones) { w.WriteLine($" {skeleton.IndexOf(bone)} \"{bone.Name}\" {bone.ParentIndex}"); } w.WriteLine("end"); w.WriteLine("skeleton"); for (int i = 0; i < animation.FrameCount; i++) { animation.UpdateSkeleton(i, skeleton); w.WriteLine("time " + i); foreach (GenericBone bone in skeleton.Bones) { GenericBone b = new GenericBone(); b.Transform = bone.GetTransform(true); w.WriteLine($" {skeleton.IndexOf(bone)} {b.Position.X} {b.Position.Y} {b.Position.Z} {b.Rotation.X} {b.Rotation.Y} {b.Rotation.Z}"); } } w.WriteLine("end"); } } }
/// <summary> /// /// </summary> /// <param name="skeleton"></param> /// <param name="animation"></param> /// <returns></returns> public bool ExportAnimation(GenericSkeleton skeleton, GenericAnimation animation) { var path = FileTools.GetSaveFile(animation.Name, GetAnimationExportFilter()); if (path != null && skeleton != null) { var ext = System.IO.Path.GetExtension(path).ToLower(); foreach (var v in AnimationExporters) { if (v.Extension().Equals(ext)) { v.Export(path, skeleton, animation); return(true); } } } return(false); }
private GenericVertex SingleBind(GenericVertex vert, GenericSkeleton s) { Vector3 p = Vector3.Zero; Vector3 n = Vector3.Zero; for (int i = 0; i < 1; i++) { if (vert.Weights[i] > 0) { n += Vector3.TransformNormal(vert.Nrm, s.GetWorldTransform((int)vert.Bones[i])); // * vert.Weights[i]; p += Vector3.TransformPosition(vert.Pos, s.GetWorldTransform((int)vert.Bones[i])); // * vert.Weights[i]; } } vert.Pos = p; vert.Nrm = n; return(vert); }
private static GenericSkeleton ReadSkel(string path) { GenericSkeleton skel = new GenericSkeleton(); using (DataReader r = new DataReader(path)) { r.BigEndian = false; r.Seek(0x10); var count = r.ReadInt16(); var count2 = r.ReadInt16(); var count3 = r.ReadInt32(); var boneInfoOffset = r.Position + r.ReadUInt32(); var boneParentInfoOffset = r.Position + r.ReadUInt32(); var hashOffset = r.Position + r.ReadUInt32(); // various hash table offsets for (uint i = 0; i < count; i++) { GenericBone b = new GenericBone(); r.Seek(boneInfoOffset + 48 * i); var rot = new OpenTK.Quaternion(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()).Inverted(); rot.Normalize(); b.QuaternionRotation = rot; b.Position = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.ReadSingle(); b.Scale = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.ReadSingle(); r.Seek(boneParentInfoOffset + 2 * i); b.ParentIndex = r.ReadInt16(); r.Seek(hashOffset + 4 * i); b.Name = "B_" + r.ReadInt32().ToString("X8"); skel.Bones.Add(b); } } return(skel); }
/// <summary> /// /// </summary> /// <param name="pos"></param> /// <param name="skel"></param> /// <param name="weights"></param> /// <param name="bones"></param> /// <param name="nunoBoneToBone"></param> /// <param name="normal"></param> /// <returns></returns> private Vector3 Weight(Vector3 pos, GenericSkeleton skel, Vector4 weights, Vector4 bones, Dictionary <int, int> nunoBoneToBone, bool normal = false) { Vector3 temp = Vector3.Zero; if (normal) { temp += Vector3.TransformNormal(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.X])) * weights.X; temp += Vector3.TransformNormal(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.Y])) * weights.Y; temp += Vector3.TransformNormal(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.Z])) * weights.Z; temp += Vector3.TransformNormal(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.W])) * weights.W; } else { temp += Vector3.TransformPosition(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.X])) * weights.X; temp += Vector3.TransformPosition(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.Y])) * weights.Y; temp += Vector3.TransformPosition(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.Z])) * weights.Z; temp += Vector3.TransformPosition(pos, skel.GetWorldTransform(nunoBoneToBone[(int)bones.W])) * weights.W; } return(temp); }
private void RigMe(Vector3 position, GenericSkeleton skel, Dictionary <int, int> nuno, out Vector4 bone, out Vector4 weight) { weight = new Vector4(); bone = new Vector4(); foreach (var v in nuno) { var t = skel.GetWorldTransform(v.Value); var p = Vector3.TransformPosition(Vector3.Zero, t); var dis = Vector3.Distance(position, p); for (int i = 0; i < 4; i++) { if (dis < weight[i] || weight[i] == 0) { weight[i] = dis; bone[i] = v.Value; break; } } } weight = weight.Normalized(); }
public GenericModel ToGenericModel() { GenericSkeleton skel = new GenericSkeleton(); foreach (var node in Nodes) { GenericBone bone = new GenericBone() { Name = node.Name, Position = node.Position, Rotation = node.Rotation, Scale = node.Scale, ParentIndex = node.ParentIndex }; skel.Bones.Add(bone); } GenericModel m = new GenericModel(); m.Skeleton = skel; // Textures var tindex = 0; foreach (var tex in Textures) { if (m.TextureBank.ContainsKey(tex.Name)) { tex.Name += "_" + tindex++; } m.TextureBank.Add(tex.Name, tex); } int index = -1; foreach (var meshObject in MeshObjects) { index++; Dictionary <int, List <GenericVertex> > MaterialToVertexBank = new Dictionary <int, List <GenericVertex> >(); //Console.WriteLine($"{meshObject.Key} {skel.Bones[meshObject.Value.SingleBind].Name}"); foreach (var d in meshObject.Value.Primitives) { if (!MaterialToVertexBank.ContainsKey(d.Material)) { MaterialToVertexBank.Add(d.Material, new List <GenericVertex>()); } var vertices = MaterialToVertexBank[d.Material]; switch (d.PrimitiveType) { case 0x02: // Triangle vertices.Add(GetVertex(meshObject.Value, d.Vertices[0], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[1], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[2], skel)); break; case 0x03: // Quad vertices.Add(GetVertex(meshObject.Value, d.Vertices[0], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[1], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[2], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[1], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[3], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[2], skel)); break; case 0x04: // Triangle Strip var verts = new List <GenericVertex>(); foreach (var dv in d.Vertices) { verts.Add(GetVertex(meshObject.Value, dv, skel)); } Tools.TriangleConverter.StripToList(verts, out verts); vertices.AddRange(verts); break; default: throw new Exception("Unsupported Primitive Type " + d.PrimitiveType.ToString("X")); } } foreach (var v in MaterialToVertexBank) { GenericMesh mesh = new GenericMesh(); mesh.Name = meshObject.Key; if (MaterialToVertexBank.Count > 1) { mesh.Name += "_" + m.Meshes.Count;// Textures[Materials[Materials1[v.Key].MaterialIndex].TextureIndex].Name; } GenericMaterial mat = new GenericMaterial(); mesh.MaterialName = "material_" + m.MaterialBank.Count; m.MaterialBank.Add(mesh.MaterialName, mat); var mat1Index = Materials1[v.Key].MaterialIndex; mat1Index = Math.Min(mat1Index, Materials.Count - 1); var textureIndex = Materials[mat1Index].TextureIndex; mat.TextureDiffuse = Textures[textureIndex].Name; m.Meshes.Add(mesh); mesh.Vertices.AddRange(v.Value); //Console.WriteLine(mesh.Name + " " + v.Key + " " + Materials[v.Key].TextureIndex + " " + Textures.Count + " " + Materials.Count); mesh.Optimize(); } } return(m); }
private GenericVertex GetVertex(MeshObject mesh, VertexGroup g, GenericSkeleton skeleton) { // Rigging Vector4 boneIndices = new Vector4(mesh.SingleBind, 0, 0, 0); Vector4 weight = new Vector4(1, 0, 0, 0); var Position = Vector3.Zero; if (g.PositionIndex < mesh.Positions.Count) { Position = mesh.Positions[g.PositionIndex]; } var bone = skeleton.Bones.Find(e => e.Name.Equals(mesh.Name)); if (bone != null) { boneIndices = new Vector4(skeleton.Bones.IndexOf(bone), 0, 0, 0); Position = Vector3.TransformPosition(Position, skeleton.GetWorldTransform(bone)); } foreach (var singleBind in mesh.SingleBinds) { if (g.PositionIndex >= singleBind.PositionIndex && g.PositionIndex < singleBind.PositionIndex + singleBind.PositionCount) { boneIndices = new Vector4(singleBind.BoneIndex, 0, 0, 0); break; } } int mbOffset = 0; foreach (var multiBind in mesh.DoubleBinds) { for (int i = mbOffset; i < mbOffset + multiBind.Count; i++) { var w = mesh.DoubleWeights[i]; if (g.PositionIndex >= w.PositionIndex && g.PositionIndex < w.PositionIndex + w.PositionCount) { boneIndices = new Vector4(multiBind.Bone1, multiBind.Bone2, 0, 0); weight = new Vector4(w.Weight, 1 - w.Weight, 0, 0); break; } } mbOffset += multiBind.Count; } mbOffset = 0; foreach (var multiBind in mesh.MultiBinds) { if (g.PositionIndex >= multiBind.PositionIndex && g.PositionIndex < multiBind.PositionIndex + multiBind.PositionCount) { boneIndices = new Vector4(0); weight = new Vector4(0); for (int i = mbOffset; i < mbOffset + multiBind.Count; i++) { boneIndices[i - mbOffset] = mesh.MultiWeights[i].BoneIndex; weight[i - mbOffset] = mesh.MultiWeights[i].Weight; } break; } mbOffset += multiBind.Count; } var uv = Vector2.Zero; var Normal = Vector3.Zero; var Color = Vector4.One; if (mesh.Normals.Count > 0 && g.NormalIndex < mesh.Normals.Count) { Normal = mesh.Normals[g.NormalIndex]; } if (mesh.Colors.Count > 0) { Normal = mesh.Colors[g.NormalIndex].Xyz; } if (g.UVIndex >= 0 && mesh.UVs.Count > 0 && g.UVIndex < mesh.UVs.Count) { uv = mesh.UVs[g.UVIndex]; } return(new GenericVertex() { Pos = Position, Nrm = Normal, // TODO: single bind normal Clr = Color, UV0 = uv, Bones = boneIndices, Weights = weight }); }
public GenericModel ToGenericModel() { var model = new GenericModel(); var skel = new GenericSkeleton(); model.Skeleton = skel; Level5_Resource resourceFile = null; var textureList = new List <GenericTexture>(); foreach (var f in Files) { //Console.WriteLine(f.Key); if (f.Key.EndsWith("RES.bin")) { resourceFile = new Level5_Resource(f.Value); model.Name = resourceFile.ModelName; } if (f.Key.EndsWith(".mbn")) { skel.Bones.Add(Level5_MBN.ToBone(f.Value)); } if (f.Key.EndsWith(".prm")) { model.Meshes.Add(Level5_PRM.ToGenericMesh(f.Value)); } if (f.Key.EndsWith(".atr")) { } if (f.Key.EndsWith(".xi")) { var tex = Level5_XI.ToGenericTexture(f.Value); tex.Name = f.Key; textureList.Add(tex); } } if (resourceFile == null) { return(model); } // add materials foreach (var mat in resourceFile.Materials) { GenericMaterial material = new GenericMaterial(); material.TextureDiffuse = mat.TexName; model.MaterialBank.Add(mat.Name, material); } // add textures for (int i = 0; i < textureList.Count; i++) { model.TextureBank.Add(resourceFile.TextureNames[i], textureList[i]); } // fix bones foreach (var bone in skel.Bones) { bone.Name = resourceFile.GetResourceName((uint)bone.ID); bone.ID = 0; } foreach (var bone in skel.Bones) { if (bone.ParentIndex == 0) { bone.ParentIndex = -1; } else { var parentName = resourceFile.GetResourceName((uint)bone.ParentIndex); bone.ParentIndex = skel.Bones.FindIndex(e => e.Name.Equals(parentName)); } } var boneIndex = 0; foreach (var bone in skel.Bones) { if (bone.Name.Equals("")) { bone.Name = "Bone_" + boneIndex++; } } foreach (var mesh in model.Meshes) { for (int i = 0; i < mesh.VertexCount; i++) { var vertex = mesh.Vertices[i]; Vector4 newBones = new Vector4(); for (int j = 0; j < 4; j++) { if (vertex.Weights[j] > 0) { var hash = BitConverter.ToUInt32(BitConverter.GetBytes(vertex.Bones[j]), 0); newBones[j] = skel.Bones.FindIndex(e => e.Name == resourceFile.GetResourceName(hash)); } } vertex.Bones = newBones; mesh.Vertices[i] = vertex; } } return(model); }