0024739: TKOpenGl - port ray-tracing from OpenCL to GLSL for better integration and...
[occt.git] / src / OpenGl / OpenGl_Group.cxx
index 5c6a63c..10af74d 100644 (file)
@@ -1,39 +1,55 @@
 // Created on: 2011-08-01
 // Created by: Sergey ZERCHANINOV
-// Copyright (c) 2011-2012 OPEN CASCADE SAS
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <OpenGl_Group.hxx>
 
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGl_Flipper.hxx>
 #include <OpenGl_PrimitiveArray.hxx>
+#include <OpenGl_StencilTest.hxx>
+#include <OpenGl_Structure.hxx>
+#include <OpenGl_Text.hxx>
 #include <OpenGl_Workspace.hxx>
 
+#include <Graphic3d_ArrayOfPrimitives.hxx>
+#include <Graphic3d_CUserDraw.hxx>
+#include <Graphic3d_GroupDefinitionError.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (OpenGl_Group, Graphic3d_Group)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Group, Graphic3d_Group)
+
 // =======================================================================
 // function : OpenGl_Group
 // purpose  :
 // =======================================================================
-OpenGl_Group::OpenGl_Group ()
-: myAspectLine (NULL),
-  myAspectFace (NULL),
-  myAspectMarker (NULL),
-  myAspectText (NULL),
-  myFirst (NULL),
-  myLast (NULL)
+OpenGl_Group::OpenGl_Group (const Handle(Graphic3d_Structure)& theStruct)
+: Graphic3d_Group (theStruct),
+  myAspectLine(NULL),
+  myAspectFace(NULL),
+  myAspectMarker(NULL),
+  myAspectText(NULL),
+  myFirst(NULL),
+  myLast(NULL),
+  myIsRaytracable (Standard_False),
+  myModificationState (0)
 {
+  Handle(OpenGl_Structure) aStruct = Handle(OpenGl_Structure)::DownCast (myStructure->CStructure());
+  if (aStruct == NULL)
+  {
+    Graphic3d_GroupDefinitionError::Raise ("OpenGl_Group should be created by OpenGl_Structure!");
+  }
 }
 
 // =======================================================================
@@ -46,110 +62,250 @@ OpenGl_Group::~OpenGl_Group()
 }
 
 // =======================================================================
-// function : SetAspectLine
+// function : UpdateAspectLine
 // purpose  :
 // =======================================================================
-void OpenGl_Group::SetAspectLine (const CALL_DEF_CONTEXTLINE& theAspect,
-                                  const Standard_Boolean theIsGlobal)
+void OpenGl_Group::UpdateAspectLine (const Standard_Boolean theIsGlobal)
 {
+  if (!ContextLine.IsDef)
+  {
+    return;
+  }
+
   if (theIsGlobal || myFirst == NULL)
   {
     if (myAspectLine == NULL)
     {
       myAspectLine = new OpenGl_AspectLine();
     }
-    myAspectLine->SetAspect (theAspect);
+    myAspectLine->SetAspect (ContextLine);
   }
   else
   {
     OpenGl_AspectLine* anAspectLine = new OpenGl_AspectLine();
-    anAspectLine->SetAspect (theAspect);
-    AddElement (TelNil/*TelAspectLine*/, anAspectLine);
+    anAspectLine->SetAspect (ContextLine);
+    AddElement (anAspectLine);
   }
 }
 
 // =======================================================================
-// function : SetAspectFace
+// function : UpdateAspectFace
 // purpose  :
 // =======================================================================
-void OpenGl_Group::SetAspectFace (const CALL_DEF_CONTEXTFILLAREA& theAspect,
-                                  const Standard_Boolean          theIsGlobal)
+void OpenGl_Group::UpdateAspectFace (const Standard_Boolean theIsGlobal)
 {
+  if (!ContextFillArea.IsDef)
+  {
+    return;
+  }
+
   if (theIsGlobal || myFirst == NULL)
   {
     if (myAspectFace == NULL)
     {
       myAspectFace = new OpenGl_AspectFace();
     }
-    myAspectFace->SetAspect (theAspect);
+    myAspectFace->SetAspect (ContextFillArea);
   }
   else
   {
     OpenGl_AspectFace* anAspectFace = new OpenGl_AspectFace();
-    anAspectFace->SetAspect (theAspect);
-    AddElement (TelNil/*TelAspectFace*/, anAspectFace);
+    anAspectFace->SetAspect (ContextFillArea);
+    AddElement (anAspectFace);
+  }
+
+  if (myIsRaytracable)
+  {
+    ++myModificationState;
+    OpenGl_Structure* aStruct = GlStruct();
+    if (aStruct != NULL)
+    {
+      aStruct->UpdateStateWithAncestorStructures();
+    }
   }
 }
 
 // =======================================================================
-// function : SetAspectMarker
+// function : UpdateAspectMarker
 // purpose  :
 // =======================================================================
-void OpenGl_Group::SetAspectMarker (const CALL_DEF_CONTEXTMARKER& theAspect,
-                                    const Standard_Boolean theIsGlobal)
+void OpenGl_Group::UpdateAspectMarker (const Standard_Boolean theIsGlobal)
 {
+  if (!ContextMarker.IsDef)
+  {
+    return;
+  }
+
   if (theIsGlobal || myFirst == NULL)
   {
     if (myAspectMarker == NULL)
     {
       myAspectMarker = new OpenGl_AspectMarker();
     }
-    myAspectMarker->SetAspect (theAspect);
+    myAspectMarker->SetAspect (ContextMarker);
   }
   else
   {
     OpenGl_AspectMarker* anAspectMarker = new OpenGl_AspectMarker();
-    anAspectMarker->SetAspect (theAspect);
-    AddElement (TelNil/*TelAspectMarker*/, anAspectMarker);
+    anAspectMarker->SetAspect (ContextMarker);
+    AddElement (anAspectMarker);
   }
 }
 
 // =======================================================================
-// function : SetAspectText
+// function : UpdateAspectText
 // purpose  :
 // =======================================================================
-void OpenGl_Group::SetAspectText (const CALL_DEF_CONTEXTTEXT& theAspect,
-                                  const Standard_Boolean theIsGlobal)
+void OpenGl_Group::UpdateAspectText (const Standard_Boolean theIsGlobal)
 {
+  if (!ContextText.IsDef)
+  {
+    return;
+  }
+
   if (theIsGlobal || myFirst == NULL)
   {
     if (myAspectText == NULL)
     {
       myAspectText = new OpenGl_AspectText();
     }
-    myAspectText->SetAspect (theAspect);
+    myAspectText->SetAspect (ContextText);
   }
   else
   {
     OpenGl_AspectText* anAspectText = new OpenGl_AspectText();
-    anAspectText->SetAspect (theAspect);
-    AddElement ( TelNil/*TelAspectText*/, anAspectText);
+    anAspectText->SetAspect (ContextText);
+    AddElement (anAspectText);
+  }
+}
+
+// =======================================================================
+// function : AddPrimitiveArray
+// purpose  :
+// =======================================================================
+void OpenGl_Group::AddPrimitiveArray (const Handle(Graphic3d_ArrayOfPrimitives)& thePrim,
+                                      const Standard_Boolean                     theToEvalMinMax)
+{
+  if (IsDeleted()
+  || !thePrim->IsValid())
+  {
+    return;
+  }
+
+  OpenGl_PrimitiveArray* anArray = new OpenGl_PrimitiveArray ((CALL_DEF_PARRAY *)thePrim->Array());
+  AddElement (anArray);
+
+  Graphic3d_Group::AddPrimitiveArray (thePrim, theToEvalMinMax);
+}
+
+// =======================================================================
+// function : Text
+// purpose  :
+// =======================================================================
+void OpenGl_Group::Text (const Standard_CString                  theTextUtf,
+                         const Graphic3d_Vertex&                 thePoint,
+                         const Standard_Real                     theHeight,
+                         const Quantity_PlaneAngle               theAngle,
+                         const Graphic3d_TextPath                theTp,
+                         const Graphic3d_HorizontalTextAlignment theHta,
+                         const Graphic3d_VerticalTextAlignment   theVta,
+                         const Standard_Boolean                  theToEvalMinMax)
+{
+  if (IsDeleted())
+  {
+    return;
+  }
+
+  OpenGl_TextParam  aParams;
+  OpenGl_Structure* aStruct = GlStruct();
+  aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
+  aParams.HAlign = theHta;
+  aParams.VAlign = theVta;
+  const OpenGl_Vec3 aPoint (thePoint.X(), thePoint.Y(), thePoint.Z());
+  OpenGl_Text* aText = new OpenGl_Text (theTextUtf, aPoint, aParams);
+  AddElement (aText);
+  Graphic3d_Group::Text (theTextUtf, thePoint, theHeight, theAngle,
+                         theTp, theHta, theVta, theToEvalMinMax);
+}
+
+// =======================================================================
+// function : UserDraw
+// purpose  :
+// =======================================================================
+void OpenGl_Group::UserDraw (const Standard_Address theObject,
+                             const Standard_Boolean theToEvalMinMax,
+                             const Standard_Boolean theContainsFacet)
+{
+  if (IsDeleted())
+  {
+    return;
   }
+
+  OpenGl_Structure* aStruct = GlStruct();
+  if (aStruct->GlDriver()->UserDrawCallback() == NULL)
+  {
+    return;
+  }
+
+  Graphic3d_CUserDraw aUserDraw;
+  aUserDraw.Data   = theObject;
+  aUserDraw.Bounds = theToEvalMinMax ? &myBounds : NULL;
+  OpenGl_Element* aUserDrawElem = aStruct->GlDriver()->UserDrawCallback()(&aUserDraw);
+  if (aUserDrawElem != NULL)
+  {
+    AddElement (aUserDrawElem);
+  }
+  Graphic3d_Group::UserDraw (theObject, theToEvalMinMax, theContainsFacet);
+}
+
+// =======================================================================
+// function : SetFlippingOptions
+// purpose  :
+// =======================================================================
+void OpenGl_Group::SetFlippingOptions (const Standard_Boolean theIsEnabled,
+                                       const gp_Ax2&          theRefPlane)
+{
+  OpenGl_Flipper* aFlipper = new OpenGl_Flipper (theRefPlane);
+  aFlipper->SetOptions (theIsEnabled);
+  AddElement (aFlipper);
+}
+
+// =======================================================================
+// function : SetStencilTestOptions
+// purpose  :
+// =======================================================================
+void OpenGl_Group::SetStencilTestOptions (const Standard_Boolean theIsEnabled)
+{
+  OpenGl_StencilTest* aStencilTest = new OpenGl_StencilTest();
+  aStencilTest->SetOptions (theIsEnabled);
+  AddElement (aStencilTest);
 }
 
 // =======================================================================
 // function : AddElement
 // purpose  :
 // =======================================================================
-void OpenGl_Group::AddElement (const TelType AType, OpenGl_Element *AElem )
+void OpenGl_Group::AddElement (OpenGl_Element* theElem)
 {
-  OpenGl_ElementNode *node = new OpenGl_ElementNode();
+  OpenGl_ElementNode *aNode = new OpenGl_ElementNode();
+
+  aNode->elem = theElem;
+  aNode->next = NULL;
+  (myLast? myLast->next : myFirst) = aNode;
+  myLast = aNode;
+
+  if (OpenGl_Raytrace::IsRaytracedElement (aNode))
+  {
+    myModificationState++;
+    myIsRaytracable = Standard_True;
 
-  node->type = AType;
-  node->elem = AElem;
-  node->next = NULL;
-  (myLast? myLast->next : myFirst) = node;
-  myLast = node;
+    OpenGl_Structure* aStruct = GlStruct();
+    if (aStruct != NULL)
+    {
+      aStruct->UpdateStateWithAncestorStructures();
+      aStruct->SetRaytracableWithAncestorStructures();
+    }
+  }
 }
 
 // =======================================================================
@@ -159,7 +315,6 @@ void OpenGl_Group::AddElement (const TelType AType, OpenGl_Element *AElem )
 void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
   // Is rendering in ADD or IMMEDIATE mode?
-  const Standard_Boolean isImmediate = (theWorkspace->NamedStatus & (OPENGL_NS_ADD | OPENGL_NS_IMMEDIATE)) != 0;
   const Handle(OpenGl_RenderFilter)& aFilter = theWorkspace->GetRenderFilter();
 
   // Setup aspects
@@ -175,27 +330,7 @@ void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
   // Render group elements
   for (OpenGl_ElementNode* aNodeIter = myFirst; aNodeIter != NULL; aNodeIter = aNodeIter->next)
   {
-    switch (aNodeIter->type)
-    {
-      case TelMarker:
-      case TelMarkerSet:
-      case TelText:
-      {
-        glDisable (GL_LIGHTING);
-        if (isImmediate)
-        {
-          glDepthMask (GL_FALSE);
-        }
-
-        aNodeIter->elem->RenderFiltered (theWorkspace, aFilter);
-        break;
-      }
-      default:
-      {
-        aNodeIter->elem->RenderFiltered (theWorkspace, aFilter);
-        break;
-      }
-    }
+    aNodeIter->elem->RenderFiltered (theWorkspace, aFilter);
   }
 
   // Restore aspects
@@ -209,6 +344,24 @@ void OpenGl_Group::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
     theWorkspace->SetAspectText (aBackAspectText);
 }
 
+// =======================================================================
+// function : Clear
+// purpose  :
+// =======================================================================
+void OpenGl_Group::Clear (const Standard_Boolean theToUpdateStructureMgr)
+{
+  if (IsDeleted())
+  {
+    return;
+  }
+
+  OpenGl_Structure* aStruct = GlStruct();
+  const Handle(OpenGl_Context)& aCtx = aStruct->GlDriver()->GetSharedContext();
+
+  Release (aCtx);
+  Graphic3d_Group::Clear (theToUpdateStructureMgr);
+}
+
 // =======================================================================
 // function : Release
 // purpose  :