/// <summary> /// 参照からなる構造体を実際に使用する構造体に変換する /// </summary> /// <param name="structure"></param> /// <param name="materialDict"></param> public static CompiledStructure Compile(RefStructure structure, MaterialDictionary materialDict) { // パーティクルのuidとindexの辞書を作成 var refParticles = structure.GetParticles(); var refEdges = structure.GetEdges(); // 描画用マテリアルの順番を考慮する var matDict = materialDict.ExportDictionry(); var particleMaterialList = CreateParticleMaterialList(refParticles, matDict); var edgeMaterialList = CreateEdgeMaterialList(refEdges, matDict); // パーティクルとエッジを使用マテリアルの順番に整列する var materialOrderRefParticles = AlignParticlesWithMaterialOrder(refParticles, particleMaterialList); var materialOrderRefEdges = AlignEdgesWithMaterialOrder(refEdges, edgeMaterialList); // 各種データを変換 var indexDict = CreateUID2IndexDictionary(materialOrderRefParticles); var particles = CompileParticles(materialOrderRefParticles); var edges = CompileEdges(materialOrderRefEdges, materialOrderRefParticles, indexDict); // マテリアルとそれぞれのオフセットを配列に var particleMaterials = particleMaterialList.Select(x => x.Key).ToArray(); var edgeMaterials = edgeMaterialList.Select(x => x.Key).ToArray(); var particleOffsets = CreateMaterialOffsets(particleMaterialList); var edgeOffsets = CreateMaterialOffsets(edgeMaterialList); // それぞれのマテリアル毎のパーティクルとエッジの数を配列に var particleCounts = CalcCountEachMaterials(particleMaterialList); var edgeCounts = CalcCountEachMaterials(edgeMaterialList); // インスタンスを生成してデータを設定 var compiled = UnityEngine.ScriptableObject.CreateInstance <CompiledStructure>(); compiled.SetDatas(particles, edges, particleMaterials, edgeMaterials, particleOffsets, edgeOffsets, particleCounts, edgeCounts); return(compiled); }
/// <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); }