static void DrawGizmosSelected(RayfireShatter shatter, GizmoType gizmoType) { // Color preview if (shatter.colorPreview == true) { ColorPreview(shatter); } // Custom point cloud preview if (shatter.type == FragType.Custom) { if (shatter.custom.enable == true) { Gizmos.color = Color.green; // Get bounds for preview Bounds bound = shatter.GetBound(); if (bound.size.magnitude > 0) { List <Vector3> pointCloud = RFFragment.GetCustomPointCLoud(shatter.custom, shatter.transform, shatter.advanced.seed, bound); if (pointCloud.Count > 0) { for (int i = 0; i < pointCloud.Count; i++) { Gizmos.DrawSphere(pointCloud[i], shatter.custom.size); } } } } } }
// Instant caching into meshes public static void CacheInstant(RayfireRigid scr) { // Timestamp float t1 = Time.realtimeSinceStartup; // Input mesh, setup if (RFFragment.InputMesh(scr) == false) { return; } // Timestamp float t2 = Time.realtimeSinceStartup; //Debug.Log (scr.gameObject.name + " Input time: " + (t2 - t1)); // Create fragments RFFragment.CacheMeshesInst(ref scr.meshes, ref scr.pivots, ref scr.subIds, scr); // Timestamp float t3 = Time.realtimeSinceStartup; //Debug.Log (t2 - t1); //Debug.Log (scr.gameObject.name + " Cache time: " + (t3 - t1)); }
/// ///////////////////////////////////////////////////////// /// Methods /// ///////////////////////////////////////////////////////// // Fragment this object by shatter properties public void Fragment() { // Cache variables if (DefineComponents() == false) { return; } // Cache default vars SetVariables(); // Check if object is too small ScaleCheck(); // Cache RFFragment.CacheMeshes(ref meshes, ref pivots, ref origSubMeshIdsRF, this); // Stop if (meshes == null) { return; } // Create fragments fragmentsLast = CreateFragments(); // Collect to all fragments fragmentsAll.AddRange(fragmentsLast); // Reset original object back if it was scaled transForm.localScale = originalScale; }
// Instant caching into meshes public static void CacheInstant(RayfireRigid scr) { // Input mesh, setup if (RFFragment.InputMesh(scr) == false) { return; } // Create fragments RFFragment.CacheMeshesInst(ref scr.meshes, ref scr.pivots, ref scr.subIds, scr); }
/// ///////////////////////////////////////////////////////// /// Methods /// ///////////////////////////////////////////////////////// // Fragment this object by shatter properties public void Fragment(int fragmentMode = 0) { // Cache variables if (DefineComponents() == false) { return; } // Cache default vars SetVariables(); // Check if object is too small ScaleCheck(); // Cache RFFragment.CacheMeshes(ref meshes, ref pivots, ref origSubMeshIdsRF, this); // Stop if (meshes == null) { return; } // Create fragments if (fragmentMode == 1) { if (rootChildList[rootChildList.Count - 1] != null) { fragmentsLast = CreateFragments(rootChildList[rootChildList.Count - 1].gameObject); } else { fragmentMode = 0; } } if (fragmentMode == 0) { fragmentsLast = CreateFragments(); } // Vertex limitation VertexLimitation(); // Collect to all fragments fragmentsAll.AddRange(fragmentsLast); // Reset original object back if it was scaled transForm.localScale = originalScale; }
/// ///////////////////////////////////////////////////////// /// Demolition types /// ///////////////////////////////////////////////////////// // Awake Mesh input // TODO add checks in case has input mesh but mesh input is off public void MeshInput() { if (objectType == ObjectType.Mesh) { // Set components for mesh / skinned mesh / clusters SetComponentsBasic(); // Timestamp //float t1 = Time.realtimeSinceStartup; // Input RFFragment.InputMesh(this); // Timestamp //float t2 = Time.realtimeSinceStartup; //Debug.Log (gameObject.name + " Input time: " + (t2 - t1)); } }
// SLice mesh public static void SliceMesh(RayfireRigid scr) { // Empty lists scr.DeleteCache(); scr.DeleteFragments(); // SLice RFFragment.SliceMeshes(ref scr.meshes, ref scr.pivots, ref scr.subIds, scr, scr.limitations.slicePlanes); // Remove plane info scr.limitations.slicePlanes.Clear(); // Stop if (scr.HasMeshes == false) { return; } // Get fragments scr.fragments = RFDemolitionMesh.CreateSlices(scr); // TODO check for fragments // Set demolition scr.limitations.demolished = true; // Fragments initialisation scr.InitMeshFragments(); // Event scr.demolitionEvent.InvokeLocalEvent(scr); RFDemolitionEvent.InvokeGlobalEvent(scr); // Destroy original RayfireMan.DestroyFragment(scr, scr.rootParent); }
// Slice object public void SliceObjectByPlanes() { // Empty lists DeleteCache(); DeleteFragments(); // SLice RFFragment.SliceMeshes(ref meshes, ref pivots, ref subIds, this, limitations.slicePlanes); // Remove plane info limitations.slicePlanes.Clear(); // Stop if (HasMeshes == false) { return; } // Get fragments fragments = CreateSlices(); // TODO check for fragments // Set demolition limitations.demolished = true; // Fragments initialisation InitFragments(); // Event demolitionEvent.InvokeLocalEvent(this); RFDemolitionEvent.InvokeGlobalEvent(this); // Destroy original RayfireMan.DestroyFragment(this, rootParent); }
// Cor to fragment mesh over several frames public IEnumerator RuntimeCachingCor(RayfireRigid scr) { // Object should be demolished when cached all meshes but not during caching bool demolitionShouldLocal = scr.limitations.demolitionShould == true; scr.limitations.demolitionShould = false; // Input mesh, setup, record time float t1 = Time.realtimeSinceStartup; if (RFFragment.InputMesh(scr) == false) { yield break; } // Set list with amount of mesh for every frame List <int> batchAmount = runtimeCaching.type == CachingType.ByFrames ? RFRuntimeCaching.GetBatchByFrames(runtimeCaching.frames, totalAmount) : RFRuntimeCaching.GetBatchByFragments(runtimeCaching.fragments, totalAmount); // Caching in progress runtimeCaching.inProgress = true; // Wait next frame if input took too much time or long batch float t2 = Time.realtimeSinceStartup - t1; if (t2 > 0.025f || batchAmount.Count > 5) { yield return(null); } // Save tm for multi frame caching GameObject tmRefGo = RFRuntimeCaching.CreateTmRef(scr); // Start rotation cacheRotationStart = scr.transForm.rotation; // Iterate every frame. Calc local frame meshes List <Mesh> meshesList = new List <Mesh>(); List <Vector3> pivotsList = new List <Vector3>(); List <RFDictionary> subList = new List <RFDictionary>(); for (int i = 0; i < batchAmount.Count; i++) { // Check for stop if (runtimeCaching.stop == true) { ResetRuntimeCaching(scr, tmRefGo); yield break; } // Cache defined points RFFragment.CacheMeshesMult(tmRefGo.transform, ref meshesList, ref pivotsList, ref subList, scr, batchAmount, i); // TODO create fragments for current batch // TODO record time and decrease batches amount if less 30 fps yield return(null); } // Set to main data vars scr.meshes = meshesList.ToArray(); scr.pivots = pivotsList.ToArray(); scr.subIds = subList; // Clear scr.DestroyObject(tmRefGo); scr.meshDemolition.scrShatter = null; // Set demolition ready state if (runtimeCaching.skipFirstDemolition == false && demolitionShouldLocal == true) { scr.limitations.demolitionShould = true; } // Reset damage if (runtimeCaching.skipFirstDemolition == true && demolitionShouldLocal == true) { scr.damage.Reset(); } // Caching finished runtimeCaching.inProgress = false; runtimeCaching.wasUsed = true; }
// 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()); }
/// ///////////////////////////////////////////////////////// /// Methods /// ///////////////////////////////////////////////////////// // Fragment this object by shatter properties public void Fragment(int fragmentMode = 0) { // Cache variables if (DefineComponents() == false) { return; } // Cache default vars SetVariables(); // Check if object is too small ScaleCheck(); // Cache RFFragment.CacheMeshes(ref meshes, ref pivots, ref origSubMeshIdsRF, this); // Stop if (meshes == null) { return; } // Create fragments if (fragmentMode == 1) { if (rootChildList[rootChildList.Count - 1] != null) { fragmentsLast = CreateFragments(rootChildList[rootChildList.Count - 1].gameObject); } else { fragmentMode = 0; } } if (fragmentMode == 0) { fragmentsLast = CreateFragments(); } // Vertex limitation if (advanced.vertexLimitation == true) { for (int i = fragmentsLast.Count - 1; i >= 0; i--) { MeshFilter mf = fragmentsLast[i].GetComponent <MeshFilter>(); if (mf.sharedMesh.vertexCount > advanced.vertexAmount) { RayfireShatter shat = fragmentsLast[i].AddComponent <RayfireShatter>(); shat.voronoi.amount = 4; shat.Fragment(); Debug.Log(shat.name); if (shat.fragmentsLast.Count > 0) { fragmentsLast.AddRange(shat.fragmentsLast); DestroyImmediate(shat.gameObject); fragmentsLast.RemoveAt(i); } } } } // Collect to all fragments fragmentsAll.AddRange(fragmentsLast); // Reset original object back if it was scaled transForm.localScale = originalScale; }