Esempio n. 1
0
        /// /////////////////////////////////////////////////////////
        /// Methods
        /// /////////////////////////////////////////////////////////

        // Add solo shards to closest cluster
        void SetSoloShardToCluster(List <RFShard> soloShards, List <RFCluster> childClusters)
        {
            // No solo shards
            if (soloShards.Count == 0)
            {
                return;
            }

            // Find neib cluster for solo shards
            for (int i = soloShards.Count - 1; i >= 0; i--)
            {
                int ind = soloShards[i].GetNeibIndArea();
                if (ind >= 0)
                {
                    RFShard neibShard = soloShards[i].neibShards[ind];
                    for (int c = 0; c < childClusters.Count; c++)
                    {
                        if (childClusters[c].shards.Contains(neibShard) == true)
                        {
                            childClusters[c].shards.Add(soloShards[i]);
                            soloShards.RemoveAt(i);
                            continue;
                        }
                    }
                }
            }
        }
        // Prepare shards. Set bounds, set neibs
        static void SetShardsByRigids(RFCluster cluster, List <RayfireRigid> rigidList, ConnectivityType connectivity)
        {
            for (int i = 0; i < rigidList.Count; i++)
            {
                // Get mesh filter
                MeshFilter mf = rigidList[i].GetComponent <MeshFilter>();

                // Child has no mesh
                if (mf == null)
                {
                    continue;
                }

                // Create new shard
                RFShard shard = new RFShard(rigidList[i].transform, i);
                shard.cluster = cluster;
                shard.rigid   = rigidList[i];
                shard.uny     = rigidList[i].activation.unyielding;
                shard.col     = rigidList[i].physics.meshCollider;

                // Set faces data for connectivity
                if (connectivity == ConnectivityType.ByMesh)
                {
                    RFTriangle.SetTriangles(shard, mf);
                }

                // Collect shard
                cluster.shards.Add(shard);
            }
        }
Esempio n. 3
0
        // Set up main cluster and set shards
        RFCluster SetupMainCluster(ConnectivityType connect)
        {
            // Create Base cluster
            RFCluster cluster = new RFCluster();

            cluster.tm    = transform;
            cluster.depth = 0;
            cluster.pos   = transform.position;

            // Set cluster id
            cluster.id = 0;

            // Set shards for main cluster
            RFShard.SetShards(cluster, connectivity);

            clusterId = 0;

            // Collect all shards
            allShards.Clear();
            allShards.AddRange(cluster.shards);

            // TODO set bound

            return(cluster);
        }
Esempio n. 4
0
 // Clear
 public static void Clear(RFShard shard)
 {
     if (shard.tris != null)
     {
         shard.tris.Clear();
     }
     shard.tris = null;
 }
Esempio n. 5
0
        // Set cluster
        void SetCluster()
        {
            cluster = new RFCluster();

            // Set shards for main cluster
            cluster.shards = RFShard.GetShards(rigidList, connectivityType);

            // Set shard neibs
            RFShard.SetShardNeibs(cluster.shards, connectivityType);
        }
Esempio n. 6
0
        /// /////////////////////////////////////////////////////////
        /// Collider
        /// /////////////////////////////////////////////////////////

        // Create base cluster with children as shards
        public static RFCluster SetCluster(Transform transform, ConnectivityType connectivity)
        {
            // Create Base cluster
            RFCluster cluster = new RFCluster();

            cluster.tm         = transform;
            cluster.rootParent = null;
            cluster.depth      = 0;
            cluster.pos        = transform.position;

            // Set cluster id
            cluster.id = 0;

            // Set shards for main cluster
            cluster.shards = RFShard.GetShards(cluster.tm, connectivity);

            return(cluster);
        }
Esempio n. 7
0
        // Reset local shard rigid, destroy components
        static void ResetShardRigid(RFShard shard)
        {
            shard.rigid = shard.tm.GetComponent <RayfireRigid>();

            if (shard.rigid != null)
            {
                // Destroy rigid body
                if (shard.rigid.physics.rigidBody != null)
                {
                    shard.rigid.physics.rigidBody.velocity = Vector3.zero;
                    Object.Destroy(shard.rigid.physics.rigidBody);
                }

                // TODO TEMP SOLUTION, DESTROY ALL DEBRIS AS WELL
                if (shard.rigid.HasDebris || shard.rigid.HasDust)
                {
                    for (int c = shard.tm.childCount - 1; c >= 0; c--)
                    {
                        Object.Destroy(shard.tm.GetChild(c).gameObject);
                    }
                }

                Object.Destroy(shard.rigid);


                // shard.rigid.gameObject.SetActive (false);

                // Stop cors
                // shard.rigid.StopAllCoroutines();

                // shard.rigid.debrisList = null;
                // shard.rigid.dustList   = null;
                //
                // // Reset Rigid
                // shard.rigid.ResetRigid();
                //
                // // Destroy rigid component
                // if (shard.rigid.reset.shards == RFReset.ShardsResetType.DestroyRigid)
                //
                // else
                //     shard.rigid.initialization = RayfireRigid.InitType.ByMethod;
                // shard.rigid.gameObject.SetActive (true);
            }
        }
        // Set cluster
        void SetCluster(List <Transform> tmList)
        {
            // In case of runtime add
            if (cluster == null)
            {
                cluster = new RFCluster();
            }

            // Main cluster cached, reinit non serialized vars
            if (cluster.shards.Count > 0)
            {
                InitShards(rigidList, cluster);
            }

            // Create main cluster
            if (cluster.shards.Count == 0)
            {
                cluster              = new RFCluster();
                cluster.id           = RFCluster.GetUniqClusterId(cluster);
                cluster.tm           = transform;
                cluster.depth        = 0;
                cluster.pos          = transform.position;
                cluster.initialized  = true;
                cluster.demolishable = demolishable;

                // Set shards for main cluster
                if (Application.isPlaying == true)
                {
                    SetShardsByRigids(cluster, rigidList, type);
                }
                else
                {
                    RFShard.SetShardsByTransforms(cluster, tmList, type);
                }

                // Set shard neibs
                RFShard.SetShardNeibs(cluster.shards, type, minimumArea, minimumSize, percentage, seed);

                // Set range for area and size
                RFCollapse.SetRangeData(cluster, percentage, seed);

                // Debug.Log ("SetCluster" + rigidList.Count);
            }
        }
Esempio n. 9
0
        // Create one cluster which includes only children meshes, not children of children meshes.
        static bool ClusterizeConnected(RayfireRigid scr)
        {
            // Setup cluster and shard if first time. Do not if copied from parent
            if (scr.clusterDemolition.cluster == null || scr.clusterDemolition.cluster.id == 0)
            {
                // Set cluster
                scr.clusterDemolition.cluster    = RFCluster.SetCluster(scr.transForm, scr.clusterDemolition.connectivity);
                scr.clusterDemolition.cluster.id = 1;

                // Set shard neibs
                RFShard.SetShardNeibs(scr.clusterDemolition.cluster.shards, scr.clusterDemolition.connectivity);
            }

            // Get all children meshes
            List <MeshFilter> childMeshes = new List <MeshFilter>();

            for (int i = 0; i < scr.transForm.childCount; i++)
            {
                MeshFilter mf = scr.transForm.GetChild(i).GetComponent <MeshFilter>();
                if (mf != null)
                {
                    childMeshes.Add(mf);
                }
            }

            // No meshes in children
            if (childMeshes.Count == 0)
            {
                return(false);
            }

            // float t1 = Time.realtimeSinceStartup;

            // Create mesh colliders for every input mesh and collect
            RFPhysic.SetClusterColliders(scr, childMeshes.ToArray());

            // TODO connectivity check to find solo shards and make sure they are not connected

            return(true);
        }
Esempio n. 10
0
        // Set mesh triangles
        public static void SetTriangles(RFShard shard, MeshFilter mf)
        {
            // Check if triangles already calculated
            if (shard.tris != null)
            {
                //Debug.Log (" no calc tris");
                return;
            }

            //Debug.Log ("calc tris");

            // Cached Vars
            int[]     triangles = mf.sharedMesh.triangles;
            Vector3[] vertices  = mf.sharedMesh.vertices;

            // Collect tris
            int     i1, i2, i3;
            Vector3 v1, v2, v3, cross, pos;

            shard.tris = new List <RFTriangle>();
            for (int i = 0; i < triangles.Length; i += 3)
            {
                // Vertex indexes
                i1 = triangles[i];
                i2 = triangles[i + 1];
                i3 = triangles[i + 2];

                // Get vertices position and area
                v1    = shard.tm.TransformPoint(vertices[i1]);
                v2    = shard.tm.TransformPoint(vertices[i2]);
                v3    = shard.tm.TransformPoint(vertices[i3]);
                cross = Vector3.Cross(v1 - v2, v1 - v3);

                // Set position
                pos = (v1 + v2 + v3) / 3f;

                // Create triangle and collect it
                shard.tris.Add(new RFTriangle(i / 3, (cross.magnitude * 0.5f), mf.sharedMesh.normals[i1], pos));
            }
        }
Esempio n. 11
0
        /// /////////////////////////////////////////////////////////
        /// Connectivity
        /// /////////////////////////////////////////////////////////

        // Connectivity check
        public static void ConnectivityUnyCheck(RFCluster cluster)
        {
            // Set up child cluster
            if (cluster.childClusters != null)
            {
                cluster.childClusters.Clear();
            }

            // Not enough shards to check for connectivity
            if (cluster.shards.Count <= 1)
            {
                return;
            }

            // Check all shards and collect new clusters
            int shardsAmount = cluster.shards.Count;

            // Check all shards for connectivity but keep uny clusters in main cluster
            List <int>     checkedShardsIds = new List <int>();
            List <RFShard> checkShards      = new List <RFShard>();
            List <RFShard> newClusterShards = new List <RFShard>();

            for (int s = cluster.shards.Count - 1; s >= 0; s--)
            {
                // Skip checked shards
                if (checkedShardsIds.Contains(cluster.shards[s].id) == true)
                {
                    continue;
                }

                // Collect
                checkedShardsIds.Add(cluster.shards[s].id);

                // New possible cluster. Create new bacouse applied to cluster
                newClusterShards.Clear();
                newClusterShards.Add(cluster.shards[s]);

                // Shards in possible connection
                checkShards.Clear();
                checkShards.Add(cluster.shards[s]);

                // Collect by neibs
                while (checkShards.Count > 0)
                {
                    // Add neibs to check If neib among current cluster shards And not already collected
                    for (int n = 0; n < checkShards[0].neibShards.Count; n++)
                    {
                        if (newClusterShards.Contains(checkShards[0].neibShards[n]) == false)
                        {
                            checkShards.Add(checkShards[0].neibShards[n]);
                            newClusterShards.Add(checkShards[0].neibShards[n]);
                            checkedShardsIds.Add(checkShards[0].neibShards[n].id);
                        }
                    }

                    // Remove checked
                    checkShards.RemoveAt(0);
                }

                // Child cluster connected
                if (shardsAmount == newClusterShards.Count)
                {
                    break;
                }

                // Start over if connected shards has uny
                if (RFShard.UnyieldingByShard(newClusterShards) == true)
                {
                    continue;
                }

                // Child cluster not connected. Create new cluster and add to parent
                RFCluster newCluster = new RFCluster();
                for (int i = 0; i < newClusterShards.Count; i++)
                {
                    newCluster.shards.Add(newClusterShards[i]);
                }
                newCluster.demolishable = cluster.demolishable;

                // Set main cluster
                if (cluster.mainCluster == null)
                {
                    newCluster.mainCluster = cluster;
                }
                else
                {
                    newCluster.mainCluster = cluster.mainCluster;
                }

                // Set uniq id after main cluster defined
                newCluster.id = GetUniqClusterId(newCluster);

                // Set shards cluster to new cluster
                for (int i = 0; i < newCluster.shards.Count; i++)
                {
                    newCluster.shards[i].cluster = newCluster;
                }

                // Set up child cluster
                if (cluster.childClusters == null)
                {
                    cluster.childClusters = new List <RFCluster>();
                }
                cluster.childClusters.Add(newCluster);
            }

            // Remove new child clusters shards from original cluster shards list before repeat while cycle
            if (cluster.childClusters != null && cluster.childClusters.Count > 0)
            {
                for (int i = cluster.shards.Count - 1; i >= 0; i--)
                {
                    if (cluster.shards[i].cluster != cluster)
                    {
                        cluster.shards.RemoveAt(i);
                    }
                }
            }

            checkedShardsIds.Clear();

            // No uny shards in cluster
            if (cluster.shards.Count == 0)
            {
                // Cluster is not connected. If not main cluster then set biggest child cluster shards to original cluster.
                ReduceChildClusters(cluster);
            }
        }
Esempio n. 12
0
        // Check for connectivity
        public void CheckConnectivity()
        {
            // Do once
            checkNeed = false;

            // Clear all activated/demolished shards
            CleanUpActivatedShards(cluster);

            // No shards to check
            if (cluster.shards.Count == 0)
            {
                return;
            }

            // Reinit neibs after cleaning
            RFShard.ReinitNeibs(cluster.shards);

            // List of shards to be activated
            List <RFShard> soloShards = new List <RFShard>();

            // TODO do not collect solo uny shards
            // Check for solo shards and collect
            RFCluster.GetSoloShards(cluster, soloShards);

            // Reinit neibs before connectivity check
            RFShard.ReinitNeibs(cluster.shards);

            // Connectivity check
            RFCluster.ConnectivityCheck(cluster);

            // Get not connected and not unyielding child cluster
            CheckUnyielding(cluster);

            // TODO ONE NEIB DETACH FOR CHILD CLUSTERS

            // Activate not connected shards.
            if (soloShards.Count > 0)
            {
                for (int i = 0; i < soloShards.Count; i++)
                {
                    soloShards[i].rigid.Activate();
                }
            }

            // Clusterize childClusters  or activate their shards
            if (cluster.HasChildClusters == true)
            {
                if (clusterize == true)
                {
                    Clusterize();
                }
                else
                {
                    for (int c = 0; c < cluster.childClusters.Count; c++)
                    {
                        for (int s = 0; s < cluster.childClusters[c].shards.Count; s++)
                        {
                            cluster.childClusters[c].shards[s].rigid.Activate();
                        }
                    }
                }
            }

            // Stop checking. Everything activated
            if (cluster.shards.Count == 0)
            {
                checkConnectivity = false;
            }
        }
Esempio n. 13
0
        // Base clustering pass for shards
        List <RFCluster> ClusterizeRangeShards(RFCluster mainCluster)
        {
            // Empty list of all new cluster roots
            List <RFShard> soloShards = new List <RFShard>();

            // List with all clusters
            List <RFCluster> childClusters = new List <RFCluster>();

            // Sort from smallest to biggest
            mainCluster.shards.Sort();

            // Clusterize starting from biggest
            while (mainCluster.shards.Count > 0)
            {
                // Local amount of shards in cluster
                int shardsAmount = Random.Range(minimumAmount, maximumAmount);

                // Start from biggest shard
                RFShard startShard = mainCluster.shards[0];

                // Remove from lists
                mainCluster.shards.RemoveAt(0);

                // Starting shard list
                List <RFShard> shardGroup = new List <RFShard>();
                shardGroup.Add(startShard);

                // Find neibs
                for (int s = 0; s < shardsAmount - 1; s++)
                {
                    // Get neib shard among cluster.shards with biggest shared area
                    RFShard biggestShard = RFShard.GetNeibShardArea(shardGroup, mainCluster.shards);

                    // No neib with shared area
                    if (biggestShard == null)
                    {
                        break;
                    }

                    // TODO check if area is much smaller than with another neibs. Set as solo

                    // Add in group
                    shardGroup.Add(biggestShard);

                    // Remove from cluster.shards
                    mainCluster.shards.RemoveAll(t => t.id == biggestShard.id);
                }

                // Solo shard
                if (shardGroup.Count == 1)
                {
                    soloShards.Add(startShard);
                }

                // Group of shards for cluster
                else if (shardGroup.Count > 1)
                {
                    // Clusterize with picked shard
                    RFCluster childCluster = new RFCluster();
                    childCluster.shards.AddRange(shardGroup);
                    childCluster.depth = 1;

                    // Set id
                    clusterId++;
                    childCluster.id = clusterId;

                    // Collect luster
                    childClusters.Add(childCluster);
                    mainCluster.childClusters.Add(childCluster);
                }
            }

            // First pass Find neib cluster for solo shards
            SetSoloShardToCluster(soloShards, childClusters);

            // Second pass Find neib cluster for solo shards
            SetSoloShardToCluster(soloShards, childClusters);

            // Roughness pass. Remove shards from cluster and add to another.
            if (smoothPass > 0)
            {
                for (int i = 0; i < smoothPass; i++)
                {
                    RoughnessPassShards(childClusters);
                }
            }

            // TODO consider solo amount

            // Set id
            int startId = 1;

            for (int i = 0; i < childClusters.Count; i++)
            {
                childClusters[i].id = startId + i;
            }

            // Set main cluster solo shards back to main cluster
            mainCluster.shards.Clear();
            mainCluster.shards.AddRange(soloShards);

            return(childClusters);
        }
Esempio n. 14
0
        /// /////////////////////////////////////////////////////////
        /// By range
        /// /////////////////////////////////////////////////////////

        // Second clustering type
        void ClusterizeRange()
        {
            if (type == ClusterType.BySharedArea)
            {
                Random.InitState(seed);

                // Create Base cluster and collect
                RFCluster mainCluster = SetupMainCluster(ConnectivityType.ByMesh);
                allClusters.Add(mainCluster);

                // Set shard neibs
                RFShard.SetShardNeibs(mainCluster.shards, ConnectivityType.ByMesh);

                // Clusterize base shards to clusters
                List <RFCluster> childClusters = ClusterizeRangeShards(mainCluster);

                // Create root and set shards and children
                foreach (RFCluster childCluster in childClusters)
                {
                    CreateRoot(childCluster, transform);
                }

                // Add to all clusters
                allClusters.AddRange(childClusters);

                // Clusterize clusters in depth
                if (depth > 1)
                {
                    for (int i = 1; i < depth; i++)
                    {
                        // Set clusters neib info
                        RFCluster.SetClusterNeib(mainCluster.childClusters, true);

                        // Get new depth clusters
                        List <RFCluster> newClusters = ClusterizeRangeClusters(mainCluster);

                        if (newClusters.Count > 1)
                        {
                            // Create root for all new clusters and set as parent for them
                            foreach (RFCluster cls in newClusters)
                            {
                                CreateRoot(cls, mainCluster.tm);
                                foreach (RFCluster childCLuster in cls.childClusters)
                                {
                                    childCLuster.tm.parent = cls.tm;
                                }
                            }

                            // Set as child cluster for main cluster to be clusterized at next pass
                            mainCluster.childClusters = newClusters;

                            // Add to all clusters
                            allClusters.AddRange(newClusters);

                            // Get all nested clusters and increment depth
                            foreach (RFCluster cls in allClusters)
                            {
                                if (cls.id != 0)
                                {
                                    cls.depth += 1;
                                }
                            }
                        }
                    }
                }

                // Set name to roots
                SetClusterNames();
            }
        }
Esempio n. 15
0
        /// /////////////////////////////////////////////////////////
        /// Voronoi
        /// /////////////////////////////////////////////////////////

        // Clusterize by Voronoi pc
        void ClusterizeVoronoi()
        {
            if (type == ClusterType.ByPointCloud)
            {
                // Create Base cluster
                RFCluster mainCluster = SetupMainCluster(connectivity);

                // Base amount of clusters is more than shards amount
                if (baseAmount >= mainCluster.shards.Count)
                {
                    return;
                }

                // Set shard neibs
                RFShard.SetShardNeibs(mainCluster.shards, connectivity);

                // List with all clusters
                List <RFCluster> clusters = new List <RFCluster> {
                    mainCluster
                };

                // Collect base cluster
                allClusters.Add(mainCluster);

                // Clusterize
                while (clusters.Count > 0)
                {
                    // Get local cluster
                    RFCluster cls = clusters[0];

                    // Remove current cluster from clustering list
                    clusters.RemoveAt(0);

                    // Low amount of shards
                    if (cls.shards.Count < 4)
                    {
                        continue;
                    }

                    // Get amount
                    int amount = baseAmount;
                    if (cls.depth > 0)
                    {
                        amount = depthAmount;
                    }

                    // Get local depth roots
                    cls.childClusters = ClusterizeClusterByAmount(cls, amount);

                    // Collect new clusters
                    allClusters.AddRange(cls.childClusters);

                    // Check if local cluster should be clusterized further and add to list
                    if (cls.childClusters.Count > 0 && depth > cls.depth + 1)
                    {
                        clusters.AddRange(cls.childClusters);
                    }
                }

                // Set name to roots
                SetClusterNames();
            }
        }