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 | // |
973c2be1 | 7 | // This library is free software; you can redistribute it and / or modify it |
8 | // under the terms of the GNU Lesser General Public version 2.1 as published | |
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> |
bf75be98 | 25 | #include <OpenGl_Workspace.hxx> |
2166f0fa | 26 | |
7fd59977 | 27 | #include <InterfaceGraphic_PrimitiveArray.hxx> |
2166f0fa | 28 | |
30f0ad28 | 29 | namespace |
30 | { | |
31 | template<class T> | |
32 | void BindProgramWithMaterial (const Handle(OpenGl_Workspace)& theWS, | |
33 | const T* theAspect) | |
34 | { | |
35 | const Handle(OpenGl_Context)& aCtx = theWS->GetGlContext(); | |
36 | const Handle(OpenGl_ShaderProgram)& aProgram = theAspect->ShaderProgramRes (theWS); | |
37 | if (aProgram.IsNull()) | |
38 | { | |
39 | OpenGl_ShaderProgram::Unbind (aCtx); | |
40 | return; | |
41 | } | |
42 | aProgram->BindWithVariables (aCtx); | |
43 | ||
44 | const OpenGl_MaterialState* aMaterialState = aCtx->ShaderManager()->MaterialState (aProgram); | |
45 | if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect) | |
46 | { | |
47 | aCtx->ShaderManager()->UpdateMaterialStateTo (aProgram, theAspect); | |
48 | } | |
49 | ||
50 | aCtx->ShaderManager()->PushState (aProgram); | |
51 | } | |
52 | } | |
53 | ||
2166f0fa SK |
54 | // ======================================================================= |
55 | // function : clearMemoryOwn | |
56 | // purpose : | |
57 | // ======================================================================= | |
58 | void OpenGl_PrimitiveArray::clearMemoryOwn() const | |
7fd59977 | 59 | { |
547702a1 | 60 | Standard::Free (myPArray->edges); |
61 | Standard::Free (myPArray->vertices); | |
62 | Standard::Free (myPArray->vcolours); | |
63 | Standard::Free (myPArray->vnormals); | |
64 | Standard::Free (myPArray->vtexels); | |
65 | Standard::Free (myPArray->edge_vis); /// ??? | |
5e27df78 | 66 | |
67 | myPArray->edges = NULL; | |
68 | myPArray->vertices = NULL; | |
69 | myPArray->vcolours = NULL; | |
70 | myPArray->vnormals = NULL; | |
71 | myPArray->vtexels = NULL; | |
72 | myPArray->edge_vis = NULL; | |
7fd59977 | 73 | } |
74 | ||
2166f0fa SK |
75 | // ======================================================================= |
76 | // function : clearMemoryGL | |
77 | // purpose : | |
78 | // ======================================================================= | |
5e27df78 | 79 | void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const |
7fd59977 | 80 | { |
5e27df78 | 81 | for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter) |
2166f0fa | 82 | { |
5e27df78 | 83 | if (!myVbos[anIter].IsNull()) |
84 | { | |
85 | myVbos[anIter]->Release (theGlCtx.operator->()); | |
86 | myVbos[anIter].Nullify(); | |
87 | } | |
2166f0fa | 88 | } |
7fd59977 | 89 | } |
90 | ||
2166f0fa | 91 | // ======================================================================= |
5e27df78 | 92 | // function : BuildVBO |
2166f0fa SK |
93 | // purpose : |
94 | // ======================================================================= | |
5e27df78 | 95 | Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const |
7fd59977 | 96 | { |
5e27df78 | 97 | const Handle(OpenGl_Context)& aGlCtx = theWorkspace->GetGlContext(); |
98 | if (myPArray->vertices == NULL) | |
2166f0fa | 99 | { |
5e27df78 | 100 | // vertices should be always defined - others are optional |
101 | return Standard_False; | |
2166f0fa | 102 | } |
5e27df78 | 103 | myVbos[VBOVertices] = new OpenGl_VertexBuffer(); |
104 | if (!myVbos[VBOVertices]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vertices[0].xyz[0])) | |
2166f0fa | 105 | { |
5e27df78 | 106 | clearMemoryGL (aGlCtx); |
107 | return Standard_False; | |
2166f0fa | 108 | } |
7fd59977 | 109 | |
ee1e83b9 | 110 | if (myPArray->edges != NULL |
111 | && myPArray->num_edges > 0) | |
2166f0fa | 112 | { |
5e27df78 | 113 | myVbos[VBOEdges] = new OpenGl_IndexBuffer(); |
114 | if (!myVbos[VBOEdges]->Init (aGlCtx, 1, myPArray->num_edges, (GLuint* )myPArray->edges)) | |
115 | { | |
116 | clearMemoryGL (aGlCtx); | |
2166f0fa | 117 | return Standard_False; |
5e27df78 | 118 | } |
7fd59977 | 119 | } |
2166f0fa SK |
120 | if (myPArray->vcolours != NULL) |
121 | { | |
5e27df78 | 122 | myVbos[VBOVcolours] = new OpenGl_VertexBuffer(); |
123 | if (!myVbos[VBOVcolours]->Init (aGlCtx, 4, myPArray->num_vertexs, (GLubyte* )myPArray->vcolours)) | |
124 | { | |
125 | clearMemoryGL (aGlCtx); | |
2166f0fa | 126 | return Standard_False; |
5e27df78 | 127 | } |
7fd59977 | 128 | } |
2166f0fa SK |
129 | if (myPArray->vnormals != NULL) |
130 | { | |
5e27df78 | 131 | myVbos[VBOVnormals] = new OpenGl_VertexBuffer(); |
132 | if (!myVbos[VBOVnormals]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vnormals[0].xyz[0])) | |
133 | { | |
134 | clearMemoryGL (aGlCtx); | |
2166f0fa | 135 | return Standard_False; |
5e27df78 | 136 | } |
7fd59977 | 137 | } |
2166f0fa SK |
138 | if (myPArray->vtexels) |
139 | { | |
5e27df78 | 140 | myVbos[VBOVtexels] = new OpenGl_VertexBuffer(); |
141 | if (!myVbos[VBOVtexels]->Init (aGlCtx, 2, myPArray->num_vertexs, &myPArray->vtexels[0].xy[0])) | |
142 | { | |
143 | clearMemoryGL (aGlCtx); | |
2166f0fa | 144 | return Standard_False; |
5e27df78 | 145 | } |
2166f0fa | 146 | } |
7fd59977 | 147 | |
e276548b | 148 | if (!aGlCtx->caps->keepArrayData) |
149 | { | |
150 | clearMemoryOwn(); | |
151 | } | |
152 | ||
2166f0fa | 153 | return Standard_True; |
7fd59977 | 154 | } |
155 | ||
2166f0fa SK |
156 | // ======================================================================= |
157 | // function : DrawArray | |
158 | // purpose : | |
159 | // ======================================================================= | |
160 | void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel, | |
161 | const Aspect_InteriorStyle theInteriorStyle, | |
162 | Tint theEdgeFlag, | |
163 | const TEL_COLOUR* theInteriorColour, | |
164 | const TEL_COLOUR* theLineColour, | |
165 | const TEL_COLOUR* theEdgeColour, | |
166 | const OPENGL_SURF_PROP* theFaceProp, | |
167 | const Handle(OpenGl_Workspace)& theWorkspace) const | |
7fd59977 | 168 | { |
2166f0fa SK |
169 | const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext(); |
170 | ||
7fd59977 | 171 | Tint i,n; |
172 | Tint transp = 0; | |
2166f0fa SK |
173 | // Following pointers have been provided for performance improvement |
174 | tel_colour pfc = myPArray->fcolours; | |
175 | Tint* pvc = myPArray->vcolours; | |
176 | if (pvc != NULL) | |
177 | { | |
178 | for (i = 0; i < myPArray->num_vertexs; ++i) | |
179 | { | |
180 | transp = int(theFaceProp->trans * 255.0f); | |
bf75be98 | 181 | #if defined (sparc) || defined (__sparc__) || defined (__sparc) |
2166f0fa SK |
182 | pvc[i] = (pvc[i] & 0xffffff00); |
183 | pvc[i] += transp; | |
bf75be98 | 184 | #else |
2166f0fa | 185 | pvc[i] = (pvc[i] & 0x00ffffff); |
7fd59977 | 186 | pvc[i] += transp << 24; |
2166f0fa | 187 | #endif |
7fd59977 | 188 | } |
189 | } | |
7fd59977 | 190 | |
2166f0fa SK |
191 | switch (myPArray->type) |
192 | { | |
7fd59977 | 193 | case TelPointsArrayType: |
7fd59977 | 194 | case TelPolylinesArrayType: |
7fd59977 | 195 | case TelSegmentsArrayType: |
2166f0fa | 196 | glColor3fv (theLineColour->rgb); |
7fd59977 | 197 | break; |
198 | case TelPolygonsArrayType: | |
7fd59977 | 199 | case TelTrianglesArrayType: |
7fd59977 | 200 | case TelQuadranglesArrayType: |
7fd59977 | 201 | case TelTriangleStripsArrayType: |
7fd59977 | 202 | case TelQuadrangleStripsArrayType: |
7fd59977 | 203 | case TelTriangleFansArrayType: |
2166f0fa | 204 | glColor3fv (theInteriorColour->rgb); |
7fd59977 | 205 | break; |
566f8441 | 206 | case TelUnknownArrayType: |
207 | break; | |
7fd59977 | 208 | } |
209 | ||
2166f0fa SK |
210 | // Temporarily disable environment mapping |
211 | if (myDrawMode <= GL_LINE_STRIP) | |
212 | { | |
213 | glPushAttrib (GL_ENABLE_BIT); | |
214 | glDisable (GL_TEXTURE_1D); | |
215 | glDisable (GL_TEXTURE_2D); | |
7fd59977 | 216 | } |
217 | ||
de75ed09 | 218 | if ((myDrawMode > GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) || |
219 | (myDrawMode <= GL_LINE_STRIP)) | |
2166f0fa SK |
220 | { |
221 | if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) | |
222 | { | |
7fd59977 | 223 | pfc = NULL; |
224 | pvc = NULL; | |
225 | } | |
226 | ||
2166f0fa SK |
227 | if (theInteriorStyle == Aspect_IS_HIDDENLINE) |
228 | { | |
229 | theEdgeFlag = 1; | |
7fd59977 | 230 | pfc = NULL; |
231 | pvc = NULL; | |
232 | } | |
233 | ||
2166f0fa | 234 | // Sometimes the GL_LIGHTING mode is activated here |
bf75be98 | 235 | // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary |
2166f0fa SK |
236 | // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism* |
237 | if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP) | |
238 | glDisable (GL_LIGHTING); | |
239 | else | |
240 | glEnable (GL_LIGHTING); | |
241 | ||
5e27df78 | 242 | if (!toDrawVbo()) |
2166f0fa SK |
243 | { |
244 | if (myPArray->vertices != NULL) | |
245 | { | |
246 | glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices | |
247 | glEnableClientState (GL_VERTEX_ARRAY); | |
248 | } | |
249 | if (myPArray->vnormals != NULL) | |
250 | { | |
251 | glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals | |
252 | glEnableClientState (GL_NORMAL_ARRAY); | |
253 | } | |
254 | if (myPArray->vtexels != NULL) | |
255 | { | |
256 | glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates | |
257 | glEnableClientState (GL_TEXTURE_COORD_ARRAY); | |
258 | } | |
7fd59977 | 259 | |
a577aaab | 260 | if ((pvc != NULL) && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0) |
2166f0fa SK |
261 | { |
262 | glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc); // array of colors | |
263 | glEnableClientState (GL_COLOR_ARRAY); | |
264 | glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); | |
265 | glEnable (GL_COLOR_MATERIAL); | |
7fd59977 | 266 | } |
267 | } | |
5e27df78 | 268 | else |
2166f0fa SK |
269 | { |
270 | // Bindings concrete pointer in accordance with VBO buffer | |
5e27df78 | 271 | myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY); |
272 | if (!myVbos[VBOVnormals].IsNull()) | |
2166f0fa | 273 | { |
5e27df78 | 274 | myVbos[VBOVnormals]->BindFixed (aGlContext, GL_NORMAL_ARRAY); |
7fd59977 | 275 | } |
5e27df78 | 276 | if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0) |
2166f0fa | 277 | { |
5e27df78 | 278 | myVbos[VBOVtexels]->BindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY); |
7fd59977 | 279 | } |
a577aaab | 280 | if (!myVbos[VBOVcolours].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0) |
2166f0fa | 281 | { |
5e27df78 | 282 | myVbos[VBOVcolours]->BindFixed (aGlContext, GL_COLOR_ARRAY); |
283 | glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); | |
2166f0fa | 284 | glEnable (GL_COLOR_MATERIAL); |
7fd59977 | 285 | } |
286 | } | |
2166f0fa | 287 | |
5e27df78 | 288 | /// OCC22236 NOTE: draw for all situations: |
289 | /// 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array | |
290 | /// 2) draw elements from vertice array, when bounds defines count of primitive's verts. | |
291 | /// 3) draw primitive by vertexes if no edges and bounds array is specified | |
292 | if (toDrawVbo()) | |
2166f0fa | 293 | { |
5e27df78 | 294 | if (!myVbos[VBOEdges].IsNull()) |
2166f0fa | 295 | { |
5e27df78 | 296 | myVbos[VBOEdges]->Bind (aGlContext); |
2166f0fa SK |
297 | if (myPArray->num_bounds > 0) |
298 | { | |
299 | // draw primitives by vertex count with the indicies | |
300 | Tint* anOffset = NULL; | |
301 | for (i = 0; i < myPArray->num_bounds; ++i) | |
302 | { | |
7cc2d520 | 303 | if (pfc != NULL) glColor3fv (pfc[i].rgb); |
5e27df78 | 304 | glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), anOffset); |
bf75be98 | 305 | anOffset += myPArray->bounds[i]; |
762aacae A |
306 | } |
307 | } | |
2166f0fa SK |
308 | else |
309 | { | |
310 | // draw one (or sequential) primitive by the indicies | |
5e27df78 | 311 | glDrawElements (myDrawMode, myPArray->num_edges, myVbos[VBOEdges]->GetDataType(), NULL); |
762aacae | 312 | } |
5e27df78 | 313 | myVbos[VBOEdges]->Unbind (aGlContext); |
7fd59977 | 314 | } |
2166f0fa SK |
315 | else if (myPArray->num_bounds > 0) |
316 | { | |
317 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
318 | { | |
7cc2d520 | 319 | if (pfc != NULL) glColor3fv (pfc[i].rgb); |
2166f0fa SK |
320 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); |
321 | n += myPArray->bounds[i]; | |
7fd59977 | 322 | } |
323 | } | |
2166f0fa SK |
324 | else |
325 | { | |
a577aaab | 326 | if (myDrawMode == GL_POINTS) |
327 | { | |
328 | DrawMarkers (theWorkspace); | |
329 | } | |
330 | else | |
331 | { | |
332 | glDrawArrays (myDrawMode, 0, myVbos[VBOVertices]->GetElemsNb()); | |
333 | } | |
762aacae A |
334 | } |
335 | ||
2166f0fa | 336 | // bind with 0 |
5e27df78 | 337 | myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY); |
338 | if (!myVbos[VBOVnormals].IsNull()) | |
339 | { | |
340 | myVbos[VBOVnormals]->UnbindFixed (aGlContext, GL_NORMAL_ARRAY); | |
341 | } | |
342 | if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0) | |
343 | { | |
344 | myVbos[VBOVtexels]->UnbindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY); | |
345 | } | |
346 | if (!myVbos[VBOVcolours].IsNull()) | |
347 | { | |
348 | myVbos[VBOVcolours]->UnbindFixed (aGlContext, GL_COLOR_ARRAY); | |
349 | glDisable (GL_COLOR_MATERIAL); | |
350 | theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material | |
351 | } | |
bf75be98 | 352 | } |
2166f0fa SK |
353 | else |
354 | { | |
355 | if (myPArray->num_bounds > 0) | |
356 | { | |
357 | if (myPArray->num_edges > 0) | |
358 | { | |
359 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
360 | { | |
361 | if (pfc != NULL) glColor3fv (pfc[i].rgb); | |
5e27df78 | 362 | glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]); |
2166f0fa SK |
363 | n += myPArray->bounds[i]; |
364 | } | |
365 | } | |
366 | else | |
367 | { | |
368 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
369 | { | |
7cc2d520 | 370 | if (pfc != NULL) glColor3fv (pfc[i].rgb); |
5e27df78 | 371 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); |
2166f0fa SK |
372 | n += myPArray->bounds[i]; |
373 | } | |
7fd59977 | 374 | } |
2166f0fa SK |
375 | } |
376 | else if (myPArray->num_edges > 0) | |
377 | { | |
5e27df78 | 378 | glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges); |
2166f0fa SK |
379 | } |
380 | else | |
381 | { | |
a577aaab | 382 | if (myDrawMode == GL_POINTS) |
383 | { | |
384 | DrawMarkers (theWorkspace); | |
385 | } | |
386 | else | |
387 | { | |
388 | glDrawArrays (myDrawMode, 0, myPArray->num_vertexs); | |
389 | } | |
2166f0fa | 390 | } |
7fd59977 | 391 | |
5e27df78 | 392 | if (pvc != NULL) |
393 | { | |
394 | glDisable (GL_COLOR_MATERIAL); | |
395 | theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material | |
396 | } | |
2166f0fa | 397 | |
2166f0fa | 398 | glDisableClientState (GL_VERTEX_ARRAY); |
5e27df78 | 399 | if (myPArray->vcolours != NULL) |
400 | glDisableClientState (GL_COLOR_ARRAY); | |
401 | if (myPArray->vnormals != NULL) | |
402 | glDisableClientState (GL_NORMAL_ARRAY); | |
403 | if (myPArray->vtexels != NULL) | |
404 | glDisableClientState (GL_TEXTURE_COORD_ARRAY); | |
405 | } | |
7fd59977 | 406 | } |
407 | ||
de75ed09 | 408 | // On some NVIDIA graphic cards, using glEdgeFlagPointer() in |
409 | // combination with VBO (edge flag data put into a VBO buffer) | |
410 | // leads to a crash in a driver. Therefore, edge flags are simply | |
411 | // igonored when VBOs are enabled, so all the edges are drawn if | |
412 | // edge visibility is turned on. In order to draw edges selectively, | |
413 | // either disable VBO or turn off edge visibilty in the current | |
414 | // primitive array and create a separate primitive array (segments) | |
415 | // and put edges to be drawn into it. | |
416 | if (theEdgeFlag && myDrawMode > GL_LINE_STRIP) | |
2166f0fa | 417 | { |
de75ed09 | 418 | DrawEdges (theEdgeColour, theWorkspace); |
2166f0fa SK |
419 | } |
420 | ||
421 | if (myDrawMode <= GL_LINE_STRIP) | |
7fd59977 | 422 | glPopAttrib(); |
423 | } | |
424 | ||
2166f0fa SK |
425 | // ======================================================================= |
426 | // function : DrawEdges | |
427 | // purpose : | |
428 | // ======================================================================= | |
429 | void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR* theEdgeColour, | |
430 | const Handle(OpenGl_Workspace)& theWorkspace) const | |
7fd59977 | 431 | { |
2166f0fa | 432 | glDisable (GL_LIGHTING); |
7fd59977 | 433 | |
2166f0fa SK |
434 | const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext(); |
435 | const OpenGl_AspectLine* anAspectLineOld = NULL; | |
436 | if (myDrawMode > GL_LINE_STRIP) | |
437 | { | |
438 | anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge()); | |
30f0ad28 | 439 | const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True); |
7fd59977 | 440 | |
2166f0fa SK |
441 | glPushAttrib (GL_POLYGON_BIT); |
442 | glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); | |
30f0ad28 | 443 | |
444 | if (aGlContext->IsGlGreaterEqual (2, 0)) | |
445 | { | |
446 | BindProgramWithMaterial (theWorkspace, anAspect); | |
447 | } | |
2166f0fa | 448 | } |
7fd59977 | 449 | |
2166f0fa | 450 | Tint i, j, n; |
7fd59977 | 451 | |
5e27df78 | 452 | /// OCC22236 NOTE: draw edges for all situations: |
453 | /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array | |
454 | /// 2) draw elements from vertice array, when bounds defines count of primitive's verts. | |
455 | /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified | |
456 | if (toDrawVbo()) | |
bf75be98 | 457 | { |
5e27df78 | 458 | myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY); |
2166f0fa | 459 | glColor3fv (theEdgeColour->rgb); |
5e27df78 | 460 | if (!myVbos[VBOEdges].IsNull()) |
2166f0fa | 461 | { |
5e27df78 | 462 | myVbos[VBOEdges]->Bind (aGlContext); |
2166f0fa | 463 | |
762aacae | 464 | // draw primitives by vertex count with the indicies |
2166f0fa SK |
465 | if (myPArray->num_bounds > 0) |
466 | { | |
762aacae | 467 | Tint* offset = 0; |
2166f0fa SK |
468 | for (i = 0, offset = 0; i < myPArray->num_bounds; ++i) |
469 | { | |
5e27df78 | 470 | glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), offset); |
2166f0fa | 471 | offset += myPArray->bounds[i]; |
762aacae A |
472 | } |
473 | } | |
474 | // draw one (or sequential) primitive by the indicies | |
2166f0fa SK |
475 | else |
476 | { | |
5e27df78 | 477 | glDrawElements (myDrawMode, myVbos[VBOEdges]->GetElemsNb(), myVbos[VBOEdges]->GetDataType(), NULL); |
762aacae | 478 | } |
5e27df78 | 479 | myVbos[VBOEdges]->Unbind (aGlContext); |
7fd59977 | 480 | } |
2166f0fa SK |
481 | else if (myPArray->num_bounds > 0) |
482 | { | |
483 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
484 | { | |
485 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); | |
486 | n += myPArray->bounds[i]; | |
7fd59977 | 487 | } |
488 | } | |
2166f0fa SK |
489 | else |
490 | { | |
491 | glDrawArrays (myDrawMode, 0, myPArray->num_vertexs); | |
762aacae A |
492 | } |
493 | ||
494 | // unbind buffers | |
5e27df78 | 495 | myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY); |
2166f0fa SK |
496 | } |
497 | else | |
498 | { | |
499 | glEnableClientState (GL_VERTEX_ARRAY); | |
500 | glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices | |
2166f0fa SK |
501 | |
502 | glColor3fv (theEdgeColour->rgb); | |
503 | if (myPArray->num_bounds > 0) | |
504 | { | |
505 | if (myPArray->num_edges > 0) | |
506 | { | |
507 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
508 | { | |
509 | if (myPArray->edge_vis) | |
510 | { | |
511 | glBegin (myDrawMode); | |
512 | for (j = 0; j < myPArray->bounds[i]; ++j) | |
513 | { | |
514 | glEdgeFlag (myPArray->edge_vis[n+j]); | |
515 | glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]); | |
516 | } | |
517 | glEnd(); | |
7fd59977 | 518 | } |
2166f0fa SK |
519 | else |
520 | { | |
5e27df78 | 521 | glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]); |
7fd59977 | 522 | } |
2166f0fa | 523 | n += myPArray->bounds[i]; |
7fd59977 | 524 | } |
2166f0fa | 525 | } |
7fd59977 | 526 | else |
2166f0fa SK |
527 | { |
528 | for (i = n = 0 ; i < myPArray->num_bounds; ++i) | |
529 | { | |
5e27df78 | 530 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); |
2166f0fa SK |
531 | n += myPArray->bounds[i]; |
532 | } | |
533 | } | |
bf75be98 | 534 | } |
2166f0fa SK |
535 | else if (myPArray->num_edges > 0) |
536 | { | |
537 | if (myPArray->edge_vis) | |
538 | { | |
539 | glBegin (myDrawMode); | |
540 | for (i = 0; i < myPArray->num_edges; ++i) | |
541 | { | |
542 | glEdgeFlag (myPArray->edge_vis[i]); | |
543 | glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]); | |
544 | } | |
545 | glEnd(); | |
546 | } | |
7fd59977 | 547 | else |
2166f0fa | 548 | { |
5e27df78 | 549 | glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges); |
7fd59977 | 550 | } |
551 | } | |
2166f0fa SK |
552 | else |
553 | { | |
5e27df78 | 554 | glDrawArrays (myDrawMode, 0, myPArray->num_vertexs); |
7fd59977 | 555 | } |
2166f0fa SK |
556 | } |
557 | ||
558 | if (myDrawMode > GL_LINE_STRIP) | |
559 | { | |
560 | // Restore line context | |
561 | theWorkspace->SetAspectLine (anAspectLineOld); | |
7fd59977 | 562 | glPopAttrib(); |
563 | } | |
564 | } | |
565 | ||
a577aaab | 566 | // ======================================================================= |
567 | // function : DrawMarkers | |
568 | // purpose : | |
569 | // ======================================================================= | |
570 | void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const | |
571 | { | |
572 | const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True); | |
573 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); | |
30f0ad28 | 574 | const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (theWorkspace); |
a577aaab | 575 | const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT); |
576 | if (aCtx->IsGlGreaterEqual (2, 0) | |
577 | && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList()) | |
578 | { | |
579 | // Textured markers will be drawn with the point sprites | |
580 | glPointSize (anAspectMarker->MarkerSize()); | |
581 | ||
582 | Handle(OpenGl_Texture) aTextureBack; | |
583 | if (anAspectMarker->Type() != Aspect_TOM_POINT) | |
584 | { | |
30f0ad28 | 585 | const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlightRes (theWorkspace)->IsValid()) |
586 | ? anAspectMarker->SpriteHighlightRes (theWorkspace) | |
a577aaab | 587 | : aSpriteNorm; |
588 | aTextureBack = theWorkspace->EnableTexture (aSprite); | |
589 | ||
590 | glEnable (GL_ALPHA_TEST); | |
591 | glAlphaFunc (GL_GEQUAL, 0.1f); | |
592 | ||
593 | glEnable (GL_BLEND); | |
594 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
595 | } | |
596 | ||
597 | glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs); | |
598 | ||
599 | glDisable (GL_BLEND); | |
600 | glDisable (GL_ALPHA_TEST); | |
601 | if (anAspectMarker->Type() != Aspect_TOM_POINT) | |
602 | { | |
603 | theWorkspace->EnableTexture (aTextureBack); | |
604 | } | |
605 | glPointSize (1.0f); | |
606 | return; | |
607 | } | |
608 | ||
609 | // Textured markers will be drawn with the glBitmap | |
a577aaab | 610 | if (anAspectMarker->Type() == Aspect_TOM_POINT |
611 | || anAspectMarker->Type() == Aspect_TOM_O_POINT) | |
612 | { | |
abe46077 | 613 | const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT |
614 | ? anAspectMarker->MarkerSize() | |
615 | : 0.0f; | |
616 | if (aPntSize > 0.0f) | |
617 | { | |
618 | glPointSize (aPntSize); | |
619 | } | |
a577aaab | 620 | glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs); |
abe46077 | 621 | if (aPntSize > 0.0f) |
622 | { | |
623 | glPointSize (1.0f); | |
624 | } | |
a577aaab | 625 | } |
626 | ||
627 | if (anAspectMarker->Type() != Aspect_TOM_POINT | |
628 | && !aSpriteNorm.IsNull()) | |
629 | { | |
630 | if (!isHilight && (myPArray->vcolours != NULL)) | |
631 | { | |
632 | for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++) | |
633 | { | |
634 | glColor4ubv ((GLubyte* )&myPArray->vcolours[anIter]); | |
635 | glRasterPos3fv (myPArray->vertices[anIter].xyz); | |
636 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); | |
637 | } | |
638 | } | |
639 | else | |
640 | { | |
641 | for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++) | |
642 | { | |
643 | glRasterPos3fv (myPArray->vertices[anIter].xyz); | |
644 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); | |
645 | } | |
646 | } | |
647 | } | |
648 | } | |
649 | ||
2166f0fa SK |
650 | // ======================================================================= |
651 | // function : OpenGl_PrimitiveArray | |
652 | // purpose : | |
653 | // ======================================================================= | |
654 | OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray) | |
655 | : myPArray (thePArray), | |
5e27df78 | 656 | myDrawMode (DRAW_MODE_NONE), |
657 | myIsVboInit (Standard_False) | |
2166f0fa SK |
658 | { |
659 | switch (myPArray->type) | |
660 | { | |
661 | case TelPointsArrayType: | |
662 | myDrawMode = GL_POINTS; | |
663 | break; | |
664 | case TelPolylinesArrayType: | |
665 | myDrawMode = GL_LINE_STRIP; | |
666 | break; | |
667 | case TelSegmentsArrayType: | |
668 | myDrawMode = GL_LINES; | |
669 | break; | |
670 | case TelPolygonsArrayType: | |
671 | myDrawMode = GL_POLYGON; | |
672 | break; | |
673 | case TelTrianglesArrayType: | |
674 | myDrawMode = GL_TRIANGLES; | |
675 | break; | |
676 | case TelQuadranglesArrayType: | |
677 | myDrawMode = GL_QUADS; | |
678 | break; | |
679 | case TelTriangleStripsArrayType: | |
680 | myDrawMode = GL_TRIANGLE_STRIP; | |
681 | break; | |
682 | case TelQuadrangleStripsArrayType: | |
683 | myDrawMode = GL_QUAD_STRIP; | |
684 | break; | |
685 | case TelTriangleFansArrayType: | |
686 | myDrawMode = GL_TRIANGLE_FAN; | |
687 | break; | |
566f8441 | 688 | case TelUnknownArrayType: |
689 | break; | |
2166f0fa SK |
690 | } |
691 | } | |
692 | ||
693 | // ======================================================================= | |
694 | // function : ~OpenGl_PrimitiveArray | |
695 | // purpose : | |
696 | // ======================================================================= | |
5e27df78 | 697 | OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray() |
2166f0fa | 698 | { |
5e27df78 | 699 | // |
700 | } | |
2166f0fa | 701 | |
5e27df78 | 702 | // ======================================================================= |
703 | // function : Release | |
704 | // purpose : | |
705 | // ======================================================================= | |
706 | void OpenGl_PrimitiveArray::Release (const Handle(OpenGl_Context)& theContext) | |
707 | { | |
708 | for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter) | |
2166f0fa | 709 | { |
5e27df78 | 710 | if (!myVbos[anIter].IsNull()) |
711 | { | |
dd8a4ce9 | 712 | if (!theContext.IsNull()) |
713 | { | |
714 | theContext->DelayedRelease (myVbos[anIter]); | |
715 | } | |
5e27df78 | 716 | myVbos[anIter].Nullify(); |
717 | } | |
2166f0fa SK |
718 | } |
719 | } | |
720 | ||
721 | // ======================================================================= | |
722 | // function : Render | |
723 | // purpose : | |
724 | // ======================================================================= | |
725 | void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const | |
726 | { | |
5e27df78 | 727 | if (myPArray == NULL || myDrawMode == DRAW_MODE_NONE || myPArray->num_vertexs <= 0) |
bf75be98 | 728 | { |
2166f0fa | 729 | return; |
bf75be98 | 730 | } |
2166f0fa | 731 | |
a577aaab | 732 | const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True); |
733 | const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True); | |
734 | const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS); | |
735 | ||
2166f0fa | 736 | // create VBOs on first render call |
58655684 | 737 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
a577aaab | 738 | if (!myIsVboInit |
739 | && !aCtx->caps->vboDisable | |
740 | && aCtx->core15 != NULL | |
30f0ad28 | 741 | && (myDrawMode != GL_POINTS || anAspectMarker->SpriteRes (theWorkspace).IsNull() || !anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList())) |
2166f0fa | 742 | { |
cbf18624 | 743 | if (!BuildVBO (theWorkspace)) |
744 | { | |
745 | TCollection_ExtendedString aMsg; | |
746 | aMsg += "VBO creation for Primitive Array has failed for "; | |
747 | aMsg += myPArray->num_vertexs; | |
748 | aMsg += " vertices. Out of memory?"; | |
749 | aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg); | |
750 | } | |
5e27df78 | 751 | myIsVboInit = Standard_True; |
2166f0fa SK |
752 | } |
753 | ||
754 | switch (myPArray->type) | |
755 | { | |
756 | case TelPointsArrayType: | |
757 | case TelPolylinesArrayType: | |
758 | case TelSegmentsArrayType: | |
759 | { | |
760 | glDisable (GL_LIGHTING); | |
2166f0fa SK |
761 | break; |
762 | } | |
763 | default: | |
764 | break; | |
765 | } | |
766 | ||
fd4a6963 | 767 | Tint aFrontLightingModel = anAspectFace->IntFront().color_mask; |
768 | const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol; | |
2166f0fa | 769 | const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color(); |
17f65eb2 | 770 | const TEL_COLOUR* aLineColor = (myPArray->type == TelPointsArrayType) ? &anAspectMarker->Color() : &anAspectLine->Color(); |
2166f0fa SK |
771 | |
772 | // Use highlight colors | |
773 | if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) | |
bf75be98 | 774 | { |
2166f0fa SK |
775 | anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor; |
776 | aFrontLightingModel = 0; | |
777 | } | |
778 | ||
30f0ad28 | 779 | if (aCtx->IsGlGreaterEqual (2, 0)) |
780 | { | |
781 | switch (myPArray->type) | |
782 | { | |
783 | case TelPointsArrayType: | |
784 | { | |
785 | BindProgramWithMaterial (theWorkspace, anAspectMarker); | |
786 | break; | |
787 | } | |
788 | case TelSegmentsArrayType: | |
789 | case TelPolylinesArrayType: | |
790 | { | |
791 | BindProgramWithMaterial (theWorkspace, anAspectLine); | |
792 | break; | |
793 | } | |
794 | default: // polygonal array | |
795 | { | |
796 | BindProgramWithMaterial (theWorkspace, anAspectFace); | |
797 | break; | |
798 | } | |
799 | } | |
800 | } | |
801 | ||
2166f0fa | 802 | DrawArray (aFrontLightingModel, |
fd4a6963 | 803 | anAspectFace->InteriorStyle(), |
804 | anAspectFace->Edge(), | |
2166f0fa SK |
805 | anInteriorColor, |
806 | aLineColor, | |
807 | anEdgeColor, | |
fd4a6963 | 808 | &anAspectFace->IntFront(), |
2166f0fa | 809 | theWorkspace); |
2166f0fa | 810 | } |