public void CalcAnimation2(Node node, Animation ani, Matrix4x4 parent_transform)
        {
            NodeAnimationChannel n = FindChannel(ani, node.Name);

            Matrix4x4 node_transform = node.Transform;

            string node_name = node.Name;

            if (n != null)
            {
                node_transform = FindRotation(n);
            }
            Matrix4x4 global_transform = node_transform * parent_transform;

            if (m_bone_mapping.ContainsKey(node_name))
            {
                uint       bone_index = m_bone_mapping[node_name];
                BoneMatrix bi         = m_bone_matrices[(int)bone_index];
                //bi.final_world_transform = m_global_inverse_transform * global_transform * m_bone_matrices[(int)bone_index].offset_matrix;
                bi.final_world_transform         = m_bone_matrices[(int)bone_index].offset_matrix * global_transform * m_global_inverse_transform;
                m_bone_matrices[(int)bone_index] = bi;
                //counter++;
            }

            for (int i = 0; i < node.ChildCount; i++)
            {
                Node child = node.Children[i];
                CalcAnimation2(child, ani, global_transform);
            }
        }
        MAnimatedMesh processMesh(Mesh mesh, Scene scene)
        {
            Console.WriteLine("bones: ", mesh.BoneCount, " vertices: ", mesh.VertexCount);

            List <AnimatedVertex> vertices = new List <AnimatedVertex>();
            List <int>            indices  = new List <int>();

            //List<MTexture> textures = new List<MTexture>();
            VertexBoneData[] bones_id_weights_for_each_vertex = new VertexBoneData[mesh.VertexCount];
            for (int i = 0; i < bones_id_weights_for_each_vertex.Length; i++)
            {
                bones_id_weights_for_each_vertex[i].InitVertexBoneData();
            }

            //vertices
            for (int i = 0; i < mesh.VertexCount; i++)
            {
                AnimatedVertex vertex = new AnimatedVertex();
                Vector3        vector;
                vector.X         = mesh.Vertices[i].X;
                vector.Y         = mesh.Vertices[i].Y;
                vector.Z         = mesh.Vertices[i].Z;
                vertex._position = vector;

                if (mesh.Normals != null)
                {
                    vector.X       = mesh.Normals[i].X;
                    vector.Y       = mesh.Normals[i].Y;
                    vector.Z       = mesh.Normals[i].Z;
                    vertex._normal = vector;
                }
                else
                {
                    vertex._normal = Vector3.Zero;
                }

                // in assimp model can have 8 different texture coordinates
                // we only care about the first set of texture coordinates
                if (mesh.HasTextureCoords(0))
                {
                    Vector2 vec = new Vector2(0, 0);
                    vec.X = mesh.TextureCoordinateChannels[0][i].X;
                    vec.Y = mesh.TextureCoordinateChannels[0][i].Y;
                    vertex._textureCoordinate = vec;
                }
                else
                {
                    vertex._textureCoordinate = new Vector2(0.0f, 0.0f);
                }
                vertices.Add(vertex);
            }

            //int[] indices = mesh.GetIndices();

            //indices
            for (int i = 0; i < mesh.FaceCount; i++)
            {
                Face face = mesh.Faces[i];
                // retrieve all indices of the face and store them in the indices vector
                for (int j = 0; j < face.IndexCount; j++)
                {
                    indices.Add(face.Indices[j]);
                }
            }

            //Indices = indices.ToArray();


            //material

            /*
             * if (mesh.MaterialIndex >= 0)
             * {
             * //all pointers created in assimp will be deleted automaticaly when we call import.FreeScene();
             * Material material = scene.Materials[mesh.MaterialIndex];
             * List<MTexture> diffuse_maps = LoadMaterialTexture(material, aiTextureType_DIFFUSE, "texture_diffuse");
             * bool exist = false;
             * for (int i = 0; (i < textures.size()) && (diffuse_maps.size() != 0); i++)
             * {
             *  if (textures[i].path == diffuse_maps[0].path) // ������ ���� �������� 1 �������� ������� � 1 ������� � ����� ����
             *  {
             *    exist = true;
             *  }
             * }
             * if (!exist && diffuse_maps.size() != 0) textures.push_back(diffuse_maps[0]); //������ �������� �� 1 �������� !!!
             *                                                                             //textures.insert(textures.end(), diffuse_maps.begin(), diffuse_maps.end());
             *
             * vector<Texture> specular_maps = LoadMaterialTexture(material, aiTextureType_SPECULAR, "texture_specular");
             * exist = false;
             * for (int i = 0; (i < textures.size()) && (specular_maps.size() != 0); i++)
             * {
             *  if (textures[i].path == specular_maps[0].path) // ������ ���� �������� 1 �������� ������� � 1 ������� � ����� ����
             *  {
             *    exist = true;
             *  }
             * }
             * if (!exist && specular_maps.size() != 0) textures.push_back(specular_maps[0]); //������ �������� �� 1 �������� !!!
             *                                                                               //textures.insert(textures.end(), specular_maps.begin(), specular_maps.end());
             *
             * }
             */

            // Dictionary<string, uint>  m_bone_mapping = new Dictionary<string, uint>();

            // load bones

            for (int i = 0; i < mesh.BoneCount; i++)
            {
                uint   bone_index = 0;
                string bone_name  = mesh.Bones[i].Name;

                //cout << mesh->mBones[i]->mName.data << endl;

                if (!m_bone_mapping.ContainsKey(bone_name)) // ��������� ��� �� � ������� ��������
                {
                    // Allocate an index for a new bone
                    bone_index = (uint)m_num_bones;
                    m_num_bones++;
                    //BoneMatrix bi = new BoneMatrix();
                    //m_bone_matrices.Add(bi);

                    BoneMatrix bbi = new BoneMatrix();
                    //m_bone_matrices[bone_index];
                    bbi.offset_matrix = mesh.Bones[i].OffsetMatrix;
                    // bbi.offset_matrix.Inverse();
                    m_bone_matrices.Add(bbi);

                    //m_bone_matrices[bone_index] = bbi;
                    m_bone_mapping[bone_name] = (uint)bone_index;

                    //cout << "bone_name: " << bone_name << "			 bone_index: " << bone_index << endl;
                }
                else
                {
                    bone_index = (uint)m_bone_mapping[bone_name];
                }

                //bones_id_weights_for_each_vertex = new List<VertexBoneData>(mesh.Bones[i].VertexWeightCount);

                for (int j = 0; j < mesh.Bones[i].VertexWeightCount; j++)
                {
                    int   vertex_id = mesh.Bones[i].VertexWeights[j].VertexID;                   // �� ������� �� ������ ����� �������� �����
                    float weight    = mesh.Bones[i].VertexWeights[j].Weight;
                    bones_id_weights_for_each_vertex[vertex_id].addBoneData(bone_index, weight); // � ������ ������� ����� ����� � �� ���

                    // ������ ������� vertex_id �� ������ ����� � �������� bone_index  ����� ��� weight
                    //cout << " vertex_id: " << vertex_id << "	bone_index: " << bone_index << "		weight: " << weight << endl;
                }
            }


            return(new MAnimatedMesh(vertices, indices.ToArray(), bones_id_weights_for_each_vertex));
        }