VTK基礎交互:
VTK交互使用vtkRenderWindowInteractor,它將負責某個vtkRenderWindow窗口的監聽,包括鼠標、鍵盤、時鐘等消息,通過vtk中的Command/Observer設計模式進行處理。vtkRenderWindowInteractor會自動創建一個默認的vtkInteraactorStyle類對象(交互器樣式)進行消息的處理,完成用戶交互作用於實際的3D模型功能。通常,我們會自己創建一個交互器樣式來處理消息,也可以重載已有的樣式進行功能擴展。
class vtkMyCallback : public vtkCommand
{
public:
static vtkMyCallback *New()
{
return new vtkMyCallback;
}
virtual void Execute(vtkObject *caller, unsigned long, void*) // 強制實現的方法
{
vtkRenderer *ren = reinterpret_cast<vtkRenderer*>(caller);
cout << ren->GetActiveCamera()->GetPosition()[0] << " "
<< ren->GetActiveCamera()->GetPosition()[1] << " "
<< ren->GetActiveCamera()->GetPosition()[2] << "\n";
}
};
// ------------------------------------------main中------------------------------------
this->renderer = vtkRenderer::New(); // 渲染器
this->renWin = vtkRenderWindow::New(); // 渲染窗口
this->renWin->AddRenderer(this->renderer); // 向渲染窗口添加渲染器
//this->renWin->SetParentId(hwnd); // 設置vtkRenderWindow的父窗口,可以使MFC/Win32窗口的HWND
this->iren = vtkRenderWindowInteractor::New(); // 交互器
this->iren->SetRenderWindow(this->renWin); // 將vtkRenderWindow設置到交互器
this->m_style = vtkInteractorStyleTrackballCamera::New();
this->iren->SetInteractorStyle(m_style);
this->iren->Initialize();
//Data
this->cone = vtkConeSource::New(); // 圓錐數據源
this->cone->SetHeight(4.0); // 圓錐高度
this->cone->SetRadius(2.0); // 圓錐半徑
this->cone->SetResolution(20); // 圓錐精度(多邊形模擬的圓)
this->coneMapper = vtkPolyDataMapper::New(); // 幾何繪圖器(幾何原始數據)
this->coneMapper->SetInputConnection(this->cone->GetOutputPort()); // 獲取到剛纔的圓錐的幾何原始數據
this->coneActor1 = vtkActor::New(); // 演員對象
this->coneActor1->SetMapper(this->coneMapper); // 演員對象使用繪圖器(裏面裝的圓錐數據, 所以是畫圓錐)
this->coneActor2 = vtkActor::New(); // 演員對象
this->coneActor2->SetMapper(this->coneMapper); // 演員對象使用繪圖器(裏面裝的圓錐數據, 所以是畫圓錐)
coneActor1->GetProperty()->SetColor(0.2, 0.63, 0.79); // vtk屬性,顏色
coneActor1->GetProperty()->SetDiffuse(0.7); // 設置漫反射分量 兩者共同可表示材質
coneActor1->GetProperty()->SetSpecular(0.4); // 設置鏡面反射分量
coneActor1->GetProperty()->SetSpecularPower(20); // 設置鏡面反射強度
vtkProperty* coneProperty = vtkProperty::New(); // 屬性對象
coneProperty->SetColor(0.5, 0.0, 0.0);
coneProperty->SetDiffuse(0.7);
coneProperty->SetSpecular(0.4);
coneProperty->SetSpecularPower(20);
coneActor2->GetProperty()->SetColor(0.0, 0.5, 0.0);
coneActor2->SetProperty(coneProperty);
coneActor2->SetOrigin(0, 0, -5); // 原點設置?旋轉中心?
coneActor2->SetPosition(3.0, 3.0, -3.0); // 直接設置位置
vtkTransform* trans = vtkTransform::New();
trans->Translate(3.0, 3.0, -3.0); // 在原來位置上再變化的
trans->RotateY(30);
//coneActor2->SetUserMatrix(trans->GetMatrix());
coneActor2->SetUserTransform(trans); // 兩者效果一樣
trans->Delete();
////////
this->renderer->AddActor(this->coneActor1); // 渲染器添加這個演員
this->renderer->AddActor(this->coneActor2); // 渲染器添加這個演員
this->renderer->SetBackground(0.1, 0.1, 0.1); // 渲染器背景色
this->renderer->SetViewport(0.0, 0.0, 1.0, 1.0); // 分配窗口比例
this->renWin->SetSize(800, 600); // 渲染窗口大小
vtkMyCallback* mol = vtkMyCallback::New();
this->renderer->AddObserver(vtkCommand::StartEvent, mol); // 爲渲染器添加觀察器(回調函數)
mol->Delete();
// 通過實時過去相機位置,不難看出,模型不動相機動,座標系方向與OpenGL是一樣的
this->renWin->Render(); // 渲染窗口開始渲染
this->iren->Start(); // 實際就是事件循環了,就不需要在外面添加事件循環了
// int i;
// for (i = 0; i < 360; ++i)
// {
// // render the image
// renWin->Render();
// // rotate the active camera by one degree
// (this->renderer)->GetActiveCamera()->Azimuth(1);
// }
上述代碼,展示了vtk交互及屬性設置,在HelloWorld這篇,我們只使用了vtkRenderWindowInteractor,沒有創建自己的交互器樣式,在實際操作中,可發現,只要鼠標點擊就可以使模型移動(實際上是相機移動),然而,在這篇中,需要鼠標點擊並移動才能看到模型移動(相機移動),這是因爲,交互器的參數不一樣。
vtkRenderWindowInteractor消息響應:
在沒有使用我們自己的交互器樣式到窗口交互對象時,vtkRenderWindowInteractor會生成一個默認的交互器,此時,可以響應比較多的消息,使用不同的交互器樣式,響應的消息也會不一樣,例如,上面程序中,我們使用了vtkInteractorStyleTrackballCamera,此時麼就不能響應鍵盤按鍵t和按鍵j,但在默認的樣式中,t和j可以設置交互模式,t設置動作敏感型(數遍按下後拖動才移動等消息),j設置位置敏感型(按下鼠標及響應移動等消息)。此外,無論是默認的交互器還是vtkInteractorStyleTrackballCamera交互器,都可以響應鼠標左鍵旋轉,中鍵移動和放大縮小,右鍵放大縮小的消息(實際上是相機的移動和旋轉,這裏爲了方便理解)。
默認交互樣式下,響應的消息有如下幾種:
(1)、按鍵 t、j
按鍵t同於設置動作敏感型,j設置位置敏感型,主要體現爲鼠標操作移動相機的方式的更改。默認爲位置敏感型。
(2)、按鍵c、a
相機和對象之間的切換,c爲相機,a爲對象,用於改變交互作用對象,作用於相機時,鼠標操作的相機移動旋轉等,作用於對象時,鼠標操作3D對象移動旋轉縮放等。
(3)、鼠標左鍵
在相機模式下,左鍵用於旋轉相機,旋轉點爲相機的焦點,對象模式下,用於旋轉模型對象,繞世界空間原點旋轉。不同敏感型操作,對於這個也是有影響的,位置敏感型表現爲與窗口中心距離越遠,旋轉越快,動作敏感型表現爲移動多少,改變多少。
(4)、鼠標中鍵
可以在當前相機方向的垂直平面上移動相機(上下左右移動),滾輪滾動可以在前後方向上移動相機。對象模式下,可做用於模型。
(5)、鼠標右鍵
相機模式可改變相機前後位置,對象模式下改變對象大小。不同敏感模式效果也會不一樣。
(6)、按鍵3
可用於激活或者取消立即渲染模式。
(7)、其他按鍵
按鍵e/q:可以關閉窗口,退出應用程序。
按鍵f:移動actor到光標當前位置,設置當前光標所在的位置爲焦點,而且會以該點爲旋轉中心。
按鍵p:執行拾取操作,渲染窗口交互器內部有一個vtkPropPicker實例,可實現拾取功能。
按鍵r:沿着當前方向重置相機,自動移動相機到合適的位置使所有對象可見。
按鍵s:改變所有actor的顯示形式爲表面模型(與下面按鈕w相對應)。
按鍵u:調用用於自定義方法(回調),通常彈出窗口提供命令交互功能。
按鍵w:改變所有actor顯示爲線框模式(比較有趣的顯示)。
vtk屬性:
vtkActor對象繼承與vtkProp,vtkProp除了可設置位置大小等信息外,其內部還包含了一個vtkMapper對象和一個vtkProperty對象,前者存放數據,後者存放屬性信息。
此外,vtkActor最終設置到vtkRender中,用於渲染,一個vtkRender中可以包含多個actor對象,可以一次渲染裏面的全部actor,上面代碼中就添加了兩個不同的actor對象(方位顏色不同)。vtkRender最終也設置到vtkRenderWindow中,一個vtkRenderWindow也可以包含多個vtkRender,即一個渲染窗口可以包含多個渲染器,但是,需要給每個渲染器指定一個範圍(SetViewport),上面代碼中 this->renderer->SetViewport(0.0, 0.0, 1.0, 1.0);就是分配整個渲染窗口給這個渲染器。
vtkActor可通過GetProperty來獲取屬性信息,也可通過SetProperty來設置屬性信息,改變一個Actor的屬性通常可以像上面代碼演示的那樣,直接獲取屬性對象再對其設置某些屬性,還可以創建一個屬性對象,最後將其設置到Actor中去。