Salome HOME
Merge branch 'V7_dev'
[modules/gui.git] / src / VTKViewer / VTKViewer_OpenGLRenderer.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "VTKViewer_OpenGLRenderer.h"
24 #include "VTKViewer_Texture.h"
25
26 #include <vtkCuller.h>
27 #include <vtkLightCollection.h>
28 #include <vtkObjectFactory.h>
29 #include <vtkOpenGLCamera.h>
30 #include <vtkOpenGLLight.h>
31 #include <vtkOpenGLProperty.h>
32 #include <vtkRenderWindow.h>
33 #include <vtkOpenGLExtensionManager.h>
34 #include <vtkgl.h> // vtkgl namespace
35 #include <vtkImageImport.h>
36 #include <vtkPNGWriter.h>
37 #include <vtkOpenGLTexture.h>
38 #include <vtkTimerLog.h>
39 #include <vtkOpenGL.h>
40 #include <vtkObjectFactory.h>
41
42 vtkStandardNewMacro(VTKViewer_OpenGLRenderer);
43
44 VTKViewer_OpenGLRenderer::VTKViewer_OpenGLRenderer()
45 {
46   this->GradientType = HorizontalGradient;
47 }
48
49 VTKViewer_OpenGLRenderer::~VTKViewer_OpenGLRenderer()
50 {
51 }
52
53 void VTKViewer_OpenGLRenderer::SetGradientType( const int theGradientType )
54 {
55   this->GradientType = theGradientType;
56 }
57
58 void VTKViewer_OpenGLRenderer::Clear(void)
59 {
60   GLbitfield clear_mask = 0;
61
62   if( !this->Transparent() )
63   {
64     glClearColor( static_cast<GLclampf>(this->Background[0]),
65                   static_cast<GLclampf>(this->Background[1]),
66                   static_cast<GLclampf>(this->Background[2]),
67                   static_cast<GLclampf>(0.0));
68     clear_mask |= GL_COLOR_BUFFER_BIT;
69   }
70
71   if( !this->GetPreserveDepthBuffer() )
72   {
73     glClearDepth(static_cast<GLclampf>(1.0));
74     clear_mask |= GL_DEPTH_BUFFER_BIT;
75   }
76
77   vtkDebugMacro(<< "glClear\n");
78   glClear(clear_mask);
79
80   // If gradient background is turned on, draw it now.
81   if( !this->Transparent() &&
82       ( this->GradientBackground || this->TexturedBackground ) )
83   {
84     double aTileViewport[4];
85     this->GetRenderWindow()->GetTileViewport( aTileViewport );
86     glPushAttrib( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_TEXTURE_BIT );
87     glDisable( GL_ALPHA_TEST );
88     glDisable( GL_DEPTH_TEST );
89     glDisable( GL_LIGHTING );
90     glDisable( GL_TEXTURE_1D );
91     glDisable( GL_TEXTURE_2D );
92     glDisable( GL_BLEND );
93     glShadeModel( GL_SMOOTH ); // color interpolation
94
95     glMatrixMode( GL_PROJECTION );
96     glPushMatrix();
97     glLoadIdentity();
98     glMatrixMode( GL_MODELVIEW );
99     glPushMatrix();
100     glLoadIdentity();
101
102     glOrtho( aTileViewport[0], aTileViewport[2], aTileViewport[1], aTileViewport[3], -1.0, 1.0 );
103
104     if( this->GradientBackground )
105     {
106       double* corner1 = 0;
107       double* corner2 = 0;
108       double* corner3 = 0;
109       double* corner4 = 0;
110       double dcorner1[3];
111       double dcorner2[3];
112
113       switch( this->GradientType )
114       {
115         case HorizontalGradient:
116           corner1 = this->Background;
117           corner2 = this->Background2;
118           corner3 = this->Background2;
119           corner4 = this->Background;
120           break;
121         case VerticalGradient:
122           corner1 = this->Background2;
123           corner2 = this->Background2;
124           corner3 = this->Background;
125           corner4 = this->Background;
126           break;
127         case FirstDiagonalGradient:
128           corner2 = this->Background2;
129           corner4 = this->Background;
130           dcorner1[0] = dcorner2[0] = 0.5F * ( corner2[0] + corner4[0] );
131           dcorner1[1] = dcorner2[1] = 0.5F * ( corner2[1] + corner4[1] );
132           dcorner1[2] = dcorner2[2] = 0.5F * ( corner2[2] + corner4[2] );
133           corner1 = dcorner1;
134           corner3 = dcorner2;
135           break;
136         case SecondDiagonalGradient:
137           corner1 = this->Background2;  
138           corner3 = this->Background;
139           dcorner1[0] = dcorner2[0] = 0.5F * ( corner1[0] + corner3[0] );
140           dcorner1[1] = dcorner2[1] = 0.5F * ( corner1[1] + corner3[1] );
141           dcorner1[2] = dcorner2[2] = 0.5F * ( corner1[2] + corner3[2] );
142           corner2 = dcorner1;
143           corner4 = dcorner2;
144           break;
145         case FirstCornerGradient:
146           corner1 = this->Background2;
147           corner2 = this->Background2;
148           corner3 = this->Background2;
149           corner4 = this->Background;
150           break;
151         case SecondCornerGradient:
152           corner1 = this->Background2;
153           corner2 = this->Background2;
154           corner3 = this->Background;
155           corner4 = this->Background2;
156           break;
157         case ThirdCornerGradient:
158           corner1 = this->Background2;
159           corner2 = this->Background;
160           corner3 = this->Background2;
161           corner4 = this->Background2;
162           break;
163         case FourthCornerGradient:
164           corner1 = this->Background;
165           corner2 = this->Background2;
166           corner3 = this->Background2;
167           corner4 = this->Background2;
168           break;
169         default: // just in case
170           corner1 = this->Background;
171           corner2 = this->Background;
172           corner3 = this->Background;
173           corner4 = this->Background;
174           break;
175       }
176
177       glBegin( GL_TRIANGLE_FAN );
178       if( this->GradientType != FirstCornerGradient && this->GradientType != ThirdCornerGradient )
179       {
180         glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
181         glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
182         glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
183         glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
184       }
185       else //if( this->GradientType == FirstCornerGradient || this->GradientType == ThirdCornerGradient )
186       {
187         glColor3f( corner2[0], corner2[1], corner2[2] ); glVertex2f( 1.F, 0.F );
188         glColor3f( corner3[0], corner3[1], corner3[2] ); glVertex2f( 1.F, 1.F );
189         glColor3f( corner4[0], corner4[1], corner4[2] ); glVertex2f( 0.F, 1.F );
190         glColor3f( corner1[0], corner1[1], corner1[2] ); glVertex2f( 0.F, 0.F );
191       }
192       glEnd();
193     }
194
195     if( this->TexturedBackground && this->BackgroundTexture )
196     {
197       if( VTKViewer_Texture* aTexture = VTKViewer_Texture::SafeDownCast( this->BackgroundTexture ) )
198       {
199         glEnable( GL_TEXTURE_2D );
200
201         aTexture->Render( this );
202
203         // NOTE: By default the mode is GL_MODULATE. Since the user
204         // cannot set the mode, the default is set to replace.
205         glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
206         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
207         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
208
209         // NOTE: vtkTexture Render enables the alpha test
210         // so that no buffer is affected if alpha of incoming fragment is
211         // below the threshold. Here we have to enable it so that it won't
212         // rejects the fragments of the quad as the alpha is set to 0 on it.
213         glDisable( GL_ALPHA_TEST );
214
215         GLfloat texX = 1.F; // texture <s> coordinate
216         GLfloat texY = 1.F; // texture <t> coordinate
217         GLfloat x_offset = 0.5, y_offset = 0.5;
218         GLfloat coeff = 0.5;
219
220         // OCCT issue 0023102: Change the algorithm of rendering the
221         // 3d viewer background using tiled texture
222         // Setting this coefficient to -1.F allows to tile textures relatively
223         // to the top-left corner of the view (value 1.F corresponds to the
224         // initial behaviour - tiling from the bottom-left corner)
225         GLfloat aCoef = -1.F;
226
227         int aPosition = aTexture->GetPosition();
228         int aWidth = aTexture->GetWidth();
229         int aHeight = aTexture->GetHeight();
230         int aViewWidth = this->RenderWindow->GetSize()[0];
231         int aViewHeight = this->RenderWindow->GetSize()[1];                    
232         if( aPosition == VTKViewer_Texture::Centered )
233         {
234           x_offset = ( (GLfloat)aWidth / (GLfloat)aViewWidth ) / 2.;
235           y_offset = ( (GLfloat)aHeight / (GLfloat)aViewHeight ) / 2.;
236         }
237         else if( aPosition == VTKViewer_Texture::Tiled )
238         {
239           texX = (GLfloat)aViewWidth / (GLfloat)aWidth;
240           texY = (GLfloat)aViewHeight / (GLfloat)aHeight;
241         }
242
243         // Note that texture is mapped using GL_REPEAT wrapping mode so integer part
244         // is simply ignored, and negative multiplier is here for convenience only
245         // and does not result e.g. in texture mirroring
246         glBegin( GL_QUADS );
247         glTexCoord2f(  0.F,          0.F ); glVertex2f( -x_offset + coeff, -aCoef * y_offset + coeff );
248         glTexCoord2f( texX,          0.F ); glVertex2f(  x_offset + coeff, -aCoef * y_offset + coeff );
249         glTexCoord2f( texX, aCoef * texY ); glVertex2f(  x_offset + coeff,  aCoef * y_offset + coeff );
250         glTexCoord2f(  0.F, aCoef * texY ); glVertex2f( -x_offset + coeff,  aCoef * y_offset + coeff );
251         glEnd();
252       }
253     }
254
255     glPopMatrix();
256     glMatrixMode( GL_PROJECTION );
257     glPopMatrix();
258     glMatrixMode( GL_MODELVIEW );
259
260     glPopAttrib();
261   }
262 }