示例#1
0
 // Set Shatter Runtime Mode properties
 static void SetShatterRuntimeMode(RFShatter shatter)
 {
     shatter.EditorMode(false);
     shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_shatter, true);
     shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_cap, true);
     shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_weld, true);
 }
示例#2
0
        // Copy from
        public void CopyFrom(RFDemolitionMesh demolition)
        {
            amount      = demolition.amount;
            variation   = demolition.variation;
            depthFade   = demolition.depthFade;
            seed        = demolition.seed;
            contactBias = demolition.contactBias;
            useShatter  = false;

            // TODO input mesh for fragments ?? turn off for now
            meshInput = demolition.meshInput;
            meshInput = MeshInputType.AtDemolition;

            properties.CopyFrom(demolition.properties);
            runtimeCaching = new RFRuntimeCaching();

            Reset();

            shatterMode        = 1;
            innerSubId         = 0;
            compressPrefab     = true;
            cacheRotationStart = Quaternion.identity;

            mesh      = null;
            rfShatter = null;
        }
示例#3
0
        // Set slicing objects
        static void SetSlices(RFShatter shatter, Transform tm, RFSlice slices)
        {
            // Filter
            List <Transform> list = new List <Transform>();

            for (int i = 0; i < slices.sliceList.Count; i++)
            {
                if (slices.sliceList[i] != null)
                {
                    list.Add(slices.sliceList[i]);
                }
            }

            // No objects
            if (list.Count == 0)
            {
                return;
            }

            // Get slice data
            Vector3[] points = list.Select(t => t.position).ToArray();
            Vector3[] norms  = list.Select(t => slices.Axis(t)).ToArray();

            // Set params
            shatter.SetBricksParams(points, norms, tm);
        }
示例#4
0
        /// /////////////////////////////////////////////////////////
        /// Fragmentation types
        /// /////////////////////////////////////////////////////////

        // Set Uniform
        static void SetVoronoi(RFShatter shatter, int numFragments, Transform tm, Vector3 centerPos, float centerBias)
        {
            // Get amount
            int amount = numFragments;

            if (amount < 1)
            {
                amount = 1;
            }
            if (amount > 20000)
            {
                amount = 2;
            }

            // Set properties
            shatter.SetFragmentParameter(RFShatter.FragmentParams.type, (int)RFShatter.FragmentType.voronoi);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_type, (int)RFShatter.VoronoiType.irregular);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_irr_num, amount);

            // Set bias to center
            if (centerBias > 0)
            {
                shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_irr_bias, centerBias);
                shatter.SetCenterParameter(centerPos, tm, Vector3.forward);
            }
        }
示例#5
0
        // Set Shatter Runtime Mode properties
        static void SetShatterRuntimeMode(RFShatter shatter)
        {
            shatter.EditorMode(false);
            //shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_shatter, true);
            //shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_cap,     true);
            //shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_weld,    true);

            // TODO tests vals
            shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_shatter, true);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_cap, true);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_weld, true);

            shatter.SetGeneralParameter(RFShatter.GeneralParams.minFacesFilter, 3);
        }
示例#6
0
        // Set Shatter Editor Mode properties
        static void SetShatterEditorMode(RFShatter shatter, float sizeFilter, bool preCap, bool remCap, bool remDbl, bool exInside)
        {
            shatter.EditorMode(true);

            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_pre_cap, preCap);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_remove_cap_faces, remCap);

            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_separate_only, false);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_elliminateCollinears_maxIterFuse, 150);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_min_bbox_diag_size_filter, sizeFilter);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_exclude_inside, exInside);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_remove_double_faces, remDbl);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_remove_inversed_double_faces, remDbl);
        }
示例#7
0
        // Set Slabs
        static void SetSlabs(RFShatter shatter, RFSplinters slabs, Transform tm, Vector3 centerPos, float centerBias)
        {
            // Set properties
            shatter.SetFragmentParameter(RFShatter.FragmentParams.type, (int)RFShatter.FragmentType.voronoi);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_type, (int)RFShatter.VoronoiType.irregular);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_irr_num, slabs.Amount);

            // Set center
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_irr_bias, centerBias);
            shatter.SetCenterParameter(centerPos, tm, Vector3.forward);

            // Set Stretching for slabs
            SetStretching(shatter, slabs.axis, slabs.strength, FragType.Slabs);
        }
示例#8
0
        // Set custom point cloud
        static void SetCustom(RFShatter shatter, RFCustom custom, Transform tm, MeshFilter mf, Bounds bound, RFSplinters splint, RFSplinters slabs, int seed)
        {
            // Set properties
            shatter.SetFragmentParameter(RFShatter.FragmentParams.type, (int)RFShatter.FragmentType.voronoi);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_type, (int)RFShatter.VoronoiType.custom);

            // Get Point Cloud
            List <Vector3> pointCloud = GetCustomPointCLoud(custom, tm, seed, bound);

            // Set points
            shatter.SetVoroCustomPoints(pointCloud.ToArray(), tm);

            // Set Stretching TODO point cloud rescale by transform
            // if (custom.modifier == RFCustom.RFModifierType.Splinters)
            //     SetStretching (shatter, splint.axis, splint.strength, FragType.Splinters);
            // else if (custom.modifier == RFCustom.RFModifierType.Slabs)
            //     SetStretching (shatter, slabs.axis, slabs.strength, FragType.Slabs);
        }
示例#9
0
        /// /////////////////////////////////////////////////////////
        /// Properties setup
        /// /////////////////////////////////////////////////////////

        // Set common fragmentation properties
        static RFShatter SetShatter(int shatterMode, Mesh mesh, Transform transform, RFSurface interior,
                                    bool decompose, bool deleteCol, int seed = 1, FragmentMode mode = FragmentMode.Runtime,
                                    bool preCap = true, bool remCap = false, bool remDbl = true, bool exInside = false, int percSize = 3)
        {
            // Creating shatter
            RFShatter shatter = new RFShatter((RFShatter.RFShatterMode)shatterMode, true);

            // Safe/unsafe properties
            if (mode == FragmentMode.Editor)
            {
                float sizeFilter = mesh.bounds.size.magnitude * percSize / 100f; // TODO check render bound size
                SetShatterEditorMode(shatter, sizeFilter, preCap, remCap, remDbl, exInside);
            }
            else
            {
                SetShatterRuntimeMode(shatter);
            }

            // Detach by elements
            shatter.DecomposeResultMesh(decompose);

            // Set properties
            shatter.SetFragmentParameter(RFShatter.FragmentParams.seed, seed);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.pre_weld_threshold, 0.001f);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.delete_collinear, deleteCol);

            // Other
            shatter.SetGeneralParameter(RFShatter.GeneralParams.maping_scale, interior.mappingScale);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.restore_normals, true);

            // Setting shatter params
            bool inputState = shatter.SetInputMesh(transform, mesh);

            // Failed input
            if (inputState == false)
            {
                Debug.Log("Bad input mesh: " + transform.name, transform.gameObject);
                return(null);
            }

            return(shatter);
        }
示例#10
0
        /// /////////////////////////////////////////////////////////
        /// Stretching
        /// /////////////////////////////////////////////////////////

        // Set stretching
        static void SetStretching(RFShatter shatter, AxisType axis, float strength, FragType fragType)
        {
            // Get slab vector
            Vector3 stretchDir = DirectionAxis(axis);

            // Adjust for slabs
            if (fragType == FragType.Slabs)
            {
                Vector3 vector = new Vector3();
                if (stretchDir.x <= 0)
                {
                    vector.x = 1f;
                }
                if (stretchDir.x >= 1f)
                {
                    vector.x = 0;
                }
                if (stretchDir.y <= 0)
                {
                    vector.y = 1f;
                }
                if (stretchDir.y >= 1f)
                {
                    vector.y = 0;
                }
                if (stretchDir.z <= 0)
                {
                    vector.z = 1f;
                }
                if (stretchDir.z >= 1f)
                {
                    vector.z = 0;
                }
                stretchDir = vector;
            }

            // Set stretch vector
            shatter.SetPoint3Parameter((int)RFShatter.FragmentParams.stretching, stretchDir * Mathf.Lerp(40f, 99f, strength));
        }
示例#11
0
        // Set Radial
        static void SetRadial(RFShatter shatter, RFRadial radial, Transform tm, Vector3 centerPos, Quaternion centerDirection)
        {
            // Set radial properties
            shatter.SetFragmentParameter(RFShatter.FragmentParams.type, (int)RFShatter.FragmentType.voronoi);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_type, (int)RFShatter.VoronoiType.radial);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_radius, radial.radius);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_divergence, radial.divergence);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_restrict, radial.restrictToPlane);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_rings_count, radial.rings);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_rings_focus, radial.focus);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_rings_strenght, radial.focusStr);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_rings_random, radial.randomRings);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_rays_count, radial.rays);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_rays_random, radial.randomRays);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.voronoi_rad_rays_twist, radial.twist);

            // Get direction axis
            Vector3 directionAxis = DirectionAxis(radial.centerAxis);
            Vector3 centerRot     = tm.rotation * centerDirection * directionAxis;

            shatter.SetCenterParameter(centerPos, tm, centerRot);
        }
示例#12
0
        /// /////////////////////////////////////////////////////////
        /// Clusters
        /// /////////////////////////////////////////////////////////

        // Set clusters
        static void SetClusters(RFShatter shatter, RFShatterCluster gluing)
        {
            shatter.InitClustering(true);
            shatter.SetClusterParameter(RFShatter.ClusterParams.enabled, true);
            shatter.SetClusterParameter(RFShatter.ClusterParams.by_pcloud_count, gluing.count);
            shatter.SetClusterParameter(RFShatter.ClusterParams.options_seed, gluing.seed);
            shatter.SetClusterParameter(RFShatter.ClusterParams.preview_scale, 100f);

            // Debris
            shatter.SetClusterParameter(RFShatter.ClusterParams.debris_layers_count, gluing.layers);
            shatter.SetClusterParameter(RFShatter.ClusterParams.debris_count, gluing.amount);
            shatter.SetClusterParameter(RFShatter.ClusterParams.debris_scale, gluing.scale);
            shatter.SetClusterParameter(RFShatter.ClusterParams.debris_min, gluing.min);
            shatter.SetClusterParameter(RFShatter.ClusterParams.debris_max, gluing.max);
            shatter.SetClusterParameter(RFShatter.ClusterParams.debris_tessellate, false);
            shatter.SetClusterParameter(RFShatter.ClusterParams.debris_remove, false);

            // Glue
            shatter.SetGeneralParameter(RFShatter.GeneralParams.glue, true);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.glue_weld_threshold, 0.001f);
            shatter.SetGeneralParameter(RFShatter.GeneralParams.relax, gluing.relax);
        }
示例#13
0
        /// /////////////////////////////////////////////////////////
        /// Constructor
        /// /////////////////////////////////////////////////////////

        // Constructor
        public RFDemolitionMesh()
        {
            amount      = 15;
            variation   = 0;
            depthFade   = 0.5f;
            contactBias = 0f;
            seed        = 1;
            useShatter  = false;

            meshInput      = MeshInputType.AtDemolition;
            properties     = new RFFragmentProperties();
            runtimeCaching = new RFRuntimeCaching();

            Reset();

            shatterMode        = 1;
            innerSubId         = 0;
            compressPrefab     = true;
            cacheRotationStart = Quaternion.identity;

            mesh      = null;
            rfShatter = null;
        }
示例#14
0
 // Decompose to elements
 static void SetDecompose(RFShatter shatter)
 {
     shatter.SetGeneralParameter(RFShatter.GeneralParams.editor_mode_separate_only, true);
 }
示例#15
0
        // Set Custom Voronoi properties
        static void SetTet(RFShatter shatter, Bounds bounds, RFTets tets)
        {
            // Main
            shatter.SetFragmentParameter(RFShatter.FragmentParams.type, (int)RFShatter.FragmentType.tetra);
            shatter.SetFragmentParameter(RFShatter.FragmentParams.tetra_type, (int)tets.lattice);

            // Get max
            float max = bounds.size.x;

            if (bounds.size.y > max)
            {
                max = bounds.size.y;
            }
            if (bounds.size.z > max)
            {
                max = bounds.size.z;
            }
            if (max == 0)
            {
                max = 0.01f;
            }

            // Get density
            Vector3Int density = new Vector3Int(
                (int)Mathf.Ceil(bounds.size.x / max * tets.density),
                (int)Mathf.Ceil(bounds.size.y / max * tets.density),
                (int)Mathf.Ceil(bounds.size.z / max * tets.density));

            // Limit
            if (density.x > 30)
            {
                density.x = 30;
            }
            else if (density.x < 1)
            {
                density.x = 1;
            }
            if (density.y > 30)
            {
                density.y = 30;
            }
            else if (density.y < 1)
            {
                density.y = 1;
            }
            if (density.z > 30)
            {
                density.z = 30;
            }
            else if (density.z < 1)
            {
                density.z = 1;
            }

            // Set density
            shatter.SetPoint3Parameter((int)RFShatter.FragmentParams.tetra2_density, density);
            shatter.SetPoint3Parameter((int)RFShatter.FragmentParams.tetra1_density, density);

            // Noise
            shatter.SetFragmentParameter(RFShatter.FragmentParams.tetra_noise, tets.noise);
        }
示例#16
0
        /// /////////////////////////////////////////////////////////
        /// Slice
        /// /////////////////////////////////////////////////////////

        // Cache for slice
        public static void SliceMeshes(ref Mesh[] meshes, ref Vector3[] pivots, ref List <RFDictionary> origSubMeshIdsRf, RayfireRigid scr, List <Vector3> sliceData)
        {
            // Get mesh
            scr.meshDemolition.mesh = GetDemolitionMesh(scr);

            // Set up shatter
            RFShatter shatter = SetShatter(
                2,
                scr.meshDemolition.mesh,
                scr.transform,
                scr.materials,
                true,
                scr.meshDemolition.properties.removeCollinear,
                scr.meshDemolition.seed,
                FragmentMode.Runtime,
                false,
                false,
                false,
                false,
                3);

            // Failed input
            if (shatter == null)
            {
                scr.meshDemolition.badMesh++;
                return;
            }

            // Get innerSubId
            int innerSubId = RFSurface.SetInnerSubId(scr);

            // Get slice data
            List <Vector3> points = new List <Vector3>();
            List <Vector3> norms  = new List <Vector3>();

            for (int i = 0; i < sliceData.Count; i++)
            {
                points.Add(sliceData[i]);
                norms.Add(sliceData[i + 1]);
                i++;
            }

            // Set params
            shatter.SetBricksParams(points.ToArray(), norms.ToArray(), scr.transform);

            // Calculate fragments
            List <Dictionary <int, int> > origSubMeshIds = new List <Dictionary <int, int> >();
            bool successState = Compute(
                2,
                shatter,
                scr.transform,
                ref meshes,
                ref pivots,
                scr.meshDemolition.mesh,
                innerSubId,
                ref origSubMeshIds,
                scr.gameObject);

            // Create RF dictionary
            origSubMeshIdsRf = new List <RFDictionary>();
            for (int i = 0; i < origSubMeshIds.Count; i++)
            {
                origSubMeshIdsRf.Add(new RFDictionary(origSubMeshIds[i]));
            }

            // Failed fragmentation. Increase bad mesh
            if (successState == false)
            {
                scr.meshDemolition.badMesh++;
                Debug.Log("Bad mesh: " + scr.name, scr.gameObject);
            }
            else
            {
                for (int i = 0; i < meshes.Length; i++)
                {
                    meshes[i].name = scr.name + "_" + i;
                }
            }
        }
示例#17
0
        /// /////////////////////////////////////////////////////////
        /// Shatter
        /// /////////////////////////////////////////////////////////

        // Cache for shatter
        public static void CacheMeshes(ref Mesh[] meshes, ref Vector3[] pivots, ref List <RFDictionary> origSubMeshIdsRf, RayfireShatter scrShatter)
        {
            // TODO check vars by type: slice list, etc

            // Turn off fast mode for tets and slices
            int shatterMode = GetShatterMode(scrShatter);

            // Get mesh
            Mesh mesh = GetDemolitionMesh(scrShatter);;

            // Decompose in Editor only, slice runtime only
            FragmentMode mode = scrShatter.mode;

            if (scrShatter.type == FragType.Decompose) // TODO FIX
            {
                mode = FragmentMode.Editor;
            }
            if (scrShatter.type == FragType.Slices)
            {
                mode = FragmentMode.Runtime;
            }

            // Set up shatter
            RFShatter shatter = SetShatter(
                shatterMode,
                mesh,
                scrShatter.transform,
                scrShatter.material,
                scrShatter.advanced.decompose,
                scrShatter.advanced.removeCollinear,
                scrShatter.advanced.seed,
                mode,
                scrShatter.advanced.inputPrecap,
                scrShatter.advanced.outputPrecap,
                scrShatter.advanced.removeDoubleFaces,
                scrShatter.advanced.excludeInnerFragments,
                scrShatter.advanced.elementSizeThreshold);

            // Failed input
            if (shatter == null)
            {
                meshes = null;
                pivots = null;
                return;
            }

            // Get innerSubId
            int innerSubId = RFSurface.SetInnerSubId(scrShatter);

            // Set fragmentation properties
            SetFragmentProperties(shatter, scrShatter, null);

            // Custom points check
            if (scrShatter.type == FragType.Custom && scrShatter.custom.noPoints == true)
            {
                meshes = null;
                pivots = null;
                Debug.Log("No custom ponts");
                return;
            }

            // Calculate fragments
            List <Dictionary <int, int> > origSubMeshIds = new List <Dictionary <int, int> >();
            bool successState = Compute(
                shatterMode,
                shatter,
                scrShatter.transform,
                ref meshes,
                ref pivots,
                mesh,
                innerSubId,
                ref origSubMeshIds,
                scrShatter);

            // Create RF dictionary
            origSubMeshIdsRf = new List <RFDictionary>();
            for (int i = 0; i < origSubMeshIds.Count; i++)
            {
                origSubMeshIdsRf.Add(new RFDictionary(origSubMeshIds[i]));
            }

            // Failed fragmentation. Increase bad mesh
            if (successState == false)
            {
                Debug.Log("Bad shatter output mesh: " + scrShatter.name);
            }
            else
            {
                for (int i = 0; i < meshes.Length; i++)
                {
                    meshes[i].name = scrShatter.name + "_" + i;
                }
            }
        }
示例#18
0
        // Set fragmentation properties
        static void SetFragmentProperties(RFShatter shatter, RayfireShatter scrSh, RayfireRigid scrRigid)
        {
            // Rigid demolition without shatter. Set and exit.
            if (scrRigid != null && scrSh == null)
            {
                // Get final amount
                int percVar = Random.Range(0, scrRigid.meshDemolition.amount * scrRigid.meshDemolition.variation / 100);
                scrRigid.meshDemolition.totalAmount = scrRigid.meshDemolition.amount + percVar;

                // Set Voronoi Uniform properties
                SetVoronoi(shatter, scrRigid.meshDemolition.totalAmount, scrRigid.transform, scrRigid.limitations.contactPoint, scrRigid.meshDemolition.contactBias);
                return;
            }

            // Rigid demolition with shatter.
            if (scrRigid != null && scrSh != null)
            {
                // Set Contact point to shatter component
                scrSh.centerPosition = scrRigid.transForm.InverseTransformPoint(scrRigid.limitations.contactPoint);

                // Set total amount by rigid component
                if (scrSh.type == FragType.Voronoi)
                {
                    scrRigid.meshDemolition.totalAmount = scrSh.voronoi.Amount;
                }
                else if (scrSh.type == FragType.Splinters)
                {
                    scrRigid.meshDemolition.totalAmount = scrSh.splinters.Amount;
                }
                else if (scrSh.type == FragType.Slabs)
                {
                    scrRigid.meshDemolition.totalAmount = scrSh.slabs.Amount;
                }
                else if (scrSh.type == FragType.Radial)
                {
                    scrRigid.meshDemolition.totalAmount = scrSh.radial.rings * scrSh.radial.rays;
                }
            }

            // Shatter fragmentation
            if (scrSh != null)
            {
                // Center position and direction
                Vector3 centerPos = scrSh.transform.TransformPoint(scrSh.centerPosition);

                // Set properties
                if (scrSh.type == FragType.Voronoi)
                {
                    SetVoronoi(shatter, scrSh.voronoi.Amount, scrSh.transform, centerPos, scrSh.voronoi.centerBias);
                }
                else if (scrSh.type == FragType.Splinters)
                {
                    SetSplinters(shatter, scrSh.splinters, scrSh.transform, centerPos, scrSh.splinters.centerBias);
                }
                else if (scrSh.type == FragType.Slabs)
                {
                    SetSlabs(shatter, scrSh.slabs, scrSh.transform, centerPos, scrSh.splinters.centerBias);
                }
                else if (scrSh.type == FragType.Radial)
                {
                    SetRadial(shatter, scrSh.radial, scrSh.transform, centerPos, scrSh.centerDirection);
                }
                else if (scrSh.type == FragType.Custom)
                {
                    SetCustom(shatter, scrSh.custom, scrSh.transform, scrSh.meshFilter, scrSh.bound, scrSh.splinters, scrSh.slabs, scrSh.advanced.seed);
                }
                else if (scrSh.type == FragType.Slices)
                {
                    SetSlices(shatter, scrSh.transform, scrSh.slice);
                }
                else if (scrSh.type == FragType.Tets)
                {
                    SetTet(shatter, scrSh.bound, scrSh.tets);
                }
                else if (scrSh.type == FragType.Decompose)
                {
                    SetDecompose(shatter);
                }

                // Clustering
                if (scrSh.clusters.enable == true)
                {
                    SetClusters(shatter, scrSh.clusters);
                }
            }
        }
示例#19
0
        /// /////////////////////////////////////////////////////////
        /// Compute
        /// /////////////////////////////////////////////////////////

        // Compute
        static bool Compute(int shatterMode, RFShatter shatter, Transform tm, ref Mesh[] meshes, ref Vector3[] pivots,
                            Mesh mesh, int innerSubId, ref List <Dictionary <int, int> > subIds, Object obj, List <int> markedElements = null)
        {
            // Compute fragments
            bool state = shatterMode == 0
                ? shatter.Compute(tm, ref meshes, ref pivots, mesh, innerSubId, ref subIds)
                : shatter.SimpleCompute(tm, ref meshes, ref pivots, mesh, innerSubId, ref subIds, markedElements);

            // Failed fragmentation
            if (state == false)
            {
                meshes = null;
                pivots = null;
                subIds = new List <Dictionary <int, int> >();
                return(false);
            }

            // Null check
            if (meshes == null)
            {
                Debug.Log("Null mesh", obj);
                meshes = null;
                pivots = null;
                subIds = new List <Dictionary <int, int> >();
                return(false);
            }

            // Empty mesh fix
            if (EmptyMeshState(meshes) == true)
            {
                List <Mesh>    meshList  = new List <Mesh>();
                List <Vector3> pivotList = new List <Vector3>();
                List <Dictionary <int, int> > subIdsList = new List <Dictionary <int, int> >();
                for (int i = 0; i < meshes.Length; i++)
                {
                    if (meshes[i].vertexCount > 2)
                    {
                        meshList.Add(meshes[i]);
                        pivotList.Add(pivots[i]);
                        subIdsList.Add(subIds[i]);
                    }
                }

                pivots = pivotList.ToArray();
                meshes = meshList.ToArray();
                subIds = subIdsList;
                Debug.Log("Empty Mesh", obj);
            }

            // Single mesh after mesh fix check
            if (meshes.Length <= 1)
            {
                Debug.Log("Mesh amount " + meshes.Length, obj);
                meshes = null;
                pivots = null;
                subIds = new List <Dictionary <int, int> >();
                return(false);
            }

            // TODO set in library
            for (int i = 0; i < meshes.Length; i++)
            {
                meshes[i].RecalculateTangents();
            }

            return(true);
        }