Created
          May 28, 2019 11:14 
        
      - 
      
- 
        Save rdeioris/f1fd87c4900140dcc0939781848fa81e to your computer and use it in GitHub Desktop. 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Text; | |
| using System.Threading.Tasks; | |
| using Assimp; | |
| using System.IO; | |
| namespace FbxImporter | |
| { | |
| struct Influence | |
| { | |
| public uint Bone; | |
| public float Weight; | |
| } | |
| class Joint | |
| { | |
| public string Name; | |
| public Matrix4x4 LocalTransform; | |
| public Matrix4x4 InverseBindPose; | |
| public int Parent; | |
| } | |
| class Program | |
| { | |
| static int GetBoneIndex(List<Joint> bonesMapping, string name) | |
| { | |
| for (int i = 0; i < bonesMapping.Count; i++) | |
| { | |
| if (bonesMapping[i].Name == name) | |
| return i; | |
| } | |
| throw new Exception("unable to find bone"); | |
| return 0; | |
| } | |
| static void BuildBonesMapping(List<Joint> bonesMapping, Node node, Dictionary<string, Bone> bones, int parent) | |
| { | |
| Joint joint = new Joint(); | |
| joint.Name = node.Name; | |
| joint.LocalTransform = node.Transform; | |
| joint.Parent = parent; | |
| if (bones.ContainsKey(node.Name)) | |
| { | |
| joint.InverseBindPose = bones[node.Name].OffsetMatrix; | |
| } | |
| else if (parent > -1) | |
| { | |
| joint.InverseBindPose = bonesMapping[parent].InverseBindPose; | |
| } | |
| bonesMapping.Add(joint); | |
| parent = bonesMapping.Count() - 1; | |
| foreach (Node child in node.Children) | |
| { | |
| BuildBonesMapping(bonesMapping, child, bones, parent); | |
| } | |
| } | |
| static Matrix4x4 BuildGlobalMatrix(List<Joint> bonesMapping, Joint bone) | |
| { | |
| Matrix4x4 matrix = bone.LocalTransform; | |
| int parentId = bone.Parent; | |
| while (parentId != -1) | |
| { | |
| Joint parent = bonesMapping[parentId]; | |
| matrix *= parent.LocalTransform; | |
| parentId = parent.Parent; | |
| } | |
| return matrix; | |
| } | |
| static Matrix4x4 BuildGlobalAnimationMatrix(List<Joint> bonesMapping, Joint bone, Dictionary<string, Matrix4x4> animation) | |
| { | |
| Matrix4x4 matrix = bone.LocalTransform; | |
| if (animation.ContainsKey(bone.Name)) | |
| { | |
| matrix = animation[bone.Name]; | |
| } | |
| int parentId = bone.Parent; | |
| while (parentId != -1) | |
| { | |
| Joint parent = bonesMapping[parentId]; | |
| if (animation.ContainsKey(parent.Name)) | |
| { | |
| matrix *= animation[parent.Name]; | |
| } | |
| else | |
| { | |
| matrix *= parent.LocalTransform; | |
| } | |
| parentId = parent.Parent; | |
| } | |
| Matrix4x4 inverseBind = bone.InverseBindPose; | |
| Console.WriteLine("--- " + bone.Name + " ---"); | |
| Console.WriteLine(bone.LocalTransform); | |
| Console.WriteLine(matrix); | |
| Console.WriteLine(inverseBind); | |
| return inverseBind * matrix; | |
| } | |
| static Matrix4x4 BuildGlobalAnimationMatrixRaw(List<Joint> bonesMapping, Joint bone, Dictionary<string, Matrix4x4> animation) | |
| { | |
| Matrix4x4 matrix = bone.LocalTransform; | |
| if (animation.ContainsKey(bone.Name)) | |
| { | |
| matrix = animation[bone.Name]; | |
| } | |
| int parentId = bone.Parent; | |
| while (parentId != -1) | |
| { | |
| Joint parent = bonesMapping[parentId]; | |
| if (animation.ContainsKey(parent.Name)) | |
| { | |
| matrix *= animation[parent.Name]; | |
| } | |
| else | |
| { | |
| matrix *= parent.LocalTransform; | |
| } | |
| parentId = parent.Parent; | |
| } | |
| Matrix4x4 inverseBind = bone.InverseBindPose; | |
| Console.WriteLine("--- " + bone.Name + " ---"); | |
| Console.WriteLine(bone.LocalTransform); | |
| Console.WriteLine(matrix); | |
| Console.WriteLine(inverseBind); | |
| return matrix; | |
| } | |
| static void WriteMatrix(BinaryWriter writer, Matrix4x4 matrix) | |
| { | |
| //matrix.Transpose(); | |
| Console.WriteLine(matrix); | |
| writer.Write(matrix.A1); | |
| writer.Write(matrix.A2); | |
| writer.Write(matrix.A3); | |
| writer.Write(matrix.A4); | |
| writer.Write(matrix.B1); | |
| writer.Write(matrix.B2); | |
| writer.Write(matrix.B3); | |
| writer.Write(matrix.B4); | |
| writer.Write(matrix.C1); | |
| writer.Write(matrix.C2); | |
| writer.Write(matrix.C3); | |
| writer.Write(matrix.C4); | |
| writer.Write(matrix.D1); | |
| writer.Write(matrix.D2); | |
| writer.Write(matrix.D3); | |
| writer.Write(matrix.D4); | |
| } | |
| static void Main(string[] args) | |
| { | |
| AssimpContext importer = new AssimpContext(); | |
| Scene scene = importer.ImportFile("C:/Users/rober/Downloads/aj_running.fbx", PostProcessSteps.Triangulate | PostProcessSteps.MakeLeftHanded | PostProcessSteps.CalculateTangentSpace); | |
| Console.WriteLine(scene.HasMeshes); | |
| Dictionary<string, Matrix4x4> animationMatrices = new Dictionary<string, Matrix4x4>(); | |
| Console.WriteLine(scene.AnimationCount); | |
| foreach (Animation animation in scene.Animations) | |
| { | |
| Console.WriteLine(animation.DurationInTicks); | |
| foreach (NodeAnimationChannel channel in animation.NodeAnimationChannels) | |
| { | |
| Matrix4x4 rotMatrix = new Matrix4x4(channel.RotationKeys[0].Value.GetMatrix()); | |
| Matrix4x4 matrix = Matrix4x4.FromScaling(channel.ScalingKeys[0].Value) * rotMatrix * Matrix4x4.FromTranslation(channel.PositionKeys[0].Value); | |
| //matrix = Matrix4x4.FromScaling(channel.ScalingKeys[0].Value); | |
| //matrix = Matrix4x4.FromTranslation(channel.PositionKeys[0].Value) * Matrix4x4.FromScaling(channel.ScalingKeys[0].Value); | |
| //matrix = Matrix4x4.FromTranslation(channel.PositionKeys[0].Value) * new Matrix4x4(channel.RotationKeys[0].Value.GetMatrix()) * Matrix4x4.FromScaling(channel.ScalingKeys[0].Value); | |
| animationMatrices.Add(channel.NodeName, matrix); | |
| // Console.WriteLine(channel.NodeName + ": " + channel.PositionKeys[0].Value + ": " + channel.ScalingKeys[0].Value + ": " + matrix); | |
| } | |
| } | |
| // Console.ReadLine(); | |
| Dictionary<int, List<Influence>> influences = new Dictionary<int, List<Influence>>(); | |
| Dictionary<string, Bone> offsets = new Dictionary<string, Bone>(); | |
| foreach (Mesh mesh in scene.Meshes) | |
| { | |
| FileStream file = new FileStream("test001.mesh", FileMode.Create); | |
| BinaryWriter writer = new BinaryWriter(file); | |
| Console.WriteLine("{0} {1} {2}", mesh.FaceCount * 3, mesh.VertexCount, mesh.Normals.Count); | |
| foreach (Bone bone in mesh.Bones) | |
| { | |
| Console.WriteLine(bone.Name); | |
| offsets.Add(bone.Name, bone); | |
| } | |
| List<Joint> bonesMapping = new List<Joint>(); | |
| foreach (Node child in scene.RootNode.Children) | |
| { | |
| BuildBonesMapping(bonesMapping, child, offsets, -1); | |
| } | |
| for (int i = 0; i < bonesMapping.Count; i++) | |
| { | |
| Console.WriteLine("{0} {1}", i, bonesMapping[i].Name); | |
| } | |
| foreach (Bone bone in mesh.Bones) | |
| { | |
| foreach (VertexWeight vw in bone.VertexWeights) | |
| { | |
| if (!influences.ContainsKey(vw.VertexID)) | |
| { | |
| influences.Add(vw.VertexID, new List<Influence>()); | |
| } | |
| // no more than 8 influences | |
| if (influences[vw.VertexID].Count < 8) | |
| influences[vw.VertexID].Add(new Influence { Bone = (uint)GetBoneIndex(bonesMapping, bone.Name), Weight = vw.Weight }); | |
| } | |
| } | |
| writer.Write((uint)mesh.FaceCount); | |
| writer.Write((uint)bonesMapping.Count); | |
| for (int i = 0; i < bonesMapping.Count; i++) | |
| { | |
| Joint joint = bonesMapping[i]; | |
| //WriteMatrix(writer, bones[bone.Name].GetGlobalTransform()); | |
| Console.Write(joint.Name + ": "); | |
| writer.Write(joint.Parent); | |
| } | |
| for (int i = 0; i < bonesMapping.Count; i++) | |
| { | |
| Joint joint = bonesMapping[i]; | |
| //WriteMatrix(writer, bones[bone.Name].GetGlobalTransform()); | |
| Console.Write(joint.Name + ": "); | |
| WriteMatrix(writer, BuildGlobalAnimationMatrixRaw(bonesMapping, joint, animationMatrices)); | |
| } | |
| for (int i = 0; i < bonesMapping.Count; i++) | |
| { | |
| Joint joint = bonesMapping[i]; | |
| //WriteMatrix(writer, bones[bone.Name].GetGlobalTransform()); | |
| Console.Write(joint.Name + ": "); | |
| //WriteMatrix(writer, BuildGlobalMatrix(bonesMapping, joint)); | |
| WriteMatrix(writer, BuildGlobalAnimationMatrix(bonesMapping, joint, animationMatrices)); | |
| //WriteMatrix(writer, BuildGlobalAnimationMatrix(scene.RootNode, animationMatrices, scene.RootNode.FindNode(bone.Name), bone.OffsetMatrix)); | |
| } | |
| //Console.WriteLine(writer.BaseStream.Position); | |
| foreach (Face face in mesh.Faces) | |
| { | |
| foreach (int index in face.Indices) | |
| { | |
| Vector3D vertex = mesh.Vertices[index]; | |
| Vector3D normal = mesh.Normals[index]; | |
| Vector3D tangent = mesh.Tangents[index]; | |
| Vector3D bitangent = mesh.BiTangents[index]; | |
| Vector3D uv = mesh.TextureCoordinateChannels[0][index]; | |
| writer.Write(vertex.X); | |
| writer.Write(vertex.Y); | |
| writer.Write(vertex.Z); | |
| writer.Write(normal.X); | |
| writer.Write(normal.Y); | |
| writer.Write(normal.Z); | |
| writer.Write(tangent.X); | |
| writer.Write(tangent.Y); | |
| writer.Write(tangent.Z); | |
| writer.Write(bitangent.X); | |
| writer.Write(bitangent.Y); | |
| writer.Write(bitangent.Z); | |
| writer.Write(uv.X); | |
| writer.Write(uv.Y); | |
| for (int i = 0; i < 8; i++) | |
| { | |
| if (i < influences[index].Count) | |
| { | |
| writer.Write(influences[index][i].Bone); | |
| } | |
| else | |
| { | |
| writer.Write(0U); | |
| } | |
| } | |
| for (int i = 0; i < 8; i++) | |
| { | |
| if (i < influences[index].Count) | |
| { | |
| writer.Write(influences[index][i].Weight); | |
| } | |
| else | |
| { | |
| writer.Write(0.0f); | |
| } | |
| } | |
| } | |
| } | |
| writer.Close(); | |
| Console.ReadLine(); | |
| } | |
| } | |
| } | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment