/// <summary>
 /// コンストラクタ
 /// </summary>
 /// <param name="target">カットターゲット</param>
 public CutterObject(CutterTarget target, bool needAnimation = false)
 {
     _target = target;
     _name   = target.Name;
     GetMeshInfo(target.GameObject, out _mesh, out _bindposes);
     CutterMesh = new CutterMesh(_mesh);
 }
Exemple #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);
        }
Exemple #3
0
        /// <summary>
        /// カットされたメッシュ情報を元にオブジェクトを生成する
        /// </summary>
        private void CreateCuttedObjects(CutterInfo info)
        {
            CutterTarget target = info.CutterTarget;

            if (target == null)
            {
                return;
            }

            // 設定されているマテリアル配列を取得
            Material[] mats = GetMaterials(target.GameObject);

            // カット面分増やしたマテリアル配列を準備
            Material[] newMats = new Material[mats.Length + 1];

            // 既存のものを新しい配列にコピー
            mats.CopyTo(newMats, 0);

            // 新しいマテリアル配列の最後に、カット面用マテリアルを追加
            newMats[mats.Length] = (target.CutMaterial != null) ? target.CutMaterial : _cutDefaultMaterial;

            // 生成したマテリアルリストを再設定
            mats = newMats;

            CutterObject cutterObject = info.CutterObject;

            CutterMesh[] cuttedMeshes = info.CutterMeshes;
            GameObject[] cuttedObject = new GameObject[cuttedMeshes.Length];

            // 生成されたメッシュ分、オブジェクトを生成する
            for (int i = 0; i < cuttedMeshes.Length; i++)
            {
                #region ### Create new object ###
                GameObject newObj = new GameObject("[Cutterd]" + target.Name + i);
                newObj.transform.position   = target.transform.position;
                newObj.transform.rotation   = target.transform.rotation;
                newObj.transform.localScale = target.transform.localScale;
                #endregion ### Create new object ###

                #region ### Create new mesh ###
                Mesh mesh = new Mesh();
                mesh.name         = "Split Mesh";
                mesh.vertices     = cuttedMeshes[i].Vertices;
                mesh.triangles    = cuttedMeshes[i].Triangles;
                mesh.normals      = cuttedMeshes[i].Normals;
                mesh.uv           = cuttedMeshes[i].UVs;
                mesh.subMeshCount = cuttedMeshes[i].SubMeshCount;
                for (int j = 0; j < cuttedMeshes[i].SubMeshCount; j++)
                {
                    mesh.SetIndices(cuttedMeshes[i].GetIndices(j), MeshTopology.Triangles, j);
                }
                #endregion ### Create new mesh ###

                GameObject obj;

                // アニメーションが必要な場合はボーンのセットアップを行う
                if (_needAnimation)
                {
                    SkinnedMeshRenderer oriRenderer = target.GameObject.GetComponent <SkinnedMeshRenderer>();
                    Transform           newRootBone = Instantiate(oriRenderer.rootBone.gameObject).transform;
                    newRootBone.name = newRootBone.name.Replace("(Clone)", "");

                    Transform[] newBones = new Transform[oriRenderer.bones.Length];
                    for (int j = 0; j < oriRenderer.bones.Length; j++)
                    {
                        Transform bone    = oriRenderer.bones[j];
                        Transform newBone = SearchBone(bone.name, newRootBone);
                        newBones[j] = newBone;
                    }

                    Animator          oriAnim   = target.GetComponent <Animator>();
                    AnimatorStateInfo stateInfo = oriAnim.GetCurrentAnimatorStateInfo(0);

                    newRootBone.SetParent(newObj.transform);
                    Animator anim = newObj.AddComponent <Animator>();
                    anim.runtimeAnimatorController = oriAnim.runtimeAnimatorController;
                    anim.avatar = target.GetComponent <Animator>().avatar;
                    anim.Play(stateInfo.fullPathHash, 0, stateInfo.normalizedTime);

                    mesh.bindposes   = cutterObject.Bindposes;
                    mesh.boneWeights = cuttedMeshes[i].BoneWeights;

                    obj = new GameObject("Split Object", new[] {
                        typeof(SkinnedMeshRenderer)
                    });
                    obj.transform.position = target.MeshTransform.position;
                    obj.transform.rotation = target.MeshTransform.rotation;

                    SkinnedMeshRenderer renderer = obj.GetComponent <SkinnedMeshRenderer>();
                    renderer.sharedMesh = mesh;
                    renderer.materials  = mats;
                    renderer.bones      = newBones;
                    renderer.rootBone   = newRootBone;
                }
                else
                {
                    obj = new GameObject("Split Object " + i, new[] {
                        typeof(MeshFilter),
                        typeof(MeshRenderer),
                        typeof(Rigidbody),
                        typeof(MeshCollider),
                        typeof(CutterTarget),
                    });
                    obj.transform.position   = target.MeshTransform.position;
                    obj.transform.rotation   = target.MeshTransform.rotation;
                    obj.transform.localScale = target.MeshTransform.lossyScale;
                    obj.GetComponent <MeshCollider>().sharedMesh  = mesh;
                    obj.GetComponent <MeshCollider>().convex      = true;
                    obj.GetComponent <MeshCollider>().material    = target.GetComponent <Collider>().material;
                    obj.GetComponent <MeshFilter>().mesh          = mesh;
                    obj.GetComponent <MeshRenderer>().materials   = mats;
                    obj.GetComponent <CutterTarget>().CutMaterial = target.CutMaterial;
                    obj.GetComponent <Rigidbody>().constraints    = target.Rigidbody.constraints;
                }

                cuttedObject[i] = obj;
                obj.transform.SetParent(newObj.transform);

                if (cutterObject.NeedsScaleAdjust)
                {
                    obj.transform.localScale = target.transform != target.MeshTransform ? target.MeshTransform.localScale : Vector3.one;
                }
                cutAnim.Anim(target, obj.GetComponent <CutterTarget>());
            }

            // Notify end of cutting.
            target.Cutted(cuttedObject);

            if (_autoDestroyTarget)
            {
                // Destroy target object.
                target.transform.localScale = Vector3.zero;
                target.gameObject.SetActive(false);
                //Destroy(target.gameObject);
            }

            if (OnCutted != null)
            {
                OnCutted.Invoke(cuttedObject, info.CutterPlane);
            }

            if (info.CutterCallback != null)
            {
                info.CutterCallback.Invoke(true, cuttedObject, info.CutterPlane, info.UserData);
            }
        }