VTK的基本概念(一)
文章目录
- 三维场景的基本要素
- 1.灯光
- 2.相机
- 3.颜色
- 4.纹理映射
三维场景的基本要素
1.灯光
在三维渲染场景中,可以有多个灯光的存在,灯光和相机是三维渲染场景的必备要素,如果没有指定的话,vtkRenderer会自动创建默认的灯光和相机。在VTK里用类vtkLight来表示渲染场景中的灯光,与现实中的灯光类似,VTK中的vtkLight实例也可以打开、关闭,设置灯光的颜色,照射位置(焦点)、灯光所在的位置、强度等。
vtkLight可以分为位置灯光(也叫聚光灯)和方向灯光。
位置灯光:即光源位置在渲染场景中的某个位置,可以指定灯光的衰减值、锥角等;
方向灯光:即指光源位置在无穷远,可以认为光线是平行的,比如自然界中的太阳光。光源的位置和焦点的连线定义光线的方向。默认的vtkLight为方向灯光。
vtkLight提供了一系列方法来设置光源的位置、颜色、类型和强度等。以下是 vtkLight 的一些常用方法。
位置与方向:
SetPosition(double x, double y, double z):设置光源的位置。
GetPosition():获取光源的位置,返回一个三元组(x, y, z)。
SetFocalPoint(double x, double y, double z):设置光源的焦点位置,即光线指向的方向。
GetFocalPoint():获取光源的焦点位置。
颜色与亮度:
SetColor(double r, double g, double b):设置光源的颜色,参数为 RGB 值(范围 0-1)。
GetColor():获取光源的颜色,返回 RGB 三元组。
SetIntensity(double intensity):设置光源的亮度(强度),值范围通常为 0 到 1。
GetIntensity():获取光源的亮度(强度)值。
光源类型:
SetLightTypeToHeadlight():将光源类型设置为“头灯”,光源总是朝向相机,无论位置如何变化。
SetLightTypeToCameraLight():将光源类型设置为“相机光源”,光源位置与相机位置一致,随相机移动。
SetLightTypeToSceneLight():将光源类型设置为“场景光源”,光源位于场景中的固定位置。
GetLightType():获取当前光源的类型。
衰减:
SetAttenuationValues(double constant, double linear, double quadratic):设置光源的衰减系数,分别控制常数、线性和二次衰减因子。
GetAttenuationValues():获取光源的衰减系数。
开关控制:
SwitchOn() / SwitchOff():开启或关闭光源。
SetSwitch(bool on):直接设置光源是否开启,true 表示开启,false 表示关闭。
GetSwitch():获取光源的开关状态,返回布尔值。
阴影设置:
SetShadowAttenuation(double attenuation):设置光源阴影的衰减值,用于控制阴影的强度。
GetShadowAttenuation():获取阴影的衰减值。
其他常用方法:
DeepCopy(vtkLight *light):复制另一个光源的属性到当前光源。
SetConeAngle(double angle):设置聚光灯的角度,仅在聚光灯模式下生效。
SetExponent(double exponent):设置聚光灯的光强指数,指数越大,光照越集中。
以下是一个使用 vtkLight 的示例,展示了如何在 VTK 场景中创建和设置光源的属性。该示例创建了一个简单的场景,包括一个立方体和一个自定义光源,并演示如何设置光源的位置、颜色、类型等。
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkLight.h>QtVTKDemo::QtVTKDemo(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);this->setFixedSize(800, 600);QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());// 创建渲染器、渲染窗口和交互器vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);// 创建一个立方体vtkSmartPointer<vtkCubeSource> cubeSource = vtkSmartPointer<vtkCubeSource>::New();// 创建映射器并连接立方体数据vtkSmartPointer<vtkPolyDataMapper> cubeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();cubeMapper->SetInputConnection(cubeSource->GetOutputPort());// 创建演员并设置映射器vtkSmartPointer<vtkActor> cubeActor = vtkSmartPointer<vtkActor>::New();cubeActor->SetMapper(cubeMapper);// 将立方体添加到渲染器中renderer->AddActor(cubeActor);// 创建光源vtkSmartPointer<vtkLight> light = vtkSmartPointer<vtkLight>::New();// 设置光源的位置、焦点、颜色和亮度light->SetPosition(1.0, 1.0, 1.0); // 设置光源位置light->SetFocalPoint(0.0, 0.0, 0.0); // 设置光源焦点,使光源指向立方体中心light->SetColor(1.0, 1.0, 1.0); // 设置光源颜色为白色light->SetIntensity(0.8); // 设置光源强度为0.8// 设置光源类型为场景光源(固定在场景中的位置,不随相机移动)light->SetLightTypeToSceneLight();// 将光源添加到渲染器renderer->AddLight(light);// 设置渲染器背景颜色renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色背景// 开始渲染和交互ui.openGLWidget->setRenderWindow(renderWindow);
}
注意:因为Render里可以有多个灯光,所以VTK提供的接口是AddLight()而不是SetLight()。
2.相机
在VTK中,相机(vtkCamera)是一个用于控制三维场景中视角的对象,相机在VTK的3D渲染中扮演着重要的角色,因为它决定了观察者如何看待场景。相机的位置、朝向和投影方式可以通过vtkCamera类来控制。相机投影示意图如下所示:
从上图可以看出与相机投影相关的要素主要有以下几个:
相机位置:相机所处的位置,用vtkCamera::SetPosition()方法设置。
相机焦点:用vtkCamera::SetFocusPoint()方法设置,默认的焦点位置在世界坐标系的原点。
朝上方向:朝上方向即哪个方向为相机朝上的方向。就好比直立看东西,方向为头朝上,看到的东西也是直立的。如果倒立看东西,这时方向为头朝下,看到的东西就是倒立的。相机位置、相机焦点和朝上方向三个因素确定了相机的实际方向,即确定相机的视图。
投影方向:相机位置到相机焦点的向量方向即为投影方向。
投影方法:该要素用于确定Actor是如何映射到像平面的。vtkCamera定义了两种投影方法;一种是正交投影,也叫平行投影,即进入相机的光线与投影方向是平行的;另一种是透视投影,即所有光线相交于一点。该投影方法最符合人类眼睛对于景物所产生的近大远小的视觉习惯。
视角:透视投影时需要指定相机的视角(View Angle),默认的视角大小为30度,可以用vtkCamera::SetViewAngle()方法设置。
前后裁剪平面:裁剪平面与投影方向相交,一般与投影方向也是垂直的,裁剪平面主要用于评估Actor与相机距离的远近,只有在前后裁剪平面之间的Actor才是可见的。裁剪平面的位置可以用vtkCamera:SetClippingRange()方法设置。
以下是一个使用 vtkCamera的示例
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkLight.h>
#include <vtkCamera.h>QtVTKDemo::QtVTKDemo(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);this->setFixedSize(800, 600);QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());// 创建渲染器、渲染窗口和交互器vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();// 创建并设置相机vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();camera->SetPosition(10, 10, 10); // 设置摄像机的位置坐标。默认位置是 (0, 0, 1)。camera->SetFocalPoint(0, 0, 0); // 设置摄像机的焦点,即摄像机所看的目标点位置。camera->SetViewAngle(40); // 设置视角(视场角),角度以度数表示,通常在30到45度之间。视角决定了摄像机的视野范围。camera->SetClippingRange(0.1, 1000); // 设置近裁剪平面和远裁剪平面。该函数控制显示的最近和最远距离。(设置裁剪平面范围为 0.1 到 1000)camera->SetViewUp(0, 1, 0); // 设置视上方向,通常用于控制摄像机的“上”方向。(设置摄像机上方向为 (0, 1, 0))renderer->SetActiveCamera(camera);vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);// 创建一个立方体vtkSmartPointer<vtkCubeSource> cubeSource = vtkSmartPointer<vtkCubeSource>::New();// 创建映射器并连接立方体数据vtkSmartPointer<vtkPolyDataMapper> cubeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();cubeMapper->SetInputConnection(cubeSource->GetOutputPort());// 创建演员并设置映射器vtkSmartPointer<vtkActor> cubeActor = vtkSmartPointer<vtkActor>::New();cubeActor->SetMapper(cubeMapper);// 将立方体添加到渲染器中renderer->AddActor(cubeActor);// 创建光源vtkSmartPointer<vtkLight> light = vtkSmartPointer<vtkLight>::New();// 设置光源的位置、焦点、颜色和亮度light->SetPosition(1.0, 1.0, 1.0); // 设置光源位置light->SetFocalPoint(0.0, 0.0, 0.0); // 设置光源焦点,使光源指向立方体中心light->SetColor(1.0, 1.0, 1.0); // 设置光源颜色为白色light->SetIntensity(0.8); // 设置光源强度为0.8// 设置光源类型为场景光源(固定在场景中的位置,不随相机移动)light->SetLightTypeToSceneLight();// 将光源添加到渲染器renderer->AddLight(light);// 设置渲染器背景颜色renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色背景renderWindow->SetSize(600, 600); // 设置渲染窗口大小// 开始渲染和交互ui.openGLWidget->setRenderWindow(renderWindow);
}
另外vtkCamera 类中的 Dolly()、Roll()、Azimuth()、Yaw()、Elevation()、Pitch() 和 Zoom() 函数提供了丰富的摄像机视角调整选项,允许你通过不同的方式调整摄像机的位置、旋转角度和缩放比例。
vtkCamera运动方向示意图
Dolly(double value): 用于沿视线方向拉近或拉远视图,值大于1会拉近,小于1会拉远。Dolly() 影响摄像机和焦点的相对距离,改变场景的纵深感。
Roll(double angle):沿摄像机视线方向旋转摄像机,使画面有“滚动”效果。通常用于模拟摄像机在视线方向上的滚动旋转。
Azimuth(double angle):绕摄像机的垂直轴(Y轴)旋转视角,相当于左右旋转视图。用于改变水平方向的视角。
Yaw(double angle):Yaw() 和 Azimuth() 类似,都是绕 Y 轴旋转,但它直接影响摄像机的方向而不是整个视图。通常用于改变摄像机的指向。
Elevation(double angle):绕 X 轴旋转摄像机视角,改变垂直方向的视角,类似于仰视或俯视场景。
Pitch(double angle):Pitch() 和 Elevation() 类似,绕 X 轴旋转摄像机,但直接影响摄像机的指向而非视图。
Zoom(double factor):用于缩放视图,影响摄像机的视角大小。factor 值大于1会放大,小于1会缩小。
以下示例展示如何结合使用这些函数来调整摄像机的视角
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
camera->SetPosition(0, 0, 10); // 设置摄像机位置
camera->SetFocalPoint(0, 0, 0); // 设置摄像机焦点camera->Dolly(1.2); // 拉近视图
camera->Roll(45); // 视线滚动45度
camera->Azimuth(30); // 水平旋转30度
camera->Yaw(20); // 绕Y轴旋转20度
camera->Elevation(15); // 垂直旋转15度
camera->Pitch(10); // 绕X轴旋转10度
camera->Zoom(1.5); // 放大视图1.5倍
从上述可以看出,Dolly 和 Zoom 都用于拉近或拉远视图,但 Dolly 更适合产生真实的深度感;Roll 适合调整画面旋转感(滚动);Azimuth 和 Elevation 改变视角的水平方向和垂直方向,Yaw 和 Pitch 改变摄像机的方向而不影响场景整体视图。
3.颜色
颜色是Actor重要的属性之一。VTK采用RGB和HSV两种颜色系统来描述颜色。
RGB颜色系统由三个颜色分量:红色(R)、绿色(G)、和蓝色(B)的组合表示,在VTK里,这三个分量的取值范围都是0~1,(0, 0, 0)表示黑色,(1, 1, 1)表示白色。vtkProperty::SetColor(r, g, b)采用的就是RGB颜色系统设置颜色属性值。
HSV颜色系统同样也是由三个分量来决定颜色,它们分别是:色相(Hue),表示颜色的基本属性,就是通常所说的颜色名称,如红色、黄色;饱和度,是指颜色的纯度,其值越高则越纯;值(Value,也就是强度Intensity或者亮度Bright),值为0通常表示的是黑色,值为1表示的是最亮的颜色。这三个分量的取值范围0~1。类vtkLookupTable提供了HSV颜色系统设置的方法。
(1).设置颜色属性
可以直接在渲染的对象上设置颜色属性,包括:
Actor的颜色设置:通过actor->GetProperty()->SetColor()来设置一个对象的颜色。
边界颜色和透明度:使用SetEdgeColor()和SetOpacity()等方法对渲染物体的边界颜色和透明度进行控制。
环境光、漫反射和镜面反射颜色:通过SetAmbientColor()、SetDiffuseColor()、SetSpecularColor()等方法来设置材质的反射特性。
以下是一个简单的VTK示例,用于演示颜色属性设置,包括颜色、边界颜色、透明度、环境光、漫反射和镜面反射等:
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkSphereSource.h>
#include <vtkProperty.h>QtVTKDemo::QtVTKDemo(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);this->setFixedSize(800, 600);QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());// 创建渲染器、渲染窗口和交互器vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);// 创建一个球体数据源vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();sphereSource->SetRadius(5.0);// 将球体数据映射到几何数据vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();sphereMapper->SetInputConnection(sphereSource->GetOutputPort());// 创建演员并设置映射器vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();sphereActor->SetMapper(sphereMapper);// 设置颜色属性sphereActor->GetProperty()->SetColor(0.1, 0.6, 0.8); // 设置球体颜色(RGB: 浅蓝色)sphereActor->GetProperty()->SetEdgeColor(0.0, 0.0, 0.0); // 设置边界颜色(黑色)sphereActor->GetProperty()->EdgeVisibilityOn(); // 开启边界显示sphereActor->GetProperty()->SetOpacity(0.7); // 设置透明度(0.0 = 全透明,1.0 = 不透明)sphereActor->GetProperty()->SetAmbientColor(0.2, 0.2, 0.2); // 设置环境光颜色sphereActor->GetProperty()->SetDiffuseColor(0.1, 0.6, 0.8); // 设置漫反射颜色sphereActor->GetProperty()->SetSpecularColor(1.0, 1.0, 1.0); // 设置镜面反射颜色(白色)sphereActor->GetProperty()->SetSpecular(0.5); // 镜面反射强度sphereActor->GetProperty()->SetSpecularPower(30.0); // 镜面反射的光泽度// 将立方体添加到渲染器中renderer->AddActor(sphereActor);// 设置渲染器背景颜色renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色背景renderWindow->SetSize(600, 600); // 设置渲染窗口大小// 开始渲染和交互ui.openGLWidget->setRenderWindow(renderWindow);
}
(2).设置颜色映射
在VTK中,颜色映射是将标量数据映射到颜色的一种方式,常用于对科学数据的可视化。颜色映射可以使用vtkLookupTable或者vtkColorTransferFunction来实现。
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkSphereSource.h>
#include <vtkProperty.h>
#include <vtkFloatArray.h>
#include <vtkLookupTable.h>
#include <vtkPointData.h>QtVTKDemo::QtVTKDemo(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);this->setFixedSize(800, 600);QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());// 创建渲染器、渲染窗口和交互器vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);// 创建一个球体数据源vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();/*作用:设置球体在水平(绕Z轴)方向的分段数量。参数:传入一个整数值,表示沿着球体赤道平分的分段数量。影响:增大 ThetaResolution 值会使球体在水平方向上更光滑细腻,但会增加计算量和渲染时间。*/sphereSource->SetThetaResolution(30); // 会将球体的水平方向分成 30 个分段。/*作用:设置球体在垂直方向的分段数量,从南极到北极。参数:传入一个整数值,表示沿着球体从底到顶(南极到北极)平分的分段数量。影响:增大 PhiResolution 值会使球体在垂直方向上更加平滑,同样会增加计算和渲染成本。*/sphereSource->SetPhiResolution(30); // 会将球体的垂直方向分成 30 个分段。/*低分辨率:SetThetaResolution(10) 和 SetPhiResolution(10) 将创建一个较粗糙的球体,因为分段少。高分辨率:SetThetaResolution(50) 和 SetPhiResolution(50) 会生成一个非常光滑的球体,但计算量和渲染成本也会增加。SetThetaResolution 和 SetPhiResolution 的值越大,球体的外观越平滑,细节越丰富,但会带来更高的计算开销。*/sphereSource->Update();// 创建一个标量数据数组,将标量数据与球体的顶点关联vtkSmartPointer<vtkFloatArray> scalars = vtkSmartPointer<vtkFloatArray>::New();for (vtkIdType i = 0; i < sphereSource->GetOutput()->GetNumberOfPoints(); ++i){scalars->InsertNextValue(static_cast<float>(i % 100) / 100.0); // 模拟生成标量数据}sphereSource->GetOutput()->GetPointData()->SetScalars(scalars);// 创建颜色映射表(Lookup Table)vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();lookupTable->SetNumberOfTableValues(256); // 设置颜色表的大小lookupTable->SetRange(0.0, 1.0); // 标量值的范围lookupTable->Build();// 设置颜色映射的渐变(如从蓝色到红色)for (int i = 0; i < 256; ++i) {double r = static_cast<double>(i) / 255.0;double b = 1.0 - r;lookupTable->SetTableValue(i, r, 0.0, b); // 渐变从蓝色到红色}// 将球体数据映射到几何数据vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();sphereMapper->SetInputConnection(sphereSource->GetOutputPort());sphereMapper->SetLookupTable(lookupTable); // 设置映射表sphereMapper->SetScalarRange(0.0, 1.0); // 设置标量数据的范围,映射到颜色表// 创建演员并设置映射器vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();sphereActor->SetMapper(sphereMapper);// 设置颜色属性sphereActor->GetProperty()->SetColor(0.1, 0.6, 0.8); // 设置球体颜色(RGB: 浅蓝色)sphereActor->GetProperty()->SetEdgeColor(0.0, 0.0, 0.0); // 设置边界颜色(黑色)sphereActor->GetProperty()->EdgeVisibilityOn(); // 开启边界显示sphereActor->GetProperty()->SetOpacity(0.7); // 设置透明度(0.0 = 全透明,1.0 = 不透明)sphereActor->GetProperty()->SetAmbientColor(0.2, 0.2, 0.2); // 设置环境光颜色sphereActor->GetProperty()->SetDiffuseColor(0.1, 0.6, 0.8); // 设置漫反射颜色sphereActor->GetProperty()->SetSpecularColor(1.0, 1.0, 1.0); // 设置镜面反射颜色(白色)sphereActor->GetProperty()->SetSpecular(0.5); // 镜面反射强度sphereActor->GetProperty()->SetSpecularPower(30.0); // 镜面反射的光泽度// 将立方体添加到渲染器中renderer->AddActor(sphereActor);// 设置渲染器背景颜色renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色背景renderWindow->SetSize(600, 600); // 设置渲染窗口大小// 开始渲染和交互ui.openGLWidget->setRenderWindow(renderWindow);
}
上述代码中创建了一个vtkFloatArray并为球体的每个顶点设置了一个标量值。这里是模拟数据,将每个顶点的标量值设置为i % 100 / 100.0。vtkLookupTable:创建了一个颜色映射表,并为其设置范围为0.0到1.0。然后通过一个循环为颜色表中的每个值设置一个渐变颜色,从蓝色到红色。将颜色表设置到vtkPolyDataMapper的映射器上,并使用SetScalarRange方法来指定标量数据的范围,使其映射到颜色表中。最后创建渲染窗口和交互器,将颜色映射应用到的球体显示在窗口中。
在计算机图形学中,RGB颜色模型用于表示颜色,其中 R(红)、G(绿)、B(蓝) 三个通道的组合决定最终的颜色。
RGB每个通道的取值范围为:
0 到 255:通常用于8位色深的颜色表示(即0-255范围的整数)。这个范围是最常见的 RGB 表示法,适用于图像处理、计算机显示器、网页设计等。
0.0 到 1.0:用于归一化的浮点表示法(即0.0-1.0的浮点数)。在计算机图形学和许多绘图库(例如 OpenGL、VTK)中常用这种表示法。0.0表示最小强度(无光),1.0表示最大强度(全亮)。
通过不同强度的 RGB 值组合可以生成不同的颜色。例如:
(255, 0, 0) 或 (1.0, 0.0, 0.0):纯红色
(0, 255, 0) 或 (0.0, 1.0, 0.0):纯绿色
(0, 0, 255) 或 (0.0, 0.0, 1.0):纯蓝色
(255, 255, 255) 或 (1.0, 1.0, 1.0):白色(所有通道全亮)
(0, 0, 0) 或 (0.0, 0.0, 0.0):黑色(所有通道关闭)
在编程中,可以方便地将0-255范围的 RGB 值转换为0.0-1.0的归一化形式。例如:
double normalizedR = r / 255.0;
double normalizedG = g / 255.0;
double normalizedB = b / 255.0;
4.纹理映射
纹理映射是创建逼真效果的强大的图形工具,它的原理是渲染时把二维的图像贴到物体的表面上,根据二维图像渲染出丰富多彩的效果,所以叫纹理贴图。纹理映射需要三个要素:待贴图的表面、纹理映射以及纹理坐标。其中纹理映射在VTK中就是vtkImageData的数据集,而纹理坐标则用于控制纹理图在表面的位置。
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkPNGReader.h>
#include <vtkTexture.h>QtVTKDemo::QtVTKDemo(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);this->setFixedSize(800, 600);QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());// 创建渲染器、渲染窗口和交互器vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);// 创建球体数据源vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();sphereSource->SetThetaResolution(30);sphereSource->SetPhiResolution(30);sphereSource->Update();// 加载纹理图像vtkSmartPointer<vtkPNGReader> pngReader = vtkSmartPointer<vtkPNGReader>::New();pngReader->SetFileName("VTKDemo.png");vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();texture->SetInputConnection(pngReader->GetOutputPort());// 创建映射器并连接立方体数据vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();sphereMapper->SetInputConnection(sphereSource->GetOutputPort());// 创建演员并设置映射器vtkSmartPointer<vtkActor> sphereeActor = vtkSmartPointer<vtkActor>::New();sphereeActor->SetMapper(sphereMapper);sphereeActor->SetTexture(texture);// 将立方体添加到渲染器中renderer->AddActor(sphereeActor);// 设置渲染器背景颜色renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色背景// 开始渲染和交互ui.openGLWidget->setRenderWindow(renderWindow);
}
针对不同的图像格式,VTK 提供了不同的读取类:
JPEG 文件:使用 vtkJPEGReader。
PNG 文件:使用 vtkPNGReader。
TIFF 文件:使用 vtkTIFFReader。
相关文章:
VTK的基本概念(一)
文章目录 三维场景的基本要素1.灯光2.相机3.颜色4.纹理映射 三维场景的基本要素 1.灯光 在三维渲染场景中,可以有多个灯光的存在,灯光和相机是三维渲染场景的必备要素,如果没有指定的话,vtkRenderer会自动创建默认的灯光和相机。…...
【动态规划】股票市场交易策略优化
文章目录 一、问题描述二、解决思路状态转移初始化最终结果 三、代码实现执行流程解析时间和空间复杂度 一、问题描述 我们要解决的是一个关于股票买卖的问题:给定一个股票价格数组 stocks,每一天的价格为数组中的一个元素。我们可以通过买入和卖出的操…...
docker-compose 升级
官方下载地址: https://github.com/docker/compose/releases 下载完放到kali root目录下 # mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose # chmod x /usr/local/bin/docker-compose # docker-compose --version...
node.js @ffmpeg-installer/ffmpeg 桌面推流
//安装npm install --save ffmpeg-installer/ffmpeg //stream.js // 引入所需模块 const ffmpeg require(ffmpeg-installer/ffmpeg); const { exec } require(child_process); // 设置 FFmpeg 路径 const ffmpegPath ffmpeg.path; const rtmpUrl "rtmp://localhost…...
电脑启动需要经历哪些过程?
传统BIOS启动流程 1. BIOS BIOS 启动,BIOS程序是烧进主板自带的ROM里的,所以无硬盘也可以启动。BIOS先进行自检,检查内存、显卡、磁盘等关键设备是否存在功能异常,会有蜂鸣器汇报错误,无错误自检飞快结束。 硬件自检…...
MobaXterm Sessions 批量录入导入,会话批量添加
此脚本用于将服务器批量录入到 MobaXterm 会话 使用方法: 1、将IP列定义在 sessions_ip_list 变量中(ssh登录的IP) 2、将登录用户定义在 sessions_user 变量中(ssh登录的用户) 3、将目录名称定义在 folder_name 变…...
ceph的用户管理和cephx认证
用户权限概述 用户格式 参考链接: 权限:https://docs.ceph.com/en/latest/rados/operations/user-management/#authorization-capabilities 用户:https://docs.ceph.com/en/reef/rados/operations/user-management/ ceph的用户格式TYPEID…...
【北京迅为】iTOP-4412全能版使用手册-第二十章 搭建和测试NFS服务器
iTOP-4412全能版采用四核Cortex-A9,主频为1.4GHz-1.6GHz,配备S5M8767 电源管理,集成USB HUB,选用高品质板对板连接器稳定可靠,大厂生产,做工精良。接口一应俱全,开发更简单,搭载全网通4G、支持WIFI、蓝牙、…...
MicroSoft Project2007 安装教程
一、安装教程 访问地址 二、安装链接 通过网盘分享的文件:Project2007CD 链接: https://pan.baidu.com/s/1Y8VnhVPiKjcmAEh8cIR5sQ?pwdp2hk 提取码: p2hk --来自百度网盘超级会员v6的分享...
怎样提高自己的能量
能量转换的基本原则是让别人需要你,而不是你去求对方。别人需要你,你的能量就高,你去求别人你的能量就低。 怎样提高自己的能量? 第一,留意你的气场和格局。气场不是说你表现的多么霸道,而是你的信念、决心…...
ScreenshotToCode安装教程
网页截图生成代码,我测试的效果一般 快速安装教程如下 1,首先你得有OpenAI的账号 国内用这个代理就可以: https://www.closeai-asia.com/ 充值一块钱,在本项目中可以生成两次 2,下载程序 下载程序压缩包࿱…...
工程企业如何做好成本控制?该如何入手?
工程企业的成本控制是企业管理中的核心工作,其直接关系到项目的盈利能力和市场竞争力。以下从几个关键方向阐述如何入手做好成本控制: 一、明确成本控制目标 成本控制的目标不仅是减少支出,更重要的是保证项目质量和工期,避免因低…...
详解桥接模式
引言 在开发过程中,可能会遇到系统设计有多种维度变化的情况,比如我们想画一幅五彩斑斓的画,需要用到12个颜色,但是需要粗细不同的线条(粗、中、细),如果用蜡笔,就需要粗中细三种蜡笔…...
田忌赛马五局三胜问题matlab代码
问题描述:在可以随机选择出场顺序的情况下,如果把比赛规则从三局两胜制改为五局三胜制,齐王胜出的概率是上升了还是下降了?五局三胜的赛制下,大家的马重新分为5个等级。前提条件仍然是齐王每种等级的马都优于田忌同等级…...
Springboot 修改post请求接口入参或重新赋值
前言 很久之前写过一篇就是自动填充接口参数的,利用的 HandlerMethodArgumentResolver 自定义注解 Springboot Controller接口默认自动填充 业务实体参数值_springboot设置入参默认值-CSDN博客 现在这一篇也差不多,达到的目的就是重新去给post请求的参数…...
jmeter学习(7)命令行控制
jmeter -n -t E:\IOT\test2.jmx -l E:\IOT\output\output.jtl -j E:\IOT\output\jmeter.log -e -o E:\IOT\output\report IOT下创建output 文件夹,jmx文件名避免中文,再次执行output.jtl不能有数据要删除...
李春葆《数据结构》-查找-课后习题代码题
一:设计一个折半查找算法,求查找到关键字为 k 的记录所需关键字的比较次数。假设 k 与 R[i].key 的比较得到 3 种情况,即 kR[i].key,k<R[i].key 或者 k>R[i].key,计为 1 次比较(在教材中讨论关键字比…...
Spring Boot教程之十: 使用 Spring Boot 实现从数据库动态下拉列表
使用 Spring Boot 实现从数据库动态下拉列表 动态下拉列表(或依赖下拉列表)的概念令人兴奋,但编写起来却颇具挑战性。动态下拉列表意味着一个下拉列表中的值依赖于前一个下拉列表中选择的值。一个简单的例子是三个下拉框,分别显示…...
Facebook的开源项目解析:推动开发者社区的技术进步
Facebook,作为全球领先的社交平台之一,其在技术领域的创新不仅体现在产品功能的实现上,也积极推动开源社区的发展。开源项目已经成为Facebook技术战略的重要组成部分,通过开源,Facebook不仅加速了技术进步,…...
以 SpringBoot 为基石的夕阳红公寓信息化管理系统设计理念
2 开发环境与技术 本章节对开发夕阳红公寓管理系统需要搭建的开发环境,还有夕阳红公寓管理系统开发中使用的编程技术等进行阐述。 2.1 Java语言 Java语言是当今为止依然在编程语言行业具有生命力的常青树之一。Java语言最原始的诞生,不仅仅是创造者感觉C…...
身份证OCR 识别 API 接口的发展前景
随着信息时代的到来,大量的身份证数据需要进行整理、存储和管理,OCR 识别技术可以将身份证信息转化为结构化的电子文本,方便后续的数据管理和分析,提高工作效率。 未来,随着人工智能和深度学习等技术的不断发展&#…...
使用vue3实现element-plus的主题切换特效
先看实现效果 实现过程 前提需要引入好 element-plus,并导入element的黑色主题CSS 示例,再 main.js 中引入 import ElementPlus from element-plus import element-plus/dist/index.css import element-plus/theme-chalk/dark/css-vars.css // 黑色主…...
深入了解决策树---机器学习中的经典算法
引言 决策树(Decision Tree)是一种重要的机器学习模型,以直观的分层决策方式和简单高效的特点成为分类和回归任务中广泛应用的工具。作为解释性和透明性强的算法,决策树不仅适用于小规模数据,也可作为复杂模型的基石&…...
深度优先算法(DFS)和广度优先算法(BFS)
一、深度优先算法 深度优先搜索属于图算法的一种,是一个针对图和树的遍历算法,英文缩写为DFS即Depth First Search。深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便…...
Linux进程信号
信号量 本质是一个计数器,用来表示系统资源中,资源数量多少的问题。 公共资源:能被多个进程同时访问的资源。 访问没有被保护的资源,可能会出现数据不一致问题。 让不同进程看到同一个资源的目的是想通信。 为了解决进程具有独立性无法 …...
东风破捉妖师横空出世
一.异动拉升实时监测 东风破就像是一个大盘监测平台,是现实版的捉妖师,一旦妖股横空出世,就会在东风破面前原形毕露。东风破AI算法逻辑是监测存在异动拉升的股票,实时分析上证,深证,创业和科创板的股票数据…...
初窥门径:React中的事件机制
React中的事件机制 什么是合成事件?使用合成事件的好处事件委托事件池 React事件执行顺序 什么是合成事件? 在React中,合成事件(Synthetic Events) 是一种跨浏览器的事件包装机制,旨在统一浏览器的事件处理…...
【Android、IOS、Flutter、鸿蒙、ReactNative 】实现 MVP 架构
Android Studio 版本 Android Java MVP 模式 参考 模型层 model public class User {private String email;private String password;public User(String email, String password) {this.email = email;this.password = password;}public String getEmail() {return email;}…...
DroneCAN 最新开发进展,Andrew在Ardupilot开发者大会2024的演讲
本文是Andrew演讲的中文翻译,你可以直接观看视频了解演讲的全部内容,此演讲视频的中文版本已经发布在Ardupilot社区的Blog板块,你可以在 Arudpilot官网(https://ardupilot.org) 获取该视频: 你也可以直接通过Bilibili链…...
从 App Search 到 Elasticsearch — 挖掘搜索的未来
作者:来自 Elastic Nick Chow App Search 将在 9.0 版本中停用,但 Elasticsearch 拥有你构建强大的 AI 搜索体验所需的一切。以下是你需要了解的内容。 生成式人工智能的最新进展正在改变用户行为,激励开发人员创造更具活力、更直观、更引人入…...
如何给GitHub的开源项目贡献PR
🎯导读:本文详细介绍了如何向开源项目“代码随想录”贡献自己的题解。首先,需要Fork原项目的仓库至个人GitHub账户,然后解决克隆仓库时可能遇到的SSH密钥问题。接着,按照标准流程对本地仓库进行代码或文档的修改&#…...
架构-微服务-服务配置
文章目录 前言一、配置中心介绍1. 什么是配置中心2. 解决方案 二、Nacos Config入门三、Nacos Config深入1. 配置动态刷新2. 配置共享 四、nacos服务配置的核心概念 前言 服务配置--Nacos Config 微服务架构下关于配置文件的一些问题: 配置文件相对分散。在一个…...
鱼眼相机模型-MEI
参考文献: Single View Point Omnidirectional Camera Calibration from Planar Grids 1. 相机模型如下: // 相机坐标系下的点投影到畸变图像// 输入:相机坐标系点坐标cam 输出: 畸变图像素点坐标disPtvoid FisheyeCamAdapter::…...
设计模式——抽象工厂模式
定义与概念 抽象工厂模式是一种创建型设计模式。它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。简单来说,抽象工厂就像是一个工厂的抽象蓝图,这个蓝图定义了生产一组产品的方法,但具体怎么生产这些产…...
大语言模型(LLM)不平衡的内存使用问题;训练过程中 Transformer层1和Transformer层2的反向传播计算量差异
目录 大语言模型(LLM)不平衡的内存使用问题 一、不平衡的内存使用概述 二、不平衡的内存使用举例 嵌入层与Transformer层之间的内存差异: 不同Transformer层之间的内存差异: 输入数据对内存使用的影响: 三、不平衡的内存使用带来的问题 四、解决方案 大语言模型的…...
AI需求条目化全面升级!支持多格式需求,打破模板限制!
AI需求条目化全面升级!支持多格式需求,打破模板限制! 一、多格兼济 标准立成 1、功能揭秘 预览未来 平台需求板块的AI需求条目化功能迎来全面升级。它支持多种需求格式,不再受限于模板文件,能够一键自动快速且灵活地生…...
C#:时间与时间戳的转换
1、将 DateTime 转换为 Unix 时间戳(秒) public static long DateTimeToUnixTimestamp(DateTime dateTime) {// 定义UTC纪元时间DateTime epochStart new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);// 计算从UTC纪元时间到指定时间的总秒数Tim…...
输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。-多语言
目录 C 语言实现 Python 实现 Java 实现 Js 实现 Ts 实现 题目:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。 程序分析:利用while语句,条件为输入的字符不为\n。 C 语言实现 #include <stdio.h>int mai…...
贪心-区间问题——acwing
题目一:最大不相交区间数量 908. 最大不相交区间数量 - AcWing题库 分析 跟区间选点一样。区间选点:贪心——acwing-CSDN博客 代码 #include<bits/stdc.h> using namespace std;const int N 1e510;struct Range {int l, r;// 重载函数bool op…...
OpenCV相机标定与3D重建(8)相机标定函数calibrateCamera()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 从校准图案的多个视图中找到相机的内参和外参参数. cv::calibrateCamera 是 OpenCV 中用于相机标定的一个非常重要的函数。它通过一系列已知的世…...
Maven 插件
为 Maven 插件配置环境变量通常涉及到设置 Java 环境变量以及 Maven 相关的环境变量。以下是一些基本步骤: 1. 设置 Java 环境变量 Maven 需要 Java 运行环境,因此您需要确保 Java 的环境变量已经正确设置。 - **JAVA_HOME**:指向您的 Java…...
【Java基础入门篇】一、变量、数据类型和运算符
Java基础入门篇 一、变量、数据类型和运算符 1.1 变量 计算机中的数据表示方式是:“二进制(0/1)”,但是同时也可以兼容其他进制,例如八进制、十进制、十六进制等。 Java变量的本质是:存储在固定空间的内容,变量名是…...
[论文阅读]Poisoning Retrieval Corpora by Injecting Adversarial Passages
Poisoning Retrieval Corpora by Injecting Adversarial Passages 通过注入对抗性文本对检索语料库进行中毒 http://arxiv.org/abs/2310.19156 EMNLP2023 文章的目标就是要让检索器检索的结果包含攻击者生成的对抗性文本,如果能够检索到,则认为攻击成…...
[Redis#10] scan | db_0 | redis_cli | RESP | C++-redis启动教程
目录 1. 渐进式遍历 1.2 常见指令 - scan 2. 数据库管理 3.redis 客户端 是否前面学习的这些 redis 命令,没有价值了呢? 4.RESP 自定义协议 为什么能编写出一个自定义的 Redis 客户端? RESP 协议 5.在 Ubuntu 下启用 C 操作 Redis …...
LCR 151.彩灯装饰记录III
题目 代码 class Solution { public List<List> levelOrder(TreeNode root) { if(root null){ return new ArrayList<>(); } Queue<TreeNode> queue new LinkedList<>();List<List<Integer>> res new ArrayList<>();int sum 1;…...
vue实现滚动条滑动到底部分页调取后端接口加载数据
一、案例效果 二、前提条件 接口返回数据 三、案例代码 子组件 const $emit defineEmits([cloneItem, updateList]);const props defineProps({rightList: {type: Array,},chartTableData: {type: Array as () > ChartListType[],},deleteChartInfo: {type: Object,}…...
Vscode连接服务器
在VS Code中连接服务器的主要步骤如下: 1.安装Remote-SSH插件:打开VS Code,进入插件市场搜索“Remote-SSH”并安装。安装完成后,VS Code的侧边栏会出现一个远程资源管理器的图标。 2.配置服务器信息:点击…...
工作中Linux 内核的链表算法的使用
在 Linux 内核中,链表是一个非常重要的数据结构,广泛用于各种场景,如任务调度、设备管理、进程管理等。Linux 内核提供了高效且灵活的链表实现,能够更好地管理系统中的数据和对象。我们将深入浅出地讲解 Linux 内核链表的实现原理、用法,并举例展示如何使用。 1. 链表基本…...
洛谷P1115
最大子段和 - 洛谷 最大子段和 题目描述 给出一个长度为 n的序列a,选出其中连续且非空的一段使得这段和最大。 输入格式 第一行是一个整数,表示序列的长度n。 第二行有n个整数,第i个整数表示序列的第 i个数字 a_i。 输出格式 输出一行…...
USB Type-C一线通扩展屏:多场景应用,重塑高效办公与极致娱乐体验
在追求高效与便捷的时代,启明智显USB Type-C一线通扩展屏方案正以其独特的优势,成为众多职场人士、娱乐爱好者和游戏玩家的首选。这款扩展屏不仅具备卓越的性能和广泛的兼容性,更能在多个应用场景中发挥出其独特的价值。 USB2.0显卡ÿ…...