public Vector3 GetFaceNormal(int[] face, FractalShape baseShape, List <Vector3> normals) { int triangleIndex = -1; for (int i = 0; i < face.Length; i++) { for (int i1 = 0; i1 < face.Length; i1++) { for (int i2 = 0; i2 < face.Length; i2++) { if (i == i1 || i == i2 || i1 == i2) { continue; } int[] triangle = new int[] { face[i], face[i1], face[i2] }; for (int i3 = 0; i3 < baseShape.triangles.Count; i3++) { if (baseShape.triangles[i3].points.SequenceEqual(triangle)) { triangleIndex = i3; } } } if (triangleIndex != -1) { break; } } if (triangleIndex != -1) { break; } } return(normals[triangleIndex]); }
public List <Shape3D> GenerateFractal(Shape3D shape, List <int[]> buildFaces, int endpt) { FractalShape origin = new FractalShape { shape = shape, buildFaces = buildFaces, endpt = endpt, depth = 0, }; List <FractalShape> unhandledChildren = new List <FractalShape> { origin }; List <Shape3D> shapes = new List <Shape3D>(); while (unhandledChildren.Count > 0) { List <FractalShape> newChildren = GetChildren(unhandledChildren[0]); unhandledChildren.AddRange(newChildren); foreach (FractalShape f in newChildren) { shapes.Add(f.shape); } unhandledChildren.RemoveAt(0); while (unhandledChildren.Count > 0 && unhandledChildren[0].depth > 3) { unhandledChildren.RemoveAt(0); } } return(shapes); }
public Fractal(FractalShape baseShape, float normalDist, float proportionBaseSize, int maxDepth) { this.baseShape = baseShape; this.normalDist = normalDist; this.proportionBaseSize = proportionBaseSize; this.maxDepth = maxDepth; fractalChild = (GameObject)Resources.Load("empty"); }
//creates a 'transition' shape between baseShapes to maintain similar baseShape proportions. public List <FractalShape> GetTransitionShapes(int[] generationFaceIndexes, FractalShape baseShape, float normalDist, float proportionBaseSize, List <Vector3> normals) { List <Vector3> generationFace = new List <Vector3>(); for (int i = 0; i < generationFaceIndexes.Length; i++) { generationFace.Add(baseShape.points[generationFaceIndexes[i]]); } Vector3 normal = GetFaceNormal(generationFaceIndexes, baseShape, normals); Debug.DrawLine(Vector3.zero, normal.normalized * 10, Color.cyan, 10000); Plane transitionPlane = new Plane(normal, generationFace[0] + normal * normalDist); Vector3 averageGenerationPoint = Vector3.zero; for (int i = 0; i < generationFace.Count; i++) { averageGenerationPoint += generationFace[i] + normal * normalDist; } averageGenerationPoint /= generationFace.Count; Vector2 averageGenerationPoint2D = transitionPlane.GetMappedPoint(averageGenerationPoint); Plane basePlane = new Plane(baseShape.points[baseShape.baseFace[0]], baseShape.points[baseShape.baseFace[1]], baseShape.points[baseShape.baseFace[2]]); Vector3 averageBase = Vector3.zero; for (int i = 0; i < baseShape.baseFace.Length; i++) { averageGenerationPoint += baseShape.points[baseShape.baseFace[i]] + normal * normalDist; } averageBase /= generationFace.Count; Vector2 averageBase2D = basePlane.GetMappedPoint(averageBase); List <Vector2> basePointsMapped = new List <Vector2>(); for (int i = 0; i < baseShape.baseFace.Length; i++) { basePointsMapped.Add((basePlane.GetMappedPoint(baseShape.points[baseShape.baseFace[i]]) - averageBase2D) * proportionBaseSize); } List <Vector3> transitionFace = new List <Vector3>(); for (int i = 0; i < basePointsMapped.Count; i++) { transitionFace.Add(basePointsMapped[i].x * transitionPlane.xDir + basePointsMapped[i].y * transitionPlane.yDir + averageGenerationPoint); } List <Vector3> transitionShapePoints = new List <Vector3>(); transitionShapePoints.AddRange(generationFace); for (int i = 0; i < generationFace.Count; i++) { float leastDist = float.MaxValue; int leastDistIndex = -1; for (int i1 = 0; i1 < transitionFace.Count; i1++) { float sqrDist = Vector2.SqrMagnitude(transitionPlane.GetMappedPoint(transitionShapePoints[i]) - transitionPlane.GetMappedPoint(basePointsMapped[i])); if (sqrDist <= leastDist) { leastDist = sqrDist; leastDistIndex = i1; } } Debug.DrawLine(generationFace[i], transitionFace[leastDistIndex], Color.white, 10000); transitionShapePoints.Add(transitionFace[leastDistIndex]); transitionFace.RemoveAt(leastDistIndex); } List <int[]> transitionShapeTriangles = new List <int[]>(); for (int i = 0; i < generationFace.Count; i++) { //transitionShapeTriangles.Add(new int[] { i, i + generationFace.Count, (i + generationFace.Count - 1) % transitionShapePoints.Count }); transitionShapeTriangles.Add(new int[] { i, (i + 1) % generationFace.Count, (i + generationFace.Count + 1) % transitionShapePoints.Count }); if (i + 2 < generationFace.Count) { transitionShapeTriangles.Add(new int[] { 0, i + 1, i + 2 }); transitionShapeTriangles.Add(new int[] { generationFace.Count, i + generationFace.Count + 1, i + generationFace.Count + 2 }); } } FractalShape transitionShape = new FractalShape(transitionShapePoints, transitionShapeTriangles, new int[0], new List <int[]>()); List <Vector2> baseShapeMapped = new List <Vector2>(); List <float> distFromBasePlane = new List <float>(); for (int i = 0; i < baseShape.points.Count; i++) { distFromBasePlane.Add(basePlane.GetDistToPlane(baseShape.points[i]) * proportionBaseSize); baseShapeMapped.Add((basePlane.GetMappedPoint(baseShape.points[i]) - averageBase2D) * proportionBaseSize); } List <Vector3> newBaseShapePoints = new List <Vector3>(); for (int i = 0; i < baseShape.points.Count; i++) { newBaseShapePoints.Add(baseShapeMapped[i].x * transitionPlane.xDir + baseShapeMapped[i].y * transitionPlane.yDir + distFromBasePlane[i] * transitionPlane.normal.normalized + averageGenerationPoint); } FractalShape newBaseShape = new FractalShape(newBaseShapePoints, baseShape.triangles, baseShape.trianglesHash, baseShape.baseFace, baseShape.generationFaces); return(new List <FractalShape> { transitionShape, newBaseShape }); }
public List <FractalShape> GetChildren(FractalShape origin) { List <int[]> triangles = origin.buildFaces; List <Vector3> points = origin.shape.points; int endpt = origin.endpt; Vector3 avgPt = Vector3.zero; foreach (Vector3 v in origin.shape.points) { avgPt += v; } avgPt /= origin.shape.points.Count; List <FractalShape> children = new List <FractalShape>(); foreach (int[] triangle in triangles) { List <Vector3> childPoints = new List <Vector3>(); childPoints.Add(points[endpt]); int[] triPts = new int[2]; int ind = 0; for (int i = 0; i < triangle.Length; i++) { if (triangle[i] != endpt) { triPts[ind] = triangle[i]; ind++; } } childPoints.Add(Vector3.Lerp(points[triPts[0]], points[endpt], UnityEngine.Random.Range(0.7f, 0.8f))); childPoints.Add(Vector3.Lerp(points[triPts[1]], points[endpt], UnityEngine.Random.Range(0.7f, 0.8f))); Vector3 A = childPoints[0]; Vector3 B = childPoints[1]; Vector3 C = childPoints[2]; Vector3 norm = Vector3.Cross((B - A), (C - A)).normalized; int mult = -1; if (Vector3.Angle(norm, A - avgPt) < 90) { mult = 1; } float d = -Vector3.Dot(norm, A); float w = Vector3.Dot(norm, -norm * mult); //reverse array if counter clockwise if (w > 0) { childPoints.Reverse(); } Vector3 sum = Vector3.zero; foreach (Vector3 v in childPoints) { sum += v; } Vector3 center = sum / 3; Plane p = new Plane(childPoints[0], childPoints[1], childPoints[2]); Vector3 outPoint = center + p.normal.normalized * (normalfactor / Mathf.Sqrt(origin.depth + 1)); childPoints.Add(outPoint); int[][] childTriangles = new int[][] { new int[] { 0, 1, 2 }, new int[] { 0, 1, 3 }, new int[] { 0, 2, 3 }, new int[] { 1, 2, 3 } }; List <int[]> buildFaces = new List <int[]> { childTriangles[1], childTriangles[2], childTriangles[3] }; Shape3D s = new Shape3D(childTriangles, childPoints); FractalShape child = new FractalShape { shape = s, buildFaces = buildFaces, endpt = 3, depth = origin.depth + 1, }; children.Add(child); } return(children); }