예제 #1
0
    void InitSpatialGrid()
    {
        spatialGrid = new List <GameObject> [flyingSpace, flyingSpace, flyingSpace];
        for (int i = 0; i < numBoids; i++)
        {
            //initialize spatial grid again.
            //if its null at hash make a list at the voxel.
            currBoid = boidList[i].GetComponent <boids>();
            position = currBoid.transform.position;

            //if boid position outside of limits, kill and reinitialize
            if (position.x < 0.0f || position.x > flyingSpace ||
                position.y < 0.0f || position.y > flyingSpace ||
                position.z < 0.0f || position.z > flyingSpace)
            {
                position = new Vector3
                               (Random.Range(0.0f + flyingSpace / 8, flyingSpace - flyingSpace / 8),
                               Random.Range(0.0f + flyingSpace / 8, flyingSpace - flyingSpace / 8),
                               Random.Range(0.0f + flyingSpace / 8, flyingSpace - flyingSpace / 8));
                //  calculateMedianPoint();
                Destroy(boidList[i]);
                boidList[i] = Instantiate(boidPrefab, position, Quaternion.identity);
            }

            if (spatialGrid[(int)Mathf.Floor(position.x), (int)Mathf.Floor(position.y), (int)Mathf.Floor(position.z)] == null)
            {
                spatialGrid[(int)Mathf.Floor(position.x),
                            (int)Mathf.Floor(position.y),
                            (int)Mathf.Floor(position.z)] = new List <GameObject>();
            }

            spatialGrid[(int)Mathf.Floor(position.x),
                        (int)Mathf.Floor(position.y),
                        (int)Mathf.Floor(position.z)].Add(boidList[i]);
        }
    }
예제 #2
0
    //Update called once per update
    void UpdateBoidPositions()
    {
        for (int i = 0; i < flyingSpace; i++)
        {
            for (int j = 0; j < flyingSpace; j++)
            {
                for (int k = 0; k < flyingSpace; k++)
                {
                    if (spatialGrid[i, j, k] != null)
                    {
                        //for each boid in list at voxel
                        int count = spatialGrid[i, j, k].Count;
                        for (int boidInVoxelList = 0; boidInVoxelList < count; boidInVoxelList++)
                        {
                            currBoid = spatialGrid[i, j, k][boidInVoxelList].GetComponent <boids>();

                            //create interaction list
                            //everything in this voxel can be added
                            // interactionList.AddRange(spatialGrid[i, j, k]); //plus everything that is one voxel away on all sides

                            //this will add 27 boxes if 3x3x3 or greater. otherwise will add all 8.
                            for (int n = i - 1; n <= i + 1; n++)
                            {
                                //if its less than 0 we dont want that
                                if (n < 0)
                                {
                                    continue;
                                }
                                if (n >= flyingSpace)
                                {
                                    continue;
                                }
                                for (int p = j - 1; p <= j + 1; p++)
                                {
                                    if (p < 0)
                                    {
                                        continue;
                                    }
                                    if (p >= flyingSpace)
                                    {
                                        continue;
                                    }
                                    for (int q = k - 1; q <= k + 1; q++)
                                    {
                                        if (q < 0)
                                        {
                                            continue;
                                        }
                                        if (q >= flyingSpace)
                                        {
                                            continue;
                                        }
                                        // Debug.Log("Would be adding boids from voxel [" + n + "," + p + "," + q + "]. /n/n");


                                        if (spatialGrid[n, p, q] != null)
                                        {
                                            interactionList.AddRange(spatialGrid[n, p, q]);
                                        }
                                    }
                                }
                            }

                            Vector3 ourBoidPosition = spatialGrid[i, j, k][boidInVoxelList].transform.position;

                            //now we have interaction list with our ijk boid. iterate thru each in list and add up accelerations
                            int interactionCount = interactionList.Count;
                            for (int r = 0; r < interactionCount; r++)
                            {
                                if (interactionList[r].GetInstanceID() != currBoid.GetInstanceID())
                                {
                                    boids otherBoid = interactionList[r].GetComponent <boids>();

                                    //compute distance between our boid and the boid from the interaction list
                                    distance = interactionList[r].transform.position - ourBoidPosition;

                                    //compute ktheta
                                    thetaOne       = currBoid.GetThetaOne();
                                    thetaTwo       = currBoid.GetThetaTwo();
                                    thetaMagnitude = Vector3.Angle(currBoid.getVelocity(), otherBoid.transform.position);

                                    if ((-thetaOne / 2 <= thetaMagnitude) && thetaMagnitude <= thetaOne / 2)
                                    {
                                        ktheta = 1.0f;
                                    }
                                    else if (((thetaOne / 2) <= thetaMagnitude) && (thetaMagnitude <= (thetaTwo / 2)))
                                    {
                                        ktheta = ((thetaTwo / 2) - thetaMagnitude) / ((thetaTwo / 2) - (thetaOne / 2));
                                    }
                                    else
                                    {
                                        ktheta = 0.0f;
                                    }

                                    //compute kd
                                    if (distance.magnitude < r1)
                                    {
                                        kd = 1.0f;
                                    }
                                    else if ((r1 <= distance.magnitude) && (distance.magnitude <= r2))
                                    {
                                        kd = (r2 - distance.magnitude) / (r2 - r1);
                                    }
                                    else
                                    {
                                        kd = 0.0f;
                                    }

                                    //pg 107 from House and Keyser's text
                                    collision     += ktheta * kd * (-1.0f * (kCollisionScale / (distance.magnitude + 0.01f)) * distance.normalized);
                                    velocityMatch += ktheta * kd * (kVelocityScale * (otherBoid.getVelocity() - currBoid.getVelocity()));
                                    centering     += ktheta * kd * kCenteringScale * distance;
                                }
                            }

                            //prioritizing acceleration source (pg 108)
                            float ar = accelerationCap;
                            combinedAcceleration = Mathf.Min(ar, collision.magnitude) * collision.normalized;
                            ar = accelerationCap - combinedAcceleration.magnitude;
                            combinedAcceleration = combinedAcceleration + Mathf.Min(ar, velocityMatch.magnitude) * velocityMatch.normalized;
                            ar = accelerationCap - combinedAcceleration.magnitude;
                            combinedAcceleration = combinedAcceleration + Mathf.Min(ar, centering.magnitude) * centering.normalized;

                            //check walls. r2 is the far distance used in calculating kd

                            //check if our boid is nearing where X = 0
                            if (ourBoidPosition.x < (3 * flyingSpace / 7))
                            {
                                combinedAcceleration.x += accelerationCap / 2;
                            }

                            //check if our boid is nearing where X = max X bound
                            else if ((flyingSpace - ourBoidPosition.x) < 3 * flyingSpace / 7)
                            {
                                combinedAcceleration.x += -accelerationCap / 2;
                            }

                            //so if acceleration = 0 then reversing doesnt work
                            //check if our boid is nearing bound where Y = 0
                            if ((ourBoidPosition.y) < 3 * flyingSpace / 7)
                            {
                                combinedAcceleration.y += accelerationCap / 2;
                            }

                            //check if our boid is nearing where Y = max Y bound
                            else if ((flyingSpace - ourBoidPosition.y) < 3 * flyingSpace / 7)
                            {
                                combinedAcceleration.y -= accelerationCap / 2;
                            }

                            //check if our boid is nearing where Z = 0
                            if ((ourBoidPosition.z) < 3 * flyingSpace / 7)
                            {
                                combinedAcceleration.z += accelerationCap / 2;
                            }

                            //check if our boid is nearing where Z = max Z bound
                            else if ((flyingSpace - ourBoidPosition.z) < 3 * flyingSpace / 7)
                            {
                                combinedAcceleration.z += -accelerationCap / 2;
                            }

                            currBoid.setVelocity(combinedAcceleration * Time.deltaTime + currBoid.getVelocity());

                            //update position
                            temp = ourBoidPosition;
                            spatialGrid[i, j, k][boidInVoxelList].transform.position =
                                (2.0f * ourBoidPosition) - currBoid.getOldPosition() + ((Time.deltaTime * Time.deltaTime) * (combinedAcceleration));
                            currBoid.setOldPosition(temp);
                            interactionList.Clear();
                        }
                    }
                }
            }
        }
        System.Array.Clear(spatialGrid, 0, spatialGrid.GetLength(0) * spatialGrid.GetLength(1) * spatialGrid.GetLength(2));
    }
 // Start is called before the first frame update
 void Start()
 {
     boid = GetComponent <boids>();
 }