Commit | Line | Data |
---|---|---|
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 | 30 | namespace |
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 | 67 | template<class TheBaseClass, int NbAttributes> |
68 | class OpenGl_VertexBufferT : public TheBaseClass | |
7fd59977 | 69 | { |
871fa103 | 70 | |
71 | public: | |
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 | ||
181 | public: | |
182 | ||
183 | Graphic3d_Attribute Attribs[NbAttributes]; | |
184 | Standard_Integer Stride; | |
185 | ||
186 | }; | |
7fd59977 | 187 | |
2166f0fa SK |
188 | // ======================================================================= |
189 | // function : clearMemoryGL | |
190 | // purpose : | |
191 | // ======================================================================= | |
5e27df78 | 192 | void 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 | 210 | Standard_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 | // ======================================================================= | |
279 | Standard_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 | 359 | void 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(); |
f9ba5c4d | 364 | const bool toHilight = theWorkspace->ToHighlight(); |
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 | // ======================================================================= | |
b6472664 | 443 | void OpenGl_PrimitiveArray::drawEdges (const OpenGl_Vec4& 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 | |
f9ba5c4d | 459 | const OpenGl_AspectLine* anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace()->AspectEdge()); |
460 | const OpenGl_AspectLine* anAspect = theWorkspace->ApplyAspectLine(); | |
30f0ad28 | 461 | |
ca3c13d1 | 462 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 463 | glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); |
ca3c13d1 | 464 | #endif |
7d3e64ef | 465 | |
4e1523ef | 466 | if (aGlContext->core20fwd != NULL) |
7d3e64ef | 467 | { |
b6472664 | 468 | aGlContext->ShaderManager()->BindLineProgram (NULL, |
469 | anAspect->Aspect()->Type() != Aspect_TOL_SOLID, | |
470 | Standard_False, | |
471 | Standard_False, | |
472 | anAspect->ShaderProgramRes (aGlContext)); | |
2166f0fa | 473 | } |
7fd59977 | 474 | |
5e27df78 | 475 | /// OCC22236 NOTE: draw edges for all situations: |
871fa103 | 476 | /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array |
477 | /// 2) draw elements from vertex array, when bounds defines count of primitive's vertices. | |
5e27df78 | 478 | /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified |
7d3e64ef | 479 | myVboAttribs->BindPositionAttribute (aGlContext); |
ac116c22 | 480 | |
b6472664 | 481 | aGlContext->SetColor4fv (theEdgeColour); |
482 | aGlContext->SetTypeOfLine (anAspect->Aspect()->Type()); | |
483 | aGlContext->SetLineWidth (anAspect->Aspect()->Width()); | |
ac116c22 | 484 | |
7d3e64ef | 485 | if (!myVboIndices.IsNull()) |
bf75be98 | 486 | { |
7d3e64ef | 487 | myVboIndices->Bind (aGlContext); |
488 | GLubyte* anOffset = myVboIndices->GetDataOffset(); | |
2166f0fa | 489 | |
7d3e64ef | 490 | // draw primitives by vertex count with the indices |
491 | if (!myBounds.IsNull()) | |
2166f0fa | 492 | { |
7d3e64ef | 493 | const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); |
871fa103 | 494 | for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter) |
2166f0fa | 495 | { |
871fa103 | 496 | const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter]; |
7d3e64ef | 497 | glDrawElements (myDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset); |
498 | anOffset += aStride * aNbElemsInGroup; | |
7fd59977 | 499 | } |
500 | } | |
7d3e64ef | 501 | // draw one (or sequential) primitive by the indices |
2166f0fa SK |
502 | else |
503 | { | |
7d3e64ef | 504 | glDrawElements (myDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset); |
762aacae | 505 | } |
7d3e64ef | 506 | myVboIndices->Unbind (aGlContext); |
2166f0fa | 507 | } |
7d3e64ef | 508 | else if (!myBounds.IsNull()) |
2166f0fa | 509 | { |
7d3e64ef | 510 | GLint aFirstElem = 0; |
511 | for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter) | |
2166f0fa | 512 | { |
7d3e64ef | 513 | const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter]; |
514 | glDrawArrays (myDrawMode, aFirstElem, aNbElemsInGroup); | |
515 | aFirstElem += aNbElemsInGroup; | |
7fd59977 | 516 | } |
2166f0fa | 517 | } |
7d3e64ef | 518 | else |
519 | { | |
b6472664 | 520 | glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements); |
7d3e64ef | 521 | } |
522 | ||
523 | // unbind buffers | |
524 | myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS); | |
2166f0fa | 525 | |
8625ef7e | 526 | // restore line context |
8625ef7e | 527 | theWorkspace->SetAspectLine (anAspectLineOld); |
7fd59977 | 528 | } |
529 | ||
a577aaab | 530 | // ======================================================================= |
7d3e64ef | 531 | // function : drawMarkers |
a577aaab | 532 | // purpose : |
533 | // ======================================================================= | |
7d3e64ef | 534 | void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const |
a577aaab | 535 | { |
f9ba5c4d | 536 | const OpenGl_AspectMarker* anAspectMarker = theWorkspace->ApplyAspectMarker(); |
a577aaab | 537 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
8625ef7e | 538 | const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx); |
539 | if (!aSpriteNorm.IsNull() | |
540 | && !aSpriteNorm->IsDisplayList()) | |
a577aaab | 541 | { |
542 | // Textured markers will be drawn with the point sprites | |
8625ef7e | 543 | aCtx->SetPointSize (anAspectMarker->MarkerSize()); |
fd59283a | 544 | aCtx->SetPointSpriteOrigin(); |
ca3c13d1 | 545 | #if !defined(GL_ES_VERSION_2_0) |
4e1523ef | 546 | if (aCtx->core11 != NULL) |
547 | { | |
548 | aCtx->core11fwd->glEnable (GL_ALPHA_TEST); | |
549 | aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f); | |
550 | } | |
ca3c13d1 | 551 | #endif |
a577aaab | 552 | |
8625ef7e | 553 | aCtx->core11fwd->glEnable (GL_BLEND); |
554 | aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
a577aaab | 555 | |
8625ef7e | 556 | aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements); |
a577aaab | 557 | |
8625ef7e | 558 | aCtx->core11fwd->glDisable (GL_BLEND); |
ca3c13d1 | 559 | #if !defined(GL_ES_VERSION_2_0) |
4e1523ef | 560 | if (aCtx->core11 != NULL) |
561 | { | |
562 | aCtx->core11fwd->glDisable (GL_ALPHA_TEST); | |
563 | } | |
ca3c13d1 | 564 | #endif |
8625ef7e | 565 | aCtx->SetPointSize (1.0f); |
a577aaab | 566 | return; |
567 | } | |
b6472664 | 568 | else if (anAspectMarker->Aspect()->Type() == Aspect_TOM_POINT) |
a577aaab | 569 | { |
8625ef7e | 570 | aCtx->SetPointSize (anAspectMarker->MarkerSize()); |
571 | aCtx->core11fwd->glDrawArrays (myDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements); | |
572 | aCtx->SetPointSize (1.0f); | |
a577aaab | 573 | } |
ca3c13d1 | 574 | #if !defined(GL_ES_VERSION_2_0) |
8625ef7e | 575 | // Textured markers will be drawn with the glBitmap |
b6472664 | 576 | else if (anAspectMarker->Aspect()->Type() != Aspect_TOM_POINT |
8625ef7e | 577 | && !aSpriteNorm.IsNull()) |
a577aaab | 578 | { |
871fa103 | 579 | /**if (!isHilight && (myPArray->vcolours != NULL)) |
a577aaab | 580 | { |
871fa103 | 581 | for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++) |
a577aaab | 582 | { |
871fa103 | 583 | glColor4ubv (myPArray->vcolours[anIter].GetData()); |
584 | glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData()); | |
a577aaab | 585 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); |
586 | } | |
587 | } | |
871fa103 | 588 | else*/ |
a577aaab | 589 | { |
871fa103 | 590 | for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++) |
a577aaab | 591 | { |
8625ef7e | 592 | aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData()); |
a577aaab | 593 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); |
594 | } | |
595 | } | |
596 | } | |
ca3c13d1 | 597 | #endif |
a577aaab | 598 | } |
599 | ||
e1c659da | 600 | // ======================================================================= |
601 | // function : OpenGl_PrimitiveArray | |
602 | // purpose : | |
603 | // ======================================================================= | |
604 | OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver) | |
605 | ||
606 | : myDrawMode (DRAW_MODE_NONE), | |
607 | myIsVboInit (Standard_False) | |
608 | { | |
609 | if (theDriver != NULL) | |
610 | { | |
611 | myUID = theDriver->GetNextPrimitiveArrayUID(); | |
612 | } | |
613 | } | |
614 | ||
2166f0fa SK |
615 | // ======================================================================= |
616 | // function : OpenGl_PrimitiveArray | |
617 | // purpose : | |
618 | // ======================================================================= | |
8d3f219f | 619 | OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver, |
620 | const Graphic3d_TypeOfPrimitiveArray theType, | |
871fa103 | 621 | const Handle(Graphic3d_IndexBuffer)& theIndices, |
622 | const Handle(Graphic3d_Buffer)& theAttribs, | |
623 | const Handle(Graphic3d_BoundBuffer)& theBounds) | |
8d3f219f | 624 | |
871fa103 | 625 | : myIndices (theIndices), |
626 | myAttribs (theAttribs), | |
627 | myBounds (theBounds), | |
628 | myDrawMode (DRAW_MODE_NONE), | |
c827ea3a | 629 | myIsVboInit (Standard_False) |
2166f0fa | 630 | { |
871fa103 | 631 | if (!myIndices.IsNull() |
632 | && myIndices->NbElements < 1) | |
633 | { | |
634 | // dummy index buffer? | |
635 | myIndices.Nullify(); | |
636 | } | |
871fa103 | 637 | |
e99a2f7c | 638 | if (theDriver != NULL) |
639 | { | |
640 | myUID = theDriver->GetNextPrimitiveArrayUID(); | |
641 | #if defined (GL_ES_VERSION_2_0) | |
642 | const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext(); | |
643 | if (!aCtx.IsNull()) | |
644 | { | |
645 | processIndices (aCtx); | |
646 | } | |
647 | #endif | |
648 | } | |
649 | ||
a79f67f8 | 650 | setDrawMode (theType); |
2166f0fa SK |
651 | } |
652 | ||
653 | // ======================================================================= | |
654 | // function : ~OpenGl_PrimitiveArray | |
655 | // purpose : | |
656 | // ======================================================================= | |
5e27df78 | 657 | OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray() |
2166f0fa | 658 | { |
5e27df78 | 659 | // |
660 | } | |
2166f0fa | 661 | |
5e27df78 | 662 | // ======================================================================= |
663 | // function : Release | |
664 | // purpose : | |
665 | // ======================================================================= | |
10b9c7df | 666 | void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext) |
5e27df78 | 667 | { |
c827ea3a | 668 | myIsVboInit = Standard_False; |
871fa103 | 669 | if (!myVboIndices.IsNull()) |
2166f0fa | 670 | { |
10b9c7df | 671 | if (theContext) |
5e27df78 | 672 | { |
871fa103 | 673 | theContext->DelayedRelease (myVboIndices); |
674 | } | |
675 | myVboIndices.Nullify(); | |
676 | } | |
677 | if (!myVboAttribs.IsNull()) | |
678 | { | |
10b9c7df | 679 | if (theContext) |
871fa103 | 680 | { |
681 | theContext->DelayedRelease (myVboAttribs); | |
5e27df78 | 682 | } |
871fa103 | 683 | myVboAttribs.Nullify(); |
2166f0fa SK |
684 | } |
685 | } | |
686 | ||
687 | // ======================================================================= | |
688 | // function : Render | |
689 | // purpose : | |
690 | // ======================================================================= | |
691 | void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const | |
692 | { | |
871fa103 | 693 | if (myDrawMode == DRAW_MODE_NONE) |
bf75be98 | 694 | { |
2166f0fa | 695 | return; |
bf75be98 | 696 | } |
2166f0fa | 697 | |
f9ba5c4d | 698 | const OpenGl_AspectFace* anAspectFace = theWorkspace->ApplyAspectFace(); |
699 | const OpenGl_AspectLine* anAspectLine = theWorkspace->ApplyAspectLine(); | |
700 | const OpenGl_AspectMarker* anAspectMarker = myDrawMode == GL_POINTS | |
701 | ? theWorkspace->ApplyAspectMarker() | |
702 | : theWorkspace->AspectMarker(); | |
a577aaab | 703 | |
2166f0fa | 704 | // create VBOs on first render call |
58655684 | 705 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
7d3e64ef | 706 | if (!myIsVboInit) |
2166f0fa | 707 | { |
7d3e64ef | 708 | // compatibility - keep data to draw markers using display lists |
709 | const Standard_Boolean toKeepData = myDrawMode == GL_POINTS | |
8625ef7e | 710 | && !anAspectMarker->SpriteRes (aCtx).IsNull() |
711 | && anAspectMarker->SpriteRes (aCtx)->IsDisplayList(); | |
e99a2f7c | 712 | #if defined (GL_ES_VERSION_2_0) |
713 | processIndices (aCtx); | |
714 | #endif | |
7d3e64ef | 715 | buildVBO (aCtx, toKeepData); |
5e27df78 | 716 | myIsVboInit = Standard_True; |
2166f0fa SK |
717 | } |
718 | ||
8625ef7e | 719 | const Standard_Boolean hasColorAttrib = !myVboAttribs.IsNull() |
720 | && myVboAttribs->HasColorAttribute(); | |
b6472664 | 721 | const Standard_Boolean isLightOn = !anAspectFace->IsNoLighting() |
722 | && !myVboAttribs.IsNull() | |
723 | && myVboAttribs->HasNormalAttribute(); | |
ca3c13d1 | 724 | #if !defined(GL_ES_VERSION_2_0) |
7d3e64ef | 725 | // manage FFP lighting |
4e1523ef | 726 | if (aCtx->core11 != NULL) |
7d3e64ef | 727 | { |
4e1523ef | 728 | if (!isLightOn) |
729 | { | |
730 | glDisable (GL_LIGHTING); | |
731 | } | |
732 | else | |
733 | { | |
734 | glEnable (GL_LIGHTING); | |
735 | } | |
7d3e64ef | 736 | } |
ca3c13d1 | 737 | #endif |
8625ef7e | 738 | // Temporarily disable environment mapping |
739 | Handle(OpenGl_Texture) aTextureBack; | |
740 | if (myDrawMode <= GL_LINE_STRIP) | |
741 | { | |
742 | aTextureBack = theWorkspace->DisableTexture(); | |
743 | } | |
7d3e64ef | 744 | |
b6472664 | 745 | if ((myDrawMode > GL_LINE_STRIP && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY) || |
7d3e64ef | 746 | (myDrawMode <= GL_LINE_STRIP)) |
747 | { | |
f9ba5c4d | 748 | const bool toHilight = theWorkspace->ToHighlight(); |
8625ef7e | 749 | const Standard_Boolean hasVertColor = hasColorAttrib && !toHilight; |
4e1523ef | 750 | if (aCtx->core20fwd != NULL) |
8625ef7e | 751 | { |
752 | switch (myDrawMode) | |
753 | { | |
754 | case GL_POINTS: | |
755 | { | |
756 | const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (aCtx); | |
757 | if (!aSpriteNorm.IsNull() | |
758 | && !aSpriteNorm->IsDisplayList()) | |
759 | { | |
760 | const Handle(OpenGl_PointSprite)& aSprite = (toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->IsValid()) | |
761 | ? anAspectMarker->SpriteHighlightRes (aCtx) | |
762 | : aSpriteNorm; | |
763 | theWorkspace->EnableTexture (aSprite); | |
299e0ab9 | 764 | aCtx->ShaderManager()->BindMarkerProgram (aSprite, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx)); |
8625ef7e | 765 | } |
766 | else | |
767 | { | |
299e0ab9 | 768 | aCtx->ShaderManager()->BindMarkerProgram (NULL, isLightOn, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx)); |
8625ef7e | 769 | } |
770 | break; | |
771 | } | |
772 | case GL_LINES: | |
773 | case GL_LINE_STRIP: | |
774 | { | |
b6472664 | 775 | aCtx->ShaderManager()->BindLineProgram (NULL, |
776 | anAspectLine->Aspect()->Type() != Aspect_TOL_SOLID, | |
777 | isLightOn, | |
778 | hasVertColor, | |
779 | anAspectLine->ShaderProgramRes (aCtx)); | |
8625ef7e | 780 | break; |
781 | } | |
782 | default: | |
783 | { | |
79f4f036 | 784 | const Handle(OpenGl_Texture)& aTexture = theWorkspace->ActiveTexture(); |
6c6aadb1 | 785 | const Standard_Boolean isLightOnFace = isLightOn |
79f4f036 | 786 | && (aTexture.IsNull() |
787 | || aTexture->GetParams()->IsModulate()); | |
83da37b1 | 788 | const Standard_Boolean toEnableEnvMap = (!aTexture.IsNull() && (aTexture == theWorkspace->EnvironmentTexture())); |
299e0ab9 | 789 | aCtx->ShaderManager()->BindFaceProgram (aTexture, |
790 | isLightOnFace, | |
791 | hasVertColor, | |
792 | toEnableEnvMap, | |
793 | anAspectFace->ShaderProgramRes (aCtx)); | |
8625ef7e | 794 | break; |
795 | } | |
796 | } | |
797 | } | |
798 | ||
299e0ab9 | 799 | // All primitives should gather material properties from the AspectFace in shading mode |
800 | if (isLightOn) | |
801 | { | |
b6472664 | 802 | aCtx->SetShadingMaterial (anAspectFace, theWorkspace->ToHighlight() ? theWorkspace->HighlightColor : NULL); |
299e0ab9 | 803 | } |
804 | ||
79f4f036 | 805 | if (!theWorkspace->ActiveTexture().IsNull() |
806 | && myDrawMode != GL_POINTS) // transformation is not supported within point sprites | |
807 | { | |
808 | aCtx->SetTextureMatrix (theWorkspace->ActiveTexture()->GetParams()); | |
809 | } | |
810 | ||
f9ba5c4d | 811 | if (myDrawMode <= GL_LINE_STRIP) |
812 | { | |
b6472664 | 813 | const OpenGl_Vec4& aLineColor = myDrawMode == GL_POINTS ? theWorkspace->MarkerColor() : theWorkspace->LineColor(); |
814 | aCtx->SetColor4fv (aLineColor); | |
f9ba5c4d | 815 | } |
816 | else | |
817 | { | |
b6472664 | 818 | const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor(); |
819 | aCtx->SetColor4fv (anInteriorColor); | |
f9ba5c4d | 820 | } |
ac116c22 | 821 | if (myDrawMode == GL_LINES |
822 | || myDrawMode == GL_LINE_STRIP) | |
823 | { | |
b6472664 | 824 | aCtx->SetTypeOfLine (anAspectLine->Aspect()->Type()); |
825 | aCtx->SetLineWidth (anAspectLine->Aspect()->Width()); | |
ac116c22 | 826 | } |
7d3e64ef | 827 | |
b6472664 | 828 | const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE |
f9ba5c4d | 829 | ? myBounds->Colors |
830 | : NULL; | |
8625ef7e | 831 | drawArray (theWorkspace, aFaceColors, hasColorAttrib); |
7d3e64ef | 832 | } |
833 | ||
8625ef7e | 834 | if (myDrawMode <= GL_LINE_STRIP) |
835 | { | |
836 | theWorkspace->EnableTexture (aTextureBack); | |
837 | } | |
838 | else | |
7d3e64ef | 839 | { |
b6472664 | 840 | if (anAspectFace->Aspect()->ToDrawEdges() |
841 | || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) | |
30f0ad28 | 842 | { |
b6472664 | 843 | const OpenGl_Vec4& anEdgeColor = theWorkspace->EdgeColor(); |
7d3e64ef | 844 | drawEdges (anEdgeColor, theWorkspace); |
b34efb62 | 845 | |
b34efb62 | 846 | // restore OpenGL polygon mode if needed |
65360da3 | 847 | #if !defined(GL_ES_VERSION_2_0) |
b6472664 | 848 | if (anAspectFace->Aspect()->InteriorStyle() >= Aspect_IS_HATCH) |
b34efb62 | 849 | { |
850 | glPolygonMode (GL_FRONT_AND_BACK, | |
b6472664 | 851 | anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_POINT ? GL_POINT : GL_FILL); |
b34efb62 | 852 | } |
853 | #endif | |
30f0ad28 | 854 | } |
855 | } | |
856 | ||
7d3e64ef | 857 | aCtx->BindProgram (NULL); |
2166f0fa | 858 | } |
a79f67f8 | 859 | |
860 | // ======================================================================= | |
861 | // function : setDrawMode | |
862 | // purpose : | |
863 | // ======================================================================= | |
864 | void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType) | |
865 | { | |
866 | if (myAttribs.IsNull()) | |
867 | { | |
868 | myDrawMode = DRAW_MODE_NONE; | |
869 | return; | |
870 | } | |
871 | ||
872 | switch (theType) | |
873 | { | |
874 | case Graphic3d_TOPA_POINTS: | |
875 | myDrawMode = GL_POINTS; | |
876 | break; | |
877 | case Graphic3d_TOPA_POLYLINES: | |
878 | myDrawMode = GL_LINE_STRIP; | |
879 | break; | |
880 | case Graphic3d_TOPA_SEGMENTS: | |
881 | myDrawMode = GL_LINES; | |
882 | break; | |
883 | case Graphic3d_TOPA_TRIANGLES: | |
884 | myDrawMode = GL_TRIANGLES; | |
885 | break; | |
886 | case Graphic3d_TOPA_TRIANGLESTRIPS: | |
887 | myDrawMode = GL_TRIANGLE_STRIP; | |
888 | break; | |
889 | case Graphic3d_TOPA_TRIANGLEFANS: | |
890 | myDrawMode = GL_TRIANGLE_FAN; | |
891 | break; | |
892 | #if !defined(GL_ES_VERSION_2_0) | |
893 | case Graphic3d_TOPA_POLYGONS: | |
894 | myDrawMode = GL_POLYGON; | |
895 | break; | |
896 | case Graphic3d_TOPA_QUADRANGLES: | |
897 | myDrawMode = GL_QUADS; | |
898 | break; | |
899 | case Graphic3d_TOPA_QUADRANGLESTRIPS: | |
900 | myDrawMode = GL_QUAD_STRIP; | |
901 | break; | |
902 | #else | |
903 | case Graphic3d_TOPA_POLYGONS: | |
904 | case Graphic3d_TOPA_QUADRANGLES: | |
905 | case Graphic3d_TOPA_QUADRANGLESTRIPS: | |
906 | #endif | |
907 | case Graphic3d_TOPA_UNDEFINED: | |
908 | break; | |
909 | } | |
910 | } | |
911 | ||
e99a2f7c | 912 | // ======================================================================= |
913 | // function : processIndices | |
914 | // purpose : | |
915 | // ======================================================================= | |
916 | Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const | |
917 | { | |
918 | if (myIndices.IsNull() | |
919 | || theContext->hasUintIndex) | |
920 | { | |
921 | return Standard_True; | |
922 | } | |
923 | ||
924 | if (myIndices->NbElements > std::numeric_limits<GLushort>::max()) | |
925 | { | |
926 | Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16)); | |
927 | if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes)) | |
928 | { | |
929 | return Standard_False; // failed to initialize attribute array | |
930 | } | |
931 | ||
932 | for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx) | |
933 | { | |
934 | const Standard_Integer anIndex = myIndices->Index (anIdxIdx); | |
935 | memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx, | |
936 | myAttribs->Data() + myAttribs->Stride * anIndex, | |
937 | myAttribs->Stride); | |
938 | } | |
939 | ||
940 | myIndices.Nullify(); | |
941 | myAttribs = anAttribs; | |
942 | } | |
943 | ||
944 | return Standard_True; | |
945 | } | |
946 | ||
a79f67f8 | 947 | // ======================================================================= |
948 | // function : InitBuffers | |
949 | // purpose : | |
950 | // ======================================================================= | |
951 | void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext, | |
952 | const Graphic3d_TypeOfPrimitiveArray theType, | |
953 | const Handle(Graphic3d_IndexBuffer)& theIndices, | |
954 | const Handle(Graphic3d_Buffer)& theAttribs, | |
955 | const Handle(Graphic3d_BoundBuffer)& theBounds) | |
956 | { | |
957 | // Release old graphic resources | |
958 | Release (theContext.operator->()); | |
959 | ||
960 | myIndices = theIndices; | |
961 | myAttribs = theAttribs; | |
962 | myBounds = theBounds; | |
e99a2f7c | 963 | #if defined(GL_ES_VERSION_2_0) |
964 | processIndices (theContext); | |
965 | #endif | |
a79f67f8 | 966 | |
967 | setDrawMode (theType); | |
968 | } |