0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[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
02a2beaa 16#include <OpenGl_PrimitiveArray.hxx>
17
a577aaab 18#include <OpenGl_PointSprite.hxx>
cc8cbabe 19#include <OpenGl_Sampler.hxx>
30f0ad28 20#include <OpenGl_ShaderManager.hxx>
21#include <OpenGl_ShaderProgram.hxx>
7d3e64ef 22#include <OpenGl_VertexBufferCompat.hxx>
6ef0d6f1 23#include <OpenGl_View.hxx>
bf75be98 24#include <OpenGl_Workspace.hxx>
2166f0fa 25
30f0ad28 26namespace
27{
871fa103 28 //! Convert data type to GL info
29 inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
30 GLint& theNbComp)
31 {
32 switch (theType)
33 {
34 case Graphic3d_TOD_USHORT:
35 theNbComp = 1;
36 return GL_UNSIGNED_SHORT;
37 case Graphic3d_TOD_UINT:
38 theNbComp = 1;
39 return GL_UNSIGNED_INT;
40 case Graphic3d_TOD_VEC2:
41 theNbComp = 2;
42 return GL_FLOAT;
43 case Graphic3d_TOD_VEC3:
44 theNbComp = 3;
45 return GL_FLOAT;
46 case Graphic3d_TOD_VEC4:
47 theNbComp = 4;
48 return GL_FLOAT;
49 case Graphic3d_TOD_VEC4UB:
50 theNbComp = 4;
51 return GL_UNSIGNED_BYTE;
4a535d3f 52 case Graphic3d_TOD_FLOAT:
53 theNbComp = 1;
54 return GL_FLOAT;
871fa103 55 }
56 theNbComp = 0;
57 return GL_NONE;
58 }
59
30f0ad28 60}
61
871fa103 62//! Auxiliary template for VBO with interleaved attributes.
7d3e64ef 63template<class TheBaseClass, int NbAttributes>
64class OpenGl_VertexBufferT : public TheBaseClass
7fd59977 65{
871fa103 66public:
67
871fa103 68 //! Create uninitialized VBO.
69 OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
da87ddc3 70 : Stride (theAttribs.IsInterleaved() ? theAttribs.Stride : 0)
871fa103 71 {
72 memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
73 }
74
75 virtual bool HasColorAttribute() const
76 {
77 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
78 {
79 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
80 if (anAttrib.Id == Graphic3d_TOA_COLOR)
81 {
82 return true;
83 }
84 }
85 return false;
86 }
87
7d3e64ef 88 virtual bool HasNormalAttribute() const
89 {
90 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
91 {
92 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
93 if (anAttrib.Id == Graphic3d_TOA_NORM)
94 {
95 return true;
96 }
97 }
98 return false;
99 }
100
101 virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 102 {
7d3e64ef 103 if (!TheBaseClass::IsValid())
871fa103 104 {
105 return;
106 }
107
7d3e64ef 108 TheBaseClass::Bind (theGlCtx);
871fa103 109 GLint aNbComp;
7d3e64ef 110 const GLubyte* anOffset = TheBaseClass::myOffset;
da87ddc3 111 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
871fa103 112 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
113 {
114 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
115 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
34253146 116 if (anAttrib.Id == Graphic3d_TOA_POS
117 && aDataType != GL_NONE)
871fa103 118 {
7d3e64ef 119 TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
871fa103 120 break;
121 }
122
da87ddc3 123 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
871fa103 124 }
125 }
126
7d3e64ef 127 virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 128 {
7d3e64ef 129 if (!TheBaseClass::IsValid())
871fa103 130 {
131 return;
132 }
133
7d3e64ef 134 TheBaseClass::Bind (theGlCtx);
871fa103 135 GLint aNbComp;
7d3e64ef 136 const GLubyte* anOffset = TheBaseClass::myOffset;
da87ddc3 137 const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
871fa103 138 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
139 {
140 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
141 const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
34253146 142 if (aDataType != GL_NONE)
871fa103 143 {
34253146 144 TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
871fa103 145 }
da87ddc3 146 anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
871fa103 147 }
148 }
149
7d3e64ef 150 virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
871fa103 151 {
7d3e64ef 152 if (!TheBaseClass::IsValid())
871fa103 153 {
154 return;
155 }
7d3e64ef 156 TheBaseClass::Unbind (theGlCtx);
871fa103 157
158 for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
159 {
160 const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
7d3e64ef 161 TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
871fa103 162 }
163 }
164
34253146 165private:
871fa103 166
167 Graphic3d_Attribute Attribs[NbAttributes];
168 Standard_Integer Stride;
169
170};
7fd59977 171
2166f0fa
SK
172// =======================================================================
173// function : clearMemoryGL
174// purpose :
175// =======================================================================
5e27df78 176void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
7fd59977 177{
871fa103 178 if (!myVboIndices.IsNull())
2166f0fa 179 {
871fa103 180 myVboIndices->Release (theGlCtx.operator->());
181 myVboIndices.Nullify();
182 }
183 if (!myVboAttribs.IsNull())
184 {
185 myVboAttribs->Release (theGlCtx.operator->());
186 myVboAttribs.Nullify();
2166f0fa 187 }
7fd59977 188}
189
2166f0fa 190// =======================================================================
7d3e64ef 191// function : initNormalVbo
2166f0fa
SK
192// purpose :
193// =======================================================================
7d3e64ef 194Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
7fd59977 195{
7d3e64ef 196 switch (myAttribs->NbAttributes)
2166f0fa 197 {
7d3e64ef 198 case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
199 case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
200 case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
201 case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
202 case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
203 case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
204 case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
205 case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
206 case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
207 case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
208 }
209
da87ddc3 210 const Standard_Boolean isAttribMutable = myAttribs->IsMutable();
211 const Standard_Boolean isAttribInterleaved = myAttribs->IsInterleaved();
212 if (myAttribs->NbElements != myAttribs->NbMaxElements()
213 && myIndices.IsNull()
214 && (!isAttribInterleaved || isAttribMutable))
215 {
216 throw Standard_ProgramError ("OpenGl_PrimitiveArray::buildVBO() - vertex attribute data with reserved size is not supported");
217 }
218
15669413 219 // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
da87ddc3 220 const Standard_Integer aNbVertexes = (isAttribMutable || !isAttribInterleaved) ? myAttribs->NbMaxElements() : myAttribs->NbElements;
221 if (!myVboAttribs->init (theCtx, myAttribs->Stride, aNbVertexes, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
7d3e64ef 222 {
da87ddc3 223 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbVertexes + " vertices. Out of memory?";
3b523c4c 224 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
7d3e64ef 225
226 clearMemoryGL (theCtx);
5e27df78 227 return Standard_False;
2166f0fa 228 }
7d3e64ef 229 else if (myIndices.IsNull())
230 {
da87ddc3 231 if (isAttribMutable && isAttribInterleaved)
232 {
233 // for mutable interlaced array we can change dynamically number of vertexes (they will be just skipped at the end of buffer);
234 // this doesn't matter in case if we have indexed array
235 myVboAttribs->SetElemsNb (myAttribs->NbElements);
236 }
7d3e64ef 237 return Standard_True;
238 }
7fd59977 239
da87ddc3 240 const Standard_Integer aNbIndexes = !myIndices->IsMutable() ? myIndices->NbElements : myIndices->NbMaxElements();
7d3e64ef 241 myVboIndices = new OpenGl_IndexBuffer();
242 bool isOk = false;
243 switch (myIndices->Stride)
244 {
245 case 2:
246 {
da87ddc3 247 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLushort*> (myIndices->Data()));
248 myVboIndices->SetElemsNb (myIndices->NbElements);
249 myIndices->Validate();
7d3e64ef 250 break;
251 }
252 case 4:
253 {
da87ddc3 254 isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLuint*> (myIndices->Data()));
255 myVboIndices->SetElemsNb (myIndices->NbElements);
256 myIndices->Validate();
7d3e64ef 257 break;
258 }
259 default:
260 {
261 clearMemoryGL (theCtx);
262 return Standard_False;
263 }
264 }
265 if (!isOk)
2166f0fa 266 {
da87ddc3 267 TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbIndexes + " indices. Out of memory?";
3b523c4c 268 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
7d3e64ef 269 clearMemoryGL (theCtx);
270 return Standard_False;
7fd59977 271 }
7d3e64ef 272 return Standard_True;
273}
871fa103 274
7d3e64ef 275// =======================================================================
276// function : buildVBO
277// purpose :
278// =======================================================================
279Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
280 const Standard_Boolean theToKeepData) const
281{
282 bool isNormalMode = theCtx->ToUseVbo();
536d98e2 283 clearMemoryGL (theCtx);
7d3e64ef 284 if (myAttribs.IsNull()
285 || myAttribs->IsEmpty()
286 || myAttribs->NbElements < 1
287 || myAttribs->NbAttributes < 1
288 || myAttribs->NbAttributes > 10)
2166f0fa 289 {
7d3e64ef 290 // vertices should be always defined - others are optional
871fa103 291 return Standard_False;
7fd59977 292 }
871fa103 293
7d3e64ef 294 if (isNormalMode
295 && initNormalVbo (theCtx))
296 {
297 if (!theCtx->caps->keepArrayData
da87ddc3 298 && !theToKeepData
299 && !myAttribs->IsMutable())
7d3e64ef 300 {
301 myIndices.Nullify();
302 myAttribs.Nullify();
303 }
da87ddc3 304 else
305 {
306 myAttribs->Validate();
307 }
7d3e64ef 308 return Standard_True;
309 }
310
311 Handle(OpenGl_VertexBufferCompat) aVboAttribs;
312 switch (myAttribs->NbAttributes)
313 {
314 case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
315 case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
316 case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
317 case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
318 case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
319 case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
320 case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
321 case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
322 case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
323 case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
324 }
325 aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
871fa103 326 if (!myIndices.IsNull())
2166f0fa 327 {
1220d98e 328 Handle(OpenGl_IndexBufferCompat) aVboIndices = new OpenGl_IndexBufferCompat();
871fa103 329 switch (myIndices->Stride)
5e27df78 330 {
871fa103 331 case 2:
332 {
7d3e64ef 333 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
871fa103 334 break;
335 }
336 case 4:
337 {
7d3e64ef 338 aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
871fa103 339 break;
340 }
7d3e64ef 341 default:
342 {
343 return Standard_False;
344 }
5e27df78 345 }
7d3e64ef 346 myVboIndices = aVboIndices;
2166f0fa 347 }
7d3e64ef 348 myVboAttribs = aVboAttribs;
349 if (!theCtx->caps->keepArrayData
350 && !theToKeepData)
e276548b 351 {
7d3e64ef 352 // does not make sense for compatibility mode
353 //myIndices.Nullify();
354 //myAttribs.Nullify();
e276548b 355 }
7d3e64ef 356
2166f0fa 357 return Standard_True;
7fd59977 358}
359
da87ddc3 360// =======================================================================
361// function : updateVBO
362// purpose :
363// =======================================================================
364void OpenGl_PrimitiveArray::updateVBO (const Handle(OpenGl_Context)& theCtx) const
365{
366 if (!myAttribs.IsNull())
367 {
368 Graphic3d_BufferRange aRange = myAttribs->InvalidatedRange();
369 if (!aRange.IsEmpty()
370 && myVboAttribs->IsValid()
371 && !myVboAttribs->IsVirtual())
372 {
373 myVboAttribs->Bind (theCtx);
374 theCtx->core15fwd->glBufferSubData (myVboAttribs->GetTarget(),
375 aRange.Start,
376 aRange.Length,
377 myAttribs->Data() + aRange.Start);
378 myVboAttribs->Unbind (theCtx);
379 if (myAttribs->IsInterleaved())
380 {
381 myVboAttribs->SetElemsNb (myAttribs->NbElements);
382 }
383 }
384 myAttribs->Validate();
385 }
386 if (!myIndices.IsNull())
387 {
388 Graphic3d_BufferRange aRange = myIndices->InvalidatedRange();
389 if (!aRange.IsEmpty()
390 && myVboIndices->IsValid()
391 && !myVboIndices->IsVirtual())
392 {
393 myVboIndices->Bind (theCtx);
394 theCtx->core15fwd->glBufferSubData (myVboIndices->GetTarget(),
395 aRange.Start,
396 aRange.Length,
397 myIndices->Data() + aRange.Start);
398 myVboIndices->Unbind (theCtx);
399 myVboIndices->SetElemsNb (myIndices->NbElements);
400 }
401 myIndices->Validate();
402 }
403}
404
2166f0fa 405// =======================================================================
7d3e64ef 406// function : drawArray
2166f0fa
SK
407// purpose :
408// =======================================================================
7d3e64ef 409void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
8625ef7e 410 const Graphic3d_Vec4* theFaceColors,
411 const Standard_Boolean theHasVertColor) const
7fd59977 412{
8f7159cb 413 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
7d3e64ef 414 if (myVboAttribs.IsNull())
2166f0fa 415 {
8f7159cb 416 if (myDrawMode == GL_POINTS
417 && aGlContext->core11ffp != NULL)
7d3e64ef 418 {
419 // extreme compatibility mode - without sprites but with markers
420 drawMarkers (theWorkspace);
421 }
422 return;
7fd59977 423 }
424
8f7159cb 425 const bool toHilight = theWorkspace->ToHighlight();
8e0a2b19 426 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
427 && aGlContext->ActiveProgram()->HasTessellationStage()
428 ? GL_PATCHES
429 : myDrawMode;
7d3e64ef 430 myVboAttribs->BindAllAttributes (aGlContext);
8625ef7e 431 if (theHasVertColor && toHilight)
2166f0fa 432 {
8625ef7e 433 // disable per-vertex color
434 OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
7d3e64ef 435 }
436 if (!myVboIndices.IsNull())
437 {
438 myVboIndices->Bind (aGlContext);
439 GLubyte* anOffset = myVboIndices->GetDataOffset();
440 if (!myBounds.IsNull())
2166f0fa 441 {
7d3e64ef 442 // draw primitives by vertex count with the indices
443 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
444 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 445 {
7d3e64ef 446 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 447 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
8f7159cb 448 aGlContext->core11fwd->glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
7d3e64ef 449 anOffset += aStride * aNbElemsInGroup;
762aacae 450 }
bf75be98 451 }
2166f0fa
SK
452 else
453 {
7d3e64ef 454 // draw one (or sequential) primitive by the indices
8f7159cb 455 aGlContext->core11fwd->glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
5e27df78 456 }
7d3e64ef 457 myVboIndices->Unbind (aGlContext);
7fd59977 458 }
7d3e64ef 459 else if (!myBounds.IsNull())
871fa103 460 {
7d3e64ef 461 GLint aFirstElem = 0;
462 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
463 {
464 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
8625ef7e 465 if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
8f7159cb 466 aGlContext->core11fwd->glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
7d3e64ef 467 aFirstElem += aNbElemsInGroup;
468 }
871fa103 469 }
7d3e64ef 470 else
2166f0fa 471 {
7d3e64ef 472 if (myDrawMode == GL_POINTS)
473 {
474 drawMarkers (theWorkspace);
475 }
476 else
477 {
8f7159cb 478 aGlContext->core11fwd->glDrawArrays (aDrawMode, 0, myVboAttribs->GetElemsNb());
7d3e64ef 479 }
2166f0fa
SK
480 }
481
7d3e64ef 482 // bind with 0
483 myVboAttribs->UnbindAllAttributes (aGlContext);
7fd59977 484}
485
2166f0fa 486// =======================================================================
7d3e64ef 487// function : drawEdges
2166f0fa
SK
488// purpose :
489// =======================================================================
bf5f0ca2 490void OpenGl_PrimitiveArray::drawEdges (const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 491{
65360da3 492 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
7d3e64ef 493 if (myVboAttribs.IsNull())
494 {
495 return;
496 }
497
bf5f0ca2 498 const OpenGl_Aspects* anAspect = theWorkspace->Aspects();
2a332745 499 const Standard_Integer aPolyModeOld = aGlContext->SetPolygonMode (GL_LINE);
7d3e64ef 500
4e1523ef 501 if (aGlContext->core20fwd != NULL)
7d3e64ef 502 {
bf5f0ca2 503 aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->EdgeLineType(),
13b36bb1 504 Graphic3d_TypeOfShadingModel_Unlit, Graphic3d_AlphaMode_Opaque, Standard_False,
b6472664 505 anAspect->ShaderProgramRes (aGlContext));
2166f0fa 506 }
bf5f0ca2 507 aGlContext->SetSampleAlphaToCoverage (aGlContext->ShaderManager()->MaterialState().HasAlphaCutoff());
8e0a2b19 508 const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
509 && aGlContext->ActiveProgram()->HasTessellationStage()
510 ? GL_PATCHES
511 : myDrawMode;
dd1ae9df 512 if (aGlContext->ActiveProgram().IsNull()
43eddb47 513 && aGlContext->core11ffp != NULL)
dd1ae9df 514 {
43eddb47 515 aGlContext->core11fwd->glDisable (GL_LIGHTING);
dd1ae9df 516 }
7fd59977 517
5e27df78 518 /// OCC22236 NOTE: draw edges for all situations:
871fa103 519 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
520 /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
5e27df78 521 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
7d3e64ef 522 myVboAttribs->BindPositionAttribute (aGlContext);
ac116c22 523
bf5f0ca2 524 aGlContext->SetColor4fv (theWorkspace->EdgeColor().a() >= 0.1f
525 ? theWorkspace->EdgeColor()
526 : theWorkspace->View()->BackgroundColor());
e0b24437 527 aGlContext->SetLineStipple((float )anAspect->Aspect()->LineStippleFactor(), anAspect->Aspect()->LinePattern());
bf5f0ca2 528 aGlContext->SetLineWidth (anAspect->Aspect()->EdgeWidth());
ac116c22 529
7d3e64ef 530 if (!myVboIndices.IsNull())
bf75be98 531 {
7d3e64ef 532 myVboIndices->Bind (aGlContext);
533 GLubyte* anOffset = myVboIndices->GetDataOffset();
2166f0fa 534
7d3e64ef 535 // draw primitives by vertex count with the indices
536 if (!myBounds.IsNull())
2166f0fa 537 {
7d3e64ef 538 const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
871fa103 539 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 540 {
871fa103 541 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
43eddb47 542 aGlContext->core11fwd->glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
7d3e64ef 543 anOffset += aStride * aNbElemsInGroup;
7fd59977 544 }
545 }
7d3e64ef 546 // draw one (or sequential) primitive by the indices
2166f0fa
SK
547 else
548 {
43eddb47 549 aGlContext->core11fwd->glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
762aacae 550 }
7d3e64ef 551 myVboIndices->Unbind (aGlContext);
2166f0fa 552 }
7d3e64ef 553 else if (!myBounds.IsNull())
2166f0fa 554 {
7d3e64ef 555 GLint aFirstElem = 0;
556 for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
2166f0fa 557 {
7d3e64ef 558 const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
43eddb47 559 aGlContext->core11fwd->glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
7d3e64ef 560 aFirstElem += aNbElemsInGroup;
7fd59977 561 }
2166f0fa 562 }
7d3e64ef 563 else
564 {
43eddb47 565 aGlContext->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
7d3e64ef 566 }
567
568 // unbind buffers
569 myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
2166f0fa 570
8625ef7e 571 // restore line context
2a332745 572 aGlContext->SetPolygonMode (aPolyModeOld);
7fd59977 573}
574
a577aaab 575// =======================================================================
7d3e64ef 576// function : drawMarkers
a577aaab 577// purpose :
578// =======================================================================
7d3e64ef 579void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
a577aaab 580{
bf5f0ca2 581 const OpenGl_Aspects* anAspectMarker = theWorkspace->Aspects();
737e9a8d 582 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
8e0a2b19 583 const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull()
584 && aCtx->ActiveProgram()->HasTessellationStage()
585 ? GL_PATCHES
586 : myDrawMode;
59500bb2 587 if (anAspectMarker->Aspect()->MarkerType() == Aspect_TOM_POINT)
a577aaab 588 {
8625ef7e 589 aCtx->SetPointSize (anAspectMarker->MarkerSize());
8e0a2b19 590 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
8625ef7e 591 aCtx->SetPointSize (1.0f);
a577aaab 592 return;
593 }
59500bb2 594
43eddb47 595 if (aCtx->core11ffp != NULL)
a577aaab 596 {
59500bb2 597 aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
598 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
599 }
8f7159cb 600
59500bb2 601 aCtx->core11fwd->glEnable (GL_BLEND);
602 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
603
604 if (anAspectMarker->HasPointSprite (aCtx))
605 {
606 // Textured markers will be drawn with the point sprites
8625ef7e 607 aCtx->SetPointSize (anAspectMarker->MarkerSize());
59500bb2 608 aCtx->SetPointSpriteOrigin();
609
8e0a2b19 610 aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
59500bb2 611
8625ef7e 612 aCtx->SetPointSize (1.0f);
a577aaab 613 }
8625ef7e 614 // Textured markers will be drawn with the glBitmap
59500bb2 615 else if (const Handle(OpenGl_PointSprite)& aSprite = anAspectMarker->SpriteRes (aCtx, theWorkspace->ToHighlight()))
a577aaab 616 {
59500bb2 617 for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
737e9a8d 618 {
43eddb47 619 aCtx->core11ffp->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
59500bb2 620 aSprite->DrawBitmap (theWorkspace->GetGlContext());
737e9a8d 621 }
59500bb2 622 }
737e9a8d 623
59500bb2 624 aCtx->core11fwd->glDisable (GL_BLEND);
43eddb47 625 if (aCtx->core11ffp != NULL)
59500bb2 626 {
627 if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast())
a577aaab 628 {
59500bb2 629 aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
a577aaab 630 }
59500bb2 631 else
a577aaab 632 {
59500bb2 633 aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff());
a577aaab 634 }
635 }
636}
637
e1c659da 638// =======================================================================
639// function : OpenGl_PrimitiveArray
640// purpose :
641// =======================================================================
642OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
643
644: myDrawMode (DRAW_MODE_NONE),
8e0a2b19 645 myIsFillType(Standard_False),
e1c659da 646 myIsVboInit (Standard_False)
647{
648 if (theDriver != NULL)
649 {
650 myUID = theDriver->GetNextPrimitiveArrayUID();
651 }
652}
653
2166f0fa
SK
654// =======================================================================
655// function : OpenGl_PrimitiveArray
656// purpose :
657// =======================================================================
8d3f219f 658OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
659 const Graphic3d_TypeOfPrimitiveArray theType,
871fa103 660 const Handle(Graphic3d_IndexBuffer)& theIndices,
661 const Handle(Graphic3d_Buffer)& theAttribs,
662 const Handle(Graphic3d_BoundBuffer)& theBounds)
8d3f219f 663
871fa103 664: myIndices (theIndices),
665 myAttribs (theAttribs),
666 myBounds (theBounds),
667 myDrawMode (DRAW_MODE_NONE),
8e0a2b19 668 myIsFillType(Standard_False),
c827ea3a 669 myIsVboInit (Standard_False)
2166f0fa 670{
871fa103 671 if (!myIndices.IsNull()
672 && myIndices->NbElements < 1)
673 {
674 // dummy index buffer?
675 myIndices.Nullify();
676 }
871fa103 677
e99a2f7c 678 if (theDriver != NULL)
679 {
680 myUID = theDriver->GetNextPrimitiveArrayUID();
e99a2f7c 681 const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
8f7159cb 682 if (!aCtx.IsNull()
683 && aCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES)
e99a2f7c 684 {
685 processIndices (aCtx);
686 }
e99a2f7c 687 }
688
a79f67f8 689 setDrawMode (theType);
2166f0fa
SK
690}
691
692// =======================================================================
693// function : ~OpenGl_PrimitiveArray
694// purpose :
695// =======================================================================
5e27df78 696OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
2166f0fa 697{
5e27df78 698 //
699}
2166f0fa 700
5e27df78 701// =======================================================================
702// function : Release
703// purpose :
704// =======================================================================
10b9c7df 705void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
5e27df78 706{
c827ea3a 707 myIsVboInit = Standard_False;
871fa103 708 if (!myVboIndices.IsNull())
2166f0fa 709 {
10b9c7df 710 if (theContext)
5e27df78 711 {
871fa103 712 theContext->DelayedRelease (myVboIndices);
713 }
714 myVboIndices.Nullify();
715 }
716 if (!myVboAttribs.IsNull())
717 {
10b9c7df 718 if (theContext)
871fa103 719 {
720 theContext->DelayedRelease (myVboAttribs);
5e27df78 721 }
871fa103 722 myVboAttribs.Nullify();
2166f0fa
SK
723 }
724}
725
3d60d73f 726// =======================================================================
727// function : EstimatedDataSize
728// purpose :
729// =======================================================================
730Standard_Size OpenGl_PrimitiveArray::EstimatedDataSize() const
731{
732 Standard_Size aSize = 0;
733 if (!myVboAttribs.IsNull())
734 {
735 aSize += myVboAttribs->EstimatedDataSize();
736 }
737 if (!myVboIndices.IsNull())
738 {
739 aSize += myVboIndices->EstimatedDataSize();
740 }
741 return aSize;
742}
743
b9f43ad1 744// =======================================================================
745// function : UpdateDrawStats
746// purpose :
747// =======================================================================
748void OpenGl_PrimitiveArray::UpdateDrawStats (Graphic3d_FrameStatsDataTmp& theStats,
749 bool theIsDetailed) const
750{
751 ++theStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled];
752 if (myIsFillType)
753 {
754 ++theStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled];
755 }
756 else if (myDrawMode == GL_POINTS)
757 {
758 ++theStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled];
759 }
760 else
761 {
762 ++theStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled];
763 }
764
765 if (!theIsDetailed
766 || myVboAttribs.IsNull()
767 || !myVboAttribs->IsValid())
768 {
769 return;
770 }
771
772 const Standard_Integer aNbIndices = !myVboIndices.IsNull() ? myVboIndices->GetElemsNb() : myVboAttribs->GetElemsNb();
773 const Standard_Integer aNbBounds = !myBounds.IsNull() ? myBounds->NbBounds : 1;
774 switch (myDrawMode)
775 {
776 case GL_POINTS:
777 {
778 theStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled] += aNbIndices;
779 break;
780 }
781 case GL_LINES:
782 {
783 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices / 2;
784 break;
785 }
786 case GL_LINE_STRIP:
787 {
788 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices - aNbBounds;
789 break;
790 }
791 case GL_LINES_ADJACENCY:
792 {
793 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices / 4;
794 break;
795 }
796 case GL_LINE_STRIP_ADJACENCY:
797 {
798 theStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled] += aNbIndices - 4 * aNbBounds;
799 break;
800 }
801 case GL_TRIANGLES:
802 {
803 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 3;
804 break;
805 }
806 case GL_TRIANGLE_STRIP:
807 case GL_TRIANGLE_FAN:
808 {
809 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 2 * aNbBounds;
810 break;
811 }
812 case GL_TRIANGLES_ADJACENCY:
813 {
814 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 6;
815 break;
816 }
817 case GL_TRIANGLE_STRIP_ADJACENCY:
818 {
819 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 4 * aNbBounds;
820 break;
821 }
b9f43ad1 822 case GL_QUADS:
823 {
824 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 2;
825 break;
826 }
827 case GL_QUAD_STRIP:
828 {
829 theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += (aNbIndices / 2 - aNbBounds) * 2;
830 break;
831 }
b9f43ad1 832 }
833}
834
2166f0fa
SK
835// =======================================================================
836// function : Render
837// purpose :
838// =======================================================================
839void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
840{
871fa103 841 if (myDrawMode == DRAW_MODE_NONE)
bf75be98 842 {
2166f0fa 843 return;
bf75be98 844 }
2166f0fa 845
72f6dc61 846 const OpenGl_Aspects* anAspectFace = theWorkspace->Aspects();
58655684 847 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
2166f0fa 848
72f6dc61 849 bool toDrawArray = true, toSetLinePolygMode = false;
2a332745 850 int toDrawInteriorEdges = 0; // 0 - no edges, 1 - glsl edges, 2 - polygonMode
6ef0d6f1 851 if (myIsFillType)
3a4a3962 852 {
853 toDrawArray = anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY;
2a332745 854 if (anAspectFace->Aspect()->ToDrawEdges())
855 {
856 toDrawInteriorEdges = 1;
857 toDrawArray = true;
8f7159cb 858 if (aCtx->GraphicsLibrary() != Aspect_GraphicsLibrary_OpenGLES
859 && (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID
860 || aCtx->hasGeometryStage == OpenGl_FeatureNotAvailable
861 || aCtx->caps->usePolygonMode))
2a332745 862 {
863 toDrawInteriorEdges = 2;
864 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_EMPTY)
865 {
866 if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID)
867 {
868 toDrawArray = false;
869 }
870 else
871 {
72f6dc61 872 toSetLinePolygMode = true;
2a332745 873 }
874 }
875 }
2a332745 876 }
3a4a3962 877 }
6ef0d6f1 878 else
8625ef7e 879 {
3a4a3962 880 if (myDrawMode == GL_POINTS)
881 {
bf5f0ca2 882 if (anAspectFace->Aspect()->MarkerType() == Aspect_TOM_EMPTY)
6ef0d6f1 883 {
884 return;
885 }
3a4a3962 886 }
887 else
888 {
bf5f0ca2 889 if (anAspectFace->Aspect()->LineType() == Aspect_TOL_EMPTY)
6ef0d6f1 890 {
891 return;
892 }
893 }
6ef0d6f1 894 }
895
896 // create VBOs on first render call
897 if (!myIsVboInit)
898 {
899 // compatibility - keep data to draw markers using display lists
737e9a8d 900 Standard_Boolean toKeepData = myDrawMode == GL_POINTS
901 && anAspectFace->IsDisplayListSprite (aCtx);
8f7159cb 902 if (aCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES)
903 {
904 processIndices (aCtx);
905 }
6ef0d6f1 906 buildVBO (aCtx, toKeepData);
907 myIsVboInit = Standard_True;
908 }
909 else if ((!myAttribs.IsNull()
910 && myAttribs->IsMutable())
911 || (!myIndices.IsNull()
912 && myIndices->IsMutable()))
913 {
914 updateVBO (aCtx);
8625ef7e 915 }
7d3e64ef 916
13b36bb1 917 Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TypeOfShadingModel_Unlit;
72f6dc61 918 anAspectFace = theWorkspace->ApplyAspects (false); // do not bind textures before binding the program
919 const Handle(OpenGl_TextureSet)& aTextureSet = theWorkspace->TextureSet();
920 const bool toEnableEnvMap = !aTextureSet.IsNull()
921 && aTextureSet == theWorkspace->EnvironmentTexture();
3a4a3962 922 if (toDrawArray)
7d3e64ef 923 {
db5d29de 924 const bool hasColorAttrib = !myVboAttribs.IsNull()
925 && myVboAttribs->HasColorAttribute();
926 const bool toHilight = theWorkspace->ToHighlight();
927 const bool hasVertColor = hasColorAttrib && !toHilight;
928 const bool hasVertNorm = !myVboAttribs.IsNull() && myVboAttribs->HasNormalAttribute();
8613985b 929 switch (myDrawMode)
8625ef7e 930 {
8613985b 931 case GL_POINTS:
8625ef7e 932 {
db5d29de 933 aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
72f6dc61 934 aCtx->ShaderManager()->BindMarkerProgram (aTextureSet,
737e9a8d 935 aShadingModel, Graphic3d_AlphaMode_Opaque,
936 hasVertColor, anAspectFace->ShaderProgramRes (aCtx));
8613985b 937 break;
938 }
939 case GL_LINES:
940 case GL_LINE_STRIP:
941 {
db5d29de 942 aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
737e9a8d 943 aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(),
bf5f0ca2 944 anAspectFace->Aspect()->LineType(),
dc89236f 945 aShadingModel,
c40eb6b9 946 Graphic3d_AlphaMode_Opaque,
8613985b 947 hasVertColor,
bf5f0ca2 948 anAspectFace->ShaderProgramRes (aCtx));
8613985b 949 break;
950 }
951 default:
952 {
db5d29de 953 aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
72f6dc61 954 aCtx->ShaderManager()->BindFaceProgram (aTextureSet,
dc89236f 955 aShadingModel,
2a332745 956 aCtx->ShaderManager()->MaterialState().HasAlphaCutoff() ? Graphic3d_AlphaMode_Mask : Graphic3d_AlphaMode_Opaque,
957 toDrawInteriorEdges == 1 ? anAspectFace->Aspect()->InteriorStyle() : Aspect_IS_SOLID,
8613985b 958 hasVertColor,
959 toEnableEnvMap,
2a332745 960 toDrawInteriorEdges == 1,
8613985b 961 anAspectFace->ShaderProgramRes (aCtx));
2a332745 962 if (toDrawInteriorEdges == 1)
963 {
964 aCtx->ShaderManager()->PushInteriorState (aCtx->ActiveProgram(), anAspectFace->Aspect());
965 }
72f6dc61 966 else if (toSetLinePolygMode)
967 {
968 aCtx->SetPolygonMode (GL_LINE);
969 }
8613985b 970 break;
8625ef7e 971 }
972 }
973
72f6dc61 974 // bind textures after GLSL program to set mock textures to slots used by program
975 aCtx->BindTextures (aTextureSet, aCtx->ActiveProgram());
976 if (!aTextureSet.IsNull()
977 && !aTextureSet->IsEmpty()
79f4f036 978 && myDrawMode != GL_POINTS) // transformation is not supported within point sprites
979 {
72f6dc61 980 if (const Handle(OpenGl_Texture)& aFirstTexture = aTextureSet->First())
981 {
faff3767 982 aCtx->SetTextureMatrix (aFirstTexture->Sampler()->Parameters(), aFirstTexture->IsTopDown());
72f6dc61 983 }
79f4f036 984 }
bf5f0ca2 985 aCtx->SetSampleAlphaToCoverage (aCtx->ShaderManager()->MaterialState().HasAlphaCutoff());
79f4f036 986
33425a46 987 const bool isForcedBlend = anAspectFace->Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend;
988 if (isForcedBlend)
989 {
990 aCtx->core11fwd->glEnable (GL_BLEND);
991 aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
992 }
993
6ef0d6f1 994 const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
995 ? myBounds->Colors
996 : NULL;
bf5f0ca2 997 const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
998 aCtx->SetColor4fv (anInteriorColor);
6ef0d6f1 999 if (!myIsFillType)
f9ba5c4d 1000 {
6ef0d6f1 1001 if (myDrawMode == GL_LINES
1002 || myDrawMode == GL_LINE_STRIP)
1003 {
e0b24437 1004 aCtx->SetLineStipple((float )anAspectFace->Aspect()->LineStippleFactor(), anAspectFace->Aspect()->LinePattern());
bf5f0ca2 1005 aCtx->SetLineWidth (anAspectFace->Aspect()->LineWidth());
6ef0d6f1 1006 }
1007
1008 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
33425a46 1009 if (isForcedBlend)
1010 {
1011 aCtx->core11fwd->glDisable (GL_BLEND);
1012 }
6ef0d6f1 1013 return;
ac116c22 1014 }
7d3e64ef 1015
8625ef7e 1016 drawArray (theWorkspace, aFaceColors, hasColorAttrib);
7d3e64ef 1017
6ef0d6f1 1018 // draw outline - only closed triangulation with defined vertex normals can be drawn in this way
1019 if (anAspectFace->Aspect()->ToDrawSilhouette()
1020 && aCtx->ToCullBackFaces()
1021 && aCtx->ShaderManager()->BindOutlineProgram())
1022 {
1023 const Graphic3d_Vec2i aViewSize (aCtx->Viewport()[2], aCtx->Viewport()[3]);
1024 const Standard_Integer aMin = aViewSize.minComp();
1025 const GLfloat anEdgeWidth = (GLfloat )anAspectFace->Aspect()->EdgeWidth() * aCtx->LineWidthScale() / (GLfloat )aMin;
008210c3 1026 const GLfloat anOrthoScale = aCtx->Camera()->IsOrthographic() ? (GLfloat )aCtx->Camera()->Scale() : -1.0f;
6ef0d6f1 1027
1028 const Handle(OpenGl_ShaderProgram)& anOutlineProgram = aCtx->ActiveProgram();
1029 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_SILHOUETTE_THICKNESS), anEdgeWidth);
1030 anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_ORTHO_SCALE), anOrthoScale);
1031 aCtx->SetColor4fv (anAspectFace->Aspect()->EdgeColorRGBA());
1032
9db675b3 1033 aCtx->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_FrontCulled);
6ef0d6f1 1034 drawArray (theWorkspace, NULL, false);
9db675b3 1035 aCtx->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled);
6ef0d6f1 1036 }
33425a46 1037
1038 if (isForcedBlend)
1039 {
1040 aCtx->core11fwd->glDisable (GL_BLEND);
1041 }
8625ef7e 1042 }
6ef0d6f1 1043
6ef0d6f1 1044 // draw triangulation edges using Polygon Mode
1045 if (toDrawInteriorEdges == 2)
7d3e64ef 1046 {
2a332745 1047 if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HOLLOW
1048 && anAspectFace->Aspect()->EdgeLineType() == Aspect_TOL_SOLID)
1049 {
1050 aCtx->SetPolygonMode (GL_FILL);
1051 }
1052 else
30f0ad28 1053 {
bf5f0ca2 1054 drawEdges (theWorkspace);
30f0ad28 1055 }
1056 }
2166f0fa 1057}
a79f67f8 1058
1059// =======================================================================
1060// function : setDrawMode
1061// purpose :
1062// =======================================================================
1063void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
1064{
1065 if (myAttribs.IsNull())
1066 {
1067 myDrawMode = DRAW_MODE_NONE;
8e0a2b19 1068 myIsFillType = false;
a79f67f8 1069 return;
1070 }
1071
1072 switch (theType)
1073 {
1074 case Graphic3d_TOPA_POINTS:
8e0a2b19 1075 myDrawMode = GL_POINTS;
1076 myIsFillType = false;
a79f67f8 1077 break;
1078 case Graphic3d_TOPA_SEGMENTS:
8e0a2b19 1079 myDrawMode = GL_LINES;
1080 myIsFillType = false;
1081 break;
1082 case Graphic3d_TOPA_POLYLINES:
1083 myDrawMode = GL_LINE_STRIP;
1084 myIsFillType = false;
a79f67f8 1085 break;
1086 case Graphic3d_TOPA_TRIANGLES:
8e0a2b19 1087 myDrawMode = GL_TRIANGLES;
1088 myIsFillType = true;
a79f67f8 1089 break;
1090 case Graphic3d_TOPA_TRIANGLESTRIPS:
8e0a2b19 1091 myDrawMode = GL_TRIANGLE_STRIP;
1092 myIsFillType = true;
a79f67f8 1093 break;
1094 case Graphic3d_TOPA_TRIANGLEFANS:
8e0a2b19 1095 myDrawMode = GL_TRIANGLE_FAN;
1096 myIsFillType = true;
a79f67f8 1097 break;
8e0a2b19 1098 //
1099 case Graphic3d_TOPA_LINES_ADJACENCY:
1100 myDrawMode = GL_LINES_ADJACENCY;
1101 myIsFillType = false;
a79f67f8 1102 break;
8e0a2b19 1103 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
1104 myDrawMode = GL_LINE_STRIP_ADJACENCY;
1105 myIsFillType = false;
1106 break;
1107 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
1108 myDrawMode = GL_TRIANGLES_ADJACENCY;
1109 myIsFillType = true;
1110 break;
1111 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
1112 myDrawMode = GL_TRIANGLE_STRIP_ADJACENCY;
1113 myIsFillType = true;
1114 break;
1115 //
a79f67f8 1116 case Graphic3d_TOPA_QUADRANGLES:
8e0a2b19 1117 myDrawMode = GL_QUADS;
1118 myIsFillType = true;
a79f67f8 1119 break;
1120 case Graphic3d_TOPA_QUADRANGLESTRIPS:
8e0a2b19 1121 myDrawMode = GL_QUAD_STRIP;
1122 myIsFillType = true;
a79f67f8 1123 break;
a79f67f8 1124 case Graphic3d_TOPA_POLYGONS:
8e0a2b19 1125 myDrawMode = GL_POLYGON;
1126 myIsFillType = true;
1127 break;
a79f67f8 1128 case Graphic3d_TOPA_UNDEFINED:
8e0a2b19 1129 myDrawMode = DRAW_MODE_NONE;
1130 myIsFillType = false;
a79f67f8 1131 break;
1132 }
1133}
1134
e99a2f7c 1135// =======================================================================
1136// function : processIndices
1137// purpose :
1138// =======================================================================
1139Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
1140{
1141 if (myIndices.IsNull()
09f30297 1142 || myAttribs.IsNull()
e99a2f7c 1143 || theContext->hasUintIndex)
1144 {
1145 return Standard_True;
1146 }
1147
09f30297 1148 if (myAttribs->NbElements > std::numeric_limits<GLushort>::max())
e99a2f7c 1149 {
02a2beaa 1150 Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (Graphic3d_Buffer::DefaultAllocator());
e99a2f7c 1151 if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
1152 {
1153 return Standard_False; // failed to initialize attribute array
1154 }
1155
1156 for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
1157 {
1158 const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
1159 memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
1160 myAttribs->Data() + myAttribs->Stride * anIndex,
1161 myAttribs->Stride);
1162 }
1163
1164 myIndices.Nullify();
1165 myAttribs = anAttribs;
1166 }
1167
1168 return Standard_True;
1169}
1170
a79f67f8 1171// =======================================================================
1172// function : InitBuffers
1173// purpose :
1174// =======================================================================
1175void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
1176 const Graphic3d_TypeOfPrimitiveArray theType,
1177 const Handle(Graphic3d_IndexBuffer)& theIndices,
1178 const Handle(Graphic3d_Buffer)& theAttribs,
1179 const Handle(Graphic3d_BoundBuffer)& theBounds)
1180{
1181 // Release old graphic resources
ad67e367 1182 Release (theContext.get());
a79f67f8 1183
1184 myIndices = theIndices;
1185 myAttribs = theAttribs;
1186 myBounds = theBounds;
8f7159cb 1187 if (!theContext.IsNull()
1188 && theContext->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES)
1189 {
1190 processIndices (theContext);
1191 }
a79f67f8 1192
1193 setDrawMode (theType);
1194}
bc73b006 1195
1196// =======================================================================
1197// function : DumpJson
1198// purpose :
1199// =======================================================================
1200void OpenGl_PrimitiveArray::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1201{
1202 OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_PrimitiveArray)
1203
1204 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Element)
1205
1206 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myVboIndices.get())
1207 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myVboAttribs.get())
1208
1209 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myIndices.get())
1210 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myAttribs.get())
1211 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myBounds.get())
1212
1213 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDrawMode)
1214 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsFillType)
1215 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsVboInit)
1216 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myUID)
1217}