Пример #1
0
            public MeshCutData(CutterMesh victimMesh, CutterPlane blade)
            {
                VictimMesh = victimMesh;
                LeftSide.SetTargetMesh(victimMesh);
                RightSide.SetTargetMesh(victimMesh);

                Blade = blade;
            }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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 });
        }