OpenGL/GLUT - 在对象上绘图

发布于 2024-12-23 04:35:05 字数 157 浏览 0 评论 0原文

我正在导入一个对象文件,例如,它是一个平面。我希望能够在飞机上画画,但我似乎不知道它是如何完成的。知道鼠标点击的 x 和 y 坐标相当简单,但是 z 坐标呢?我需要能够进行某种光线追踪,发射光线并在光线到达物体时立即通知我。我想知道的是对象上单击的 z 坐标。我的空间中没有其他物体是一个很好的假设。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

魂归处 2024-12-30 04:35:05

谷歌搜索给了我这些很好的建议:

前段时间我用过他们(几乎所有人)来创建我的应用程序。由于某些原因,我现在还没有得到这个应用程序,但我可以向您展示我的代码,在 2 .. 3 小时内获取拾取点的 3D 向量 =)

如果您确实想实现“在对象上绘图”,我建议您需要找到拾取点的UV(纹理)坐标,然后对对象纹理执行一些绘制操作。

UPADTE:我的选择函数实现

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);
}

在这里,sf::Vector3f只是一个SFML Vector 类。

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.

放手` 2024-12-30 04:35:05

检索鼠标下的点的 XYZ 很简单。您不需要光线投射,只需从光标下的帧缓冲区中检索深度值,然后执行 gluUnProject

如果您想在对象上绘画,您可能需要修改纹理,而不是几何形状,因此您主要需要 UV 坐标,而不是 XYZ。如果您的对象是使用单个纹理绘制的,那么我建议使用 MRT(多个渲染目标)并在渲染场景期间将每像素 UV 坐标写入屏幕外缓冲区,以便您可以轻松读取它们。


回答您的进一步询问:

我想在对象上画一条线,所以我想获取多个 XYZ 并将它们连接在一起。我想在对象前面绘制线条,但距离它非常非常近,就好像它在它上面一样(或者实际上在它上面,无论哪种可能。)

如果你想在对象“上”绘制,那么你可能会遇到 z-fighting (两个片段具有相同的深度值,导致不酷的工件 。

画一点点 前面的可以工作。(为了获得最佳结果,您可以将法线保存到屏幕外缓冲区,就像我之前描述的 UV 一样,这样您就可以始终沿着表面法线的方向偏移线,而不仅仅是朝着表面法线方向偏移。相机)。

如何从帧缓冲区检索深度值?

尝试 glReadPixels格式 = GL_DEPTH_COMPONENT

2- 如何修改纹理?

只需 glTexImage*glTexSubImage*

此外,MRT 渲染技术听起来非常复杂,而且我并不是这方面的真正专家。

您实际上不需要成为专家:),MRT 本身并不复杂(它分解为将颜色值输出到屏幕缓冲区,同时将任何其他值输出到屏幕外缓冲区)。到目前为止我还没有实现它,但一旦你掌握了着色器和帧缓冲区对象,应该会很容易(你绝对应该尽快做,因为这就是你如何充分利用 OpenGL 的方法!如果我上 OpenGL 课程,着色器将是第二课) )。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文