Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

Thread: Help getting perpendicular angle of point on sphere

  1. #1
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    4

    Question Help getting perpendicular angle of point on sphere

    Hey Guys,

    I'm trying to figure out the rotation of an object placed around a sphere. Here is the sphere with the objects unrotated:



    I can get the Y rotation by just setting y rotation to -pi2 * xProgress + pi*0.5, seen here:



    But I can't figure out the X rotation and I think the way I'm going about this is flawed. If I apply what I did for Y to X I get:



    The center of the sphere is just 0,0,0, so the projected vector to the surface of the sphere is just the position where each face is placed (x,y,z).

    Any ideas?

    Thanks! -andy

  2. #2
    Member Regular Contributor
    Join Date
    May 2000
    Location
    Philadelphia
    Posts
    285
    Try changing the order of rotation. For example, instead of X then Y, rotate Y then X.

  3. #3
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,213
    Quote Originally Posted by mrbendel View Post
    Hey Guys,
    I'm trying to figure out the rotation of an object placed around a sphere. ...

    I can get the Y rotation by just setting y rotation to -pi2 * xProgress + pi*0.5...
    But I can't figure out the X rotation
    Not sure I completely get the jist of your question, but sounds like you just want to orient a quad tangent to a sphere at a specific point on the sphere. To do so you just need MODELING transform which positions the quad on the sphere. This MODELING transform is just a frame of reference (3 orthonormal vectors [UVW] and an origin offset).

    Building this transform with vector math is often much simpler than using trig and euler angles. You know your origin offset -- it's the point on the sphere where you want your quad to touch. Your "W" vector is a vector from the center of the sphere to the point. Assuming the sphere center is 0,0,0, just normalize the position vector on the sphere. Then to get the "U" orthonormal vector, pick some generally up vector (e.g. a vector through the north pole -- say, 0,0,1), cross it with the W vector, and normalize the result. Then cross W and U to get V.

    Stuff those 3 orthonormal vector (U,V,W) and the origin offset into a matrix, and you're done. No trig or euler angles required.

  4. #4
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    4
    Thanks for the help!

    I'm trying to follow –*I'm sorry If i'm a bit slow. I think I have the W, U, V being calculated correctly, I'm just not sure what you mean by the last step - stuffing them into a matrix. Also I have to apologize in advance, I'm writing all this for webgl (javascript) so I'm using the THREEjs library. I hope the library code is clear enough. Here is what I have so far:

    var x = this.vertexArray[i].x;
    var y = this.vertexArray[i].y;
    var z = this.vertexArray[i].z;

    var cube = new THREE.CubeGeometry(20, 20, 1);
    var tmp = new THREE.Mesh(new THREE.CubeGeometry(20, 20, 1));

    var w = new THREE.Vector3(x,y,z);

    var u = new THREE.Vector3(0,0,1);
    u = u.crossSelf(w);

    var v = new THREE.Vector3(0,0,0)
    var v = v.cross(w,u);

    var mat = new THREE.Matrix4(
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    0.0, 0.0, 0.0, 1.0
    );

    // User UVW to rotate somehow?

    mat.translate(new THREE.Vector3(x*this.worldScale,
    y*this.worldScale,
    z*this.worldScale));

    tmp.geometry.applyMatrix( mat );



    Now I know my 3D math isn't the greatest, so I'm not sure what to do to make the rotations work...

    Thanks,
    Andy
    Last edited by mrbendel; 09-07-2012 at 08:24 AM.

  5. #5
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    4
    I got my original method working! Here's the code that ended up working right:

    var mat = new THREE.Matrix4(
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    0.0, 0.0, 0.0, 1.0
    );

    mat.translate(new THREE.Vector3(x*this.worldScale,
    y*this.worldScale,
    z*this.worldScale));


    var rotationY = (i%this.resX/this.resX) * -Math.PI*2 + (Math.PI*0.5);
    var rotationX = (Math.floor(i/this.resY)/this.resY) * -Math.PI + (Math.PI*0.5);

    mat.rotateY(rotationY);
    mat.rotateX(rotationX);

    tmp.geometry.applyMatrix( mat );

  6. #6
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,213
    Glad you got an approach working. You may not care about the other method then. But just in case you're curious...

    Quote Originally Posted by mrbendel View Post
    var w = new THREE.Vector3(x,y,z);
    Ok, now subtract the center of the sphere from that, and normalize the result. So you have a unit vector pointing from the center of the sphere to the point on the sphere. That is:

    Code :
    w = normalize( (x,y,z) - center );

    var u = new THREE.Vector3(0,0,1);
    u = u.crossSelf(w);
    var v = new THREE.Vector3(0,0,0)
    var v = v.cross(w,u);
    Not sure what "crossSelf does, but you want:

    Code :
    v = normalize( cross( w, (0,0,1) ) );  (assuming a right handed coordinate system).
    u = cross( v,w );

    I'm just not sure what you mean by the last step - stuffing them into a matrix.
    Stuff them in the upper-left 3x3 of your 4x4 matrix, like this:

    Code :
    u_x u_y u_z 0
    v_x v_y v_z 0
    w_x w_y w_z 0
    0   0   0   1

    As you can see, if you premultiply this by a vector (1,0,0), you get "u". If you premultiply this by a vector (0,1,0), you get "v". Similarly for (0,0,1) -> w. You've just built a basis change matrix (i.e. the rotation matrix), without having to mess with any trig!


    Now slam (x,y,z) in the last column (your translation), and you're done!

    By the way, the one bit of error checking you'll want to add to the above is if "cross( w, (0,0,1) )" is (0,0,0) (i.e. the length is 0), then w and (0,0,1) are colinear. -- in this case just chose another arbitrary "up vector". If (0,0,1) points toward the north pole of your sphere, you'd only do this for points that are exactly on the north or south poles.
    Last edited by Dark Photon; 09-08-2012 at 06:57 PM.

  7. #7
    Junior Member Newbie
    Join Date
    Sep 2012
    Posts
    4
    Thanks for the detailed help – I'll give this a go and see if I can get it working.

    /andy

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •