Advertisement

Moving a point around a Sphere

Started by August 30, 2016 06:31 PM
4 comments, last by PhoenixGames 8 years, 5 months ago

Hello,

I am currently working on a problem which I can't seem to solve.

I am trying to move a set of point around a sphere by a certain angle (or, preferably, by a distance, but most of the math examples I have found use angles).

What I am currently doing is as follows:

Convert the set of points from Cartesian (XYZ) coordinates to Spherical Coordinates,
Use Rodrigues Rotation formula to get "vRot", the rotation vector,
Multiply vRot with the original Spherical coordinates to get the new position.

According to Gnuplot, I can successfully convert the points to Spherical Coordinates, but I am having problems with the next two steps.

The equation for Rodrigues formula that I am using is this one:

rOKBK.png

Which I got from here:

http://stackoverflow.com/questions/26453951/rotateing-vector-on-plane-in-3d

This is the relevant section of code:


        F32 x = renderlist[i].point.x;
        F32 y = renderlist[i].point.y;
        F32 z = renderlist[i].point.z;
 
        //Values are between -1 and +1, this ensures all values are positive, since negative values seem to cause issues:
 
        F32 xscaled = x+1;
        F32 yscaled = y+1;
        F32 zscaled = z+1;
 
        //convert to spherical coordinates:
        F32 radialdistance_r = sqrt(xscaled*xscaled + yscaled*yscaled + zscaled*zscaled);
        F32 polarangle_theta = mAcos(zscaled / radialdistance_r);//0-PI
        F32 azimuthalangle_phi = mAtan2(yscaled, xscaled); //0-2PI
 
        //Using Rodrigues rotation forumula, as given here:
        //http://stackoverflow.com/questions/26453951/rotateing-vector-on-plane-in-3d
 
        Point3F v = Point3F(radialdistance_r, polarangle_theta, azimuthalangle_phi);
        Point3F k = Point3F(0, 1, 0); //rotate on y axix
        F32 theta = 0.0174533;// rotate by 1 degree only for now
 
        Point3F vRot = v*mCos(theta) + mCross(k, v)*mSin(theta) + k*mDot(k, v)*(1 - mCos(theta));
 
        Point3F newpos = v * vRot;
 
        Con::printf("%f %f %f",  newpos.x, newpos.y, newpos.z);

Is there anything obviously wrong here?

Thanks!

I might be misunderstanding something here, but why are you converting to spherical coordinates? The Rodriguez formula takes vectors in any representation; you should just be able to apply it to x, y, and z directly. I think that might be your problem; unless mCross, mDot, and the * operator with a float are defined to work with spherical coordinates, you would expect to get the wrong answer. For example, for the common overload of *(float, vector), multiplying v by mCos(theta) will scale all three components, but with spherical coordinates you want it to scale r and leave theta and phi unchanged.

As an aside, it shouldn't be necessary to add 1 to x, y, and z either in spherical coordinates or for the Rodriguez formula. Wouldn't you expect doing so to change the result?

EDIT: I apologize, it looks like I didn't read the last part of your code carefully enough. It looks like you're using the Rodriguez formula to produce a vector vRot that rotates another vector, which is also not correct. The behavior of v * vRot depends on how *(vector, vector) is defined, but in general it's very weird to define a rotation as some sort of multiplication between two vectors - in fact, multiplication between vectors is usually defined to be a dot or cross product.

The correct usage of the Rodriguez formula is to take vRot as your rotated result without any additional multiplications.

Advertisement

Hi,

Thanks for your reply.

I was under the impression that in order to rotate on a sphere (IE, for the point to be rotated along the curve of the sphere, to another point on the same sphere) I needed to convert to spherical coordinates?

I am adding 1 because the conversion to spherical coordinates didnt seem to work at all when the cartesian coordinate were in their initial range of -1 to +1. I intended to subtract it before converting back to cartesian.

So, vRot *IS* the actual rotated point then, I don't need to apply it to anything? I will try that, thank you!

I was under the impression that in order to rotate on a sphere (IE, for the point to be rotated along the curve of the sphere, to another point on the same sphere) I needed to convert to spherical coordinates?

Cartesian and spherical coordinates are two ways of representing exactly the same thing. The thing that keeps the point on the sphere is the Rodriguez formula, not the use of spherical coordinates. A rotation never changes the length of a vector. A sphere is just the surface at a particular distance from the center, so a rotation around the center of a sphere will never move you off of that sphere, regardless of your coordinate system. You should be able to stick with Cartesian coordinates and do everything in a few lines:

1. define your rotation axis

2. apply the Rodriguez formula to renderlist.point to get the new point

I am adding 1 because the conversion to spherical coordinates didnt seem to work at all when the cartesian coordinate were in their initial range of -1 to +1. I intended to subtract it before converting back to cartesian.

I haven't figured out where you're getting the error with negatives from, but your strategy is probably not going to work. The +1s that you add are going to get 'mixed up' by the rotation, so when you subtract them off it won't cancel properly.

Ahh, I see, it would certainly make things a lot easier if I could stick to the same coordinate system throughout the process.

I'll try it with the cartesian coordinates, and see what happens, thanks!

The adding 1 was more of an experiment which seemed to work, I can remove it.

Thank you very much for your help, I seem to have rotation working now!

I did exactly what you said, I didn't need to convert to spherical coordinates at all, or add the 1.

The only issue that I have now is that that rotation doesn't seem to be solving the problem that I was having.

I'm not sure if I should post a new topic or not, but what I am really trying to do, at a high level, is implement a floating-origin type system for a spherical terrain implementation.
The terrain is basically working, as the player moves, the terrain is paged in and out.

However, what I now need to do is reset the player and the currently rendering terrain nodes back to the origin when the player exceeds a certain distance. Moving the player and other objects is simple, I just move them back by changing their transform, so move them 10,000 meters on the x axis, for example.

The problem is that doing this with the nodes on the spherical terrain doesn't work. The x position is correct, the y position seems correct too, but the z position is above where it should be, and every time the player moves, the terrain moves further and further up the z axis. All I am doing is moving the terrain on the x axis, so I am not sure why it's not aligned correctly on Z.

I assumed the issue was caused by the curvature of the terrain itself, but I am not so sure now.

What I need to do, really, is take a series of points and move them along a sphere of known radius along a vector. Is what I am doing the correct way to do this?

This topic is closed to new replies.

Advertisement