如何修复OpenGL中纹理贴图创建的3D模型表面上的点?

时间:2016-07-11 09:28:02

标签: c++ opengl

让我们先看一张图片:

enter image description here

图像中的模型是通过纹理映射创建的。我想在屏幕上点击鼠标,然后我想在模型的表面上放置一个固定点。而且,随着模型的旋转,固定点仍然在模型的表面上。

我的问题是:

  1. 如何将固定点放在模型的表面上?
  2. 如何获得固定点的坐标(x,y,z)?
  3. 我的想法如下:

    1. 当我在屏幕上点击鼠标时,使用gluUnproject函数获取两个点。一点是在近侧平面上,另一点是在远侧平面上。
    2. 连接两个点以形成一条线。
    3. 迭代第2步行的点,并使用glReadPixels获取迭代点的像素值。如果值从零跳到非零或从非零跳到零(背景的像素值为零),则找到表面点。
    4. 这是我的想法。但似乎它不起作用!任何人都可以给我一些建议。谢谢!

2 个答案:

答案 0 :(得分:0)

  

图像中的模型是通过纹理映射创建的。

不,不是。首先,根本没有模型。你有一个体素的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在屏幕外执行此操作。

另一种可行的方法是采用常规体素raycaster并在阈值位置修改特定片段的深度值输出。这种方法的缺点是,深度输出修改会破坏性能,因此如果帧速率很重要,您将不希望这样做。这种方法的好处是,你实际上可以在深度缓冲区上使用glReadPixels并在你的moust指针的位置使用gluUnProject深度值。

  

我的想法如下:

     

使用gluUnproject函数在我有鼠标时得到两个点      点击屏幕。一点是在近夹片平面上      另一个是远方的。将这两点连接起来形成一个      线。      迭代第2步行的点并使用glReadPixels来获取      迭代点的像素值。如果值跳过      零到非零或从非零跳到零(像素值为      背景为零),找到表面点。

那不行。出于简单的原因,glReadPixels看到的与您看到的完全相同。您无法“选择”glReadPixels读取像素的深度,因为图片中没有深度。 glReadPixels只看到你看到的内容:窗口中显示的平面图像。您将不得不迭代体素数据,但您不能在事后进行此操作。您必须实现或修改卷raterizer以提取所需的信息。

答案 1 :(得分:-1)

我不打算在这里写下你需要的全部实现。另外,你可以在网上搜索关于这个主题的find quite alot信息。但是你要找的是{{3} .Nvidia还提出了一种名为"Decals"的技术。简而言之,你绘制一个平面(或封闭的体积)几何体来将贴花纹理投射到它上面。实际过程有点复杂,你可以看到例子。