public InstanceData CreateInstanceData <NamedControllers, NamedBlendShapes>(Mesh sourceMesh, Transform sourceRig, Warnings warnings) where NamedControllers : struct where NamedBlendShapes : struct
        {
            var meshName = sourceMesh.name;

            if (meshName.EndsWith(MeshInstanceBehaviour.meshInstanceSuffix))
            {
                meshName = meshName.Substring(0, meshName.IndexOf(MeshInstanceBehaviour.meshInstanceSuffix));
            }

            var blendShapePrefix = meshName + "_blendShape.";
            var blendShapeNames  = typeof(NamedBlendShapes).GetFields();

            var controllerPrefix = string.Empty;
            var controllerNames  = typeof(NamedControllers).GetFields();

            InstanceData instanceData;

            instanceData.definition        = this;
            instanceData.sourceMesh        = sourceMesh;
            instanceData.sourceRig         = sourceRig;
            instanceData.rigTransforms     = new Transform[controllerNames.Length];
            instanceData.rigControllers    = new SnappersController[controllerNames.Length];
            instanceData.blendShapeCount   = sourceMesh.blendShapeCount;
            instanceData.blendShapeIndices = new int[blendShapeNames.Length];
            instanceData.blendShapeWeights = new float[blendShapeNames.Length];
            instanceData.shaderParamFloats = new float[UnsafeUtility.SizeOf <SnappersShaderParam>() / sizeof(float)];

            //Debug.Log("CreateInstanceData for " + sourceMesh + " (blendShapePrefix = " + blendShapePrefix + ")");

            unsafe
            {
                fixed(void *ptrSnappersControllers = instanceData.rigControllers)
                {
                    InitializeControllerCaps(ptrSnappersControllers);
                }
            }

            if (sourceRig != null)
            {
                for (int i = 0; i != controllerNames.Length; i++)
                {
                    var transform = FindRecursive(sourceRig, controllerPrefix + controllerNames[i].Name);
                    if (transform != null)
                    {
                        instanceData.rigTransforms[i] = transform;
                    }
                    else if (warnings.HasFlag(Warnings.MissingTransforms))
                    {
                        Debug.LogWarningFormat("rig definition {0} targets transform not present in linked rig: {1}", this.name, controllerPrefix + controllerNames[i].Name);
                    }
                }
            }

            for (int i = 0; i != blendShapeNames.Length; i++)
            {
                int blendShapeIndex = sourceMesh.GetBlendShapeIndex(blendShapePrefix + blendShapeNames[i].Name);
                if (blendShapeIndex != -1)
                {
                    instanceData.blendShapeIndices[i] = blendShapeIndex;
                }
                else if (warnings.HasFlag(Warnings.MissingBlendShapes))
                {
                    Debug.LogWarningFormat("rig definition {0} targets blend shape not present in linked mesh: {1}", this.name, blendShapePrefix + blendShapeNames[i].Name);
                }
            }

            return(instanceData);
        }