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