public override RefStructure Build(Matrix4x4 toWorld) { var s = RefStructure.CreateNew(); var stepSize = Mathf.PI * 2f / _resolution; //パーティクルを配置 var p = new RefParticle[_resolution]; for (var i = 0; i < _resolution; ++i) { var t = stepSize * i; var x = Mathf.Cos(t) * _radius; var y = Mathf.Sin(t) * _radius; p[i] = _particleBuilder.Add(s, new Vector2(x, y)); } // エッジを配置 for (var i = 0; i < _resolution; ++i) { _edgeBuilder.Add(s, p[i], p[(i + 1) % _resolution]); for (var j = 0; j < _supportIntervals.Length; ++j) { _supportEdgeBuilder.Add(s, p[i], p[(i + _supportIntervals[j]) % _resolution]); } } s.TranslateParticles(toWorld); return(s); }
RefParticle MakeBranch(RefStructure s, int depth, RefParticle parent, float angle, float length) { var dir = Utilities.Angle2Vector(angle * Mathf.Deg2Rad); var pos = parent.position + dir * length; var current = _branchParticleBuilder.Add(s, pos); depth--; if (depth > 0) { /*var edge = */ _branchEdgeBuilder.Add(s, parent, current); // 分岐していく RefParticle b1, b2; if (length * Random.Range(1f, 2f) / _tempBaseBranchLength > 1f) { b1 = MakeBranch(s, depth, current, angle + _angleoffsetA.random, length * _branchLengthDampingA.random); } else { b1 = MakeBranch(s, depth, current, angle + _angleoffsetB.random, length * _branchLengthDampingB.random); } if (length * Random.Range(1f, 2f) / _tempBaseBranchLength > 1f) { b2 = MakeBranch(s, depth, current, angle - _angleoffsetA.random, length * _branchLengthDampingA.random); } else { b2 = MakeBranch(s, depth, current, angle - _angleoffsetB.random, length * _branchLengthDampingB.random); } // サポート _branchSupportEdgeBuilder.Add(s, b1, b2); _branchSupportEdgeBuilder.Add(s, parent, b1); _branchSupportEdgeBuilder.Add(s, parent, b2); } else { current.position = parent.position + dir * _leafLength.random; /*var leaf = */ _leafEdgeBuilder.Add(s, parent, current); } return(current); }
/// <summary> /// エッジの追加処理 /// </summary> void HandleAddEdge() { if (_structure) { var wpos = Camera.main.ScreenToWorldPoint(Input.mousePosition); var hitten = RefStructure.HitParticle(_structure, wpos); if (hitten != null) { if (_prevHitten == null) { _prevHitten = hitten; } else if (_prevHitten != hitten) { _edgeBuilder.Add(_structure, _prevHitten, hitten); AddEditHistory(); _prevHitten = null; SetDirty(); } } } }
/// <summary> /// 特定のパーティクルの距離によるミックスを行う。多分これが一番シンプルな方法何じゃないかな? /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="dist"></param> /// <param name="edgeBuilder"></param> /// <returns></returns> public static RefStructure Mix(RefStructure a, RefStructure b, float dist, BaseEdgeBuilder edgeBuilder) { Assert.IsNotNull(a); Assert.IsNotNull(b); Assert.IsNotNull(edgeBuilder); var dst = RefStructure.CreateNew(); // それぞれの構造体の中から一定の距離感にある。パーティクル同士をエッジでつなげる。 var aParticles = a.GetParticles(); var bParticles = b.GetParticles(); var pairDict = new Dictionary <RefParticle, int[]>(); for (var i = 0; i < aParticles.Length; ++i) { var t = aParticles[i]; var neighbours = FindParticles(t, dist, bParticles); pairDict.Add(t, neighbours); } // とりあえずペアを見つけ出したので、つないでみる。 // ここで注意なのがパーティクルがaとbのどちらに属しているのかということ。 // それらを意識しながら、接続関係をまとめていく。 var aCount = aParticles.Length; // 一旦すべてのパーティクルとエッジを追加する AddParticles(dst, aParticles); AddParticles(dst, bParticles); // エッジの追加にはパーティクルのUIDからIdxへのマッピング辞書が必要。 var aEdges = a.GetEdges(); var bEdges = b.GetEdges(); var uid2IdxDictA = CreateUID2IdxDictionary(aParticles); var uid2IdxDictB = CreateUID2IdxDictionary(bParticles); // Debug.Log(uid2IdxDictA.Count); AddEdges(dst, aEdges, uid2IdxDictA, 0); AddEdges(dst, bEdges, uid2IdxDictB, aCount); // ここから新しい接続用のエッジを追加していく。 foreach (var pair in pairDict) { if (pair.Value.Length == 0) { continue; } var idx = uid2IdxDictA[pair.Key.uid]; for (var i = 0; i < pair.Value.Length; ++i) { var tIdx = pair.Value[i] + aCount; // 2つのインデックスが揃ったのでエッジを作る edgeBuilder.Add(dst, idx, tIdx); } } return(dst); }