private bool ChopModeGeometry(ChopRequest cr)
        {
            if ((Data.ChopGeometry == null) || !Data.ChopGeometry.HasMesh() || Data.NDesiredPieces <= 0)
            {
                return(false);
            }

            Matrix4x4 m_Local_to_World = Data.ChopGeometry.transform.localToWorldMatrix;

            UnityEngine.Mesh un_chopGeometry = Data.ChopGeometry.GetMesh();

            UnityEngine.Mesh transformedMesh;
            CRGeometryUtils.CreateMeshTransformed(un_chopGeometry, m_Local_to_World, out transformedMesh);

            CaronteSharp.MeshSimple car_chopGeometry = new CaronteSharp.MeshSimple();
            car_chopGeometry.Set(transformedMesh);
            Object.DestroyImmediate(transformedMesh);

            cr.nDesiredPieces_    = (uint)Data.NDesiredPieces;
            cr.meshFocusGeometry_ = car_chopGeometry;
            cr.focusMode_         = (PSBG_FOCUS_MODE)Data.FocusMode;
            cr.gridResolution_    = (uint)Data.GridResolution;
            cr.densityRate_       = Data.DensityRate;
            cr.transitionLength_  = Data.TransitionLength;
            cr.doExtrusionEffect_ = Data.DoExtrusionEffect;
            cr.doCoordinate_      = Data.DoCoordinate;

            return(true);
        }
        private bool ChopModeUniform(ChopRequest cr)
        {
            if (Data.NDesiredPieces == 0)
            {
                return(false);
            }
            cr.nDesiredPieces_    = (uint)Data.NDesiredPieces;
            cr.doExtrusionEffect_ = Data.DoExtrusionEffect;
            cr.doCoordinate_      = Data.DoCoordinate;

            return(true);
        }
        private bool ChopModeRadial(ChopRequest cr)
        {
            if (Data.ReferenceSystem == null)
            {
                Debug.Log("Radial mode requires specifying a reference system.");
                return(false);
            }

            Transform tr = Data.ReferenceSystem.transform;
            Matrix4x4 m_LOCAL_to_WORLD = tr.localToWorldMatrix;

            cr.focusSystem_center_ = Data.ReferenceSystem.position;

            switch (Data.ReferenceSystemAxis)
            {
            case CNFracture.AxisDir.x:
                cr.focusSystem_axisDir_ = m_LOCAL_to_WORLD.MultiplyVector(Data.ReferenceSystem.right);
                break;

            case CNFracture.AxisDir.y:
                cr.focusSystem_axisDir_ = m_LOCAL_to_WORLD.MultiplyVector(Data.ReferenceSystem.up);
                break;

            case CNFracture.AxisDir.z:
                cr.focusSystem_axisDir_ = m_LOCAL_to_WORLD.MultiplyVector(Data.ReferenceSystem.forward);
                break;
            }

            cr.rays_number_   = (uint)Data.RaysNumber;
            cr.rays_rateRand_ = Data.RaysRateRand;

            cr.rings_numberInsideAnnulus_ = (uint)Data.RingsNumberInsideAnnulus;
            cr.rings_intRadius_           = Data.RingsIntRadius;
            cr.rings_extRadius_           = Data.RingsExtRadius;
            cr.rings_intTransitionLength_ = Data.RingsIntTransitionLength;
            cr.rings_extTransitionLength_ = Data.RingsExtTransitionLength;
            cr.rings_intTransitionDecay_  = Data.RingsIntTransitionDecay;
            cr.rings_extTransitionDecay_  = Data.RingsExtTransitionDecay;;

            cr.rings_rateRand_ = Data.RingsRateRand;
            cr.doCentralPiece_ = Data.DoCentralPiece;

            cr.noiseRate_    = Data.NoiseRate;
            cr.twistRate_    = Data.TwistRate;
            cr.doCoordinate_ = Data.DoCoordinate;

            return(true);
        }
        public void Chop()
        {
            GameObject[] goToChop   = FieldController.GetUnityGameObjects();
            int          numObjects = goToChop.Length;

            string errorMessage = string.Empty;

            if (numObjects == 0)
            {
                errorMessage = "Objects field must contain at least one object with geometry";
            }

            if (Data.CropGeometry != null && !Data.CropGeometry.HasMesh())
            {
                errorMessage = "Crop geometry GameObject must contain a mesh";
            }

            if (Data.ChopMode == CNFracture.CHOP_MODE.VORONOI_BY_GEOMETRY)
            {
                if (Data.ChopGeometry == null)
                {
                    errorMessage = "Specifying a steering geometry is mandatory";
                }
                else if (!Data.ChopGeometry.HasMesh())
                {
                    errorMessage = "Steering geometry GameObject must contain a mesh";
                }
            }

            if (Data.ChopMode == CNFracture.CHOP_MODE.VORONOI_RADIAL)
            {
                if (Data.ReferenceSystem == null)
                {
                    errorMessage = "Specifying the reference system is mandatory";
                }
            }

            if (errorMessage != string.Empty)
            {
                EditorUtility.DisplayDialog("CaronteFX", errorMessage, "Ok");
                return;
            }

            Undo.RecordObject(Data, "Chop - " + Data.Name);

            List <GameObject>  listParentGO           = new List <GameObject>();
            List <Mesh>        listParentMesh_un      = new List <Mesh>();
            List <MeshComplex> listParentMesh_car     = new List <MeshComplex>();
            List <Matrix4x4>   listMatrixModelToWorld = new List <Matrix4x4>();

            for (int i = 0; i < numObjects; i++)
            {
                GameObject go      = goToChop[i];
                Mesh       un_mesh = go.GetMesh();

                if (un_mesh != null)
                {
                    MeshComplex mc = new MeshComplex();
                    mc.Set(un_mesh);

                    listParentMesh_car.Add(mc);
                    listParentMesh_un.Add(un_mesh);
                    listParentGO.Add(go);
                    listMatrixModelToWorld.Add(go.transform.localToWorldMatrix);
                }
            }

            Bounds globalBounds = CREditorUtils.GetGlobalBoundsWorld(listParentGO);

            ChopRequest cr = new ChopRequest();

            cr.doKeepUVCoords_          = true;
            cr.doKeepVertexNormals_     = true;
            cr.doParentIndexTriangInfo_ = true;
            cr.arrMeshToChop_           = listParentMesh_car.ToArray();
            cr.arrMatrixModelToWorld_   = listMatrixModelToWorld.ToArray();

            cr.doGlobalPattern_ = Data.DoGlobalPattern;
            cr.seed_            = (uint)Data.Seed;

            bool chopModeUniform  = false;
            bool chopModeGeometry = false;
            bool chopModeRadial   = false;

            cr.pProgressFunction_ = null;

            switch (Data.ChopMode)
            {
            case CNFracture.CHOP_MODE.VORONOI_UNIFORM:
                cr.chopMode_    = CaronteSharp.CP_CHOP_MODE.CP_CHOP_MODE_VORONOI_UNIFORM;
                chopModeUniform = ChopModeUniform(cr);
                break;

            case CNFracture.CHOP_MODE.VORONOI_BY_GEOMETRY:
                cr.chopMode_     = CaronteSharp.CP_CHOP_MODE.CP_CHOP_MODE_VORONOI_BY_GEOMETRY;
                chopModeGeometry = ChopModeGeometry(cr);
                break;

            case CNFracture.CHOP_MODE.VORONOI_RADIAL:
                cr.chopMode_   = CaronteSharp.CP_CHOP_MODE.CP_CHOP_MODE_VORONOI_RADIAL;
                chopModeRadial = ChopModeRadial(cr);
                break;
            }

            if (!chopModeUniform && !chopModeGeometry && !chopModeRadial)
            {
                return;
            }

            WeldRequest wr = GetWeldRequest();

            CaronteSharp.MeshComplex[]    arrMeshPieceCaronte;
            CaronteSharp.MeshParentInfo[] arrMeshParentInfo;
            Vector3[]  arrMeshPosition;
            ArrayIndex arrInsideOutsideIdx;

            EditorUtility.DisplayProgressBar(Data.Name, "Chopping...", 1.0f);
            CaronteSharp.Tools.FractureMeshesV2(cr, wr, out arrMeshPieceCaronte, out arrMeshParentInfo, out arrMeshPosition, out arrInsideOutsideIdx);


            bool thereIsOutput = arrMeshPieceCaronte.Length > 0;

            if (cnManager.IsFreeVersion() && !thereIsOutput)
            {
                EditorUtility.DisplayDialog("CaronteFX - Free version", "CaronteFX Free version can only fracture the meshes included in the example scenes and the unity primitives (cube, plane, sphere, etc.)", "Ok");
            }

            if (thereIsOutput)
            {
                List <GameObject> listChoppedParentGO;
                CreateListChoppedParentGO(listParentGO, out listChoppedParentGO);

                EditorUtility.DisplayProgressBar(Data.Name, "Post processing...", 1.0f);
                UnityEngine.Mesh[]  arrMeshPieceUnity;
                Tuple2 <int, int>[] arrSubmeshRange;
                int[] arrMeshComplexIdx;

                CreateMeshPiecesUnity(listChoppedParentGO, arrMeshPieceCaronte, arrMeshParentInfo, arrMeshPosition,
                                      out arrMeshPieceUnity, out arrSubmeshRange, out arrMeshComplexIdx);

                Transform oldParent = DestroyOldObjects();

                Undo.RecordObject(Data, "Chop - " + Data.Name);
                CreateNewObjects(globalBounds.center, listParentGO, listChoppedParentGO, arrMeshParentInfo,
                                 arrMeshPieceUnity, arrSubmeshRange, arrMeshComplexIdx, arrMeshPosition, arrInsideOutsideIdx.arrIdx_);


                if (oldParent != null)
                {
                    Data.GameObjectChoppedRoot.transform.parent = oldParent;
                }

                SeparatePieces();

                CalculateStatistics();

                EditorUtility.ClearProgressBar();

                Undo.SetCurrentGroupName("Chop - " + Data.Name);
                Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
                EditorUtility.SetDirty(Data);
            }
        }