public void Noise(NoiseGenerator noise) { ComputePolygonNormals(); ComputePointNormals("point_normals_smooth"); var pointLocations = PointAttributes.FindOrNull <Vector3>("point_locations"); var pointNormals = PointAttributes.FindOrNull <Vector3>("point_normals_smooth"); foreach (Point point in Points) { if ( (pointLocations != null) && pointLocations.ContainsKey(point) ) { var pos = pointLocations[point]; var normal = Vector3.Normalize(pointLocations[point]); pointLocations[point] = pos + noise.Generate(pos) * normal; } } ComputePolygonCentroids(); ComputePolygonNormals(); SmoothNormalize("corner_normals", "polygon_normals", (2.0f * (float)System.Math.PI)); BuildEdges(); }
/// \warning This is inefficient! Try not to use this public void MergePoints() { Dictionary <Point, Point> removedPointToRemainingPoint = new Dictionary <Point, Point>(); var pointLocations = PointAttributes.FindOrNull <Vector3>("point_locations"); float pointEpsilon = 0.0000001f; // Merge points foreach (Point p1 in Points) { Vector3 pos1 = pointLocations[p1]; bool alreadyUsed = false; foreach (Point p2 in Points) { if (p1 == p2) { continue; } if (removedPointToRemainingPoint.ContainsKey(p1)) { continue; } Vector3 pos2 = pointLocations[p2]; float distanceSquared = pos1.DistanceSquared(pos2); if (distanceSquared < pointEpsilon) { if (alreadyUsed) { System.Diagnostics.Debug.WriteLine("point already used"); } removedPointToRemainingPoint[p2] = p1; alreadyUsed = true; } } } // Merge polygons foreach (var polygon in Polygons) { polygon.ReplacePoints(removedPointToRemainingPoint); } foreach (var point in removedPointToRemainingPoint.Keys) { Points.Remove(point); } }
public void Transform(Matrix4 transform) { Matrix4 inverseTransposeTransform = Matrix4.Transpose(Matrix4.Invert(transform)); // Check.. Did I forget something? // \todo Mark each attributemap how they should be transformed var polygonCentroids = PolygonAttributes.FindOrNull <Vector3>("polygon_centroids"); var polygonNormals = PolygonAttributes.FindOrNull <Vector3>("polygon_normals"); var pointLocations = PointAttributes.FindOrNull <Vector3>("point_locations"); var pointNormals = PointAttributes.FindOrNull <Vector3>("point_normals"); var cornerNormals = CornerAttributes.FindOrNull <Vector3>("corner_normals"); // Make copies of old points foreach (Point point in Points) { if (pointLocations != null && pointLocations.ContainsKey(point)) { pointLocations[point] = transform.TransformPoint(pointLocations[point]); } if (pointNormals != null && pointNormals.ContainsKey(point)) { pointNormals[point] = inverseTransposeTransform.TransformDirection(pointNormals[point]); } } foreach (Polygon polygon in Polygons) { if (polygonCentroids != null && polygonCentroids.ContainsKey(polygon)) { polygonCentroids[polygon] = transform.TransformPoint(polygonCentroids[polygon]); } if (polygonNormals != null && polygonNormals.ContainsKey(polygon)) { polygonNormals[polygon] = inverseTransposeTransform.TransformDirection(polygonNormals[polygon]); } if (cornerNormals != null) { foreach (Corner corner in polygon.Corners) { if (cornerNormals.ContainsKey(corner)) { cornerNormals[corner] = inverseTransposeTransform.TransformDirection(cornerNormals[corner]); } } } } }
public void Geodesate(float radius) { float rInv = 1.0f / radius; var polygonCentroids = PolygonAttributes.FindOrNull <Vector3>("polygon_centroids"); var polygonNormals = PolygonAttributes.FindOrNull <Vector3>("polygon_normals"); var pointLocations = PointAttributes.FindOrNull <Vector3>("point_locations"); var pointNormals = PointAttributes.FindOrNull <Vector3>("point_normals"); var cornerNormals = CornerAttributes.FindOrNull <Vector3>("corner_normals"); // Make copies of old points foreach (Point point in Points) { if ( (pointLocations != null) && pointLocations.ContainsKey(point) ) { Vector3 newNormal = Vector3.Normalize(pointLocations[point]); pointLocations[point] = radius * newNormal; if ( (pointNormals != null) && pointNormals.ContainsKey(point) ) { pointNormals[point] = newNormal; } } } foreach (Polygon polygon in Polygons) { if ( (polygonCentroids != null) && polygonCentroids.ContainsKey(polygon) ) { Vector3 newNormalizedCentroid = Vector3.Normalize(polygonCentroids[polygon]); polygonCentroids[polygon] = radius * newNormalizedCentroid; if ( (polygonNormals != null) && polygonNormals.ContainsKey(polygon) ) { polygonNormals[polygon] = newNormalizedCentroid; } } if (cornerNormals != null) { foreach (Corner corner in polygon.Corners) { if ( cornerNormals.ContainsKey(corner) ) { if (pointNormals.ContainsKey(corner.Point)) { cornerNormals[corner] = pointNormals[corner.Point]; } else if (pointLocations.ContainsKey(corner.Point)) { cornerNormals[corner] = pointLocations[corner.Point] * rInv; } } } } } }
public void MergeFast(Geometry other, Polygon thisPolygon, Polygon otherPolygon) { Dictionary <Point, Point> otherPointsToNewPoints = new Dictionary <Point, Point>(); var pointLocationsSelf = PointAttributes.FindOrNull <Vector3>("point_locations"); var pointLocationsOther = other.PointAttributes.FindOrNull <Vector3>("point_locations"); float pointEpsilon = 0.0001f; // Merge points foreach (Point otherPoint in other.Points) { Vector3 otherPosition = pointLocationsOther[otherPoint]; bool existingPointCloseEnough = false; foreach (Corner existingCorner in thisPolygon.Corners) { Point existingPoint = existingCorner.Point; Vector3 existingPosition = pointLocationsSelf[existingPoint]; float distanceSquared = existingPosition.DistanceSquared(otherPosition); if (distanceSquared < pointEpsilon) { existingPointCloseEnough = true; otherPointsToNewPoints[otherPoint] = existingPoint; break; } } if (existingPointCloseEnough == false) { otherPointsToNewPoints[otherPoint] = MakePoint(otherPosition); } } RemovePolygon(thisPolygon); // Merge polygons foreach (Polygon otherPolygon2 in other.Polygons) { if (otherPolygon != otherPolygon2) { Polygon newPolygon = MakePolygon(); foreach (Corner otherCorner in otherPolygon.Corners) { Point otherPoint = otherCorner.Point; Point newPoint = otherPointsToNewPoints[otherPoint]; newPolygon.MakeCorner(newPoint); } } } // Finally, remove unused points HashSet <Point> usedPoints = new HashSet <Point>(); foreach (Polygon polygon in Polygons) { foreach (Corner corner in polygon.Corners) { usedPoints.Add(corner.Point); } } List <Point> pointsToRemove = new List <Point>(); foreach (Point point in Points) { if (usedPoints.Contains(point) == false) { pointsToRemove.Add(point); } } foreach (Point pointToRemove in pointsToRemove) { Points.Remove(pointToRemove); } }
/// \todo Accelerate by sorting along major axis public void Merge(Geometry other) { Dictionary <Point, Point> otherPointsToNewPoints = new Dictionary <Point, Point>(); var pointLocationsSelf = PointAttributes.FindOrNull <Vector3>("point_locations"); var pointLocationsOther = other.PointAttributes.FindOrNull <Vector3>("point_locations"); float pointEpsilon = 0.0001f; // Merge points foreach (Point otherPoint in other.Points) { Vector3 otherPosition = pointLocationsOther[otherPoint]; bool existingPointCloseEnough = false; foreach (Point existingPoint in Points) { Vector3 existingPosition = pointLocationsSelf[existingPoint]; float distanceSquared = existingPosition.DistanceSquared(otherPosition); if (distanceSquared < pointEpsilon) { existingPointCloseEnough = true; otherPointsToNewPoints[otherPoint] = existingPoint; break; } } if (existingPointCloseEnough == false) { otherPointsToNewPoints[otherPoint] = MakePoint(otherPosition); } } // Merge polygons foreach (Polygon otherPolygon in other.Polygons) { // Test if we can find at least single matching polygon Polygon matchingPolygon = null; foreach (Polygon existingPolygon in Polygons) { // Test that all other corners can be found bool missingCorners = false; foreach (Corner otherCorner in otherPolygon.Corners) { Point newPoint = otherPointsToNewPoints[otherCorner.Point]; bool cornerFound = false; // Find matching corner foreach (Corner existingCorner in existingPolygon.Corners) { if (newPoint == existingCorner.Point) { cornerFound = true; break; } } // No matching corner found, continue if (cornerFound == false) { missingCorners = true; break; } } if (missingCorners == true) { continue; } // No missing corners - polygons match matchingPolygon = existingPolygon; break; } if (matchingPolygon != null) { // There was a matching polygon, delete it and do not create new from other RemovePolygon(matchingPolygon); //Polygons.Remove(matchingPolygon); } else { // There was no match, add new from other Polygon newPolygon = MakePolygon(); foreach (Corner otherCorner in otherPolygon.Corners) { Point otherPoint = otherCorner.Point; Point newPoint = otherPointsToNewPoints[otherPoint]; newPolygon.MakeCorner(newPoint); } } } // Finally, remove unused points HashSet <Point> usedPoints = new HashSet <Point>(); foreach (Polygon polygon in Polygons) { foreach (Corner corner in polygon.Corners) { usedPoints.Add(corner.Point); } } List <Point> pointsToRemove = new List <Point>(); foreach (Point point in Points) { if (usedPoints.Contains(point) == false) { pointsToRemove.Add(point); } } foreach (Point pointToRemove in pointsToRemove) { Points.Remove(pointToRemove); } }