]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketcherPrs/SketcherPrs_SymbolPrs.cpp
Salome HOME
20fc780a705d564a603b0e8dde375b97e2975123
[modules/shaper.git] / src / SketcherPrs / SketcherPrs_SymbolPrs.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        SketcherPrs_SymbolPrs.cpp
4 // Created:     12 March 2015
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "SketcherPrs_SymbolPrs.h"
8 #include "SketcherPrs_Tools.h"
9 #include "SketcherPrs_PositionMgr.h"
10
11 #include <GeomAPI_Edge.h>
12
13 #include <Graphic3d_ArrayOfSegments.hxx>
14 #include <Graphic3d_BndBox4f.hxx>
15
16 #include <SelectMgr_Selection.hxx>
17 #include <SelectMgr_SelectionManager.hxx>
18 #include <Select3D_SensitivePoint.hxx>
19 #include <TopLoc_Location.hxx>
20 #include <AIS_InteractiveContext.hxx>
21 #include <V3d_Viewer.hxx>
22 #include <Prs3d_Root.hxx>
23
24 #include <OpenGl_Element.hxx>
25 #include <OpenGl_GraphicDriver.hxx>
26 #include <OpenGl_Context.hxx>
27 #include <OpenGl_View.hxx>
28 #include <OpenGl_PointSprite.hxx>
29 #include <OpenGl_VertexBuffer.hxx>
30 #include <OpenGl_ShaderManager.hxx>
31 #include <OpenGl_VertexBufferCompat.hxx>
32 #include <OpenGl_GraphicDriver.hxx>
33
34 #ifdef WIN32
35 # define FSEP "\\"
36 #else
37 # define FSEP "/"
38 #endif
39
40 /// Step between icons
41 static const double MyDist = 0.02;
42
43 /// Function to convert opengl data type
44 GLenum toGlDataType (const Graphic3d_TypeOfData theType, GLint& theNbComp)
45 {
46   switch (theType) {
47     case Graphic3d_TOD_USHORT:
48       theNbComp = 1;
49       return GL_UNSIGNED_SHORT;
50     case Graphic3d_TOD_UINT:
51       theNbComp = 1;
52       return GL_UNSIGNED_INT;
53     case Graphic3d_TOD_VEC2:
54       theNbComp = 2;
55       return GL_FLOAT;
56     case Graphic3d_TOD_VEC3:
57       theNbComp = 3;
58       return GL_FLOAT;
59     case Graphic3d_TOD_VEC4:
60       theNbComp = 4;
61       return GL_FLOAT;
62     case Graphic3d_TOD_VEC4UB:
63       theNbComp = 4;
64       return GL_UNSIGNED_BYTE;
65   }
66   theNbComp = 0;
67   return GL_NONE;
68 }
69
70
71 //*******************************************************************
72 //! Auxiliary class for Vertex buffer with interleaved attributes.
73 class SketcherPrs_VertexBuffer : public OpenGl_VertexBuffer
74 {
75
76 public:
77
78   //! Create uninitialized VBO..
79   SketcherPrs_VertexBuffer (const Graphic3d_Attribute* theAttribs,
80                         const Standard_Integer     theStride)
81   : Stride (theStride), NbAttributes(1)
82   {
83
84     memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
85   }
86
87   //! Create uninitialized VBO.
88   SketcherPrs_VertexBuffer (const Graphic3d_Buffer& theAttribs)
89   : Stride (theAttribs.Stride), NbAttributes(1)
90   {
91     memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
92   }
93
94   virtual bool HasColorAttribute() const
95   {
96     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) {
97       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
98       if (anAttrib.Id == Graphic3d_TOA_COLOR) {
99         return true;
100       }
101     }
102     return false;
103   }
104
105   virtual bool HasNormalAttribute() const
106   {
107     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) {
108       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
109       if (anAttrib.Id == Graphic3d_TOA_NORM) {
110         return true;
111       }
112     }
113     return false;
114   }
115
116   virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
117   {
118     if (!OpenGl_VertexBuffer::IsValid()) {
119       return;
120     }
121
122     OpenGl_VertexBuffer::Bind (theGlCtx);
123     GLint aNbComp;
124     const GLubyte* anOffset = OpenGl_VertexBuffer::myOffset;
125     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) {
126       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
127       const GLenum   aDataType = toGlDataType (anAttrib.DataType, aNbComp);
128       if (aDataType == GL_NONE) {
129         continue;
130       } else if (anAttrib.Id == Graphic3d_TOA_POS) {
131         OpenGl_VertexBuffer::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
132         break;
133       }
134
135       anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
136     }
137   }
138
139   virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
140   {
141     if (!OpenGl_VertexBuffer::IsValid())
142       return;
143
144     OpenGl_VertexBuffer::Bind (theGlCtx);
145     GLint aNbComp;
146     const GLubyte* anOffset = OpenGl_VertexBuffer::myOffset;
147     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
148     {
149       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
150       const GLenum   aDataType = toGlDataType (anAttrib.DataType, aNbComp);
151       if (aDataType == GL_NONE)
152         continue;
153
154       OpenGl_VertexBuffer::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
155       anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
156     }
157   }
158
159   virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
160   {
161     if (!OpenGl_VertexBuffer::IsValid())
162       return;
163     OpenGl_VertexBuffer::Unbind (theGlCtx);
164
165     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter) {
166       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
167       OpenGl_VertexBuffer::unbindAttribute (theGlCtx, anAttrib.Id);
168     }
169   }
170
171 public:
172
173   Graphic3d_Attribute Attribs[1];
174   Standard_Integer    Stride;
175   Standard_Integer NbAttributes;
176 };
177
178 //**************************************************************
179 //! Redefinition of OpenGl_Element
180 class SketcherPrs_Element: public OpenGl_Element
181 {
182 public:
183   SketcherPrs_Element(const Handle(SketcherPrs_SymbolPrs)& theObj) : 
184   OpenGl_Element(), myObj(theObj) {}
185
186   virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const
187   {
188     if (!myObj.IsNull())
189       myObj->Render(theWorkspace);
190   }
191
192   virtual void Release (OpenGl_Context* theContext) 
193   {
194     if (!myObj.IsNull())
195       myObj->Release(theContext);
196   }
197
198 private:
199   Handle(SketcherPrs_SymbolPrs) myObj;
200 };
201
202
203 //**************************************************************
204 //! Definition of call back
205 OpenGl_Element* SymbolPrsCallBack(const CALL_DEF_USERDRAW * theUserDraw)
206 {
207   Handle(SketcherPrs_SymbolPrs) anIObj = (SketcherPrs_SymbolPrs*)theUserDraw->Data;
208   if (anIObj.IsNull()) {
209     std::cout << "VUserDrawCallback error: null object passed, the custom scene element will not be rendered" << std::endl;
210   }
211   return new SketcherPrs_Element(anIObj);
212 }
213
214
215 //*****************************************************************************
216 IMPLEMENT_STANDARD_HANDLE(SketcherPrs_SymbolPrs, AIS_InteractiveObject);
217 IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_SymbolPrs, AIS_InteractiveObject);
218
219
220 std::map<const char*, Handle(Image_AlienPixMap)> SketcherPrs_SymbolPrs::myIconsMap;
221
222
223 SketcherPrs_SymbolPrs::SketcherPrs_SymbolPrs(ModelAPI_Feature* theConstraint, 
224                                              const std::shared_ptr<GeomAPI_Ax3>& thePlane)
225  : AIS_InteractiveObject(), myConstraint(theConstraint), myPlane(thePlane)
226 {
227   SetAutoHilight(Standard_False);
228 }
229
230 SketcherPrs_SymbolPrs::~SketcherPrs_SymbolPrs()
231 {
232   SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
233   aMgr->deleteConstraint(this);
234 }
235
236
237
238 Handle(Image_AlienPixMap) SketcherPrs_SymbolPrs::icon()
239 {
240   if (myIconsMap.count(iconName()) == 1) {
241     return myIconsMap[iconName()];
242   }
243   TCollection_AsciiString aFile(getenv("NewGeomResources"));
244   aFile += FSEP;
245   aFile += iconName();
246   Handle(Image_AlienPixMap) aPixMap = new Image_AlienPixMap();
247   if (aPixMap->Load(aFile)) {
248     myIconsMap[iconName()] = aPixMap;
249     return aPixMap;
250   }
251   return Handle(Image_AlienPixMap)();
252 }
253
254 void SketcherPrs_SymbolPrs::ClearSelected()
255 {
256   Handle( Prs3d_Presentation ) aSelectionPrs = GetSelectPresentation( NULL );  
257   if( !aSelectionPrs.IsNull() ) {
258     aSelectionPrs->Clear(); 
259   }
260 }
261
262 void SketcherPrs_SymbolPrs::prepareAspect()
263 {
264   if (myAspect.IsNull()) {
265     myAspect = new Graphic3d_AspectMarker3d(icon());
266   }
267 }
268
269 void SketcherPrs_SymbolPrs::addLine(const Handle(Graphic3d_Group)& theGroup, std::string theAttrName) const
270 {
271   ObjectPtr aObj = SketcherPrs_Tools::getResult(myConstraint, theAttrName);
272   std::shared_ptr<GeomAPI_Shape> aLine = SketcherPrs_Tools::getShape(aObj);
273   if (aLine.get() == NULL)
274     return;
275   std::shared_ptr<GeomAPI_Edge> aEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLine));
276
277   std::shared_ptr<GeomAPI_Pnt> aPnt1 = aEdge->firstPoint();
278   std::shared_ptr<GeomAPI_Pnt> aPnt2 = aEdge->lastPoint();
279
280   Handle(Graphic3d_ArrayOfSegments) aLines = new Graphic3d_ArrayOfSegments(2, 1);
281   aLines->AddVertex(aPnt1->impl<gp_Pnt>());
282   aLines->AddVertex(aPnt2->impl<gp_Pnt>());
283   theGroup->AddPrimitiveArray(aLines);
284 }
285
286 void SketcherPrs_SymbolPrs::HilightSelected(const Handle(PrsMgr_PresentationManager3d)& thePM, 
287                                            const SelectMgr_SequenceOfOwner& theOwners)
288 {
289
290   Handle( Prs3d_Presentation ) aSelectionPrs = GetSelectPresentation( thePM );
291   aSelectionPrs->Clear();
292   drawLines(aSelectionPrs, Quantity_NOC_WHITE);
293
294   aSelectionPrs->SetDisplayPriority(9);
295   aSelectionPrs->Display();
296   thePM->Highlight(this);
297 }
298
299 void SketcherPrs_SymbolPrs::HilightOwnerWithColor(const Handle(PrsMgr_PresentationManager3d)& thePM, 
300                                                  const Quantity_NameOfColor theColor, const Handle(SelectMgr_EntityOwner)& theOwner)
301 {
302   thePM->Color(this, theColor);
303
304   Handle( Prs3d_Presentation ) aHilightPrs = GetHilightPresentation( thePM );
305   aHilightPrs->Clear();
306   drawLines(aHilightPrs, theColor);
307
308   if (thePM->IsImmediateModeOn())
309     thePM->AddToImmediateList(aHilightPrs);
310 }
311
312 void SketcherPrs_SymbolPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
313                                    const Handle(Prs3d_Presentation)& thePresentation, 
314                                    const Standard_Integer theMode)
315 {
316   prepareAspect();
317
318   Handle(AIS_InteractiveContext) aCtx = GetContext();
319   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast(aCtx->CurrentViewer()->Driver());
320   if (!aDriver.IsNull()) {
321     // register the custom element factory function
322     aDriver->UserDrawCallback() = SymbolPrsCallBack;
323   }
324
325   if (!updatePoints(20))
326     return;
327
328   int aNbVertex = myPntArray->VertexNumber();
329   if (myOwner.IsNull()) {
330     myOwner = new SelectMgr_EntityOwner(this);
331     for (int i = 1; i <= aNbVertex; i++) {
332       Handle(SketcherPrs_SensitivePoint) aSP = new SketcherPrs_SensitivePoint(myOwner, myPntArray, i);
333       mySPoints.Append(aSP);
334     }
335   }
336
337   Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup(thePresentation);
338   aGroup->SetPrimitivesAspect(myAspect);
339
340   Graphic3d_BndBox4f& aBnd = aGroup->ChangeBoundingBox();
341   gp_Pnt aVert;
342   aBnd.Clear();
343   for (int i = 1; i <= myPntArray->ItemNumber(); i++) {
344     aVert = myPntArray->Vertice(i);
345     aBnd.Add (Graphic3d_Vec4((float)aVert.X(), (float)aVert.Y(), (float)aVert.Z(), 1.0f));
346   }
347
348   aGroup->UserDraw(this, true);
349   //aGroup->AddPrimitiveArray(myPntArray);
350 }
351
352
353
354 void SketcherPrs_SymbolPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
355                                             const Standard_Integer aMode)
356 {
357   ClearSelected();
358   if ((aMode == 0) || (aMode == SketcherPrs_Tools::Sel_Constraint)) {
359     for (int i = 1; i <= mySPoints.Length(); i++)
360       aSelection->Add(mySPoints.Value(i));
361   }
362 }
363
364
365 void SketcherPrs_SymbolPrs::Render(const Handle(OpenGl_Workspace)& theWorkspace) const
366 {
367   const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker(Standard_True);
368   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
369   Handle(OpenGl_View) aView = theWorkspace->ActiveView();
370   
371   double aScale = aView->Camera()->Scale();
372   if (!updatePoints(MyDist * aScale))
373     return;
374
375   Handle(Graphic3d_Buffer) aAttribs = myPntArray->Attributes();
376
377   if (myVboAttribs.IsNull()) {
378     myVboAttribs = new SketcherPrs_VertexBuffer(*aAttribs);
379   }
380
381   if (!myVboAttribs->init(aCtx, 0, aAttribs->NbElements, aAttribs->Data(), GL_NONE, aAttribs->Stride)) {
382     myVboAttribs->Release (aCtx.operator->());
383     myVboAttribs.Nullify();
384     return;
385   }
386     
387   Handle(OpenGl_Texture) aTextureBack = theWorkspace->DisableTexture();
388
389   const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes(aCtx);
390       
391   if (!aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList()) {
392     const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
393     const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes(aCtx)->IsValid())
394                                               ? anAspectMarker->SpriteHighlightRes(aCtx)
395                                               : aSpriteNorm;
396     theWorkspace->EnableTexture (aSprite);
397     aCtx->ShaderManager()->BindProgram(anAspectMarker, aSprite, Standard_False, Standard_False, anAspectMarker->ShaderProgramRes(aCtx));
398     const TEL_COLOUR* aLineColor  =  &anAspectMarker->Color();
399     if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
400       aLineColor = theWorkspace->HighlightColor;
401
402     aCtx->SetColor4fv(*(const OpenGl_Vec4* )(aLineColor->rgb));
403
404
405     myVboAttribs->BindAllAttributes(aCtx);
406     // Textured markers will be drawn with the point sprites
407     aCtx->SetPointSize (anAspectMarker->MarkerSize());
408     aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
409     aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
410
411     aCtx->core11fwd->glEnable (GL_BLEND);
412     aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
413
414     aCtx->core11fwd->glDrawArrays (0, 0, myVboAttribs->GetElemsNb());
415
416     aCtx->core11fwd->glDisable (GL_BLEND);
417     aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
418     aCtx->SetPointSize (1.0f);
419   }
420   theWorkspace->EnableTexture (aTextureBack);
421   aCtx->BindProgram (NULL);
422
423   // Update selection position only if there is no selected object
424   // because it can corrupt selection of other objects
425   if ((GetContext()->NbCurrents() == 0) && (GetContext()->NbSelected() == 0))
426     GetContext()->RecomputeSelectionOnly(this);
427 }
428
429
430 void SketcherPrs_SymbolPrs::Release (OpenGl_Context* theContext)
431 {
432   if (!myVboAttribs.IsNull()) {
433     if (theContext) {
434       theContext->DelayedRelease (myVboAttribs);
435     }
436     myVboAttribs.Nullify();
437   }
438 }
439