更改VTK的不透明对象渲染顺序 (Z-顺序)
我想找到一种方法来控制多个物体(比如X光图像或三维图像)在同一个Z平面上的渲染顺序。现在我在考虑是否可以在自定义的OpaquePass中重新排列PropArray,但我想知道有没有其他人有更简单的方法来处理这个问题。可惜的是,虽然Image2D有SetDisplayLocationToForeground/BackGround()
这个方法,但我不能使用它。
有没有比自己写渲染代码和使用自定义OpaquePass更简单的方法呢?使用这个软件的人可以通过bringToFront/Back的控制来改变X光的渲染顺序。
我已经在WebGL和Three.js中成功测试了这个功能,这两个工具可以控制渲染顺序。比如:
注意:我使用的是Python(2.7.5)和Python Vtk:5.10.1
1 个回答
经过一个月的开发和调试,我终于解决了问题!
下面是我如何解决VTK中的渲染深度问题的。
注意:这个方法只会解决在同一z深度上的物体的渲染深度。前面或后面的物体会正常绘制,尽管它们有渲染深度。
逻辑
我们将编辑vtkRenderer的viewProps对象中的绘制顺序。所有渲染深度为null的vtk对象会先绘制,然后是按渲染深度降序排列的对象。
示例:
未排序的渲染深度
viewProps = [ NULL, 3, NULL, 1, 2, 4, NULL]
排序后的渲染深度
viewProps = [ NULL, NULL, NULL, 4, 3, 2, 1]
实现
给vtkObject添加一个叫“renderDepth”的属性,并提供获取和设置的方法。在创建vtkObject时,将renderDepth = NULL;
。
在vtkRenderer中创建一个方法(我称之为RenderDepthSort)。
递归调用viewProp对象树,然后用简单的冒泡排序交换任何具有渲染深度的项目。
vtkRenderer::RenderDepthSort(vtkPropCollection * propArray){
propArray->InitTraversal();
for(int i=0; i < propArray->GetNumberOfItems(); i++){
vtkProp * prop = propArray->GetNextProp();
if(prop->IsA("vtkAssembly")){
vtkAssembly * ptr = static_cast<vtkAssembly *>(prop);
if(ptr->GetParts()->GetNumberOfItems() > 0)
this->RenderDepthSort(ptr->GetParts());
}
}
bool isUnsorted = true;
while(isUnsorted){
isUnsorted = false;
propArray->InitTraversal();
for(int i=0; i < propArray->GetNumberOfItems()-1; i++){
vtkProp * propA = propArray->GetNextProp();
vtkProp * propB = static_cast<vtkProp *>(propArray->GetItemAsObject(i+1));
if(propA->GetRenderDepth() == NULL || propB->GetRenderDepth() == NULL){
if(propA->GetRenderDepth() != NULL && propB->GetRenderDepth() == NULL){
propArray->ReplaceItem(i, propB);
propArray->ReplaceItem(i+1, propA);
isUnsorted = true;
}
}else if(propA->GetRenderDepth() < propB->GetRenderDepth()){
propArray->ReplaceItem(i, propB);
propArray->ReplaceItem(i+1, propA);
isUnsorted = true;
}
} //end for loop
} // 结束while循环
}//结束renderDepthSort方法
如果你像我们一样抽象了你的vtk实现,并且没有完全控制你的vtkViewProps,那么可以实现另一个方法来解决渲染深度并向上传播。
void vtkRenderer::InitSolveRenderDepths(vtkPropCollection * propArray){
int depth = NULL;
int numDepths = 0;
propArray->InitTraversal();
for(int i=0; i < propArray->GetNumberOfItems(); i++){
vtkProp * prop = propArray->GetNextProp();
if(prop->IsA("vtkAssembly")){
this->SolveRenderDepths(prop);
int temp = prop->GetRenderDepth();
if(temp != NULL){
if(temp < depth || depth == NULL){
depth = temp;
}
numDepths++;
}
}
}
}
最后
再创建一个方法叫UpdateDrawOrder()
void vtkRenderer::UpdateDrawOrder(){
vtkPropCollection * props = this->GetViewProps();
this->InitSolveRenderDepths(props);
this->RenderDepthSort(props);
}
将这个方法设置为在vtkRenderer::Render()或你的vtkRenderer对象中调用UpdateDrawOrder。
结束!