Пример #1
0
 // Copy from
 public void CopyFrom(RFSurface interior)
 {
     innerMaterial = interior.innerMaterial;
     mappingScale  = interior.mappingScale;
     needNewMat    = interior.needNewMat;
     outerMaterial = interior.outerMaterial;
 }
Пример #2
0
        /// /////////////////////////////////////////////////////////
        /// Rigid
        /// /////////////////////////////////////////////////////////

        // Prepare rigid component to cache fragment meshes
        public static bool InputMesh(RayfireRigid scr)
        {
            // Set up shatter
            if (SetRigidShatter(scr) == false)
            {
                return(false);
            }

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

            // Set fragmentation properties
            SetFragmentProperties(scr.meshDemolition.rfShatter, scr.meshDemolition.scrShatter, scr);

            return(true);
        }
Пример #3
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);
        }
Пример #4
0
        // Create slices by mesh and pivots array
        public static List <RayfireRigid> CreateSlices(RayfireRigid scr)
        {
            // Fragments list
            List <RayfireRigid> scrArray = new List <RayfireRigid>();

            // Stop if has no any meshes
            if (scr.meshes == null)
            {
                return(scrArray);
            }

            // Create RayFire manager if not created
            RayfireMan.RayFireManInit();

            // Create root object and parent
            RFLimitations.CreateRoot(scr);

            // Vars
            int    baseLayer = scr.meshDemolition.GetLayer(scr);
            string baseTag   = scr.gameObject.tag;
            string baseName  = scr.gameObject.name + fragmentStr;

            // Get original mats
            Material[] mats = scr.skinnedMeshRend != null
                ? scr.skinnedMeshRend.sharedMaterials
                : scr.meshRenderer.sharedMaterials;

            // Create fragment objects
            for (int i = 0; i < scr.meshes.Length; ++i)
            {
                // Get object from pool or create
                RayfireRigid rfScr = RayfireMan.inst == null
                    ? RFPoolingFragment.CreateRigidInstance()
                    : RayfireMan.inst.fragments.GetPoolObject(RayfireMan.inst.transForm);

                // Setup
                rfScr.transform.position = scr.transForm.position + scr.pivots[i];
                rfScr.transform.parent   = scr.rootChild;
                rfScr.name                  = baseName + i;
                rfScr.gameObject.tag        = baseTag;
                rfScr.gameObject.layer      = baseLayer;
                rfScr.meshFilter.sharedMesh = scr.meshes[i];
                rfScr.rootParent            = scr.rootChild;

                // Copy properties from parent to fragment node
                scr.CopyPropertiesTo(rfScr);

                // Copy particles
                RFParticles.CopyParticles(scr, rfScr);

                // Set collider
                RFPhysic.SetFragmentMeshCollider(rfScr, scr.meshes[i]);

                // Shadow casting
                if (RayfireMan.inst.advancedDemolitionProperties.sizeThreshold > 0 &&
                    RayfireMan.inst.advancedDemolitionProperties.sizeThreshold > scr.meshes[i].bounds.size.magnitude)
                {
                    rfScr.meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
                }

                // Turn on
                rfScr.gameObject.SetActive(true);

                // Set multymaterial
                RFSurface.SetMaterial(scr.subIds, mats, scr.materials, rfScr.meshRenderer, i, scr.meshes.Length);

                // Update depth level and amount
                rfScr.limitations.currentDepth = scr.limitations.currentDepth + 1;
                //rfScr.meshDemolition.amount = (int)(rfScr.meshDemolition.amount * rfScr.meshDemolition.depthFade);
                //if (rfScr.meshDemolition.amount < 2)
                //    rfScr.meshDemolition.amount = 2;

                // Add in array
                scrArray.Add(rfScr);
            }

            // Empty lists
            scr.DeleteCache();

            return(scrArray);
        }
Пример #5
0
        // Create fragments by mesh and pivots array
        public static List <RayfireRigid> CreateFragments(RayfireRigid scr)
        {
            // Fragments list
            List <RayfireRigid> scrArray = new List <RayfireRigid>();

            // Stop if has no any meshes
            if (scr.meshes == null)
            {
                return(scrArray);
            }

            // Create RayFire manager if not created
            RayfireMan.RayFireManInit();

            // Create root object and parent
            RFLimitations.CreateRoot(scr);

            // Vars
            int    baseLayer = scr.meshDemolition.GetLayer(scr);
            string baseTag   = scr.gameObject.tag;
            string baseName  = scr.gameObject.name + fragmentStr;

            // Save original rotation
            // Quaternion originalRotation = rootChild.transform.rotation;

            // Set rotation to precache rotation
            if (scr.demolitionType == DemolitionType.AwakePrecache)
            {
                scr.rootChild.transform.rotation = scr.cacheRotation;
            }

            // Get original mats
            Material[] mats = scr.skinnedMeshRend != null
                ? scr.skinnedMeshRend.sharedMaterials
                : scr.meshRenderer.sharedMaterials;

            // Create fragment objects
            for (int i = 0; i < scr.meshes.Length; ++i)
            {
                // Get object from pool or create
                RayfireRigid rfScr = RayfireMan.inst == null
                    ? RFPoolingFragment.CreateRigidInstance()
                    : RayfireMan.inst.fragments.GetPoolObject(RayfireMan.inst.transForm);

                // Setup
                rfScr.transform.position = scr.transForm.position + scr.pivots[i];
                rfScr.transform.parent   = scr.rootChild;
                rfScr.name                  = baseName + i;
                rfScr.gameObject.tag        = baseTag;
                rfScr.gameObject.layer      = baseLayer;
                rfScr.meshFilter.sharedMesh = scr.meshes[i];
                rfScr.rootParent            = scr.rootChild;

                // Copy properties from parent to fragment node
                scr.CopyPropertiesTo(rfScr);

                // Copy particles
                RFParticles.CopyParticles(scr, rfScr);

                // Set collider
                RFPhysic.SetFragmentMeshCollider(rfScr, scr.meshes[i]);

                // Shadow casting
                if (RayfireMan.inst.advancedDemolitionProperties.sizeThreshold > 0 &&
                    RayfireMan.inst.advancedDemolitionProperties.sizeThreshold > scr.meshes[i].bounds.size.magnitude)
                {
                    rfScr.meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
                }

                // Turn on
                rfScr.gameObject.SetActive(true);

                // Set multymaterial
                RFSurface.SetMaterial(scr.subIds, mats, scr.materials, rfScr.meshRenderer, i, scr.meshes.Length);

                // Update depth level and amount
                rfScr.limitations.currentDepth = scr.limitations.currentDepth + 1;
                rfScr.meshDemolition.amount    = (int)(rfScr.meshDemolition.amount * rfScr.meshDemolition.depthFade);
                if (rfScr.meshDemolition.amount < 3)
                {
                    rfScr.meshDemolition.amount = 3;
                }

                // Add in array
                scrArray.Add(rfScr);

                // Debug.Log (rfScr.rootParent);
            }

            // Fix transform for precached fragments
            if (scr.demolitionType == DemolitionType.AwakePrecache)
            {
                scr.rootChild.rotation = scr.transForm.rotation;
            }

            // Fix runtime caching rotation difference. Get rotation difference and add to root
            if (scr.demolitionType == DemolitionType.Runtime && scr.meshDemolition.runtimeCaching.type != CachingType.Disable)
            {
                Quaternion cacheRotationDif = scr.transForm.rotation * Quaternion.Inverse(scr.meshDemolition.cacheRotationStart);
                scr.rootChild.rotation = cacheRotationDif * scr.rootChild.rotation;
            }

            return(scrArray);
        }
Пример #6
0
        // Create fragments by mesh and pivots array
        private List <GameObject> CreateFragments(GameObject lastRoot = null)
        {
            // No mesh were cached
            if (meshes == null)
            {
                return(null);
            }

            // Clear array for new fragments
            GameObject[] fragArray = new GameObject[meshes.Length];

            // Vars
            string goName   = gameObject.name;
            string baseName = goName + "_sh_";

            // Create root object
            GameObject root = lastRoot;

            if (lastRoot == null)
            {
                root = new GameObject(goName + "_root");
                root.transform.position = transForm.position;
                root.transform.rotation = transForm.rotation;
                root.transform.parent   = transForm.parent;
                rootChildList.Add(root.transform);
            }

            // KEVINJ: when operating on project assets, causes the new root object to be in the scene rather than a child of the prefab
            // Use https://docs.unity3d.com/ScriptReference/PrefabUtility.LoadPrefabContents.html in order to be able to set the parent
            // PrefabMode prefabMode = GetPrefabMode(gameObject);
            // if ( prefabMode != PrefabMode.Scene)
            // {
            //  // PREFAB, AVOID CREATING INTO SCENE
            //  root.transform.parent = transForm;
            // }
            // else
            // {
            //  // ORIGINAL BEHAVIOR
            //  root.transform.parent = transForm.parent;
            // }

            // Create instance for fragments
            GameObject fragInstance;

            if (advanced.copyComponents == true)
            {
                fragInstance = Instantiate(gameObject);
                fragInstance.transform.rotation   = Quaternion.identity;
                fragInstance.transform.localScale = Vector3.one;

                // Destroy shatter
                DestroyImmediate(fragInstance.GetComponent <RayfireShatter>());
            }
            else
            {
                fragInstance = new GameObject();
                fragInstance.AddComponent <MeshFilter>();
                fragInstance.AddComponent <MeshRenderer>();
            }

            // Get original mats
            Material[] mats = skinnedMeshRend != null
                ? skinnedMeshRend.sharedMaterials
                : meshRenderer.sharedMaterials;

            // Create fragment objects
            for (int i = 0; i < meshes.Length; ++i)
            {
                // Rescale mesh
                if (rescaleFix != 1f)
                {
                    RFFragment.RescaleMesh(meshes[i], rescaleFix);
                }

                // Instantiate. IMPORTANT do not parent when Instantiate
                GameObject fragGo = Instantiate(fragInstance);
                fragGo.transform.localScale = Vector3.one;

                // Set multymaterial
                MeshRenderer targetRend = fragGo.GetComponent <MeshRenderer>();
                RFSurface.SetMaterial(origSubMeshIdsRF, mats, material, targetRend, i, meshes.Length);

                // Set fragment object name and tm
                fragGo.name = baseName + (i + 1);
                fragGo.transform.position = root.transform.position + (pivots[i] / rescaleFix);
                fragGo.transform.parent   = root.transform;

                // Set fragment mesh
                MeshFilter mf = fragGo.GetComponent <MeshFilter>();


                /*// KevinJ:
                 #if UNITY_EDITOR
                 * // Up to the caller to use AssetDatabase.RemoveObjectFromAsset to remove meshes from any prior calls to CreateFragments()
                 * if (prefabMode == PrefabMode.Asset)
                 * {
                 *      AssetDatabase.AddObjectToAsset(meshes[i], gameObject.scene.path);
                 * }
                 * else if (prefabMode == PrefabMode.PrefabEditingMode)
                 * {
                 *      //string assetPath = UnityEditor.Experimental.GetPrefabStage(gameObject).prefabAssetPath;
                 *      //AssetDatabase.AddObjectToAsset(meshes[i], assetPath);
                 * }
                 #endif*/


                mf.sharedMesh      = meshes[i];
                mf.sharedMesh.name = fragGo.name;

                // Set mesh collider
                MeshCollider mc = fragGo.GetComponent <MeshCollider>();
                if (mc != null)
                {
                    mc.sharedMesh = meshes[i];
                }

                // Add in array
                fragArray[i] = fragGo;
            }

            // Destroy instance
            DestroyImmediate(fragInstance);

            // Empty lists
            meshes           = null;
            pivots           = null;
            origSubMeshIdsRF = new List <RFDictionary>();

            return(fragArray.ToList());
        }
Пример #7
0
        /// /////////////////////////////////////////////////////////
        /// Methods
        /// /////////////////////////////////////////////////////////

        // Set material to fragment by it's interior properties and parent material
        public static void SetMaterial(List <RFDictionary> origSubMeshIdsRF, Material[] sharedMaterials, RFSurface interior, MeshRenderer targetRend, int i, int amount)
        {
            if (origSubMeshIdsRF != null && origSubMeshIdsRF.Count == amount)
            {
                Material[] newMaterials = new Material[origSubMeshIdsRF[i].values.Count];

                // TODO implement in fragmentation to avoid calcs
                if (interior.outerMaterial != null)
                {
                    for (int j = 0; j < newMaterials.Length; j++)
                    {
                        newMaterials[j] = interior.outerMaterial;
                    }
                }
                else
                {
                    for (int j = 0; j < origSubMeshIdsRF[i].values.Count; j++)
                    {
                        int matId = origSubMeshIdsRF[i].values[j];
                        if (matId < sharedMaterials.Length)
                        {
                            newMaterials[j] = sharedMaterials[matId];
                        }
                        else
                        {
                            newMaterials[j] = interior.innerMaterial;
                        }
                    }
                }

                targetRend.sharedMaterials = newMaterials;
            }
        }
Пример #8
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;
                }
            }
        }
Пример #9
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;
                }
            }
        }
Пример #10
0
        // Create slices by mesh and pivots array
        List <RayfireRigid> CreateSlices()
        {
            // Create root object
            RFLimitations.CreateRoot(this);

            // Clear array for new fragments
            List <RayfireRigid> scrArray = new List <RayfireRigid>();

            // Vars
            int    baseLayer = meshDemolition.GetLayer(this);
            string baseTag   = gameObject.tag;
            string baseName  = gameObject.name + "_sl_";

            // Create fragment objects
            for (int i = 0; i < meshes.Length; ++i)
            {
                // Get object from pool or create
                RayfireRigid rfScr = RayfireMan.inst.GetPoolObject();

                // Setup
                rfScr.transform.position = transForm.position + pivots[i];
                rfScr.transform.parent   = rootChild;
                rfScr.name                       = baseName + i;
                rfScr.gameObject.tag             = baseTag;
                rfScr.gameObject.layer           = baseLayer;
                rfScr.meshFilter.sharedMesh      = meshes[i];
                rfScr.meshFilter.sharedMesh.name = baseName + i;
                rfScr.rootParent                 = rootChild;

                // Copy properties from parent to fragment node
                CopyPropertiesTo(rfScr);

                // Copy particles
                RFParticles.CopyParticles(this, rfScr);

                // Shadow casting
                if (RayfireMan.inst.advancedDemolitionProperties.sizeThreshold > 0 &&
                    RayfireMan.inst.advancedDemolitionProperties.sizeThreshold > meshes[i].bounds.size.magnitude)
                {
                    rfScr.meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
                }

                // Turn on
                rfScr.gameObject.SetActive(true);

                // Set multymaterial
                RFSurface.SetMaterial(subIds, meshRenderer.sharedMaterials, materials, rfScr.meshRenderer, i, meshes.Length);

                // Inherit same current depth level
                rfScr.limitations.currentDepth = limitations.currentDepth + 1;

                // Set collider mesh
                MeshCollider mc = rfScr.physics.meshCollider as MeshCollider;
                if (mc != null)
                {
                    mc.sharedMesh = meshes[i];
                    mc.name       = meshes[i].name;
                }

                // Add in array
                scrArray.Add(rfScr);
            }

            // Empty lists
            DeleteCache();

            return(scrArray);
        }