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.
335 lines
8.2 KiB
335 lines
8.2 KiB
2 years ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: $RCSfile: vtkOpenGLRenderer.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 "vtkOpenGLRenderer.h"
|
||
|
|
||
|
#include "vtkCuller.h"
|
||
|
#include "vtkLightCollection.h"
|
||
|
#include "vtkObjectFactory.h"
|
||
|
#include "vtkOpenGLCamera.h"
|
||
|
#include "vtkOpenGLLight.h"
|
||
|
#include "vtkOpenGLProperty.h"
|
||
|
#include "vtkRenderWindow.h"
|
||
|
|
||
|
#ifndef VTK_IMPLEMENT_MESA_CXX
|
||
|
# include "vtkOpenGL.h"
|
||
|
#endif
|
||
|
|
||
|
#include <math.h>
|
||
|
|
||
|
class vtkGLPickInfo
|
||
|
{
|
||
|
public:
|
||
|
GLuint* PickBuffer;
|
||
|
GLuint PickedId;
|
||
|
};
|
||
|
|
||
|
#ifndef VTK_IMPLEMENT_MESA_CXX
|
||
|
vtkCxxRevisionMacro(vtkOpenGLRenderer, "$Revision: 1.50 $");
|
||
|
vtkStandardNewMacro(vtkOpenGLRenderer);
|
||
|
#endif
|
||
|
|
||
|
#define VTK_MAX_LIGHTS 8
|
||
|
|
||
|
vtkOpenGLRenderer::vtkOpenGLRenderer()
|
||
|
{
|
||
|
this->PickInfo = new vtkGLPickInfo;
|
||
|
this->NumberOfLightsBound = 0;
|
||
|
this->PickInfo->PickBuffer = 0;
|
||
|
this->PickInfo->PickedId = 0;
|
||
|
this->PickedZ = 0;
|
||
|
}
|
||
|
|
||
|
// Internal method temporarily removes lights before reloading them
|
||
|
// into graphics pipeline.
|
||
|
void vtkOpenGLRenderer::ClearLights (void)
|
||
|
{
|
||
|
short curLight;
|
||
|
float Info[4];
|
||
|
|
||
|
// define a lighting model and set up the ambient light.
|
||
|
// use index 11 for the heck of it. Doesn't matter except for 0.
|
||
|
|
||
|
// update the ambient light
|
||
|
Info[0] = this->Ambient[0];
|
||
|
Info[1] = this->Ambient[1];
|
||
|
Info[2] = this->Ambient[2];
|
||
|
Info[3] = 1.0;
|
||
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Info);
|
||
|
|
||
|
if ( this->TwoSidedLighting )
|
||
|
{
|
||
|
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
|
||
|
}
|
||
|
|
||
|
// now delete all the old lights
|
||
|
for (curLight = GL_LIGHT0; curLight < GL_LIGHT0 + VTK_MAX_LIGHTS; curLight++)
|
||
|
{
|
||
|
glDisable((GLenum)curLight);
|
||
|
}
|
||
|
|
||
|
this->NumberOfLightsBound = 0;
|
||
|
}
|
||
|
|
||
|
// Ask lights to load themselves into graphics pipeline.
|
||
|
int vtkOpenGLRenderer::UpdateLights ()
|
||
|
{
|
||
|
vtkLight *light;
|
||
|
short curLight;
|
||
|
float status;
|
||
|
int count;
|
||
|
|
||
|
// Check if a light is on. If not then make a new light.
|
||
|
count = 0;
|
||
|
curLight= this->NumberOfLightsBound + GL_LIGHT0;
|
||
|
|
||
|
vtkCollectionSimpleIterator sit;
|
||
|
for(this->Lights->InitTraversal(sit);
|
||
|
(light = this->Lights->GetNextLight(sit)); )
|
||
|
{
|
||
|
status = light->GetSwitch();
|
||
|
if ((status > 0.0)&& (curLight < (GL_LIGHT0+VTK_MAX_LIGHTS)))
|
||
|
{
|
||
|
curLight++;
|
||
|
count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( !count )
|
||
|
{
|
||
|
vtkDebugMacro(<<"No lights are on, creating one.");
|
||
|
this->CreateLight();
|
||
|
}
|
||
|
|
||
|
count = 0;
|
||
|
curLight= this->NumberOfLightsBound + GL_LIGHT0;
|
||
|
|
||
|
// set the matrix mode for lighting. ident matrix on viewing stack
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glPushMatrix();
|
||
|
|
||
|
for(this->Lights->InitTraversal(sit);
|
||
|
(light = this->Lights->GetNextLight(sit)); )
|
||
|
{
|
||
|
|
||
|
status = light->GetSwitch();
|
||
|
|
||
|
// if the light is on then define it and bind it.
|
||
|
// also make sure we still have room.
|
||
|
if ((status > 0.0)&& (curLight < (GL_LIGHT0+VTK_MAX_LIGHTS)))
|
||
|
{
|
||
|
light->Render((vtkRenderer *)this,curLight);
|
||
|
glEnable((GLenum)curLight);
|
||
|
// increment the current light by one
|
||
|
curLight++;
|
||
|
count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this->NumberOfLightsBound = curLight - GL_LIGHT0;
|
||
|
|
||
|
glPopMatrix();
|
||
|
glEnable(GL_LIGHTING);
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
// Concrete open gl render method.
|
||
|
void vtkOpenGLRenderer::DeviceRender(void)
|
||
|
{
|
||
|
// Do not remove this MakeCurrent! Due to Start / End methods on
|
||
|
// some objects which get executed during a pipeline update,
|
||
|
// other windows might get rendered since the last time
|
||
|
// a MakeCurrent was called.
|
||
|
this->RenderWindow->MakeCurrent();
|
||
|
|
||
|
// standard render method
|
||
|
this->ClearLights();
|
||
|
|
||
|
this->UpdateCamera();
|
||
|
this->UpdateLightGeometry();
|
||
|
this->UpdateLights();
|
||
|
|
||
|
// set matrix mode for actors
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
|
||
|
this->UpdateGeometry();
|
||
|
|
||
|
// clean up the model view matrix set up by the camera
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glPopMatrix();
|
||
|
}
|
||
|
|
||
|
|
||
|
void vtkOpenGLRenderer::PrintSelf(ostream& os, vtkIndent indent)
|
||
|
{
|
||
|
this->Superclass::PrintSelf(os,indent);
|
||
|
|
||
|
os << indent << "Number Of Lights Bound: " <<
|
||
|
this->NumberOfLightsBound << "\n";
|
||
|
os << indent << "PickBuffer " << this->PickInfo->PickBuffer << "\n";
|
||
|
os << indent << "PickedId" << this->PickInfo->PickedId<< "\n";
|
||
|
os << indent << "PickedZ " << this->PickedZ << "\n";
|
||
|
}
|
||
|
|
||
|
|
||
|
void vtkOpenGLRenderer::Clear(void)
|
||
|
{
|
||
|
GLbitfield clear_mask = 0;
|
||
|
|
||
|
if (! this->Transparent())
|
||
|
{
|
||
|
glClearColor( ((GLclampf)(this->Background[0])),
|
||
|
((GLclampf)(this->Background[1])),
|
||
|
((GLclampf)(this->Background[2])),
|
||
|
((GLclampf)(0.0)) );
|
||
|
clear_mask |= GL_COLOR_BUFFER_BIT;
|
||
|
}
|
||
|
|
||
|
glClearDepth( (GLclampd)( 1.0 ) );
|
||
|
clear_mask |= GL_DEPTH_BUFFER_BIT;
|
||
|
|
||
|
vtkDebugMacro(<< "glClear\n");
|
||
|
glClear(clear_mask);
|
||
|
}
|
||
|
|
||
|
void vtkOpenGLRenderer::StartPick(unsigned int pickFromSize)
|
||
|
{
|
||
|
|
||
|
int bufferSize = pickFromSize * 4;
|
||
|
|
||
|
// Do not remove this MakeCurrent! Due to Start / End methods on
|
||
|
// some objects which get executed during a pipeline update,
|
||
|
// other windows might get rendered since the last time
|
||
|
// a MakeCurrent was called.
|
||
|
this->RenderWindow->MakeCurrent();
|
||
|
this->RenderWindow->IsPickingOn();
|
||
|
this->PickInfo->PickBuffer = new GLuint[bufferSize];
|
||
|
glSelectBuffer(bufferSize, this->PickInfo->PickBuffer);
|
||
|
// change to selection mode
|
||
|
(void)glRenderMode(GL_SELECT);
|
||
|
// initialize the pick names and add a 0 name, for no pick
|
||
|
glInitNames();
|
||
|
glPushName(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void vtkOpenGLRenderer::UpdatePickId()
|
||
|
{
|
||
|
glLoadName(this->CurrentPickId++);
|
||
|
}
|
||
|
|
||
|
|
||
|
void vtkOpenGLRenderer::DevicePickRender()
|
||
|
{
|
||
|
// Do not remove this MakeCurrent! Due to Start / End methods on
|
||
|
// some objects which get executed during a pipeline update,
|
||
|
// other windows might get rendered since the last time
|
||
|
// a MakeCurrent was called.
|
||
|
this->RenderWindow->MakeCurrent();
|
||
|
|
||
|
// standard render method
|
||
|
this->ClearLights();
|
||
|
|
||
|
this->UpdateCamera();
|
||
|
this->UpdateLightGeometry();
|
||
|
this->UpdateLights();
|
||
|
|
||
|
// set matrix mode for actors
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
|
||
|
this->PickGeometry();
|
||
|
|
||
|
// clean up the model view matrix set up by the camera
|
||
|
glMatrixMode(GL_MODELVIEW);
|
||
|
glPopMatrix();
|
||
|
}
|
||
|
|
||
|
|
||
|
void vtkOpenGLRenderer::DonePick()
|
||
|
{
|
||
|
glFlush();
|
||
|
GLuint hits = glRenderMode(GL_RENDER);
|
||
|
unsigned int depth = (unsigned int)-1;
|
||
|
GLuint* ptr = this->PickInfo->PickBuffer;
|
||
|
this->PickInfo->PickedId = 0;
|
||
|
for(unsigned int k =0; k < hits; k++)
|
||
|
{
|
||
|
int num_names = *ptr;
|
||
|
int save = 0;
|
||
|
ptr++; // move to first depth value
|
||
|
if(*ptr <= depth)
|
||
|
{
|
||
|
depth = *ptr;
|
||
|
save = 1;
|
||
|
}
|
||
|
ptr++; // move to next depth value
|
||
|
if(*ptr <= depth)
|
||
|
{
|
||
|
depth = *ptr;
|
||
|
save = 1;
|
||
|
}
|
||
|
// move to first name picked
|
||
|
ptr++;
|
||
|
if(save)
|
||
|
{
|
||
|
this->PickInfo->PickedId = *ptr;
|
||
|
}
|
||
|
// skip additonal names
|
||
|
ptr += num_names;
|
||
|
}
|
||
|
// If there was a pick, then get the Z value
|
||
|
if(this->PickInfo->PickedId)
|
||
|
{
|
||
|
// convert from pick depth described as:
|
||
|
// Returned depth values are mapped such that the largest unsigned
|
||
|
// integer value corresponds to window coordinate depth 1.0,
|
||
|
// and zero corresponds to window coordinate depth 0.0.
|
||
|
|
||
|
this->PickedZ = ((double)depth / (double)VTK_UNSIGNED_INT_MAX);
|
||
|
|
||
|
// Clamp to range [0,1]
|
||
|
this->PickedZ = (this->PickedZ < 0.0) ? 0.0 : this->PickedZ;
|
||
|
this->PickedZ = (this->PickedZ > 1.0) ? 1.0: this->PickedZ;
|
||
|
}
|
||
|
delete [] this->PickInfo->PickBuffer;
|
||
|
this->PickInfo->PickBuffer = 0;
|
||
|
this->RenderWindow->IsPickingOff();
|
||
|
}
|
||
|
|
||
|
double vtkOpenGLRenderer::GetPickedZ()
|
||
|
{
|
||
|
return this->PickedZ;
|
||
|
}
|
||
|
|
||
|
unsigned int vtkOpenGLRenderer::GetPickedId()
|
||
|
{
|
||
|
return (unsigned int)this->PickInfo->PickedId;
|
||
|
}
|
||
|
|
||
|
vtkOpenGLRenderer::~vtkOpenGLRenderer()
|
||
|
{
|
||
|
if (this->PickInfo->PickBuffer)
|
||
|
{
|
||
|
delete [] this->PickInfo->PickBuffer;
|
||
|
this->PickInfo->PickBuffer = 0;
|
||
|
}
|
||
|
delete this->PickInfo;
|
||
|
}
|
||
|
|