上一节我们讲到最后我们要考虑VTKOBJECT(this)是什么意思,经过查找,我们发现。它是当这个stream在interpret(解释器)中时,让他调用vtkClassName::MethodName()。其中vtkClassName是其中的代理对象代表的的类的类名,方法就是后面这个方法。所以我们这里就是调用vtkPVRenderView这个类的
我们来解析之前那段代码:
int
vtkClientServerInterpreter::CallCommandFunction(const char* cname,
vtkObjectBase* ptr,
const char* method,
const vtkClientServerStream& msg,
vtkClientServerStream& result)
{
vtkClientServerInterpreterInternals::ClassToFunctionMapType::const_iterator f =
this->Internal->ClassToFunctionMap.find(cname);
if (f == this->Internal->ClassToFunctionMap.end())
{
vtkErrorMacro("Cannot find command function for \"" << cname << "\".");
return 1;
}
const vtkClientServerInterpreterInternals::CommandFunction* n = f->second;
vtkClientServerCommandFunction function = n->Function;
void* ctx = n->Context ? n->Context->Context : 0;
return function(this, ptr, method, msg, result, ctx);
}
这段代码中,f是一个迭代器,从这个类到方法的map的方法中找到cname对应的方法f,然后n赋值为f的f的第二项,可以假设f是key,n是value,n是命令方法(是在解释器中的),然后根据它解析出它代表的方法执行。经过试验,这里的cname其实已经是vtkPVRenderView了,所以这里很好理解,根据类名找到对应的解释器,然后根据解释器找到对应的命令方法,再根据这个类对应的命令
方法,解析出在服务器上执行的命令方法,然后以命令方法的形式执行vtkPVRenderView下的StillRender方法。
所以下面我们来看:
void vtkPVRenderView::StillRender()//高分辨率的render
{
vtkTimerLog::MarkStartEvent("Still Render");
this->GetRenderWindow()->SetDesiredUpdateRate(0.002);
this->Internals->PreRender(this->RenderView);
this->Render(false, false);
vtkTimerLog::MarkEndEvent("Still Render");
}
非常简单,就是设置里几个参数,然后执行Render:
void vtkPVRenderView::Render(bool interactive, bool skip_rendering)
{
if (this->SynchronizedWindows->GetMode() !=
vtkPVSynchronizedRenderWindows::CLIENT ||
(!interactive && this->UseDistributedRenderingForStillRender) ||
(interactive && this->UseDistributedRenderingForInteractiveRender))
{
通过这段代码,我们可以看到Paraview渲染的三种模式,第一种是客户端直接渲染,第二种是采用分布式渲染的StillRender模式,第三种是采用分布式渲染的交互渲染模式。
不论哪种模式其实都要与客户端相配合,去完成update。
// Although Selection do trigger a Render on the server side and in such
// case we MUST NOT execute that collaboration synchronization
if(!this->MakingSelection)
{
this->SynchronizeForCollaboration();
}
}
我们不需要做执行协作同步
// BUG #13534. Reset the clip planes on every render. Since this does not
// involve any communication, doing this on every render is not a big deal.
this->ResetCameraClippingRange();
bool in_tile_display_mode = this->InTileDisplayMode();
bool in_cave_mode = this->SynchronizedWindows->GetIsInCave();
if (in_cave_mode && !this->RemoteRenderingAvailable)
{
static bool warned_once = false;
if (!warned_once)
{
vtkErrorMacro(
"In Cave mode and Display cannot be opened on server-side! "
"Ensure the environment is set correctly in the pvx file.");
in_cave_mode = false;
}
}
重置每个render上的夹面,这不包括任何通讯,在每个render上做这个不是一个大问题。获得是否使用tile_display或者cave的模式,在cave模式下,如果不允许远程渲染,那么报错:检查是否在pvx文件中设置了环境参数。
// Use loss-less image compression for client-server for full-res renders.
this->SynchronizedRenderers->SetLossLessCompression(!interactive);
bool use_lod_rendering = interactive? this->GetUseLODForInteractiveRender() : false;
if (use_lod_rendering)
{
this->RequestInformation->Set(USE_LOD(), 1);
}
对客户端服务器的所有的render采用无损图像压缩的方式。这种方式是针对StillRender模式的。
// cout << "Using remote rendering: " << use_distributed_rendering << endl;
// Decide if we are doing remote rendering or local rendering.
bool use_distributed_rendering = interactive?
this->GetUseDistributedRenderingForInteractiveRender():
this->GetUseDistributedRenderingForStillRender();
bool use_ordered_compositing = this->GetUseOrderedCompositing();
if (use_ordered_compositing)
{
this->Internals->DeliveryManager->RedistributeDataForOrderedCompositing(
use_lod_rendering);
this->SynchronizedRenderers->SetKdTree(
this->Internals->DeliveryManager->GetKdTree());
}
else
{
this->SynchronizedRenderers->SetKdTree(NULL);
}
决定是采用远程渲染还是本地渲染。第一个参数是采用哪种分布式渲染模式,是StillRender还是InteractiveRender模式。
// enable render empty images if it was requested
this->SynchronizedRenderers->SetRenderEmptyImages(this->GetRenderEmptyImages());
如果需要,使可以渲染空图片。
// Render each representation with available geometry.
// This is the pass where representations get an opportunity to get the
// currently "available" represented data and try to render it.
this->CallProcessViewRequest(vtkPVView::REQUEST_RENDER(),
this->RequestInformation, this->ReplyInformationVector);
通过合适的几何形状渲染每一个representation。这是通过:representations获得机会去得到现在的“available”,这应该代表现在的数据是这个representation的。然后去渲染它。
// set the image reduction factor.
this->SynchronizedRenderers->SetImageReductionFactor(
(interactive?
this->InteractiveRenderImageReductionFactor :
this->StillRenderImageReductionFactor));
this->UsedLODForLastRender = use_lod_rendering;
if (skip_rendering)
{
// essential to restore state.
return;
}
// When in tile-display mode, we are always doing shared rendering. However
// when use_distributed_rendering we tell IceT that geometry is duplicated on
// all processes.
this->SynchronizedWindows->SetEnabled(
use_distributed_rendering || in_tile_display_mode || in_cave_mode);
this->SynchronizedRenderers->SetEnabled(
use_distributed_rendering || in_tile_display_mode || in_cave_mode);
this->SynchronizedRenderers->SetDataReplicatedOnAllProcesses(
in_cave_mode ||
(!use_distributed_rendering && in_tile_display_mode));
if (this->ShowAnnotation)
{
std::ostringstream stream;
stream
<< "Mode: " << (interactive? "interactive" : "still") << "\n"
<< "Level-of-detail: " << (use_lod_rendering? "yes" : "no") << "\n"
<< "Remote/parallel rendering (if applicable): " << (use_distributed_rendering? "yes" : "no") << "\n";
this->Annotation->SetText(stream.str().c_str());
}
// When in batch mode, we are using the same render window for all views. That
// makes it impossible for vtkPVSynchronizedRenderWindows to identify which
// view is being rendered. We explicitly mark the view being rendered using
// this HACK.
this->SynchronizedWindows->BeginRender(this->GetIdentifier());
当是采用批量的模式,我们对于所有的views采用相同的render window。这样使得vtkPVSynchronizedRenderWindows可以判定那个view正在被渲染。我们明确的标记这个正在被渲染的view
// Call Render() on local render window only if
// 1: Local process is the driver OR
// 2: RenderEventPropagation is Off and we are doing distributed rendering.
// 3: In tile-display mode or cave-mode.
// Note, ParaView no longer has RenderEventPropagation ON. It's set to off
// always.
if (
(this->SynchronizedWindows->GetLocalProcessIsDriver() ||
(!this->SynchronizedWindows->GetRenderEventPropagation() && use_distributed_rendering) ||
in_tile_display_mode || in_cave_mode) &&
vtkProcessModule::GetProcessType() != vtkProcessModule::PROCESS_DATA_SERVER)
{
this->GetRenderWindow()->Render();
}
if (!this->MakingSelection)
{
// If we are making selection, then it's a multi-step render process and we
// need to leave the SynchronizedWindows/SynchronizedRenderers enabled for
// that entire process.
this->SynchronizedWindows->SetEnabled(false);
this->SynchronizedRenderers->SetEnabled(false);
}
}
只有当:
1.本地的进程是driver
2.我们是使用分布式渲染,但是我们不使用渲染事件传播
3.是tile-display模式或者cave模式
4.并且当前进程的类型不是dataserver
这三种情况时才调用本地的渲染窗口进行渲染。
注意,Paraview不再默认设置RenderEventPropagation为on,默认是off
如果我们做了决定,他是一个多步的渲染进程,我们需要给整个进程舍弃同步window和同步渲染