Help with spherical-cartesian coordinates

Started by
10 comments, last by Zakwayda 17 years, 12 months ago
Heyall. I should be able to solve this on my own, but bleh. Someone here is probably a better mathematician than me. I have an object in three-dimensional space. On this object I have a number of hotspots, whose position I know as a set of three offset coordinates from the centre of the object when it has a rotation of zero in all planes. The object can move freely through space and rotate either in the xy-plane (around the z axis) or in the xz plane (around the y axis - basically the tilt of the object). What I need to do is keep track of the hotspots and update their positions in cartesian coordinates. So far, I've managed to compensate for rotations in the xy-plane, which I do something like this (rewritten from memory, so the actual formulae might be wrong, but you get the idea):
pos.x = objpos.x + offset.y * -sin(angle) + offset.x * cos(angle);
pos.y = objpos.x + offset.y * cos(angle) + offset.x * sin(angle);
pos.z = objpos.z;
However, I can't seem to figure out how to compensate for tilt. I know all three coordinates must take the tilt into account, but I do not know how. Any help is appreciated. Thanks.
-------------Please rate this post if it was useful.
Advertisement
If you can successfully position, orient and render your object, then somewhere you have a 4x4 matrix representing this transformation; all you need to do is multiply the 'hot spot' points by this matrix.

The caveat here is that if you're using OpenGL, you may not have easy access to this matrix, and may not have code available to construct it yourself. If this is the case, perhaps you could post the code where you set up OpenGL to render the object; from there someone can probably help you with constructing the matrix and transforming the points yourself.
Yes, I'm using OpenGL. I don't have the source available at this location though. Could I not simply use glGetDoublev to fetch the matrix? If so, which matrix do I need - modelview or perspective?

Also, I obviously can't multiply a 1X3 vector with a 4X4 matrix. How to resolve that problem?
-------------Please rate this post if it was useful.
Quote:Original post by Hnefi
Yes, I'm using OpenGL. I don't have the source available at this location though. Could I not simply use glGetDoublev to fetch the matrix? If so, which matrix do I need - modelview or perspective?

Also, I obviously can't multiply a 1X3 vector with a 4X4 matrix. How to resolve that problem?


I can't answer the first part of your question, but as for the second, transform it as a 4d vector with 4th coordinate W == 1. After mulitplication, this fourth coordinate may have changed. Divide all components of the new vector by its W, to effectively turn the 4th component into 1 again. Only then it will represent an actual point in space (just like before multiplication).

You set the fourth coordinate to 1 because the 4d vector represents a point in a space, a coordinate. If it wasn't a point, but it was rather an arbitrary direction (that can't be translated), you should set it to 0.

This is -pretty much- the concept of a homogeneous vector, you may have heard the term...

Quote:Original post by Hnefi
Yes, I'm using OpenGL. I don't have the source available at this location though. Could I not simply use glGetDoublev to fetch the matrix? If so, which matrix do I need - modelview or perspective?

Also, I obviously can't multiply a 1X3 vector with a 4X4 matrix. How to resolve that problem?
Querying the OpenGL matrix should only be considered as a temporary solution, for various reasons; eventually you'll want to write some simple math library code and do it yourself.

Meanwhile though, you want the modelview matrix; the problem is though that it will probably contain the view transform also. There are ways around this, such as setting up a temporary transform and re-doing the object transform setup, and then extracting the matrix. If it sounds inefficient and inelegant, well, it is :)

Once you have the matrix, you multiply it with each point in question (remember that OpenGL matrices are column-major with column vectors). Just treat the 1x3 vector (should actually be 3x1) as a 4x1 with a w of 1. In code, this comes out to just tacking elements 12, 13 and 14 onto the respective expressions.

Let us know if you have any further questions.
If I have to do another transfrom and then retransform and whatnot just to get the matrix, isn't it more efficient to simply calculate each coordinate by its base transformation, similar to what I tried in the OP?
-------------Please rate this post if it was useful.
Quote:Original post by Hnefi
If I have to do another transfrom and then retransform and whatnot just to get the matrix, isn't it more efficient to simply calculate each coordinate by its base transformation, similar to what I tried in the OP?
Whether you write it out longhand or express it in matrix form, it's essentially the same thing.

Either way though you'll have to calculate the basis vectors that represent the orientation of your object; as your post title suggests, one way to go about this is via spherical coordinates. If you can post the code where you set up the transformation for the object (presumably using glRotate() and the like), I or someone else could probably show you how to compute the basis vectors that you need.
Thanks. I'll post it as soon as I get back home and then back here (sometimes, my choice to remain without internet at home seems like a bad way to go).
-------------Please rate this post if it was useful.
Okay, here it is. The code is, of course, split over several rather large .cpp files, so I'll line it up in the order it gets called in run-time.
//Initialization of OpenGL viewport:{	glViewport(0,0,width,height);	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f, 100.0f);	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();}/*each frame begins with taking input, then calculating what happens in the game world, then finally rendering the scene. It is here that I need to update the position of my fixed points. As I said earlier, the points are simply three-dimensional vectors representing their offset relative to their "parent" object when that object is facing straight forward with no tilt.*///the code that gets called first during the render loop each frame:{	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	glLoadIdentity();	fbo->Bind();	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	world->Render();	fbo->DisableFBO();}//world->Render() renders each object. A typical object render looks like this:{	glLoadIdentity();	glTranslated(pos.x - Game::camera.x, pos.y - Game::camera.y, pos.z + Game::zoom);	glRotated(facing_angle, 0, 0, 1);	glRotated(tilt, 0, 1, 0);	glColor4d(1, 1, 1, 1);	model->Render();	stuff_that_relies_on_the_points_I_need_to_keep_track_of->Render();}//then buffers are swapped, timer is checked and a new frame begins.
-------------Please rate this post if it was useful.
Quote:
glLoadIdentity();glTranslated(pos.x - Game::camera.x, pos.y - Game::camera.y, pos.z + Game::zoom);glRotated(facing_angle, 0, 0, 1);glRotated(tilt, 0, 1, 0);
I started to sketch out an ad hoc solution based on the above, but honestly it would be much easier using matrices. All you'd really need (if you don't have it already) is a 4x4 matrix class with functions for matrix-matrix and matrix-vector multiplication, and functions for loading a rotation about a global axis (x, y or z) and loading a translation. Given that, you can do what you're wanting in just a few lines of code. If you don't already have a matrix class, now's as good a time as any to start one; you're going to need it sooner or later.

The aforementioned functions should be easy to write; you just have to make sure you get the conventions right (column-major, column vectors), or the results won't match OpenGL's.

This topic is closed to new replies.

Advertisement