public NormalMapRenderer MakeNormalMapRenderer(Figure figureWithGrafts, UvSet uvSetWithGrafts, ChannelInputs shapeInputsWithGrafts)
    {
        /*
         * HUGE HACKS:
         * This class only works on figures without grafts whereas everything else works on figures with grafts.
         * So I have to convert the uvSet and shapeInputs the with-grafts figure to the without-grafts figure.
         */

        var uvSet = figure.UvSets[uvSetWithGrafts.Name];

        ChannelInputs ldInputs = figure.MakeDefaultChannelInputs();
        ChannelInputs hdInputs = figure.MakeDefaultChannelInputs();

        string hdCorrectionMorphChannelName = HdCorrectionMorphSynthesizer.CalcChannelName(figure.Name);

        foreach (var channel in figure.Channels)
        {
            var channelWithGrafts = figureWithGrafts.ChannelsByName[channel.Name];

            double value = channelWithGrafts.GetInputValue(shapeInputsWithGrafts);
            channel.SetValue(ldInputs, value);
            if (channel.Name != hdCorrectionMorphChannelName)
            {
                channel.SetValue(hdInputs, value);
            }
        }

        return(MakeNormalMapRenderer(ldInputs, hdInputs, uvSet));
    }
    public void Dump(string name, UvSet uvSet)
    {
        DirectoryInfo uvSetDirectory = uvSetsDirectory.Subdirectory(name);

        if (uvSetDirectory.Exists)
        {
            return;
        }

        Console.WriteLine($"Dumping uv-set {name}...");

        MultisurfaceQuadTopology spatialTopology         = figure.Geometry.AsTopology();
        MultisurfaceQuadTopology texturedControlTopology = ExtractTexturedTopology(spatialTopology, uvSet);
        var texturedRefinementResult = texturedControlTopology.Refine(surfaceProperties.SubdivisionLevel);
        var texturedTopology         = texturedRefinementResult.Mesh.Topology;
        var texturedTopologyInfo     = texturedRefinementResult.TopologyInfo;
        var derivStencils            = texturedRefinementResult.Mesh.Stencils;

        var stencils   = derivStencils.Map(stencil => new WeightedIndex(stencil.Index, stencil.Weight));
        var duStencils = derivStencils.Map(stencil => new WeightedIndex(stencil.Index, stencil.DuWeight));
        var dvStencils = derivStencils.Map(stencil => new WeightedIndex(stencil.Index, stencil.DvWeight));

        Vector2[] controlTextureCoords = uvSet.Uvs;
        Vector2[] textureCoords        = new Subdivider(stencils).Refine(controlTextureCoords, new Vector2Operators());
        Vector2[] textureCoordDus      = new Subdivider(duStencils).Refine(controlTextureCoords, new Vector2Operators());
        Vector2[] textureCoordDvs      = new Subdivider(dvStencils).Refine(controlTextureCoords, new Vector2Operators());

        int[] spatialIdxMap = CalculateTextureToSpatialIndexMap(texturedTopology, spatialFaces);

        TexturedVertexInfo[] texturedVertexInfos = Enumerable.Range(0, textureCoords.Length)
                                                   .Select(idx => {
            int spatialVertexIdx = spatialIdxMap[idx];
            Vector2 textureCoord = textureCoords[idx];
            Vector2 du           = textureCoordDus[idx];
            Vector2 dv           = textureCoordDvs[idx];

            List <int> spatialNeighbours = spatialTopologyInfo.AdjacentVertices.GetElements(spatialVertexIdx).ToList();
            var spatialVertexRule        = spatialTopologyInfo.VertexRules[spatialVertexIdx];

            List <int> neighbours = texturedTopologyInfo.AdjacentVertices.GetElements(idx).Select(i => spatialIdxMap[i]).ToList();
            var vertexRule        = texturedTopologyInfo.VertexRules[idx];

            Tuple <Vector2, Vector2> remappedTangents = RemapTangents(spatialNeighbours, spatialVertexRule, neighbours, vertexRule, du, dv);

            return(new TexturedVertexInfo(
                       spatialVertexIdx,
                       textureCoord,
                       remappedTangents.Item1,
                       remappedTangents.Item2));
        })
                                                   .ToArray();

        uvSetDirectory.CreateWithParents();
        uvSetDirectory.File("textured-faces.array").WriteArray(texturedTopology.Faces);
        uvSetDirectory.File("textured-vertex-infos.array").WriteArray(texturedVertexInfos);
    }
    public Figure Bake(Figure parentFigure)
    {
        if (Channels == null)
        {
            Channels = new List <ChannelRecipe>();
        }
        if (Formulas == null)
        {
            Formulas = new List <FormulaRecipe>();
        }
        if (Morphs == null)
        {
            Morphs = new List <MorphRecipe>();
        }

        Geometry geometry = Geometry.Bake();

        Dictionary <string, UvSet> uvSets = new Dictionary <string, UvSet>();

        UvSets.ForEach(recipe => recipe.Bake(geometry, uvSets));
        UvSet defaultUvSet = uvSets[Geometry.DefaultUvSet];

        ChannelSystem channelSystem = new ChannelSystemRecipe(Channels, Formulas).Bake(parentFigure?.ChannelSystem);

        int graftVertexOffset = Geometry.VertexPositions.Length;

        List <MorphRecipe> rewrittenMorphRecipes = Automorpher != null?Automorpher.Rewrite(Morphs, parentFigure) : Morphs;

        List <Morph> morphs  = rewrittenMorphRecipes.Select(recipe => recipe.Bake(channelSystem.ChannelsByName)).ToList();
        Morpher      morpher = new Morpher(morphs);

        Automorpher automorpher = Automorpher?.Bake();

        BoneSystem selfBoneSystem = new BoneSystemRecipe(Bones).Bake(channelSystem.ChannelsByName);

        BoneSystem boneSystem;

        RigidTransform[] childToParentBindPoseTransforms;
        if (parentFigure != null)
        {
            boneSystem = parentFigure.BoneSystem;
            childToParentBindPoseTransforms = MakeChildToParentBindPoseTransforms(channelSystem, selfBoneSystem, boneSystem);
        }
        else
        {
            boneSystem = selfBoneSystem;
            childToParentBindPoseTransforms = null;
        }

        SkinBinding skinBinding = SkinBinding.Bake(boneSystem.BonesByName, selfBoneSystem.BonesByName);

        OcclusionBinding occlusionBinding = OcclusionBinding.MakeForFigure(Name, geometry, boneSystem, skinBinding);

        return(new Figure(Name, parentFigure, this, geometry, channelSystem, boneSystem, childToParentBindPoseTransforms, morpher, automorpher, skinBinding, uvSets, defaultUvSet, occlusionBinding));
    }
    private UvSet RemapToDefault(UvSet uvSet)
    {
        var defaultUvSet         = figure.DefaultUvSet;
        var defaultUvSetTopology = new QuadTopology(defaultUvSet.Uvs.Length, defaultUvSet.Faces);
        var indexMap             = QuadTopology.CalculateVertexIndexMap(defaultUvSetTopology, uvSet.Faces);

        Vector2[] remappedUvs = indexMap
                                .Select(idx => uvSet.Uvs[idx])
                                .ToArray();

        return(new UvSet(uvSet.Name, remappedUvs, defaultUvSet.Faces));
    }
 public Figure(string name, Figure parent, FigureRecipe recipe, Geometry geometry, ChannelSystem channelSystem, BoneSystem boneSystem, RigidTransform[] childToParentBindPoseTransforms, Morpher morpher, Automorpher automorpher, SkinBinding skinBinding, Dictionary <string, UvSet> uvSets, UvSet defaultUvSet, OcclusionBinding occlusionBinding)
 {
     this.name          = name;
     this.parent        = parent;
     this.recipe        = recipe;
     this.geometry      = geometry;
     this.channelSystem = channelSystem;
     this.boneSystem    = boneSystem;
     this.childToParentBindPoseTransforms = childToParentBindPoseTransforms;
     this.morpher          = morpher;
     this.automorpher      = automorpher;
     this.skinBinding      = skinBinding;
     this.uvSets           = uvSets;
     this.defaultUvSet     = defaultUvSet;
     this.occlusionBinding = occlusionBinding;
 }
Exemple #6
0
    public void Bake(Geometry geometry, Dictionary <string, UvSet> uvSets)
    {
        var uvSet = new UvSet(Name, Uvs, Faces);

        uvSets.Add(Name, uvSet);
    }
Exemple #7
0
 public static TextureMask Make(UvSet uvSet, int[] surfaceMap, int surfaceIdx)
 {
     return(new TextureMask(uvSet, surfaceMap, surfaceIdx));
 }
Exemple #8
0
 public TextureMask(UvSet uvSet, int[] surfaceMap, int surfaceIdx)
 {
     this.uvSet      = uvSet;
     this.surfaceMap = surfaceMap;
     surfaceIdxs.Add(surfaceIdx);
 }
    private MultisurfaceQuadTopology ExtractTexturedTopology(MultisurfaceQuadTopology spatialTopology, UvSet uvSet)
    {
        Quad[] texuredFaces        = uvSet.Faces;
        int    texturedVertexCount = uvSet.Uvs.Length;

        return(new MultisurfaceQuadTopology(
                   spatialTopology.Type,
                   texturedVertexCount,
                   spatialTopology.SurfaceCount,
                   texuredFaces,
                   spatialTopology.SurfaceMap));
    }
    public NormalMapRenderer MakeNormalMapRenderer(ChannelInputs ldChannelInputs, ChannelInputs hdChannelInputs, UvSet uvSet)
    {
        var ldChannelOutputs = figure.Evaluate(null, ldChannelInputs);
        var hdChannelOutputs = figure.Evaluate(null, hdChannelInputs);

        var ldControlPositions = figure.Geometry.VertexPositions.Select(p => p).ToArray();

        figure.Morpher.Apply(ldChannelOutputs, ldControlPositions);

        var hdControlPositions = figure.Geometry.VertexPositions.Select(p => p).ToArray();

        figure.Morpher.Apply(hdChannelOutputs, hdControlPositions);

        var activeHdMorphs = figure.Morpher.LoadActiveHdMorphs(hdChannelOutputs);

        int maxLevel = activeHdMorphs.Max(morph => morph.Morph.MaxLevel) + ExtraRefinementLevels;

        var controlTopology = new QuadTopology(figure.Geometry.VertexCount, figure.Geometry.Faces);

        var applier = HdMorphApplier.Make(controlTopology, hdControlPositions);

        var controlUvTopology = new QuadTopology(uvSet.Uvs.Length, uvSet.Faces);
        var controlUvs        = uvSet.Uvs;

        var refinement   = new Refinement(controlTopology, maxLevel);
        var uvRefinement = new Refinement(controlUvTopology, maxLevel, BoundaryInterpolation.EdgeAndCorner);

        var topology    = controlTopology;
        var ldPositions = ldControlPositions;
        var hdPositions = hdControlPositions;

        var uvTopology          = controlUvTopology;
        var uvs                 = controlUvs;
        var texturedLdPositions = ExtractTexturedPositions(topology, uvTopology, ldPositions);

        for (int levelIdx = 1; levelIdx <= maxLevel; ++levelIdx)
        {
            topology    = refinement.GetTopology(levelIdx);
            ldPositions = refinement.Refine(levelIdx, ldPositions);
            hdPositions = refinement.Refine(levelIdx, hdPositions);

            foreach (var activeHdMorph in activeHdMorphs)
            {
                applier.Apply(activeHdMorph.Morph, activeHdMorph.Weight, levelIdx, topology, hdPositions);
            }

            uvTopology          = uvRefinement.GetTopology(levelIdx);
            uvs                 = uvRefinement.Refine(levelIdx, uvs);
            texturedLdPositions = uvRefinement.Refine(levelIdx, texturedLdPositions);
        }

        var ldLimit         = refinement.Limit(ldPositions);
        var hdLimit         = refinement.Limit(hdPositions);
        var uvLimit         = uvRefinement.Limit(uvs);
        var texturedLdLimit = uvRefinement.Limit(texturedLdPositions);

        int[] faceMap = refinement.GetFaceMap();

        refinement.Dispose();
        uvRefinement.Dispose();

        var hdNormals  = CalculateNormals(hdLimit);
        var ldNormals  = CalculateNormals(ldLimit);
        var ldTangents = CalculateTangents(uvLimit, texturedLdLimit);

        int[] controlSurfaceMap = figure.Geometry.SurfaceMap;
        int[] surfaceMap        = faceMap
                                  .Select(controlFaceIdx => controlSurfaceMap[controlFaceIdx])
                                  .ToArray();

        var renderer = new NormalMapRenderer(device, shaderCache, hdNormals, ldNormals, topology.Faces, uvLimit.values, ldTangents, uvTopology.Faces, surfaceMap);

        return(renderer);
    }
    public void Dump(string name, UvSet uvSet)
    {
        DirectoryInfo uvSetDirectory = uvSetsDirectory.Subdirectory(name);

        if (uvSetDirectory.Exists)
        {
            return;
        }

        Console.WriteLine($"Dumping uv-set {name}...");

        int subdivisionLevel = surfaceProperties.SubdivisionLevel;

        var geometry = figure.Geometry;
        var spatialControlTopology  = new QuadTopology(geometry.VertexCount, geometry.Faces);
        var spatialControlPositions = geometry.VertexPositions;

        QuadTopology          spatialTopology;
        LimitValues <Vector3> spatialLimitPositions;

        using (var refinement = new Refinement(spatialControlTopology, subdivisionLevel)) {
            spatialTopology       = refinement.GetTopology();
            spatialLimitPositions = refinement.LimitFully(spatialControlPositions);
        }

        uvSet = RemapToDefault(uvSet);

        var texturedControlTopology = new QuadTopology(uvSet.Uvs.Length, uvSet.Faces);

        Vector2[] controlTextureCoords = uvSet.Uvs;

        int[]     controlSpatialIdxMap     = QuadTopology.CalculateVertexIndexMap(texturedControlTopology, spatialControlTopology.Faces);
        Vector3[] texturedControlPositions = controlSpatialIdxMap
                                             .Select(spatialIdx => spatialControlPositions[spatialIdx])
                                             .ToArray();

        QuadTopology          texturedTopology;
        LimitValues <Vector3> texturedLimitPositions;
        LimitValues <Vector2> limitTextureCoords;

        using (var refinement = new Refinement(texturedControlTopology, surfaceProperties.SubdivisionLevel, BoundaryInterpolation.EdgeAndCorner)) {
            texturedTopology       = refinement.GetTopology();
            texturedLimitPositions = refinement.LimitFully(texturedControlPositions);
            limitTextureCoords     = refinement.LimitFully(controlTextureCoords);
        }

        Vector2[] textureCoords;
        if (geometry.Type == GeometryType.SubdivisionSurface)
        {
            textureCoords = limitTextureCoords.values;
        }
        else
        {
            if (subdivisionLevel != 0)
            {
                throw new InvalidOperationException("polygon meshes cannot be subdivided");
            }
            Debug.Assert(limitTextureCoords.values.Length == controlTextureCoords.Length);

            textureCoords = controlTextureCoords;
        }

        int[] spatialIdxMap = QuadTopology.CalculateVertexIndexMap(texturedTopology, spatialTopology.Faces);

        TexturedVertexInfo[] texturedVertexInfos = Enumerable.Range(0, textureCoords.Length)
                                                   .Select(idx => {
            int spatialVertexIdx = spatialIdxMap[idx];
            Vector2 textureCoord = textureCoords[idx];

            Vector3 positionDu = TangentSpaceUtilities.CalculatePositionDu(
                limitTextureCoords.tangents1[idx],
                limitTextureCoords.tangents2[idx],
                texturedLimitPositions.tangents1[idx],
                texturedLimitPositions.tangents2[idx]);

            Vector3 spatialPositionTan1 = spatialLimitPositions.tangents1[spatialVertexIdx];
            Vector3 spatialPositionTan2 = spatialLimitPositions.tangents2[spatialVertexIdx];

            Vector2 tangentUCoeffs = TangentSpaceUtilities.CalculateTangentSpaceRemappingCoeffs(spatialPositionTan1, spatialPositionTan2, positionDu);

            DebugUtilities.AssertFinite(tangentUCoeffs.X);
            DebugUtilities.AssertFinite(tangentUCoeffs.Y);

            return(new TexturedVertexInfo(
                       textureCoord,
                       tangentUCoeffs));
        })
                                                   .ToArray();

        uvSetDirectory.CreateWithParents();
        uvSetDirectory.File("textured-vertex-infos.array").WriteArray(texturedVertexInfos);
    }