0023067: OpenGl package API needed by UserDraw feature is not exported
[occt.git] / src / ViewerTest / ViewerTest_OpenGlCommands.cxx
1 // Created on: 2012-04-09
2 // Created by: Sergey ANIKIN
3 // Copyright (c) 2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <ViewerTest.hxx>
25
26 #include <AIS_InteractiveObject.hxx>
27 #include <Draw.hxx>
28 #include <Draw_Interpretor.hxx>
29 #include <Graphic3d_Group.hxx>
30 #include <OpenGl_ArbVBO.hxx>
31 #include <OpenGl_AspectFace.hxx>
32 #include <OpenGl_AspectLine.hxx>
33 #include <OpenGl_AspectMarker.hxx>
34 #include <OpenGl_AspectText.hxx>
35 #include <OpenGl_Callback.hxx>
36 #include <OpenGl_Context.hxx>
37 #include <OpenGl_Element.hxx>
38 #include <OpenGl_ExtFBO.hxx>
39 #include <OpenGl_GlCore20.hxx>
40 #include <OpenGl_ResourceCleaner.hxx>
41 #include <OpenGl_ResourceTexture.hxx>
42 #include <OpenGl_ResourceVBO.hxx>
43 #include <OpenGl_Workspace.hxx>
44 #include <Prs3d_Presentation.hxx>
45 #include <Prs3d_Root.hxx>
46 #include <Select3D_SensitiveCurve.hxx>
47 #include <SelectMgr_EntityOwner.hxx>
48 #include <SelectMgr_Selection.hxx>
49 #include <TCollection_AsciiString.hxx>
50
51 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
52                                            const Handle(AIS_InteractiveObject)& theAISObj,
53                                            Standard_Boolean theReplaceIfExists = Standard_True);
54
55 //=======================================================================
56 //function : VUserDraw
57 //purpose  : Checks availability and operation of UserDraw feature
58 //=======================================================================
59 DEFINE_STANDARD_HANDLE(VUserDrawObj, AIS_InteractiveObject)
60
61 class VUserDrawObj : public AIS_InteractiveObject
62 {
63 public:
64     // CASCADE RTTI
65     DEFINE_STANDARD_RTTI(VUserDrawObj);
66
67     VUserDrawObj()
68     {
69       myCoords[0] = -10.;
70       myCoords[1] = -20.;
71       myCoords[2] = -30.;
72       myCoords[3] =  10.;
73       myCoords[4] =  20.;
74       myCoords[5] =  30.;
75     }
76
77 public:
78   class Element : public OpenGl_Element
79   {
80   private:
81     Handle(VUserDrawObj) myIObj;
82
83   public:
84     Element (const Handle(VUserDrawObj)& theIObj,
85              CALL_DEF_BOUNDS* theBounds)
86     : myIObj( theIObj )
87     {
88       if (!myIObj.IsNull())
89         myIObj->GetBounds(theBounds);
90     }
91
92     virtual ~Element ()
93     {
94     }
95
96     virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
97     {
98       if (!myIObj.IsNull())
99         myIObj->Render(theWorkspace);
100     }
101
102   public:
103     DEFINE_STANDARD_ALLOC
104   };
105
106 private:
107     // Virtual methods implementation
108     void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
109                   const Handle(Prs3d_Presentation)& thePresentation,
110                   const Standard_Integer theMode);
111
112     void ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
113                            const Standard_Integer theMode);
114
115     // Called by VUserDrawElement
116     void Render(const Handle(OpenGl_Workspace)& theWorkspace) const;
117     void GetBounds(CALL_DEF_BOUNDS* theBounds);
118
119     GLfloat myCoords[6];
120
121     friend class Element;
122 };
123 IMPLEMENT_STANDARD_HANDLE(VUserDrawObj, AIS_InteractiveObject)
124 IMPLEMENT_STANDARD_RTTIEXT(VUserDrawObj, AIS_InteractiveObject)
125
126 void VUserDrawObj::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
127                            const Handle(Prs3d_Presentation)& thePresentation,
128                            const Standard_Integer theMode)
129 {
130   thePresentation->Clear();
131
132   Handle(Graphic3d_Group) aGrp = Prs3d_Root::CurrentGroup(thePresentation);
133   aGrp->UserDraw(this, Standard_True, Standard_True);
134 }
135
136 void VUserDrawObj::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
137                                      const Standard_Integer theMode)
138 {
139   Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
140   Handle(TColgp_HArray1OfPnt) aPnts = new TColgp_HArray1OfPnt(1, 5);
141   aPnts->SetValue(1, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
142   aPnts->SetValue(2, gp_Pnt(myCoords[3], myCoords[4], myCoords[2]));
143   aPnts->SetValue(3, gp_Pnt(myCoords[3], myCoords[4], myCoords[5]));
144   aPnts->SetValue(4, gp_Pnt(myCoords[0], myCoords[1], myCoords[5]));
145   aPnts->SetValue(5, gp_Pnt(myCoords[0], myCoords[1], myCoords[2]));
146   Handle(Select3D_SensitiveCurve) aSensitive = new Select3D_SensitiveCurve(anEntityOwner, aPnts);
147   theSelection->Add(aSensitive);
148 }
149
150 void VUserDrawObj::GetBounds(CALL_DEF_BOUNDS* theBounds)
151 {
152   if (theBounds)
153   {
154     theBounds->XMin = myCoords[0];
155     theBounds->YMin = myCoords[1];
156     theBounds->ZMin = myCoords[2];
157     theBounds->XMax = myCoords[3];
158     theBounds->YMax = myCoords[4];
159     theBounds->ZMax = myCoords[5];
160   }
161 }
162
163 void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
164 {
165   // To test linking against OpenGl_Workspace and all aspect classes
166   const OpenGl_AspectLine* aLA = theWorkspace->AspectLine(0);
167   const OpenGl_AspectFace* aFA = theWorkspace->AspectFace(0);
168   aFA->Context();
169   const OpenGl_AspectMarker* aMA = theWorkspace->AspectMarker(0);
170   aMA->Type();
171   const OpenGl_AspectText* aTA = theWorkspace->AspectText(0);
172   aTA->Font();
173   TEL_COLOUR aColor = theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT ?
174     *(theWorkspace->HighlightColor) : aLA->Color();
175
176   // To test OpenGl_Window
177   Handle(OpenGl_Context) aCtx = theWorkspace->GetGlContext();
178   GLCONTEXT aGlContext = theWorkspace->GetGContext();
179
180   // To link against OpenGl_Context and extensions
181   GLuint aVboId = -1, aTexId = -1;
182   if (aCtx->arbVBO)
183     aCtx->arbVBO->glGenBuffersARB(1, &aVboId);
184   glGenTextures(1, &aTexId);
185
186   // To link against OpenGl_ResourceCleaner, OpenGl_ResourceVBO, OpenGl_ResourceTexture
187   OpenGl_ResourceCleaner* aResCleaner = OpenGl_ResourceCleaner::GetInstance();
188   if (aVboId != (GLuint)-1)
189     aResCleaner->AddResource(aGlContext, new OpenGl_ResourceVBO(aVboId));
190   if (aTexId != (GLuint)-1)
191     aResCleaner->AddResource(aGlContext, new OpenGl_ResourceTexture(aTexId));
192
193   // Finally draw something to make sure UserDraw really works
194   glPushAttrib(GL_ENABLE_BIT);
195   glDisable(GL_LIGHTING);
196   glColor4fv(aColor.rgb);
197   glBegin(GL_LINE_LOOP);
198   glVertex3f(myCoords[0], myCoords[1], myCoords[2]);
199   glVertex3f(myCoords[3], myCoords[4], myCoords[2]);
200   glVertex3f(myCoords[3], myCoords[4], myCoords[5]);
201   glVertex3f(myCoords[0], myCoords[1], myCoords[5]);
202   glEnd();
203   glPopAttrib();
204 }
205
206
207
208 OpenGl_Element* VUserDrawCallback(const CALL_DEF_USERDRAW * theUserDraw)
209 {
210   Handle(VUserDrawObj) anIObj = (VUserDrawObj*)theUserDraw->Data;
211   if (anIObj.IsNull())
212   {
213     std::cout << "VUserDrawCallback error: null object passed, the custom scene element will not be rendered" << std::endl;
214   }
215
216   return new VUserDrawObj::Element(anIObj, theUserDraw->Bounds);
217 }
218
219 static Standard_Integer VUserDraw (Draw_Interpretor& di,
220                                     Standard_Integer argc,
221                                     const char ** argv)
222 {
223   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
224   if (aContext.IsNull())
225   {
226     di << argv[0] << "Call 'vinit' before!\n";
227     return 1;
228   }
229
230   if (argc > 2)
231   {
232     di << argv[0] << "Wrong number of arguments, only the object name expected\n";
233     return 1;
234   }
235
236   TCollection_AsciiString aName (argv[1]);
237   VDisplayAISObject(aName, Handle(AIS_InteractiveObject)());
238
239   // register the custom element factory function
240   ::UserDrawCallback() = VUserDrawCallback;
241
242   Handle(VUserDrawObj) anIObj = new VUserDrawObj();
243   VDisplayAISObject(aName, anIObj);
244
245   return 0;
246 }
247
248 //=======================================================================
249 //function : OpenGlCommands
250 //purpose  :
251 //=======================================================================
252
253 void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
254 {
255   const char* aGroup ="Commands for low-level TKOpenGl features";
256
257   theCommands.Add("vuserdraw",
258     "vuserdraw : name - simulates drawing with help of UserDraw",
259     __FILE__, VUserDraw, aGroup);
260 }