0025974: Visualization - fix misprints in method naming of Graphic3d_GraduatedTrihedron
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
CommitLineData
b311480e 1// Created on: 2011-07-13
2// Created by: Sergey ZERCHANINOV
de75ed09 3// Copyright (c) 2011-2013 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
2166f0fa 16#include <OpenGl_AspectFace.hxx>
30f0ad28 17#include <OpenGl_Context.hxx>
2166f0fa 18#include <OpenGl_GraphicDriver.hxx>
30f0ad28 19#include <OpenGl_IndexBuffer.hxx>
a577aaab 20#include <OpenGl_PointSprite.hxx>
30f0ad28 21#include <OpenGl_PrimitiveArray.hxx>
22#include <OpenGl_ShaderManager.hxx>
23#include <OpenGl_ShaderProgram.hxx>
2166f0fa 24#include <OpenGl_Structure.hxx>
7d3e64ef 25#include <OpenGl_VertexBufferCompat.hxx>
bf75be98 26#include <OpenGl_Workspace.hxx>
6c6aadb1 27#include <Graphic3d_TextureParams.hxx>
2166f0fa 28
30f0ad28 29namespace
30{
871fa103 31 //! Convert index data type from size
32 inline GLenum toGlIndexType (const Standard_Integer theStride)
33 {
34 switch (theStride)
35 {
36 case 2: return GL_UNSIGNED_SHORT;
37 case 4: return GL_UNSIGNED_INT;
38 default: return GL_NONE;
39 }
40 }
41
42 //! Convert data type to GL info
43 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
44 GLint& theNbComp)
45 {
46 switch (theType)
47 {
48 case Graphic3d_TOD_USHORT:
49 theNbComp = 1;
50 return GL_UNSIGNED_SHORT;
51 case Graphic3d_TOD_UINT:
52 theNbComp = 1;
53 return GL_UNSIGNED_INT;
54 case Graphic3d_TOD_VEC2:
55 theNbComp = 2;
56 return GL_FLOAT;
57 case Graphic3d_TOD_VEC3:
58 theNbComp = 3;
59 return GL_FLOAT;
60 case Graphic3d_TOD_VEC4:
61 theNbComp = 4;
62 return GL_FLOAT;
63 case Graphic3d_TOD_VEC4UB:
64 theNbComp = 4;
65 return GL_UNSIGNED_BYTE;
66 }
67 theNbComp = 0;
68 return GL_NONE;
69 }
70
30f0ad28 71}
72
871fa103 73//! Auxiliary template for VBO with interleaved attributes.
7d3e64ef 74template<class TheBaseClass, int NbAttributes>
75class OpenGl_VertexBufferT : public TheBaseClass
7fd59977 76{
871fa103 77
78public:
79
80 //! Create uninitialized VBO.
81 OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
82 const Standard_Integer theStride)
83 : Stride (theStride)
84 {
85 memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
86 }
87
88 //! Create uninitialized VBO.
89 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
90 : Stride (theAttribs.Stride)
91 {
92 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
93 }
94
95 virtual bool HasColorAttribute() const
96 {
97 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
98 {
99 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
100 if (anAttrib.Id == Graphic3d_TOA_COLOR)
101 {
102 return true;
103 }
104 }
105 return false;
106 }
107
7d3e64ef 108 virtual bool HasNormalAttribute() const
109 {
110 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
111 {
112 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
113 if (anAttrib.Id == Graphic3d_TOA_NORM)
114 {
115 return true;
116 }
117 }
118 return false;
119 }
120
121 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 122 {
7d3e64ef 123 if (!TheBaseClass::IsValid())
871fa103 124 {
125 return;
126 }
127
7d3e64ef 128 TheBaseClass::Bind (theGlCtx);
871fa103 129 GLint aNbComp;
7d3e64ef 130 const GLubyte* anOffset = TheBaseClass::myOffset;
871fa103 131 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
132 {
133 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
134 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
135 if (aDataType == GL_NONE)
136 {
137 continue;
138 }
139 else if (anAttrib.Id == Graphic3d_TOA_POS)
140 {
7d3e64ef 141 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
871fa103 142 break;
143 }
144
145 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
146 }
147 }
148
7d3e64ef 149 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 150 {
7d3e64ef 151 if (!TheBaseClass::IsValid())
871fa103 152 {
153 return;
154 }
155
7d3e64ef 156 TheBaseClass::Bind (theGlCtx);
871fa103 157 GLint aNbComp;
7d3e64ef 158 const GLubyte* anOffset = TheBaseClass::myOffset;
871fa103 159 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
160 {
161 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
162 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
163 if (aDataType == GL_NONE)
164 {
165 continue;
166 }
167
7d3e64ef 168 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
871fa103 169 anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
170 }
171 }
172
7d3e64ef 173 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 174 {
7d3e64ef 175 if (!TheBaseClass::IsValid())
871fa103 176 {
177 return;
178 }
7d3e64ef 179 TheBaseClass::Unbind (theGlCtx);
871fa103 180
181 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
182 {
183 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
7d3e64ef 184 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
871fa103 185 }
186 }
187
188public:
189
190 Graphic3d_Attribute Attribs[NbAttributes];
191 Standard_Integer Stride;
192
193};
7fd59977 194
2166f0fa
SK
195// =======================================================================
196// function : clearMemoryGL
197// purpose :
198// =======================================================================
5e27df78 199void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
7fd59977 200{
871fa103 201 if (!myVboIndices.IsNull())
2166f0fa 202 {
871fa103 203 myVboIndices->Release (theGlCtx.operator->());
204 myVboIndices.Nullify();
205 }
206 if (!myVboAttribs.IsNull())
207 {
208 myVboAttribs->Release (theGlCtx.operator->());
209 myVboAttribs.Nullify();
2166f0fa 210 }
7fd59977 211}
212
2166f0fa 213// =======================================================================
7d3e64ef 214// function : initNormalVbo
2166f0fa
SK
215// purpose :
216// =======================================================================
7d3e64ef 217Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
7fd59977 218{
7d3e64ef 219 switch (myAttribs->NbAttributes)
2166f0fa 220 {
7d3e64ef 221 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
222 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
223 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
224 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
225 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
226 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
227 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
228 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
229 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
230 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
231 }
232
233 if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
234 {
235 TCollection_ExtendedString aMsg;
236 aMsg += "VBO creation for Primitive Array has failed for ";
237 aMsg += myAttribs->NbElements;
238 aMsg += " vertices. Out of memory?";
239 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
240
241 clearMemoryGL (theCtx);
5e27df78 242 return Standard_False;
2166f0fa 243 }
7d3e64ef 244 else if (myIndices.IsNull())
245 {
246 return Standard_True;
247 }
7fd59977 248
7d3e64ef 249 myVboIndices = new OpenGl_IndexBuffer();
250 bool isOk = false;
251 switch (myIndices->Stride)
252 {
253 case 2:
254 {
255 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
256 break;
257 }
258 case 4:
259 {
260 isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
261 break;
262 }
263 default:
264 {
265 clearMemoryGL (theCtx);
266 return Standard_False;
267 }
268 }
269 if (!isOk)
2166f0fa 270 {
7d3e64ef 271 TCollection_ExtendedString aMsg;
272 aMsg += "VBO creation for Primitive Array has failed for ";
273 aMsg += myIndices->NbElements;
274 aMsg += " indices. Out of memory?";
275 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
276 clearMemoryGL (theCtx);
277 return Standard_False;
7fd59977 278 }
7d3e64ef 279 return Standard_True;
280}
871fa103 281
7d3e64ef 282// =======================================================================
283// function : buildVBO
284// purpose :
285// =======================================================================
286Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
287 const Standard_Boolean theToKeepData) const
288{
289 bool isNormalMode = theCtx->ToUseVbo();
536d98e2 290 clearMemoryGL (theCtx);
7d3e64ef 291 if (myAttribs.IsNull()
292 || myAttribs->IsEmpty()
293 || myAttribs->NbElements < 1
294 || myAttribs->NbAttributes < 1
295 || myAttribs->NbAttributes > 10)
2166f0fa 296 {
7d3e64ef 297 // vertices should be always defined - others are optional
871fa103 298 return Standard_False;
7fd59977 299 }
871fa103 300
7d3e64ef 301 if (isNormalMode
302 && initNormalVbo (theCtx))
303 {
304 if (!theCtx->caps->keepArrayData
305 && !theToKeepData)
306 {
307 myIndices.Nullify();
308 myAttribs.Nullify();
309 }
310 return Standard_True;
311 }
312
313 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
314 switch (myAttribs->NbAttributes)
315 {
316 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
317 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
318 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
319 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
320 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
321 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
322 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
323 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
324 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
325 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
326 }
327 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
871fa103 328 if (!myIndices.IsNull())
2166f0fa 329 {
7d3e64ef 330 Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
871fa103 331 switch (myIndices->Stride)
5e27df78 332 {
871fa103 333 case 2:
334 {
7d3e64ef 335 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
871fa103 336 break;
337 }
338 case 4:
339 {
7d3e64ef 340 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
871fa103 341 break;
342 }
7d3e64ef 343 default:
344 {
345 return Standard_False;
346 }
5e27df78 347 }
7d3e64ef 348 myVboIndices = aVboIndices;
2166f0fa 349 }
7d3e64ef 350 myVboAttribs = aVboAttribs;
351 if (!theCtx->caps->keepArrayData
352 && !theToKeepData)
e276548b 353 {
7d3e64ef 354 // does not make sense for compatibility mode
355 //myIndices.Nullify();
356 //myAttribs.Nullify();
e276548b 357 }
7d3e64ef 358
2166f0fa 359 return Standard_True;
7fd59977 360}
361
2166f0fa 362// =======================================================================
7d3e64ef 363// function : drawArray
2166f0fa
SK
364// purpose :
365// =======================================================================
7d3e64ef 366void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
8625ef7e 367 const Graphic3d_Vec4* theFaceColors,
368 const Standard_Boolean theHasVertColor) const
7fd59977 369{
871fa103 370 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
871fa103 371 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
8625ef7e 372 bool hasVColors = theHasVertColor && !toHilight;
7d3e64ef 373 if (myVboAttribs.IsNull())
2166f0fa 374 {
ca3c13d1 375 #if !defined(GL_ES_VERSION_2_0)
7d3e64ef 376 if (myDrawMode == GL_POINTS)
377 {
378 // extreme compatibility mode - without sprites but with markers
379 drawMarkers (theWorkspace);
380 }
ca3c13d1 381 #endif
7d3e64ef 382 return;
7fd59977 383 }
384
7d3e64ef 385 myVboAttribs->BindAllAttributes (aGlContext);
8625ef7e 386 if (theHasVertColor && toHilight)
2166f0fa 387 {
8625ef7e 388 // disable per-vertex color
389 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
7d3e64ef 390 }
391 if (!myVboIndices.IsNull())
392 {
393 myVboIndices->Bind (aGlContext);
394 GLubyte* anOffset = myVboIndices->GetDataOffset();
395 if (!myBounds.IsNull())
2166f0fa 396 {
7d3e64ef 397 // draw primitives by vertex count with the indices
398 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
399 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 400 {
7d3e64ef 401 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 402 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
7d3e64ef 403 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
404 anOffset += aStride * aNbElemsInGroup;
762aacae 405 }
bf75be98 406 }
2166f0fa
SK
407 else
408 {
7d3e64ef 409 // draw one (or sequential) primitive by the indices
410 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
5e27df78 411 }
7d3e64ef 412 myVboIndices->Unbind (aGlContext);
7fd59977 413 }
7d3e64ef 414 else if (!myBounds.IsNull())
871fa103 415 {
7d3e64ef 416 GLint aFirstElem = 0;
417 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
418 {
419 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 420 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
7d3e64ef 421 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
422 aFirstElem += aNbElemsInGroup;
423 }
871fa103 424 }
7d3e64ef 425 else
2166f0fa 426 {
7d3e64ef 427 if (myDrawMode == GL_POINTS)
428 {
429 drawMarkers (theWorkspace);
430 }
431 else
432 {
433 glDrawArrays (myDrawMode, 0, myVboAttribs->GetElemsNb());
434 }
2166f0fa
SK
435 }
436
7d3e64ef 437 // bind with 0
438 myVboAttribs->UnbindAllAttributes (aGlContext);
439
440 if (hasVColors)
441 {
442 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT;
443 }
7fd59977 444}
445
2166f0fa 446// =======================================================================
7d3e64ef 447// function : drawEdges
2166f0fa
SK
448// purpose :
449// =======================================================================
7d3e64ef 450void OpenGl_PrimitiveArray::drawEdges (const TEL_COLOUR* theEdgeColour,
2166f0fa 451 const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 452{
65360da3 453 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
7d3e64ef 454 if (myVboAttribs.IsNull())
455 {
456 return;
457 }
458
ca3c13d1 459#if !defined(GL_ES_VERSION_2_0)
65360da3 460 if (aGlContext->core11 != NULL)
461 {
462 glDisable (GL_LIGHTING);
463 }
ca3c13d1 464#endif
7fd59977 465
2166f0fa 466 const OpenGl_AspectLine* anAspectLineOld = NULL;
7fd59977 467
7d3e64ef 468 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
469 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
30f0ad28 470
ca3c13d1 471#if !defined(GL_ES_VERSION_2_0)
7d3e64ef 472 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
ca3c13d1 473#endif
7d3e64ef 474
4e1523ef 475 if (aGlContext->core20fwd != NULL)
7d3e64ef 476 {
8625ef7e 477 aGlContext->ShaderManager()->BindProgram (anAspect, NULL, Standard_False, Standard_False, anAspect->ShaderProgramRes (aGlContext));
2166f0fa 478 }
7fd59977 479
5e27df78 480 /// OCC22236 NOTE: draw edges for all situations:
871fa103 481 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
482 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
5e27df78 483 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
7d3e64ef 484 myVboAttribs->BindPositionAttribute (aGlContext);
8625ef7e 485 aGlContext->SetColor4fv (*(const OpenGl_Vec4* )theEdgeColour->rgb);
7d3e64ef 486 if (!myVboIndices.IsNull())
bf75be98 487 {
7d3e64ef 488 myVboIndices->Bind (aGlContext);
489 GLubyte* anOffset = myVboIndices->GetDataOffset();
2166f0fa 490
7d3e64ef 491 // draw primitives by vertex count with the indices
492 if (!myBounds.IsNull())
2166f0fa 493 {
7d3e64ef 494 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
871fa103 495 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 496 {
871fa103 497 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
7d3e64ef 498 glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
499 anOffset += aStride * aNbElemsInGroup;
7fd59977 500 }
501 }
7d3e64ef 502 // draw one (or sequential) primitive by the indices
2166f0fa
SK
503 else
504 {
7d3e64ef 505 glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
762aacae 506 }
7d3e64ef 507 myVboIndices->Unbind (aGlContext);
2166f0fa 508 }
7d3e64ef 509 else if (!myBounds.IsNull())
2166f0fa 510 {
7d3e64ef 511 GLint aFirstElem = 0;
512 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 513 {
7d3e64ef 514 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
515 glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup);
516 aFirstElem += aNbElemsInGroup;
7fd59977 517 }
2166f0fa 518 }
7d3e64ef 519 else
520 {
521 glDrawArrays (myDrawMode, 0, myAttribs->NbElements);
522 }
523
524 // unbind buffers
525 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
2166f0fa 526
8625ef7e 527 // restore line context
8625ef7e 528 theWorkspace->SetAspectLine (anAspectLineOld);
7fd59977 529}
530
a577aaab 531// =======================================================================
7d3e64ef 532// function : drawMarkers
a577aaab 533// purpose :
534// =======================================================================
7d3e64ef 535void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
a577aaab 536{
537 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
538 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
8625ef7e 539 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
540 if (!aSpriteNorm.IsNull()
541 && !aSpriteNorm->IsDisplayList())
a577aaab 542 {
543 // Textured markers will be drawn with the point sprites
8625ef7e 544 aCtx->SetPointSize (anAspectMarker->MarkerSize());
ca3c13d1 545 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 546 if (aCtx->core11 != NULL)
547 {
548 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
549 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
550 }
ca3c13d1 551 #endif
a577aaab 552
8625ef7e 553 aCtx->core11fwd->glEnable (GL_BLEND);
554 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
a577aaab 555
8625ef7e 556 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
a577aaab 557
8625ef7e 558 aCtx->core11fwd->glDisable (GL_BLEND);
ca3c13d1 559 #if !defined(GL_ES_VERSION_2_0)
4e1523ef 560 if (aCtx->core11 != NULL)
561 {
562 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
563 }
ca3c13d1 564 #endif
8625ef7e 565 aCtx->SetPointSize (1.0f);
a577aaab 566 return;
567 }
8625ef7e 568 else if (anAspectMarker->Type() == Aspect_TOM_POINT)
a577aaab 569 {
8625ef7e 570 aCtx->SetPointSize (anAspectMarker->MarkerSize());
571 aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
572 aCtx->SetPointSize (1.0f);
a577aaab 573 }
ca3c13d1 574#if !defined(GL_ES_VERSION_2_0)
8625ef7e 575 // Textured markers will be drawn with the glBitmap
576 else if (anAspectMarker->Type() != Aspect_TOM_POINT
577 && !aSpriteNorm.IsNull())
a577aaab 578 {
871fa103 579 /**if (!isHilight && (myPArray->vcolours != NULL))
a577aaab 580 {
871fa103 581 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
a577aaab 582 {
871fa103 583 glColor4ubv (myPArray->vcolours[anIter].GetData());
584 glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
a577aaab 585 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
586 }
587 }
871fa103 588 else*/
a577aaab 589 {
871fa103 590 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
a577aaab 591 {
8625ef7e 592 aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
a577aaab 593 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
594 }
595 }
596 }
ca3c13d1 597#endif
a577aaab 598}
599
e1c659da 600// =======================================================================
601// function : OpenGl_PrimitiveArray
602// purpose :
603// =======================================================================
604OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
605
606: myDrawMode (DRAW_MODE_NONE),
607 myIsVboInit (Standard_False)
608{
609 if (theDriver != NULL)
610 {
611 myUID = theDriver->GetNextPrimitiveArrayUID();
612 }
613}
614
2166f0fa
SK
615// =======================================================================
616// function : OpenGl_PrimitiveArray
617// purpose :
618// =======================================================================
8d3f219f 619OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
620 const Graphic3d_TypeOfPrimitiveArray theType,
871fa103 621 const Handle(Graphic3d_IndexBuffer)& theIndices,
622 const Handle(Graphic3d_Buffer)& theAttribs,
623 const Handle(Graphic3d_BoundBuffer)& theBounds)
8d3f219f 624
871fa103 625: myIndices (theIndices),
626 myAttribs (theAttribs),
627 myBounds (theBounds),
628 myDrawMode (DRAW_MODE_NONE),
c827ea3a 629 myIsVboInit (Standard_False)
2166f0fa 630{
c827ea3a 631 if (theDriver != NULL)
632 {
633 myUID = theDriver->GetNextPrimitiveArrayUID();
634 }
635
871fa103 636 if (!myIndices.IsNull()
637 && myIndices->NbElements < 1)
638 {
639 // dummy index buffer?
640 myIndices.Nullify();
641 }
871fa103 642
a79f67f8 643 setDrawMode (theType);
2166f0fa
SK
644}
645
646// =======================================================================
647// function : ~OpenGl_PrimitiveArray
648// purpose :
649// =======================================================================
5e27df78 650OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
2166f0fa 651{
5e27df78 652 //
653}
2166f0fa 654
5e27df78 655// =======================================================================
656// function : Release
657// purpose :
658// =======================================================================
10b9c7df 659void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
5e27df78 660{
c827ea3a 661 myIsVboInit = Standard_False;
871fa103 662 if (!myVboIndices.IsNull())
2166f0fa 663 {
10b9c7df 664 if (theContext)
5e27df78 665 {
871fa103 666 theContext->DelayedRelease (myVboIndices);
667 }
668 myVboIndices.Nullify();
669 }
670 if (!myVboAttribs.IsNull())
671 {
10b9c7df 672 if (theContext)
871fa103 673 {
674 theContext->DelayedRelease (myVboAttribs);
5e27df78 675 }
871fa103 676 myVboAttribs.Nullify();
2166f0fa
SK
677 }
678}
679
680// =======================================================================
681// function : Render
682// purpose :
683// =======================================================================
684void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
685{
871fa103 686 if (myDrawMode == DRAW_MODE_NONE)
bf75be98 687 {
2166f0fa 688 return;
bf75be98 689 }
2166f0fa 690
a577aaab 691 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
692 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
693 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
694
2166f0fa 695 // create VBOs on first render call
58655684 696 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
7d3e64ef 697 if (!myIsVboInit)
2166f0fa 698 {
7d3e64ef 699 // compatibility - keep data to draw markers using display lists
700 const Standard_Boolean toKeepData = myDrawMode == GL_POINTS
8625ef7e 701 && !anAspectMarker->SpriteRes (aCtx).IsNull()
702 && anAspectMarker->SpriteRes (aCtx)->IsDisplayList();
7d3e64ef 703 buildVBO (aCtx, toKeepData);
5e27df78 704 myIsVboInit = Standard_True;
2166f0fa
SK
705 }
706
fd4a6963 707 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
708 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
2166f0fa 709 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
871fa103 710 const TEL_COLOUR* aLineColor = myDrawMode == GL_POINTS ? &anAspectMarker->Color() : &anAspectLine->Color();
2166f0fa
SK
711
712 // Use highlight colors
713 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
bf75be98 714 {
2166f0fa
SK
715 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
716 aFrontLightingModel = 0;
717 }
718
8625ef7e 719 const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull()
720 && myVboAttribs->HasColorAttribute();
721 const Standard_Boolean isLightOn = aFrontLightingModel != 0
722 && !myVboAttribs.IsNull()
723 && myVboAttribs->HasNormalAttribute();
ca3c13d1 724#if !defined(GL_ES_VERSION_2_0)
7d3e64ef 725 // manage FFP lighting
4e1523ef 726 if (aCtx->core11 != NULL)
7d3e64ef 727 {
4e1523ef 728 if (!isLightOn)
729 {
730 glDisable (GL_LIGHTING);
731 }
732 else
733 {
734 glEnable (GL_LIGHTING);
735 }
7d3e64ef 736 }
ca3c13d1 737#endif
8625ef7e 738 // Temporarily disable environment mapping
739 Handle(OpenGl_Texture) aTextureBack;
740 if (myDrawMode <= GL_LINE_STRIP)
741 {
742 aTextureBack = theWorkspace->DisableTexture();
743 }
7d3e64ef 744
745 if ((myDrawMode > GL_LINE_STRIP && anAspectFace->InteriorStyle() != Aspect_IS_EMPTY) ||
746 (myDrawMode <= GL_LINE_STRIP))
747 {
748 const bool toHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) != 0;
749 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->InteriorStyle() != Aspect_IS_HIDDENLINE
750 ? myBounds->Colors
751 : NULL;
8625ef7e 752 const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight;
4e1523ef 753 if (aCtx->core20fwd != NULL)
8625ef7e 754 {
755 switch (myDrawMode)
756 {
757 case GL_POINTS:
758 {
759 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx);
760 if (!aSpriteNorm.IsNull()
761 && !aSpriteNorm->IsDisplayList())
762 {
763 const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid())
764 ? anAspectMarker->SpriteHighlightRes (aCtx)
765 : aSpriteNorm;
766 theWorkspace->EnableTexture (aSprite);
767 aCtx->ShaderManager()->BindProgram (anAspectMarker, aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
768 }
769 else
770 {
771 aCtx->ShaderManager()->BindProgram (anAspectMarker, NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
772 }
773 break;
774 }
775 case GL_LINES:
776 case GL_LINE_STRIP:
777 {
778 aCtx->ShaderManager()->BindProgram (anAspectLine, NULL, isLightOn, hasVertColor, anAspectLine->ShaderProgramRes (aCtx));
779 break;
780 }
781 default:
782 {
6c6aadb1 783 const Standard_Boolean isLightOnFace = isLightOn
784 && (theWorkspace->ActiveTexture().IsNull()
785 || theWorkspace->ActiveTexture()->GetParams()->IsModulate());
786 aCtx->ShaderManager()->BindProgram (anAspectFace, theWorkspace->ActiveTexture(), isLightOnFace, hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
8625ef7e 787 break;
788 }
789 }
790 }
791
792 aCtx->SetColor4fv (*(const OpenGl_Vec4* )(myDrawMode <= GL_LINE_STRIP ? aLineColor->rgb : anInteriorColor->rgb));
7d3e64ef 793
8625ef7e 794 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
7d3e64ef 795 }
796
8625ef7e 797 if (myDrawMode <= GL_LINE_STRIP)
798 {
799 theWorkspace->EnableTexture (aTextureBack);
800 }
801 else
7d3e64ef 802 {
803 if (anAspectFace->Edge()
804 || anAspectFace->InteriorStyle() == Aspect_IS_HIDDENLINE)
30f0ad28 805 {
7d3e64ef 806 drawEdges (anEdgeColor, theWorkspace);
b34efb62 807
b34efb62 808 // restore OpenGL polygon mode if needed
65360da3 809 #if !defined(GL_ES_VERSION_2_0)
b34efb62 810 if (anAspectFace->InteriorStyle() >= Aspect_IS_HATCH)
811 {
812 glPolygonMode (GL_FRONT_AND_BACK,
813 anAspectFace->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL);
814 }
815 #endif
30f0ad28 816 }
817 }
818
7d3e64ef 819 aCtx->BindProgram (NULL);
2166f0fa 820}
a79f67f8 821
822// =======================================================================
823// function : setDrawMode
824// purpose :
825// =======================================================================
826void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
827{
828 if (myAttribs.IsNull())
829 {
830 myDrawMode = DRAW_MODE_NONE;
831 return;
832 }
833
834 switch (theType)
835 {
836 case Graphic3d_TOPA_POINTS:
837 myDrawMode = GL_POINTS;
838 break;
839 case Graphic3d_TOPA_POLYLINES:
840 myDrawMode = GL_LINE_STRIP;
841 break;
842 case Graphic3d_TOPA_SEGMENTS:
843 myDrawMode = GL_LINES;
844 break;
845 case Graphic3d_TOPA_TRIANGLES:
846 myDrawMode = GL_TRIANGLES;
847 break;
848 case Graphic3d_TOPA_TRIANGLESTRIPS:
849 myDrawMode = GL_TRIANGLE_STRIP;
850 break;
851 case Graphic3d_TOPA_TRIANGLEFANS:
852 myDrawMode = GL_TRIANGLE_FAN;
853 break;
854 #if !defined(GL_ES_VERSION_2_0)
855 case Graphic3d_TOPA_POLYGONS:
856 myDrawMode = GL_POLYGON;
857 break;
858 case Graphic3d_TOPA_QUADRANGLES:
859 myDrawMode = GL_QUADS;
860 break;
861 case Graphic3d_TOPA_QUADRANGLESTRIPS:
862 myDrawMode = GL_QUAD_STRIP;
863 break;
864 #else
865 case Graphic3d_TOPA_POLYGONS:
866 case Graphic3d_TOPA_QUADRANGLES:
867 case Graphic3d_TOPA_QUADRANGLESTRIPS:
868 #endif
869 case Graphic3d_TOPA_UNDEFINED:
870 break;
871 }
872}
873
874// =======================================================================
875// function : InitBuffers
876// purpose :
877// =======================================================================
878void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
879 const Graphic3d_TypeOfPrimitiveArray theType,
880 const Handle(Graphic3d_IndexBuffer)& theIndices,
881 const Handle(Graphic3d_Buffer)& theAttribs,
882 const Handle(Graphic3d_BoundBuffer)& theBounds)
883{
884 // Release old graphic resources
885 Release (theContext.operator->());
886
887 myIndices = theIndices;
888 myAttribs = theAttribs;
889 myBounds = theBounds;
890
891 setDrawMode (theType);
892}