Page 1 of 1

Converting window coordinates to opengl

Posted: Wed Mar 31, 2010 2:14 pm
by short

Code: Select all

//CVector3 GetOGLPos(int x, int y)
sf::Vector3f GetOGLPos(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);

	return sf::Vector3f( winX, winY, winZ);
	//return CVector3(posX, posY, posZ);
}
Hey guys, I've been working on this for a few days (between classes and studying) and have had no luck, so

I want to get the current mouse position (note: I am using sfml + opengl and I JUST switched from sdl to sfml so its kinda new) from the window.
I call the GetOGLPos (nehe productions) like this:

Code: Select all

int mouseX = window.GetInput().GetMouseX();
		int mouseY = window.GetInput().GetMouseY();

		sf::Vector3f newCoords =  GetOGLPos(mouseX, mouseY);
This method is not getting me the correct coordinates, I also tried using this:

Code: Select all

sf::RenderWindow window;

sf::Vector2f newCoordinates = window.ConvertCoords(window.GetInput().GetMouseX(), window.GetInput().GetMouseY());
Which also does not seem to be working. Any ideas?

Re: Converting window coordinates to opengl

Posted: Wed Mar 31, 2010 3:17 pm
by qpHalcy0n
Ok, I'm confused as to what you're doing.

Obtaining the mouse position in screen space is a function of the OS's API.

Are you trying to obtain an object space position from a screen space position? That is the only reason you'd de-project the pixel.

What you're saying you want, and what you're showing are completely different concepts.

Re: Converting window coordinates to opengl

Posted: Wed Mar 31, 2010 6:47 pm
by short
Ok, it's most likely stemming from the fact that I'm still new to OGL. I'll try though

Like I said earlier I am using sfml for my window handling.

Code: Select all

sf::RenderWindow window;

	//window.Create(sf::VideoMode(1440, 900, 32), "OGL APP", sf::Style::Fullscreen);
	window.Create(sf::VideoMode(1440, 900, 32), "OGL APP");
	window.SetActive(); // sets this window to be active.
I assume the above code makes sense.

Code: Select all

int mouseX = window.GetInput().GetMouseX();
int mouseY = window.GetInput().GetMouseY();
This code should make sense as well. I am asking the window for the mouse x and y position. If my mouse is in the upper-left hand corner it will return 0,0. If my mouse is in the bottom right corner, it will return 1440, 900.

In OGL the coordinates 0,0 are the center of the screen. Here's my init function, it doesn't do anything too special (still learning) but maybe it will shed some light:

Code: Select all

void init()
{
	glShadeModel(GL_SMOOTH);                // Enable Smooth Shading
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);   // Set background color
	glClearDepth(1.0f);                     // Depth Buffer Setup
	glDisable(GL_DEPTH_TEST);                // Disables Depth Testing (may enable later)
	glDepthFunc(GL_LEQUAL);                 // The Type Of Depth Testing To Do

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(90.0f, 1.0f, 1.0f, 500.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.f, 0.f, -200.f);

}
What I am trying to do is ask the window object for the coordinates, then be able to convert them to OGL coordinates. I am sorry, the last part of the last sentence does NOT use the correct terminology, but I am unsure how else to describe it. Maybe convert them to world coordinates...? IDK.

Anyways, say my mouse is in the top left of the screen. According to my window object, if I ask it where my mouse is it will say 0,0 and if I tell tell OGL to draw at 0,0 it will draw in the center of the screen, not the top left. I'm having difficulties figuring out how to convert the coordinates from what the window object says to OGL. I hope that is more clear.

Re: Converting window coordinates to opengl

Posted: Wed Mar 31, 2010 6:52 pm
by Live-Dimension
OGL's start from the bottom left, and work up, right. I'm not sure why everyone does things differently, its a pain :mrgreen:

ie

3---
2---
1---
0123

Really, the Y is inverted to most X/Y systems. That's all. Why do you say it's in the centre?

Re: Converting window coordinates to opengl

Posted: Wed Mar 31, 2010 7:07 pm
by short
Live-Dimension wrote:OGL's start from the bottom left, and work up, right. I'm not sure why everyone does things differently, its a pain :mrgreen:

ie

3---
2---
1---
0123

Really, the Y is inverted to most X/Y systems. That's all. Why do you say it's in the centre?
Well the reason I say it's in the center, because of this code:

Code: Select all

void Particle::update(sf::Vector3f newCoords)
{
	if(getTimer()->GetElapsedTime() < m_life_timer)
		{
			position = velocity + position;
		}
		else
		{
			//position.x = newCoords.x;
			//position.y = newCoords.y;
			position.y = 0;
			position.x = 0;
			getTimer()->Reset();

			float random = sf::Randomizer::Random(0.0f, 2*(float)M_PI);

			this->velocity.x = cos(random);
			this->velocity.y = sin(random);
		}
}
When I set the position of the particle to 0,0 and then call my draw function, like so:

Code: Select all

void draw(std::vector<Particle> * particles_container, sf::Vector3f newCoords)
{
	std::vector<Particle>::iterator it; // Iterator

	for (it=particles_container->begin();it < particles_container->end();it++)
	{
		it->update(newCoords); // update the particle (position, etc...)
		it->drawMe(); // draw the particle to the screen
	}
}
They all get drawn to the center of the screen. Youtube is down currently, and there is a halfhour wait for the vimeo to finish uploading but I uploaded a video to show exactly what I mean.

http://vimeo.com/10595347[/youtube]

BTW can you imbed a vimeo video in the youtube tags on here? If not, a direct link: http://vimeo.com/10595347

Re: Converting window coordinates to opengl

Posted: Wed Mar 31, 2010 7:19 pm
by qpHalcy0n
Mkay, I see where you're going with this.

Firstly, you don't need to use gluUnProject for this. What this function does is take a position in screen space and go all the way back to object space. This is the space in which you specify vertices in absence of a model (aka world) transform.

Under the assumption that you're getting the correct screen space mouse coordinates relative to the window the only thing you need to do is account for the viewport transform. Now, the code you have there is actually not going to render in screen space.

By setting a view matrix (the translate call after setting the modelview matrix as current) and a projection matrix (gluPerspective after setting the projection matrix as current) you are not rendering in screen space. You are then passing model space coordinates which will be subject to the aforementioned transformations. Now, the easiest way to render in screen space (if this is indeed what you're trying to do) is to simply render a quad that covers the entire buffer. What you'll do is render to what's called NDC (Normalized Device Coordinates) which is a uniform cube from -1 to 1 in all directions (in OpenGL). By setting up identity matrices for both the view and projection transforms you're effectively rendering to NDC space. This is why you say that OpenGL draws to the point (0, 0)...because (0, 0) is the center of the screen in NDC space.

Code: Select all

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glDisable(GL_DEPTH_TEST);   // Turn zbuffer off if you want to use a 3 component vertex //
glBegin(GL_QUADS);
     glVertex3f(-1.0F, -1.0F, 1.0F);
     glVertex3f(-1.0F, 1.0F, 1.0F);
     glVertex3f(1.0F, 1.0F, 1.0F);
     glVertex3f(1.0F, -1.0F, 1.0F);
glEnd();
glEnable(GL_DEPTH_TEST);     // Avoid doing this frequently //

// Restore state //
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
OK, so there's a quad that covers the entire damn buffer. Now....where to PUT that buffer in relation to the parent window. Easy.
Where's your mouse? At some point (x, y).

Well, the only thing to determine is how big of a surface you want to cover here. It's unclear in your post as to what EXACTLY you're drawing here...so we'll just assume its a square. Set up a viewport mapping before actually rendering.
So assuming this surface has a width and height (width, height). The other thing you have to consider here is that in screen space, your OS API or whatever API you're using to give you the mouse coordinates will MOST likely be giving them to you where (0, 0) is the upper left. In OpenGL, (0, 0) is the lower left....so Y is inverted.

Code: Select all

glViewport(x - width * 0.5, (height - y) - height * 0.5, width, height);
So you'd call something like so before you call the draw routine I posted earlier for any other square you seek to draw.

Re: Converting window coordinates to opengl

Posted: Fri Apr 09, 2010 3:09 pm
by short
Okay I did solve this by the way, I just took awhile to get back to what I meant.

I may have described what I wanted to do wrong to you QP, sorry, but here is the code that ended up allowing me to draw where the mouse is:

Code: Select all

void Particle::drawMe()
{
	glDisable(GL_TEXTURE); 
	glDisable(GL_TEXTURE_2D);

	glPushMatrix();

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluOrtho2D(0.0, ENGINE.getWindowWidth(), 0.0, ENGINE.getWindowHeight()); // setup 2d screen view

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		glBegin(GL_POINTS);
			glVertex2d(position.x, position.y);
		glEnd();

	glPopMatrix();

	glEnable(GL_TEXTURE);
	glEnable(GL_TEXTURE_2D);

}
Here is a quick 12second video showing what I really wanted, again I am sorry qp if I didn't convey clearly what I wanted, taking my time learning OGL along with school :)

<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/TxPrvGCG4yE&hl ... ram><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/TxPrvGCG4yE&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>[/youtube]

On a side note, my c++ programming language 3rd edition by Bjarne Stroustrup book got here today !!!! :)


edit: I did A LOT of research into what you were saying QP, I definitely learned a lot, thank you! :)

Re: Converting window coordinates to opengl

Posted: Fri Apr 09, 2010 3:33 pm
by GroundUpEngine
Cool! :)

This reminds of of something I learned a while back it's pretty much same, "orthogonal view" e.g. put stuff between begin and end and it gets drawn 2D

Code: Select all

void VideoSubsystem::orthogonalBegin()
{
        // Get Screen Properties //
        int width = screen->GetScreenSurface()->GetWidth();
        int height = screen->GetScreenSurface()->GetHeight();

        // Begin Orthographic View //
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        gluOrtho2D(0, width, 0, height);
        glScalef(1, -1, 1);
        glTranslatef(0, -height, 0);
        glMatrixMode(GL_MODELVIEW);
    }
    void VideoSubsystem::orthogonalEnd()
    {
        // End Orthographic View //
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
    }