Thanks in advance
Lynton
England UK
Use gluUnproject to make a line in space between the near
and far clip planes (winz=0 and winz=1).
Now intersect this line with your sphere (Google for "ray
sphere intersection").
--
<\___/>
/ O O \
\_____/ FTB. Remove my socks for email address.
> The texture coordinates go from 0,0 thru 1,1 (u,v) so given they are never
> going to change even if the sphere is resized I figure these could be used
> to generate latitude and longitude references.
> Is there a way of returning u,v (s & t ?) for a given pixel beneath the
> current mouse position by adding some code to the mouse
> "glutPassiveMotionFunc" callback for example ?
Could you gluUnProject using the the mouse coordinates and the depth
component at the mouse position to get the coordinates in the sphere's
space? You could take the object coordinates two at a time, then, and
determine the angles of rotation that span the surface of the sphere.
If you normalize them (divide by 2 * pi), they'll be between 0 and 1
like the texture coordinates.
- Chris
void MouseMotionNoButtonPressed(int x, int y)
{
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)x;
winY = (float)viewport[3] - (float)y;
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX,
&posY, &posZ);
printf("rotX:%f\trotY:%f\n", rotX, rotY);
if (posZ > -120.0f) /* Check if the mouse is on the earth ie posZ is >
zFar */
{
sprintf(strLatDisp, "Lat: %.5f", posY);
sprintf(strLonDisp, "Lon: %.5f", posX);
}
}
The sphere starts off with 0 degrees latitude and longitude at the centre of
the screen and this almost seems to work. When the sphere is rotated the
coordinates system gets skewed. I think I need to do some math with the rotX
and rotY angles of the sphere along with posY and posX. to compensate for
the rotation ?
Does that sound about right or have I totally missed the point somewhere ?
Thanks to both "fungus" and "Chris" for the pointers so far.
Lynton
"crjjrc" <crj...@gmail.com> wrote in message
news:faa542e9-4b28-46bf...@d21g2000prf.googlegroups.com...
if the matrices are those used to draw the sphere, then you should get
unprojected values back in you original object's coordinate system. Is the
modelview matrix the one used to draw the rotated sphere ? Or, are you
missing adding in your rotates() (due to push/pop ?) ? If the latter, then
save away the modelview at the time of the last draw of the sphere.
jbw
Ah, "missing adding in my rotates()", now this does sound interesting and
probably quite right. To be honest I'm getting a bit bogged down with this
now but am determined to solve it somehow.
I'm not using gluSphere do draw my sphere but rather the following code:-
In my Initialize function
float angX, angY;
for (int x=0; x<=EARTH_LON_RES; x++) {
for (int y=0; y<=EARTH_LAT_RES; y++) {
angX = (x * 360.f / EARTH_LON_RES) * PI / 180.f;
angY = (-90.f + (y * 180.f / EARTH_LAT_RES)) * PI / 180.f;
vertices[x][y].x = fabsf(cosf(angY)) * EARTH_RADIUS * sinf(angX);
vertices[x][y].y = EARTH_RADIUS * sinf(angY);
vertices[x][y].z = fabsf(cosf(angY)) * EARTH_RADIUS * cosf(angX);
mapping[x][y].u = (float)x / EARTH_LON_RES;
mapping[x][y].v = (float)y / EARTH_LAT_RES;
}
}
Then in my drawScene function
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
rotX += autoRotX * 0.1f;
rotY += autoRotY * 0.1f;
glTranslatef(0, 0, zoomLevel);
glScalef(WORLD_SCALE, WORLD_SCALE, WORLD_SCALE);
glScalef(1.0f, 1.0f, 1.0f);
glRotatef(rotX, 1, 0, 0);
glRotatef(rotY, 0, 1, 0);
/* Draw earth */
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture); /* Bind the texture id */
glColor3f(1, 1, 1);
for (int y=0; y<EARTH_LAT_RES; y++) {
glBegin(GL_TRIANGLE_STRIP); /* Was glBegin(GL_QUAD_STRIP) */
for (int x=0; x<EARTH_LON_RES; x++) {
glTexCoord2fv((float*)&mapping[x][y]);
glVertex3fv((float*)&vertices[x][y]);
glTexCoord2fv((float*)&mapping[x][y+1]);
glVertex3fv((float*)&vertices[x][y+1]);
glTexCoord2fv((float*)&mapping[x+1][y]);
glVertex3fv((float*)&vertices[x+1][y]);
glTexCoord2fv((float*)&mapping[x+1][y+1]);
glVertex3fv((float*)&vertices[x+1][y+1]);
}
glEnd();
}
glDisable(GL_TEXTURE_2D);
/* End draw earth */
....
...
....
if (winZ < 0.999f) { /* Only show locations in our field of view */
printString(winX + 7, winY + 5, 1.0f, 1.0f, 1.0f, 1.0f, FONT_8X8,
location[i].name);
}
}
glPopMatrix();
/* End draw the sun and locations */
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glutSwapBuffers();
glutPostRedisplay();
CalculateFPS();
checkGLErrors("DrawScene()");
}
I'm rotating the sphere with
glRotatef(rotX, 1, 0, 0);
glRotatef(rotY, 0, 1, 0);
Sorry for posting chunks of code but it may help give an idea whats wrong
with my methods :-)
Whats the best way of debugging my rotates due to push/pop ?
I'm really confused and probably need to do some more reading to refresh my
memory but any further assistance the group can offer is really very much
appreciated.
I guess to you guys who are the experts this problem is so trivial its
untrue but to me its a nightmare!
Regards
Lynton
Save away the projection & modelview matrices at the time you draw, before
the pop, not later after you've changed them
What's in the framebuffer, and what you read back, is projected with these
matrices, not the re-set ones you
are currently using for gluUnproject(), right ?
-jbw
Thanks for your assistance so far. I think I being really stupid
here........................
To simplify things a bit I have ripped out all the extra bits and pieces I
had in my DrawScene() function to leave the bare minimum.
This minimum now has only two glPushMatrix() and two glPopMatrix() calls but
I'm still not having any luck.
When the window first opens I have it so 0 degrees latitude and longitude on
the earth are in the centre of the screen by adjusting rotX and rotY
accordingly. 0 degrees latitude and 0 degrees longitude remains in the
centre of the screen even when I rotate the earth so of course the
coordinates are then all wrong.
I am of course getting the lattitude and longitude from
MouseMotionNoButtonPressed() that is the glutMotionFunc callback function.
The simplified DrawScene function is shown below.
Do the glPushMatrix and glPopMatrix calls look about right now ?
If they look OK then maybe the problem is elsewhere in my code but I just
don't see where.
Its looking like I might be better off leaving this project for a few days
then come back to it fresh but I dearly love to get it sorted before I start
back at work on Monday for the first time since the Christmas break.
Kind Regards
Lynton
void DrawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
rotX += autoRotX * 0.1f;
rotY += autoRotY * 0.1f;
glTranslatef(0, 0, zoomLevel);
glScalef(WORLD_SCALE, WORLD_SCALE, WORLD_SCALE);
glScalef(1.0f, 1.0f, 1.0f);
glRotatef(rotX, 1, 0, 0);
glRotatef(rotY, 0, 1, 0);
printf("%s\n", strMouseLatLonDisp);
/* Draw earth */
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture); /* Bind the texture id */
glColor3f(1, 1, 1);
for (int y=0; y<EARTH_LAT_RES; y++) {
glBegin(GL_TRIANGLE_STRIP); /* Was glBegin(GL_QUAD_STRIP) */
for (int x=0; x<EARTH_LON_RES; x++) {
glTexCoord2fv((float*)&mapping[x][y]);
glVertex3fv((float*)&vertices[x][y]);
glTexCoord2fv((float*)&mapping[x][y+1]);
glVertex3fv((float*)&vertices[x][y+1]);
glTexCoord2fv((float*)&mapping[x+1][y]);
glVertex3fv((float*)&vertices[x+1][y]);
glTexCoord2fv((float*)&mapping[x+1][y+1]);
glVertex3fv((float*)&vertices[x+1][y+1]);
}
glEnd();
}
glDisable(GL_TEXTURE_2D);
/* End draw earth */
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glutSwapBuffers();
CalculateFPS();
checkGLErrors("DrawScene()");
}
[big snip[
No, you still don't understand, you need to pass gluUnproject *the very same
matrices used to draw*.
Once you've popped out the current matrices at the end of draw, you do not
have the right matrices for gluUnproject in the mousefunc any more, get it ?
jbw
This is the technique I used in Albatross 3D to allow user to draw in
3D on the texture.
Hope this help,
Craouette
Hi,
Thanks for the comments.
Your method sounds interesting and definitely worth bearing in mind for a
future project when I am a lot more familiar with openGL.
To be honest I'm an openGL newbie so I need to keep things as simple as
possible. I have lots to learn but am thoroughly enjoying it although I am
getting frustrated sometimes.
I'm going to continue trying to work with gluUnproject to solve my problem
for the moment as that seems like it ought to be a straight forward solution
that I'm making more difficult than it should be.
Thanks to everyone in this NG for the help so far even though I haven't
solved the problem quite yet.
Regards
Lynton
England UK
The problem is best solved outside OGL. If you got your data set, you
have triangles with vertex positions. Intersect a ray, find which
triangle it hits and use the barycentric coordinate to compute any
gradient aka. varying at the point of intersection.
You need the projection matrix to map the pixel coordinate into view
coordinate. Then you need the inverse of the modelview matrix to map
the view coordinate into model coordinate. At this point the problem
is pretty much solved one.
If you can store the scene/dataset hierarchically the intersection
computation should be be several orders of magnitude quicker than
asking feedback from the driver in a form or other, including the
already suggested techniques with the kind of datasets that the OGL
typically renders in the first place. YMMV, in which case something
more specific can be suggested.
Thanks for the alternative idea. To be honest I'd need to do some very
serious reading to get my head round that because I quite simply don't
understand some of the terminology.
Having said that I've no objection to learning about this stuff, after all
thats why I'm currently playing around with OGL anyway.
The solution with glUnproject I'm currently looking at ought to be straight
forward I think but I just can't make it work so its a bit frustrating.
If I can't get a simple thing like that working then what chance have I got
with the more advanced stuff until I have learned a bit more :-)
All the responses the NG has given me thus far contain lots of useful
phrases and terms that will be useful during "Google" searches as part of
the learning process.
Lynton
I'm so sorry. You're right I don't understand. At the risk of getting sworn
at would you be kind enough to look at the following two functions and
add/remove the lines necessary to make it work ?
I wouldn't ask for this favour but the impression I get is that its only
half a dozen or so lines of code that you'd find a breeze to hack together
but its frustrating the hell out of me.
I really think the solution will make some sense to me when I see it because
thats the way I learn best.
Sorry to be a pain and thanks so much for your patience so far with this
thicko. :-)
Lynton
void DrawScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); // Object Coordinates transformed by this to
produce eye Coordinates
glPushMatrix();
rotX += autoRotX * 0.1f;
rotY += autoRotY * 0.1f;
glTranslatef(0, 0, zoomLevel);
glScalef(WORLD_SCALE, WORLD_SCALE, WORLD_SCALE);
glScalef(1.0f, 1.0f, 1.0f); // Multiply current matrix by a general scaling
matrix
glRotatef(rotX, 1, 0, 0); // Multiply current matrix by a rotation matrix
glRotatef(rotY, 0, 1, 0); // Multiply current matrix by a rotation matrix
printf("%s\n", strMouseLatLonDisp);
/* Draw earth */
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture); /* Bind the texture id */
glColor3f(1, 1, 1);
for (int y=0; y<EARTH_LAT_RES; y++) {
glBegin(GL_TRIANGLE_STRIP); /* Was glBegin(GL_QUAD_STRIP) */
for (int x=0; x<EARTH_LON_RES; x++) {
glTexCoord2fv((float*)&mapping[x][y]);
glVertex3fv((float*)&vertices[x][y]);
glTexCoord2fv((float*)&mapping[x][y+1]);
glVertex3fv((float*)&vertices[x][y+1]);
glTexCoord2fv((float*)&mapping[x+1][y]);
glVertex3fv((float*)&vertices[x+1][y]);
glTexCoord2fv((float*)&mapping[x+1][y+1]);
glVertex3fv((float*)&vertices[x+1][y+1]);
}
glEnd();
}
glDisable(GL_TEXTURE_2D);
/* End draw earth */
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
// glMatrixMode(GL_PROJECTION);
// glPopMatrix();
glutSwapBuffers();
}
void MouseMotionNoButtonPressed(int x, int y)
{
/* Grab current viewport */
/* viewport[0]=x viewport[1]=y viewport[2]=width viewport[3]=height */
GLint viewport[4]; // Where the viewport values will be stored.
GLdouble modelview_matrix[16]; // Where the 16 doubles of the modelview
matrix are to be stored.
GLdouble projection_matrix[16]; // Where the 16 doubles of the projection
matrix are to be stored.
GLfloat winX, winY, winZ; // Where our X, Y and Z voordinates are to be
stored.
GLdouble posX, posY, posZ; // Where the final values are to be held.
glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); // Retrieve the
modelview matrix.
glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); // Retrieve the
projection matrix.
glGetIntegerv(GL_VIEWPORT, viewport); // Retrieve the viewport values (X,
Y, Width, Height).
winX = (float)x; // The mouse X coordinate.
winY = (float)viewport[3] - (float)y; // Subtract the current mouse Y
coordinate from
// screen height.
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); //
Get missing Z coordinate.
/* Convert window screen coordinates to openGL object coordinates */
gluUnProject(winX, winY, winZ, modelview_matrix, projection_matrix,
viewport, &posX, &posY, &posZ);
if (posZ > -120.0f) /* Check if the mouse is on the earth ie posZ is >
zFar */
{
sprintf(strMouseLatLonDisp, "Lat: %8.5f Lon: %8.5f", posY, posX);
}
}
Don't you underwstand that you have to have the exact same modelview and
projection matrices presented to gluUnproject that you used to actually draw
the object, if you expect to get object coordinates back from unproject?
move the glGet() calls right after /* End draw earth */ and before you pop
(destroy!) the current matrix stack.
then the values returned by gluUnproject will be you earth lat/long.
jbw
> Don't you underwstand that you have to have the exact same modelview and
> projection matrices presented to gluUnproject that you used to actually
> draw the object, if you expect to get object coordinates back from
> unproject?
>
> move the glGet() calls right after /* End draw earth */ and before you pop
> (destroy!) the current matrix stack.
>
> then the values returned by gluUnproject will be you earth lat/long.
>
>
> jbw
>
>
Hi,
Well, you won't believe it but we got there in the end :-)
I now have working latitude and longitude coordinates. I had to convert from
radians to degrees to get the result I wanted but its now working absolutely
great.
double longitude = RadsToDegs(atan2(-posX, -posZ));
double latitude = 90 - RadsToDegs(acos(posY / EARTH_RADIUS));
Thanks so much for your help and patience with all of this.
Regards
Lynton