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