コード例 #1
0
 /// <summary>
 /// Creates a capsule collider using the height from first 2 vertices, and then getting radius from the best fit sphere algorithm.
 /// </summary>
 /// <param name="worldVertices">List of world vertices</param>
 /// <param name="properties">Properties of collider</param>
 /// <returns></returns>
 public Collider CreateCapsuleCollider_BestFit(List <Vector3> worldVertices, EasyColliderProperties properties)
 {
     if (worldVertices.Count >= 3)
     {
         if (properties.Orientation == COLLIDER_ORIENTATION.ROTATED)
         {
             GameObject obj = CreateGameObjectOrientation(worldVertices, properties.AttachTo, "Rotated Capsule Collider");
             if (obj != null)
             {
                 properties.AttachTo = obj;
             }
         }
         // use local verts.
         List <Vector3> localVertices = ToLocalVerts(properties.AttachTo.transform, worldVertices);
         // height from first 2 verts selected.
         Vector3 v0     = localVertices[0];
         Vector3 v1     = localVertices[1];
         float   height = Vector3.Distance(v0, v1);
         float   dX     = Mathf.Abs(v1.x - v0.x);
         float   dY     = Mathf.Abs(v1.y - v0.y);
         float   dZ     = Mathf.Abs(v1.z - v0.z);
         localVertices.RemoveAt(1);
         localVertices.RemoveAt(0);
         // radius from best fit sphere of the rest of the vertices.
         BestFitSphere   bfs             = CalculateBestFitSphere(localVertices);
         CapsuleCollider capsuleCollider = Undo.AddComponent <CapsuleCollider>(properties.AttachTo);
         Vector3         center          = bfs.Center;
         if (dX > dY && dX > dZ)
         {
             capsuleCollider.direction = 0;
             center.x = (v1.x + v0.x) / 2;
         }
         else if (dY > dX && dY > dZ)
         {
             capsuleCollider.direction = 1;
             center.y = (v1.y + v0.y) / 2;
         }
         else
         {
             capsuleCollider.direction = 2;
             center.z = (v1.z + v0.z) / 2;
         }
         capsuleCollider.center = center;
         capsuleCollider.height = height;
         capsuleCollider.radius = bfs.Radius;
         SetPropertiesOnCollider(capsuleCollider, properties);
         return(capsuleCollider);
     }
     return(null);
 }
コード例 #2
0
 /// <summary>
 /// Creates a sphere collider using the best fit sphere algorithm.
 /// </summary>
 /// <param name="worldVertices">List of world space vertices</param>
 /// <param name="properties">Properties of collider</param>
 /// <returns></returns>
 public Collider CreateSphereCollider_BestFit(List <Vector3> worldVertices, EasyColliderProperties properties)
 {
     if (worldVertices.Count >= 2)
     {
         // Convert to local space.
         List <Vector3> localVertices  = ToLocalVerts(properties.AttachTo.transform, worldVertices);
         BestFitSphere  bfs            = CalculateBestFitSphere(localVertices);
         SphereCollider sphereCollider = Undo.AddComponent <SphereCollider>(properties.AttachTo);
         sphereCollider.radius = bfs.Radius;
         sphereCollider.center = bfs.Center;
         SetPropertiesOnCollider(sphereCollider, properties);
         return(sphereCollider);
     }
     return(null);
 }
コード例 #3
0
 /// <summary>
 /// Creates a box collider by calculating the min and max x, y, and z.
 /// </summary>
 /// <param name="worldVertices">List of world space vertices</param>
 /// <param name="properties">Properties of collider</param>
 /// <returns></returns>
 public Collider CreateBoxCollider(List <Vector3> worldVertices, EasyColliderProperties properties)
 {
     if (worldVertices.Count >= 2)
     {
         if (properties.Orientation == COLLIDER_ORIENTATION.ROTATED)
         {
             if (worldVertices.Count >= 3)
             {
                 GameObject obj = CreateGameObjectOrientation(worldVertices, properties.AttachTo, "Rotated Box Collider");
                 if (obj != null)
                 {
                     obj.layer           = properties.Layer;
                     properties.AttachTo = obj;
                 }
             }
             else
             {
                 Debug.LogWarning("Easy Collider Editor: Creating a Rotated Box Collider requires at least 3 points to be selected.");
             }
         }
         List <Vector3> localVertices = ToLocalVerts(properties.AttachTo.transform, worldVertices);
         float          xMin, yMin, zMin = xMin = yMin = Mathf.Infinity;
         float          xMax, yMax, zMax = xMax = yMax = -Mathf.Infinity;
         foreach (Vector3 vertex in localVertices)
         {
             //x min & max.
             xMin = (vertex.x < xMin) ? vertex.x : xMin;
             xMax = (vertex.x > xMax) ? vertex.x : xMax;
             //y min & max
             yMin = (vertex.y < yMin) ? vertex.y : yMin;
             yMax = (vertex.y > yMax) ? vertex.y : yMax;
             //z min & max
             zMin = (vertex.z < zMin) ? vertex.z : zMin;
             zMax = (vertex.z > zMax) ? vertex.z : zMax;
         }
         Vector3     max = new Vector3(xMax, yMax, zMax);
         Vector3     min = new Vector3(xMin, yMin, zMin);
         Vector3     size        = max - min;
         Vector3     center      = (max + min) / 2;
         BoxCollider boxCollider = Undo.AddComponent <BoxCollider>(properties.AttachTo);
         boxCollider.size   = size;
         boxCollider.center = center;
         SetPropertiesOnCollider(boxCollider, properties);
         return(boxCollider);
     }
     return(null);
 }
コード例 #4
0
 /// <summary>
 /// Creates a sphere collider by calculating the min and max in x, y, and z.
 /// </summary>
 /// <param name="worldVertices">List of world space vertices</param>
 /// <param name="properties">Properties of collider</param>
 /// <returns></returns>
 public Collider CreateSphereCollider_MinMax(List <Vector3> worldVertices, EasyColliderProperties properties)
 {
     if (worldVertices.Count >= 2)
     {
         // use local space verts.
         List <Vector3> localVertices = ToLocalVerts(properties.AttachTo.transform, worldVertices);
         float          xMin, yMin, zMin = xMin = yMin = Mathf.Infinity;
         float          xMax, yMax, zMax = xMax = yMax = -Mathf.Infinity;
         for (int i = 0; i < localVertices.Count; i++)
         {
             //x min & max.
             xMin = (localVertices[i].x < xMin) ? localVertices[i].x : xMin;
             xMax = (localVertices[i].x > xMax) ? localVertices[i].x : xMax;
             //y min & max
             yMin = (localVertices[i].y < yMin) ? localVertices[i].y : yMin;
             yMax = (localVertices[i].y > yMax) ? localVertices[i].y : yMax;
             //z min & max
             zMin = (localVertices[i].z < zMin) ? localVertices[i].z : zMin;
             zMax = (localVertices[i].z > zMax) ? localVertices[i].z : zMax;
         }
         // calculate center
         Vector3        center         = (new Vector3(xMin, yMin, zMin) + new Vector3(xMax, yMax, zMax)) / 2;
         SphereCollider sphereCollider = Undo.AddComponent <SphereCollider>(properties.AttachTo);
         sphereCollider.center = center;
         // calculate radius to contain all points
         float maxDistance = 0.0f;
         float distance    = 0.0f;
         foreach (Vector3 vertex in localVertices)
         {
             distance = Vector3.Distance(vertex, center);
             if (distance > maxDistance)
             {
                 maxDistance = distance;
             }
         }
         sphereCollider.radius = maxDistance;
         SetPropertiesOnCollider(sphereCollider, properties);
         return(sphereCollider);
     }
     return(null);
 }
コード例 #5
0
 /// <summary>
 /// Sets the collider properties isTrigger and physicMaterial.
 /// </summary>
 /// <param name="collider">Collider to set properties on</param>
 /// <param name="properties">Properties object with the properties you want to set</param>
 private void SetPropertiesOnCollider(Collider collider, EasyColliderProperties properties)
 {
     collider.isTrigger      = properties.IsTrigger;
     collider.sharedMaterial = properties.PhysicMaterial;
 }
コード例 #6
0
        /// <summary>
        /// Creates a capsule collider using the Min-Max method
        /// </summary>
        /// <param name="worldVertices">List of world space vertices</param>
        /// <param name="properties">Properties to set on collider</param>
        /// <param name="method">Min-Max method to use to add radius' to height.</param>
        /// <returns></returns>
        public Collider CreateCapsuleCollider_MinMax(List <Vector3> worldVertices, EasyColliderProperties properties, CAPSULE_COLLIDER_METHOD method)
        {
            if (properties.Orientation == COLLIDER_ORIENTATION.ROTATED)
            {
                GameObject obj = CreateGameObjectOrientation(worldVertices, properties.AttachTo, "Rotated Capsule Collider");
                if (obj != null)
                {
                    properties.AttachTo = obj;
                }
            }
            List <Vector3> localVertices = ToLocalVerts(properties.AttachTo.transform, worldVertices);

            // calculate min and max points from vertices.
            Vector3 min = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);
            Vector3 max = new Vector3(-Mathf.Infinity, -Mathf.Infinity, -Mathf.Infinity);

            foreach (Vector3 vertex in localVertices)
            {
                // Calc minimums
                min.x = vertex.x < min.x ? vertex.x : min.x;
                min.y = vertex.y < min.y ? vertex.y : min.y;
                min.z = vertex.z < min.z ? vertex.z : min.z;
                // Calc maximums
                max.x = vertex.x > max.x ? vertex.x : max.x;
                max.y = vertex.y > max.y ? vertex.y : max.y;
                max.z = vertex.z > max.z ? vertex.z : max.z;
            }
            // Deltas for max-min
            float           dX = max.x - min.x;
            float           dY = max.y - min.y;
            float           dZ = max.z - min.z;
            CapsuleCollider capsuleCollider = Undo.AddComponent <CapsuleCollider>(properties.AttachTo);
            // center is between min and max values.
            Vector3 center = (max + min) / 2;

            // set center.
            capsuleCollider.center = center;
            // set direction and height.
            if (dX > dY && dX > dZ) // direction is x
            {
                capsuleCollider.direction = 0;
                // height is the max difference in x.
                capsuleCollider.height = dX;
            }
            else if (dY > dX && dY > dZ) // direction is y
            {
                capsuleCollider.direction = 1;
                capsuleCollider.height    = dY;
            }
            else // direction is z.
            {
                capsuleCollider.direction = 2;
                capsuleCollider.height    = dZ;
            }

            // Calculate radius, makes sure that all vertices are within the radius.
            // Esentially to points on plane defined by direction axis, and find the furthest distance.
            float   maxRadius = -Mathf.Infinity;
            Vector3 current   = Vector3.zero;

            foreach (Vector3 vertex in localVertices)
            {
                current = vertex;
                if (capsuleCollider.direction == 0)
                {
                    current.x = center.x;
                }
                else if (capsuleCollider.direction == 1)
                {
                    current.y = center.y;
                }
                else if (capsuleCollider.direction == 2)
                {
                    current.z = center.z;
                }
                float d = Vector3.Distance(current, center);
                if (d > maxRadius)
                {
                    maxRadius = d;
                }
            }
            capsuleCollider.radius = maxRadius;
            // method add radius / diameter
            if (method == CAPSULE_COLLIDER_METHOD.MinMaxPlusRadius)
            {
                capsuleCollider.height += capsuleCollider.radius;
            }
            else if (method == CAPSULE_COLLIDER_METHOD.MinMaxPlusDiameter)
            {
                capsuleCollider.height += capsuleCollider.radius * 2;
            }
            // set properties
            SetPropertiesOnCollider(capsuleCollider, properties);
            return(capsuleCollider);
        }
コード例 #7
0
        /// <summary>
        /// Creates a Sphere Collider by finding the 2 points with a maximum distance between them.
        /// </summary>
        /// <param name="worldVertices">List of world space vertices</param>
        /// <param name="properties">Properties of collider</param>
        /// <returns></returns>
        public Collider CreateSphereCollider_Distance(List <Vector3> worldVertices, EasyColliderProperties properties)
        {
            // with how min-max works, i dont think this is needed.
            // Future work: instead of switching to faster algorithm
            // calculating the convex hull from the list of points, and then using those points is nlogn
            // whereas our slow algorithm is n^2, and the fast one is n.
            if (worldVertices.Count >= 2)
            {
                // // if calculations take to long, it switches to a faster less accurate algorithm using the mean.
                bool           switchToFasterAlgorithm = false;
                double         startTime     = EditorApplication.timeSinceStartup;
                double         maxTime       = 0.1f;
                List <Vector3> localVertices = ToLocalVerts(properties.AttachTo.transform, worldVertices);
                Vector3        distanceVert1 = Vector3.zero;
                Vector3        distanceVert2 = Vector3.zero;
                float          maxDistance   = -Mathf.Infinity;
                float          distance      = 0;
                for (int i = 0; i < localVertices.Count; i++)
                {
                    for (int j = i + 1; j < localVertices.Count; j++)
                    {
                        distance = Vector3.Distance(localVertices[i], localVertices[j]);
                        if (distance > maxDistance)
                        {
                            maxDistance   = distance;
                            distanceVert1 = localVertices[i];
                            distanceVert2 = localVertices[j];
                        }
                    }
                    if (EditorApplication.timeSinceStartup - startTime > maxTime)
                    {
                        switchToFasterAlgorithm = true;
                        break;
                    }
                }

                if (switchToFasterAlgorithm)
                {
                    // use a significantly faster algorithm that is less accurate for a large # of points.
                    Vector3 mean = Vector3.zero;
                    foreach (Vector3 vertex in localVertices)
                    {
                        mean += vertex;
                    }
                    mean = mean / localVertices.Count;
                    foreach (Vector3 vertex in localVertices)
                    {
                        distance = Vector3.Distance(vertex, mean);
                        if (distance > maxDistance)
                        {
                            distanceVert1 = vertex;
                            maxDistance   = distance;
                        }
                    }
                    maxDistance = -Mathf.Infinity;
                    foreach (Vector3 vertex in localVertices)
                    {
                        distance = Vector3.Distance(vertex, distanceVert1);
                        if (distance > maxDistance)
                        {
                            maxDistance   = distance;
                            distanceVert2 = vertex;
                        }
                    }
                }

                Vector3        center         = (distanceVert1 + distanceVert2) / 2;
                SphereCollider sphereCollider = Undo.AddComponent <SphereCollider>(properties.AttachTo);
                sphereCollider.radius = maxDistance / 2;
                sphereCollider.center = center;
                SetPropertiesOnCollider(sphereCollider, properties);
                return(sphereCollider);
            }
            return(null);
        }