// Add rigid component to transform list static void AddRigidComponent(RayfireRigid scr, List <Transform> tmList) { for (int i = 0; i < tmList.Count; i++) { // Turn off tmList[i].gameObject.SetActive(false); // Check if object already has Rigid script RayfireRigid newScr = tmList[i].gameObject.AddComponent <RayfireRigid>(); newScr.initialization = RayfireRigid.InitType.AtStart; // Skip excluded ???????????? if (newScr.physics.exclude == true) { continue; } // Collect fragment scr.fragments.Add(newScr); // Copy properties from parent to fragment node scr.CopyPropertiesTo(newScr); // Copy particles RFParticles.CopyParticles(scr, newScr); // Set to mesh newScr.objectType = ObjectType.Mesh; newScr.physics.colliderType = RFColliderType.Mesh; // Set as cluster if has children with meshes TODO check for mesh filter if (newScr.transform.childCount > 0) { newScr.objectType = ObjectType.NestedCluster; } // Set to dynamic if solo TODO fix else { newScr.simulationType = SimType.Dynamic; } // Update depth level and amount newScr.limitations.currentDepth = scr.limitations.currentDepth + 1; // Turn on tmList[i].gameObject.SetActive(true); // IMPORTANT. Set mesh collider convex for gun impact detection if (newScr.objectType == ObjectType.Mesh) { if (newScr.physics.meshCollider != null) { ((MeshCollider)newScr.physics.meshCollider).convex = true; } } } }
// Create runtime clusters static void CreateClusterRuntime(RayfireRigid source, RFCluster cls) { // Cluster with solo shard. Add rigid component, reparent if (cls.shards.Count == 1) { AddRigidComponent(source, new List <Transform> (1) { cls.shards[0].tm }); cls.shards[0].tm.parent = RayfireMan.inst.transForm; return; } // Create root for left children GameObject leftRoot = new GameObject(); // Turn off leftRoot.SetActive(false); leftRoot.name = source.gameObject.name + "_cls"; leftRoot.transform.position = source.transForm.position; leftRoot.transform.rotation = source.transForm.rotation; leftRoot.transform.parent = RayfireMan.inst.transForm; // Parent to main root for (int s = 0; s < cls.shards.Count; s++) { cls.shards[s].tm.parent = leftRoot.transform; } // Add rigid to object RayfireRigid target = leftRoot.gameObject.AddComponent <RayfireRigid>(); target.initialization = RayfireRigid.InitType.AtStart; // Collect fragment source.fragments.Add(target); // Copy properties from parent to fragment node source.CopyPropertiesTo(target); // Copy particles RFParticles.CopyParticles(source, target); // Set to mesh target.objectType = ObjectType.ConnectedCluster; target.physics.colliderType = RFColliderType.Mesh; // Set cluster target.clusterDemolition.cluster = cls; target.clusterDemolition.cluster.id = 2; // Turn on leftRoot.SetActive(true); }
// 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); }
// 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); }
// Demolish object to reference public static bool DemolishReference(RayfireRigid scr) { if (scr.demolitionType == DemolitionType.ReferenceDemolition) { // Get instance GameObject referenceGo = scr.referenceDemolition.GetReference(); // Has reference if (referenceGo != null) { // Instantiate turned off reference bool refState = referenceGo.activeSelf; referenceGo.SetActive(false); GameObject fragRoot = scr.InstantiateGo(referenceGo); referenceGo.SetActive(refState); fragRoot.name = referenceGo.name; // Set tm scr.rootChild = fragRoot.transform; scr.rootChild.position = scr.transForm.position; scr.rootChild.rotation = scr.transForm.rotation; scr.rootChild.transform.parent = RayfireMan.inst.transForm; // Clear list for fragments scr.fragments = new List <RayfireRigid>(); // Check root for rigid props RayfireRigid rootScr = fragRoot.gameObject.GetComponent <RayfireRigid>(); // Reference Root has not rigid. Add to if (rootScr == null && scr.referenceDemolition.addRigid == true) { // Add rigid and copy rootScr = fragRoot.gameObject.AddComponent <RayfireRigid>(); rootScr.initialization = RayfireRigid.InitType.AtStart; scr.CopyPropertiesTo(rootScr); // Copy particles RFParticles.CopyParticles(scr, rootScr); // Single mesh TODO improve if (fragRoot.transform.childCount == 0) { rootScr.objectType = ObjectType.Mesh; } // Multiple meshes if (fragRoot.transform.childCount > 0) { rootScr.objectType = ObjectType.MeshRoot; } } // Activate and init rigid scr.rootChild.gameObject.SetActive(true); // Reference has rigid if (rootScr != null) { // Create rigid for root children if (rootScr.objectType == ObjectType.MeshRoot) { for (int i = 0; i < rootScr.fragments.Count; i++) { rootScr.fragments[i].limitations.currentDepth++; } scr.fragments.AddRange(rootScr.fragments); scr.DestroyRigid(rootScr); } // Get ref rigid else if (rootScr.objectType == ObjectType.Mesh || rootScr.objectType == ObjectType.SkinnedMesh) { rootScr.meshDemolition.runtimeCaching.type = CachingType.Disable; RFDemolitionMesh.DemolishMesh(rootScr); // TODO COPY MESH DATA FROM ROOTSCR TO THIS TO REUSE scr.fragments.AddRange(rootScr.fragments); RayfireMan.DestroyFragment(rootScr, rootScr.rootParent, 1f); } // Get ref rigid else if (rootScr.objectType == ObjectType.NestedCluster || rootScr.objectType == ObjectType.ConnectedCluster) { rootScr.Default(); rootScr.limitations.contactPoint = scr.limitations.contactPoint; RFDemolitionCluster.DemolishCluster(rootScr); rootScr.physics.exclude = true; scr.fragments.AddRange(rootScr.fragments); RayfireMan.DestroyFragment(rootScr, rootScr.rootParent, 1f); } // Has rigid by has No fragments. Stop demolition if (scr.HasFragments == false) { scr.demolitionType = DemolitionType.None; return(false); } } } // Has no rigid, has No fragments, but demolished scr.limitations.demolished = true; } return(true); }
// 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); }
// Demolish object to reference public static bool DemolishReference(RayfireRigid scr) { if (scr.demolitionType == DemolitionType.ReferenceDemolition) { // Demolished scr.limitations.demolished = true; // Turn off original scr.gameObject.SetActive(false); // Get instance GameObject refGo = scr.referenceDemolition.GetReference(); // Has no reference if (refGo == null) { return(true); } // Instantiate turned off reference with null parent GameObject instGo = Object.Instantiate(refGo, scr.transForm.position, scr.transForm.rotation); instGo.name = refGo.name; // Set root to manager or to the same parent if (RayfireMan.inst != null && RayfireMan.inst.advancedDemolitionProperties.parent == RFManDemolition.FragmentParentType.Manager) { instGo.transform.parent = RayfireMan.inst.transform; } else { instGo.transform.parent = scr.transForm.parent; } // Set tm scr.rootChild = instGo.transform; // Copy scale if (scr.referenceDemolition.inheritScale == true) { scr.rootChild.localScale = scr.transForm.localScale; } // Clear list for fragments scr.fragments = new List <RayfireRigid>(); // Check root for rigid props RayfireRigid refScr = instGo.gameObject.GetComponent <RayfireRigid>(); // Reference Root has not rigid. Add to if (refScr == null && scr.referenceDemolition.addRigid == true) { // Add rigid and copy refScr = instGo.gameObject.AddComponent <RayfireRigid>(); // Copy rigid scr.CopyPropertiesTo(refScr); // Copy particles RFParticles.CopyParticles(scr, refScr); // Single mesh TODO improve if (instGo.transform.childCount == 0) { refScr.objectType = ObjectType.Mesh; } // Multiple meshes if (instGo.transform.childCount > 0) { refScr.objectType = ObjectType.MeshRoot; } } // Activate and init rigid instGo.transform.gameObject.SetActive(true); // Reference has rigid if (refScr != null) { // Init if not initialized yet refScr.Initialize(); // Create rigid for root children if (refScr.objectType == ObjectType.MeshRoot) { for (int i = 0; i < refScr.fragments.Count; i++) { refScr.fragments[i].limitations.currentDepth++; } scr.fragments.AddRange(refScr.fragments); scr.DestroyRigid(refScr); } // Get ref rigid else if (refScr.objectType == ObjectType.Mesh || refScr.objectType == ObjectType.SkinnedMesh) { refScr.meshDemolition.runtimeCaching.type = CachingType.Disable; RFDemolitionMesh.DemolishMesh(refScr); // TODO COPY MESH DATA FROM ROOTSCR TO THIS TO REUSE scr.fragments.AddRange(refScr.fragments); RayfireMan.DestroyFragment(refScr, refScr.rootParent, 1f); } // Get ref rigid else if (refScr.objectType == ObjectType.NestedCluster || refScr.objectType == ObjectType.ConnectedCluster) { refScr.Default(); // Copy contact data refScr.limitations.contactPoint = scr.limitations.contactPoint; refScr.limitations.contactVector3 = scr.limitations.contactVector3; refScr.limitations.contactNormal = scr.limitations.contactNormal; // Demolish RFDemolitionCluster.DemolishCluster(refScr); // Collect new fragments scr.fragments.AddRange(refScr.fragments); //refScr.physics.exclude = true; //RayfireMan.DestroyFragment (refScr, refScr.rootParent, 1f); } } } return(true); }