1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4 
5   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
6   All rights reserved.
7   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #include "vtkOpenGLCamera.h"
15 
16 #include "vtkMatrix4x4.h"
17 #include "vtkMatrix3x3.h"
18 #include "vtkObjectFactory.h"
19 #include "vtkRenderer.h"
20 #include "vtkOutputWindow.h"
21 #include "vtkOpenGLRenderWindow.h"
22 #include "vtkOpenGLError.h"
23 
24 #include <math.h>
25 
26 vtkStandardNewMacro(vtkOpenGLCamera);
27 
28 
vtkOpenGLCamera()29 vtkOpenGLCamera::vtkOpenGLCamera()
30 {
31   this->WCDCMatrix = vtkMatrix4x4::New();
32   this->WCVCMatrix = vtkMatrix4x4::New();
33   this->NormalMatrix = vtkMatrix3x3::New();
34   this->VCDCMatrix = vtkMatrix4x4::New();
35   this->LastRenderer = 0;
36 }
37 
~vtkOpenGLCamera()38 vtkOpenGLCamera::~vtkOpenGLCamera()
39 {
40   this->WCDCMatrix->Delete();
41   this->WCVCMatrix->Delete();
42   this->NormalMatrix->Delete();
43   this->VCDCMatrix->Delete();
44 }
45 
46 // Implement base class method.
Render(vtkRenderer * ren)47 void vtkOpenGLCamera::Render(vtkRenderer *ren)
48 {
49   vtkOpenGLClearErrorMacro();
50 
51   int lowerLeft[2];
52   int usize, vsize;
53 
54   vtkOpenGLRenderWindow *win = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
55 
56   // find out if we should stereo render
57   this->Stereo = (ren->GetRenderWindow())->GetStereoRender();
58   ren->GetTiledSizeAndOrigin(&usize, &vsize, lowerLeft, lowerLeft+1);
59 
60   // if were on a stereo renderer draw to special parts of screen
61   if (this->Stereo)
62     {
63     switch ((ren->GetRenderWindow())->GetStereoType())
64       {
65       case VTK_STEREO_CRYSTAL_EYES:
66         if (this->LeftEye)
67           {
68           if (ren->GetRenderWindow()->GetDoubleBuffer())
69             {
70             glDrawBuffer(static_cast<GLenum>(win->GetBackLeftBuffer()));
71             glReadBuffer(static_cast<GLenum>(win->GetBackLeftBuffer()));
72             }
73           else
74             {
75             glDrawBuffer(static_cast<GLenum>(win->GetFrontLeftBuffer()));
76             glReadBuffer(static_cast<GLenum>(win->GetFrontLeftBuffer()));
77             }
78           }
79         else
80           {
81            if (ren->GetRenderWindow()->GetDoubleBuffer())
82             {
83             glDrawBuffer(static_cast<GLenum>(win->GetBackRightBuffer()));
84             glReadBuffer(static_cast<GLenum>(win->GetBackRightBuffer()));
85             }
86           else
87             {
88             glDrawBuffer(static_cast<GLenum>(win->GetFrontRightBuffer()));
89             glReadBuffer(static_cast<GLenum>(win->GetFrontRightBuffer()));
90             }
91           }
92         break;
93       case VTK_STEREO_LEFT:
94         this->LeftEye = 1;
95         break;
96       case VTK_STEREO_RIGHT:
97         this->LeftEye = 0;
98         break;
99       default:
100         break;
101       }
102     }
103   else
104     {
105     if (ren->GetRenderWindow()->GetDoubleBuffer())
106       {
107       glDrawBuffer(static_cast<GLenum>(win->GetBackBuffer()));
108 
109       // Reading back buffer means back left. see OpenGL spec.
110       // because one can write to two buffers at a time but can only read from
111       // one buffer at a time.
112       glReadBuffer(static_cast<GLenum>(win->GetBackBuffer()));
113       }
114     else
115       {
116       glDrawBuffer(static_cast<GLenum>(win->GetFrontBuffer()));
117 
118       // Reading front buffer means front left. see OpenGL spec.
119       // because one can write to two buffers at a time but can only read from
120       // one buffer at a time.
121       glReadBuffer(static_cast<GLenum>(win->GetFrontBuffer()));
122       }
123     }
124 
125   glViewport(lowerLeft[0], lowerLeft[1], usize, vsize);
126   glEnable(GL_SCISSOR_TEST);
127   glScissor(lowerLeft[0], lowerLeft[1], usize, vsize);
128 
129   if ((ren->GetRenderWindow())->GetErase() && ren->GetErase()
130       && !ren->GetIsPicking())
131     {
132     ren->Clear();
133     }
134 
135   vtkOpenGLCheckErrorMacro("failed after Render");
136 }
137 
138 //----------------------------------------------------------------------------
UpdateViewport(vtkRenderer * ren)139 void vtkOpenGLCamera::UpdateViewport(vtkRenderer *ren)
140 {
141   vtkOpenGLClearErrorMacro();
142 
143   int lowerLeft[2];
144   int usize, vsize;
145   ren->GetTiledSizeAndOrigin(&usize, &vsize, lowerLeft, lowerLeft+1);
146 
147   glViewport(lowerLeft[0], lowerLeft[1], usize, vsize);
148   glEnable(GL_SCISSOR_TEST);
149   glScissor(lowerLeft[0], lowerLeft[1], usize, vsize);
150 
151   vtkOpenGLCheckErrorMacro("failed after UpdateViewport");
152 }
153 
154 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)155 void vtkOpenGLCamera::PrintSelf(ostream& os, vtkIndent indent)
156 {
157   this->Superclass::PrintSelf(os,indent);
158 }
159 
GetKeyMatrices(vtkRenderer * ren,vtkMatrix4x4 * & wcvc,vtkMatrix3x3 * & normMat,vtkMatrix4x4 * & vcdc,vtkMatrix4x4 * & wcdc)160 void vtkOpenGLCamera::GetKeyMatrices(vtkRenderer *ren, vtkMatrix4x4 *&wcvc,
161         vtkMatrix3x3 *&normMat, vtkMatrix4x4 *&vcdc, vtkMatrix4x4 *&wcdc)
162 {
163   // has the camera changed?
164   if (ren != this->LastRenderer ||
165       this->MTime > this->KeyMatrixTime ||
166       ren->GetMTime() > this->KeyMatrixTime)
167     {
168     this->WCVCMatrix->DeepCopy(this->GetModelViewTransformMatrix());
169 
170     for(int i = 0; i < 3; ++i)
171       {
172       for (int j = 0; j < 3; ++j)
173         {
174         this->NormalMatrix->SetElement(i, j, this->WCVCMatrix->GetElement(i, j));
175         }
176       }
177     this->NormalMatrix->Invert();
178 
179     this->WCVCMatrix->Transpose();
180 
181     double aspect[2];
182     int  lowerLeft[2];
183     int usize, vsize;
184     ren->GetTiledSizeAndOrigin(&usize, &vsize, lowerLeft, lowerLeft+1);
185 
186     ren->ComputeAspect();
187     ren->GetAspect(aspect);
188     double aspect2[2];
189     ren->vtkViewport::ComputeAspect();
190     ren->vtkViewport::GetAspect(aspect2);
191     double aspectModification = aspect[0] * aspect2[1] / (aspect[1] * aspect2[0]);
192 
193     if (usize && vsize)
194       {
195       this->VCDCMatrix->DeepCopy(this->GetProjectionTransformMatrix(
196                          aspectModification * usize / vsize, -1, 1));
197       this->VCDCMatrix->Transpose();
198       }
199 
200     vtkMatrix4x4::Multiply4x4(this->WCVCMatrix, this->VCDCMatrix, this->WCDCMatrix);
201 
202     this->KeyMatrixTime.Modified();
203     this->LastRenderer = ren;
204     }
205 
206   wcvc = this->WCVCMatrix;
207   normMat = this->NormalMatrix;
208   vcdc = this->VCDCMatrix;
209   wcdc = this->WCDCMatrix;
210 }