1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_AspectFace.hxx>
17 #include <OpenGl_Context.hxx>
18 #include <OpenGl_GraphicDriver.hxx>
19 #include <OpenGl_IndexBuffer.hxx>
20 #include <OpenGl_PointSprite.hxx>
21 #include <OpenGl_PrimitiveArray.hxx>
22 #include <OpenGl_ShaderManager.hxx>
23 #include <OpenGl_ShaderProgram.hxx>
24 #include <OpenGl_Structure.hxx>
25 #include <OpenGl_VertexBufferCompat.hxx>
26 #include <OpenGl_Workspace.hxx>
31 const Handle(OpenGl_ShaderProgram)& bindProgram (const Handle(OpenGl_Workspace)& theWS,
34 const Handle(OpenGl_Context)& aCtx = theWS->GetGlContext();
35 const Handle(OpenGl_ShaderProgram)& aProgram = theAspect->ShaderProgramRes (theWS);
36 aCtx->BindProgram (aProgram);
37 if (aProgram.IsNull())
39 return aCtx->ActiveProgram();
42 aProgram->ApplyVariables (aCtx);
44 const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram);
45 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
47 aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, theAspect);
50 aCtx->ShaderManager()->PushState (aProgram);
54 inline const Handle(OpenGl_ShaderProgram)& bindProgram (const Handle(OpenGl_Workspace)& theWorkspace,
55 const OpenGl_AspectFace* theAspectFace,
56 const OpenGl_AspectLine* theAspectLine,
57 const OpenGl_AspectMarker* theAspectMarker,
58 const GLint theDrawMode)
60 if (!theWorkspace->GetGlContext()->IsGlGreaterEqual (2, 0))
62 return theWorkspace->GetGlContext()->ActiveProgram();
67 return bindProgram (theWorkspace, theAspectMarker);
70 return bindProgram (theWorkspace, theAspectLine);
72 return bindProgram (theWorkspace, theAspectFace);
75 //! Convert index data type from size
76 inline GLenum toGlIndexType (const Standard_Integer theStride)
80 case 2: return GL_UNSIGNED_SHORT;
81 case 4: return GL_UNSIGNED_INT;
82 default: return GL_NONE;
86 //! Convert data type to GL info
87 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
92 case Graphic3d_TOD_USHORT:
94 return GL_UNSIGNED_SHORT;
95 case Graphic3d_TOD_UINT:
97 return GL_UNSIGNED_INT;
98 case Graphic3d_TOD_VEC2:
101 case Graphic3d_TOD_VEC3:
104 case Graphic3d_TOD_VEC4:
107 case Graphic3d_TOD_VEC4UB:
109 return GL_UNSIGNED_BYTE;
117 //! Auxiliary template for VBO with interleaved attributes.
118 template<class TheBaseClass, int NbAttributes>
119 class OpenGl_VertexBufferT : public TheBaseClass
124 //! Create uninitialized VBO.
125 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
126 const Standard_Integer theStride)
129 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
132 //! Create uninitialized VBO.
133 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
134 : Stride (theAttribs.Stride)
136 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
139 virtual bool HasColorAttribute() const
141 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
143 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
144 if (anAttrib.Id == Graphic3d_TOA_COLOR)
152 virtual bool HasNormalAttribute() const
154 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
156 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
157 if (anAttrib.Id == Graphic3d_TOA_NORM)
165 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
167 if (!TheBaseClass::IsValid())
172 TheBaseClass::Bind (theGlCtx);
174 const GLubyte* anOffset = TheBaseClass::myOffset;
175 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
177 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
178 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
179 if (aDataType == GL_NONE)
183 else if (anAttrib.Id == Graphic3d_TOA_POS)
185 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
189 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
193 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
195 if (!TheBaseClass::IsValid())
200 TheBaseClass::Bind (theGlCtx);
202 const GLubyte* anOffset = TheBaseClass::myOffset;
203 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
205 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
206 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
207 if (aDataType == GL_NONE)
212 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
213 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
217 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
219 if (!TheBaseClass::IsValid())
223 TheBaseClass::Unbind (theGlCtx);
225 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
227 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
228 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
234 Graphic3d_Attribute Attribs[NbAttributes];
235 Standard_Integer Stride;
239 // =======================================================================
240 // function : clearMemoryGL
242 // =======================================================================
243 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
245 if (!myVboIndices.IsNull())
247 myVboIndices->Release (theGlCtx.operator->());
248 myVboIndices.Nullify();
250 if (!myVboAttribs.IsNull())
252 myVboAttribs->Release (theGlCtx.operator->());
253 myVboAttribs.Nullify();
257 // =======================================================================
258 // function : initNormalVbo
260 // =======================================================================
261 Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
263 switch (myAttribs->NbAttributes)
265 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
266 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
267 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
268 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
269 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
270 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
271 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
272 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
273 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
274 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
277 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
279 TCollection_ExtendedString aMsg;
280 aMsg += "VBO creation for Primitive Array has failed for ";
281 aMsg += myAttribs->NbElements;
282 aMsg += " vertices. Out of memory?";
283 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
285 clearMemoryGL (theCtx);
286 return Standard_False;
288 else if (myIndices.IsNull())
290 return Standard_True;
293 myVboIndices = new OpenGl_IndexBuffer();
295 switch (myIndices->Stride)
299 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
304 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
309 clearMemoryGL (theCtx);
310 return Standard_False;
315 TCollection_ExtendedString aMsg;
316 aMsg += "VBO creation for Primitive Array has failed for ";
317 aMsg += myIndices->NbElements;
318 aMsg += " indices. Out of memory?";
319 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
320 clearMemoryGL (theCtx);
321 return Standard_False;
323 return Standard_True;
326 // =======================================================================
327 // function : buildVBO
329 // =======================================================================
330 Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
331 const Standard_Boolean theToKeepData) const
333 bool isNormalMode = theCtx->ToUseVbo();
334 if (myAttribs.IsNull()
335 || myAttribs->IsEmpty()
336 || myAttribs->NbElements < 1
337 || myAttribs->NbAttributes < 1
338 || myAttribs->NbAttributes > 10)
340 // vertices should be always defined - others are optional
341 return Standard_False;
345 && initNormalVbo (theCtx))
347 if (!theCtx->caps->keepArrayData
353 return Standard_True;
356 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
357 switch (myAttribs->NbAttributes)
359 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
360 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
361 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
362 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
363 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
364 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
365 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
366 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
367 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
368 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
370 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
371 if (!myIndices.IsNull())
373 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
374 switch (myIndices->Stride)
378 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
383 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
388 return Standard_False;
391 myVboIndices = aVboIndices;
393 myVboAttribs = aVboAttribs;
394 if (!theCtx->caps->keepArrayData
397 // does not make sense for compatibility mode
398 //myIndices.Nullify();
399 //myAttribs.Nullify();
402 return Standard_True;
405 // =======================================================================
406 // function : drawArray
408 // =======================================================================
409 void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
410 const Graphic3d_Vec4* theFaceColors) const
412 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
413 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
414 bool hasVColors = false;
415 if (myVboAttribs.IsNull())
417 if (myDrawMode == GL_POINTS)
419 // extreme compatibility mode - without sprites but with markers
420 drawMarkers (theWorkspace);
425 myVboAttribs->BindAllAttributes (aGlContext);
426 if (myVboAttribs->HasColorAttribute())
430 // disable per-vertex colors
431 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
438 if (!myVboIndices.IsNull())
440 myVboIndices->Bind (aGlContext);
441 GLubyte* anOffset = myVboIndices->GetDataOffset();
442 if (!myBounds.IsNull())
444 // draw primitives by vertex count with the indices
445 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
446 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
448 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
449 if (theFaceColors != NULL) glColor3fv (theFaceColors[aGroupIter].GetData());
450 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
451 anOffset += aStride * aNbElemsInGroup;
456 // draw one (or sequential) primitive by the indices
457 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
459 myVboIndices->Unbind (aGlContext);
461 else if (!myBounds.IsNull())
463 GLint aFirstElem = 0;
464 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
466 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
467 if (theFaceColors != NULL) glColor3fv (theFaceColors[aGroupIter].GetData());
468 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
469 aFirstElem += aNbElemsInGroup;
474 if (myDrawMode == GL_POINTS)
476 drawMarkers (theWorkspace);
480 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
485 myVboAttribs->UnbindAllAttributes (aGlContext);
489 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
493 // =======================================================================
494 // function : drawEdges
496 // =======================================================================
497 void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour,
498 const Handle(OpenGl_Workspace)& theWorkspace) const
500 if (myVboAttribs.IsNull())
505 glDisable (GL_LIGHTING);
507 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
508 const OpenGl_AspectLine* anAspectLineOld = NULL;
510 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
511 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
513 glPushAttrib (GL_POLYGON_BIT);
514 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
516 if (aGlContext->IsGlGreaterEqual (2, 0))
518 bindProgram (theWorkspace, anAspect);
521 /// OCC22236 NOTE: draw edges for all situations:
522 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
523 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
524 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
525 myVboAttribs->BindPositionAttribute (aGlContext);
526 glColor3fv (theEdgeColour->rgb);
527 if (!myVboIndices.IsNull())
529 myVboIndices->Bind (aGlContext);
530 GLubyte* anOffset = myVboIndices->GetDataOffset();
532 // draw primitives by vertex count with the indices
533 if (!myBounds.IsNull())
535 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
536 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
538 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
539 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
540 anOffset += aStride * aNbElemsInGroup;
543 // draw one (or sequential) primitive by the indices
546 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
548 myVboIndices->Unbind (aGlContext);
550 else if (!myBounds.IsNull())
552 GLint aFirstElem = 0;
553 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
555 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
556 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
557 aFirstElem += aNbElemsInGroup;
562 glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
566 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
568 if (myDrawMode > GL_LINE_STRIP)
570 // Restore line context
571 theWorkspace->SetAspectLine (anAspectLineOld);
576 // =======================================================================
577 // function : drawMarkers
579 // =======================================================================
580 void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
582 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
583 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
584 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (theWorkspace);
585 const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT);
586 if (aCtx->IsGlGreaterEqual (2, 0)
587 && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList())
589 // Textured markers will be drawn with the point sprites
590 glPointSize (anAspectMarker->MarkerSize());
592 Handle(OpenGl_Texture) aTextureBack;
593 if (anAspectMarker->Type() != Aspect_TOM_POINT)
595 const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlightRes (theWorkspace)->IsValid())
596 ? anAspectMarker->SpriteHighlightRes (theWorkspace)
598 aTextureBack = theWorkspace->EnableTexture (aSprite);
600 glEnable (GL_ALPHA_TEST);
601 glAlphaFunc (GL_GEQUAL, 0.1f);
604 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
607 glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
609 glDisable (GL_BLEND);
610 glDisable (GL_ALPHA_TEST);
611 if (anAspectMarker->Type() != Aspect_TOM_POINT)
613 theWorkspace->EnableTexture (aTextureBack);
619 // Textured markers will be drawn with the glBitmap
620 if (anAspectMarker->Type() == Aspect_TOM_POINT
621 || anAspectMarker->Type() == Aspect_TOM_O_POINT)
623 const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT
624 ? anAspectMarker->MarkerSize()
628 glPointSize (aPntSize);
630 glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
637 if (anAspectMarker->Type() != Aspect_TOM_POINT
638 && !aSpriteNorm.IsNull())
640 /**if (!isHilight && (myPArray->vcolours != NULL))
642 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
644 glColor4ubv (myPArray->vcolours[anIter].GetData());
645 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
646 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
651 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
653 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
654 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
660 // =======================================================================
661 // function : OpenGl_PrimitiveArray
663 // =======================================================================
664 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
665 const Graphic3d_TypeOfPrimitiveArray theType,
666 const Handle(Graphic3d_IndexBuffer)& theIndices,
667 const Handle(Graphic3d_Buffer)& theAttribs,
668 const Handle(Graphic3d_BoundBuffer)& theBounds)
670 : myIndices (theIndices),
671 myAttribs (theAttribs),
672 myBounds (theBounds),
673 myDrawMode (DRAW_MODE_NONE),
674 myIsVboInit (Standard_False),
675 myUID (theDriver->GetNextPrimitiveArrayUID())
677 if (!myIndices.IsNull()
678 && myIndices->NbElements < 1)
680 // dummy index buffer?
683 if (myAttribs.IsNull())
690 case Graphic3d_TOPA_POINTS:
691 myDrawMode = GL_POINTS;
693 case Graphic3d_TOPA_POLYLINES:
694 myDrawMode = GL_LINE_STRIP;
696 case Graphic3d_TOPA_SEGMENTS:
697 myDrawMode = GL_LINES;
699 case Graphic3d_TOPA_POLYGONS:
700 myDrawMode = GL_POLYGON;
702 case Graphic3d_TOPA_TRIANGLES:
703 myDrawMode = GL_TRIANGLES;
705 case Graphic3d_TOPA_QUADRANGLES:
706 myDrawMode = GL_QUADS;
708 case Graphic3d_TOPA_TRIANGLESTRIPS:
709 myDrawMode = GL_TRIANGLE_STRIP;
711 case Graphic3d_TOPA_QUADRANGLESTRIPS:
712 myDrawMode = GL_QUAD_STRIP;
714 case Graphic3d_TOPA_TRIANGLEFANS:
715 myDrawMode = GL_TRIANGLE_FAN;
717 case Graphic3d_TOPA_UNDEFINED:
722 // =======================================================================
723 // function : ~OpenGl_PrimitiveArray
725 // =======================================================================
726 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
731 // =======================================================================
732 // function : Release
734 // =======================================================================
735 void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
737 if (!myVboIndices.IsNull())
741 theContext->DelayedRelease (myVboIndices);
743 myVboIndices.Nullify();
745 if (!myVboAttribs.IsNull())
749 theContext->DelayedRelease (myVboAttribs);
751 myVboAttribs.Nullify();
755 // =======================================================================
758 // =======================================================================
759 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
761 if (myDrawMode == DRAW_MODE_NONE)
766 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
767 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
768 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
770 // create VBOs on first render call
771 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
774 // compatibility - keep data to draw markers using display lists
775 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
776 && !anAspectMarker->SpriteRes (theWorkspace).IsNull()
777 && anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList();
778 buildVBO (aCtx, toKeepData);
779 myIsVboInit = Standard_True;
782 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
783 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
784 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
785 const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color();
787 // Use highlight colors
788 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
790 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
791 aFrontLightingModel = 0;
794 // Temporarily disable environment mapping
795 if (myDrawMode <= GL_LINE_STRIP)
797 glPushAttrib (GL_ENABLE_BIT);
798 glDisable (GL_TEXTURE_1D);
799 glDisable (GL_TEXTURE_2D);
801 // manage FFP lighting
802 if (aFrontLightingModel == 0
803 || myVboAttribs.IsNull()
804 || !myVboAttribs->HasNormalAttribute())
806 glDisable (GL_LIGHTING);
810 glEnable (GL_LIGHTING);
813 bindProgram (theWorkspace,
814 anAspectFace, anAspectLine, anAspectMarker,
817 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
818 (myDrawMode <= GL_LINE_STRIP))
820 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
821 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
824 glColor3fv (myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb);
826 drawArray (theWorkspace, aFaceColors);
829 if (myDrawMode > GL_LINE_STRIP)
831 if (anAspectFace->Edge()
832 || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
834 drawEdges (anEdgeColor, theWorkspace);
838 if (myDrawMode <= GL_LINE_STRIP)
842 aCtx->BindProgram (NULL);