Skip to content

Instantly share code, notes, and snippets.

@rdeioris
Created May 28, 2019 11:14
Show Gist options
  • Save rdeioris/f1fd87c4900140dcc0939781848fa81e to your computer and use it in GitHub Desktop.
Save rdeioris/f1fd87c4900140dcc0939781848fa81e to your computer and use it in GitHub Desktop.
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