// ref. vertex_transformations.h, construct_deformed_cube_instance_matrix()
 public Matrix ConstructDeformedCubeInstanceMatrix(ref Vector4UByte boneIndices, ref Vector4 boneWeights, out Matrix localMatrix)
 {
     localMatrix = LocalMatrix;
     Matrix ret = localMatrix;
     if (EnableSkinning)
     {
         Vector3 offset = ComputeBoneOffset(ref boneIndices, ref boneWeights);
         Vector3 translationM = ret.Translation;
         translationM += offset;
         ret.Translation = translationM;
     }
     return ret;
 }
        public Vector3 ComputeBoneOffset(ref Vector4UByte boneIndices, ref Vector4 boneWeights)
        {
            Matrix bonesMatrix = new Matrix();
            Vector4 bone0 = GetNormalizedBone(boneIndices[0]);
            Vector4 bone1 = GetNormalizedBone(boneIndices[1]);
            Vector4 bone2 = GetNormalizedBone(boneIndices[2]);
            Vector4 bone3 = GetNormalizedBone(boneIndices[3]);
            bonesMatrix.SetRow(0, bone0);
            bonesMatrix.SetRow(1, bone1);
            bonesMatrix.SetRow(2, bone2);
            bonesMatrix.SetRow(3, bone3);

            return Denormalize(Vector4.Transform(boneWeights, bonesMatrix), BoneRange);
        }
        // http://web.stanford.edu/class/cs248/pdf/class_13_skinning.pdf
        private Matrix ComputeSkinning(Vector4UByte indices, ref VRageMath.Vector4 weights)
        {
            // TODO: Optmize
            Matrix ret = new Matrix();
            for (int it = 0; it < 4; it++)
            {
                float weight = weights[it];
                if (weight == 0)
                    break;

                // NOTE: m_skinTransforms are already transposed
                Matrix transform;
                Matrix.Transpose(ref m_skinTransforms[m_skeletonIndices[indices[it]]], out transform);

                transform *= weight;
                ret += transform;
            }

            return ret;
        }