图形处理之纹理映射vtkTextureMapToCylinder

本文介绍了VTK中vtkTextureMapToCylinder类的应用,演示了如何使用该类为圆柱形模型设置纹理坐标,并讨论了纹理映射的重复性和缝隙问题。
不少人对vtkTextureMapToCylinder很感兴趣,就介绍它。

vtkTextureMapToCylinder

VTK中定义了多个类实现纹理空间到模型空间的映射,例如vtkTextureMapToPlane通过一个平面建立纹理空间到模型空间的 映射关系;vtkTextureMapToCylinder通过圆柱棉建立映射关系;vtkTextureMapToSphere通过球面建立映射关系。它们的本质是给输入数据的点数据设置纹理坐标,属性数据的一种。

示例演示

首先我们对自己生产的圆柱,应用vtkTextureMapToCylinder。利用vtkCylinderSource产生一个圆柱,注意这个圆柱的轴是和全局坐标Y轴平行。

/**********************************************************************

Copyright (c) Mr.Bin. All rights reserved.
For more information visit:   http://blog.youkuaiyun.com/webzhuce

**********************************************************************/
#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 <vtkCylinderSource.h>

int main (int argc, char *argv[])
{
	vtkSmartPointer<vtkBMPReader> imageReader = vtkSmartPointer<vtkBMPReader>::New();
	imageReader->SetFileName("E:/TestData/lena.bmp");

	vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
	texture->SetInputConnection(imageReader->GetOutputPort());

	vtkSmartPointer<vtkCylinderSource> cylinder = vtkSmartPointer<vtkCylinderSource>::New();
	cylinder->SetHeight(20.0);
	cylinder->SetCenter(0, 0, 0);
	cylinder->SetRadius(3.0);
	cylinder->SetResolution(100);

	vtkSmartPointer<vtkTextureMapToCylinder> texturemap = vtkSmartPointer<vtkTextureMapToCylinder>::New();
	texturemap->SetInputConnection(cylinder->GetOutputPort());
	texturemap->SetPreventSeam(0);

	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("TextureExample");
	renderWindow->Render();
	renderWindow->Render();
	renWinInteractor->Start();

	return EXIT_SUCCESS;
}

运行结果:

这里写图片描述

默认情况下,纹理映射是重复的,如果不想重复,可以调用SetPreventSeam(0)。为什么这样呢?vtkTextureMapToCylinder的原理是将数据的点投影到特定线段(默认利用vtkOBBTree求得最长轴作为这个线段),在这个线段上的比例作为纹理坐标的t;投影的夹角来设置纹理坐标的s,默认情况下0度到180度对应0到1,1180度到360度对应0到1。所以纹理映射是重复的。调用SetPreventSeam(0)后,0度到360度对应0到1。
前面提到vtkCylinderSource生成圆柱的轴平行于Y轴,所以如果圆柱的高度小于直径时,纹理主要映射到圆柱的的圆面。如下图所示。
这里写图片描述
  我们发现无论是否设置SetPreventSeam,都存在白线,即纹理映射有问题。这是为什么?求纹理坐标s时,从0度到360度是闭环的,那么在360度或者180度时,从s=1到s=0没有指明如何纹理映射。OpenGL中可以设置镜像重复解决,VTK中不知道如何设置解决。如果知道,请留言。谢谢。
这里写图片描述

代码下载

在Activiz.NET中添加纹理贴图通常涉及以下几个步骤: 1. **创建纹理对象**:首先需要创建一个纹理对象,并加载所需的图像文件作为纹理。这可以通过`vtkTexture`类来完成。 2. **设置纹理属性**:可以根据需求调整纹理的一些属性,例如重复模式、边缘处理等。 3. **关联纹理到演员**:将创建好的纹理对象与场景中的演员(Actor)相关联,这样纹理就会应用到该演员所表示的几何体上。 4. **更新渲染器**:最后确保渲染器能够正确地显示带有纹理的几何体。 以下是一个简单的代码示例,展示了如何在Activiz.NET中实现纹理贴图的基本流程: ```csharp using System; using System.Windows.Forms; using Kitware.VTK; namespace TextureMappingExample { public partial class Form1 : Form { public Form1() { InitializeComponent(); // 创建一个球体源 vtkSphereSource sphereSource = vtkSphereSource.New(); sphereSource.SetRadius(5.0); sphereSource.Update(); // 创建映射vtkPolyDataMapper mapper = vtkPolyDataMapper.New(); mapper.SetInputConnection(sphereSource.GetOutputPort()); // 创建演员 vtkActor actor = vtkActor.New(); actor.SetMapper(mapper); // 创建纹理 vtkTexture texture = vtkTexture.New(); vtkJPEGReader jPEGReader = vtkJPEGReader.New(); jPEGReader.SetFileName("path_to_your_texture_image.jpg"); // 替换为实际的纹理图片路径 jPEGReader.Update(); texture.SetInputConnection(jPEGReader.GetOutputPort()); // 将纹理应用到演员 actor.SetTexture(texture); // 创建渲染器和渲染窗口 vtkRenderer renderer = vtkRenderer.New(); vtkRenderWindow renderWindow = vtkRenderWindow.New(); renderWindow.AddRenderer(renderer); // 添加演员到渲染器 renderer.AddActor(actor); renderer.SetBackground(0.1, 0.2, 0.4); // 设置背景颜色 // 创建交互器 vtkRenderWindowInteractor renderWindowInteractor = vtkRenderWindowInteractor.New(); renderWindowInteractor.SetRenderWindow(renderWindow); // 初始化并启动交互 renderWindow.Render(); renderWindowInteractor.Start(); } } } ``` 这段代码展示了如何创建一个带有纹理贴图的球体。请注意,你需要替换`jPEGReader.SetFileName`中的路径为你自己的纹理图片路径。此外,根据具体需求,你可能还需要对纹理的其他属性进行配置,比如过滤方式、环绕模式等[^1]。 如果你正在开发更复杂的三维应用程序,可能还需要考虑纹理坐标的生成以及如何正确地将纹理映射到不规则形状的表面上。对于这些情况,可以使用`vtkTextureMapToSphere`、`vtkTextureMapToCylinder`等类来自动计算纹理坐标[^2]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值