在vtkMapper中有一个函数:
vtkDataSet *vtkMapper::GetInput()
{
if (this->GetNumberOfInputConnections(0) < 1)
{
return 0;
}
return vtkDataSet::SafeDownCast(
this->GetExecutive()->GetInputData(0, 0));
}
从这里我们可以看出,每一个Mapper都可以从外界得到数据,通过vtkDataSet::SafeDownCast函数,从this的GetExecutive()中获取GetInputData(0, 0),GetExecutive()是vtkAlgorithms中的一个方法,如果存在默认的Executive则直接返回,没有则创建一个,返回类型为vtkExecutive。而在vtkExecutive中又有函数GetInputData(int port,int index),通过这个函数来获得输入。从而可以得到输入导入Mapper,可具体那些数据什么数据进Mapper,还要看vtkDataSet和vtkAlgorithms和vtkExecutive。还有一个vtkScalarsToColor的Lookuptable也需要关注。
在vtkActor中有一个宏函数:
vtkCxxSetObjectMacro(vtkActor,Mapper,vtkMapper);
void vtkActor::SetMapper (vtkMapper* _arg) \
{ \
{ \
{ \
if (this->GetDebug() && vtkObject::GetGlobalWarningDisplay()) \
{ \
vtkOStreamWrapper::EndlType endl; \
vtkOStreamWrapper::UseEndl(endl); \
vtkOStrStreamWrapper vtkmsg; \
vtkmsg << "Debug: In " "/usr/local/paraview4.2my/ParaView-v4.2.0-source/VTK/Rendering/Core/vtkActor.cxx" ", line " << 33 << "\n" \
<< this->GetClassName() << " (" << this << "): " << this->GetClassName() << " (" << this \
<< "): setting " << "Mapper" " to " << _arg << "\n\n"; \
vtkOutputWindowDisplayDebugText(vtkmsg.str()); \
vtkmsg.rdbuf()->freeze(0); \
} \
}; \
if (this->Mapper != _arg) \
{ \
vtkMapper* tempSGMacroVar = this->Mapper; \
this->Mapper = _arg;
if (this->Mapper != 0) { this->Mapper->Register(this); } \
if (tempSGMacroVar != 0) \
{ \
tempSGMacroVar->UnRegister(this); \
} \
this->Modified(); \
} \
}; \
}
_arg一般代表的是类成员变量,也就是静态变量,所有的类公用的类成员变量。
在renderer中,我们可以看到:
void vtkRenderer::Render(void)
{
if(this->Delegate!=0 && this->Delegate->GetUsed())
{
this->Delegate->Render(this);
return;
}
double t1, t2;
int i;
vtkProp *aProp;
int *size;
他有一个render函数,这个函数应该就是用来执行渲染的函数,Delegate是类vtkRendererDelegate类的对象。vtkRendererDelegate主要代替vtkRenderer中的Render方法使其可以从外部的项目中渲染。
// If Draw is not on, ignore the render.
if (!this->Draw)
{
vtkDebugMacro("Ignoring render because Draw is off.");
return;
}
只有在Draw是on时,才能允许render
t1 = vtkTimerLog::GetUniversalTime();
this->InvokeEvent(vtkCommand::StartEvent,NULL);
size = this->RenderWindow->GetSize();//获得RenderWindow的size,从这里我们可以看出RenderWindow是Renderer的一个属性
// if backing store is on and we have a stored image
if (this->BackingStore && this->BackingImage &&
this->MTime < this->RenderTime &&
this->ActiveCamera->GetMTime() < this->RenderTime &&
this->RenderWindow->GetMTime() < this->RenderTime &&
this->BackingStoreSize[0] == size[0] &&
this->BackingStoreSize[1] == size[1])
{
int mods = 0;
vtkLight *light;
backing store是on,并且有BackingImage,且我们可以看出,要在一切ActiveCamera,RenderWindow,this他们都已经更新到最新的(我们可以知道,每一次的修改这三个如果要进行修改,那么只有在这三个修改好之后我们才能开始渲染,不用修改则直接开始)。
// now we just need to check the lights and actors
vtkCollectionSimpleIterator sit;
for(this->Lights->InitTraversal(sit);
(light = this->Lights->GetNextLight(sit)); )
{
if (light->GetSwitch() &&
light->GetMTime() > this->RenderTime)
{
mods = 1;
goto completed_mod_check;
}
}
vtkCollectionSimpleIterator pit;
for (this->Props->InitTraversal(pit);
(aProp = this->Props->GetNextProp(pit)); )
{ // if it's invisible, we can skip the rest
if (aProp->GetVisibility())
{
if (aProp->GetRedrawMTime() > this->RenderTime)
{
mods = 1;
goto completed_mod_check;
}
}
}
确认各个light已经修改完毕,并且确认actors,如果不可见则直接跳过,可见则检查有没有变为最新。
completed_mod_check:
if (!mods)
{
int rx1, ry1, rx2, ry2;
// backing store should be OK, lets use it
// calc the pixel range for the renderer
rx1 = static_cast
(this->RenderWindow->GetSize()[0] - 1));
ry1 = static_cast
(this->RenderWindow->GetSize()[1] - 1));
rx2 = static_cast
(this->RenderWindow->GetSize()[0] - 1));
ry2 = static_cast
(this->RenderWindow->GetSize()[1] - 1));
this->RenderWindow->SetPixelData(rx1,ry1,rx2,ry2,this->BackingImage,0);//画?
this->InvokeEvent(vtkCommand::EndEvent,NULL);
return;
}
}
以上我们可以看出,这是如果已经修改好了,我们则开始执行render。
如果light和actor参数没有设置好:
创建初始的可见的props的list,它将通过AllocateTime()传递。在AllocateTime()这个函数中,time将被分配给每一个prop,并且list可能会被这些cullers重新排序。并且为需要光线投射的props和需要渲染进图片的props创建一些子列表。并且在之后的 AllocateTime类中,这些将会被填满,并且在那里会获得他们总共的数量:
if ( this->Props->GetNumberOfItems() > 0 )
{
this->PropArray = new vtkProp *[this->Props->GetNumberOfItems()];//props的数组
}
else
{
this->PropArray = NULL;
}
this->PropArrayCount = 0;
vtkCollectionSimpleIterator pit;//创建一个集
for ( this->Props->InitTraversal(pit);
(aProp = this->Props->GetNextProp(pit)); )//这里我们可以看出还是从this的Props中得到,可是这是从哪来的
{
if ( aProp->GetVisibility() )
this->PropArray[this->PropArrayCount++] = aProp;//可见的加进去
}
}
if ( this->PropArrayCount == 0 )
{
vtkDebugMacro( << "There are no visible props!" );
}
else
{
// Call all the culling methods to set allocated time
// for each prop and re-order the prop list if desired
this->AllocateTime();
}
// do the render library specific stuff
this->DeviceRender();
// If we aborted, restore old estimated times失败,重新读取旧的预估时间,把分配渲染时间设为0.预估时间也置为0.
// Setting the allocated render time to zero also sets the
// estimated render time to zero, so that when we add back
// in the old value we have set it correctly.
if ( this->RenderWindow->GetAbortRender() )
{
for ( i = 0; i < this->PropArrayCount; i++ )
{
this->PropArray[i]->RestoreEstimatedRenderTime();
}
}
// Clean up the space we allocated before. If the PropArray exists,
// they all should exist
// If we aborted, do not record the last render time.
// Lets play around with determining the accuracy of the
// EstimatedRenderTimes. We can try to adjust for bad
// estimates with the TimeFactor.
后面全是一些渲染放弃后的一些恢复操作和一些相关设置。
下面来看一下在renderer中,是如何设置RenderWindow的:
void vtkRenderer::SetRenderWindow(vtkRenderWindow *renwin)
{
vtkProp *aProp;
if (renwin != this->RenderWindow)
{
// This renderer is be dis-associated with its previous render window.
// this information needs to be passed to the renderer's actors and
// volumes so they can release and render window specific (or graphics
// context specific) information (such as display lists and texture ids)
vtkCollectionSimpleIterator pit;
this->Props->InitTraversal(pit);
for ( aProp = this->Props->GetNextProp(pit);
aProp != NULL;
aProp = this->Props->GetNextProp(pit) )
{
aProp->ReleaseGraphicsResources(this->RenderWindow);
}
// what about lights?
// what about cullers?
this->ReleaseGraphicsResources(this->RenderWindow);
if(this->BackgroundTexture != 0 && this->RenderWindow!=0)
{
this->BackgroundTexture->ReleaseGraphicsResources(this->RenderWindow);
}
this->VTKWindow = renwin;
this->RenderWindow = renwin;
}
}//其实就是如果与前一个窗口不一样,则要释放Prop(actors和Volumes),纹理等都释放掉。
在vtkRenderWindow中我们可以看到也有一个render,所以在渲染时,是通过启动renderer和vtkRenderWindow共同绘制,但是在vtkRenderWindow中视乎是调用它的所有的renderer启动绘制。