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; |
7fd59977 | 210 | } |
211 | ||
2166f0fa SK |
212 | // Temporarily disable environment mapping |
213 | if (myDrawMode <= GL_LINE_STRIP) | |
214 | { | |
215 | glPushAttrib (GL_ENABLE_BIT); | |
216 | glDisable (GL_TEXTURE_1D); | |
217 | glDisable (GL_TEXTURE_2D); | |
7fd59977 | 218 | } |
219 | ||
de75ed09 | 220 | if ((myDrawMode > GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) || |
221 | (myDrawMode <= GL_LINE_STRIP)) | |
2166f0fa SK |
222 | { |
223 | if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) | |
224 | { | |
7fd59977 | 225 | pfc = NULL; |
226 | pvc = NULL; | |
227 | } | |
228 | ||
2166f0fa SK |
229 | if (theInteriorStyle == Aspect_IS_HIDDENLINE) |
230 | { | |
231 | theEdgeFlag = 1; | |
7fd59977 | 232 | pfc = NULL; |
233 | pvc = NULL; | |
234 | } | |
235 | ||
2166f0fa | 236 | // Sometimes the GL_LIGHTING mode is activated here |
bf75be98 | 237 | // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary |
2166f0fa SK |
238 | // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism* |
239 | if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP) | |
240 | glDisable (GL_LIGHTING); | |
241 | else | |
242 | glEnable (GL_LIGHTING); | |
243 | ||
5e27df78 | 244 | if (!toDrawVbo()) |
2166f0fa SK |
245 | { |
246 | if (myPArray->vertices != NULL) | |
247 | { | |
248 | glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices | |
249 | glEnableClientState (GL_VERTEX_ARRAY); | |
250 | } | |
251 | if (myPArray->vnormals != NULL) | |
252 | { | |
253 | glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals | |
254 | glEnableClientState (GL_NORMAL_ARRAY); | |
255 | } | |
256 | if (myPArray->vtexels != NULL) | |
257 | { | |
258 | glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates | |
259 | glEnableClientState (GL_TEXTURE_COORD_ARRAY); | |
260 | } | |
7fd59977 | 261 | |
a577aaab | 262 | if ((pvc != NULL) && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0) |
2166f0fa SK |
263 | { |
264 | glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc); // array of colors | |
265 | glEnableClientState (GL_COLOR_ARRAY); | |
266 | glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); | |
267 | glEnable (GL_COLOR_MATERIAL); | |
7fd59977 | 268 | } |
269 | } | |
5e27df78 | 270 | else |
2166f0fa SK |
271 | { |
272 | // Bindings concrete pointer in accordance with VBO buffer | |
5e27df78 | 273 | myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY); |
274 | if (!myVbos[VBOVnormals].IsNull()) | |
2166f0fa | 275 | { |
5e27df78 | 276 | myVbos[VBOVnormals]->BindFixed (aGlContext, GL_NORMAL_ARRAY); |
7fd59977 | 277 | } |
5e27df78 | 278 | if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0) |
2166f0fa | 279 | { |
5e27df78 | 280 | myVbos[VBOVtexels]->BindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY); |
7fd59977 | 281 | } |
a577aaab | 282 | if (!myVbos[VBOVcolours].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0) |
2166f0fa | 283 | { |
5e27df78 | 284 | myVbos[VBOVcolours]->BindFixed (aGlContext, GL_COLOR_ARRAY); |
285 | glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); | |
2166f0fa | 286 | glEnable (GL_COLOR_MATERIAL); |
7fd59977 | 287 | } |
288 | } | |
2166f0fa | 289 | |
5e27df78 | 290 | /// OCC22236 NOTE: draw for all situations: |
291 | /// 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array | |
292 | /// 2) draw elements from vertice array, when bounds defines count of primitive's verts. | |
293 | /// 3) draw primitive by vertexes if no edges and bounds array is specified | |
294 | if (toDrawVbo()) | |
2166f0fa | 295 | { |
5e27df78 | 296 | if (!myVbos[VBOEdges].IsNull()) |
2166f0fa | 297 | { |
5e27df78 | 298 | myVbos[VBOEdges]->Bind (aGlContext); |
2166f0fa SK |
299 | if (myPArray->num_bounds > 0) |
300 | { | |
301 | // draw primitives by vertex count with the indicies | |
302 | Tint* anOffset = NULL; | |
303 | for (i = 0; i < myPArray->num_bounds; ++i) | |
304 | { | |
7cc2d520 | 305 | if (pfc != NULL) glColor3fv (pfc[i].rgb); |
5e27df78 | 306 | glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), anOffset); |
bf75be98 | 307 | anOffset += myPArray->bounds[i]; |
762aacae A |
308 | } |
309 | } | |
2166f0fa SK |
310 | else |
311 | { | |
312 | // draw one (or sequential) primitive by the indicies | |
5e27df78 | 313 | glDrawElements (myDrawMode, myPArray->num_edges, myVbos[VBOEdges]->GetDataType(), NULL); |
762aacae | 314 | } |
5e27df78 | 315 | myVbos[VBOEdges]->Unbind (aGlContext); |
7fd59977 | 316 | } |
2166f0fa SK |
317 | else if (myPArray->num_bounds > 0) |
318 | { | |
319 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
320 | { | |
7cc2d520 | 321 | if (pfc != NULL) glColor3fv (pfc[i].rgb); |
2166f0fa SK |
322 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); |
323 | n += myPArray->bounds[i]; | |
7fd59977 | 324 | } |
325 | } | |
2166f0fa SK |
326 | else |
327 | { | |
a577aaab | 328 | if (myDrawMode == GL_POINTS) |
329 | { | |
330 | DrawMarkers (theWorkspace); | |
331 | } | |
332 | else | |
333 | { | |
334 | glDrawArrays (myDrawMode, 0, myVbos[VBOVertices]->GetElemsNb()); | |
335 | } | |
762aacae A |
336 | } |
337 | ||
2166f0fa | 338 | // bind with 0 |
5e27df78 | 339 | myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY); |
340 | if (!myVbos[VBOVnormals].IsNull()) | |
341 | { | |
342 | myVbos[VBOVnormals]->UnbindFixed (aGlContext, GL_NORMAL_ARRAY); | |
343 | } | |
344 | if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0) | |
345 | { | |
346 | myVbos[VBOVtexels]->UnbindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY); | |
347 | } | |
348 | if (!myVbos[VBOVcolours].IsNull()) | |
349 | { | |
350 | myVbos[VBOVcolours]->UnbindFixed (aGlContext, GL_COLOR_ARRAY); | |
351 | glDisable (GL_COLOR_MATERIAL); | |
352 | theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material | |
353 | } | |
bf75be98 | 354 | } |
2166f0fa SK |
355 | else |
356 | { | |
357 | if (myPArray->num_bounds > 0) | |
358 | { | |
359 | if (myPArray->num_edges > 0) | |
360 | { | |
361 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
362 | { | |
363 | if (pfc != NULL) glColor3fv (pfc[i].rgb); | |
5e27df78 | 364 | glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]); |
2166f0fa SK |
365 | n += myPArray->bounds[i]; |
366 | } | |
367 | } | |
368 | else | |
369 | { | |
370 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
371 | { | |
7cc2d520 | 372 | if (pfc != NULL) glColor3fv (pfc[i].rgb); |
5e27df78 | 373 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); |
2166f0fa SK |
374 | n += myPArray->bounds[i]; |
375 | } | |
7fd59977 | 376 | } |
2166f0fa SK |
377 | } |
378 | else if (myPArray->num_edges > 0) | |
379 | { | |
5e27df78 | 380 | glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges); |
2166f0fa SK |
381 | } |
382 | else | |
383 | { | |
a577aaab | 384 | if (myDrawMode == GL_POINTS) |
385 | { | |
386 | DrawMarkers (theWorkspace); | |
387 | } | |
388 | else | |
389 | { | |
390 | glDrawArrays (myDrawMode, 0, myPArray->num_vertexs); | |
391 | } | |
2166f0fa | 392 | } |
7fd59977 | 393 | |
5e27df78 | 394 | if (pvc != NULL) |
395 | { | |
396 | glDisable (GL_COLOR_MATERIAL); | |
397 | theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material | |
398 | } | |
2166f0fa | 399 | |
2166f0fa | 400 | glDisableClientState (GL_VERTEX_ARRAY); |
5e27df78 | 401 | if (myPArray->vcolours != NULL) |
402 | glDisableClientState (GL_COLOR_ARRAY); | |
403 | if (myPArray->vnormals != NULL) | |
404 | glDisableClientState (GL_NORMAL_ARRAY); | |
405 | if (myPArray->vtexels != NULL) | |
406 | glDisableClientState (GL_TEXTURE_COORD_ARRAY); | |
407 | } | |
7fd59977 | 408 | } |
409 | ||
de75ed09 | 410 | // On some NVIDIA graphic cards, using glEdgeFlagPointer() in |
411 | // combination with VBO (edge flag data put into a VBO buffer) | |
412 | // leads to a crash in a driver. Therefore, edge flags are simply | |
413 | // igonored when VBOs are enabled, so all the edges are drawn if | |
414 | // edge visibility is turned on. In order to draw edges selectively, | |
415 | // either disable VBO or turn off edge visibilty in the current | |
416 | // primitive array and create a separate primitive array (segments) | |
417 | // and put edges to be drawn into it. | |
418 | if (theEdgeFlag && myDrawMode > GL_LINE_STRIP) | |
2166f0fa | 419 | { |
de75ed09 | 420 | DrawEdges (theEdgeColour, theWorkspace); |
2166f0fa SK |
421 | } |
422 | ||
423 | if (myDrawMode <= GL_LINE_STRIP) | |
7fd59977 | 424 | glPopAttrib(); |
425 | } | |
426 | ||
2166f0fa SK |
427 | // ======================================================================= |
428 | // function : DrawEdges | |
429 | // purpose : | |
430 | // ======================================================================= | |
431 | void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR* theEdgeColour, | |
432 | const Handle(OpenGl_Workspace)& theWorkspace) const | |
7fd59977 | 433 | { |
2166f0fa | 434 | glDisable (GL_LIGHTING); |
7fd59977 | 435 | |
2166f0fa SK |
436 | const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext(); |
437 | const OpenGl_AspectLine* anAspectLineOld = NULL; | |
438 | if (myDrawMode > GL_LINE_STRIP) | |
439 | { | |
440 | anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge()); | |
30f0ad28 | 441 | const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True); |
7fd59977 | 442 | |
2166f0fa SK |
443 | glPushAttrib (GL_POLYGON_BIT); |
444 | glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); | |
30f0ad28 | 445 | |
446 | if (aGlContext->IsGlGreaterEqual (2, 0)) | |
447 | { | |
448 | BindProgramWithMaterial (theWorkspace, anAspect); | |
449 | } | |
2166f0fa | 450 | } |
7fd59977 | 451 | |
2166f0fa | 452 | Tint i, j, n; |
7fd59977 | 453 | |
5e27df78 | 454 | /// OCC22236 NOTE: draw edges for all situations: |
455 | /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array | |
456 | /// 2) draw elements from vertice array, when bounds defines count of primitive's verts. | |
457 | /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified | |
458 | if (toDrawVbo()) | |
bf75be98 | 459 | { |
5e27df78 | 460 | myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY); |
2166f0fa | 461 | glColor3fv (theEdgeColour->rgb); |
5e27df78 | 462 | if (!myVbos[VBOEdges].IsNull()) |
2166f0fa | 463 | { |
5e27df78 | 464 | myVbos[VBOEdges]->Bind (aGlContext); |
2166f0fa | 465 | |
762aacae | 466 | // draw primitives by vertex count with the indicies |
2166f0fa SK |
467 | if (myPArray->num_bounds > 0) |
468 | { | |
762aacae | 469 | Tint* offset = 0; |
2166f0fa SK |
470 | for (i = 0, offset = 0; i < myPArray->num_bounds; ++i) |
471 | { | |
5e27df78 | 472 | glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), offset); |
2166f0fa | 473 | offset += myPArray->bounds[i]; |
762aacae A |
474 | } |
475 | } | |
476 | // draw one (or sequential) primitive by the indicies | |
2166f0fa SK |
477 | else |
478 | { | |
5e27df78 | 479 | glDrawElements (myDrawMode, myVbos[VBOEdges]->GetElemsNb(), myVbos[VBOEdges]->GetDataType(), NULL); |
762aacae | 480 | } |
5e27df78 | 481 | myVbos[VBOEdges]->Unbind (aGlContext); |
7fd59977 | 482 | } |
2166f0fa SK |
483 | else if (myPArray->num_bounds > 0) |
484 | { | |
485 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
486 | { | |
487 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); | |
488 | n += myPArray->bounds[i]; | |
7fd59977 | 489 | } |
490 | } | |
2166f0fa SK |
491 | else |
492 | { | |
493 | glDrawArrays (myDrawMode, 0, myPArray->num_vertexs); | |
762aacae A |
494 | } |
495 | ||
496 | // unbind buffers | |
5e27df78 | 497 | myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY); |
2166f0fa SK |
498 | } |
499 | else | |
500 | { | |
501 | glEnableClientState (GL_VERTEX_ARRAY); | |
502 | glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices | |
2166f0fa SK |
503 | |
504 | glColor3fv (theEdgeColour->rgb); | |
505 | if (myPArray->num_bounds > 0) | |
506 | { | |
507 | if (myPArray->num_edges > 0) | |
508 | { | |
509 | for (i = n = 0; i < myPArray->num_bounds; ++i) | |
510 | { | |
511 | if (myPArray->edge_vis) | |
512 | { | |
513 | glBegin (myDrawMode); | |
514 | for (j = 0; j < myPArray->bounds[i]; ++j) | |
515 | { | |
516 | glEdgeFlag (myPArray->edge_vis[n+j]); | |
517 | glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]); | |
518 | } | |
519 | glEnd(); | |
7fd59977 | 520 | } |
2166f0fa SK |
521 | else |
522 | { | |
5e27df78 | 523 | glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]); |
7fd59977 | 524 | } |
2166f0fa | 525 | n += myPArray->bounds[i]; |
7fd59977 | 526 | } |
2166f0fa | 527 | } |
7fd59977 | 528 | else |
2166f0fa SK |
529 | { |
530 | for (i = n = 0 ; i < myPArray->num_bounds; ++i) | |
531 | { | |
5e27df78 | 532 | glDrawArrays (myDrawMode, n, myPArray->bounds[i]); |
2166f0fa SK |
533 | n += myPArray->bounds[i]; |
534 | } | |
535 | } | |
bf75be98 | 536 | } |
2166f0fa SK |
537 | else if (myPArray->num_edges > 0) |
538 | { | |
539 | if (myPArray->edge_vis) | |
540 | { | |
541 | glBegin (myDrawMode); | |
542 | for (i = 0; i < myPArray->num_edges; ++i) | |
543 | { | |
544 | glEdgeFlag (myPArray->edge_vis[i]); | |
545 | glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]); | |
546 | } | |
547 | glEnd(); | |
548 | } | |
7fd59977 | 549 | else |
2166f0fa | 550 | { |
5e27df78 | 551 | glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges); |
7fd59977 | 552 | } |
553 | } | |
2166f0fa SK |
554 | else |
555 | { | |
5e27df78 | 556 | glDrawArrays (myDrawMode, 0, myPArray->num_vertexs); |
7fd59977 | 557 | } |
2166f0fa SK |
558 | } |
559 | ||
560 | if (myDrawMode > GL_LINE_STRIP) | |
561 | { | |
562 | // Restore line context | |
563 | theWorkspace->SetAspectLine (anAspectLineOld); | |
7fd59977 | 564 | glPopAttrib(); |
565 | } | |
566 | } | |
567 | ||
a577aaab | 568 | // ======================================================================= |
569 | // function : DrawMarkers | |
570 | // purpose : | |
571 | // ======================================================================= | |
572 | void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const | |
573 | { | |
574 | const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True); | |
575 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); | |
30f0ad28 | 576 | const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (theWorkspace); |
a577aaab | 577 | const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT); |
578 | if (aCtx->IsGlGreaterEqual (2, 0) | |
579 | && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList()) | |
580 | { | |
581 | // Textured markers will be drawn with the point sprites | |
582 | glPointSize (anAspectMarker->MarkerSize()); | |
583 | ||
584 | Handle(OpenGl_Texture) aTextureBack; | |
585 | if (anAspectMarker->Type() != Aspect_TOM_POINT) | |
586 | { | |
30f0ad28 | 587 | const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlightRes (theWorkspace)->IsValid()) |
588 | ? anAspectMarker->SpriteHighlightRes (theWorkspace) | |
a577aaab | 589 | : aSpriteNorm; |
590 | aTextureBack = theWorkspace->EnableTexture (aSprite); | |
591 | ||
592 | glEnable (GL_ALPHA_TEST); | |
593 | glAlphaFunc (GL_GEQUAL, 0.1f); | |
594 | ||
595 | glEnable (GL_BLEND); | |
596 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
597 | } | |
598 | ||
599 | glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs); | |
600 | ||
601 | glDisable (GL_BLEND); | |
602 | glDisable (GL_ALPHA_TEST); | |
603 | if (anAspectMarker->Type() != Aspect_TOM_POINT) | |
604 | { | |
605 | theWorkspace->EnableTexture (aTextureBack); | |
606 | } | |
607 | glPointSize (1.0f); | |
608 | return; | |
609 | } | |
610 | ||
611 | // Textured markers will be drawn with the glBitmap | |
a577aaab | 612 | if (anAspectMarker->Type() == Aspect_TOM_POINT |
613 | || anAspectMarker->Type() == Aspect_TOM_O_POINT) | |
614 | { | |
abe46077 | 615 | const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT |
616 | ? anAspectMarker->MarkerSize() | |
617 | : 0.0f; | |
618 | if (aPntSize > 0.0f) | |
619 | { | |
620 | glPointSize (aPntSize); | |
621 | } | |
a577aaab | 622 | glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs); |
abe46077 | 623 | if (aPntSize > 0.0f) |
624 | { | |
625 | glPointSize (1.0f); | |
626 | } | |
a577aaab | 627 | } |
628 | ||
629 | if (anAspectMarker->Type() != Aspect_TOM_POINT | |
630 | && !aSpriteNorm.IsNull()) | |
631 | { | |
632 | if (!isHilight && (myPArray->vcolours != NULL)) | |
633 | { | |
634 | for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++) | |
635 | { | |
636 | glColor4ubv ((GLubyte* )&myPArray->vcolours[anIter]); | |
637 | glRasterPos3fv (myPArray->vertices[anIter].xyz); | |
638 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); | |
639 | } | |
640 | } | |
641 | else | |
642 | { | |
643 | for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++) | |
644 | { | |
645 | glRasterPos3fv (myPArray->vertices[anIter].xyz); | |
646 | aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext()); | |
647 | } | |
648 | } | |
649 | } | |
650 | } | |
651 | ||
2166f0fa SK |
652 | // ======================================================================= |
653 | // function : OpenGl_PrimitiveArray | |
654 | // purpose : | |
655 | // ======================================================================= | |
656 | OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray) | |
657 | : myPArray (thePArray), | |
5e27df78 | 658 | myDrawMode (DRAW_MODE_NONE), |
659 | myIsVboInit (Standard_False) | |
2166f0fa SK |
660 | { |
661 | switch (myPArray->type) | |
662 | { | |
663 | case TelPointsArrayType: | |
664 | myDrawMode = GL_POINTS; | |
665 | break; | |
666 | case TelPolylinesArrayType: | |
667 | myDrawMode = GL_LINE_STRIP; | |
668 | break; | |
669 | case TelSegmentsArrayType: | |
670 | myDrawMode = GL_LINES; | |
671 | break; | |
672 | case TelPolygonsArrayType: | |
673 | myDrawMode = GL_POLYGON; | |
674 | break; | |
675 | case TelTrianglesArrayType: | |
676 | myDrawMode = GL_TRIANGLES; | |
677 | break; | |
678 | case TelQuadranglesArrayType: | |
679 | myDrawMode = GL_QUADS; | |
680 | break; | |
681 | case TelTriangleStripsArrayType: | |
682 | myDrawMode = GL_TRIANGLE_STRIP; | |
683 | break; | |
684 | case TelQuadrangleStripsArrayType: | |
685 | myDrawMode = GL_QUAD_STRIP; | |
686 | break; | |
687 | case TelTriangleFansArrayType: | |
688 | myDrawMode = GL_TRIANGLE_FAN; | |
689 | break; | |
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 | } |