From 19475e1fbdb1a82a620a6957e1080e4e6ac4f718 Mon Sep 17 00:00:00 2001 From: ouv Date: Tue, 30 Aug 2005 10:00:41 +0000 Subject: [PATCH] Initially added --- src/PIPELINE/VISU_OpenGLPointSpriteMapper.cxx | 1157 +++++++++++++++++ src/PIPELINE/VISU_OpenGLPointSpriteMapper.hxx | 230 ++++ 2 files changed, 1387 insertions(+) create mode 100755 src/PIPELINE/VISU_OpenGLPointSpriteMapper.cxx create mode 100755 src/PIPELINE/VISU_OpenGLPointSpriteMapper.hxx diff --git a/src/PIPELINE/VISU_OpenGLPointSpriteMapper.cxx b/src/PIPELINE/VISU_OpenGLPointSpriteMapper.cxx new file mode 100755 index 00000000..b6938437 --- /dev/null +++ b/src/PIPELINE/VISU_OpenGLPointSpriteMapper.cxx @@ -0,0 +1,1157 @@ +// VISU OBJECT : interactive object for VISU entities implementation +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File: VISU_OpenGLPointSpriteMapper.cxx +// Author: +// Module : VISU + +//#include "GL/glew.h" +#include "VISU_OpenGLPointSpriteMapper.hxx" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCommand.h" +#include "vtkDataArray.h" +#include "vtkFloatArray.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderer.h" +#include "vtkPlane.h" +#include "vtkPlaneCollection.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkProperty.h" +#include "vtkTimerLog.h" +#include "vtkTriangle.h" +#include "vtkOpenGLRenderWindow.h" +#include "vtkOpenGLTexture.h" +#include "vtkBMPReader.h" +#include "vtkXMLImageDataReader.h" + +#include "vtkImageData.h" + +#include "GL/glext.h" + +#include + + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(VISU_OpenGLPointSpriteMapper, "$Revision$"); +vtkStandardNewMacro(VISU_OpenGLPointSpriteMapper); +#endif + +// some definitions for what the polydata has in it +#define VTK_PDPSM_COLORS 0x0001 +#define VTK_PDPSM_CELL_COLORS 0x0002 +#define VTK_PDPSM_POINT_TYPE_FLOAT 0x0004 +#define VTK_PDPSM_POINT_TYPE_DOUBLE 0x0008 +#define VTK_PDPSM_NORMAL_TYPE_FLOAT 0x0010 +#define VTK_PDPSM_NORMAL_TYPE_DOUBLE 0x0020 +#define VTK_PDPSM_OPAQUE_COLORS 0x0040 +#define VTK_PDPSM_ALPHA_ARRAY 0x0080 +//----------------------------------------------------------------------------- +vtkCxxSetObjectMacro(VISU_OpenGLPointSpriteMapper, ParticleImage, vtkImageData); +//----------------------------------------------------------------------------- +// Construct empty object. +VISU_OpenGLPointSpriteMapper::VISU_OpenGLPointSpriteMapper() +{ + this->ListId = 0; + this->TotalCells = 0; + this->ExtensionsInitialized = 0; + this->ExtensionsOK = 0; + this->ParticleImage = NULL; + this->ParticleImageFileName = NULL; + this->AlphaChannelArray = NULL; + this->SizeChannelArray = NULL; + this->ParticleTexture = NULL; + this->bmpReader = NULL; + this->gaussian = vtkImageData::New(); + if (!this->bmpReader) + { + this->bmpReader = vtkBMPReader::New(); + } + this->DefaultPointSize = 25.0;//-1.0; + this->MaximumSupportedSize = 0.0; + this->QuadraticPointDistanceAttenuation[0] = 1.0; + this->QuadraticPointDistanceAttenuation[1] = 0.0; + this->QuadraticPointDistanceAttenuation[2] = 0.0; + // + this->NVidiaMode = 0; + this->Texture3D = 0; + this->TextureDimension = 2; + // + this->RenderMode = VISU_OpenGLPointSpriteMapper::Accumulate; + + this->XMLImageDataReader = vtkXMLImageDataReader::New(); + TextureIntensity = 0; + TextureAlphaChannel = 0; +} +//----------------------------------------------------------------------------- +// Destructor (don't call ReleaseGraphicsResources() since it is virtual +VISU_OpenGLPointSpriteMapper::~VISU_OpenGLPointSpriteMapper() +{ + if (this->LastWindow) + { + this->ReleaseGraphicsResources(this->LastWindow); + } + if (this->ParticleImageFileName) + { + delete [] this->ParticleImageFileName; + this->ParticleImageFileName = NULL; + } + if (this->AlphaChannelArray) + { + delete [] this->AlphaChannelArray; + this->AlphaChannelArray = NULL; + } + if (this->SizeChannelArray) + { + delete [] this->SizeChannelArray; + this->SizeChannelArray = NULL; + } + if (this->bmpReader) + { + this->bmpReader->Delete(); + this->bmpReader = NULL; + } + if (this->ParticleImage) + { + this->ParticleImage->Delete(); + this->ParticleImage = 0; + } + if (this->ParticleTexture) + { // Resources released previously. + this->ParticleTexture->Delete(); + this->ParticleTexture = 0; + } + if (this->gaussian) + { + this->gaussian->Delete(); + this->gaussian = 0; + } + if (this->XMLImageDataReader) + { + this->XMLImageDataReader->Delete(); + this->XMLImageDataReader = NULL; + } +} +//----------------------------------------------------------------------------- +void VISU_OpenGLPointSpriteMapper::InitializeExtensions() +{ + /* + // + // Glew initialization + // + GLenum err = glewInit(); + if (GLEW_OK != err) + { + std::cout << "glew Initialization Error: " << glewGetErrorString(err) << std::endl; + return; + } + // + // GL_ARB_point_sprite + // + if (glewIsSupported("GL_ARB_point_sprite") && GLEW_ARB_point_sprite && + glewIsSupported("GL_ARB_point_parameters") && GLEW_ARB_point_parameters) + { + this->ExtensionsOK = 1; + std::cout << "GL_ARB_point_sprite OK" << std::endl; + } + // + // GL_NV_point_sprite + // + this->NVidiaMode = 0; + if (glewIsSupported("GL_NV_point_sprite") && GLEW_NV_point_sprite && + glewIsSupported("GL_EXT_point_parameters") && GLEW_EXT_point_parameters) + { + this->NVidiaMode = 1; + this->ExtensionsOK = 1; + std::cout << "GL_NV_point_sprite OK" << std::endl; + } + */ + + this->ExtensionsOK = 1; + //std::cout << "GL_ARB_point_sprite OK" << std::endl; + + // + // if we didn't find either point sprite mode, then exit + // + if (!this->ExtensionsOK) + { + //std::cout << "GL_ARB_point_sprite or GL_NV_point_sprite not found" << std::endl; + vtkErrorMacro( << "GL_ARB_point_sprite or GL_NV_point_sprite not found" ); + return; + } + + /* + // + // glTexImage3D + // + if (glTexImage3D) + { + this->Texture3D = 1; + } + else + { + vtkDebugMacro( << "VISU_OpenGLPointSpriteMapper::glTexImage3D not found" ); + this->Texture3D = 0; + } + */ + // + if (this->ExtensionsOK) this->ExtensionsInitialized = 1; +} +//----------------------------------------------------------------------------- +// Release the graphics resources used by this mapper. In this case, release +// the display list if any. +void VISU_OpenGLPointSpriteMapper::ReleaseGraphicsResources(vtkWindow *win) +{ + if (this->ListId && win) + { + win->MakeCurrent(); + glDeleteLists(this->ListId,1); + this->ListId = 0; + } + this->LastWindow = NULL; + // We actually only want to release our texture when the texture needs reloading, or when + // we are supposed to free up resources + if (this->ParticleTexture) + { + this->ParticleTexture->ReleaseGraphicsResources(win); + } +} +//----------------------------------------------------------------------------- +// +// Receives from Actor -> maps data to primitives +// +void VISU_OpenGLPointSpriteMapper::RenderPiece(vtkRenderer *ren, vtkActor *act) +{ + vtkIdType numPts; + vtkPolyData *input= this->GetInput(); + vtkPlaneCollection *clipPlanes; + vtkPlane *plane; + int i, numClipPlanes; + double planeEquation[4]; + + // + // make sure that we've been properly initialized + // + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + return; + } + + if ( input == NULL ) + { + vtkErrorMacro(<< "No input!"); + return; + } + else + { + this->InvokeEvent(vtkCommand::StartEvent,NULL); + input->Update(); + this->InvokeEvent(vtkCommand::EndEvent,NULL); + + numPts = input->GetNumberOfPoints(); + } + + if (numPts == 0) + { + vtkDebugMacro(<< "No points!"); + return; + } + + if ( this->LookupTable == NULL ) + { + this->CreateDefaultLookupTable(); + } + + // make sure our window is current + ren->GetRenderWindow()->MakeCurrent(); + + // Make sure open GL extensions are initialized + if (!this->ExtensionsInitialized) + { + this->InitializeExtensions(); + } + if (!this->ExtensionsOK) + { + return; + } + + vtkImageData *particlesource = NULL; + if (this->ParticleImageFileName && !this->ParticleImage) + { + // ensure Particle texture pipeline is up to date. + this->bmpReader->SetFileName(this->ParticleImageFileName); + particlesource = this->bmpReader->GetOutput(); + } + else + { + particlesource = this->ParticleImage; + } + + particlesource->Update(); + + if (particlesource->GetMTime()>this->ParticleBuildTime || this->GetMTime()>this->ParticleBuildTime) + { + gaussian->CopyStructure(particlesource); + // + int t = particlesource->GetPointData()->GetScalars()->GetDataType(); + int c = particlesource->GetPointData()->GetScalars()->GetNumberOfComponents(); + int N = particlesource->GetPointData()->GetScalars()->GetNumberOfTuples(); + // + vtkUnsignedCharArray *rgba = vtkUnsignedCharArray::New(); + rgba->SetNumberOfComponents(4); + rgba->SetNumberOfTuples(N); + gaussian->GetPointData()->SetScalars( rgba ); + rgba->Delete(); + unsigned char *newdata = (unsigned char *)(rgba->WritePointer(0,N)); + // + switch (t) + { + case VTK_UNSIGNED_CHAR: + case VTK_SHORT: + { + unsigned char *bmpdata = (unsigned char *)(particlesource->GetPointData()->GetScalars()->GetVoidPointer(0)); + for (int i=0; i255) temp = 255; + newdata[i*4 + 3] = static_cast(std::floor(std::sqrt(temp*temp)+0.5)); + int val = newdata[i*4 + 3]; + } + break; + } + // + case VTK_DOUBLE: + case 10: + { + double *bmpdata = (double *)(particlesource->GetPointData()->GetScalars()->GetVoidPointer(0)); + for (int i=0; i(bmpdata[i]); + newdata[i*4 + 1] = static_cast(bmpdata[i]); + newdata[i*4 + 2] = static_cast(bmpdata[i]); + double temp = bmpdata[i]; + if (temp>255) temp = 255; + newdata[i*4 + 3] = static_cast(std::floor(std::sqrt(temp*temp)+0.5)); + int val = newdata[i*4 + 3]; + } + break; + } + // + default: + { + vtkErrorMacro(<<"Can't handle this data type yet"); + return; + } + } + ParticleBuildTime.Modified(); + } + + // + if (this->ParticleTexture == 0) + { + this->ParticleTexture = vtkOpenGLTexture::New(); + this->ParticleTexture->RepeatOff(); + } + + this->ParticleTexture->SetInput(gaussian); + this->ParticleTexture->SetLookupTable(this->bmpReader->GetLookupTable()); + +// this->ParticleTexture->DebugOn(); +// this->ParticleTexture->Update(); + + // setup clippingplanes + clipPlanes = this->ClippingPlanes; + if (clipPlanes == NULL) + { + numClipPlanes = 0; + } + else + { + numClipPlanes = clipPlanes->GetNumberOfItems(); + if (numClipPlanes > 6) + { + vtkErrorMacro(<< "OpenGL guarantees at most 6 additional clipping planes"); + } + } + + for (i = 0; i < numClipPlanes; i++) + { + glEnable((GLenum)(GL_CLIP_PLANE0+i)); + } + + if ( clipPlanes ) + { + vtkMatrix4x4 *actorMatrix = vtkMatrix4x4::New(); + act->GetMatrix( actorMatrix ); + actorMatrix->Invert(); + + float origin[4], normal[3], point[4]; + + for (i = 0; i < numClipPlanes; i++) + { + plane = (vtkPlane *)clipPlanes->GetItemAsObject(i); + + plane->GetOrigin(origin); + plane->GetNormal(normal); + + point[0] = origin[0] + normal[0]; + point[1] = origin[1] + normal[1]; + point[2] = origin[2] + normal[2]; + + origin[3] = point[3] = 1.0; + + actorMatrix->MultiplyPoint( origin, origin ); + actorMatrix->MultiplyPoint( point, point ); + + if ( origin[3] != 1.0 ) + { + origin[0] /= origin[3]; + origin[1] /= origin[3]; + origin[2] /= origin[3]; + } + + if ( point[3] != 1.0 ) + { + point[0] /= point[3]; + point[1] /= point[3]; + point[2] /= point[3]; + } + + normal[0] = point[0] - origin[0]; + normal[1] = point[1] - origin[1]; + normal[2] = point[2] - origin[2]; + + planeEquation[0] = normal[0]; + planeEquation[1] = normal[1]; + planeEquation[2] = normal[2]; + planeEquation[3] = -(planeEquation[0]*origin[0]+ + planeEquation[1]*origin[1]+ + planeEquation[2]*origin[2]); + glClipPlane((GLenum)(GL_CLIP_PLANE0+i),planeEquation); + } + + actorMatrix->Delete(); + } + + // For vertex coloring, this sets this->Colors as side effect. + // Color arrays are cached. If nothing has changed, + // then the scalars do not have to be regenerted. + this->actorOpacity = act->GetProperty()->GetOpacity(); + this->MapScalars(this->actorOpacity); + + // + // if something has changed regenerate colors and display lists + // if required + // + int noAbort=1; + if ( this->GetMTime() > this->BuildTime || + input->GetMTime() > this->BuildTime || + act->GetProperty()->GetMTime() > this->BuildTime || + ren->GetRenderWindow() != this->LastWindow) + { + if (!this->ImmediateModeRendering && + !this->GetGlobalImmediateModeRendering()) + { + this->ReleaseGraphicsResources(ren->GetRenderWindow()); + this->LastWindow = ren->GetRenderWindow(); + + // Load the texture for the particle into gl + this->ParticleTexture->Load(ren); + + // get a unique display list id + this->ListId = glGenLists(1); + glNewList(this->ListId,GL_COMPILE); + + noAbort = this->Draw(ren,act); + glEndList(); + + // Time the actual drawing + this->Timer->StartTimer(); + glCallList(this->ListId); + this->Timer->StopTimer(); + } + else + { + this->ReleaseGraphicsResources(ren->GetRenderWindow()); + this->LastWindow = ren->GetRenderWindow(); + } + if (noAbort) + { + this->BuildTime.Modified(); + } + } + // if nothing changed but we are using display lists, draw it + else + { + if (!this->ImmediateModeRendering && + !this->GetGlobalImmediateModeRendering()) + { + // Load the texture for the particle into gl + this->ParticleTexture->Load(ren); + + // Time the actual drawing + this->Timer->StartTimer(); + glCallList(this->ListId); + this->Timer->StopTimer(); + } + } + + // if we are in immediate mode rendering we always + // want to draw the primitives here + if (this->ImmediateModeRendering || + this->GetGlobalImmediateModeRendering()) + { + // Load the texture for the particle into gl + this->ParticleTexture->Load(ren); + + // Time the actual drawing + this->Timer->StartTimer(); + this->Draw(ren,act); + this->Timer->StopTimer(); + } + + this->TimeToDraw = (float)this->Timer->GetElapsedTime(); + + // If the timer is not accurate enough, set it to a small + // time so that it is not zero + if ( this->TimeToDraw == 0.0 ) + { + this->TimeToDraw = 0.0001; + } + + for (i = 0; i < numClipPlanes; i++) + { + glDisable((GLenum)(GL_CLIP_PLANE0+i)); + } +} +//----------------------------------------------------------------------------- +#define vtkDrawPointsMacro(ptype,glVertFuncs,glInitFuncs) \ +{ \ + vtkIdType nPts; unsigned short count = 0; \ + ptype *points = (ptype *)voidPoints; \ + glInitFuncs \ + glBegin(GL_POINTS); \ + while (ptIds < endPtIds) \ + { \ + nPts = *ptIds; \ + ++ptIds; \ + while (nPts > 0) \ + { \ + glVertFuncs \ + ++ptIds; \ + --nPts; \ + } \ + if (++count == 10000) \ + { \ + cellNum += 10000; \ + count = 0; \ + this->UpdateProgress((double)cellNum/this->TotalCells); \ + if (ren->GetRenderWindow()->CheckAbortStatus()) \ + { \ + noAbort = 0; \ + break; \ + } \ + } \ + } \ + cellNum += count; \ + glEnd(); \ +} +//----------------------------------------------------------------------------- +// Configure vertex array: +/* + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glTexCoordPointer(1, GL_FLOAT, SizeOf(TPointSprite), @points[0].S); + glVertexPointer(3, GL_FLOAT, SizeOf(TPointSprite), @points[0].X); +*/ + +// Configure 3D texture +/* + glEnable(GL_TEXTURE_3D); + glGenTextures(1, @tex); + glBindTexture(GL_TEXTURE_3D, tex); + SetLength(buf, 64*64*3*4); + for i := 0 to 3 do + begin + AssignFile(f, Format('frame%d.tga', [i+1])); + Reset(f, 1); + Seek(f, 17); + BlockRead(f, buf[64*64*3*i], 64*64*3); + CloseFile(f); + end; + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, 64, 64, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, buf); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); +*/ +//----------------------------------------------------------------------------- +void VISU_OpenGLPointSpriteMapper::cleanupSprites() +{ + // + // Set GL params back to normal to stop other vtkMappers diusplaying wrongly + // + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable( GL_BLEND ); + + if (this->NVidiaMode) + { + glDisable( GL_POINT_SPRITE_ARB ); + } + else + { + glDisable( GL_POINT_SPRITE_NV ); + } + + glEnable( GL_DEPTH_TEST ); +} +//----------------------------------------------------------------------------- +int FindPowerOfTwo(int i) +{ + int size; + + for ( i--, size=1; i > 0; size*=2 ) + { + i /= 2; + } + + // [these lines added by Tim Hutton (implementing Joris Vanden Wyngaerd's suggestions)] + // limit the size of the texture to the maximum allowed by OpenGL + // (slightly more graceful than texture failing but not ideal) + GLint maxDimGL; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxDimGL); + if ( size > maxDimGL ) + { + size = maxDimGL ; + } + // end of Tim's additions + + return size; +} +//----------------------------------------------------------------------------- +// Creates resampled unsigned char texture map that is a power of two in bith x and y. +unsigned char* ResampleToPowerOfTwo(int &xs, int &ys, unsigned char *dptr, int bpp) +{ + unsigned char *tptr, *p, *p1, *p2, *p3, *p4; + int xsize, ysize, i, j, k, jOffset, iIdx, jIdx; + float pcoords[3], hx, hy, rm, sm, w0, w1, w2, w3; + + xsize = FindPowerOfTwo(xs); + ysize = FindPowerOfTwo(ys); + + hx = (float)(xs - 1.0) / (xsize - 1.0); + hy = (float)(ys - 1.0) / (ysize - 1.0); + + tptr = p = new unsigned char[xsize*ysize*bpp]; + + //Resample from the previous image. Compute parametric coordinates and interpolate + for (j=0; j < ysize; j++) + { + pcoords[1] = j*hy; + + jIdx = (int)pcoords[1]; + if ( jIdx >= (ys-1) ) //make sure to interpolate correctly at edge + { + jIdx = ys - 2; + pcoords[1] = 1.0; + } + else + { + pcoords[1] = pcoords[1] - jIdx; + } + jOffset = jIdx*xs; + sm = 1.0 - pcoords[1]; + + for (i=0; i < xsize; i++) + { + pcoords[0] = i*hx; + iIdx = (int)pcoords[0]; + if ( iIdx >= (xs-1) ) + { + iIdx = xs - 2; + pcoords[0] = 1.0; + } + else + { + pcoords[0] = pcoords[0] - iIdx; + } + rm = 1.0 - pcoords[0]; + + // Get pointers to 4 surrounding pixels + p1 = dptr + bpp*(iIdx + jOffset); + p2 = p1 + bpp; + p3 = p1 + bpp*xs; + p4 = p3 + bpp; + + // Compute interpolation weights interpolate components + w0 = rm*sm; + w1 = pcoords[0]*sm; + w2 = rm*pcoords[1]; + w3 = pcoords[0]*pcoords[1]; + for (k=0; k < bpp; k++) + { + *p++ = (unsigned char) (p1[k]*w0 + p2[k]*w1 + p3[k]*w2 + p4[k]*w3); + } + } + } + + xs = xsize; + ys = ysize; + + return tptr; +} +//----------------------------------------------------------------------------- +GLuint VISU_OpenGLPointSpriteMapper::LoadTexture( vtkImageData* imageData ) +{ + //this->XMLImageDataReader->SetFileName( fileName ); + //vtkImageData* imageData = this->XMLImageDataReader->GetOutput(); + //imageData->DebugOn(); + imageData->RequestExactExtentOn(); + imageData->UpdateInformation(); + imageData->SetUpdateExtentToWholeExtent(); + imageData->Update(); + //cout << "Dimension of image data : " << imageData->GetDataDimension() << endl; + + int* size = imageData->GetDimensions(); + vtkDataArray* scalars = imageData->GetPointData()->GetScalars(); + unsigned char* dataPtr = static_cast(scalars)->GetPointer(0); + + GLuint texture; + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, dataPtr ); + + return texture; +} +//----------------------------------------------------------------------------- +void VISU_OpenGLPointSpriteMapper::DrawTexture( GLuint texture, GLfloat x, GLfloat y, GLfloat z ) +{ + //cout << "DrawTexture : " << texture << endl; + glColor4f( 1.0, 1.0, 1.0, 1.0 ); + + glEnable( GL_POINT_SPRITE_ARB ); + glEnable( GL_TEXTURE_2D ); + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + //glAlphaFunc( GL_GREATER, 0.95F ); + //glEnable( GL_ALPHA_TEST ); + + glBindTexture( GL_TEXTURE_2D, texture ); + glBegin( GL_POINTS ); + + glVertex3f( x, y, z ); + + glEnd(); + glFlush(); + + //glDisable( GL_ALPHA_TEST ); + glDisable( GL_TEXTURE_2D ); +} +//----------------------------------------------------------------------------- +void VISU_OpenGLPointSpriteMapper::initSprites() +{ + switch (this->RenderMode) + { + case VISU_OpenGLPointSpriteMapper::Accumulate: + { + glDisable(GL_DEPTH_TEST); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE ); + break; + } + + case VISU_OpenGLPointSpriteMapper::Occlude: + { + glDepthFunc( GL_LEQUAL ); + glEnable( GL_DEPTH_TEST ); + glDisable( GL_BLEND ); + break; + } + + default: + { + break; + } + } + // Disable Lighting/Shading. + // This will fall back on the color set in the glColor4fv() + // call in vtkOpenGLProperty::Render() - the color returned + // by vtkProperty::GetColor() with alpha set to 1.0. + glDisable( GL_LIGHTING); + + // Disable material properties + glDisable( GL_COLOR_MATERIAL ); + + // + // Enable point smoothing. Not really needed + // + //glEnable(GL_POINT_SMOOTH); + + // + // Get the max point size : we need it to control Point Fading + // + float CurrentPointSize = 1.0; + if (this->MaximumSupportedSize==0.0) + { + glGetFloatv( GL_POINT_SIZE_MAX_ARB, &this->MaximumSupportedSize ); + } + if (this->DefaultPointSize==-1) + { + CurrentPointSize = this->MaximumSupportedSize; + } + else + { + CurrentPointSize = this->DefaultPointSize; + } + glPointSize( CurrentPointSize ); + + glEnable( GL_POINT_SPRITE_ARB ); + + /* + // + // Set up the OpenGL state machine for using point sprites... + // + if (this->NVidiaMode) + { + // + // NVidia Point Sprites initialization + // + glEnable(GL_POINT_SPRITE_NV); + + // + // Set Quadratic Attenuation parameters Use GL_EXT_point_parameters to control the sprite size. + // + glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, this->QuadraticPointDistanceAttenuation); + + // + // Set Point Fade Threshold size + // + // The alpha of a point is calculated to allow the fading of points + // instead of shrinking them past a defined threshold size. The threshold + // is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to + // the minimum and maximum point sizes. + glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0); + glPointParameterfEXT(GL_POINT_SIZE_MIN_EXT, 1.0); + glPointParameterfEXT(GL_POINT_SIZE_MAX_EXT, CurrentPointSize); + + if (this->Texture3D && this->TextureDimension==3) + { + // The texture is an animation that we load from a sequence of TGAs, and then + // pack into the slices of a volume texture. The R texture coordinate can be + // used to loop through the animation frames (with free tweening), but we + // can't specify it directly. + + // The following two lines will tell the GL to take the supplied S texture + // coordinate (see TPointSprite above), and copy it into R. _After_ this is + // done, it will generate the texture coordinates for the sprite itself. + + glTexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV, GL_TRUE); + glPointParameteriNV(GL_POINT_SPRITE_R_MODE_NV, GL_S); + } + else + { + // Enable texture coord replacement, but only 2D : no R coord + glTexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV, GL_TRUE); + glPointParameteriNV(GL_POINT_SPRITE_R_MODE_NV, GL_ZERO); + } + } + else + { + // + // GL ARB Point Sprites initialization + // + glEnable( GL_POINT_SPRITE_ARB ); + + // + // Set Quadratic Attenuation parameters + // + glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, this->QuadraticPointDistanceAttenuation ); + + // + // Set Point Fade Threshold size + // + // The alpha of a point is calculated to allow the fading of points + // instead of shrinking them past a defined threshold size. The threshold + // is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to + // the minimum and maximum point sizes. + glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0f ); + glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f ); + glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, CurrentPointSize ); + + // + // Specify point sprite texture coordinate replacement mode for each texture unit + // + glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE ); + } + */ +} +//----------------------------------------------------------------------------- +void VISU_OpenGLPointSpriteMapper::DrawPoints(int idx, + vtkPoints *p, + vtkUnsignedCharArray *colors, + vtkFloatArray *alpha, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *cells, + vtkRenderer *ren) +{ + void *voidPoints = p->GetVoidPointer(0); + unsigned char *rgba; + float *alphadata; + + if (cells->GetNumberOfCells() == 0) + { + return; + } + if (colors) + { + rgba = colors->GetPointer(0); + } + + vtkIdType *ptIds = cells->GetPointer(); + vtkIdType *endPtIds = ptIds + cells->GetNumberOfConnectivityEntries(); + + // draw all the elements, use fast path if available + switch (idx) + { + case VTK_PDPSM_POINT_TYPE_FLOAT: + //std::cout << "VTK_PDPSM_POINT_TYPE_FLOAT " << std::endl; + vtkDrawPointsMacro(float, glVertex3fv(points + 3**ptIds);, initSprites();); + break; + case VTK_PDPSM_POINT_TYPE_DOUBLE: + //std::cout << "VTK_PDPSM_POINT_TYPE_DOUBLE " << std::endl; + vtkDrawPointsMacro(double, glVertex3dv(points + 3**ptIds);, initSprites();); + break; + case VTK_PDPSM_POINT_TYPE_FLOAT | VTK_PDPSM_COLORS: + //std::cout << "VTK_PDPSM_POINT_TYPE_FLOAT | VTK_PDPSM_COLORS " << std::endl; + vtkDrawPointsMacro(float, + glColor4ubv(rgba + 4**ptIds); + glVertex3fv(points + 3**ptIds);, initSprites();); + + break; + case VTK_PDPSM_POINT_TYPE_DOUBLE | VTK_PDPSM_COLORS: + //std::cout << "VTK_PDPSM_POINT_TYPE_DOUBLE | VTK_PDPSM_COLORS " << std::endl; + vtkDrawPointsMacro(double, + glColor4ubv(rgba + 4**ptIds); + glVertex3dv(points + 3**ptIds);, initSprites();); + + break; + case VTK_PDPSM_POINT_TYPE_FLOAT | VTK_PDPSM_COLORS | VTK_PDPSM_OPAQUE_COLORS: + //std::cout << "VTK_PDPSM_POINT_TYPE_FLOAT | VTK_PDPSM_COLORS | VTK_PDPSM_OPAQUE_COLORS " << std::endl; + vtkDrawPointsMacro(float, + glColor3ubv(rgba + 4**ptIds); + glVertex3fv(points + 3**ptIds);, initSprites();); + break; + default: + { + //std::cout << "Default " << std::endl; + if (idx & VTK_PDPSM_ALPHA_ARRAY) + { + alphadata = alpha->GetPointer(0); + } + + initSprites(); + + vtkIdType *pts = 0; + vtkIdType npts = 0; + unsigned short count = 0; + glBegin(GL_POINTS); + for (cells->InitTraversal(); noAbort && cells->GetNextCell(npts,pts); count++) + { + if (colors) + { + if (idx & VTK_PDPSM_CELL_COLORS) + { + unsigned char *col = colors->GetPointer(cellNum << 2); + if (idx & VTK_PDPSM_ALPHA_ARRAY) + { + vtkErrorMacro(<<"Not yet fully implemented cell arrays for Point sprite mapper"); + } + glColor4ubv(col); + } + else + { + unsigned char *col = colors->GetPointer(pts[0]<< 2); + if (idx & VTK_PDPSM_ALPHA_ARRAY) + { + col[3] = (unsigned char)(this->actorOpacity*255.0*alphadata[pts[0]]+0.499999); + } + glColor4ubv(col); + } + } + + //cout << "POINT : "; + //cout << p->GetPoint(pts[0])[0] << " "; + //cout << p->GetPoint(pts[0])[1] << " "; + //cout << p->GetPoint(pts[0])[2] << endl; + + glVertex3fv(p->GetPoint(pts[0])); + + /* + vtkXMLImageDataReader* aReader = vtkXMLImageDataReader::New(); + aReader->SetFileName( "/dn06/salome/ouv/SALOME3/TextureIntensity.vti" ); + TextureIntensity = this->LoadTexture( aReader->GetOutput() ); + aReader->Delete(); + + aReader = vtkXMLImageDataReader::New(); + aReader->SetFileName( "/dn06/salome/ouv/SALOME3/TextureAlphaChannel.vti" ); + TextureAlphaChannel = this->LoadTexture( aReader->GetOutput() ); + aReader->Delete(); + */ + + /* + this->DrawTexture( TextureIntensity, + p->GetPoint(pts[0])[0], + p->GetPoint(pts[0])[1], + p->GetPoint(pts[0])[2] ); + + this->DrawTexture( TextureAlphaChannel, + p->GetPoint(pts[0])[0], + p->GetPoint(pts[0])[1], + p->GetPoint(pts[0])[2] ); + */ + + + // check for abort condition + if (count == 10000) + { + count = 0; + // report progress + this->UpdateProgress((double)cellNum/this->TotalCells); + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + noAbort = 0; + } + } + ++cellNum; + } + glEnd(); + } + } + // + // restore Gl state to normal + // + cleanupSprites(); +} + +//----------------------------------------------------------------------------- +// Draw method for OpenGL. +int VISU_OpenGLPointSpriteMapper::Draw(vtkRenderer *aren, vtkActor *act) +{ + vtkOpenGLRenderer *ren = (vtkOpenGLRenderer *)aren; + vtkUnsignedCharArray *colors = NULL; + vtkFloatArray *alpha = NULL; + vtkPolyData *input = this->GetInput(); + vtkPoints *points; + int tDim; + int noAbort = 1; + int cellScalars = 0; + vtkIdType cellNum = 0; + float tran; + + // get the transparency + tran = act->GetProperty()->GetOpacity(); + + // if the primitives are invisable then get out of here + if (tran <= 0.0) + { + return noAbort; + } + + // and draw the display list + points = input->GetPoints(); + + // are they cell or point scalars + if ( this->Colors ) + { + colors = this->Colors; + if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA || + this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA || + !input->GetPointData()->GetScalars() ) + && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA) + { + cellScalars = 1; + } + } + + unsigned long idx = 0; + if (colors) + { + idx |= VTK_PDPSM_COLORS; + if (colors->GetName()) + { + // In the future, I will look at the number of components. + // All paths will have to handle 3 component colors. + idx |= VTK_PDPSM_OPAQUE_COLORS; + } + } + if (cellScalars) + { + idx |= VTK_PDPSM_CELL_COLORS; + } + + // store the types in the index + if (points->GetDataType() == VTK_FLOAT) + { + idx |= VTK_PDPSM_POINT_TYPE_FLOAT; + } + else if (points->GetDataType() == VTK_DOUBLE) + { + idx |= VTK_PDPSM_POINT_TYPE_DOUBLE; + } + + if (this->AlphaChannelArray && (alpha = vtkFloatArray::SafeDownCast(input->GetPointData()->GetArray(this->AlphaChannelArray))) + ) + { + idx |= VTK_PDPSM_ALPHA_ARRAY; + } + + // we need to know the total number of cells so that we can report progress + this->TotalCells = input->GetVerts()->GetNumberOfCells(); + + this->DrawPoints(idx, points, colors, alpha, cellNum, noAbort, input->GetVerts(), ren); + + this->UpdateProgress(1.0); + return noAbort; +} +//----------------------------------------------------------------------------- +void VISU_OpenGLPointSpriteMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} +//----------------------------------------------------------------------------- + + + + diff --git a/src/PIPELINE/VISU_OpenGLPointSpriteMapper.hxx b/src/PIPELINE/VISU_OpenGLPointSpriteMapper.hxx new file mode 100755 index 00000000..446b7dc9 --- /dev/null +++ b/src/PIPELINE/VISU_OpenGLPointSpriteMapper.hxx @@ -0,0 +1,230 @@ +// VISU OBJECT : interactive object for VISU entities implementation +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// +// +// +// File: VISU_OpenGLPointSpriteMapper.hxx +// Author: +// Module : VISU + +#ifndef VISU_OpenGLPointSpriteMapper_HeaderFile +#define VISU_OpenGLPointSpriteMapper_HeaderFile + +#include "vtkPolyDataMapper.h" +#include "vtkConfigure.h" + +#if defined(_MSC_VER) && defined(vtkCSCSBase_SHARED) +# pragma warning ( disable : 4275 ) +#endif + +#if defined(WIN32) +# if defined(vtkCSCSBase_EXPORTS) +# define VTK_vtkCSCSBase_EXPORT __declspec( dllexport ) +# else +# define VTK_vtkCSCSBase_EXPORT __declspec( dllimport ) +# endif +#else +# define VTK_vtkCSCSBase_EXPORT +#endif + +#if defined(__APPLE__) && (defined(VTK_USE_CARBON) || defined(VTK_USE_COCOA)) +# include // Include OpenGL API. +#else +//# include "vtkWindows.h" // Needed to include OpenGL header on Windows. +# include // Include OpenGL API. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 + +#define GL_ARB_point_parameters 1 +GLAPI void APIENTRY glPointParameterfARB (GLenum, GLfloat); +GLAPI void APIENTRY glPointParameterfvARB (GLenum, const GLfloat *); +GLAPI void APIENTRY glPointParameterfEXT (GLenum, GLfloat); +GLAPI void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *); +GLAPI void APIENTRY glPointParameteriNV (GLenum, GLint); + +#ifdef __cplusplus +} +#endif + +class vtkCellArray; +class vtkPoints; +class vtkProperty; +class vtkRenderWindow; +class vtkOpenGLRenderer; +class vtkOpenGLTexture; +class vtkBMPReader; +class vtkImageData; +class vtkFloatArray; +class vtkXMLImageDataReader; + +class VTK_vtkCSCSBase_EXPORT VISU_OpenGLPointSpriteMapper : public vtkPolyDataMapper +{ +public: +//BTX + enum RenderModes { + Accumulate=0, + Occlude + }; +//ETX + static VISU_OpenGLPointSpriteMapper *New(); + vtkTypeRevisionMacro(VISU_OpenGLPointSpriteMapper,vtkPolyDataMapper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of particle bitmap + vtkSetStringMacro(ParticleImageFileName); + vtkGetStringMacro(ParticleImageFileName); + + // Description: + // Specify image object for particle bitmap + vtkGetObjectMacro(ParticleImage, vtkImageData); + virtual void SetParticleImage(vtkImageData *); + + // Description: + // Specify the name of a scalar array which will be used to control + // the alpha value of each point. The values should be between 0,1 + vtkSetStringMacro(AlphaChannelArray); + vtkGetStringMacro(AlphaChannelArray); + + // Description: + // Specify the name of a scalar array which will be used to control + // the size of each point. + // NOT YET IMPLEMENTED + vtkSetStringMacro(SizeChannelArray); + vtkGetStringMacro(SizeChannelArray); + + // Description: + // Set the initial point size to be used. This value forms the + // base upon which the distance attenuation acts. + // Usually the pointsize is set to the maximum supported by the graphics + // card for sprite display, then the quadratic factors are adjusted to + // bring the size down. + // Set the default size to -1 if you wish the value returned by + // glGetFloatv( GL_POINT_SIZE_MAX_ARB, &MaximimSupportedSize ); + // to be used as the initial default point size. + vtkSetMacro(DefaultPointSize, float); + vtkGetMacro(DefaultPointSize, float); + + // Description: + // Set the 3 values (a,b,c) of the parametric function which controls the + // reduction in point size with increasing distance (d). + // e.g. (1,0,0) will give all points the same size regardless of distance. + // @verbatim + // point fading = _____1_______ + // (a + bd + cd^2) + // @endverbatim + vtkSetVector3Macro(QuadraticPointDistanceAttenuation, float); + vtkGetVector3Macro(QuadraticPointDistanceAttenuation, float); + + // Description: + // Return the maximum point size supported by the graphics hardware. + // If OpenGl has not yet been initialized, then this call will + // return a value of 0, otherwise it will return the value + // from glGetFloatv( GL_POINT_SIZE_MAX_ARB, &MaximimSupportedSize ); + vtkGetMacro(MaximumSupportedSize, float); + + // Description: + // Set/Get the RenderMode for this mapper. Currently 2 modes are supported + // Accumulate : Uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), and no depth testing + // so that points are accumulated. Suitable for Galaxy plots. + // Occlude : No blending. Particles are solid spheres and depth testing is + // used as usual. Suitable for most particle simulations without the need + // for opacity. + vtkSetMacro(RenderMode, int); + vtkGetMacro(RenderMode, int); + void SetRenderModeToAccumulate() { this->SetRenderMode(Accumulate); } + void SetRenderModeToOcclude() { this->SetRenderMode(Occlude); } + + // Description: + // Implement superclass render method. + virtual void RenderPiece(vtkRenderer *ren, vtkActor *a); + + // 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. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Draw method for OpenGL. + virtual int Draw(vtkRenderer *ren, vtkActor *a); + + GLuint LoadTexture( vtkImageData* ); + void DrawTexture( GLuint texture, GLfloat x, GLfloat y, GLfloat z ); + + vtkSetMacro(TextureIntensity, GLuint); + vtkSetMacro(TextureAlphaChannel, GLuint); + +protected: + VISU_OpenGLPointSpriteMapper(); + ~VISU_OpenGLPointSpriteMapper(); + + void DrawPoints(int idx, + vtkPoints *p, + vtkUnsignedCharArray *c, + vtkFloatArray *alpha, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *ca, + vtkRenderer *ren); + + void InitializeExtensions(); + void initSprites(); + void cleanupSprites(); + + vtkIdType TotalCells; + + int ListId; + int ExtensionsInitialized; + int ExtensionsOK; + vtkBMPReader *bmpReader; + vtkOpenGLTexture *ParticleTexture; + vtkImageData *ParticleImage; + char *ParticleImageFileName; + char *AlphaChannelArray; + double actorOpacity; + char *SizeChannelArray; + float DefaultPointSize; + float MaximumSupportedSize; + float QuadraticPointDistanceAttenuation[3]; + vtkTimeStamp ParticleBuildTime; + vtkImageData *gaussian; + int NVidiaMode; + int Texture3D; + int TextureDimension; + int RenderMode; + + vtkXMLImageDataReader* XMLImageDataReader; + GLuint TextureIntensity; + GLuint TextureAlphaChannel; + +private: + VISU_OpenGLPointSpriteMapper(const VISU_OpenGLPointSpriteMapper&); // Not implemented. + void operator=(const VISU_OpenGLPointSpriteMapper&); // Not implemented. +}; + +#endif -- 2.39.2