Exemple #1
0
    public static UvSetRecipe Merge(FigureRecipeMerger.Reindexer reindexer, UvSetRecipe parentUvSet, UvSetRecipe[] childUvSets)
    {
        List <Vector2> mergedUvs   = new List <Vector2>();
        List <Quad>    mergedFaces = new List <Quad>();

        mergedUvs.AddRange(parentUvSet.Uvs);

        Quad[] parentFaces = parentUvSet.Faces;
        for (int faceIdx = 0; faceIdx < parentFaces.Length; ++faceIdx)
        {
            if (reindexer.IsParentFaceHidden(faceIdx))
            {
                continue;
            }
            mergedFaces.Add(parentFaces[faceIdx]);
        }

        for (int childIdx = 0; childIdx < childUvSets.Length; ++childIdx)
        {
            UvSetRecipe childUvSet = childUvSets[childIdx];

            int uvOffset = mergedUvs.Count;

            mergedUvs.AddRange(childUvSet.Uvs);

            mergedFaces.AddRange(childUvSet.Faces.Select(face => face.Reindex(uvOffset)));
        }

        return(new UvSetRecipe(
                   parentUvSet.Name,
                   mergedUvs.ToArray(),
                   mergedFaces.ToArray()));
    }
    public static SkinBindingRecipe Merge(FigureRecipeMerger.Reindexer reindexer, SkinBindingRecipe parentSkinBinding, SkinBindingRecipe[] childSkinBindings)
    {
        List <string>            mergedBones = new List <string>(parentSkinBinding.BoneNames);
        Dictionary <string, int> mergedBonesIndicesByName = Enumerable.Range(0, mergedBones.Count)
                                                            .ToDictionary(idx => mergedBones[idx], idx => idx);

        PackedLists <BoneWeight> mergedBoneWeights = parentSkinBinding.BoneWeights;

        foreach (SkinBindingRecipe childSkinBinding in childSkinBindings)
        {
            var remappedChildBoneWeights = childSkinBinding.BoneWeights
                                           .Map(boneWeight => {
                string boneName = childSkinBinding.BoneNames[boneWeight.Index];

                if (!mergedBonesIndicesByName.TryGetValue(boneName, out int mergedBoneIdx))
                {
                    mergedBoneIdx = mergedBones.Count;
                    mergedBonesIndicesByName[boneName] = mergedBoneIdx;
                    mergedBones.Add(boneName);
                }

                return(new BoneWeight(mergedBoneIdx, boneWeight.Weight));
            });
            mergedBoneWeights = PackedLists <BoneWeight> .Concat(mergedBoneWeights, remappedChildBoneWeights);
        }

        return(new SkinBindingRecipe {
            BoneNames = mergedBones.ToArray(),
            BoneWeights = mergedBoneWeights,
            FaceGroupToNodeMap = parentSkinBinding.FaceGroupToNodeMap
        });
    }
    public static MorphRecipe Merge(string channelName, FigureRecipeMerger.Reindexer reindexer, MorphRecipe parentMorph, MorphRecipe[] childMorphs, AutomorpherRecipe[] childAutomorphers)
    {
        List <MorphDelta> morphDeltas = new List <MorphDelta>();

        Vector3[] flatPositionOffsets;

        if (parentMorph != null)
        {
            morphDeltas.AddRange(parentMorph.Deltas);

            flatPositionOffsets = new Vector3[reindexer.GetParentVertexCount()];
            foreach (MorphDelta parentDelta in parentMorph.Deltas)
            {
                flatPositionOffsets[parentDelta.VertexIdx] = parentDelta.PositionOffset;
            }
        }
        else
        {
            flatPositionOffsets = null;
        }

        for (int childIdx = 0; childIdx < reindexer.ChildOffsets.Length; ++childIdx)
        {
            int childVertexOffset = reindexer.ChildOffsets[childIdx].Vertex;
            var childMorph        = childMorphs[childIdx];

            if (childMorph != null)
            {
                morphDeltas.AddRange(childMorph.Deltas
                                     .Select(delta => new MorphDelta(delta.VertexIdx + childVertexOffset, delta.PositionOffset)));
            }
            else
            {
                if (flatPositionOffsets == null)
                {
                    continue;
                }

                //generate the deltas using the automorpher
                var automorpher = childAutomorphers[childIdx];
                for (int childVertexIdx = 0; childVertexIdx < automorpher.BaseDeltaWeights.Count; ++childVertexIdx)
                {
                    Vector3 childPositionOffset = Vector3.Zero;
                    foreach (var baseDeltaWeight in automorpher.BaseDeltaWeights.GetElements(childVertexIdx))
                    {
                        childPositionOffset += baseDeltaWeight.Weight * flatPositionOffsets[baseDeltaWeight.Index];
                    }

                    if (!childPositionOffset.IsZero)
                    {
                        morphDeltas.Add(new MorphDelta(childVertexIdx + childVertexOffset, childPositionOffset));
                    }
                }
            }
        }

        return(new MorphRecipe {
            Channel = channelName,
            Deltas = morphDeltas.ToArray()
        });
    }
    public static GeometryRecipe Merge(FigureRecipeMerger.Reindexer reindexer, GeometryRecipe parent, GeometryRecipe[] children, AutomorpherRecipe[] childAutomorphers)
    {
        List <Quad>    mergedFaces           = new List <Quad>();
        List <int>     mergedFaceGroupMap    = new List <int>();
        List <int>     mergedSurfaceMap      = new List <int>();
        List <Vector3> mergedVertexPositions = new List <Vector3>();
        List <string>  mergedSurfaceNames    = new List <string>();

        for (int faceIdx = 0; faceIdx < parent.Faces.Length; faceIdx++)
        {
            if (reindexer.IsParentFaceHidden(faceIdx))
            {
                continue;
            }

            mergedFaces.Add(parent.Faces[faceIdx]);
            mergedFaceGroupMap.Add(parent.FaceGroupMap[faceIdx]);
            mergedSurfaceMap.Add(parent.SurfaceMap[faceIdx]);
        }

        mergedVertexPositions.AddRange(parent.VertexPositions);
        mergedSurfaceNames.AddRange(parent.SurfaceNames);

        for (int childIdx = 0; childIdx < children.Length; ++childIdx)
        {
            GeometryRecipe    child       = children[childIdx];
            AutomorpherRecipe automorpher = childAutomorphers[childIdx];

            Dictionary <int, int> graftVertexMap = new Dictionary <int, int>();
            if (child.Graft != null)
            {
                foreach (var pair in child.Graft.VertexPairs)
                {
                    graftVertexMap[pair.Source] = pair.Target;
                }
            }

            FigureRecipeMerger.Offset offset = reindexer.ChildOffsets[childIdx];

            if (child.Type != parent.Type)
            {
                throw new InvalidOperationException("children must have same geometry type as parent");
            }

            mergedSurfaceNames.AddRange(child.SurfaceNames);

            /*
             * Children start "turned off" so instead of adding the child's base vertex positions here, I add the
             * nearest positions on the parent's surface. Later I'll add a morph that moves the child vertices
             * into place.
             */
            mergedVertexPositions.AddRange(automorpher.ParentSurfacePositions);

            foreach (Quad face in child.Faces)
            {
                mergedFaces.Add(face.Map(idx => {
                    if (graftVertexMap.TryGetValue(idx, out int graftIdx))
                    {
                        return(graftIdx);
                    }
                    else
                    {
                        return(idx + offset.Vertex);
                    }
                }));
            }

            int[] childToParentFaceGroupIdx = new int[child.FaceGroupNames.Length];
            for (int childFaceGroupIdx = 0; childFaceGroupIdx < child.FaceGroupNames.Length; ++childFaceGroupIdx)
            {
                string faceGroupName      = child.FaceGroupNames[childFaceGroupIdx];
                int    parentFaceGroupIdx = Array.FindIndex(parent.FaceGroupNames, name => name == faceGroupName);
                childToParentFaceGroupIdx[childFaceGroupIdx] = parentFaceGroupIdx;
            }

            foreach (int childFaceGroupIdx in child.FaceGroupMap)
            {
                int parentFaceGroupIdx = childToParentFaceGroupIdx[0];
                mergedFaceGroupMap.Add(parentFaceGroupIdx);
            }

            foreach (int surfaceIdx in child.SurfaceMap)
            {
                mergedSurfaceMap.Add(surfaceIdx + offset.Surface);
            }
        }

        return(new GeometryRecipe(
                   parent.Type,
                   mergedFaces.ToArray(),
                   mergedFaceGroupMap.ToArray(),
                   mergedSurfaceMap.ToArray(),
                   mergedVertexPositions.ToArray(),
                   parent.FaceGroupNames,
                   mergedSurfaceNames.ToArray(),
                   parent.DefaultUvSet,
                   null));
    }