Waleed
Waleed

Reputation: 177

OpenGL/GLUT - drawing on an object

I'm importing an object file, let's say it's a plane for example. I want to be able to draw on the plane and I just can't seem to figure out how it's done. It's fairly trivial to know the x and y coordinates of the mouse click but what about the z coordinate? I need to be able to do some sort of ray tracing that shoots out a ray and tells me as soon as it reaches the object. What I'm trying to know is the z coordinate of the click which is on the object. There are no other objects in my space is a good assumption.

Upvotes: 0

Views: 1122

Answers (2)

shybovycha
shybovycha

Reputation: 12245

Googling a bit gave me these nice advices:

Some time ago i used them (almost all of them) to create my application. For some reasons i have not got this application now but i can show you my code getting 3D-vector of pick point in a 2 .. 3 hrs =)

If you do want to implement "drawing on an object" i suggest you need to find the UV (texture) coordinates of the pick point and then perform some drawing operations on the object texture.

UPADTE: my picking function implementation

sf::Vector3f ScreenToSpace(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((float) posX, (float) posY, (float) posZ);
}

Here, sf::Vector3f is simply a SFML Vector class.

Upvotes: 1

Kos
Kos

Reputation: 72271

Retrieving the XYZ of a point under the mouse is simple. You don't need ray casting, you just need to retrieve the depth value from the framebuffer under your cursor and then do a gluUnProject.

If you want to paint on objects, you probably want to modify the texture, not the geometry, so you need mostly the UV coordinates, not XYZ. If your object is painted using a single texture, then I suggest to use MRT (multiple render targets) and write the per-pixel UV coordinates to an off-screen buffer during rendering your scene, so that you can read them easily.


Answering your further inquiries:

I want to draw a line on the object so I want to get multiple XYZs and connect them together. I want to draw the lines in front of the object but very very close to it as if it's on it, (or actually on it, whichever is possible.)

If you want to draw "on" the object, then you'd probably run into z-fighting (two fragments having ~same values of depth, resulting in uncool artifacts.

Drawing just a little bit in front could work. (For best results you could save the normals to the off-screen buffer like I described with UVs earlier, so that you'd always offset the line along the direction of surface normal, not just towards the camera).

How do I retrieve the depth value from the framebuffer?

Try glReadPixels with format = GL_DEPTH_COMPONENT.

2- How do I modify a texture?

Just glTexImage* or glTexSubImage*.

Also, the MRT rendering technique sounds awfully complicated and I'm not really an expert on any of this.

You don't really need to be an expert :), MRT itself isn't complicated (it breaks down to outputting colour values onto the screen buffer and any other values onto an off-screen buffer at the same time). I haven't implemented it so far but should be really easy once you grasp shaders and frame buffer objects (which you should definitely do ASAP since that's how you get the most of OpenGL anyway! If I conducted OpenGL classes, shaders would be lesson two).

Upvotes: 1

Related Questions