public void DumpShared()
    {
        var texturedFacesFile          = uvSetsDirectory.File("textured-faces.array");
        var textureToSpatialIdxMapFile = uvSetsDirectory.File("textured-to-spatial-idx-map.array");

        if (texturedFacesFile.Exists && textureToSpatialIdxMapFile.Exists)
        {
            return;
        }

        int subdivisionLevel = surfaceProperties.SubdivisionLevel;

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

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

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

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

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

        uvSetsDirectory.CreateWithParents();
        texturedFacesFile.WriteArray(texturedTopology.Faces);
        textureToSpatialIdxMapFile.WriteArray(texturedToSpatialIndexMap);
    }
    public void Apply(HdMorph morph, float weight, int levelIdx, QuadTopology topology, Vector3[] positions)
    {
        var level = morph.GetLevel(levelIdx);

        if (level == null)
        {
            return;
        }

        foreach (var faceEdit in level.FaceEdits)
        {
            foreach (var vertexEdit in faceEdit.VertexEdits)
            {
                int pathLength     = vertexEdit.PathLength;
                int refinedFaceIdx = faceEdit.ControlFaceIdx;
                for (int i = 0; i < pathLength - 1; ++i)
                {
                    refinedFaceIdx = refinedFaceIdx * 4 + vertexEdit.GetPathElement(i);
                }
                int cornerIdx        = vertexEdit.GetPathElement(pathLength - 1);
                int refinedVertexIdx = topology.Faces[refinedFaceIdx].GetCorner(cornerIdx);

                Vector3   tangentSpaceDelta = vertexEdit.Delta;
                int       tangentToObjectSpaceTransformIdx = faceEdit.ControlFaceIdx * 4 + vertexEdit.GetPathElement(0);
                Matrix3x3 tangentToObjectSpaceTransform    = tangentToObjectSpaceTransforms[tangentToObjectSpaceTransformIdx];
                Vector3   objectSpaceDelta = Vector3.Transform(tangentSpaceDelta, tangentToObjectSpaceTransform);

                positions[refinedVertexIdx] += weight * objectSpaceDelta;
            }
        }
    }
Beispiel #3
0
    /**
     * Given two topologies with the same faces but different vertex indices, returns a map from the vertex
     * indices of one topology to the vertex indices of the other topologies.
     *
     * Each vertex in the source topology must map to a single vertex in the dest topology. However, it's
     * allowable for multiple source vertices to map to the same dest vertex. Thus it's possible to map
     * from a source UV topology with seams to a dest spatial topology without seams.
     */
    public static int[] CalculateVertexIndexMap(QuadTopology sourceTopology, Quad[] destFaces)
    {
        int faceCount = sourceTopology.Faces.Length;

        if (destFaces.Length != faceCount)
        {
            throw new InvalidOperationException("face count mismatch");
        }

        int[] indexMap = new int[sourceTopology.VertexCount];
        for (int faceIdx = 0; faceIdx < faceCount; ++faceIdx)
        {
            Quad sourceFace = sourceTopology.Faces[faceIdx];
            Quad destFace   = destFaces[faceIdx];

            for (int i = 0; i < Quad.SideCount; ++i)
            {
                int sourceIdx = sourceFace.GetCorner(i);
                int destIdx   = destFace.GetCorner(i);

                int previousMapping = indexMap[sourceIdx];
                if (previousMapping != default(int) && previousMapping != destIdx)
                {
                    throw new InvalidOperationException("mapping conflict");
                }

                indexMap[sourceIdx] = destIdx;
            }
        }

        return(indexMap);
    }
Beispiel #4
0
    public static int[] CalculateTextureToSpatialIndexMap(QuadTopology texturedTopology, Quad[] spatialFaces)
    {
        int faceCount = texturedTopology.Faces.Length;

        if (spatialFaces.Length != faceCount)
        {
            throw new InvalidOperationException("textured and spatial face count mismatch");
        }

        int[] spatialIdxMap = new int[texturedTopology.VertexCount];
        for (int faceIdx = 0; faceIdx < faceCount; ++faceIdx)
        {
            Quad texturedFace = texturedTopology.Faces[faceIdx];
            Quad spatialFace  = spatialFaces[faceIdx];

            for (int i = 0; i < Quad.SideCount; ++i)
            {
                int texturedIdx = texturedFace.GetCorner(i);
                int spatialIdx  = spatialFace.GetCorner(i);

                int previousMapping = spatialIdxMap[texturedIdx];
                if (previousMapping != default(int) && previousMapping != spatialIdx)
                {
                    throw new InvalidOperationException("mapping conflict");
                }

                spatialIdxMap[texturedIdx] = spatialIdx;
            }
        }

        return(spatialIdxMap);
    }
    public GpuOcclusionCalculator(Device device, ShaderCache shaderCache, QuadTopology topology, float[] faceTransparencies,
                                  uint[] faceMasks, uint[] vertexMasks)
    {
        if (topology.Faces.Length != faceTransparencies.Length)
        {
            throw new ArgumentException("face count mismatch");
        }
        if (topology.Faces.Length != faceMasks.Length)
        {
            throw new ArgumentException("face count mismatch");
        }

        if (topology.VertexCount != vertexMasks.Length)
        {
            throw new ArgumentException("vertex count mismatch");
        }

        shader = shaderCache.GetComputeShader <GpuOcclusionCalculator>("occlusion/HemisphericalRasterizingComputeShader");
        segmentBufferManager = new ConstantBufferManager <ArraySegment>(device);
        SetupHemispherePointsAndWeights(device);
        SetupRasterTable(device, shaderCache);
        SetupTopologyBuffers(device, topology, faceTransparencies);

        faceMasksView   = BufferUtilities.ToStructuredBufferView(device, faceMasks);
        vertexMasksView = BufferUtilities.ToStructuredBufferView(device, vertexMasks);
    }
    public void Run()
    {
        int controlVertexCount = 6;

        Quad[] controlFaces = new [] {
            new Quad(0, 1, 2, 3),
            new Quad(1, 4, 5, 2)
        };
        QuadTopology controlTopology = new QuadTopology(controlVertexCount, controlFaces);

        int refinementLevel = 1;

        using (Refinement refinement = new Refinement(controlTopology, refinementLevel)) {
            QuadTopology topology = refinement.GetTopology();
            int[]        faceMap  = refinement.GetFaceMap();

            for (int faceIdx = 0; faceIdx < topology.Faces.Length; ++faceIdx)
            {
                Console.WriteLine(topology.Faces[faceIdx] + " -> " + faceMap[faceIdx]);
            }
            Console.WriteLine();

            PackedLists <WeightedIndex> stencils = refinement.GetStencils(StencilKind.LimitStencils);
            Console.WriteLine("stencils: ");
            for (int vertexIdx = 0; vertexIdx < stencils.Count; ++vertexIdx)
            {
                Console.WriteLine(vertexIdx + ":");
                foreach (WeightedIndex weightedIndex in stencils.GetElements(vertexIdx))
                {
                    Console.WriteLine("\t" + weightedIndex.Index + " -> " + weightedIndex.Weight);
                }
            }
        }
    }
    public static HdMorphApplier Make(QuadTopology controlTopology, Vector3[] controlPositions)
    {
        Matrix3x3[] tangentToObjectSpaceTransforms = new Matrix3x3[controlTopology.Faces.Length * 4];
        for (int faceIdx = 0; faceIdx < controlTopology.Faces.Length; ++faceIdx)
        {
            for (int cornerIdx = 0; cornerIdx < Quad.SideCount; ++cornerIdx)
            {
                Vector3 cur  = controlPositions[controlTopology.Faces[faceIdx].GetCorner(cornerIdx)];
                Vector3 prev = controlPositions[controlTopology.Faces[faceIdx].GetCorner(cornerIdx - 1)];
                Vector3 next = controlPositions[controlTopology.Faces[faceIdx].GetCorner(cornerIdx + 1)];

                Vector3 edge1 = (prev - cur);
                Vector3 edge2 = (cur - next);

                Vector3 tangent   = Vector3.Normalize(edge1);
                Vector3 normal    = Vector3.Normalize(Vector3.Cross(edge1, edge2));
                Vector3 bitangent = Vector3.Cross(tangent, normal);

                Matrix3x3 tangentToObjectSpaceTransform = new Matrix3x3(
                    tangent.X, tangent.Y, tangent.Z,
                    normal.X, normal.Y, normal.Z,
                    bitangent.X, bitangent.Y, bitangent.Z);
                tangentToObjectSpaceTransforms[faceIdx * 4 + cornerIdx] = tangentToObjectSpaceTransform;
            }
        }

        return(new HdMorphApplier(tangentToObjectSpaceTransforms));
    }
 private static Vector3[] ExtractTexturedPositions(QuadTopology topology, QuadTopology uvTopology, Vector3[] ldPositions)
 {
     int[] texturedToSpatialIndexMap = QuadTopology.CalculateVertexIndexMap(uvTopology, topology.Faces);
     return(texturedToSpatialIndexMap
            .Select(spatialIdx => ldPositions[spatialIdx])
            .ToArray());
 }
Beispiel #9
0
    public PackedLists <WeightedIndex> MakeStencils(StencilKind kind, int refinementLevel)
    {
        var controlTopology = new QuadTopology(VertexCount, Faces);

        using (var refinement = new Refinement(controlTopology, refinementLevel)) {
            return(refinement.GetStencils(kind));
        }
    }
    private void SetupTopologyBuffers(Device device, QuadTopology topology, float[] faceTransparencies)
    {
        vertexCount = topology.VertexCount;

        facesView          = BufferUtilities.ToStructuredBufferView(device, topology.Faces);
        transparenciesView = BufferUtilities.ToStructuredBufferView(device, faceTransparencies);

        outputBufferManager = new StageableStructuredBufferManager <OcclusionInfo>(device, vertexCount);
    }
Beispiel #11
0
    public static SubdivisionMesh Combine(SubdivisionMesh meshA, SubdivisionMesh meshB)
    {
        int offset = meshA.ControlVertexCount;

        return(new SubdivisionMesh(
                   meshA.ControlVertexCount + meshB.ControlVertexCount,
                   QuadTopology.Combine(meshA.Topology, meshB.Topology),
                   PackedLists <WeightedIndexWithDerivatives> .Concat(
                       meshA.Stencils,
                       meshB.Stencils.Map(w => w.Reindex(offset)))));
    }
Beispiel #12
0
    public SubdivisionMesh(int controlVertexCount, QuadTopology topology, PackedLists <WeightedIndexWithDerivatives> stencils)
    {
        if (stencils.Count != topology.VertexCount)
        {
            throw new ArgumentException("vertex count mismatch");
        }

        ControlVertexCount = controlVertexCount;
        Topology           = topology;
        Stencils           = stencils;
    }
Beispiel #13
0
 public static void AssertTopologyAssumptions(QuadTopology topology, QuadTopology nextLevelTopology)
 {
     for (int faceIdx = 0; faceIdx < topology.Faces.Length; ++faceIdx)
     {
         for (int cornerIdx = 0; cornerIdx < Quad.SideCount; ++cornerIdx)
         {
             int vertexIdx          = topology.Faces[faceIdx].GetCorner(cornerIdx);
             int nextLevelVertexIdx = nextLevelTopology.Faces[faceIdx * 4 + cornerIdx].GetCorner(cornerIdx);
             Debug.Assert(vertexIdx == nextLevelVertexIdx);
         }
     }
 }
    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));
    }
Beispiel #15
0
    public static QuadTopology Combine(QuadTopology topologyA, QuadTopology topologyB)
    {
        int combinedVertexCount = topologyA.VertexCount + topologyB.VertexCount;

        Quad[] combinedFaces = topologyA.Faces
                               .Concat(
            topologyB.Faces.Select(face => face.Reindex(topologyA.VertexCount))
            )
                               .ToArray();

        return(new QuadTopology(combinedVertexCount, combinedFaces));
    }
    public static SubdivisionMesh Load(IArchiveDirectory directory)
    {
        var stencilSegments = directory.File(StencilSegmentsFilename).ReadArray <ArraySegment>();
        var stencilElements = directory.File(StencilElementsFilename).ReadArray <WeightedIndexWithDerivatives>();
        var faces           = directory.File(StencilFacesFilename).ReadArray <Quad>();

        var stencils = new PackedLists <WeightedIndexWithDerivatives>(stencilSegments, stencilElements);

        int vertexCount = stencils.Count;
        var topology    = new QuadTopology(vertexCount, faces);

        return(new SubdivisionMesh(0, topology, stencils));
    }
Beispiel #17
0
    public ApplyHdMorphDemo()
    {
        var fileLocator      = new ContentFileLocator();
        var objectLocator    = new DsonObjectLocator(fileLocator);
        var contentPackConfs = ContentPackImportConfiguration.LoadAll(CommonPaths.ConfDir);
        var pathManager      = ImporterPathManager.Make(contentPackConfs);
        var loader           = new FigureRecipeLoader(fileLocator, objectLocator, pathManager);
        var figureRecipe     = loader.LoadFigureRecipe("genesis-3-female", null);
        var figure           = figureRecipe.Bake(fileLocator, null);
        var geometry         = figure.Geometry;

        controlTopology        = new QuadTopology(geometry.VertexCount, geometry.Faces);
        controlVertexPositions = geometry.VertexPositions;
    }
Beispiel #18
0
    private static (QuadTopology, Vector3[]) ApplyHdMorph(HdMorph hdMorph, QuadTopology controlTopology, Vector3[] controlPositions, Refinement refinement)
    {
        var applier = HdMorphApplier.Make(controlTopology, controlPositions);

        var topology  = controlTopology;
        var positions = controlPositions;

        for (int levelIdx = 1; levelIdx <= hdMorph.MaxLevel; ++levelIdx)
        {
            topology  = refinement.GetTopology(levelIdx);
            positions = refinement.Refine(levelIdx, positions);
            applier.Apply(hdMorph, 1, levelIdx, topology, positions);
        }

        return(topology, positions);
    }
    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));
    }
Beispiel #20
0
 private static (QuadTopology, Vector3[]) ApplyHdMorph(HdMorph hdMorph, QuadTopology controlTopology, Vector3[] controlPositions)
 {
     using (var refinement = new Refinement(controlTopology, hdMorph.MaxLevel)) {
         return(ApplyHdMorph(hdMorph, controlTopology, controlPositions, refinement));
     }
 }
    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);
    }