public static AutomorpherRecipe Make(Geometry parentGeometry, Geometry childGeometry) { var parentLimit0Stencils = parentGeometry.MakeStencils(StencilKind.LimitStencils, 0); var subdivider = new Subdivider(parentLimit0Stencils); var parentLimit0VertexPositions = subdivider.Refine(parentGeometry.VertexPositions, new Vector3Operators()); List <(List <WeightedIndex>, Vector3)> resultPairs = Enumerable.Range(0, childGeometry.VertexCount) .AsParallel().AsOrdered() .Select(childVertexIdx => { Vector3 graftVertex = childGeometry.VertexPositions[childVertexIdx]; ClosestPoint.PointOnMesh closestPointOnBaseMesh = ClosestPoint.FindClosestPointOnMesh(parentGeometry.Faces, parentLimit0VertexPositions, graftVertex); var merger = new WeightedIndexMerger(); merger.Merge(parentLimit0Stencils.GetElements(closestPointOnBaseMesh.VertexIdxA), closestPointOnBaseMesh.BarycentricWeights.X); merger.Merge(parentLimit0Stencils.GetElements(closestPointOnBaseMesh.VertexIdxB), closestPointOnBaseMesh.BarycentricWeights.Y); merger.Merge(parentLimit0Stencils.GetElements(closestPointOnBaseMesh.VertexIdxC), closestPointOnBaseMesh.BarycentricWeights.Z); var cloestPointAsVector = closestPointOnBaseMesh.AsPosition(parentLimit0VertexPositions); return(merger.GetResult(), cloestPointAsVector); }) .ToList(); List <List <WeightedIndex> > baseDeltaWeights = resultPairs.Select(t => t.Item1).ToList(); Vector3[] parentSurfacePositions = resultPairs.Select(t => t.Item2).ToArray(); var packedBaseDeltaWeights = PackedLists <WeightedIndex> .Pack(baseDeltaWeights); return(new AutomorpherRecipe(packedBaseDeltaWeights, parentSurfacePositions)); }
public MorphRecipe SynthesizeMorph() { Vector3[] controlVertices = geometry.VertexPositions; Vector3[] refinedVertices = limit0Subdivider.Refine(controlVertices, new Vector3Operators()); MorphDelta[] deltas = Enumerable.Range(0, controlVertices.Length) .Select(i => new MorphDelta(i, controlVertices[i] - refinedVertices[i])) .ToArray(); return(new MorphRecipe { Channel = ChannelName, Deltas = deltas }); }