/// <summary> /// バッファ内の最も近接にあるペアを返す /// </summary> /// <param name="id1"></param> /// <param name="id2"></param> /// <returns></returns> public bool GetNearPointPair(out int id1, out int id2) { int index = -1; int nearIndex = -1; float nearDist = 100000.0f; foreach (var keyval in nearDict) { int id = keyval.Key; int nearId = keyval.Value; if (nearId == -1) { continue; } // ロックペアならスルー uint pair = DataUtility.PackPair(id, nearId); if (lockPairSet.Contains(pair)) { continue; } float dist = distDict[id]; if (dist > radius) { continue; } if (dist < nearDist) { index = id; nearIndex = nearId; nearDist = dist; } } if (index >= 0 && nearIndex >= 0) { id1 = index; id2 = nearIndex; return(true); } else { id1 = -1; id2 = -1; return(false); } }
// エッジに隣接するトライアングルを追加する static void AddTriangleEdge(int v0, int v1, int tindex, Dictionary <uint, List <int> > triangleEdgeDict) { // 頂点v0/v1をパックする uint pack = DataUtility.PackPair(v0, v1); List <int> tlist; if (triangleEdgeDict.ContainsKey(pack)) { // 既存 tlist = triangleEdgeDict[pack]; } else { // 新規 tlist = new List <int>(); triangleEdgeDict.Add(pack, tlist); } // 追加 tlist.Add(tindex); }
/// <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); }
public void AddLockPair(int id1, int id2) { uint pair = DataUtility.PackPair(id1, id2); lockPairSet.Add(pair); }
/// <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); }