Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1109 lines
29 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkRenderWindow.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkRenderWindow.h"
#include "vtkCamera.h"
#include "vtkCommand.h"
#include "vtkGraphicsFactory.h"
#include "vtkMath.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRendererCollection.h"
#include "vtkTransform.h"
vtkCxxRevisionMacro(vtkRenderWindow, "$Revision: 1.144 $");
//----------------------------------------------------------------------------
// Needed when we don't use the vtkStandardNewMacro.
vtkInstantiatorNewMacro(vtkRenderWindow);
//----------------------------------------------------------------------------
// Construct an instance of vtkRenderWindow with its screen size
// set to 300x300, borders turned on, positioned at (0,0), double
// buffering turned on, stereo capable off.
vtkRenderWindow::vtkRenderWindow()
{
this->IsPicking = 0;
this->Borders = 1;
this->FullScreen = 0;
this->OldScreen[0] = this->OldScreen[1] = 0;
this->OldScreen[2] = this->OldScreen[3] = 300;
this->OldScreen[4] = 1;
this->DoubleBuffer = 1;
this->PointSmoothing = 0;
this->LineSmoothing = 0;
this->PolygonSmoothing = 0;
this->StereoRender = 0;
this->StereoType = VTK_STEREO_RED_BLUE;
this->StereoStatus = 0;
this->StereoCapableWindow = 0;
this->AlphaBitPlanes = 0;
this->Interactor = NULL;
this->AAFrames = 0;
this->FDFrames = 0;
this->SubFrames = 0;
this->AccumulationBuffer = NULL;
this->AccumulationBufferSize = 0;
this->CurrentSubFrame = 0;
this->DesiredUpdateRate = 0.0001;
this->ResultFrame = NULL;
this->SwapBuffers = 1;
this->AbortRender = 0;
this->InAbortCheck = 0;
this->InRender = 0;
this->NeverRendered = 1;
this->Renderers = vtkRendererCollection::New();
this->NumberOfLayers = 1;
this->CurrentCursor = VTK_CURSOR_DEFAULT;
this->AnaglyphColorSaturation = 0.65;
this->AnaglyphColorMask[0] = 4; // red
this->AnaglyphColorMask[1] = 3; // cyan
}
vtkRenderWindow::~vtkRenderWindow()
{
this->SetInteractor(NULL);
if (this->AccumulationBuffer)
{
delete [] this->AccumulationBuffer;
this->AccumulationBuffer = NULL;
this->AccumulationBufferSize = 0;
}
if (this->ResultFrame)
{
delete [] this->ResultFrame;
this->ResultFrame = NULL;
}
this->Renderers->Delete();
}
// return the correct type of RenderWindow
vtkRenderWindow *vtkRenderWindow::New()
{
// First try to create the object from the vtkObjectFactory
vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkRenderWindow");
return (vtkRenderWindow*)ret;
}
// Create an interactor that will work with this renderer.
vtkRenderWindowInteractor *vtkRenderWindow::MakeRenderWindowInteractor()
{
this->Interactor = vtkRenderWindowInteractor::New();
this->Interactor->SetRenderWindow(this);
return this->Interactor;
}
// Set the interactor that will work with this renderer.
void vtkRenderWindow::SetInteractor(vtkRenderWindowInteractor *rwi)
{
if (this->Interactor != rwi)
{
// to avoid destructor recursion
vtkRenderWindowInteractor *temp = this->Interactor;
this->Interactor = rwi;
if (temp != NULL) {temp->UnRegister(this);}
if (this->Interactor != NULL)
{
this->Interactor->Register(this);
if (this->Interactor->GetRenderWindow() != this)
{
this->Interactor->SetRenderWindow(this);
}
}
}
}
void vtkRenderWindow::SetSubFrames(int subFrames)
{
if (this->SubFrames != subFrames)
{
this->SubFrames = subFrames;
if (this->CurrentSubFrame >= this->SubFrames)
{
this->CurrentSubFrame = 0;
}
vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting SubFrames to " << subFrames);
this->Modified();
}
}
void vtkRenderWindow::SetDesiredUpdateRate(double rate)
{
vtkRenderer *aren;
if (this->DesiredUpdateRate != rate)
{
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(aren = this->Renderers->GetNextRenderer(rsit)); )
{
aren->SetAllocatedRenderTime(1.0/
(rate*this->Renderers->GetNumberOfItems()));
}
this->DesiredUpdateRate = rate;
this->Modified();
}
}
//
// Set the variable that indicates that we want a stereo capable window
// be created. This method can only be called before a window is realized.
//
void vtkRenderWindow::SetStereoCapableWindow(int capable)
{
if (this->StereoCapableWindow != capable)
{
this->StereoCapableWindow = capable;
this->Modified();
}
}
// Turn on stereo rendering
void vtkRenderWindow::SetStereoRender(int stereo)
{
if (stereo == this->StereoRender)
{
return;
}
if (this->StereoCapableWindow ||
(!this->StereoCapableWindow
&& this->StereoType != VTK_STEREO_CRYSTAL_EYES))
{
if (stereo != this->StereoRender)
{
this->StereoRender = stereo;
this->Modified();
}
}
else
{
vtkWarningMacro(<< "Adjusting stereo mode on a window that does not "
<< "support stereo type " << this->GetStereoTypeAsString()
<< " is not possible.");
}
}
// Ask each renderer owned by this RenderWindow to render its image and
// synchronize this process.
void vtkRenderWindow::Render()
{
int *size;
int x,y;
float *p1;
// if we are in the middle of an abort check then return now
if (this->InAbortCheck)
{
return;
}
// if we are in a render already from somewhere else abort now
if (this->InRender)
{
return;
}
// reset the Abort flag
this->AbortRender = 0;
this->InRender = 1;
vtkDebugMacro(<< "Starting Render Method.\n");
this->InvokeEvent(vtkCommand::StartEvent,NULL);
this->NeverRendered = 0;
if ( this->Interactor && ! this->Interactor->GetInitialized() )
{
this->Interactor->Initialize();
}
// if there is a reason for an AccumulationBuffer
if ( this->SubFrames || this->AAFrames || this->FDFrames)
{
// check the current size
size = this->GetSize();
unsigned int bufferSize = 3*size[0]*size[1];
// If there is not a buffer or the size is too small
// re-allocate it
if( !this->AccumulationBuffer
|| bufferSize > this->AccumulationBufferSize)
{
// it is OK to delete null, no sense in two if's
delete [] this->AccumulationBuffer;
// Save the size of the buffer
this->AccumulationBufferSize = 3*size[0]*size[1];
this->AccumulationBuffer = new float [this->AccumulationBufferSize];
memset(this->AccumulationBuffer,0,this->AccumulationBufferSize*sizeof(float));
}
}
// handle any sub frames
if (this->SubFrames)
{
// get the size
size = this->GetSize();
// draw the images
this->DoAARender();
// now accumulate the images
if ((!this->AAFrames) && (!this->FDFrames))
{
p1 = this->AccumulationBuffer;
unsigned char *p2;
unsigned char *p3;
if (this->ResultFrame)
{
p2 = this->ResultFrame;
}
else
{
p2 = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
}
p3 = p2;
for (y = 0; y < size[1]; y++)
{
for (x = 0; x < size[0]; x++)
{
*p1 += *p2; p1++; p2++;
*p1 += *p2; p1++; p2++;
*p1 += *p2; p1++; p2++;
}
}
delete [] p3;
}
// if this is the last sub frame then convert back into unsigned char
this->CurrentSubFrame++;
if (this->CurrentSubFrame >= this->SubFrames)
{
double num;
unsigned char *p2 = new unsigned char [3*size[0]*size[1]];
num = this->SubFrames;
if (this->AAFrames)
{
num *= this->AAFrames;
}
if (this->FDFrames)
{
num *= this->FDFrames;
}
this->ResultFrame = p2;
p1 = this->AccumulationBuffer;
for (y = 0; y < size[1]; y++)
{
for (x = 0; x < size[0]; x++)
{
*p2 = (unsigned char)(*p1/num); p1++; p2++;
*p2 = (unsigned char)(*p1/num); p1++; p2++;
*p2 = (unsigned char)(*p1/num); p1++; p2++;
}
}
this->CurrentSubFrame = 0;
this->CopyResultFrame();
// free any memory
delete [] this->AccumulationBuffer;
this->AccumulationBuffer = NULL;
}
}
else // no subframes
{
// get the size
size = this->GetSize();
this->DoAARender();
// if we had some accumulation occur
if (this->AccumulationBuffer)
{
double num;
unsigned char *p2 = new unsigned char [3*size[0]*size[1]];
if (this->AAFrames)
{
num = this->AAFrames;
}
else
{
num = 1;
}
if (this->FDFrames)
{
num *= this->FDFrames;
}
this->ResultFrame = p2;
p1 = this->AccumulationBuffer;
for (y = 0; y < size[1]; y++)
{
for (x = 0; x < size[0]; x++)
{
*p2 = (unsigned char)(*p1/num); p1++; p2++;
*p2 = (unsigned char)(*p1/num); p1++; p2++;
*p2 = (unsigned char)(*p1/num); p1++; p2++;
}
}
delete [] this->AccumulationBuffer;
this->AccumulationBuffer = NULL;
}
this->CopyResultFrame();
}
if (this->ResultFrame)
{
delete [] this->ResultFrame;
this->ResultFrame = NULL;
}
this->InRender = 0;
this->InvokeEvent(vtkCommand::EndEvent,NULL);
}
// Handle rendering any antialiased frames.
void vtkRenderWindow::DoAARender()
{
int i;
// handle any anti aliasing
if (this->AAFrames)
{
int *size;
int x,y;
float *p1;
vtkRenderer *aren;
vtkCamera *acam;
double *dpoint;
double offsets[2];
double origfocus[4];
double worldOffset[3];
// get the size
size = this->GetSize();
origfocus[3] = 1.0;
for (i = 0; i < this->AAFrames; i++)
{
// jitter the cameras
offsets[0] = vtkMath::Random() - 0.5;
offsets[1] = vtkMath::Random() - 0.5;
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(aren = this->Renderers->GetNextRenderer(rsit)); )
{
acam = aren->GetActiveCamera();
// calculate the amount to jitter
acam->GetFocalPoint(origfocus);
aren->SetWorldPoint(origfocus);
aren->WorldToDisplay();
dpoint = aren->GetDisplayPoint();
aren->SetDisplayPoint(dpoint[0] + offsets[0],
dpoint[1] + offsets[1],
dpoint[2]);
aren->DisplayToWorld();
dpoint = aren->GetWorldPoint();
dpoint[0] /= dpoint[3];
dpoint[1] /= dpoint[3];
dpoint[2] /= dpoint[3];
acam->SetFocalPoint(dpoint);
worldOffset[0] = dpoint[0] - origfocus[0];
worldOffset[1] = dpoint[1] - origfocus[1];
worldOffset[2] = dpoint[2] - origfocus[2];
acam->GetPosition(dpoint);
acam->SetPosition(dpoint[0]+worldOffset[0],
dpoint[1]+worldOffset[1],
dpoint[2]+worldOffset[2]);
}
// draw the images
this->DoFDRender();
// restore the jitter to normal
for (this->Renderers->InitTraversal(rsit);
(aren = this->Renderers->GetNextRenderer(rsit)); )
{
acam = aren->GetActiveCamera();
// calculate the amount to jitter
acam->GetFocalPoint(origfocus);
aren->SetWorldPoint(origfocus);
aren->WorldToDisplay();
dpoint = aren->GetDisplayPoint();
aren->SetDisplayPoint(dpoint[0] - offsets[0],
dpoint[1] - offsets[1],
dpoint[2]);
aren->DisplayToWorld();
dpoint = aren->GetWorldPoint();
dpoint[0] /= dpoint[3];
dpoint[1] /= dpoint[3];
dpoint[2] /= dpoint[3];
acam->SetFocalPoint(dpoint);
worldOffset[0] = dpoint[0] - origfocus[0];
worldOffset[1] = dpoint[1] - origfocus[1];
worldOffset[2] = dpoint[2] - origfocus[2];
acam->GetPosition(dpoint);
acam->SetPosition(dpoint[0]+worldOffset[0],
dpoint[1]+worldOffset[1],
dpoint[2]+worldOffset[2]);
}
// now accumulate the images
p1 = this->AccumulationBuffer;
if (!this->FDFrames)
{
unsigned char *p2;
unsigned char *p3;
if (this->ResultFrame)
{
p2 = this->ResultFrame;
}
else
{
p2 = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
}
p3 = p2;
for (y = 0; y < size[1]; y++)
{
for (x = 0; x < size[0]; x++)
{
*p1 += (float)*p2; p1++; p2++;
*p1 += (float)*p2; p1++; p2++;
*p1 += (float)*p2; p1++; p2++;
}
}
delete [] p3;
}
}
}
else
{
this->DoFDRender();
}
}
// Handle rendering any focal depth frames.
void vtkRenderWindow::DoFDRender()
{
int i;
// handle any focal depth
if (this->FDFrames)
{
int *size;
int x,y;
unsigned char *p2;
unsigned char *p3;
float *p1;
vtkRenderer *aren;
vtkCamera *acam;
double focalDisk;
double *vpn, *dpoint;
double vec[3];
vtkTransform *aTrans = vtkTransform::New();
double offsets[2];
double *orig;
vtkCollectionSimpleIterator rsit;
// get the size
size = this->GetSize();
orig = new double [3*this->Renderers->GetNumberOfItems()];
for (i = 0; i < this->FDFrames; i++)
{
int j = 0;
offsets[0] = vtkMath::Random(); // radius
offsets[1] = vtkMath::Random()*360.0; // angle
// store offsets for each renderer
for (this->Renderers->InitTraversal(rsit);
(aren = this->Renderers->GetNextRenderer(rsit)); )
{
acam = aren->GetActiveCamera();
focalDisk = acam->GetFocalDisk()*offsets[0];
vpn = acam->GetViewPlaneNormal();
aTrans->Identity();
aTrans->Scale(focalDisk,focalDisk,focalDisk);
aTrans->RotateWXYZ(-offsets[1],vpn[0],vpn[1],vpn[2]);
aTrans->TransformVector(acam->GetViewUp(),vec);
dpoint = acam->GetPosition();
// store the position for later
memcpy(orig + j*3,dpoint,3 * sizeof (double));
j++;
acam->SetPosition(dpoint[0]+vec[0],
dpoint[1]+vec[1],
dpoint[2]+vec[2]);
}
// draw the images
this->DoStereoRender();
// restore the jitter to normal
j = 0;
for (this->Renderers->InitTraversal(rsit);
(aren = this->Renderers->GetNextRenderer(rsit)); )
{
acam = aren->GetActiveCamera();
acam->SetPosition(orig + j*3);
j++;
}
// get the pixels for accumulation
// now accumulate the images
p1 = this->AccumulationBuffer;
if (this->ResultFrame)
{
p2 = this->ResultFrame;
}
else
{
p2 = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
}
p3 = p2;
for (y = 0; y < size[1]; y++)
{
for (x = 0; x < size[0]; x++)
{
*p1 += (float)*p2; p1++; p2++;
*p1 += (float)*p2; p1++; p2++;
*p1 += (float)*p2; p1++; p2++;
}
}
delete [] p3;
}
// free memory
delete [] orig;
aTrans->Delete();
}
else
{
this->DoStereoRender();
}
}
// Handle rendering the two different views for stereo rendering.
void vtkRenderWindow::DoStereoRender()
{
this->Start();
this->StereoUpdate();
if (this->StereoType != VTK_STEREO_RIGHT)
{ // render the left eye
this->Renderers->Render();
}
if (this->StereoRender)
{
this->StereoMidpoint();
if (this->StereoType != VTK_STEREO_LEFT)
{ // render the right eye
this->Renderers->Render();
}
this->StereoRenderComplete();
}
}
// Add a renderer to the list of renderers.
void vtkRenderWindow::AddRenderer(vtkRenderer *ren)
{
if (this->HasRenderer(ren))
{
return;
}
// we are its parent
this->MakeCurrent();
ren->SetRenderWindow(this);
this->Renderers->AddItem(ren);
vtkRenderer *aren;
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(aren = this->Renderers->GetNextRenderer(rsit)); )
{
aren->SetAllocatedRenderTime
(1.0/(this->DesiredUpdateRate*this->Renderers->GetNumberOfItems()));
}
}
// Remove a renderer from the list of renderers.
void vtkRenderWindow::RemoveRenderer(vtkRenderer *ren)
{
// we are its parent
this->Renderers->RemoveItem(ren);
}
int vtkRenderWindow::HasRenderer(vtkRenderer *ren)
{
return (ren && this->Renderers->IsItemPresent(ren));
}
int vtkRenderWindow::CheckAbortStatus()
{
if (!this->InAbortCheck)
{
this->InAbortCheck = 1;
this->InvokeEvent(vtkCommand::AbortCheckEvent,NULL);
this->InAbortCheck = 0;
}
return this->AbortRender;
}
void vtkRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Borders: " << (this->Borders ? "On\n":"Off\n");
os << indent << "IsPicking: " << (this->IsPicking ? "On\n":"Off\n");
os << indent << "Double Buffer: " << (this->DoubleBuffer ? "On\n":"Off\n");
os << indent << "Full Screen: " << (this->FullScreen ? "On\n":"Off\n");
os << indent << "Renderers:\n";
this->Renderers->PrintSelf(os,indent.GetNextIndent());
os << indent << "Stereo Capable Window Requested: "
<< (this->StereoCapableWindow ? "Yes\n":"No\n");
os << indent << "Stereo Render: "
<< (this->StereoRender ? "On\n":"Off\n");
os << indent << "Point Smoothing: "
<< (this->PointSmoothing ? "On\n":"Off\n");
os << indent << "Line Smoothing: "
<< (this->LineSmoothing ? "On\n":"Off\n");
os << indent << "Polygon Smoothing: "
<< (this->PolygonSmoothing ? "On\n":"Off\n");
os << indent << "Anti Aliased Frames: " << this->AAFrames << "\n";
os << indent << "Abort Render: " << this->AbortRender << "\n";
os << indent << "Current Cursor: " << this->CurrentCursor << "\n";
os << indent << "Desired Update Rate: " << this->DesiredUpdateRate << "\n";
os << indent << "Focal Depth Frames: " << this->FDFrames << "\n";
os << indent << "In Abort Check: " << this->InAbortCheck << "\n";
os << indent << "NeverRendered: " << this->NeverRendered << "\n";
os << indent << "Interactor: " << this->Interactor << "\n";
os << indent << "Motion Blur Frames: " << this->SubFrames << "\n";
os << indent << "Swap Buffers: " << (this->SwapBuffers ? "On\n":"Off\n");
os << indent << "Stereo Type: " << this->GetStereoTypeAsString() << "\n";
os << indent << "Number of Layers: " << this->NumberOfLayers << "\n";
os << indent << "AccumulationBuffer Size " << this->AccumulationBufferSize << "\n";
os << indent << "AlphaBitPlanes: " << (this->AlphaBitPlanes ? "On" : "Off")
<< endl;
os << indent << "AnaglyphColorSaturation: "
<< this->AnaglyphColorSaturation << "\n";
os << indent << "AnaglyphColorMask: "
<< this->AnaglyphColorMask[0] << " , "
<< this->AnaglyphColorMask[1] << "\n";
}
// Update the system, if needed, due to stereo rendering. For some stereo
// methods, subclasses might need to switch some hardware settings here.
void vtkRenderWindow::StereoUpdate(void)
{
// if stereo is on and it wasn't before
if (this->StereoRender && (!this->StereoStatus))
{
switch (this->StereoType)
{
case VTK_STEREO_RED_BLUE:
this->StereoStatus = 1;
break;
case VTK_STEREO_ANAGLYPH:
this->StereoStatus = 1;
break;
case VTK_STEREO_DRESDEN:
this->StereoStatus = 1;
break;
case VTK_STEREO_INTERLACED:
this->StereoStatus = 1;
}
}
else if ((!this->StereoRender) && this->StereoStatus)
{
switch (this->StereoType)
{
case VTK_STEREO_RED_BLUE:
this->StereoStatus = 0;
break;
case VTK_STEREO_ANAGLYPH:
this->StereoStatus = 0;
break;
case VTK_STEREO_DRESDEN:
this->StereoStatus = 0;
break;
case VTK_STEREO_INTERLACED:
this->StereoStatus = 0;
break;
}
}
}
// Intermediate method performs operations required between the rendering
// of the left and right eye.
void vtkRenderWindow::StereoMidpoint(void)
{
vtkRenderer * aren;
/* For IceT stereo */
for (Renderers->InitTraversal() ; (aren = Renderers->GetNextItem()) ; )
{
aren->StereoMidpoint();
}
if ((this->StereoType == VTK_STEREO_RED_BLUE) ||
(this->StereoType == VTK_STEREO_INTERLACED) ||
(this->StereoType == VTK_STEREO_DRESDEN) ||
(this->StereoType == VTK_STEREO_ANAGLYPH))
{
int *size;
// get the size
size = this->GetSize();
// get the data
this->StereoBuffer = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
}
}
// Handles work required once both views have been rendered when using
// stereo rendering.
void vtkRenderWindow::StereoRenderComplete(void)
{
switch (this->StereoType)
{
case VTK_STEREO_RED_BLUE:
{
unsigned char *buff;
unsigned char *p1, *p2, *p3;
unsigned char* result;
int *size;
int x,y;
int res;
// get the size
size = this->GetSize();
// get the data
buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
p1 = this->StereoBuffer;
p2 = buff;
// allocate the result
result = new unsigned char [size[0]*size[1]*3];
if (!result)
{
vtkErrorMacro(<<"Couldn't allocate memory for RED BLUE stereo.");
return;
}
p3 = result;
// now merge the two images
for (x = 0; x < size[0]; x++)
{
for (y = 0; y < size[1]; y++)
{
res = p1[0] + p1[1] + p1[2];
p3[0] = res/3;
res = p2[0] + p2[1] + p2[2];
p3[1] = 0;
p3[2] = res/3;
p1 += 3;
p2 += 3;
p3 += 3;
}
}
this->ResultFrame = result;
delete [] this->StereoBuffer;
this->StereoBuffer = NULL;
delete [] buff;
}
break;
case VTK_STEREO_ANAGLYPH:
{
unsigned char *buff;
unsigned char *p0, *p1, *p2;
unsigned char* result;
int *size;
int x,y;
int m0, m1, ave0, ave1;
int avecolor[256][3], satcolor[256];
float a;
// get the size
size = this->GetSize();
// get the data
buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
p0 = this->StereoBuffer;
p1 = buff;
// allocate the result
result = new unsigned char [size[0]*size[1]*3];
if (!result)
{
vtkErrorMacro(<<"Couldn't allocate memory for ANAGLYPH stereo.");
return;
}
p2 = result;
// build some tables
a = this->AnaglyphColorSaturation;
m0 = this->AnaglyphColorMask[0];
m1 = this->AnaglyphColorMask[1];
for(x = 0; x < 256; x++)
{
avecolor[x][0] = int((1.0-a)*x*0.3086);
avecolor[x][1] = int((1.0-a)*x*0.6094);
avecolor[x][2] = int((1.0-a)*x*0.0820);
satcolor[x] = int(a*x);
}
// now merge the two images
for (x = 0; x < size[0]; x++)
{
for (y = 0; y < size[1]; y++)
{
ave0 = avecolor[p0[0]][0] + avecolor[p0[1]][1] + avecolor[p0[2]][2];
ave1 = avecolor[p1[0]][0] + avecolor[p1[1]][1] + avecolor[p1[2]][2];
if (m0 & 0x4)
{
p2[0] = satcolor[p0[0]] + ave0;
}
if (m0 & 0x2)
{
p2[1] = satcolor[p0[1]] + ave0;
}
if (m0 & 0x1)
{
p2[2] = satcolor[p0[2]] + ave0;
}
if (m1 & 0x4)
{
p2[0] = satcolor[p1[0]] + ave1;
}
if (m1 & 0x2)
{
p2[1] = satcolor[p1[1]] + ave1;
}
if (m1 & 0x1)
{
p2[2] = satcolor[p1[2]] + ave1;
}
p0 += 3;
p1 += 3;
p2 += 3;
}
}
this->ResultFrame = result;
delete [] this->StereoBuffer;
this->StereoBuffer = NULL;
delete [] buff;
}
break;
case VTK_STEREO_INTERLACED:
{
unsigned char *buff;
unsigned char *p1, *p2, *p3;
unsigned char* result;
int *size, line;
int x,y;
// get the size
size = this->GetSize();
// get the data
buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
p1 = this->StereoBuffer;
p2 = buff;
line = size[0] * 3;
// allocate the result
result = new unsigned char [size[0]*size[1]*3];
if (!result)
{
vtkErrorMacro(<<"Couldn't allocate memory for interlaced stereo.");
return;
}
// now merge the two images
p3 = result;
for (y = 0; y < size[1]; y += 2)
{
for (x = 0; x < size[0]; x++)
{
*p3++ = *p1++;
*p3++ = *p1++;
*p3++ = *p1++;
}
// skip a line
p3 += line;
p1 += line;
}
// now the other eye
p3 = result + line;
p2 += line;
for (y = 1; y < size[1]; y += 2)
{
for (x = 0; x < size[0]; x++)
{
*p3++ = *p2++;
*p3++ = *p2++;
*p3++ = *p2++;
}
// skip a line
p3 += line;
p2 += line;
}
this->ResultFrame = result;
delete [] this->StereoBuffer;
this->StereoBuffer = NULL;
delete [] buff;
}
break;
case VTK_STEREO_DRESDEN:
{
unsigned char *buff;
unsigned char *p1, *p2, *p3;
unsigned char* result;
int *size;
int x,y;
// get the size
size = this->GetSize();
// get the data
buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer);
p1 = this->StereoBuffer;
p2 = buff;
// allocate the result
result = new unsigned char [size[0]*size[1]*3];
if (!result)
{
vtkErrorMacro(
<<"Couldn't allocate memory for dresden display stereo.");
return;
}
// now merge the two images
p3 = result;
for (y = 0; y < size[1]; y++ )
{
for (x = 0; x < size[0]; x+=2)
{
*p3++ = *p1++;
*p3++ = *p1++;
*p3++ = *p1++;
p3+=3;
p1+=3;
}
if( size[0] % 2 == 1 )
{
p3 -= 3;
p1 -= 3;
}
}
// now the other eye
p3 = result + 3;
p2 += 3;
for (y = 0; y < size[1]; y++)
{
for (x = 1; x < size[0]; x+=2)
{
*p3++ = *p2++;
*p3++ = *p2++;
*p3++ = *p2++;
p3+=3;
p2+=3;
}
if( size[0] % 2 == 1 )
{
p3 += 3;
p2 += 3;
}
}
this->ResultFrame = result;
delete [] this->StereoBuffer;
this->StereoBuffer = NULL;
delete [] buff;
}
break;
}
}
void vtkRenderWindow::CopyResultFrame(void)
{
if (this->ResultFrame)
{
int *size;
// get the size
size = this->GetSize();
this->SetPixelData(0,0,size[0]-1,size[1]-1,this->ResultFrame,!this->DoubleBuffer);
}
this->Frame();
}
// treat renderWindow and interactor as one object.
// it might be easier if the GetReference count method were redefined.
void vtkRenderWindow::UnRegister(vtkObjectBase *o)
{
if (this->Interactor && this->Interactor->GetRenderWindow() == this &&
this->Interactor != o)
{
if (this->GetReferenceCount() + this->Interactor->GetReferenceCount() == 3)
{
this->vtkObject::UnRegister(o);
vtkRenderWindowInteractor *tmp = this->Interactor;
tmp->Register(0);
this->Interactor->SetRenderWindow(NULL);
tmp->UnRegister(0);
return;
}
}
this->vtkObject::UnRegister(o);
}
const char *vtkRenderWindow::GetRenderLibrary()
{
return vtkGraphicsFactory::GetRenderLibrary();
}