• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Finnigan · Nov 20, 2014 at 02:06 PM · spherebounds

Smallest bounding sphere

I need to set a sphere collider for a diamond-shape model. When I add the component the sphere doesn't cover the entire shape. With the next code I manage to set the center and radius of the sphere based on the mesh center and extents magnitude:

 Bounds meshBounds = piece.GetComponent<MeshFilter>().mesh.bounds;
 sphereCollider.center = meshBounds.center;
 sphereCollider.radius = meshBounds.extents.magnitude;

However, it ends up covering more than necessary. Something to consider is that the pivot point of the Model is not centered, and the original rotation of the model may be in an almost random direction. Here's a graphical example:

alt text

consulta.jpg (100.9 kB)
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MrSoad · Nov 20, 2014 at 02:06 PM 0
Share

If you are going to turn this into a prefab for use later then you can offset and scale the collider in the inspector window, much easier to get precise than using code. You could then use these values later if you do need to create this at run time.

avatar image Finnigan · Nov 20, 2014 at 02:09 PM 0
Share

This is a fragment of a much more complex figure (that contains around 50 different shapes, this is one of them). Each fragment must have a sphere collider, therefore I really need to do it automatically.

2 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by Bunny83 · Nov 20, 2014 at 03:34 PM

There is no easy solution to this problem. See Bounding Sphere for possible solutions / approximations.

edit
I found this implementation of Ritter's algorithm and just ported it to C# / Unity:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public struct BoundingSphere
 {
     public Vector3 center;
     public float radius;
     public BoundingSphere(Vector3 aCenter, float aRadius)
     {
         center = aCenter;
         radius = aRadius;
     }
 
     public static BoundingSphere Calculate(IEnumerable<Vector3> aPoints)
     {
         Vector3 xmin, xmax, ymin, ymax, zmin, zmax;
         xmin = ymin = zmin = Vector3.one * float.PositiveInfinity;
         xmax = ymax = zmax = Vector3.one * float.NegativeInfinity;
         foreach(var p in aPoints)
         {
             if(p.x < xmin.x) xmin = p;
             if(p.x > xmax.x) xmax = p;
             if(p.y < ymin.y) ymin = p;
             if(p.y > ymax.y) ymax = p;
             if(p.z < zmin.z) zmin = p;
             if(p.z > zmax.z) zmax = p;
         }
         var xSpan = (xmax - xmin).sqrMagnitude;
         var ySpan = (ymax - ymin).sqrMagnitude;
         var zSpan = (zmax - zmin).sqrMagnitude;
         var dia1 = xmin;
         var dia2 = xmax;
         var maxSpan = xSpan;
         if (ySpan > maxSpan)
         {
             maxSpan = ySpan;
             dia1 = ymin; dia2 = ymax;
         }
         if (zSpan > maxSpan)
         {
             dia1 = zmin; dia2 = zmax;
         }
         var center = (dia1 + dia2) * 0.5f;
         var sqRad = (dia2 - center).sqrMagnitude;
         var radius = Mathf.Sqrt(sqRad);
         foreach (var p in aPoints)
         {
             float d = (p - center).sqrMagnitude;
             if(d > sqRad)
             {
                 var r = Mathf.Sqrt(d);
                 radius = (radius + r) * 0.5f;
                 sqRad = radius * radius;
                 var offset = r - radius;
                 center = (radius * center + offset * p) / r;
             }
         }
         return new BoundingSphere(center, radius);
     }
 }

Note: haven't tested it yet ;) It's just a 1 to 1 translation. This could be a usage:

 void Start()
 {
     MeshFilter mf = GetComponent<MeshFilter>();
     Mesh m = mf.sharedMesh;
     var sphere = BoundingSphere.Calculate(m.vertices);
     var col = gameObject.AddComponent<SphereCollider>();
     col.center = sphere.center;
     col.radius = sphere.radius;
 }

Keep in mind that this will use all vertices in the mesh. If you have unused vertices and just want to include "used" vertices you would have to iterate through the triangles and grab all referenced vertices. The easiest way is to linq like this:

 void Start()
 {
     MeshFilter mf = GetComponent<MeshFilter>();
     Mesh m = mf.sharedMesh;
     var verts = m.vertices;
     var tris = m.triangles;
     var sphere = BoundingSphere.Calculate(tris.Select(i=>verts[i]));
     var col = gameObject.AddComponent<SphereCollider>();
     col.center = sphere.center;
     col.radius = sphere.radius;
 }

If the mesh has shared vertices you will actually use those vertices multiple times, but it shouldn't hurt.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Owen-Reynolds · Nov 20, 2014 at 04:19 PM 0
Share

...because this comes down to a standard, pure-math problem. That's really a good thing. It means you can now use the entire internet, not just Unity sites.

In theory, someone could say "oh, just check this box to enable auto sphere-covering in Unity." But if Unity had that, I think it would do it for all fresh spheres, the same way it does for box colliders.

avatar image Bunny83 · Nov 20, 2014 at 05:39 PM 0
Share

Had a typo in the struct ;) Fixed it.

avatar image Finnigan · Nov 20, 2014 at 08:38 PM 0
Share

Ok, I don't know why I can't make a comment with images. Anyway, the algorithm is great Bunny83, thanks for the quick answer. However, the pieces are not well centered and I think the sphere could be even smaller. I worry more about the "not centered" part.

In the picture with the 3 diamonds, the third is with Ritter's algorithm

Edit: Apparently I can't upload 4 images... alt text alt text

consulta1.jpg (281.7 kB)
consulta3.jpg (104.5 kB)
avatar image Owen-Reynolds · Nov 20, 2014 at 10:42 PM 0
Share

Well, sure. If you look it up, that how Ritter's works -- guaranteed to hold everything, but tends to be a little large. And runs fast.

Will you be computing these during game play (where speed matters,) or just "offline" in an editor script?

avatar image Finnigan · Nov 21, 2014 at 12:34 AM 0
Share

Can be offline or at the start of the game. However, at the moment it does it instantly.

Show more comments
avatar image
0

Answer by sagron6015 · Jan 07, 2015 at 05:28 AM

Here's a c# conversion I did of a java library from https://github.com/hbf/miniball Warning: crappy code as it's an almost straight conversion (and doc is unchanged) Works pretty well, has a sample scene consisting of a rotated cylinder and a quad that are combined into a single mesh and then the bounding sphere generator is added (which calculates once on start and sets a spherecollider to results).

BoundingSphere

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How do I keep an Ortho camera in a specific range when the ortho changes? 3 Answers

Checking if ground is 'level' 1 Answer

Imported mesh bounds size is alwasy too big and pivot point is not aligned 1 Answer

Shader LOD 1 Answer

Bounds NaN issue 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges