Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: Drawing a point at the right 3d position

  1. #1
    Junior Member Newbie
    Join Date
    Jun 2017
    Posts
    6

    Drawing a point at the right 3d position

    Hi people,

    I've got a problem, for which I couldn't find any solution so far, despite searching the whole internet for several days and trying different formulas.
    It's about clicking inside the world and drawing a "point" at the right 3d x/z-position (y-position in 3d coordinates should always be at 0).

    What I've got so far, are the sfml mouse-coordinates, but I don't know the formula for getting the right x,z position, when I click somewhere in the 3d world.
    The question is: How to draw the red point at the right position in the 3d world without using any external libraries? (that don't work for me anyway :-)).
    Many thx in advance for any help.

    This is the full code example, where you can rotate and move around freely (the problem is in the line with the formula "pointx = ....., pointz =....":
    I'm sure, there is a simple solution for it without thousands of lines of code......

    Code :
    #include <SFML/Graphics.hpp>
    #include <iostream>
    #define _USE_MATH_DEFINES
    #include <math.h>
    #include <SFML/OpenGL.hpp>
     
    const float height = 1000;
    const float width = height*0.75f;
     
    void myGluPerspective(double fovy, double aspect, double zNear, double zFar)
    {
        double f = 1.0 / tan(fovy * M_PI / 360);
     
    	double xform[16] =
        {
            f / aspect, 0, 0, 0,
            0,          f, 0, 0,
    		0,          0, (zFar + zNear)/(zNear - zFar), -1,
    	    0,          0, (2*zFar*zNear)/(zNear - zFar), 0
        };
        glMultMatrixd(xform);
     
    }
     
    float camposx, camposy, camposz, cammovex, cammovey, cammovez = 0;
    short rotationsvariable = 0;
    float pointx = 0;
    float pointz = 1;
     
    int main()
    {
    	sf::RenderWindow window(sf::VideoMode(height, width, 32), "SFML OpenGL", sf::Style::Close);
     
    	window.setFramerateLimit(40);
        glClearColor(0.8f, 0.8f, 0.8f, 0);
    	glClearDepth(1);
     
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
     
    	myGluPerspective(60,height/width,0.1f,180);
     
    	glTranslatef(0,0,-3);
    	camposz = -3;
     
        while (window.isOpen())
        {
            sf::Event event;
     
    		while (window.pollEvent(event))
    		{
    			switch (event.type)
    			{
    			case sf::Event::Closed:
    				window.close();
    				break;
    			case sf::Event::KeyPressed:
    				if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    				{
    					GLfloat matrixf[16];
    					glGetFloatv(GL_MODELVIEW_MATRIX, matrixf);
     
    					cammovex = (float)sin(rotationsvariable*M_PI/180)*-0.2f;			
    					cammovez = (float)cos(rotationsvariable*M_PI/180)*0.2f;
    					camposx = camposx + cammovex;
    					camposz = camposz + cammovez;
     
    					glLoadIdentity();  
    					myGluPerspective(60,height/width,0.1f,180);
    					glRotatef(rotationsvariable, 0, 1.0f, 0);
    					glTranslatef(camposx,0,camposz);
    					break;
    				}
    				if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    				{
    					GLfloat matrixf[16];
    					glGetFloatv(GL_MODELVIEW_MATRIX, matrixf);
     
    					cammovex = (float)sin(rotationsvariable*M_PI/180)*-0.2f;			
    					cammovez = (float)cos(rotationsvariable*M_PI/180)*0.2f;
    					camposx = camposx - cammovex;
    					camposz = camposz - cammovez;
     
    					glLoadIdentity();  
    					myGluPerspective(60,height/width,0.1f,180);
    					glRotatef(rotationsvariable, 0, 1.0f, 0);
    					glTranslatef(camposx,0,camposz);
    					break;
    				}
    				if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    				{
    					GLfloat matrixf[16];
    					glGetFloatv(GL_MODELVIEW_MATRIX, matrixf);
     
    					rotationsvariable = rotationsvariable - 10;
     
    					if(rotationsvariable==-360)
    					{
    						rotationsvariable = 0;
    					}
    					glLoadIdentity();  
    					myGluPerspective(60,height/width,0.1f,180);
    					glRotatef(rotationsvariable, 0, 1.0f, 0);
    					glTranslatef(camposx,0,camposz);
    					break;
    				}
    				if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    				{
    					rotationsvariable = rotationsvariable + 10;
     
    					if(rotationsvariable==360)
    					{
    						rotationsvariable = 0;
    					}
    					glLoadIdentity();  
    					myGluPerspective(60,height/width,0.1f,180);
    					glRotatef(rotationsvariable, 0, 1.0f, 0);
    					glTranslatef(camposx,0,camposz);
    					break;
    				}
    			case sf::Event::MouseButtonPressed:
    				if (event.mouseButton.button == sf::Mouse::Left) 
    				{
    					sf::Vector2i pixel_pos = sf::Mouse::getPosition(window);
    					sf::Vector2f coord_pos = window.mapPixelToCoords(pixel_pos);
     
    					pointx = -camposx+(coord_pos.x/650)*2.0f-1.5f;			// test
    					//pointz = ......?
    				}
    			}
    		}
     
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    		glColor3f(1,1,1); 
    		glBegin(GL_QUADS);
    		glVertex3f(-1,-1,-1);
    		glVertex3f(-1,-1,1);
    		glVertex3f(1,-1,1);
    		glVertex3f(1,-1,-1);
    		glEnd();
     
     		glColor3f(1,0,0); 
    		glPointSize(10);
    		glBegin(GL_POINTS);
            glVertex3f(pointx, -1.0f, pointz);
            glEnd( );
     
            window.display();
        }
     
        return 0;
    }

  2. #2
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    420
    From where you click, you have an infinite number of points (all along the line from the view center, directed by the vector where you clicked).
    This might help you get all the maths in order to get that vector.

  3. #3
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,411
    Code :
    void screen_to_obj(
        double screen_x, double screen_y,
        double plane[4],
        double *obj_x, double *obj_y, double *obj_z)
    {
        GLdouble modelview[16], projection[16];
        GLint viewport[4];
        glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
        glGetDoublev(GL_PROJECTION_MATRIX, projection);
        glGetIntegerv(GL_VIEWPORT, viewport);
     
        GLdouble x1, y1, z1;
        gluUnProject(screen_x, screen_y,  0.0,  modelview,  projection,  viewport,  &x1, &y1, &z1);
        GLdouble x2, y2, z2;
        gluUnProject(screen_x, screen_y,  1.0,  modelview,  projection,  viewport,  &x2, &y2, &z2);
     
        double k1 = plane[0]*x1 + plane[1]*y1 + plane[2]*z1 + plane[3];
        double k2 = plane[0]*x2 + plane[1]*y2 + plane[2]*z2 + plane[3];
        double t = -k1/(k2-k1);
        *obx_x = x1 + t*(x2-x1);
        *obx_y = y1 + t*(y2-y1);
        *obx_z = z1 + t*(z2-z1);
    }
    ...
    double plane[4] = {0,1,0,0}; // for Y=0
    screen_to_obj(sx, sy, plane, &ox, &oy, &oz);

  4. #4
    Junior Member Newbie
    Join Date
    Jun 2017
    Posts
    6
    I tried this code and it at least compiles perfectly after some modifications :-)
    But, when I leftclick, the point is always drawn directly beneath "me".

    Code :
    double plane[4] = {0,1,0,0};
    screen_to_obj(coord_pos.x, coord_pos.y, plane, &pointx, &pointy, &pointz);

    Did even try to set screen_x to width and so on.....

  5. #5
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,411
    Quote Originally Posted by Bronislaw666 View Post
    But, when I leftclick, the point is always drawn directly beneath "me"
    Check that you're using the coordinates correctly. Also, check that the model-view and projection matrices are set correctly at the point you call obj_to_screen() (here, "correctly" means having the same values as when you use the coordinates with glVertex() or whatever).

    Note that the result is undefined if the viewpoint is on the Y=0 plane. Also note that if the screen coordinates are "above the horizon" (for the Y=0 plane), the calculated point will be behind the viewpoint.

  6. #6
    Junior Member Newbie
    Join Date
    Jun 2017
    Posts
    6
    I experimented with the code, but I got stuck not knowing what to do now. For example: &obj_x,&obj_y,&obj_z don't work. What is it supposed to be? Is it possible to click anywhere in the world with this code? (not only on the small quad)
    Plz help.

    Code :
    #include <SFML/Graphics.hpp>
    #include <iostream>
    #define _USE_MATH_DEFINES
    #include <math.h>
    #include <SFML/OpenGL.hpp>
    #include <gl\glu.h>
    #pragma comment(lib, "glu32")
     
    const float height = 1000;
    const float width = 1000;
     
    void myGluPerspective(double fovy, double aspect, double zNear, double zFar)
    {
    	double f = 1.0 / tan(fovy * M_PI / 360);
     
    	double xform[16] =
    	{
    		f / aspect, 0, 0, 0,
    		0,          f, 0, 0,
    		0,          0, (zFar + zNear)/(zNear - zFar), -1,
    		0,          0, (2*zFar*zNear)/(zNear - zFar), 0
    	};
    	glMultMatrixd(xform);
     
    }
     
    double pointx, pointy, pointz = 0;
     
    void screen_to_obj(
    double screen_x, double screen_y,
    double plane[4],
    double *obj_x, double *obj_y, double *obj_z)
    {
    	GLdouble modelview[16], projection[16];
    	GLint viewport[4];
    	glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
    	glGetDoublev(GL_PROJECTION_MATRIX, projection);
    	glGetIntegerv(GL_VIEWPORT, viewport);
     
    	GLdouble x1, y1, z1;
    	gluUnProject(screen_x, screen_y,  0.0,  modelview,  projection,  viewport,  &x1, &y1, &z1);
    	GLdouble x2, y2, z2;
    	gluUnProject(screen_x, screen_y,  1.0,  modelview,  projection,  viewport,  &x2, &y2, &z2);
     
    	double k1 = plane[0]*x1 + plane[1]*y1 + plane[2]*z1 + plane[3];
    	double k2 = plane[0]*x2 + plane[1]*y2 + plane[2]*z2 + plane[3];
    	double t = -k1/(k2-k1);
    	*obj_x = x1 + t*(x2-x1);
    	*obj_y = y1 + t*(y2-y1);
    	*obj_z = z1 + t*(z2-z1);
    }
     
    int main()
    {
    	sf::RenderWindow window(sf::VideoMode(height, width, 32), "SFML OpenGL", sf::Style::Close);
    	glClearDepth(1);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();
    	myGluPerspective(60,height/width,0.1f,180);
    	glTranslatef(0,0,-3);
     
        while (window.isOpen())
        {
            sf::Event event;
    		while (window.pollEvent(event))
    		{
    			switch (event.type)
    			{
    			case sf::Event::Closed:
    				window.close();
    				break;
    			case sf::Event::MouseButtonPressed:
    				if (event.mouseButton.button == sf::Mouse::Left) 
    				{
    					sf::Vector2i pixel_pos = sf::Mouse::getPosition(window);
    					sf::Vector2f coord_pos = window.mapPixelToCoords(pixel_pos);
     
    					GLdouble modelview[16];
    					glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
    					GLdouble projection[16];
    					glGetDoublev (GL_PROJECTION_MATRIX, projection);
     
    					GLint viewport[4];
    					glViewport(0,0,1000,1000);
    					glGetIntegerv(GL_VIEWPORT, viewport);
     
    					double plane[4] = {0,1,0,0}; // for Y=0
    					//screen_to_obj(sx, sy, plane, &ox, &oy, &oz);
    					screen_to_obj(coord_pos.x,coord_pos.y, plane,&obj_x,&obj_y,&obj_z);
    				}
    			}
    		}
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    		glColor3f(1,1,1); 
    		glBegin(GL_QUADS);
    		glVertex3f(-1,-1,-1);
    		glVertex3f(-1,-1,1);
    		glVertex3f(1,-1,1);
    		glVertex3f(1,-1,-1);
    		glEnd();
    		glColor3f(1,0,0); 
    		glPointSize(10);
    		glBegin(GL_POINTS);
    		glVertex3f(pointx, -1.0f, pointz);
    		glEnd( );
    		window.display();
        }
        return 0;
    }

  7. #7
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,411
    This is likely related to the problem:
    Quote Originally Posted by Bronislaw666 View Post
    Code :
    sf::Vector2f coord_pos = window.mapPixelToCoords(pixel_pos);
    If you're going to mix SFML and OpenGL, I think you'll need to ask on the SFML forums.

  8. #8
    Junior Member Newbie
    Join Date
    Jun 2017
    Posts
    6
    Ok, solved: Indeed the link: http://nehe.gamedev.net/article/usin...project/16013/ from "Silence" and activating the depth buffer helped.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •