public MeshCutData(CutterMesh victimMesh, CutterPlane blade) { VictimMesh = victimMesh; LeftSide.SetTargetMesh(victimMesh); RightSide.SetTargetMesh(victimMesh); Blade = blade; }
/// <summary> /// Perform cutting. /// </summary> /// <param name="target">Cut target object.</param> /// <param name="position">Cut plane position.</param> /// <param name="normal">Cut plane normal.</param> /// <param name="callback">Callback for cutting process. (optional)</param> /// <param name="userdata">User data. (optional)</param> public void Cut(CutterTarget target, Vector3 position, Vector3 normal, CutterCallback callback = null, object userdata = null) { _normal = normal; // Create convert matrix for position. Matrix4x4 worldToLocMat = target.MeshTransform.worldToLocalMatrix; if (target.NeedsConvertLocal) { Matrix4x4 scaleMat = Matrix4x4.Scale(target.MeshTransform.lossyScale); worldToLocMat = scaleMat * worldToLocMat; } Vector4 pos = new Vector4(position.x, position.y, position.z, 1f); Vector3 localPos = worldToLocMat * pos; // Create convert matrix for normal. Vector3 nor = new Vector4(normal.x, normal.y, normal.z, 1f); Vector4 c0 = worldToLocMat.GetColumn(0); Vector4 c1 = worldToLocMat.GetColumn(1); Vector4 c2 = worldToLocMat.GetColumn(2); Vector4 c3 = new Vector4(0, 0, 0, 1f); Matrix4x4 worldToLocNormMat = new Matrix4x4(); worldToLocNormMat.SetColumn(0, c0); worldToLocNormMat.SetColumn(1, c1); worldToLocNormMat.SetColumn(2, c2); worldToLocNormMat.SetColumn(3, c3); worldToLocNormMat = worldToLocNormMat.inverse.transpose; Vector3 localNor = worldToLocNormMat * nor; localNor.Normalize(); CutterPlane blade = new CutterPlane(localPos, localNor); CutterInfo info = new CutterInfo { CutterTarget = target, CutterObject = new CutterObject(target, _needAnimation), CutterPlane = blade, CutterCallback = callback, UserData = userdata, }; _worker.Cut(info); }
/// <summary> /// Cut the specified victim, blade_plane and capMaterial. /// (指定された「victim」をカットする。ブレード(平面)とマテリアルから切断を実行する) /// </summary> /// <param name="victim">Victim.</param> /// <param name="blade_plane">Blade plane.</param> public CutterMesh[] Cut(CutterObject victim, CutterPlane blade) { // 対象のメッシュを取得 MeshCutData data = new MeshCutData(victim.CutterMesh, blade); // ここでの「3」はトライアングル bool[] sides = new bool[3]; int[] indices; int p1, p2, p3; // go throught the submeshes // サブメッシュの数だけループ for (int sub = 0; sub < victim.SubMeshCount; sub++) { // サブメッシュのインデックス数を取得 indices = victim.CutterMesh.GetIndices(sub); // List<List<int>>型のリスト。サブメッシュ一つ分のインデックスリスト data.LeftSide.SubIndices.Add(new List <int>()); // 左 data.RightSide.SubIndices.Add(new List <int>()); // 右 // サブメッシュのインデックス数分ループ for (int i = 0; i < indices.Length; i += 3) { // p1 - p3のインデックスを取得。つまりトライアングル p1 = indices[i + 0]; p2 = indices[i + 1]; p3 = indices[i + 2]; // それぞれ評価中のメッシュの頂点が、冒頭で定義された平面の左右どちらにあるかを評価。 // `GetSide` メソッドによりboolを得る。 sides[0] = blade.GetSide(data.VictimMesh.Vertices[p1]); sides[1] = blade.GetSide(data.VictimMesh.Vertices[p2]); sides[2] = blade.GetSide(data.VictimMesh.Vertices[p3]); // whole triangle // 頂点0と頂点1および頂点2がどちらも同じ側にある場合はカットしない if (sides[0] == sides[1] && sides[0] == sides[2]) { if (sides[0]) { // left side // GetSideメソッドでポジティブ(true)の場合は左側にあり data.LeftSide.AddTriangle(p1, p2, p3, sub); } else { data.RightSide.AddTriangle(p1, p2, p3, sub); } } else { // cut the triangle // そうではなく、どちらかの点が平面の反対側にある場合はカットを実行する CutFace(sub, sides, p1, p2, p3, data); } } } // Check separating verticies. if (data.LeftSide.Vertices.Count == 0 || data.RightSide.Vertices.Count == 0) { Debug.Log("No need cutting, because all verticies are in one side."); return(null); } data.LeftSide.SubIndices.Add(new List <int>()); data.RightSide.SubIndices.Add(new List <int>()); // カット開始 Capping(data); // 左側のメッシュを生成 // MeshCutSideクラスのメンバから各値をコピー CutterMesh leftHalfMesh = new CutterMesh { Vertices = data.LeftSide.Vertices.ToArray(), Triangles = data.LeftSide.Triangles.ToArray(), Normals = data.LeftSide.Normals.ToArray(), UVs = data.LeftSide.UVs.ToArray(), BoneWeights = data.LeftSide.BoneWeights.ToArray(), }; int[][] leftSubIndices = new int[data.LeftSide.SubIndices.Count][]; for (int i = 0; i < data.LeftSide.SubIndices.Count; i++) { leftSubIndices[i] = data.LeftSide.SubIndices[i].ToArray(); } leftHalfMesh.SetIndices(leftSubIndices); // 右側のメッシュも同様に生成 CutterMesh rightHalfMesh = new CutterMesh { Vertices = data.RightSide.Vertices.ToArray(), Triangles = data.RightSide.Triangles.ToArray(), Normals = data.RightSide.Normals.ToArray(), UVs = data.RightSide.UVs.ToArray(), BoneWeights = data.RightSide.BoneWeights.ToArray(), }; int[][] rightSubIndices = new int[data.RightSide.SubIndices.Count][]; for (int i = 0; i < data.RightSide.SubIndices.Count; i++) { rightSubIndices[i] = data.RightSide.SubIndices[i].ToArray(); } rightHalfMesh.SetIndices(rightSubIndices); Debug.Log("cutter finish"); // 左右のGameObjectの配列を返す return(new CutterMesh[] { leftHalfMesh, rightHalfMesh }); }