[英]How to fix a point on the surface of a 3D model created by texture mapping in OpenGL?
让我们先来看一张图片:
图像中的模型是通过纹理映射创建的。 我想在屏幕上单击鼠标,然后在模型表面放置一个固定点。 而且,随着模型旋转,固定点仍在模型表面上。
我的问题是:
我的想法如下:
这是我的想法。 但是看来这行不通!!! 谁能给我一些建议。 谢谢!
图像中的模型是通过纹理映射创建的。
不,这不对。 首先,根本没有模型。 您所拥有的是一个3D体素数据集,然后您具有一个体积栅格化器,可以通过该数据集“拍摄”射线,将它们集成起来,并为每条射线产生颜色和不透明度值。
此过程不是 (!!!)纹理映射。 纹理贴图是当您绘制“实体”图元时,对于每个片段(片段最终变成像素)将确定纹理数据集中的单个位置并对其进行采样。 但是,如您所愿,它具有执行整体光线整合的功能,可以有效地将整个数据集中的许多体素采样到单个像素中。 这是创建颜色不透明度值的完全不同的方法。
我的问题是:
- 如何在模型表面放置固定点?
您不能,因为那里的数据集没有“固定”曲面点。 您必须定义一些分割操作,以决定沿射线的哪个位置构成“这是表面” 。 最简单的方法是使用阈值截止功能。
- 如何获得不动点的坐标(x,y,z)?
最好的选择是修改体积射线广播代码,将其从积分器更改为分段器。 假设您要使用阈值方法。
典型的体积栅格化器的工作方式如下(通常在着色器中实现):
vec4 output;
for(vec3 pos = start
; length(pos - start) <= length(end - start)
; pos += voxel_grid_increment ){
vec4 t = texture3D(voxeldata, pos);
/* integrate t into output */
}
积分步骤将纹理体素t的输入颜色和不透明度合并为输出颜色+不透明度。 有几种方法可以做到这一点。
您可以将其更改为着色器,该着色器仅在给定的截止阈值处停止循环并发出该体素的位置:
vec3 output;
for(vec3 pos = start
; length(pos - start) <= length(end - start)
; pos += voxel_grid_increment ){
float t = texture3D(voxeldata, pos).r;
if( t > threshold ){
output = pos;
break;
}
}
这样的结果将是一幅图片,在其像素RGB值中编码确定的体素位置。 使用每通道16位纹理格式(或单精度半精度浮点数),您就具有足够的分辨率来解决典型GPU在3D纹理中可以解决的问题。
您需要使用FBO在屏幕外进行此操作。
另一种可行的方法是使用常规体素射线投射器,并在阈值位置修改特定片段的深度值输出。 这种方法的缺点是深度输出修改会破坏性能,因此,如果帧速率很重要,您就不想这样做。 这种方法的好处是,你那么实际上可以使用glReadPixels
的深度缓冲和gluUnProject
在那里你moust指针的深度值。
我的想法如下:
当我在屏幕上单击鼠标时,请使用gluUnproject函数获得两点。 一个点在附近的剪辑平面上,另一个点在远的剪辑平面上。 将两个点连接成一条线。 在步骤2的行上迭代点,然后使用glReadPixels获取迭代点的像素值。 如果值从零跳到非零或从非零跳到零(背景的像素值为零),则找到表面点。
那是行不通的。 出于简单的原因, glReadPixels
与您看到的完全相同。 您无法“选择” glReadPixels
读取像素的深度,因为图片中没有深度。 glReadPixels
只能看到您看到的内容:窗口中显示的平面图像。 您必须遍历体素数据,但是不能事后进行。 您必须实现或修改音量评估器才能提取所需的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.