vtkMapper,vtkActor,vtkRenderer,vtkRenderWindow四者之间的关系,以及与输入输出相连

在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->Viewport[0]*
                             (this->RenderWindow->GetSize()[0] - 1));
      ry1 = static_cast(this->Viewport[1]*
                             (this->RenderWindow->GetSize()[1] - 1));
      rx2 = static_cast(this->Viewport[2]*
                             (this->RenderWindow->GetSize()[0] - 1));
      ry2 = static_cast(this->Viewport[3]*
                             (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启动绘制。


你可能感兴趣的:(vtkMapper,vtkActor,vtkRenderer,vtkRenderWindow四者之间的关系,以及与输入输出相连)