diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 5b183b4..6eabfed 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -130,8 +130,6 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 197491476} - - component: {fileID: 197491475} - - component: {fileID: 197491474} - component: {fileID: 197491473} m_Layer: 0 m_Name: Fractal @@ -153,53 +151,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: depth: 6 ---- !u!23 &197491474 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 197491472} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 8f3914ac4291e664ba60ae208ae66460, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &197491475 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 197491472} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} + mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} + material: {fileID: 2100000, guid: 8f3914ac4291e664ba60ae208ae66460, type: 2} --- !u!4 &197491476 Transform: m_ObjectHideFlags: 0 diff --git a/Assets/Script/Fractal.cs b/Assets/Script/Fractal.cs index fd51466..6359f1c 100644 --- a/Assets/Script/Fractal.cs +++ b/Assets/Script/Fractal.cs @@ -2,44 +2,108 @@ public class Fractal : MonoBehaviour { + private struct FractalPart + { + public Vector3 direction; + public Quaternion rotation; + public Transform transform; + } + + FractalPart[][] parts; + [SerializeField, Range(1, 8)] int depth = 4; - private void Start() - { - name = "Fractal " + depth; - Debug.Log(name); + [SerializeField] + Mesh mesh = default; - if (depth <= 1) + [SerializeField] + Material material = default; + + static Vector3[] directions = + { + Vector3.up, + Vector3.right, + Vector3.left, + Vector3.forward, + Vector3.back + }; + + static Quaternion[] rotations = + { + Quaternion.identity, + Quaternion.Euler(0f, 0f, -90f), + Quaternion.Euler(0f, 0f, 90f), + Quaternion.Euler(90f, 0f, 0f), + Quaternion.Euler(-90f, 0f, 0f) + }; + + private FractalPart CreatePart(int levelIndex, int childIndex, float scale) + { + var go = new GameObject("Fractal Part L" + levelIndex + " C" + childIndex); + go.transform.localScale = scale * Vector3.one; + go.transform.SetParent(transform, false); + go.AddComponent().mesh = mesh; + go.AddComponent().material = material; + + return new FractalPart() { - return; + direction = directions[childIndex], + rotation = rotations[childIndex], + transform = go.transform + }; + } + + private void Awake() + { + parts = new FractalPart[depth][]; + for (int i = 0, length = 1; i < parts.Length; i++, length *= 5) + { + parts[i] = new FractalPart[length]; } - var childA = CreateChild(Vector3.up, Quaternion.identity); - var childB = CreateChild(Vector3.right, Quaternion.Euler(0f, 0f, -90f)); - var childC = CreateChild(Vector3.left, Quaternion.Euler(0f, 0f, 90f)); - var childD = CreateChild(Vector3.forward, Quaternion.Euler(90f, 0f, 0f)); - var childE = CreateChild(Vector3.back, Quaternion.Euler(-90f, 0f, 0f)); - - childA.transform.SetParent(transform, false); - childB.transform.SetParent(transform, false); - childC.transform.SetParent(transform, false); - childD.transform.SetParent(transform, false); - childE.transform.SetParent(transform, false); + var scale = 1f; + parts[0][0] = CreatePart(0, 0, scale); + for (int li = 1; li < parts.Length; li++) + { + scale *= 0.5f; + FractalPart[] levelParts = parts[li]; + for (int fpi = 0; fpi < levelParts.Length; fpi += 5) + { + for (int ci = 0; ci < 5; ci++) + { + levelParts[fpi + ci] = CreatePart(li, ci, scale); + } + } + } } private void Update() { - transform.Rotate(0f, 22.5f * Time.deltaTime, 0f); - } + Quaternion deltaRotation = Quaternion.Euler(0f, 22.5f * Time.deltaTime, 0f); - private Fractal CreateChild(Vector3 direction, Quaternion rotation) - { - var child = Instantiate(this); - child.depth = depth - 1; - child.transform.localPosition = 0.75f * direction; - child.transform.localRotation = rotation; - child.transform.localScale = 0.5f * Vector3.one; - return child; + FractalPart rootPart = parts[0][0]; + rootPart.rotation *= deltaRotation; + rootPart.transform.localRotation = rootPart.rotation; + parts[0][0] = rootPart; + + for (int li = 1; li < parts.Length; li++) + { + FractalPart[] parentParts = parts[li - 1]; + FractalPart[] levelParts = parts[li]; + for (int fpi = 0; fpi < levelParts.Length; fpi++) + { + var parentTransform = parentParts[fpi / 5].transform; + var part = levelParts[fpi]; + part.rotation *= deltaRotation; + part.transform.rotation = + parentTransform.localRotation * part.rotation; + part.transform.localPosition = + parentTransform.localPosition + + parentTransform.localRotation * + (1.5f * part.transform.localScale.x * part.direction); + levelParts[fpi] = part; + } + } } }