8

I'm trying to make a spherical burst of rays for the purpose of checking collision, but having specific interactions happen based upon what or where each ray hit. Hence why I'm using rays rather then something simpler such as OverlapSphere.

The reason I'm looking for how to make a sphere is because I can use the same math for my rays, by having them go to the vertices of where the sphere would be. But every way I can find for making a sphere has the lines get closer the near to the poles, which makes sense, as its pretty easy to do. But as you can imagine, its not that useful for my current project.

TL;DR: How do I make a sphere with equidistant vertices? If its not perfectly equidistant its fine, it just needs to pretty close. If this happens, it would be great if you could give how much the difference would be, and where, if applicable.

Extra notes: I've looked at this and this, but the math is way over my head, so what I've been looking for might've just been staring me in the face this whole time.

user1118321
  • 25,567
  • 4
  • 55
  • 86
Matrixian
  • 177
  • 2
  • 6
  • Making them exactly equidistant might be difficult. But if you just need something that's fairly close, some of the methods in my answer here might work for you: http://stackoverflow.com/questions/24137198/opengl-es-2-0-sphere. – Reto Koradi Jul 31 '14 at 07:29
  • Why, in the name of goodness, would you do this, when it is completely and totally built-in to Unity? – Fattie Feb 16 '16 at 01:29
  • Just to be clear, a solution for **what you are trying to achieve** is built-in to Unity. AND if for whatever reason you want the **"evenly-spaced vertices"** ... that too is built-in to Unity! Heh! – Fattie Feb 16 '16 at 16:26
  • Your solution seems pretty good. Unfortunately when I was working on this, the features you mentioned didn't exist. This was way back in 4.6, when there was no icosphere or support for the required version of PhysX. Regardless, thanks for the input. – Matrixian Feb 20 '16 at 19:48

6 Answers6

7

You could use an icosphere. As the vertices are distributed on equilateral triangles, your vertices are guaranteed to be equidistant.

enter image description here

To construct the icosphere, first you make an icosahedron and then split the faces recursively in smaller triangles as explained in this article.

Elie Génard
  • 1,673
  • 3
  • 21
  • 34
  • (Note that there are a couple famous bugs in the famous article there.) Just FYI note that you absolutely do not have to do this, as it is completely built-in to Unity. – Fattie Feb 16 '16 at 16:33
  • This sounds exactly like what I'm looking for. Would you take a look at this question? https://stackoverflow.com/questions/46777626/mathematically-producing-sphere-shaped-hexagonal-grid – Aaron Franke Oct 17 '17 at 17:08
5

Are you aware that the sphere given to you by Unity is in fact designed

with this exact goal in mind?

ie, the entire raison d'etre of the sphere built-in to Unity is that the points are fairly smoothly space ...... roughly equidistant, as you phrase it.

enter image description here

To bring up such a sphere in Unity, just do this:

enter image description here

You can then instantly get access to the verts, as you know

Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vv = mesh.vertices;
int kVerts=vv.Length
for (int i=0; i<kVerts; ++i)
  Debug.Log ... vv[i] 

Note you can easily check "which part of the sphere" they are on by (for example) checking how far they are from your "cities" (or whatever) or just check (for example) the z values to see which hemisphere they are in .. et cetera.


Furthermore...

Please note. Regarding your overall reason for wanting to do this:

but having specific interactions happen based upon what or where each ray hit

Note that it could not be easier to do this using PhysX. (The completely built-in game physics in Unity.) Indeed, I have never, ever, looked at a collision without doing something "specific" depending on "where it hit!"

You can for example get the point where the contact was with http://docs.unity3d.com/ScriptReference/RaycastHit-point.html

It's worth noting it is absolutely inconceivable one could write something approaching the performance of PhysX in casual programming.

I hope this makes things easier!

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
4
  1. slice the sphere into N circles
  2. compute perimeter of it
  3. divide it by the same angle that create the slice
    • this gives you the number of vertexes
    • and also angle step inside circle
  4. cast rays

This is how I coded it in C++ + OpenGL:

// draw unit sphere points (r=1 center=(0,0,0)) ... your rays directions
int ia,na,ib,nb;
double x,y,z,r;
double a,b,da,db;
na=16;                                  // number of slices
da=M_PI/double(na-1);                   // latitude angle step
for (a=-0.5*M_PI,ia=0;ia<na;ia++,a+=da) // slice sphere to circles in xy planes
    {
    r=cos(a);                           // radius of actual circle in xy plane
    z=sin(a);                           // height of actual circle in xy plane
    nb=ceil(2.0*M_PI*r/da);
    db=2.0*M_PI/double(nb);             // longitude angle step
    if ((ia==0)||(ia==na-1)) { nb=1; db=0.0; }  // handle edge cases
    for (b=0.0,ib=0;ib<nb;ib++,b+=db)   // cut circle to vertexes
        {
        x=r*cos(b);                     // compute x,y of vertex
        y=r*sin(b);
        // this just draw the ray direction (x,y,z) as line in OpenGL
        // so you can ignore this
        // instead add the ray cast of yours
        double w=1.2;
        glBegin(GL_LINES);
        glColor3f(1.0,1.0,1.0); glVertex3d(x,y,z);
        glColor3f(0.0,0.0,0.0); glVertex3d(w*x,w*y,w*z);
        glEnd();
        }
    }

This is how it looks like:

sphere vertexes

  • R,G,B lines are the sphere coordinate system axises X,Y,Z
  • White-ish lines are your Vertexes (White) + direction (Gray)

coordinate systems

[Notes]

  • do not forget to include math.h
  • and replace the OpenGL stuff with yours
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Just to repeat myself - Spektre, this is for Unity3D. A facility for doing this is absolutely built-in to Unity3D, it seems the OP was just not aware of this. Just BTW note that Unity has absolutely no connection to c++ nor OpenGL for programming. (Again, anyway, you "click one button" and get what the OP wants.) – Fattie Feb 16 '16 at 16:34
  • @Spektre do you know how to connect the resulted vertices into triangles ? I'm trying for the 2nd day in the row, so far i got a method without including the poles: ``` for( var i = 0; i < N; ++i ) { int b = i + 8 , c = b + 13; if( c < N ) Triangle( i, b, c ); b = i + 13; c = b + 8; if( c < N ) Triangle( c, b, i ); } ``` Where later i try and close the poles manually ( which results in weird looking angles sometimes ) for : index < 21 && index >= count - 21 – Vlad Oct 10 '20 at 21:58
  • if you want better looking mesh then you need to have poles as a vertexes which is the case only for specific numbers of points ... far easier for meshing sphere is to use subdivision like [this](https://stackoverflow.com/a/29139125/2521214) but starting with icosahedron instead. There are also more wild methods like [this](https://stackoverflow.com/a/62754601/2521214) and [this](https://stackoverflow.com/a/57240140/2521214) – Spektre Oct 11 '20 at 07:18
  • Thanks will try that as well, also I sort of did manage to connect the points, have a look at : https://i.imgur.com/kMRCCSA.mp4 – Vlad Oct 11 '20 at 18:39
2

If you want 4, 6, 8, 12 or 20 vertices then you can have exactly equidistant vertices as the Platonic solid which all fit inside a sphere. The actual coordinates of these should be easy to get. For other numbers of vertices you can use other polyhedra and scale the verties so they lie on a sphere. If you need lots of points then a geodesic dome might be a good base. The C60 bucky-ball could be a good base with 60 points. For most of these you should be able to find 3D models from which you can extract coordinates.

Salix alba
  • 7,536
  • 2
  • 32
  • 38
  • Just to repeat myself - Salix, this is for Unity3D. A facility for doing this is absolutely built-in to Unity3D, it seems the OP was just not aware of this. – Fattie Feb 16 '16 at 16:30
0

I think the easiest way to control points on a sphere is by using spherical coordinates. Then you can control position of points around the sphere by using two angles (rho and phi) and the radius.

Example code for filling points uniformly around a rotating sphere (for fun):

var time = 1; // Increment this variable every frame to see the rotation
var count = 1000;
for (int i = 0; i < count; i++)
{
    var rho = time + i; 
    var phi = 2 * Math.PI * i / count;
    var x = (float)(radius * Math.Sin(phi) * Math.Cos(rho));
    var z = (float)(radius * Math.Sin(phi) * Math.Sin(rho));
    var y = (float)(radius * Math.Cos(phi));
    Draw(x, y, z); // your drawing code for rendering the point
}
glopes
  • 4,038
  • 3
  • 26
  • 29
  • this would draw like one curved loop around a sphere right? – Fattie Feb 16 '16 at 16:29
  • no, it should actually draw the whole sphere. a curved loop would be setting `rho` to a fixed value. if you do `rho = i % 2` for example, you would draw only 2 loops, etc. – glopes Feb 16 '16 at 21:16
0

As some answers have already suggested, use an icosahedron based solution. The source for this is quite easy to come by (and I have written my own several times) but I find the excellent Primitives Pro plugin extremely handy under many other circumstances, and always use their sphere instead of the built-in Unity one.

Link to Primitives Pro component

Primitives Pro options

LITM
  • 51
  • 3