Search Unity

How do I calculate a point on sphere given angles and radius?

Discussion in 'Scripting' started by EternalMe, Jan 17, 2022.

  1. EternalMe

    EternalMe

    Joined:
    Sep 12, 2014
    Posts:
    183
    Assuming sphere is at 0,0,0.
    For example angles 90,0,0 should give 1,0,0 if radius is 1.

    Edit:

    Trying like this:

    Code (CSharp):
    1. var rot = Quaternion.AngleAxis(xAngle, Vector3.right);
    2. var lDirection = rot * Vector3.up;
    But it moves Z instead of x :/
     
    Last edited: Jan 17, 2022
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    What do you mean by "given angles"? Which angles?

    I'll assume you mean like rotation coordinates (like latitude and longitude), and if so, then you can use some basic trigonometry. When given an angle, Sin gets you the "Y" coordinate and Cos gives you the "X" coordinate - I put those in quotes because obviously in 3 dimensions, if you feed it different angles, that'll give you different axes. Also make sure to convert the angle to radians, as that's what Unity's trig functions take.

    Let's do longitude first, as it's straightforward. This will give you essentially the point along the equator. In this case, you'll want to get back X and Z coordinates:
    Code (csharp):
    1. float equatorX = Mathf.Cos(longitude);
    2. float equatorZ = Mathf.Sin(longitude);
    Next you need the vertical coordinate. Y is easy:
    Code (csharp):
    1. float y = Mathf.Sin(latitude);
    If you use these numbers as they are now, you'll have a cylinder. So the next step here is to scale the X and Z based on latitude:
    Code (csharp):
    1. float multiplier = Mathf.Cos(latitude);
    2. float x = multiplier * equatorX;
    3. float z = multiplier * equatorZ;
    All that's left is to multiply all 3 numbers by the radius.
     
    EternalMe, Olmi and Bunny83 like this.
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,992
    What kind of reference coordinate system would yield that result? Rotating around the x axis should not change the x position at all since you rotate around an axis that goes through a point on the x axis. What should be the result if the angles are both 0?

    There are countless of spherical to cartesian coordinate mappings possible. So how should be know which one you have in mind? The usual one is explained over here.
     
    EternalMe and Kurt-Dekker like this.
  4. EternalMe

    EternalMe

    Joined:
    Sep 12, 2014
    Posts:
    183
    I am not rotating anything. I am trying to find a point (3d vector) on Sphere by given angles.
    Assuming that Sphere is at 0,0,0 position and starting reference is 0,1,0 (very top middle point on sphere with radius 1). If you would rotate this vector by 90 degrees in x direction +, it would end up being 1,0,0 what also gives me a point on sphere.
     
  5. EternalMe

    EternalMe

    Joined:
    Sep 12, 2014
    Posts:
    183
    But yeah. 2 angles should be enough to find a point. 3rd just spins around it self.
     
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,992
    No, it would not. The expected result would be (0,0,1). I think you have something messed up in your visualization of the coordinate axis. A rotation around the x axis rotates in the y-z plane. So your y=1 rotates to z=1. Using (0,1,0) as start reference is quite strange as in all normal coordinate systems this would be a gimbal lock orientation.

    If you want to reach from (0,1,0) to (1,0,0) you have to rotate by (90,90,0) or something like that. Though I would highly recommend to stick with common references. (0,0,0) should be (0,0,1) so simply forward. up and down would be (90,0,0) and (-90,0,0) respectively. For spherical coordinates you generally have one "yaw" angle or longitude which goes 360° around the sphere horizontally. So it rotates around the y axis. In addition you would have a "pitch" angle or latitude that goes +- 90°. Of course you could construct any spherical coordinate system you like, however it just complicates the conversion. If you really want to start at the top, you have to be more specific how the initial orientation should look like and which of the two angles depend on the other. So which one goes first and which one goes last. One angle rotates around a global axis (as said, usually the y axis) and the other angle rotates around a local axis that rotates with the first angle (usually the x axis). The z axis is usually the look axis, so the axis that has no effect on the position.
     
    orionsyndrome and EternalMe like this.
  7. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    It seems as if AngleAxis is most of the problem. You don't want it(*). The normal way to convert "normal" x,y,z's into an angle is Quaternion.Euler(x,y,z). And as you note, for a point, z won't matter.

    The other issue is that in Unity Vector3.forward is the (0,0,0)-rotation direction (you used Vector3.up). So the final thing should be:
    Quaternion.Euler(x,y,0)*Vector3.forward
    .

    (*)AngleAxis is like a 5-prong screw-driver head. It's great when you have the one particular problem it solves, but you will almost never need it. When you do, you'll know it.
     
    EternalMe likes this.
  8. EternalMe

    EternalMe

    Joined:
    Sep 12, 2014
    Posts:
    183
    Thank you all guys who left comments. U rock :)
     
  9. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    Of course it can be done with AngleAxis.

    First you want to rotate a point in one plane, which lands you at a circumference of a circle.
    Then you rotate this circle, so that the point lands on a surface of a sphere.

    First let's declare two angles, theta (polar, 0..2Pi) and phi (azimuthal, -Pi/2..Pi/2).
    There are zillions of conventions, but I'm fond of the one where the 360 rotation goes around the polar axis (longitude), and then the other dictates the distance from the equator (latitude).

    If the longitude is around Y (up), and the latitude is around Z (forward), then the code (for angles in radians) should be
    Code (csharp):
    1. Vector3 Spherical(float theta, float phi)
    2.   => Quaternion.AngleAxis(phi, Vector3.forward) * Quaternion.AngleAxis(theta, Vector3.up) * Vector3.forward;
    Euler is more compact (because the axes are already aligned to basis vectors).
    Code (csharp):
    1. Vector3 Spherical(float theta, float phi) => Quaternion.Euler(0f, theta, phi) * Vector3.forward;
    Another way to approach this would be to do it "by hand", by merging two 2D projections.
    Code (csharp):
    1. Vector3 Spherical(float theta, float phi) {
    2.   Vector2 polar_theta = Polar(theta), polar_phi = Polar(phi);
    3.   return new Vector3(polar_theta.y * polar_phi.x, polar_theta.y * polar_phi.y, polar_theta.x);
    4. }
    where
    Code (csharp):
    1. Vector2 Polar(float theta)
    2.   => new Vector2(Mathf.Cos(theta), Mathf.Sin(theta));
    I'm sure I've swapped something, this hasn't been tested. But these are the general ideas.
     
    Bunny83 likes this.
  10. ccfoo242

    ccfoo242

    Joined:
    Oct 9, 2014
    Posts:
    85
    Maybe I have theta and phi mixed up but I was able to properly render the 7 stars of the Big Dipper plus polaris with right ascension and declination using this for position:
    Code (CSharp):
    1. go.transform.position = Quaternion.Euler(-star.DeDegrees, star.RaDegrees,0f) *
    2.                 Vector3.forward * radius;
    I had to negate declination because it was rendering them below 0,0,0 not above. Anyone know why? Its the same with the camera. Place it at 0,0,0 and rotate in positive X, it will look down.

    Right ascension is longitude and declination is latitude.



    PS - I don't suggest using game objects to render lots of stars. This was just a POC for me. Aside from the overhead of thousands of game objects, they can't be rendered far enough away to feel like stars feel.
     
  11. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    Don't worry, everybody does :) After a while I even abandoned names such as azimuth and whatnot. Sometimes it has a zenith, sometimes it's the longitude. Everybody seems to be confused about what's what. So phi and theta.

    Rotations go anti-clockwise (when you orient yourself downstream the axis). Unity has a left-handed coordinate system.

    So if you look X downstream (to the right), a positive rotation should make a thing that looked towards positive Z (
    forward
    ) look downward. Conversely, a thing that looked at you (
    back
    ), would look up.



    I can't find the appropriate image for the rotations because there are so many conflicting standards.

    A useful reminder is the plain 2D rotation which works exactly like in math textbooks (0° is to the right, and rotates anti-clockwise), but then you notice that it depicts a rotation around
    forward
    . Then you simply apply the left-hand rule.

    In other words, when you make something oriented forward, it's already intrinsically rotated by 180°, even though it shows 0,0,0. When you positively rotate X, it will go downward.

    Good job with the stars btw!
     
    Last edited: Oct 23, 2022
    ccfoo242 and Bunny83 like this.