private static Vector3[] RefineVertexPositions(Geometry geometry, RefinementResult refinementResult) { var stencils = refinementResult.Mesh.Stencils.Map(stencil => new WeightedIndex(stencil.Index, stencil.Weight)); Vector3[] refinedVertexPositions = new Subdivider(stencils).Refine(geometry.VertexPositions, new Vector3Operators()); return(refinedVertexPositions); }
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 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 IEnumerable <Parcel> CreateParcels(Parcel shape, Func <double> random, INamedDataCollection metadata) { Contract.Requires(shape != null); Contract.Requires(random != null); Contract.Requires(metadata != null); Contract.Ensures(Contract.Result <IEnumerable <Parcel> >() != null); //Generate parcels from shape var parcels = Subdivider.GenerateParcels(shape, random, metadata); //Adjust parcels foreach (var adjustment in _adjustments) { parcels = adjustment.Adjust(shape, parcels, random); } return(parcels); }
public static MeshData CreateGeosphere(float radius, SubdivisionCount numSubdivisions) { var tempMesh = new MeshData(); tempMesh.Vertices = IcosahedronVertices.Select(p => new Vertex { Position = p }).ToList(); tempMesh.Indices = IcosahedronIndices; var mh = new Subdivider(); for (var i = 0; i < (int)numSubdivisions; i++) { mh.Subdivide4(tempMesh); } // Project vertices onto sphere and scale. for (var i = 0; i < tempMesh.Vertices.Count; i++) { // Project onto unit sphere. var n = Vector3.Normalize(tempMesh.Vertices[i].Position); // Project onto sphere. var p = radius * n; // Derive texture coordinates from spherical coordinates. var theta = MathF.AngleFromXY(tempMesh.Vertices[i].Position.X, tempMesh.Vertices[i].Position.Z); var phi = MathF.Acos(tempMesh.Vertices[i].Position.Y / radius); var texC = new Vector2(theta / (2 * MathF.PI), phi / MathF.PI); // Partial derivative of P with respect to theta var tangent = new Vector3( -radius * MathF.Sin(phi) * MathF.Sin(theta), 0, radius * MathF.Sin(phi) * MathF.Cos(theta) ); tangent.Normalize(); tempMesh.Vertices[i] = new Vertex(p, n, tangent, texC); } return(tempMesh); }
public static MeshData CreateGeosphere(float radius, SubdivisionCount numSubdivisions) { var tempMesh = new MeshData(); tempMesh.Vertices = IcosahedronVertices.Select(p => new Vertex { Position = p }).ToList(); tempMesh.Indices = IcosahedronIndices; var mh = new Subdivider(); for (var i = 0; i < (int)numSubdivisions; i++) { mh.Subdivide4(tempMesh); } // Project vertices onto sphere and scale. for (var i = 0; i < tempMesh.Vertices.Count; i++) { // Project onto unit sphere. var n = Vector3.Normalize(tempMesh.Vertices[i].Position); // Project onto sphere. var p = radius * n; // Derive texture coordinates from spherical coordinates. var theta = MathF.AngleFromXY(tempMesh.Vertices[i].Position.X, tempMesh.Vertices[i].Position.Z); var phi = MathF.Acos(tempMesh.Vertices[i].Position.Y / radius); var texC = new Vector2(theta / (2 * MathF.PI), phi / MathF.PI); // Partial derivative of P with respect to theta var tangent = new Vector3( -radius * MathF.Sin(phi) * MathF.Sin(theta), 0, radius * MathF.Sin(phi) * MathF.Cos(theta) ); tangent.Normalize(); tempMesh.Vertices[i] = new Vertex(p, n, tangent, texC); } return tempMesh; }
public HdCorrectionMorphSynthesizer(string figureName, Geometry geometry) { this.figureName = figureName; this.geometry = geometry; limit0Subdivider = new Subdivider(geometry.MakeStencils(StencilKind.LimitStencils, 0)); }
private static ContourVertex[] CreateContourFromFigure([CanBeNull] Matrix3x2?transform, float flatteningTolerance, Figure figure) { if (figure.FigureEnd == FigureEnd.Open) { throw new InvalidOperationException("Cannot create a contour, which may be filled, from an open figure."); } var vertices = new List <ContourVertex>(); var origin = figure.Origin; var lastPoint = origin; AddPoint(transform, origin, vertices); foreach (var element in figure.Elements) { switch (element.Type) { case GeometryElementType.Line: { AddPoint(transform, element.LineSegment, vertices); lastPoint = element.LineSegment; break; } case GeometryElementType.Arc: { var arc = element.ArcSegment; // The unit in ArcSegment is degrees, not radians; // positive value means clockwise rotation (https://msdn.microsoft.com/en-us/library/windows/desktop/dd370900.aspx). var divided = Subdivider.DivideSvgArc(lastPoint.X, lastPoint.Y, arc.Point.X, arc.Point.Y, arc.Size.X, arc.Size.Y, -MathHelper.ToRadians(arc.RotationAngle), arc.ArcSize == ArcSize.Large, arc.SweepDirection == SweepDirection.Clockwise, flatteningTolerance); AddPoints(transform, divided, vertices); lastPoint = arc.Point; break; } case GeometryElementType.Bezier: { var bezier = element.BezierSegment; var divided = Subdivider.DivideBezier(lastPoint.X, lastPoint.Y, bezier.Point1.X, bezier.Point1.Y, bezier.Point2.X, bezier.Point2.Y, bezier.Point3.X, bezier.Point3.Y, flatteningTolerance); AddPoints(transform, divided, vertices); lastPoint = bezier.Point3; break; } case GeometryElementType.QuadraticBezier: { var bezier = element.QuadraticBezierSegment; var divided = Subdivider.DivideQuadraticBezier(lastPoint.X, lastPoint.Y, bezier.Point1.X, bezier.Point1.Y, bezier.Point2.X, bezier.Point2.Y, flatteningTolerance); AddPoints(transform, divided, vertices); lastPoint = bezier.Point2; break; } case GeometryElementType.MathArc: { var mathArc = element.MathArcSegment; var divided = Subdivider.DivideArc(mathArc.Center.X, mathArc.Center.Y, mathArc.Radius.X, mathArc.Radius.Y, MathHelper.ToRadians(mathArc.StartAngle), MathHelper.ToRadians(mathArc.SweepAngle), MathHelper.ToRadians(mathArc.RotationAngle), flatteningTolerance); AddPoints(transform, divided, vertices); // Not setting lastPoint because we don't need it. See notes of MathArcSegment. break; } default: throw new ArgumentOutOfRangeException(); } } AddPoint(transform, origin, vertices); return(vertices.ToArray()); }