0024381: Visualization, TKOpenGl - revise matrices stack and usage of temporary matrices
[occt.git] / src / OpenGl / OpenGl_View_2.cxx
index 91164cc..4cced5d 100644 (file)
@@ -69,9 +69,10 @@ struct OPENGL_CLIP_PLANE
 /*
 *  Set des lumieres
 */
-static void bind_light (const OpenGl_Light& theLight,
-                        GLenum&             theLightGlId,
-                        Graphic3d_Vec4&     theAmbientColor)
+static void bindLight (const OpenGl_Light&             theLight,
+                       GLenum&                         theLightGlId,
+                       Graphic3d_Vec4&                 theAmbientColor,
+                       const Handle(OpenGl_Workspace)& theWorkspace)
 {
   // Only 8 lights in OpenGL...
   if (theLightGlId > GL_LIGHT7)
@@ -86,14 +87,16 @@ static void bind_light (const OpenGl_Light& theLight,
     return;
   }
 
+  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+
   // the light is a headlight?
-  GLint aMatrixModeOld = 0;
   if (theLight.IsHeadlight)
   {
-    glGetIntegerv (GL_MATRIX_MODE, &aMatrixModeOld);
-    glMatrixMode  (GL_MODELVIEW);
-    glPushMatrix();
-    glLoadIdentity();
+
+    aContext->WorldViewState.Push();
+    aContext->WorldViewState.SetIdentity();
+
+    aContext->ApplyWorldViewMatrix();
   }
 
   // setup light type
@@ -148,8 +151,7 @@ static void bind_light (const OpenGl_Light& theLight,
   // restore matrix in case of headlight
   if (theLight.IsHeadlight)
   {
-    glPopMatrix();
-    glMatrixMode (aMatrixModeOld);
+    aContext->WorldViewState.Pop();
   }
 
   glEnable (theLightGlId++);
@@ -169,12 +171,16 @@ void OpenGl_View::DrawBackground (OpenGl_Workspace& theWorkspace)
 
     glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
 
-    glMatrixMode( GL_PROJECTION );
-    glPushMatrix();
-    glLoadIdentity();
-    glMatrixMode( GL_MODELVIEW );
-    glPushMatrix();
-    glLoadIdentity();
+    const Handle(OpenGl_Context)& aContext = theWorkspace.GetGlContext();
+
+    aContext->WorldViewState.Push();
+    aContext->ProjectionState.Push();
+
+    aContext->WorldViewState.SetIdentity();
+    aContext->ProjectionState.SetIdentity();
+
+    aContext->ApplyProjectionMatrix();
+    aContext->ApplyWorldViewMatrix();
 
     if ( glIsEnabled( GL_DEPTH_TEST ) )
       glDisable( GL_DEPTH_TEST ); //push GL_ENABLE_BIT
@@ -335,10 +341,10 @@ void OpenGl_View::DrawBackground (OpenGl_Workspace& theWorkspace)
       glEnd();
     }
 
-    glPopMatrix();
-    glMatrixMode( GL_PROJECTION );
-    glPopMatrix();
-    glMatrixMode( GL_MODELVIEW );
+    aContext->WorldViewState.Pop();
+    aContext->ProjectionState.Pop();
+
+    aContext->ApplyProjectionMatrix();
 
     glPopAttrib(); //GL_ENABLE_BIT | GL_TEXTURE_BIT
 
@@ -388,6 +394,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   }
 #endif
 
+  // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm).
   Standard_Boolean isProjectionMatUpdateNeeded  = Standard_False;
   Standard_Boolean isOrientationMatUpdateNeeded = Standard_False;
   if (myBVHSelector.ProjectionState() != myCamera->ProjectionState())
@@ -401,7 +408,12 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     myBVHSelector.ChangeModelViewState() = myCamera->ModelViewState();
   }
 
-  // Set OCCT state uniform variables
+  if (isProjectionMatUpdateNeeded
+   || isOrientationMatUpdateNeeded)
+  {
+    myBVHSelector.SetViewVolume (myCamera);
+  }
+
   const Handle(OpenGl_ShaderManager) aManager   = aContext->ShaderManager();
   const Standard_Boolean             isSameView = aManager->IsSameView (this); // force camera state update when needed
   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
@@ -414,30 +426,21 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   || !isSameView)
   {
     myProjectionState = myCamera->ProjectionState();
-    aManager->UpdateProjectionStateTo ((const Tmatrix3*)myCamera->ProjectionMatrixF().GetData());
+    aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF());
+    aContext->ApplyProjectionMatrix();
   }
 
   if (myModelViewState != myCamera->ModelViewState()
   || !isSameView)
   {
     myModelViewState = myCamera->ModelViewState();
-    aManager->UpdateWorldViewStateTo ((const Tmatrix3*)myCamera->OrientationMatrixF().GetData());
+    aContext->WorldViewState.SetCurrent (myCamera->OrientationMatrixF());
+    aContext->ApplyWorldViewMatrix();
   }
 
   if (aManager->ModelWorldState().Index() == 0)
   {
-    Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f },
-                                  { 0.f, 1.f, 0.f, 0.f },
-                                  { 0.f, 0.f, 1.f, 0.f },
-                                  { 0.f, 0.f, 0.f, 1.f } };
-
-    aContext->ShaderManager()->UpdateModelWorldStateTo (&aModelWorldState);
-  }
-
-  if (isProjectionMatUpdateNeeded
-   || isOrientationMatUpdateNeeded)
-  {
-    myBVHSelector.SetViewVolume (myCamera);
+    aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
   }
 
   // ====================================
@@ -459,7 +462,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   //      Step 3: Draw underlayer
   // =================================
 
-  RedrawLayer2d (thePrintContext, theCView, theCUnderLayer);
+  RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCUnderLayer);
 
   // =================================
   //      Step 4: Redraw main plane
@@ -548,25 +551,21 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   if (!myCamera->IsStereo() || !aContext->HasStereoBuffers())
   {
     // single-pass monographic rendering
-    const OpenGl_Matrix* aProj = (const OpenGl_Matrix*) &myCamera->ProjectionMatrixF();
-
-    const OpenGl_Matrix* aOrient = (const OpenGl_Matrix*) &myCamera->OrientationMatrixF();
-
     // redraw scene with normal orientation and projection
-    RedrawScene (thePrintContext, theWorkspace, aProj, aOrient);
+    RedrawScene (thePrintContext, theWorkspace);
   }
   else
   {
     // two stereographic passes
-    const OpenGl_Matrix* aLProj  = (const OpenGl_Matrix*) &myCamera->ProjectionStereoLeftF();
-    const OpenGl_Matrix* aRProj  = (const OpenGl_Matrix*) &myCamera->ProjectionStereoRightF();
-    const OpenGl_Matrix* aOrient = (const OpenGl_Matrix*) &myCamera->OrientationMatrixF();
 
     // safely switch to left Eye buffer
     aContext->SetDrawBufferLeft();
 
+    aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
+    aContext->ApplyProjectionMatrix();
+
     // redraw left Eye
-    RedrawScene (thePrintContext, theWorkspace, aLProj, aOrient);
+    RedrawScene (thePrintContext, theWorkspace);
 
     // reset depth buffer of first rendering pass
     if (theWorkspace->UseDepthTest())
@@ -576,8 +575,11 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     // safely switch to right Eye buffer
     aContext->SetDrawBufferRight();
 
+    aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
+    aContext->ApplyProjectionMatrix();
+
     // redraw right Eye
-    RedrawScene (thePrintContext, theWorkspace, aRProj, aOrient);
+    RedrawScene (thePrintContext, theWorkspace);
 
     // switch back to monographic rendering
     aContext->SetDrawBufferMono();
@@ -631,7 +633,7 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
   const int aMode = 0;
   theWorkspace->DisplayCallback (theCView, (aMode | OCC_PRE_OVERLAY));
 
-  RedrawLayer2d (thePrintContext, theCView, theCOverLayer);
+  RedrawLayer2d (thePrintContext, theWorkspace, theCView, theCOverLayer);
 
   theWorkspace->DisplayCallback (theCView, aMode);
 
@@ -728,6 +730,7 @@ void OpenGl_View::RenderStructs (const Handle(OpenGl_Workspace) &AWorkspace)
 
 //call_togl_redraw_layer2d
 void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintContext,
+                                 const Handle(OpenGl_Workspace)&      theWorkspace,
                                  const Graphic3d_CView&               ACView,
                                  const Aspect_CLayer2d&               ACLayer)
 {
@@ -736,16 +739,19 @@ void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintCo
    || ACLayer.ptrLayer == NULL
    || ACLayer.ptrLayer->listIndex == 0) return;
 
+  const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
+
   GLsizei dispWidth  = (GLsizei )ACLayer.viewport[0];
   GLsizei dispHeight = (GLsizei )ACLayer.viewport[1];
 
-  glMatrixMode( GL_MODELVIEW );
-  glPushMatrix ();
-  glLoadIdentity ();
+  aContext->WorldViewState.Push();
+  aContext->ProjectionState.Push();
 
-  glMatrixMode (GL_PROJECTION);
-  glPushMatrix ();
-  glLoadIdentity ();
+  aContext->WorldViewState.SetIdentity();
+  aContext->ProjectionState.SetIdentity();
+
+  aContext->ApplyWorldViewMatrix();
+  aContext->ApplyProjectionMatrix();
 
   if (!ACLayer.sizeDependent)
     glViewport (0, 0, dispWidth, dispHeight);
@@ -809,7 +815,10 @@ void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintCo
     // tiling; scaling of graphics by matrix helps render a
     // part of a view (frame) in same viewport, but with higher
     // resolution
-    thePrintContext->LoadProjTransformation();
+
+    // set printing scale/tiling transformation
+    aContext->ProjectionState.SetCurrent (thePrintContext->ProjTransformation());
+    aContext->ApplyProjectionMatrix();
 
     // printing operation also assumes other viewport dimension
     // to comply with transformation matrix or graphics scaling
@@ -846,11 +855,11 @@ void OpenGl_View::RedrawLayer2d (const Handle(OpenGl_PrinterContext)& thePrintCo
 
   glPopAttrib ();
 
-  glMatrixMode (GL_PROJECTION);
-  glPopMatrix ();
+  aContext->WorldViewState.Pop();
+  aContext->ProjectionState.Pop();
 
-  glMatrixMode( GL_MODELVIEW );
-  glPopMatrix ();
+  aContext->ApplyProjectionMatrix();
+  aContext->ApplyWorldViewMatrix();
 
   if (!ACLayer.sizeDependent)
     glViewport (0, 0, (GLsizei) ACView.DefWindow.dx, (GLsizei) ACView.DefWindow.dy);
@@ -1111,9 +1120,7 @@ void OpenGl_View::ChangePriority (const OpenGl_Structure *theStructure,
 //=======================================================================
 
 void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintContext,
-                               const Handle(OpenGl_Workspace)& theWorkspace,
-                               const OpenGl_Matrix* theProjection,
-                               const OpenGl_Matrix* theOrientation)
+                               const Handle(OpenGl_Workspace)& theWorkspace)
 {
   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
 
@@ -1165,37 +1172,16 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
     }
   }
 
-#if !defined(GL_ES_VERSION_2_0)
-  // Setup view projection
-  glMatrixMode (GL_PROJECTION);
-
 #ifdef _WIN32
-  // add printing scale/tiling transformation
-  if (!thePrintContext.IsNull())
-  {
-    thePrintContext->LoadProjTransformation();
-  }
-  else
-#endif
-    glLoadIdentity();
-
-  glMultMatrixf ((const GLfloat*)theProjection);
-
+  // set printing scale/tiling transformation
   if (!thePrintContext.IsNull())
   {
-    // update shader uniform projection matrix with new data
-    Tmatrix3 aResultProjection;
-    glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection);
-    aContext->ShaderManager()->UpdateProjectionStateTo (&aResultProjection);
-
-    // force shader uniform restore on next frame
-    myProjectionState = 0;
+    aContext->ProjectionState.Push();
+    aContext->ProjectionState.SetCurrent (thePrintContext->ProjTransformation() * aContext->ProjectionState.Current());
+    aContext->ApplyProjectionMatrix();
   }
 #endif
 
-  // Setup view orientation
-  theWorkspace->SetViewMatrix (theOrientation);
-
   // Specify clipping planes in view transformation space
   if (!myClipPlanes.IsEmpty())
   {
@@ -1233,7 +1219,7 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
     for (OpenGl_ListOfLight::Iterator aLightIt (myLights);
          aLightIt.More(); aLightIt.Next())
     {
-      bind_light (aLightIt.Value(), aLightGlId, anAmbientColor);
+      bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, theWorkspace);
     }
 
     // apply accumulated ambient color
@@ -1325,4 +1311,17 @@ void OpenGl_View::RedrawScene (const Handle(OpenGl_PrinterContext)& thePrintCont
       }
       break;
   }
+
+  // Apply restored view matrix.
+  aContext->ApplyWorldViewMatrix();
+
+#ifdef _WIN32
+  // set printing scale/tiling transformation
+  if (!thePrintContext.IsNull())
+  {
+    aContext->ProjectionState.Pop();
+    aContext->ApplyProjectionMatrix();
+  }
+#endif
+
 }