Where can I call gluUnproject? - opengl

This is a really simple question.
Where can I call gluUnproject? Do I need a current openGL context of some kind?
I looked up the function here, but that isn't telling me if there's any kind of precondition.
I want to do this:
GLdouble near[3];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
eq::Matrix4f projection;
getView()->getProjection(projection);
GLdouble *projMatrix = Matrix4d(projection).array;
glMultMatrixd(projMatrix);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
eq::Matrix4f camera;
getView()->getCamera(camera);
GLdouble *modelMatrix = Matrix4d(camera).array;
glMultMatrixd(modelMatrix);
const PixelViewport pvp = event.context.pvp;
int viewport[4] = {pvp.x, pvp.y, pvp.w, pvp.h};
// SCREEN HEIGHT NOT CONTEXT HEIGHT
const int y = (int)getWindow()->getPixelViewport().h - event.pointerButtonPress.y;
gluUnProject(
event.pointerButtonPress.x,
y,
0.0,
modelMatrix,
projMatrix,
viewport,
&near[0],
&near[1],
&near[2]
);
near[2] = 1.0f;
GLdouble far[3] = {near[0],near[1], -1.0f};
On my server node instead of having to pass it to my render nodes, and have them return the result. The server doesn't have an openGL context. Can I still call gluUnproject?

gluUnProject is not part of OpenGL. It's part of GLU. Technically you can use all of the GLU functions which don't access OpenGL without having a context at all. gluUnProject is such a function.

Mesa's implementation doesn't seem to require a current context.

Related

moving camera using glOrtho

I'm having a problem with moving my camera with glOrtho. I have a small quad in the center and i want to try to move the camera using glOrtho, but it just doesn't seem to be working. The quad doesn't move at all, so the camera isn't moving too i guess. maybe i miss understand how glOrtho works?
here is my code so far.
void Camera::updateCamera(float x, float y, float zoom)
{
camX = x;
camY = y;
this->zoom = zoom;
viewWidth = 320;
viewHeight = 240;
//viewWidth = tan(60) * this->zoom;
//viewHeight = tan(45) * this->zoom;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(camX - viewWidth,
camX + viewWidth,
camY - viewHeight,
camY + viewHeight,
-1,
1);
glMatrixMode(GL_MODELVIEW);
}
and here is where i apply it. i tried to move it along the x axis for 25 points.
void Engine::renderAll()
{
x += 25;
glClear(GL_COLOR_BUFFER_BIT);
shader->use();
camera.updateCamera(x, y, 1.0);
//shader->setUniform4fv("view", camera.getView());
batchManager->renderBatches();
SDL_GL_SwapWindow(window);
}
Yes, I guess you misundertood how glOrtho works. The role of glOrtho is transform a 3D view in a 2D view, using an orthographic projection.
If you want to work with positioning camera in a 3D space, the correct function is normally called LookAt. Once, it seems me that you are using old OpenGL, you can try the glu function gluLookAt
PS. In moderm openGL, this functions is now deprecated. I suggest you to try to learn the modern way.

3D Orthographic Projection

I want to construct a Orthographic projection to make my sun's shadow map look right. Unfortunately, the code is not achieving the desired results as using the regular perspective projection. Here's my code for setting up the projection matrix:
glViewport (0, 0, (GLsizei)shadowMap.x, (GLsizei)shadowMap.y);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
//suns use this
glOrtho(0, shadowMap.x, 0, shadowMap.y, 0.1,1000.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
From what I understand that should be correct. However, after a quick debug render, I noticed that the scene was rendering in a tiny portion of the screen. After some experimentation, I found changing the shadowMap values in glOrtho made it cover the whole texture, but it was really zoomed in. In my perspective projection I use 0.1 and 1000.0 for my near and far, and I've experimented with those and it does change the results, but not get the desired results still. The only time that I get the correct results is when the values are kept with shadowMap.x and shadowMap.y, but like I said, its rendering really small.
What am I doing wrong here? Everything I've read said that the initial code is correct.
EDIT:
Apparently it wasn't clear that this is for the shadow map pass, the regular pass is rendered with perspective and is fine.
Shadow mapping is multi pass algorithm.
You are reffering to the first pass (point 1).
Render scene form light source view into depth texture
Render scene from camera view with depth texture projection mapping enabled.
current fragment xy+depth is then transformed into light projection coordinates and is compared to stored depth on depth texture
if both depths are equal (or nearly equal) current fragment should be considered as lit, otherwise as shadowed.
So everything's fine with your code, store depth values from this pass to depth texture and proceed to point 2.
One thing you should think about is how wide area your light should cover (in world space). With loadidentity on modelview you are attempting to cover 1 world unit x 1 world unit area for you light only.
Consider we have a sphere at 0,0,0 with radius 5.0
We have depth texture of 256,256 dims.
We want to project it along Z onto sphere.
glVieport(0,0,256,256);
glMatrixMode(GL_PROJECTION);
glLoadidentity();
glOrtho(-2.5,2.5,-2.5,2.5,-1000,1000);
glMatrixMode(GL_MODELVIEW);
glLoadidentity();
//flip z, we cast light from obove
glRotate(1,0,0,180);
I don't see where you set the light modelview matrix. You can render a shadow map using the code below:
double* getOrthoMVPmatrix(vector3 position,vector3 lookat,
GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble nearVal, GLdouble farVal)
{
glPushMatrix();
double projection[16];
double modelView[16];
double *matrix = new double [16];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( left, right, bottom, top, nearVal, farVal) ;
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glLoadIdentity();
gluLookAt(position.x,position.y,position.z,lookat.x,lookat.y,lookat.z,0,1,0);
glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glPopMatrix();
matrix = projection*modelView;
return matrix ;
}
void renderShadowMap(void)
{
//"Bind your depth framebuffer"
glViewport(0,0,"Your SM SIZE","Your SM SIZE");
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
double *MVP = getOrthoMVPmatrix( "your light position","your light position" + "your light direction",
-"left","right",
"bottom","top",
"near","far"
) ;
//"call glUseProgram to bind your shader"
// set the uniform MVP we made "
//"Draw your scene "
glViewport(0,0,"screen width","screen height");
}
Your will need to make a multiplication operator for double [16] array. In my case i made a matrix class but do it your way.
Dont forget to call glCullFace(GL_BACK) before drawing your real scene and free MVP after.

gluUnproject returning 0, seems to be related to modelview matrix

I'm working on a 2D image viewer, I want to retrieve openGL mouse position on texture but I can't get it to work if glTranslatef() or glScalef() calls are made on the modelview matrix.
I'm using a QGLWidget , of the famous Qt library.
Here are the important calls :
Resize function :
void ViewerGL::resizeGL(int width, int height){
glViewport (0, 0, width, height);
Display function :
void ViewerGL::paintGL()
{ int w = width();
int h = height();
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
//transX,transY are for panning around the image in the viewer
float left = (0.f+transX) ;
float right = (w+transX) ;
float bottom = (h-transY);
float top = (0.f-transY) ;
glOrtho(left, right, top, bottom, -1, 1);
... later in paintGL:
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
//padx,pady are used to translate the image from the bottom left corner
// to the center of the viewer
float padx,pady;
padx= ((float)width() - _dw.w()*zoomFactor)/2.f; // _dw.w is the width of the texture
pady =((float)height() - _dw.h()*zoomFactor)/2.f ;// _dw.h is the height of the texture
glTranslatef( padx , pady, 0);
//zoomX,zoomY are the position at which the user required a zoom
glTranslatef(-zoomX,-zoomY, 0.f);
glScalef(zoomFactor, zoomFactor,0.f);
glTranslatef(zoomX ,zoomY, 0.f);
Now here is my function to retrieve the openGL coordinates :
QPoint ViewerGL::openGLpos(int x,int y){
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX=0, winY=0, winZ=0;
GLdouble posX=0, posY=0, posZ=0;
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
winX = (float)x;
winY = height()- y;
if(winY == 0) winY =1.f;
glReadPixels( x, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
return QPoint(posX,posY);
}
So far , here is what I noticed:
The code like this returns always (0,0) and GLU_FALSE is returned from gluUnproject. I read somewhere on a forum that it could be because of the modelview matrix, so I put the identity matrix instead, but,if I do it, I get exactly the coordinates of the mouse in the window...
Before , I dealt with the zoom using the orthographic projection, but I couldn't make it work perfectly, so to make it simpler I decided to retrieve openGL position, and use glTranslatef/glScalef instead .
If I remove all the translating / scaling stuff in the paintGL function, everything is working...but the zoom doesn't work :x)
I'm requesting your help to make this damned zoom to point working, using the gluUnProject solution;)
Aigth , nevermind, I found the solution : I was zeroing out the z in glScalef(x,y,z)
so it made the matrix non-invertible...

glTranslatef Equivalent without it

Ok so I'm hooking into a game to retrieve data from it and use it. I got as far as hooking text (via CallLists).
The game uses:
glNewlist()
glBegin(GL_QUADS)
glVertex2i(....); //Stored the location of each char in the bitmap above..
glTexCoords2f(....); //Not sure what this is..
glEnd()
glEndList()
glCallList(876); //Represents a single character in the above bitmap.
glLoadIdentity(); //Resets the matrix.
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTranslatef(336, 196, 0); //Places it on screen somehow! :S? This is what I need to know.
glColor4ub(0, 0, 0, 255); //Colours the text.
LoadIdentity(); //Resets the matrix and does the next character.
glCallList(877); //Next char.
To render text to the screen. Is there a way I can figure out the coords of the text on the screen? I have access to all functions via Detours.
I'm not sure what the glTranslate did. How can I get the X and Y of the text?
I've used this to project the coords from glTranslate but it still projects it wrong. What do I pass to my WorldVector? It is just a struct with X, Y, Z. I've passed it the glTranslate coords but that doesn't work.
bool WorldToScreen(GLfloat &X, GLfloat &Y, Vector3D World, GLdouble* ModelViewMatrix, GLdouble* ProjectionMatrix)
{
GLint ViewPort[4];
GLdouble Screen[3];
glGetIntegerv(GL_VIEWPORT, ViewPort);
if(gluProject(World.X, World.Y, World.Z, ModelViewMatrix, ProjectionMatrix, ViewPort, &Screen[0], &Screen[1], &Screen[2]) == GL_TRUE)
{
X = Screen[0];
Y = ViewPort[3] - Screen[1];
return true;
}
return false;
}
That really depends, if you are drawing your text in orthographic mode, whatever you pass into glTranslatef is the actual screen coordinate, where if you are in perspective mode, you will have to pass them through the transformation pipeline to get the screen coordinates, I believe the function for doing this would be in the GLU library called gluProject, where gluUnProject would bring screen coordinates to world space
translate to world position
translate to view position
divide by W (Copy of Z) to get projection coordinates
ScreenX = Px * ScreenWidth/2 + ScreenWidth/2
ScreenY = -Py * ScreenWidth/2 + ScreenWidth/2
Here is an example of translating and calling your list in orthographic
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(336.0f, 196.0f, 0.0f);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f); //Red
glCallList(877); //Or whatever list you wish to call
At this point, you may want to have the width of the next character to write, and simply translate value to put your text directly to the right of it,
By the way, there is a great free to use library called FreeType 2 , Blizzard uses it for there games, as well as myself, the former of which gives it good credibility.
If I am still not answering your question be sure to let me know

handling click on 3d or 2d figure in opengl

how to handle clik on specific 3d or 2d object in opengl, for example i have the following code
void Widget::drawCircle(float radius) {
glBegin(GL_TRIANGLE_FAN);
for (int i = 0; i < 360; i++) {
float degInRad = i*DEG2RAD;
glVertex2f(cos(degInRad) * radius, sin(degInRad) * radius);
}
glEnd();
}
So i need to handle click on this circle, is there any solutions for this problem?
When I need to detect clicks, I usually do my ordinary draw loop, but instead of drawing the objects with texturing, lighting and other effects enabled, I draw each of them with flat/no shading, each in a different color. I then check the color on the pixel the mouse is on, and map backwards from the color returned from the framebuffer to the object that I drew with that color.
Perhaps this technique is useful for you, too.
Take a look into this nehe tutorial item. It is very complex, but it shows how opengl picking works. In my opinion, if you need it, you are better with some game engine then with opengl.
Here is another (similar) way of selecting items in opengl.
opengl mouse raytracing will provide you with all details how to select items in opengl. This thread even provides the code how it is done :
Vector3 World::projectedMouse(float mx, float my){
GLdouble model_view[16];
GLint viewport[4];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble dx, dy, dz;
glGetDoublev(GL_MODELVIEW_MATRIX, model_view);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)mx;
winY = (float)viewport[3] - (float)my;
glReadPixels ((int)mx, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
gluUnProject(winX, winY, 0, model_view, projection, viewport, &bx, &by, &bz);
Vector3 pr2 = Vector3(bx, by, bz);
glColor3f(1,0,0);
glBegin (GL_LINE_LOOP);
glVertex3f(player->getPosition().x, player->getPosition().y + 100, player->getPosition().z); // 0
glVertex3f(pr.x,pr.y,pr.z); // 1
glVertex3f(player->getPosition().x, player->getPosition().y, player->getPosition().z); // 0
glEnd();
return pr;
}