Advertisement
Guest User

Untitled

a guest
May 30th, 2015
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.91 KB | None | 0 0
  1. using Psychomix.EngineMath;
  2. using Psychomix.Mesh;
  3. using SharpDX;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8.  
  9. namespace Psychomix.Animation
  10. {
  11.     using SharpDX.Toolkit;
  12.     using SharpDX.Toolkit.Graphics;
  13.     using System.Diagnostics;
  14.     using TribeGame.Animation;
  15.  
  16.     public class SkinningModel
  17.     {
  18.         public class SkinnedBone
  19.         {
  20.             public string Name;
  21.             public int IndexGlobal;
  22.             public SRTMatrix BindTransform;
  23.             public SRTMatrix DefaultTransform;
  24.         }
  25.  
  26.         public class Skeleton
  27.         {
  28.             public SkinnedBone[] Bones;
  29.             public int[][] Hierarchy;
  30.             public int RootBone;
  31.  
  32.             public int[] HierarchyOrderAccess;
  33.  
  34.             private Dictionary<string, int> _indexHashtable;
  35.  
  36.             public void BuildIndexHash()
  37.             {
  38.                 _indexHashtable = new Dictionary<string, int>();
  39.                 for (int i = 0; i < Bones.Length; i++)
  40.                 {
  41.                     _indexHashtable.Add(Bones[i].Name, i);
  42.                 }
  43.             }
  44.  
  45.             public int GetBoneIndex(string name)
  46.             {
  47.                 if(!_indexHashtable.ContainsKey(name))
  48.                     return -1;
  49.  
  50.                 return _indexHashtable[name];
  51.             }
  52.  
  53.             public Matrix[] LocalToWorld(Matrix[] array)
  54.             {
  55.                 Matrix[] matrix = new Matrix[array.Length];
  56.  
  57.                 for (int i = 0; i < matrix.Length; i++)
  58.                 {
  59.                     int[] hierarchy = Hierarchy[i];
  60.  
  61.                     matrix[i] = array[i];
  62.  
  63.                     for (int h = 0; h < hierarchy.Length; h++)
  64.                     {
  65.                         matrix[i] *= array[hierarchy[h]];
  66.                     }
  67.                 }
  68.  
  69.                 return matrix;
  70.             }
  71.  
  72.             public Matrix[] WorldToLocal(Matrix[] array)
  73.             {
  74.                 Matrix[] matrix = new Matrix[array.Length];
  75.  
  76.                 for (int i = 0; i < matrix.Length; i++)
  77.                 {
  78.                     int boneID = HierarchyOrderAccess[i];
  79.                     int[] hierarchy = Hierarchy[boneID];
  80.  
  81.                     Matrix localMatrix = array[boneID];
  82.                     for (int h = 0; h < hierarchy.Length; h++)
  83.                     {
  84.                         Matrix invertH = Matrix.Invert(matrix[hierarchy[hierarchy.Length - h - 1]]);
  85.                         localMatrix *= invertH;
  86.                     }
  87.  
  88.                     matrix[boneID] = localMatrix;
  89.                 }
  90.  
  91.                 return matrix;
  92.             }
  93.         }
  94.  
  95.         public class GeometryMesh
  96.         {
  97.             public string Name;
  98.             public SkinnedBone[] SkinnedBones;
  99.             public Buffer<SkinningVertex> VertexBuffer;
  100.             public Buffer<uint> IndexBuffer;
  101.             public int IndexCount;
  102.         }
  103.  
  104.         public class Mesh
  105.         {
  106.             //TODO: NEED HIERARCHY
  107.             public SRTMatrix ModelWorldTransform;
  108.            
  109.             public string Name;
  110.             public GeometryMesh[] GeometryMeshes;
  111.         }
  112.  
  113.         private class BonesPresentation
  114.         {
  115.             public List<string> Names;
  116.             public int BoneCount { get { return Names.Count; } }
  117.             public BonesPresentation()
  118.             {
  119.                 Names = new List<string>();
  120.             }
  121.  
  122.             public void AddBone(string name)
  123.             {
  124.                 if (!Names.Contains(name))
  125.                     Names.Add(name);
  126.             }
  127.  
  128.             public int FindBone(string name)
  129.             {
  130.                 for (int i = 0; i < Names.Count; i++)
  131.                     if (Names[i].Equals(name)) return i;
  132.                 return -1;
  133.             }
  134.         }
  135.  
  136.         public GeometryMesh[] _geometryMeshes;
  137.         public Mesh[] _modelMeshes;
  138.         public Skeleton _modelSkeleton;
  139.         public AnimationClip[] _animationClips;
  140.  
  141.         //TODO: SKINNING MODEL DRAW, OTHER METHODS
  142.         public int[] BuildChannelMap(AnimationClip clip)
  143.         {
  144.             int[] channelMap = new int[clip.Bones.Length];
  145.  
  146.             for (int i = 0; i < clip.Bones.Length; i++)
  147.             {
  148.                 channelMap[i] = -1;
  149.  
  150.                 foreach (SkinningModel.SkinnedBone bone in _modelSkeleton.Bones)
  151.                 {
  152.                     if (bone.Name == clip.Bones[i].Name)
  153.                     {
  154.                         channelMap[i] = bone.IndexGlobal;
  155.                         break;
  156.                     }
  157.                 }
  158.             }
  159.  
  160.             return channelMap;
  161.         }
  162.  
  163.         //private Mesh
  164.         public static Assimp.PostProcessSteps DefaultPPS = Assimp.PostProcessSteps.FlipUVs |
  165.                                                 Assimp.PostProcessSteps.FlipWindingOrder |
  166.                                                 Assimp.PostProcessSteps.LimitBoneWeights |
  167.                                                 Assimp.PostProcessSteps.SplitByBoneCount |
  168.                                                 Assimp.PostProcessSteps.CalculateTangentSpace |
  169.                                                 Assimp.PostProcessSteps.Triangulate;
  170.  
  171.         public static SkinningModel Load(GraphicsDevice graphics, string path)
  172.         {
  173.             SkinningModel model = new SkinningModel();
  174.  
  175.             {
  176.                 Stopwatch stopwatch = new Stopwatch();
  177.  
  178.                 stopwatch.Start();
  179.  
  180.                 Assimp.AssimpImporter importer = new Assimp.AssimpImporter();
  181.                 Assimp.PostProcessSteps steps = DefaultPPS;
  182.  
  183.                
  184.                 Assimp.Scene scene = importer.ImportFile(path, steps);
  185.  
  186.                 stopwatch.Stop();
  187.                 Debug.WriteLine("Time (SkinnedModel) [ASSIMP-LOAD]: " + stopwatch.Elapsed.TotalMilliseconds + "ms");
  188.                 stopwatch.Restart();
  189.  
  190.                 if (!scene.HasAnimations)
  191.                     throw new InvalidOperationException("Model don't have animations!");
  192.                
  193.                 BonesPresentation bp = new BonesPresentation();
  194.                 for (int m = 0; m < scene.MeshCount; m++)
  195.                     foreach (Assimp.Bone assimpBone in scene.Meshes[m].Bones)
  196.                         //if (assimpBone.HasVertexWeights)
  197.                         {
  198.                             bp.AddBone(assimpBone.Name);
  199.                         }
  200.  
  201.                 model._modelSkeleton = new Skeleton();
  202.                 model._modelSkeleton.Bones = new SkinnedBone[bp.BoneCount];
  203.              
  204.                 /* GEOMETRY MESH LOAD */
  205.                 model._geometryMeshes = new GeometryMesh[scene.Meshes.Length];
  206.  
  207.                 for (int m = 0; m < model._geometryMeshes.Length; m++)
  208.                 {
  209.                     Assimp.Mesh assimpMesh = scene.Meshes[m];
  210.                    
  211.                     if(assimpMesh.Vertices.Length != assimpMesh.Normals.Length ||
  212.                        assimpMesh.Vertices.Length != assimpMesh.Tangents.Length ||
  213.                        assimpMesh.Vertices.Length != assimpMesh.BiTangents.Length)
  214.                         throw new InvalidOperationException("Problem with count Vertices and TBN data!");
  215.  
  216.                     Assimp.Vector3D[] uvChannel = assimpMesh.GetTextureCoords(0);
  217.  
  218.                     SkinningVertex[] vertices = new SkinningVertex[assimpMesh.Vertices.Length];
  219.                     uint[] indices = new uint[assimpMesh.Faces.Length * 3];
  220.  
  221.                     for (int i = 0; i < assimpMesh.Faces.Length; i++)
  222.                     {
  223.                         indices[3 * i + 0] = assimpMesh.Faces[i].Indices[0];
  224.                         indices[3 * i + 1] = assimpMesh.Faces[i].Indices[1];
  225.                         indices[3 * i + 2] = assimpMesh.Faces[i].Indices[2];
  226.                     }
  227.  
  228.                     /* PROCESS BLEND IW */
  229.                     bool hasWeights = false;
  230.                     int[] skinningCount = new int[assimpMesh.VertexCount];
  231.                     Int4[] skinningIndices = new Int4[assimpMesh.VertexCount];
  232.                     Vector4[] skinningWeights = new Vector4[assimpMesh.VertexCount];
  233.                     List<SkinnedBone> skinnedBones = new List<SkinnedBone>();
  234.  
  235.                     for (int b = 0; b < assimpMesh.Bones.Length; b++)
  236.                     {
  237.                         Assimp.Bone assimpBone = assimpMesh.Bones[b];
  238.  
  239.                             int skinnedBoneIndex = skinnedBones.Count;
  240.  
  241.                             SkinnedBone bone = new SkinnedBone();
  242.                             bone.Name = assimpBone.Name;
  243.                             bone.IndexGlobal = bp.FindBone(bone.Name);
  244.                             System.Diagnostics.Debug.Assert(bone.IndexGlobal != -1);
  245.  
  246.                             bone.BindTransform = MathCrossoverHelper._srtm(assimpBone.OffsetMatrix);
  247.                             model._modelSkeleton.Bones[bone.IndexGlobal] = bone;
  248.  
  249.                             if (assimpBone.HasVertexWeights)
  250.                             {
  251.                                 skinnedBones.Add(bone);
  252.  
  253.                                 for (int j = 0; j < assimpBone.VertexWeightCount; j++)
  254.                                 {
  255.                                     var weights = assimpBone.VertexWeights[j];
  256.                                     var vertexSkinningCount = skinningCount[weights.VertexID];
  257.  
  258.                                     skinningIndices[weights.VertexID][vertexSkinningCount] = skinnedBoneIndex;
  259.                                     skinningWeights[weights.VertexID][vertexSkinningCount] = weights.Weight;
  260.                                     skinningCount[weights.VertexID] = ++vertexSkinningCount;
  261.                                 }
  262.  
  263.                                 hasWeights = true;
  264.                             }
  265.                     }
  266.  
  267.                     /* VERTICES LOAD */
  268.                     for (int i = 0; i < vertices.Length; i++)
  269.                     {
  270.                         Vector3 position = MathCrossoverHelper._vc3(assimpMesh.Vertices[i]);
  271.                         Vector3 tangent = MathCrossoverHelper._vc3(assimpMesh.Tangents[i]);
  272.                         Vector3 bitangent = MathCrossoverHelper._vc3(assimpMesh.BiTangents[i]);
  273.                         Vector3 normal = MathCrossoverHelper._vc3(assimpMesh.Normals[i]);
  274.                         Vector2 uv = MathCrossoverHelper._vc2(uvChannel[i]);
  275.  
  276.                         vertices[i] = new SkinningVertex(position, uv, tangent, bitangent, normal);
  277.  
  278.                         System.Diagnostics.Debug.Assert(hasWeights);
  279.                         if (hasWeights)
  280.                         {
  281.                             Int4 blendIndices = skinningIndices[i];
  282.                             Vector4 blendWeight = skinningWeights[i];
  283.  
  284.                             vertices[i].BlendIndices = blendIndices;
  285.                             vertices[i].BlendWeights = blendWeight;
  286.                         }
  287.                     }
  288.  
  289.  
  290.                     GeometryMesh mesh = new GeometryMesh();
  291.                     mesh.Name = assimpMesh.Name;
  292.                     mesh.SkinnedBones = skinnedBones.ToArray();
  293.  
  294.                     // TODO: PACK VERTICES
  295.                     mesh.VertexBuffer = Buffer.New<SkinningVertex>(graphics, vertices, BufferFlags.VertexBuffer, SharpDX.Direct3D11.ResourceUsage.Immutable);
  296.                     mesh.IndexBuffer = Buffer.New<uint>(graphics, indices, BufferFlags.IndexBuffer, SharpDX.Direct3D11.ResourceUsage.Immutable);
  297.  
  298.                     mesh.IndexCount = indices.Length;
  299.  
  300.                     model._geometryMeshes[m] = mesh;
  301.                 }
  302.  
  303.                 model._modelSkeleton.BuildIndexHash();
  304.  
  305.                 /* LOAD MESHES */
  306.                 model._modelMeshes = _collectMesh(scene, ref model._geometryMeshes);
  307.  
  308.                 model._modelSkeleton.Hierarchy = new int[bp.BoneCount][];
  309.                
  310.                 /* LOAD SKELETON HIERARCHY */
  311.                 for (int i = 0; i < model._modelSkeleton.Bones.Length; i++)
  312.                 {
  313.                     SkinnedBone bone = model._modelSkeleton.Bones[i];
  314.  
  315.                     Assimp.Node bnode = _recursivityFindNode(scene.RootNode, bone.Name);
  316.  
  317.                     System.Diagnostics.Debug.Assert(bnode != null);
  318.  
  319.                     bone.DefaultTransform = MathCrossoverHelper._srtm(bnode.Transform);
  320.  
  321.                     List<int> hierarchy = new List<int>();
  322.  
  323.                     while (bnode.Parent != null)
  324.                     {
  325.                         SkinnedBone parent = null;
  326.                         /* FIND IN SKINNED CHUNK */
  327.                         for (int j = 0; j < model._modelSkeleton.Bones.Length; j++)
  328.                         {
  329.                             if (model._modelSkeleton.Bones[j].Name == bnode.Parent.Name)
  330.                             {
  331.                                 parent = model._modelSkeleton.Bones[j];
  332.                                 parent.DefaultTransform = MathCrossoverHelper._srtm(bnode.Parent.Transform);
  333.  
  334.                                 break;
  335.                             }
  336.                         }
  337.  
  338.                         if (parent == null)
  339.                             break;
  340.  
  341.  
  342.                         hierarchy.Add(parent.IndexGlobal);
  343.  
  344.                         bnode = bnode.Parent;
  345.                     }
  346.  
  347.                     model._modelSkeleton.Hierarchy[i] = hierarchy.ToArray();
  348.                 }
  349.  
  350.                 model._modelSkeleton.HierarchyOrderAccess = new int[model._modelSkeleton.Hierarchy.Length];
  351.                 for (int i = 0; i < model._modelSkeleton.HierarchyOrderAccess.Length; i++)
  352.                 {
  353.                     model._modelSkeleton.HierarchyOrderAccess[i] = i;
  354.                 }
  355.  
  356.                 model._modelSkeleton.HierarchyOrderAccess = model._modelSkeleton.HierarchyOrderAccess.OrderBy(
  357.                     c => model._modelSkeleton.Hierarchy[c].Length).ToArray();
  358.  
  359.                 model._animationClips = AnimationClip.LoadAnimations(scene);
  360.  
  361.                 Debug.WriteLine("Time (SkinnedModel) [PROCESSED]: " + stopwatch.Elapsed.TotalMilliseconds + "ms");
  362.  
  363.             }
  364.  
  365.            
  366.             return model;
  367.         }
  368.  
  369.         private static Mesh[] _collectMesh(Assimp.Scene scene, ref GeometryMesh[] geometryMeshes)
  370.         {
  371.             List<Mesh> meshes = new List<Mesh>();
  372.             _recursivityMeshCollect(scene.RootNode, ref meshes, ref geometryMeshes, Matrix.Identity);
  373.             return meshes.ToArray();
  374.         }
  375.  
  376.         private static void _recursivityMeshCollect(Assimp.Node node, ref List<Mesh> meshes, ref GeometryMesh[] geometryMeshes, Matrix previousMatrix)
  377.         {
  378.             if (node.HasMeshes)
  379.             {
  380.                 Mesh mesh = new Mesh();
  381.                 SRTMatrix localTransform = MathCrossoverHelper._srtm(node.Transform);
  382.                 mesh.ModelWorldTransform = previousMatrix * localTransform;
  383.  
  384.                 mesh.Name = node.Name;
  385.                
  386.                 mesh.GeometryMeshes = new GeometryMesh[node.MeshCount];
  387.                 for (int i = 0; i < node.MeshCount; i++)
  388.                     mesh.GeometryMeshes[i] = geometryMeshes[node.MeshIndices[i]];
  389.  
  390.                 meshes.Add(mesh);
  391.             }
  392.  
  393.             if (node.HasChildren)
  394.             {
  395.                 foreach (Assimp.Node children in node.Children)
  396.                     _recursivityMeshCollect(children, ref meshes, ref geometryMeshes, MathCrossoverHelper._srtm(node.Transform));
  397.             }
  398.         }
  399.  
  400.         private static Assimp.Node _recursivityFindNode(Assimp.Node node, string nodeName)
  401.         {
  402.             if (node.Name == nodeName)
  403.                 return node;
  404.  
  405.             if (node.HasChildren)
  406.             {
  407.                 foreach (Assimp.Node children in node.Children)
  408.                 {
  409.                     Assimp.Node result = _recursivityFindNode(children, nodeName);
  410.                     if (result != null)
  411.                         return result;
  412.                 }
  413.             }
  414.  
  415.             return null;
  416.         }
  417.     }
  418. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement