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