实现纹理映射主要是建立纹理空间与模型空间、模型空间与屏幕空间之间的映射关系(见图 6-28):
其中纹理空间可以定义为u-v 空间,每个轴标范围为 (0.1)。其中对于一个纹理图像,其左下角 v 标为 0.0),右上角标为 1.1)。而对于简单的参数模型,可以方便地建立模型与纹理空间的映射关系,例如球面、圆柱面等。
而根据图形学三维空间变换容易实现模型空间到屏幕空间的变换,因此最终显示在计算机屏幕上的图像即是纹理映射后的结果。
而对于无参数化曲面的纹理映射技术,通常需要将纹理空间到模型空间的映射分解为两个简单映射。这里需要引入一个包围景物的中介三维曲面作为中介映射媒介,主要实现步骤如下:
1.先将二维纹理空间映射为一个简单的三维物体表面,例如球面、圆柱面等;
2.然后将上述中介物体表面的纹理映射到模型表面,例如以模型表面法线与中介模型的交点作为映射点。这样即可实现由纹理空间到模型空间的映射。
VTK中定义了多个类实现纹理空间到模型空间的映射,例如vtkTextureMapToPlane通过一个平面建立纹理空间到模型空间的映射关系;
vtkTextureMapToCylinder 通过圆柱面建立映射关系;
vtkTextureMapToSphere 通过球面建立映射关系。
vtkTexture 则实现加载纹理(在第2章中已经介绍过)。另外,vtkTransformTextureCoords 也是一个非常有用的类,可以实现纹理坐标的平移和缩放,例如,如果要实现重复纹理,只需通过vtkTransformTextureCoords::SetScale()将纹理坐标每个方向进行放大,如由[0,1]变换到[0,101即可。
下例中使用vtkTextureMapToCylinder 来建立纹理映射(TextureMap.cpp):
#include <vtkSmartPointer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkTransformTextureCoords.h>
#include <vtkTexture.h>
#include <vtkTextureMapToSphere.h>
#include <vtkTextureMapToCylinder.h>
#include <vtkBMPReader.h>
#include <vtkTexturedSphereSource.h>
#include <vtkXMLPolyDataReader.h>
//测试:../data/masonry.bmp ../data/cow.vtp
int main (int argc, char *argv[])
{
if (argc < 3)
{
std::cout << "Usage: " << argv[0]
<< "texture(.png)"
<< "model(.vtp)" <<std::endl;
return EXIT_FAILURE;
}
double translate[3];
translate[0] = 10.0;
translate[1] = 0.0;
translate[2] = 0.0;
std::cout << translate[0] << ", "
<< translate[1] << ", "
<< translate[2] << "\n";
vtkSmartPointer<vtkBMPReader> texReader =
vtkSmartPointer<vtkBMPReader>::New();
texReader->SetFileName(argv[1]);
vtkSmartPointer<vtkTexture> texture =
vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(texReader->GetOutputPort());
vtkSmartPointer<vtkXMLPolyDataReader> modelReader =
vtkSmartPointer<vtkXMLPolyDataReader>::New();
modelReader->SetFileName(argv[2]);
vtkSmartPointer<vtkTextureMapToCylinder> texturemap =
vtkSmartPointer<vtkTextureMapToCylinder>::New();
texturemap->SetInputConnection(modelReader->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(texturemap->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper( mapper );
actor->SetTexture( texture );
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renWinInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renWinInteractor->SetRenderWindow( renderWindow );
renderWindow->SetSize(640, 480);
renderWindow->Render();
renderWindow->SetWindowName("TextureMap");
renderWindow->Render();
renderWindow->Render();
renWinInteractor->Start();
return EXIT_SUCCESS;
}
代码中先使用vtkTexture 来加载纹理图像,并通过vtkActor::SetTexture()设置纹理:然后
使用vtkTextureMapToCylinder 来建立纹理空间与模型空间的映射关系;最后通过VTK 渲染
引擎进行渲染,执行结果如图 6-29所示: