//=========================================================================================
        /// <summary>
        /// クロス初期化
        /// </summary>
        protected override void ClothInit()
        {
            // 中央トランスフォームに移動パーティクルを1つ設定する(これが揺れる)
            // クロスデータはこの場で作成する
            ClothData cdata = ShareDataObject.CreateShareData <ClothData>("ClothData_work");

            cdata.selectionData.Add(SelectionData.Move);
            cdata.vertexFlagLevelList.Add(0);
            cdata.vertexDepthList.Add(0);
            cdata.rootList.Add(0);
            cdata.useVertexList.Add(0);
            cdata.initScale       = SpringData.initScale;
            cdata.SaveDataHash    = 1;
            cdata.SaveDataVersion = cdata.GetVersion();
            ClothData             = cdata;

            // エラーが出ないように
            clothDataHash    = cdata.SaveDataHash;
            clothDataVersion = cdata.SaveDataVersion;

            // クロス初期化
            base.ClothInit();

            // スプリングではClampPositonの速度制限は無視する
            MagicaPhysicsManager.Instance.Team.SetFlag(TeamId, PhysicsManagerTeamData.Flag_IgnoreClampPositionVelocity, true);
        }
示例#2
0
        /// <summary>
        /// 新規選択クラスを作成して返す
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        protected SelectionData CreateSelection(MonoBehaviour obj, string property)
        {
            string dataname  = "SelectionData_" + obj.name;
            var    selection = ShareDataObject.CreateShareData <SelectionData>(dataname);

            return(selection);
        }
        /// <summary>
        /// 近接ラインの接続
        /// </summary>
        /// <param name="lineSet"></param>
        /// <param name="wposList"></param>
        /// <param name="mdata"></param>
        //void CreateNearLine(BoneCloth scr, HashSet<uint> lineSet, List<Vector3> wposList, MeshData mdata)
        //{
        //    for (int i = 0; i < (mdata.VertexCount - 1); i++)
        //    {
        //        for (int j = i + 1; j < mdata.VertexCount; j++)
        //        {
        //            float dist = Vector3.Distance(wposList[i], wposList[j]);
        //            if (dist <= scr.ClothTarget.ConnectionDistance)
        //            {
        //                // 接続
        //                uint pair = DataUtility.PackPair(i, j);
        //                lineSet.Add(pair);
        //            }
        //        }
        //    }
        //}

        /// <summary>
        /// クロスデータ作成
        /// </summary>
        void CreateClothdata(MagicaBoneCloth scr)
        {
            if (scr.MeshData == null)
            {
                return;
            }

            // クロスデータ共有データ作成(既存の場合は選択状態のみコピーする)
            string dataname = "BoneClothData_" + scr.name;
            var    cloth    = ShareDataObject.CreateShareData <ClothData>(dataname);

            // クロスデータ作成
            cloth.CreateData(
                scr,
                scr.Params,
                scr.TeamData,
                scr.MeshData,
                scr,
                scr.ClothSelection.GetSelectionData(scr.MeshData, null)
                );
            serializedObject.FindProperty("clothData").objectReferenceValue = cloth;

            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(cloth);
        }
示例#4
0
        /// <summary>
        /// クロスデータ作成
        /// </summary>
        void CreateClothdata(MagicaBoneSpring scr)
        {
            if (scr.MeshData == null)
            {
                return;
            }

            // クロスデータ共有データ作成(既存の場合は選択状態のみコピーする)
            string dataname = "BoneSpringData_" + scr.name;
            var    cloth    = ShareDataObject.CreateShareData <ClothData>(dataname);

            // セレクトデータはすべて「移動」で受け渡す
            List <int> selectList = new List <int>();

            for (int i = 0; i < scr.MeshData.VertexCount; i++)
            {
                selectList.Add(SelectionData.Move);
            }

            // クロスデータ作成
            cloth.CreateData(
                scr,
                scr.Params,
                scr.TeamData,
                scr.MeshData,
                scr,
                selectList
                );
            serializedObject.FindProperty("clothData").objectReferenceValue = cloth;

            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(cloth);
        }
示例#5
0
        //=========================================================================================
        /// <summary>
        /// データ作成
        /// </summary>
        void CreateData()
        {
            MagicaMeshCloth scr = target as MagicaMeshCloth;

            Debug.Log("Started creating. [" + scr.name + "]");

            // 共有選択データが存在しない場合は作成する
            if (scr.ClothSelection == null)
            {
                InitSelectorData();
            }

            // チームハッシュを設定
            scr.TeamData.ValidateColliderList();

            // クロスデータ共有データ作成
            string dataname = "MeshClothData_" + scr.name;
            var    cloth    = ShareDataObject.CreateShareData <ClothData>(dataname);

            // クロスデータ用にセレクションデータを拡張する
            // (1)無効頂点の隣接が移動/固定頂点なら拡張に変更する
            // (2)移動/固定頂点に影響する子頂点に接続する無効頂点は拡張に変更する
            var selection = scr.Deformer.MeshData.ExtendSelection(
                scr.ClothSelection.GetSelectionData(scr.Deformer.MeshData, scr.Deformer.GetRenderDeformerMeshList()),
                true,
                true
                );

            // クロスデータ作成
            cloth.CreateData(
                scr,
                scr.Params,
                scr.TeamData,
                scr.Deformer.MeshData,
                scr.Deformer,
                selection
                );

            // クロスデータを設定
            var cdata = serializedObject.FindProperty("clothData");

            cdata.objectReferenceValue = cloth;
            serializedObject.ApplyModifiedProperties();

            // 検証
            scr.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(cloth);

            if (scr.VerifyData() == Define.Error.None)
            {
                Debug.Log("Creation completed. [" + scr.name + "]");
            }
            else
            {
                Debug.LogError("Creation failed.");
            }
        }
        //=========================================================================================
        /// <summary>
        /// データ作成
        /// </summary>
        void CreateData()
        {
            MagicaMeshSpring scr = target as MagicaMeshSpring;

            Debug.Log("Started creating. [" + scr.name + "]");

            // センタートランスフォーム
            if (scr.CenterTransform == null)
            {
                serializedObject.FindProperty("centerTransform").objectReferenceValue = scr.transform;
            }

            // デフォーマーリスト整理
            //scr.VerifyDeformer();

            // 共有データオブジェクト作成
            SpringData sdata = ShareDataObject.CreateShareData <SpringData>("SpringData_" + scr.name);

            serializedObject.ApplyModifiedProperties();
            CreateClothData(scr, sdata, scr.GetDeformer(0));

            // データ検証
            sdata.CreateVerifyData();

            // 新しいデータを設定
            serializedObject.FindProperty("springData").objectReferenceValue = sdata;
            serializedObject.ApplyModifiedProperties();

            // 仮想デフォーマーのハッシュを設定
            //var property = serializedObject.FindProperty("virtualDeformerHash");
            //property.intValue = scr.VirtualDeformerHash;
            //serializedObject.ApplyModifiedProperties();

            // データ検証
            scr.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(sdata);

            if (scr.VerifyData() == Define.Error.None)
            {
                Debug.Log("Creation completed. [" + scr.name + "]");
            }
            else
            {
                Debug.LogError("Creation failed.");
            }
        }
        //=========================================================================================
        /// <summary>
        /// 事前データ作成(エディット時のみ)
        /// ※RenderDeformerはマルチ選択+コンポーネントアタッチで自動生成する必要があるのでこちらに配置する
        /// </summary>
        public void CreateData()
        {
            Debug.Log("Started creating. [" + this.name + "]");

            var serializedObject = new SerializedObject(this);

            // ターゲットオブジェクト
            serializedObject.FindProperty("deformer.targetObject").objectReferenceValue = gameObject;
            serializedObject.FindProperty("deformer.dataHash").intValue = 0;

            // 共有データ作成
            var meshData = ShareDataObject.CreateShareData <MeshData>("RenderMeshData_" + this.name);

            // renderer
            var ren = GetComponent <Renderer>();

            if (ren == null)
            {
                Debug.LogError("Creation failed. Renderer not found.");
                return;
            }

            Mesh sharedMesh = null;

            if (ren is SkinnedMeshRenderer)
            {
                meshData.isSkinning = true;
                var sren = ren as SkinnedMeshRenderer;
                sharedMesh = sren.sharedMesh;
            }
            else
            {
                meshData.isSkinning = false;
                var meshFilter = ren.GetComponent <MeshFilter>();
                if (meshFilter == null)
                {
                    Debug.LogError("Creation failed. MeshFilter not found.");
                    return;
                }
                sharedMesh = meshFilter.sharedMesh;
            }

            // 頂点
            meshData.vertexCount = sharedMesh.vertexCount;

            // 頂点ハッシュ
            var          vlist          = sharedMesh.vertices;
            List <ulong> vertexHashList = new List <ulong>();

            for (int i = 0; i < vlist.Length; i++)
            {
                var vhash = DataHashExtensions.GetVectorDataHash(vlist[i]);
                //Debug.Log("[" + i + "] (" + (vlist[i] * 1000) + ") :" + vhash);
                vertexHashList.Add(vhash);
            }
            meshData.vertexHashList = vertexHashList.ToArray();

            // トライアングル
            meshData.triangleCount = sharedMesh.triangles.Length / 3;

            // レンダーデフォーマーのメッシュデータにはローカル座標、法線、接線、UV、トライアングルリストは保存しない
            // 不要なため

            // ボーン
            int boneCount = meshData.isSkinning ? sharedMesh.bindposes.Length : 1;

            meshData.boneCount = boneCount;

            // メッシュデータの検証とハッシュ
            meshData.CreateVerifyData();

            serializedObject.FindProperty("deformer.sharedMesh").objectReferenceValue = sharedMesh;
            serializedObject.FindProperty("deformer.meshData").objectReferenceValue   = meshData;
            serializedObject.FindProperty("deformer.meshOptimize").intValue           = EditUtility.GetOptimizeMesh(sharedMesh);
            serializedObject.ApplyModifiedProperties();

            // デフォーマーデータの検証とハッシュ
            Deformer.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            // コアコンポーネントの検証とハッシュ
            CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(meshData);

            // 変更後数
            Debug.Log("Creation completed. [" + this.name + "]");
        }
示例#8
0
        //=========================================================================================
        /// <summary>
        /// 事前データ作成
        /// </summary>
        /// <param name="scr"></param>
        private void CreateData(MagicaVirtualDeformer scr)
        {
            Debug.Log("Started creating. [" + scr.name + "]");

            // 子メッシュの検証
            if (VerifyChildData(scr.Deformer) == false)
            {
                // error
                Debug.LogError("Setup failed. Invalid RenderDeformer data.");
                return;
            }

            serializedObject.FindProperty("deformer.targetObject").objectReferenceValue = scr.gameObject;

            // 新規メッシュデータ
            var meshData = ShareDataObject.CreateShareData <MeshData>("VirtualMeshData_" + scr.name);

            // 設計時スケール
            meshData.baseScale = scr.transform.lossyScale;

            // 仮想メッシュ作成
            var reductionMesh = new MagicaReductionMesh.ReductionMesh();

            reductionMesh.WeightMode = MagicaReductionMesh.ReductionMesh.ReductionWeightMode.Average; // 平均法(v1.5.2)
            reductionMesh.MeshData.MaxWeightCount   = scr.Deformer.MaxWeightCount;
            reductionMesh.MeshData.WeightPow        = scr.Deformer.WeightPow;
            reductionMesh.MeshData.SameSurfaceAngle = scr.Deformer.SameSurfaceAngle;
            for (int i = 0; i < scr.Deformer.RenderDeformerCount; i++)
            {
                var deformer = scr.Deformer.GetRenderDeformer(i).Deformer;
                if (deformer != null)
                {
                    var sren = deformer.TargetObject.GetComponent <SkinnedMeshRenderer>();
                    List <Transform> boneList = new List <Transform>();
                    if (sren)
                    {
                        boneList = new List <Transform>(sren.bones);
                    }
                    else
                    {
                        boneList.Add(deformer.TargetObject.transform);
                    }
                    reductionMesh.AddMesh(
                        deformer.MeshData.isSkinning,
                        deformer.SharedMesh,
                        boneList,
                        deformer.SharedMesh.bindposes,
                        deformer.SharedMesh.boneWeights
                        );
                }
            }

            //reductionMesh.DebugData.DispMeshInfo("リダクション前");

            // リダクション
            reductionMesh.Reduction(
                scr.Deformer.MergeVertexDistance > 0.0f ? 0.0001f : 0.0f,
                scr.Deformer.MergeVertexDistance,
                scr.Deformer.MergeTriangleDistance,
                false
                );

            // (1)ゼロ距離リダクション
            //if (scr.Deformer.MergeVertexDistance > 0.0f)
            //    reductionMesh.ReductionZeroDistance();

            //// (2)頂点距離マージ
            //if (scr.Deformer.MergeVertexDistance > 0.0001f)
            //    reductionMesh.ReductionRadius(scr.Deformer.MergeVertexDistance);

            //// (3)トライアングル接続マージ
            //if (scr.Deformer.MergeTriangleDistance > 0.0f)
            //    reductionMesh.ReductionPolygonLink(scr.Deformer.MergeTriangleDistance);

            //// (4)未使用ボーンの削除
            //reductionMesh.ReductionBone();

            // (5)頂点の最大接続トライアングル数制限
            //reductionMesh.ReductionTriangleConnect(6);

            //reductionMesh.DebugData.DispMeshInfo("リダクション後");

            // 最終メッシュデータ取得
            var final = reductionMesh.GetFinalData(scr.gameObject.transform);

            // メッシュデータシリアライズ
            meshData.isSkinning  = final.IsSkinning;
            meshData.vertexCount = final.VertexCount;

            List <uint> vlist;
            List <MeshData.VertexWeight> wlist;

            CreateVertexWeightList(
                final.VertexCount, final.vertices, final.normals, final.tangents, final.boneWeights, final.bindPoses,
                out vlist, out wlist
                );
            meshData.vertexInfoList   = vlist.ToArray();
            meshData.vertexWeightList = wlist.ToArray();
            meshData.boneCount        = final.BoneCount;

            meshData.uvList        = final.uvs.ToArray();
            meshData.lineCount     = final.LineCount;
            meshData.lineList      = final.lines.ToArray();
            meshData.triangleCount = final.TriangleCount;
            meshData.triangleList  = final.triangles.ToArray();

            List <uint> vertexToTriangleInfoList = new List <uint>();

            for (int i = 0; i < final.VertexCount; i++)
            {
                int tcnt   = final.vertexToTriangleCountList[i];
                int tstart = final.vertexToTriangleStartList[i];
                vertexToTriangleInfoList.Add(DataUtility.Pack8_24(tcnt, tstart));
            }
            meshData.vertexToTriangleInfoList  = vertexToTriangleInfoList.ToArray();
            meshData.vertexToTriangleIndexList = final.vertexToTriangleIndexList.ToArray();

            // 子メッシュ情報
            for (int i = 0; i < final.MeshCount; i++)
            {
                var minfo     = final.meshList[i];
                var rdeformer = scr.Deformer.GetRenderDeformer(i).Deformer;
                var mdata     = new MeshData.ChildData();

                mdata.childDataHash = rdeformer.GetDataHash();
                mdata.vertexCount   = minfo.VertexCount;

                // 頂点ウエイト情報作成
                CreateVertexWeightList(
                    minfo.VertexCount, minfo.vertices, minfo.normals, minfo.tangents, minfo.boneWeights, final.vertexBindPoses,
                    out vlist, out wlist
                    );

                mdata.vertexInfoList   = vlist.ToArray();
                mdata.vertexWeightList = wlist.ToArray();

                mdata.parentIndexList = minfo.parents.ToArray();

                meshData.childDataList.Add(mdata);
            }

            // レイヤー情報
            //for (int i = 0; i < final.LayerCount; i++)
            //{
            //    var linfo = new MeshData.LayerInfo();
            //    linfo.triangleList = new List<int>(final.layerList[i].triangleList);
            //    meshData.layerInfoList.Add(linfo);
            //}

            // 検証
            meshData.CreateVerifyData();
            serializedObject.FindProperty("deformer.meshData").objectReferenceValue = meshData;

            // ボーン
            var property = serializedObject.FindProperty("deformer.boneList");

            property.arraySize = final.bones.Count;
            for (int i = 0; i < final.bones.Count; i++)
            {
                property.GetArrayElementAtIndex(i).objectReferenceValue = final.bones[i];
            }

            serializedObject.ApplyModifiedProperties();

            // デフォーマーデータの検証とハッシュ
            scr.Deformer.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            // コアコンポーネントの検証とハッシュ
            scr.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(meshData);

            Debug.Log("Setup completed. [" + scr.name + "]");
        }
        /// <summary>
        /// メッシュデータ作成
        /// </summary>
        void CreateMeshData(MagicaBoneCloth scr)
        {
            // 共有データオブジェクト作成
            string   dataname = "BoneClothMeshData_" + scr.name;
            MeshData mdata    = ShareDataObject.CreateShareData <MeshData>(dataname);

            // トランスフォームリスト作成
            var transformList = scr.GetTransformList();

            if (transformList.Count == 0)
            {
                return;
            }

            // 頂点作成
            List <Vector3> wposList = new List <Vector3>();
            List <Vector3> lposList = new List <Vector3>();
            List <Vector3> lnorList = new List <Vector3>();
            List <Vector3> ltanList = new List <Vector3>();
            Transform      myt      = scr.transform;

            for (int i = 0; i < transformList.Count; i++)
            {
                var t = transformList[i];

                // 頂点追加
                var pos  = t.position;
                var lpos = myt.InverseTransformDirection(pos - myt.position);
                var lnor = myt.InverseTransformDirection(t.forward);
                var ltan = myt.InverseTransformDirection(t.up);
                wposList.Add(pos);
                lposList.Add(lpos);
                lnorList.Add(lnor);
                ltanList.Add(ltan);
            }
            var vertexInfoList   = new List <uint>();
            var vertexWeightList = new List <MeshData.VertexWeight>();

            for (int i = 0; i < lposList.Count; i++)
            {
                // 1ウエイトで追加
                uint vinfo = DataUtility.Pack4_28(1, i);
                vertexInfoList.Add(vinfo);
                var vw = new MeshData.VertexWeight();
                vw.parentIndex = i;
                vw.weight      = 1.0f;
                vw.localPos    = lposList[i];
                vw.localNor    = lnorList[i];
                vw.localTan    = ltanList[i];
            }
            mdata.vertexInfoList   = vertexInfoList.ToArray();
            mdata.vertexWeightList = vertexWeightList.ToArray();
            mdata.vertexCount      = lposList.Count;

            // ライン作成
            HashSet <uint> lineSet = new HashSet <uint>();

            // 構造ライン
            for (int i = 0; i < transformList.Count; i++)
            {
                var t  = transformList[i];
                var pt = t.parent;
                if (pt != null && transformList.Contains(pt))
                {
                    int  v0   = i;
                    int  v1   = transformList.IndexOf(pt);
                    uint pair = DataUtility.PackPair(v0, v1);
                    lineSet.Add(pair);
                }
            }

            // 近接ライン接続
            //if (scr.ClothTarget.LineConnection)
            //{
            //    CreateNearLine(scr, lineSet, wposList, mdata);
            //}

            // ライン格納
            List <int> lineList = new List <int>();

            foreach (var pair in lineSet)
            {
                int v0, v1;
                DataUtility.UnpackPair(pair, out v0, out v1);
                lineList.Add(v0);
                lineList.Add(v1);
            }
            mdata.lineList  = lineList.ToArray();
            mdata.lineCount = lineList.Count / 2;

            serializedObject.FindProperty("meshData").objectReferenceValue = mdata;
            serializedObject.ApplyModifiedProperties();

            // 使用トランスフォームシリアライズ
            var property    = serializedObject.FindProperty("useTransformList");
            var propertyPos = serializedObject.FindProperty("useTransformPositionList");
            var propertyRot = serializedObject.FindProperty("useTransformRotationList");
            var propertyScl = serializedObject.FindProperty("useTransformScaleList");

            property.arraySize    = transformList.Count;
            propertyPos.arraySize = transformList.Count;
            propertyRot.arraySize = transformList.Count;
            propertyScl.arraySize = transformList.Count;
            for (int i = 0; i < transformList.Count; i++)
            {
                property.GetArrayElementAtIndex(i).objectReferenceValue = transformList[i];
                propertyPos.GetArrayElementAtIndex(i).vector3Value      = transformList[i].localPosition;
                propertyRot.GetArrayElementAtIndex(i).quaternionValue   = transformList[i].localRotation;
                propertyScl.GetArrayElementAtIndex(i).vector3Value      = transformList[i].localScale;
            }
            serializedObject.ApplyModifiedProperties();

            // データ検証とハッシュ
            mdata.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(mdata);
        }
        /// <summary>
        /// メッシュデータ作成
        /// </summary>
        void CreateMeshData(MagicaBoneCloth scr)
        {
            // 共有データオブジェクト作成
            string   dataname = "BoneClothMeshData_" + scr.name;
            MeshData mdata    = ShareDataObject.CreateShareData <MeshData>(dataname);

            // トランスフォームリスト作成
            var transformList = scr.GetTransformList();

            if (transformList.Count == 0)
            {
                return;
            }

            // 頂点作成
            int            vcnt     = transformList.Count;
            List <Vector3> wposList = new List <Vector3>();
            List <Vector3> wnorList = new List <Vector3>();
            List <Vector4> wtanList = new List <Vector4>();
            List <Vector3> lposList = new List <Vector3>();
            List <Vector3> lnorList = new List <Vector3>();
            List <Vector3> ltanList = new List <Vector3>();
            Transform      myt      = scr.transform;

            for (int i = 0; i < transformList.Count; i++)
            {
                var t = transformList[i];

                // 頂点追加
                var pos  = t.position;
                var lpos = myt.InverseTransformDirection(pos - myt.position);
                var lnor = myt.InverseTransformDirection(t.forward);
                var ltan = myt.InverseTransformDirection(t.up);
                wposList.Add(pos);
                wnorList.Add(t.forward);
                wtanList.Add(t.up);
                lposList.Add(lpos);
                lnorList.Add(lnor);
                ltanList.Add(ltan);
            }
            var vertexInfoList   = new List <uint>();
            var vertexWeightList = new List <MeshData.VertexWeight>();

            for (int i = 0; i < lposList.Count; i++)
            {
                // 1ウエイトで追加
                uint vinfo = DataUtility.Pack4_28(1, i);
                vertexInfoList.Add(vinfo);
                var vw = new MeshData.VertexWeight();
                vw.parentIndex = i;
                vw.weight      = 1.0f;
                vw.localPos    = lposList[i];
                vw.localNor    = lnorList[i];
                vw.localTan    = ltanList[i];
            }
            mdata.vertexInfoList   = vertexInfoList.ToArray();
            mdata.vertexWeightList = vertexWeightList.ToArray();
            mdata.vertexCount      = lposList.Count;

            // デプスリスト作成
            var        sel       = scr.ClothSelection.GetSelectionData(null, null);
            List <int> depthList = new List <int>();

            for (int i = 0; i < transformList.Count; i++)
            {
                int depth = 0;
                var t     = transformList[i];

                while (t && transformList.Contains(t))
                {
                    int index = transformList.IndexOf(t);
                    if (sel[index] != SelectionData.Move)
                    {
                        break;
                    }

                    depth++;
                    t = t.parent;
                }

                depthList.Add(depth);
                //Debug.Log($"[{transformList[i].name}] depth:{depth}");
            }


            // 構造ライン
            HashSet <uint> lineSet = new HashSet <uint>();

            for (int i = 0; i < transformList.Count; i++)
            {
                var t  = transformList[i];
                var pt = t.parent;
                if (pt != null && transformList.Contains(pt))
                {
                    int  v0   = i;
                    int  v1   = transformList.IndexOf(pt);
                    uint pair = DataUtility.PackPair(v0, v1);
                    lineSet.Add(pair);
                }
            }

            // グリッドによるトライアングル
            List <int> triangleList = new List <int>();

            if (scr.ClothTarget.Connection == BoneClothTarget.ConnectionMode.Mesh)
            {
                HashSet <uint> triangleLineSet = new HashSet <uint>(lineSet);

                // 周りのボーンを調べ一定範囲内のボーンを接続する
                for (int i = 0; i < transformList.Count; i++)
                {
                    //if (sel[i] != SelectionData.Move)
                    //    continue;

                    var   t       = transformList[i];
                    int   depth   = depthList[i];
                    float mindist = 10000.0f;

                    List <int>   linkList = new List <int>();
                    List <float> distList = new List <float>();

                    for (int j = 0; j < transformList.Count; j++)
                    {
                        if (i == j || depthList[j] != depth)
                        {
                            continue;
                        }

                        linkList.Add(j);
                        var dist = Vector3.Distance(t.position, transformList[j].position);
                        distList.Add(dist);
                        mindist = Mathf.Min(mindist, dist);
                    }

                    // 最短距離より少し長めの範囲の頂点以外は削除する
                    HashSet <int> removeSet = new HashSet <int>();
                    mindist *= 1.5f;
                    for (int j = 0; j < linkList.Count; j++)
                    {
                        if (distList[j] > mindist)
                        {
                            removeSet.Add(j);
                        }
                    }

#if true
                    // 方向が一定以内ならば最も近い接続以外を削除する
                    for (int j = 0; j < linkList.Count - 1; j++)
                    {
                        for (int k = j + 1; k < linkList.Count; k++)
                        {
                            if (removeSet.Contains(j))
                            {
                                continue;
                            }
                            if (removeSet.Contains(k))
                            {
                                continue;
                            }

                            int index0 = linkList[j];
                            int index1 = linkList[k];

                            var ang = Vector3.Angle(transformList[index0].position - t.position, transformList[index1].position - t.position);
                            if (ang <= 45.0f)
                            {
                                removeSet.Add(distList[j] < distList[k] ? k : j);
                            }
                        }
                    }
#endif
                    // 登録
                    for (int j = 0; j < linkList.Count; j++)
                    {
                        if (removeSet.Contains(j))
                        {
                            continue;
                        }
                        // 接続する
                        uint pair = DataUtility.PackPair(i, linkList[j]);
                        triangleLineSet.Add(pair);
                    }
                }

                // 一旦各頂点の接続頂点リストを取得
                var vlink = MeshUtility.GetVertexLinkList(mdata.vertexCount, triangleLineSet);

                // トライアングル情報作成
                HashSet <ulong> registTriangleSet = new HashSet <ulong>();
                for (int i = 0; i < vlink.Count; i++)
                {
                    var linkset = vlink[i];
                    var t       = transformList[i];
                    var move    = sel[i] == SelectionData.Move;

                    foreach (var j in linkset)
                    {
                        var t2    = transformList[j];
                        var v     = (t2.position - t.position).normalized;
                        var move2 = sel[j] == SelectionData.Move;

                        foreach (var k in linkset)
                        {
                            if (j == k)
                            {
                                continue;
                            }

                            // j-kのエッジがtriangleLineSetに含まれていない場合は無効
                            //if (triangleLineSet.Contains(DataUtility.PackPair(j, k)) == false)
                            //    continue;

                            var t3    = transformList[k];
                            var v2    = (t3.position - t.position).normalized;
                            var move3 = sel[k] == SelectionData.Move;

                            // すべて固定頂点なら無効
                            if (move == false && move2 == false && move3 == false)
                            {
                                continue;
                            }

                            // 面積が0のトライアングルは除外する
                            var n    = Vector3.Cross(t2.position - t.position, t3.position - t.position);
                            var clen = n.magnitude;
                            if (clen < 1e-06f)
                            {
                                //Debug.Log($"clen == 0 ({i},{j},{k})");
                                continue;
                            }

                            var ang = Vector3.Angle(v, v2); // deg
                            if (ang <= 100)
                            {
                                // i - j - k をトライアングルとして登録する
                                var thash = DataUtility.PackTriple(i, j, k);
                                if (registTriangleSet.Contains(thash) == false)
                                {
                                    triangleList.Add(i);
                                    triangleList.Add(j);
                                    triangleList.Add(k);
                                    registTriangleSet.Add(thash);
                                }
                            }
                        }
                    }
                }
            }

            // トライアングルの法線を揃える
            HashSet <ulong> triangleSet = new HashSet <ulong>();
            if (triangleList.Count > 0)
            {
                // リダクションメッシュを作成する
                // ただ現在は面法線を揃える用途にしか使用しない
                var reductionMesh = new MagicaReductionMesh.ReductionMesh();
                reductionMesh.WeightMode = MagicaReductionMesh.ReductionMesh.ReductionWeightMode.Distance;
                reductionMesh.MeshData.MaxWeightCount   = 1;
                reductionMesh.MeshData.WeightPow        = 1;
                reductionMesh.MeshData.SameSurfaceAngle = scr.ClothTarget.SameSurfaceAngle; // 80?
                reductionMesh.AddMesh(myt, wposList, wnorList, wtanList, null, triangleList);

                // リダクション(面法線を整えるだけでリダクションは行わない)
                reductionMesh.Reduction(0.0f, 0.0f, 0.0f, false);

                // 最終メッシュデータ取得
                var final = reductionMesh.GetFinalData(myt);
                Debug.Assert(vcnt == final.VertexCount);

                // トライアングルデータ取得
                triangleList = final.triangles;
            }

            // 近接ライン接続
            //if (scr.ClothTarget.LineConnection)
            //{
            //    CreateNearLine(scr, lineSet, wposList, mdata);
            //}

#if false
            // トライアングル接続されているエッジはラインセットから削除する
            for (int i = 0; i < triangleList.Count / 3; i++)
            {
                int v0, v1, v2;
                int index = i * 3;
                v0 = triangleList[index];
                v1 = triangleList[index + 1];
                v2 = triangleList[index + 2];

                var pair0 = DataUtility.PackPair(v0, v1);
                var pair1 = DataUtility.PackPair(v1, v2);
                var pair2 = DataUtility.PackPair(v2, v0);

                lineSet.Remove(pair0);
                lineSet.Remove(pair1);
                lineSet.Remove(pair2);
            }
#endif

            // todo:test
            //lineSet.Clear();

            // ライン格納
            if (lineSet.Count > 0)
            {
                List <int> lineList = new List <int>();
                foreach (var pair in lineSet)
                {
                    int v0, v1;
                    DataUtility.UnpackPair(pair, out v0, out v1);
                    lineList.Add(v0);
                    lineList.Add(v1);
                }
                mdata.lineList  = lineList.ToArray();
                mdata.lineCount = lineList.Count / 2;
            }

            // トライアングル格納
            //if (triangleSet.Count > 0)
            //{
            //    List<int> triangleList = new List<int>();
            //    foreach (var tpack in triangleSet)
            //    {
            //        int v0, v1, v2;
            //        DataUtility.UnpackTriple(tpack, out v0, out v1, out v2);
            //        triangleList.Add(v0);
            //        triangleList.Add(v1);
            //        triangleList.Add(v2);
            //    }
            //    mdata.triangleCount = triangleSet.Count;
            //    mdata.triangleList = triangleList.ToArray();
            //}
            if (triangleList.Count > 0)
            {
                mdata.triangleCount = triangleList.Count / 3;
                mdata.triangleList  = triangleList.ToArray();
            }

            serializedObject.FindProperty("meshData").objectReferenceValue = mdata;
            serializedObject.ApplyModifiedProperties();

            // 使用トランスフォームシリアライズ
            var property    = serializedObject.FindProperty("useTransformList");
            var propertyPos = serializedObject.FindProperty("useTransformPositionList");
            var propertyRot = serializedObject.FindProperty("useTransformRotationList");
            var propertyScl = serializedObject.FindProperty("useTransformScaleList");
            property.arraySize    = transformList.Count;
            propertyPos.arraySize = transformList.Count;
            propertyRot.arraySize = transformList.Count;
            propertyScl.arraySize = transformList.Count;
            for (int i = 0; i < transformList.Count; i++)
            {
                property.GetArrayElementAtIndex(i).objectReferenceValue = transformList[i];
                propertyPos.GetArrayElementAtIndex(i).vector3Value      = transformList[i].localPosition;
                propertyRot.GetArrayElementAtIndex(i).quaternionValue   = transformList[i].localRotation;
                propertyScl.GetArrayElementAtIndex(i).vector3Value      = transformList[i].localScale;
            }
            serializedObject.ApplyModifiedProperties();

            // データ検証とハッシュ
            mdata.CreateVerifyData();
            serializedObject.ApplyModifiedProperties();

            EditorUtility.SetDirty(mdata);
        }