首页 > 代码库 > vtkMapper

vtkMapper

本文只是整理了该网页的内容:http://www.cnblogs.com/lizhengjin/archive/2009/08/16/1547340.html

 

vtkMapper是一个抽象类,指定了几何数据和图元的接口,子类化vtkMapper,利用颜色查找表把数据映射成图元;封装了opengl的核心函数glBegin(GL_Vertex)glEnd()等生成图元的函数。

有几个重要的机制影响Actror的行为,ScalarVisibility控制标量数据如点属性,单元属性是否启用.

标量模式(ScalarMode)ivar 被用来决定是使用点的scalar数据还是拓扑结构(cell data)的scalar为模型对象(object)添加彩色。默认情况下,是使用点的scalar,当然,如果point和cell都没有scalar,也就不会有添加颜色这个动作了。反之,你也可以明确指出是使用点(point)的scalar或cell的scalar。最后,通过查找颜色表的方式将颜色映射(mapping)到模型对象上,颜色模式是由ColorMode flag决定。

该类的另一个特点是,是否使用“直接渲染模式(immediate mode rendering)”,在直接渲染模式关闭的情况下,则使用“显示链表渲染模式(display list rendering)”。如果使用显示链表模式渲染,就需要构建一个数据结构,通过渲染库(renering library)可以快速完成数据结构构建,并渲染。显示链表渲染模式的一个弱点是,需要另外开辟内存,这会影响运行性能。

// Another important feature of the mapper is the ability to shift the
// z-buffer to resolve coincident topology. For example, if you‘d like to
// draw a mesh with some edges a different color, and the edges lie on the
// mesh, this feature can be useful to get nice looking lines. (See the
// ResolveCoincidentTopology-related methods.)
//另一个特性是利用z-buffer去解决深度容差,比如,如果你想画一个网格,这个网格带有边界,并且边界线的
艳色和网格的艳色不一样,这个时候打开深度偏移就可以得到很好的效果

映射器的另一个重要特征是,它能够将z-buffer转换到与拓扑结构同步解析( shift the z-buffer to resolve coincident topology)。比如,如果你想绘制一个网格,网格上有不同颜色的边线(edges),映射器的这个特征可以使我们得到非常好看的线段(参见ResolveConincidentTopology方法)。

// .SECTION See Also
// vtkDataSetMapper vtkPolyDataMapper

#ifndef __vtkMapper_h
#define __vtkMapper_h

#include "vtkAbstractMapper3D.h"
#include "vtkScalarsToColors.h" // For VTK_COLOR_MODE_DEFAULT and _MAP_SCALARS

#define VTK_RESOLVE_OFF 0
#define VTK_RESOLVE_POLYGON_OFFSET 1
#define VTK_RESOLVE_SHIFT_ZBUFFER 2

#define VTK_GET_ARRAY_BY_ID 0
#define VTK_GET_ARRAY_BY_NAME 1

#define VTK_MATERIALMODE_DEFAULT  0
#define VTK_MATERIALMODE_AMBIENT  1
#define VTK_MATERIALMODE_DIFFUSE  2
#define VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE  3

class vtkWindow;
class vtkRenderer;
class vtkActor;
class vtkDataSet;
class vtkFloatArray;
class vtkImageData;

class VTK_RENDERING_EXPORT vtkMapper : public vtkAbstractMapper3D
{
public:
  vtkTypeRevisionMacro(vtkMapper,vtkAbstractMapper3D);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // Make a shallow copy of this mapper.
  void ShallowCopy(vtkAbstractMapper *m);

  // Description:
  // Overload standard modified time function. If lookup table is modified,
  // then this object is modified as well.
  unsigned long GetMTime();

  // Description:
  // Method initiates the mapping process. Generally sent by the actor 
  // as each frame is rendered.
  virtual void Render(vtkRenderer *ren, vtkActor *a) = 0;//执行渲染的代码,由子类实现

  // Description:
  // Release any graphics resources that are being consumed by this mapper.
  // The parameter window could be used to determine which graphic
  // resources to release.
  virtual void ReleaseGraphicsResources(vtkWindow *) {};

  // Description:
  // Specify a lookup table for the mapper to use.
  void SetLookupTable(vtkScalarsToColors *lut);设置艳色查找表,给actor着色
  vtkScalarsToColors *GetLookupTable();

  // Description:
  // Create default lookup table. Generally used to create one when none
  // is available with the scalar data.
  virtual void CreateDefaultLookupTable();

  // Description:
  // Turn on/off flag to control whether scalar data is used to color objects.
  vtkSetMacro(ScalarVisibility,int);
  vtkGetMacro(ScalarVisibility,int);
  vtkBooleanMacro(ScalarVisibility,int);

  // Description:
  // Turn on/off flag to control whether the mapper‘s data is static. Static data
  // means that the mapper does not propagate updates down the pipeline, greatly
  // decreasing the time it takes to update many mappers. This should only be
  // used if the data never changes.
//如果mapper里面的数据集不发生变化的时候,可以极大的增加速度
  vtkSetMacro(Static,int);
  vtkGetMacro(Static,int);
  vtkBooleanMacro(Static,int);

  // Description:
  // Control how the scalar data is mapped to colors.  By default
  // (ColorModeToDefault), unsigned char scalars are treated as colors, and
  // NOT mapped through the lookup table, while everything else is. Setting
  // ColorModeToMapScalars means that all scalar data will be mapped through
  // the lookup table.  (Note that for multi-component scalars, the
  // particular component to use for mapping can be specified using the
  // SelectColorArray() method.)
//所有的艳色模式都要通过艳色查找表实现
  vtkSetMacro(ColorMode,int);
  vtkGetMacro(ColorMode,int);
  void SetColorModeToDefault() 
    {this->SetColorMode(VTK_COLOR_MODE_DEFAULT);};
  void SetColorModeToMapScalars() 
    {this->SetColorMode(VTK_COLOR_MODE_MAP_SCALARS);};

  // Description:
  // Return the method of coloring scalar data.
  const char *GetColorModeAsString();

  // Description:
  // By default, vertex color is used to map colors to a surface.
  // Colors are interpolated after being mapped.
  // This option avoids color interpolation by using a one dimensional
  // texture map for the colors.
//映射艳色后插值
  vtkSetMacro(InterpolateScalarsBeforeMapping,int);
  vtkGetMacro(InterpolateScalarsBeforeMapping,int);
  vtkBooleanMacro(InterpolateScalarsBeforeMapping,int);

  // Description:
  // Control whether the mapper sets the lookuptable range based on its
  // own ScalarRange, or whether it will use the LookupTable ScalarRange
  // regardless of it‘s own setting. By default the Mapper is allowed to set
  // the LookupTable range, but users who are sharing LookupTables between
  // mappers/actors will probably wish to force the mapper to use the
  // LookupTable unchanged.
  vtkSetMacro(UseLookupTableScalarRange,int);
  vtkGetMacro(UseLookupTableScalarRange,int);
  vtkBooleanMacro(UseLookupTableScalarRange,int);

  // Description:
  // Specify range in terms of scalar minimum and maximum (smin,smax). These
  // values are used to map scalars into lookup table. Has no effect when
  // UseLookupTableScalarRange is true.
  vtkSetVector2Macro(ScalarRange,double);
  vtkGetVectorMacro(ScalarRange,double,2);

  // Description:
  // Turn on/off flag to control whether data is rendered using
  // immediate mode or note. Immediate mode rendering
  // tends to be slower but it can handle larger datasets.
  // The default value is immediate mode off. If you are
  // having problems rendering a large dataset you might
  // want to consider using immediate more rendering.
//控制是否渲染大的数据集
  vtkSetMacro(ImmediateModeRendering,int);
  vtkGetMacro(ImmediateModeRendering,int);
  vtkBooleanMacro(ImmediateModeRendering,int);

  // Description:
  // Turn on/off flag to control whether data is rendered using
  // immediate mode or note. Immediate mode rendering
  // tends to be slower but it can handle larger datasets.
  // The default value is immediate mode off. If you are 
  // having problems rendering a large dataset you might
  // want to consider using immediate more rendering.
  static void SetGlobalImmediateModeRendering(int val);
  static void GlobalImmediateModeRenderingOn() 
    {vtkMapper::SetGlobalImmediateModeRendering(1);};
  static void GlobalImmediateModeRenderingOff() 
    {vtkMapper::SetGlobalImmediateModeRendering(0);};
  static int  GetGlobalImmediateModeRendering();

  // Description:
  // Control how the filter works with scalar point data and cell attribute
  // data.  By default (ScalarModeToDefault), the filter will use point data,
  // and if no point data is available, then cell data is used. Alternatively
  // you can explicitly set the filter to use point data
  // (ScalarModeToUsePointData) or cell data (ScalarModeToUseCellData).
  // You can also choose to get the scalars from an array in point field
  // data (ScalarModeToUsePointFieldData) or cell field data
  // (ScalarModeToUseCellFieldData).  If scalars are coming from a field
  // data array, you must call SelectColorArray before you call
  // GetColors.
  // When ScalarMode is set to use Field Data (ScalarModeToFieldData), you 
  // must call SelectColorArray to choose the field data array to be used to
  // color cells. In this mode, if the poly data has triangle strips, 
  // the field data is treated as the celldata for each mini-cell formed by
  // a triangle in the strip rather than the entire strip.
  vtkSetMacro(ScalarMode,int);
  vtkGetMacro(ScalarMode,int);
  void SetScalarModeToDefault() {
    this->SetScalarMode(VTK_SCALAR_MODE_DEFAULT);};
  void SetScalarModeToUsePointData() {
    this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA);};
  void SetScalarModeToUseCellData() {
    this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_DATA);};
  void SetScalarModeToUsePointFieldData() {
    this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA);};
  void SetScalarModeToUseCellFieldData() {
    this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA);};
  void SetScalarModeToUseFieldData() {
    this->SetScalarMode(VTK_SCALAR_MODE_USE_FIELD_DATA); }
  
  // Description:
  // When ScalarMode is set to UsePointFieldData or UseCellFieldData,
  // you can specify which array to use for coloring using these methods.
  // The lookup table will decide how to convert vectors to colors.
//用点哉属性或者单元哉属性
  void SelectColorArray(int arrayNum); 
  void SelectColorArray(const char* arrayName);

  // Description:
  // Legacy:
  // These methods used to be used to specify the array component.
  // It is better to do this in the lookup table.
  void ColorByArrayComponent(int arrayNum, int component);
  void ColorByArrayComponent(const char* arrayName, int component);
  
  // Description:
  // Get the array name or number and component to color by.
  char* GetArrayName() { return this->ArrayName; }
  int GetArrayId() { return this->ArrayId; }
  int GetArrayAccessMode() { return this->ArrayAccessMode; }
  int GetArrayComponent() { return this->ArrayComponent; }

  // Description:
  // Return the method for obtaining scalar data.
  const char *GetScalarModeAsString();

  // Description:
  // Set/Get a global flag that controls whether coincident topology (e.g., a
  // line on top of a polygon) is shifted to avoid z-buffer resolution (and
  // hence rendering problems). If not off, there are two methods to choose
  // from. PolygonOffset uses graphics systems calls to shift polygons, but
  // does not distinguish vertices and lines from one another. ShiftZBuffer
  // remaps the z-buffer to distinguish vertices, lines, and polygons, but
  // does not always produce acceptable results. If you use the ShiftZBuffer
  // approach, you may also want to set the ResolveCoincidentTopologyZShift
  // value. (Note: not all mappers/graphics systems implement this 
  // functionality.)
  static void SetResolveCoincidentTopology(int val);
  static int  GetResolveCoincidentTopology();
  static void SetResolveCoincidentTopologyToDefault();
  static void SetResolveCoincidentTopologyToOff() 
    {SetResolveCoincidentTopology(VTK_RESOLVE_OFF);}
  static void SetResolveCoincidentTopologyToPolygonOffset() 
    {SetResolveCoincidentTopology(VTK_RESOLVE_POLYGON_OFFSET);}
  static void SetResolveCoincidentTopologyToShiftZBuffer() 
    {SetResolveCoincidentTopology(VTK_RESOLVE_SHIFT_ZBUFFER);}

  // Description:
  // Used to set the polygon offset scale factor and units.
  // Used when ResolveCoincidentTopology is set to PolygonOffset. 
  // These are global variables.
  static void SetResolveCoincidentTopologyPolygonOffsetParameters(
    double factor, double units);
  static void GetResolveCoincidentTopologyPolygonOffsetParameters(
    double& factor, double& units);

  // Description:
  // Used when ResolveCoincidentTopology is set to PolygonOffset. The polygon
  // offset can be applied either to the solid polygonal faces or the
  // lines/vertices. When set (default), the offset is applied to the faces 
  // otherwise it is applied to lines and vertices.
  // This is a global variable.
  static void SetResolveCoincidentTopologyPolygonOffsetFaces(int faces);
  static int GetResolveCoincidentTopologyPolygonOffsetFaces();

  // Description:
  // Used to set the z-shift if ResolveCoincidentTopology is set to
  // ShiftZBuffer. This is a global variable.
  static void SetResolveCoincidentTopologyZShift(double val);
  static double GetResolveCoincidentTopologyZShift();

  // Description:
  // Return bounding box (array of six doubles) of data expressed as
  // (xmin,xmax, ymin,ymax, zmin,zmax).
  virtual double *GetBounds();
  virtual void GetBounds(double bounds[6]) 
    {this->vtkAbstractMapper3D::GetBounds(bounds);};

  // Description:
  // This instance variable is used by vtkLODActor to determine which
  // mapper to use.  It is an estimate of the time necessary to render.
  // Setting the render time does not modify the mapper.
//vtkLoadActor在不同的时刻需要不同的vtkMapper
  void SetRenderTime(double time) {this->RenderTime = time;}
  vtkGetMacro(RenderTime, double);

  //BTX
  // Description:
  // Get the input as a vtkDataSet.  This method is overridden in
  // the specialized mapper classes to return more specific data types.
  vtkDataSet *GetInput();
  //ETX

  // Description:
  // Get the input to this mapper as a vtkDataSet, instead of as a 
  // more specialized data type that the subclass may return from
  // GetInput().  This method is provided for use in the wrapper languages,
  // C++ programmers should use GetInput() instead.
  vtkDataSet *GetInputAsDataSet() 
    {return this->GetInput();}

  // Description:
  // Map the scalars (if there are any scalars and ScalarVisibility is on)
  // through the lookup table, returning an unsigned char RGBA array. This is
  // typically done as part of the rendering process. The alpha parameter 
  // allows the blending of the scalars with an additional alpha (typically
  // which comes from a vtkActor, etc.)
  vtkUnsignedCharArray *MapScalars(double alpha);
  
  // Description:
  // Set/Get the light-model color mode. 
  vtkSetMacro(ScalarMaterialMode,int);
  vtkGetMacro(ScalarMaterialMode,int);
  void SetScalarMaterialModeToDefault() 
    {this->SetScalarMaterialMode(VTK_MATERIALMODE_DEFAULT);};
  void SetScalarMaterialModeToAmbient() 
    {this->SetScalarMaterialMode(VTK_MATERIALMODE_AMBIENT);};
  void SetScalarMaterialModeToDiffuse() 
    {this->SetScalarMaterialMode(VTK_MATERIALMODE_DIFFUSE);};
  void SetScalarMaterialModeToAmbientAndDiffuse() 
    {this->SetScalarMaterialMode(VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE);};

  // Description:
  // Return the light-model color mode.
  const char *GetScalarMaterialModeAsString();

protected:
  vtkMapper();
  ~vtkMapper();

  vtkUnsignedCharArray *Colors;

  // Use texture coordinates for coloring.
  int InterpolateScalarsBeforeMapping;
  // Coordinate for each point.
  vtkFloatArray *ColorCoordinates;
  // 1D ColorMap used for the texture image.
  vtkImageData* ColorTextureMap;
  void MapScalarsToTexture(vtkDataArray* scalars, double alpha);

  vtkScalarsToColors *LookupTable;
  int ScalarVisibility;
  vtkTimeStamp BuildTime;
  double ScalarRange[2];
  int UseLookupTableScalarRange;
  int ImmediateModeRendering;
  int ColorMode;
  int ScalarMode;
  int ScalarMaterialMode;

  double RenderTime;

  // for coloring by a component of a field data array
  int ArrayId;
  char ArrayName[256];
  int ArrayComponent;
  int ArrayAccessMode;

  int Static;
  
private:
  vtkMapper(const vtkMapper&);  // Not implemented.
  void operator=(const vtkMapper&);  // Not implemented.
};

#endif
//提供了艳色查找表,深度偏移等


#include "vtkMapper.h"

#include "vtkDataSet.h"
#include "vtkExecutive.h"
#include "vtkLookupTable.h"
#include "vtkFloatArray.h"
#include "vtkImageData.h"
#include "vtkPointData.h"
#include "vtkMath.h"

vtkCxxRevisionMacro(vtkMapper, "$Revision: 1.122 $");

// Initialize static member that controls global immediate mode rendering
static int vtkMapperGlobalImmediateModeRendering = 0;

// Initialize static member that controls global coincidence resolution
static int vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
static double vtkMapperGlobalResolveCoincidentTopologyZShift = 0.01;
static double vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = 1.0;
static double vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = 1.0;
static int vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFaces = 1;

//偏移相关的参数


// Construct with initial range (0,1).            
vtkMapper::vtkMapper()
{
  this->Colors = 0;
  this->Static = 0;
  this->LookupTable = 0;

  this->ScalarVisibility = 1;
  this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0;
  this->UseLookupTableScalarRange = 0;

  this->ImmediateModeRendering = 0;

  this->ColorMode = VTK_COLOR_MODE_DEFAULT;
  this->ScalarMode = VTK_SCALAR_MODE_DEFAULT;
  this->ScalarMaterialMode = VTK_MATERIALMODE_DEFAULT;
  
  vtkMath::UninitializeBounds(this->Bounds);
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
  
  this->RenderTime = 0.0;
  
  strcpy(this->ArrayName, "");
  this->ArrayId = -1;
  this->ArrayComponent = 0;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;

  this->InterpolateScalarsBeforeMapping = 0;
  this->ColorCoordinates = 0;
  this->ColorTextureMap = 0;
}

vtkMapper::~vtkMapper()
{
  if (this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  if ( this->Colors != 0 )
    {
    this->Colors->UnRegister(this);
    }
  if ( this->ColorCoordinates != 0 )
    {
    this->ColorCoordinates->UnRegister(this);
    }
  if ( this->ColorTextureMap != 0 )
    {
    this->ColorTextureMap->UnRegister(this);
    }
}

// Get the bounds for the input of this mapper as 
// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
double *vtkMapper::GetBounds()
{
  static double bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  vtkDataSet *input = this->GetInput();
  if ( ! input ) 
    {
    return bounds;
    }
  else
    {
    if (!this->Static)
      {
      this->Update();
      }
    input->GetBounds(this->Bounds);
    return this->Bounds;
    }
}

vtkDataSet *vtkMapper::GetInput()
{
  if (this->GetNumberOfInputConnections(0) < 1)
    {
    return 0;
    }
  return vtkDataSet::SafeDownCast(
    this->GetExecutive()->GetInputData(0, 0));
}

void vtkMapper::SetGlobalImmediateModeRendering(int val)
{
  if (val == vtkMapperGlobalImmediateModeRendering)
    {
    return;
    }
  vtkMapperGlobalImmediateModeRendering = val;
}

int vtkMapper::GetGlobalImmediateModeRendering()
{
  return vtkMapperGlobalImmediateModeRendering;
}

void vtkMapper::SetResolveCoincidentTopology(int val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopology)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopology = val;
}

int vtkMapper::GetResolveCoincidentTopology()
{
  return vtkMapperGlobalResolveCoincidentTopology;
}

void vtkMapper::SetResolveCoincidentTopologyToDefault()
{
  vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
}

void vtkMapper::SetResolveCoincidentTopologyZShift(double val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopologyZShift)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyZShift = val;
}

double vtkMapper::GetResolveCoincidentTopologyZShift()
{
  return vtkMapperGlobalResolveCoincidentTopologyZShift;
}

void vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(
                                            double factor, double units)
{
  if (factor == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor &&
      units == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits )
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = factor;
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = units;
}

void vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(
                           double& factor, double& units)
{
  factor = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor;
  units = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits;
}

void vtkMapper::SetResolveCoincidentTopologyPolygonOffsetFaces(int faces)
{
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFaces = faces;
}

int vtkMapper::GetResolveCoincidentTopologyPolygonOffsetFaces()
{
  return vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFaces;
}

// Overload standard modified time function. If lookup table is modified,
// then this object is modified as well.
unsigned long vtkMapper::GetMTime()
{
  //unsigned long mTime=this->MTime.GetMTime();
  unsigned long mTime=vtkAbstractMapper::GetMTime();
  unsigned long lutMTime;

  if ( this->LookupTable != NULL )
    {
    lutMTime = this->LookupTable->GetMTime();
    mTime = ( lutMTime > mTime ? lutMTime : mTime );
    }

  return mTime;
}

void vtkMapper::ShallowCopy(vtkAbstractMapper *mapper)
{
  vtkMapper *m = vtkMapper::SafeDownCast(mapper);
  if ( m != NULL )
    {
    this->SetLookupTable(m->GetLookupTable());
    this->SetScalarVisibility(m->GetScalarVisibility());
    this->SetScalarRange(m->GetScalarRange());
    this->SetColorMode(m->GetColorMode());
    this->SetScalarMode(m->GetScalarMode());
    this->SetScalarMaterialMode(m->GetScalarMaterialMode());
    this->SetImmediateModeRendering(m->GetImmediateModeRendering());
    this->SetUseLookupTableScalarRange(m->GetUseLookupTableScalarRange());
    if ( m->GetArrayAccessMode() == VTK_GET_ARRAY_BY_ID )
      {
      this->ColorByArrayComponent(m->GetArrayId(),m->GetArrayComponent());
      }
    else
      {
      this->ColorByArrayComponent(m->GetArrayName(),m->GetArrayComponent());
      }
    }

  // Now do superclass
  this->vtkAbstractMapper3D::ShallowCopy(mapper);

}

// a side effect of this is that this->Colors is also set
// to the return value
vtkUnsignedCharArray *vtkMapper::MapScalars(double alpha)
{
  int cellFlag = 0;
  
  vtkDataArray *scalars = vtkAbstractMapper::
    GetScalars(this->GetInput(), this->ScalarMode, this->ArrayAccessMode,
               this->ArrayId, this->ArrayName, cellFlag);

  // This is for a legacy feature: selection of the array component to color by
  // from the mapper.  It is now in the lookuptable.  When this feature
  // is removed, we can remove this condition.
  if (scalars == 0 || scalars->GetNumberOfComponents() <= this->ArrayComponent)
    {
    this->ArrayComponent = 0;
    }

  if ( !this->ScalarVisibility || scalars==0 || this->GetInput()==0)
    { // No scalar colors.
    if ( this->ColorCoordinates )
      {
      this->ColorCoordinates->UnRegister(this);
      this->ColorCoordinates = 0;
      }
    if ( this->ColorTextureMap )
      {
      this->ColorTextureMap->UnRegister(this);
      this->ColorTextureMap = 0;
      }
    if ( this->Colors )
      {
      this->Colors->UnRegister(this);
      this->Colors = 0;
      }
    return 0;
    }

  // Get the lookup table.
  if ( scalars->GetLookupTable() )
    {
    this->SetLookupTable(scalars->GetLookupTable());
    }
  else
    {
    // make sure we have a lookup table//make sure we have a lookup table
    if ( this->LookupTable == 0 )
      {
      this->CreateDefaultLookupTable();
      }
    this->LookupTable->Build();
    }
  if ( !this->UseLookupTableScalarRange )
    {
    this->LookupTable->SetRange(this->ScalarRange);
    }

  // Decide betweeen texture color or vertex color.
  // Cell data always uses vertext color.
  // Only point data can use both texture and vertext coloring.
  if (this->InterpolateScalarsBeforeMapping && ! cellFlag)
    {
    // Only use texture color if we are mapping scalars.
    // Directly coloring with RGB unsigned chars should not use texture.
    if ( this->ColorMode != VTK_COLOR_MODE_DEFAULT || 
         (vtkUnsignedCharArray::SafeDownCast(scalars)) == 0 )
      { // Texture color option.
      this->MapScalarsToTexture(scalars, alpha);
      return 0;
      }
    }
    
  // Vertex colors are being used.
  // Get rid of texure Color arrays.  Only texture or vertex coloring 
  // can be active at one time.  The existence of the array is the 
  // signal to use that technique.
  if ( this->ColorCoordinates )
    {
    this->ColorCoordinates->UnRegister(this);
    this->ColorCoordinates = 0;
    }
  if ( this->ColorTextureMap )
    {
    this->ColorTextureMap->UnRegister(this);
    this->ColorTextureMap = 0;
    }

  // Lets try to resuse the old colors.//Lets try to resuse the old colors;
  if (this->Colors)
    {
    if (this->LookupTable && this->LookupTable->GetAlpha() == alpha)
      {
      if (this->GetMTime() < this->Colors->GetMTime() &&
          this->GetInput()->GetMTime() < this->Colors->GetMTime() &&
          this->LookupTable->GetMTime() < this->Colors->GetMTime())
        {
        return this->Colors;
        }
      }
    }
  
  // Get rid of old colors
  if ( this->Colors )
    {
    this->Colors->UnRegister(this);
    this->Colors = 0;
    }
  
  // map scalars
  this->LookupTable->SetAlpha(alpha);
  this->Colors = this->LookupTable->
    MapScalars(scalars, this->ColorMode, this->ArrayComponent);
  // Consistent register and unregisters
  this->Colors->Register(this);
  this->Colors->Delete();

  return this->Colors;
}


void vtkMapper::SelectColorArray(int arrayNum)//SelectColorArray(int arrayNum)
{
  this->ColorByArrayComponent(arrayNum, -1);
}
 

void vtkMapper::SelectColorArray(const char* arrayName)
{
  this->ColorByArrayComponent(arrayName, -1);
}


void vtkMapper::ColorByArrayComponent(int arrayNum, int component)
{
  if (this->ArrayId == arrayNum && component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();
  
  this->ArrayId = arrayNum;
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;
}

void vtkMapper::ColorByArrayComponent(const char* arrayName, int component)
{
  if (!arrayName || 
      ( strcmp(this->ArrayName, arrayName) == 0 &&
        component == this->ArrayComponent &&
        this->ArrayAccessMode == VTK_GET_ARRAY_BY_NAME ))
    {
    return;
    }
  this->Modified();
  
  strcpy(this->ArrayName, arrayName);
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME;
}

// Specify a lookup table for the mapper to use.
void vtkMapper::SetLookupTable(vtkScalarsToColors *lut)
{
  if ( this->LookupTable != lut ) 
    {
    if ( this->LookupTable) 
      {
      this->LookupTable->UnRegister(this);
      }
    this->LookupTable = lut;
    if (lut)
      {
      lut->Register(this);
      }
    this->Modified();
    }
}

vtkScalarsToColors *vtkMapper::GetLookupTable()
{
  if ( this->LookupTable == 0 )
    {
    this->CreateDefaultLookupTable();
    }
  return this->LookupTable;
}

void vtkMapper::CreateDefaultLookupTable()
{
  if ( this->LookupTable) 
    {
    this->LookupTable->UnRegister(this);
    }
  this->LookupTable = vtkLookupTable::New();
  // Consistent Register/UnRegisters.
  this->LookupTable->Register(this);
  this->LookupTable->Delete();
}

// Return the method of coloring scalar data.
const char *vtkMapper::GetColorModeAsString(void)
{
  if ( this->ColorMode == VTK_COLOR_MODE_MAP_SCALARS ) 
    {
    return "MapScalars";
    }
  else 
    {
    return "Default";
    }
}

// Return the method for obtaining scalar data.
const char *vtkMapper::GetScalarModeAsString(void)
{
  if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    return "UseCellData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA ) 
    {
    return "UsePointData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    return "UsePointFieldData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    return "UseCellFieldData";
    }
  else 
    {
    return "Default";
    }
}

const char *vtkMapper::GetScalarMaterialModeAsString(void)
{
  if ( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT )
    {
    return "Ambient";
    }
  else if ( this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE )
    {
    return "Diffuse";
    }
  else if ( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE )
    {
    return "Ambient and Diffuse";
    }
  else
    {
    return "Default";
    }
}


template<class T>
void vtkMapperCreateColorTextureCoordinates(T* input, float* output,
                                            vtkIdType num, int numComps, 
                                            int component, double* range)
{
  double tmp, sum;
  double k = 1.0 / (range[1]-range[0]);
  vtkIdType i;
  int j;

  if (component < 0 || component >= numComps)
    {
    for (i = 0; i < num; ++i)
      {
      sum = 0;
      for (j = 0; j < numComps; ++j)
        {
        tmp = static_cast<double>(*input);
        sum += (tmp * tmp);
        ++input;
        }
      output[i] = k * (sqrt(sum) - range[0]);
      if (output[i] > 1.0)
        {
        output[i] = 1.0;
        }
      if (output[i] < 0.0)
        {
        output[i] = 0.0;
        }
      }
    }  
  else
    {
    input += component;
    for (i = 0; i < num; ++i)
      {
      output[i] = k * (static_cast<double>(*input) - range[0]);
      if (output[i] > 1.0)
        {
        output[i] = 1.0;
        }
      if (output[i] < 0.0)
        {
        output[i] = 0.0;
        }
      input = input + numComps;
      }      
    }
}


#define ColorTextureMapSize 256
// a side effect of this is that this->ColorCoordinates and 
// this->ColorTexture are set.
void vtkMapper::MapScalarsToTexture(vtkDataArray* scalars, double alpha)
{
  double* range = this->LookupTable->GetRange();
  
  // Get rid of vertex color array.  Only texture or vertex coloring 
  // can be active at one time.  The existence of the array is the 
  // signal to use that technique.
  if ( this->Colors )
    {
    this->Colors->UnRegister(this);
    this->Colors = 0;
    }

  // If the lookup table has changed, the recreate the color texture map.
  // Set a new lookup table changes this->MTime.
  if (this->ColorTextureMap == 0 || 
      this->GetMTime() > this->ColorTextureMap->GetMTime() ||
      this->LookupTable->GetMTime() > this->ColorTextureMap->GetMTime() ||
      this->LookupTable->GetAlpha() != alpha)
    {
    this->LookupTable->SetAlpha(alpha);
    if ( this->ColorTextureMap )
      {
      this->ColorTextureMap->UnRegister(this);
      this->ColorTextureMap = 0;
      }
    // Get the texture map from the lookup table.
    // Create a dummy ramp of scalars.
    // In the future, we could extend vtkScalarsToColors.
    double k = (range[1]-range[0]) / (ColorTextureMapSize-1);
    vtkFloatArray* tmp = vtkFloatArray::New();
    tmp->SetNumberOfTuples(ColorTextureMapSize);
    float* ptr = tmp->GetPointer(0);
    for (int i = 0; i < ColorTextureMapSize; ++i)
      {
      *ptr = range[0] + i * k;
      ++ptr;
      }
    this->ColorTextureMap = vtkImageData::New();
    this->ColorTextureMap->SetExtent(0,ColorTextureMapSize-1, 
                                     0,0, 0,0);
    this->ColorTextureMap->SetNumberOfScalarComponents(4);
    this->ColorTextureMap->SetScalarTypeToUnsignedChar();
    this->ColorTextureMap->GetPointData()->SetScalars(
         this->LookupTable->MapScalars(tmp, this->ColorMode, 0));
    // Do we need to delete the scalars?
    this->ColorTextureMap->GetPointData()->GetScalars()->Delete();
    // Consistent register and unregisters
    this->ColorTextureMap->Register(this);
    this->ColorTextureMap->Delete();
    tmp->Delete();
    }

  // Create new coordinates if necessary.
  // Need to compare lookup table incase the range has changed.
  if (this->ColorCoordinates == 0 ||
      this->GetMTime() > this->ColorCoordinates->GetMTime() ||
      this->GetInput()->GetMTime() > this->ColorCoordinates->GetMTime() ||
      this->LookupTable->GetMTime() > this->ColorCoordinates->GetMTime())
    {
    // Get rid of old colors
    if ( this->ColorCoordinates )
      {
      this->ColorCoordinates->UnRegister(this);
      this->ColorCoordinates = 0;
      }
  
    // Now create the color texture coordinates.
    int numComps = scalars->GetNumberOfComponents();
    void* input = scalars->GetVoidPointer(0);
    vtkIdType num = scalars->GetNumberOfTuples();
    this->ColorCoordinates = vtkFloatArray::New();
    this->ColorCoordinates->SetNumberOfTuples(num);
    float* output = this->ColorCoordinates->GetPointer(0);
    int scalarComponent;
    // Although I like the feature of applying magnitude to single component
    // scalars, it is not how the old MapScalars for vertex coloring works.
    if (this->LookupTable->GetVectorMode() == vtkScalarsToColors::MAGNITUDE &&
        scalars->GetNumberOfComponents() > 1)
      {
      scalarComponent = -1;
      }
    else
      {
      scalarComponent = this->LookupTable->GetVectorComponent();
      }
    switch (scalars->GetDataType())
      {
      vtkTemplateMacro(
        vtkMapperCreateColorTextureCoordinates(static_cast<VTK_TT*>(input),
                                               output, num, numComps,
                                               scalarComponent, range)
        );
      case VTK_BIT:
        vtkErrorMacro("Cannot color by bit array.");
        break;
      default:
        vtkErrorMacro(<< "Unknown input ScalarType");
        return;
      }
    }
}

void vtkMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }

  os << indent << "Immediate Mode Rendering: " 
    << (this->ImmediateModeRendering ? "On\n" : "Off\n");
  os << indent << "Global Immediate Mode Rendering: " << 
    (vtkMapperGlobalImmediateModeRendering ? "On\n" : "Off\n");

  os << indent << "Scalar Visibility: " 
    << (this->ScalarVisibility ? "On\n" : "Off\n");

  os << indent << "Static: " 
    << (this->Static ? "On\n" : "Off\n");

  double *range = this->GetScalarRange();
  os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";

  os << indent << "UseLookupTableScalarRange: " 
     << this->UseLookupTableScalarRange << "\n";

  os << indent << "Color Mode: " << this->GetColorModeAsString() << endl;
  os << indent << "InterpolateScalarsBeforeMapping: " 
     << (this->InterpolateScalarsBeforeMapping ? "On\n" : "Off\n");

  os << indent << "Scalar Mode: " << this->GetScalarModeAsString() << endl;

  os << indent << "LM Color Mode: " 
     << this->GetScalarMaterialModeAsString() << endl;

  os << indent << "RenderTime: " << this->RenderTime << endl;

  os << indent << "Resolve Coincident Topology: ";
  if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_OFF )
    {
    os << "Off" << endl;
    }
  else if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_POLYGON_OFFSET )
    {
    os << "Polygon Offset" << endl;
    }
  else
    {
    os << "Shift Z-Buffer" << endl;
    }
}

 

vtkMapper