public PackedLists <VertexDelta> ConvertToVertexDeltas(int vertexCount, bool[] channelsToInclude)
    {
        List <List <VertexDelta> > vertexDeltas = Enumerable.Range(0, vertexCount)
                                                  .Select(idx => new List <VertexDelta>())
                                                  .ToList();

        int morphCount = Morphs.Count;

        for (int morphIdx = 0; morphIdx < morphCount; ++morphIdx)
        {
            Morph morph = morphs[morphIdx];

            if (channelsToInclude != null && !channelsToInclude[morph.Channel.Index])
            {
                continue;
            }

            foreach (var delta in morph.Deltas)
            {
                vertexDeltas[delta.VertexIdx].Add(new VertexDelta(morphIdx, delta.PositionOffset));
            }
        }

        return(PackedLists <VertexDelta> .Pack(vertexDeltas));
    }
Ejemplo n.º 2
0
    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));
    }
Ejemplo n.º 3
0
    private PackedLists <WeightedIndex> NormalizeAndPackFormFactors(double[][] rawFormFactors)
    {
        List <List <WeightedIndex> > weightsByReceiver = new List <List <WeightedIndex> >();

        for (int receiverIdx = 0; receiverIdx < vertexCount; receiverIdx++)
        {
            double[] formFactorsForReceiver = rawFormFactors[receiverIdx];

            double total = 0;
            for (int transmitterIdx = 0; transmitterIdx < vertexCount; transmitterIdx++)
            {
                total += formFactorsForReceiver[transmitterIdx];
            }

            if (total == 0)
            {
                weightsByReceiver.Add(new List <WeightedIndex>());
                continue;
            }

            List <WeightedIndex> sortedWeights = Enumerable.Range(0, vertexCount)
                                                 .Select(transmitterIdx => new WeightedIndex(transmitterIdx, (float)(formFactorsForReceiver[transmitterIdx] / total)))
                                                 .Where(weightedIndex => weightedIndex.Weight != 0)
                                                 .OrderByDescending(weightedIndex => weightedIndex.Weight)
                                                 .ToList();

            List <WeightedIndex> topWeights = new List <WeightedIndex>();
            double accumulatedWeight        = 0;
            foreach (WeightedIndex weightedIndex in sortedWeights)
            {
                topWeights.Add(weightedIndex);

                accumulatedWeight += weightedIndex.Weight;
                if (accumulatedWeight > 0.995)
                {
                    break;
                }
            }

            if (topWeights.Count > 5000)
            {
                throw new InvalidOperationException("too many contributing vertices");
            }

            weightsByReceiver.Add(topWeights);

            if (receiverIdx % 1000 == 0)
            {
                Console.WriteLine(receiverIdx + ": " + topWeights.Count);
            }
        }

        var packedWeightsByReceiver = PackedLists <WeightedIndex> .Pack(weightsByReceiver);

        return(packedWeightsByReceiver);
    }
Ejemplo n.º 4
0
    public static RefinementResult Make(QuadTopology controlTopology, int[] controlSurfaceMap, int refinementLevel, bool derivativesOnly)
    {
        if (controlTopology.Faces.Length == 0 && controlTopology.VertexCount == 0)
        {
            return(RefinementResult.Empty);
        }

        PackedLists <WeightedIndex> limitStencils, limitDuStencils, limitDvStencils;
        QuadTopology            refinedTopology;
        SubdivisionTopologyInfo refinedTopologyInfo;

        int[] controlFaceMap;
        using (var refinement = new Refinement(controlTopology, refinementLevel)) {
            limitStencils   = refinement.GetStencils(StencilKind.LimitStencils);
            limitDuStencils = refinement.GetStencils(StencilKind.LimitDuStencils);
            limitDvStencils = refinement.GetStencils(StencilKind.LimitDvStencils);
            refinedTopology = refinement.GetTopology();

            var adjacentVertices = refinement.GetAdjacentVertices();
            var rules            = refinement.GetVertexRules();
            refinedTopologyInfo = new SubdivisionTopologyInfo(adjacentVertices, rules);

            controlFaceMap = refinement.GetFaceMap();
        }

        if (derivativesOnly)
        {
            if (refinementLevel != 0)
            {
                throw new InvalidOperationException("derivatives-only mode can only be used at refinement level 0");
            }

            limitStencils = PackedLists <WeightedIndex> .Pack(Enumerable.Range(0, controlTopology.VertexCount)
                                                              .Select(vertexIdx => {
                var selfWeight = new WeightedIndex(vertexIdx, 1);
                return(new List <WeightedIndex> {
                    selfWeight
                });
            }).ToList());
        }

        PackedLists <WeightedIndexWithDerivatives> stencils = WeightedIndexWithDerivatives.Merge(limitStencils, limitDuStencils, limitDvStencils);
        var refinedMesh = new SubdivisionMesh(controlTopology.VertexCount, refinedTopology, stencils);

        return(new RefinementResult(refinedMesh, refinedTopologyInfo, controlFaceMap));
    }
Ejemplo n.º 5
0
    public OccluderParameters CalculateOccluderParameters()
    {
        var baseInputs         = MakePosedShapeInputs();
        var baseOutputs        = figure.Evaluate(null, baseInputs);
        var baseOcclusionInfos = CalculateOcclusion(baseOutputs);

        List <Channel> channels = new List <Channel>();
        List <List <OcclusionDelta> > perVertexDeltas = new List <List <OcclusionDelta> >();

        for (int i = 0; i < baseOcclusionInfos.Length; ++i)
        {
            perVertexDeltas.Add(new List <OcclusionDelta>());
        }

        foreach (var channel in GetChannelsForOcclusionSystem())
        {
            Console.WriteLine($"\t{channel.Name}...");

            int occlusionChannelIdx = channels.Count;
            channels.Add(channel);

            var inputs = new ChannelInputs(baseInputs);
            channel.SetValue(inputs, 1);
            var outputs        = figure.Evaluate(null, inputs);
            var occlusionInfos = CalculateOcclusion(outputs);

            for (int vertexIdx = 0; vertexIdx < occlusionInfos.Length; ++vertexIdx)
            {
                if (Math.Abs(occlusionInfos[vertexIdx].Front - baseOcclusionInfos[vertexIdx].Front) > OcclusionDifferenceThreshold)
                {
                    var delta = new OcclusionDelta(occlusionChannelIdx, OcclusionInfo.Pack(occlusionInfos[vertexIdx]));
                    perVertexDeltas[vertexIdx].Add(delta);
                }
            }
        }

        var parameters = new OccluderParameters(
            OcclusionInfo.PackArray(baseOcclusionInfos),
            channels.Select(channel => channel.Name).ToList(),
            PackedLists <OcclusionDelta> .Pack(perVertexDeltas));

        return(parameters);
    }
    public static PackedLists <Vector3WeightedIndex> Merge(
        PackedLists <WeightedIndex> values0,
        PackedLists <WeightedIndex> values1,
        PackedLists <WeightedIndex> values2)
    {
        int segmentCount = values0.Count;

        if (values1.Count != segmentCount)
        {
            throw new InvalidOperationException("expected values1 count to match");
        }
        if (values2.Count != segmentCount)
        {
            throw new InvalidOperationException("expected values2 count to match");
        }

        var combined = new List <List <Vector3WeightedIndex> >(segmentCount);

        for (int segmentIdx = 0; segmentIdx < segmentCount; ++segmentIdx)
        {
            IEnumerable <Vector3WeightedIndex> v0s = values0.GetElements(segmentIdx)
                                                     .Select(w => new Vector3WeightedIndex(w.Index, new Vector3(w.Weight, 0, 0)));

            IEnumerable <Vector3WeightedIndex> v1s = values1.GetElements(segmentIdx)
                                                     .Select(w => new Vector3WeightedIndex(w.Index, new Vector3(0, w.Weight, 0)));

            IEnumerable <Vector3WeightedIndex> v2s = values2.GetElements(segmentIdx)
                                                     .Select(w => new Vector3WeightedIndex(w.Index, new Vector3(0, 0, w.Weight)));

            List <Vector3WeightedIndex> combinedWeightedIndices = v0s.Concat(v1s).Concat(v2s).GroupBy(w => w.Index).Select(group => {
                float sum0 = group.Sum(w => w.Weight[0]);
                float sum1 = group.Sum(w => w.Weight[1]);
                float sum2 = group.Sum(w => w.Weight[2]);
                return(new Vector3WeightedIndex(group.Key, new Vector3(sum0, sum1, sum2)));
            }).ToList();

            combined.Add(combinedWeightedIndices);
        }

        return(PackedLists <Vector3WeightedIndex> .Pack(combined));
    }
Ejemplo n.º 7
0
    public static PackedLists <WeightedIndexWithDerivatives> Merge(
        PackedLists <WeightedIndex> valueStencils,
        PackedLists <WeightedIndex> duStencils,
        PackedLists <WeightedIndex> dvStencils)
    {
        int segmentCount = valueStencils.Count;

        if (duStencils.Count != segmentCount)
        {
            throw new InvalidOperationException("expected du segment count to match");
        }
        if (dvStencils.Count != segmentCount)
        {
            throw new InvalidOperationException("expected dv segment count to match");
        }

        var combinedStencils = new List <List <WeightedIndexWithDerivatives> >(segmentCount);

        for (int segmentIdx = 0; segmentIdx < segmentCount; ++segmentIdx)
        {
            IEnumerable <WeightedIndexWithDerivatives> values = valueStencils.GetElements(segmentIdx)
                                                                .Select(w => new WeightedIndexWithDerivatives(w.Index, w.Weight, 0, 0));

            IEnumerable <WeightedIndexWithDerivatives> dvs = duStencils.GetElements(segmentIdx)
                                                             .Select(w => new WeightedIndexWithDerivatives(w.Index, 0, w.Weight, 0));

            IEnumerable <WeightedIndexWithDerivatives> dus = dvStencils.GetElements(segmentIdx)
                                                             .Select(w => new WeightedIndexWithDerivatives(w.Index, 0, 0, w.Weight));

            List <WeightedIndexWithDerivatives> combinedWeightedIndices = values.Concat(dvs).Concat(dus).GroupBy(w => w.Index).Select(group => {
                float sumWeight   = group.Sum(w => w.Weight);
                float sumDuWeight = group.Sum(w => w.DuWeight);
                float sumDvWeight = group.Sum(w => w.DvWeight);
                return(new WeightedIndexWithDerivatives(group.Key, sumWeight, sumDuWeight, sumDvWeight));
            }).ToList();

            combinedStencils.Add(combinedWeightedIndices);
        }

        return(PackedLists <WeightedIndexWithDerivatives> .Pack(combinedStencils));
    }
    public void Import(DsonTypes.SkinBinding skinBinding)
    {
        int vertexCount = skinBinding.vertex_count;

        List <List <BoneWeight> > boneWeightsByVertex = new List <List <BoneWeight> >(vertexCount);

        for (int i = 0; i < vertexCount; ++i)
        {
            boneWeightsByVertex.Add(new List <BoneWeight>());
        }

        DsonTypes.WeightedJoint[] joints = skinBinding.joints;

        string[] boneNames = new string[joints.Length];

        for (int boneIdx = 0; boneIdx < joints.Length; ++boneIdx)
        {
            DsonTypes.WeightedJoint joint = joints[boneIdx];

            if (joint.node_weights == null)
            {
                throw new InvalidOperationException("expected scale_weights to be non-null");
            }
            if (joint.scale_weights != null)
            {
                throw new InvalidOperationException("expected scale_weights to be null");
            }
            if (joint.local_weights != null)
            {
                throw new InvalidOperationException("expected local_weights to be null");
            }
            if (joint.bulge_weights != null)
            {
                throw new InvalidOperationException("expected bulge_weights to be null");
            }

            DsonTypes.Node jointNode = joint.node.ReferencedObject;
            boneNames[boneIdx] = jointNode.name;

            foreach (DsonTypes.IndexedFloat elem in joint.node_weights.values)
            {
                boneWeightsByVertex[elem.index].Add(new BoneWeight(boneIdx, (float)elem.value));
            }
        }

        Dictionary <string, string> faceGroupToNodeMap = new Dictionary <string, string>();

        if (skinBinding.selection_map.Length != 1)
        {
            throw new InvalidOperationException("expected only one face-group-to-node map");
        }
        foreach (DsonTypes.StringPair pair in skinBinding.selection_map[0].mappings)
        {
            faceGroupToNodeMap.Add(pair.from, pair.to);
        }

        SkinBindingRecipe recipe = new SkinBindingRecipe {
            BoneNames          = boneNames,
            BoneWeights        = PackedLists <BoneWeight> .Pack(boneWeightsByVertex),
            FaceGroupToNodeMap = faceGroupToNodeMap
        };

        recipes.Add(recipe);
    }