Esempio n. 1
0
    /// <summary>
    /// Hook up the BlendShape data
    /// </summary>
    /// <param name="go">
    /// A <see cref="GameObject"/>
    /// </param>
    public virtual void OnPostprocessModel(GameObject go)
    {
        // early out if no blend shape data were found
        if (baseShapePairs.Count < 1)
        {
            return;
        }

        // process each blend shape data object
        foreach (GameObject indexMap in baseShapePairs.Keys)
        {
            // grab the container for the new BlendShape component from the HashTable
            Transform blendContainer = TransformHelpers.GetTransformInHierarchy(go.transform, baseShapePairs[indexMap] as string);
            // if no match is found, try to find a skin with the mesh
            Component[] skins = go.GetComponentsInChildren <SkinnedMeshRenderer>();
            foreach (SkinnedMeshRenderer skin in skins)
            {
                if (skin.sharedMesh.name == baseShapePairs[indexMap] as string)
                {
                    blendContainer = skin.transform;
                }
            }
            // if no match was found, then assume it is the root
            if (blendContainer == null || blendContainer.GetComponent <Renderer>() == null)
            {
                blendContainer = go.transform;
            }
            // add the blendShape component if it does not yet exist
            BlendShape blendShapeNode = blendContainer.gameObject.AddComponent <BlendShape>();
            blendShapeNode.meshRenderer = blendShapeNode.GetComponent <Renderer>();

            // grab the base mesh to map target indices and the ArrayList of target models
            Mesh      taggedBaseMesh = indexMap.GetComponent <MeshFilter>().sharedMesh;
            ArrayList targetModels   = targetMeshes[indexMap.name] as ArrayList;

            // grab the seamless base mesh
            GameObject seamlessBaseModel = seamlessShapePairs[indexMap.name] as GameObject;
            blendShapeNode.seamlessBaseMesh = seamlessBaseModel.GetComponent <MeshFilter>().sharedMesh;

            // create the index map between the seamless base mesh and the actual base mesh
            Mesh outMesh;
            if (blendShapeNode.GetComponent <MeshFilter>() == null)
            {
                outMesh = blendShapeNode.GetComponent <SkinnedMeshRenderer>().sharedMesh;
            }
            else
            {
                outMesh = blendShapeNode.GetComponent <MeshFilter>().sharedMesh;
            }
            blendShapeNode.indexMap = new int[outMesh.vertexCount];
            for (int i = 0; i < taggedBaseMesh.colors.Length; i++)
            {
                // point indices on the seamless mesh should be identical to tag values
                blendShapeNode.indexMap[i] = ColorToTag(taggedBaseMesh.colors[i]);
            }

            // create BlendShapeTargets from the target models
            blendShapeNode.targets = new BlendShape.Target[targetModels.Count];
            for (int i = 0; i < targetModels.Count; i++)
            {
                // create the new BlendShapeTarget
                GameObject        targetModel = targetModels[i] as GameObject;
                Mesh              targetMesh  = targetModel.GetComponent <MeshFilter>().sharedMesh;
                BlendShape.Target target      = new BlendShape.Target();
                target.name = targetMesh.name.Substring(targetMesh.name.LastIndexOf("__blendShapeTarget__") + 20);

                // store the indices and deltaPosition values for the target
                ArrayList vertices = new ArrayList();
                ArrayList deltaPos = new ArrayList();
                for (int j = 0; j < targetMesh.vertexCount; j++)
                {
                    int     tag       = ColorToTag(targetMesh.colors[j]);
                    Vector3 compareTo = blendShapeNode.seamlessBaseMesh.vertices[tag];                     // simply use tag since it should be identical to point index on seamless mesh
                    // early out if the threshold test is not satisfied
                    if ((targetMesh.vertices[j] - compareTo).sqrMagnitude < sqrMagThreshold)
                    {
                        continue;
                    }
                    vertices.Add(tag);
                    deltaPos.Add(targetMesh.vertices[j] - compareTo);
                }
                target.vertices = new int[vertices.Count];
                for (int j = 0; j < target.vertices.Length; j++)
                {
                    target.vertices[j] = (int)vertices[j];
                }
                target.deltaPositions = new Vector3[deltaPos.Count];
                for (int j = 0; j < target.deltaPositions.Length; j++)
                {
                    target.deltaPositions[j] = (Vector3)deltaPos[j];
                }

                // copy the target to the BlendShape component
                blendShapeNode.targets[i] = target;

                // remove the target's assets
                GameObject.DestroyImmediate(targetMesh, true);
                GameObject.DestroyImmediate(targetModel, true);
            }

            // remove the tagged base mesh assets
            GameObject.DestroyImmediate(taggedBaseMesh, true);
            GameObject.DestroyImmediate(indexMap, true);
            // remove the seamless base mesh GameObject
            GameObject.DestroyImmediate(seamlessBaseModel, true);
        }
    }