02a14a6db0a53f4088f82842f9fd947a09304565
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
1 // Created on: 2011-07-13
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2013 OPEN CASCADE SAS
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
20 #include <OpenGl_IndexBuffer.hxx>
21 #include <OpenGl_Context.hxx>
22
23 #include <OpenGl_PrimitiveArray.hxx>
24
25 #include <OpenGl_AspectFace.hxx>
26 #include <OpenGl_GraphicDriver.hxx>
27 #include <OpenGl_Structure.hxx>
28 #include <OpenGl_Workspace.hxx>
29
30 #include <InterfaceGraphic_PrimitiveArray.hxx>
31
32 // =======================================================================
33 // function : clearMemoryOwn
34 // purpose  :
35 // =======================================================================
36 void OpenGl_PrimitiveArray::clearMemoryOwn() const
37 {
38   Standard::Free ((Standard_Address& )myPArray->edges);
39   Standard::Free ((Standard_Address& )myPArray->vertices);
40   Standard::Free ((Standard_Address& )myPArray->vcolours);
41   Standard::Free ((Standard_Address& )myPArray->vnormals);
42   Standard::Free ((Standard_Address& )myPArray->vtexels);
43   Standard::Free ((Standard_Address& )myPArray->edge_vis); /// ???
44
45   myPArray->edges    = NULL;
46   myPArray->vertices = NULL;
47   myPArray->vcolours = NULL;
48   myPArray->vnormals = NULL;
49   myPArray->vtexels  = NULL;
50   myPArray->edge_vis = NULL;
51 }
52
53 // =======================================================================
54 // function : clearMemoryGL
55 // purpose  :
56 // =======================================================================
57 void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
58 {
59   for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
60   {
61     if (!myVbos[anIter].IsNull())
62     {
63       myVbos[anIter]->Release (theGlCtx.operator->());
64       myVbos[anIter].Nullify();
65     }
66   }
67 }
68
69 // =======================================================================
70 // function : BuildVBO
71 // purpose  :
72 // =======================================================================
73 Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const
74 {
75   const Handle(OpenGl_Context)& aGlCtx = theWorkspace->GetGlContext();
76   if (myPArray->vertices == NULL)
77   {
78     // vertices should be always defined - others are optional
79     return Standard_False;
80   }
81   myVbos[VBOVertices] = new OpenGl_VertexBuffer();
82   if (!myVbos[VBOVertices]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vertices[0].xyz[0]))
83   {
84     clearMemoryGL (aGlCtx);
85     return Standard_False;
86   }
87
88   if (myPArray->edges != NULL
89    && myPArray->num_edges > 0)
90   {
91     myVbos[VBOEdges] = new OpenGl_IndexBuffer();
92     if (!myVbos[VBOEdges]->Init (aGlCtx, 1, myPArray->num_edges, (GLuint* )myPArray->edges))
93     {
94       clearMemoryGL (aGlCtx);
95       return Standard_False;
96     }
97   }
98   if (myPArray->vcolours != NULL)
99   {
100     myVbos[VBOVcolours] = new OpenGl_VertexBuffer();
101     if (!myVbos[VBOVcolours]->Init (aGlCtx, 4, myPArray->num_vertexs, (GLubyte* )myPArray->vcolours))
102     {
103       clearMemoryGL (aGlCtx);
104       return Standard_False;
105     }
106   }
107   if (myPArray->vnormals != NULL)
108   {
109     myVbos[VBOVnormals] = new OpenGl_VertexBuffer();
110     if (!myVbos[VBOVnormals]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vnormals[0].xyz[0]))
111     {
112       clearMemoryGL (aGlCtx);
113       return Standard_False;
114     }
115   }
116   if (myPArray->vtexels)
117   {
118     myVbos[VBOVtexels] = new OpenGl_VertexBuffer();
119     if (!myVbos[VBOVtexels]->Init (aGlCtx, 2, myPArray->num_vertexs, &myPArray->vtexels[0].xy[0]))
120     {
121       clearMemoryGL (aGlCtx);
122       return Standard_False;
123     }
124   }
125
126   clearMemoryOwn();
127   return Standard_True;
128 }
129
130 // =======================================================================
131 // function : DrawArray
132 // purpose  :
133 // =======================================================================
134 void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel,
135                                        const Aspect_InteriorStyle theInteriorStyle,
136                                        Tint theEdgeFlag,
137                                        const TEL_COLOUR* theInteriorColour,
138                                        const TEL_COLOUR* theLineColour,
139                                        const TEL_COLOUR* theEdgeColour,
140                                        const OPENGL_SURF_PROP* theFaceProp,
141                                        const Handle(OpenGl_Workspace)& theWorkspace) const
142 {
143   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
144
145   Tint i,n;
146   Tint transp = 0;
147   // Following pointers have been provided for performance improvement
148   tel_colour pfc = myPArray->fcolours;
149   Tint* pvc = myPArray->vcolours;
150   if (pvc != NULL)
151   {
152     for (i = 0; i < myPArray->num_vertexs; ++i)
153     {
154       transp = int(theFaceProp->trans * 255.0f);
155     #if defined (sparc) || defined (__sparc__) || defined (__sparc)
156       pvc[i] = (pvc[i] & 0xffffff00);
157       pvc[i] += transp;
158     #else
159       pvc[i] = (pvc[i] & 0x00ffffff);
160       pvc[i] += transp << 24;
161     #endif
162     }
163   }
164
165   switch (myPArray->type)
166   {
167     case TelPointsArrayType:
168     case TelPolylinesArrayType:
169     case TelSegmentsArrayType:
170       glColor3fv (theLineColour->rgb);
171       break;
172     case TelPolygonsArrayType:
173     case TelTrianglesArrayType:
174     case TelQuadranglesArrayType:
175     case TelTriangleStripsArrayType:
176     case TelQuadrangleStripsArrayType:
177     case TelTriangleFansArrayType:
178       glColor3fv (theInteriorColour->rgb);
179       break;
180   }
181
182   // Temporarily disable environment mapping
183   if (myDrawMode <= GL_LINE_STRIP)
184   {
185     glPushAttrib (GL_ENABLE_BIT);
186     glDisable (GL_TEXTURE_1D);
187     glDisable (GL_TEXTURE_2D);
188   }
189
190   if ((myDrawMode >  GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
191       (myDrawMode <= GL_LINE_STRIP))
192   {
193     if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
194     {
195       pfc = NULL;
196       pvc = NULL;
197     }
198
199     if (theInteriorStyle == Aspect_IS_HIDDENLINE)
200     {
201       theEdgeFlag = 1;
202       pfc = NULL;
203       pvc = NULL;
204     }
205
206     // Sometimes the GL_LIGHTING mode is activated here
207     // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary
208     // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
209     if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
210       glDisable (GL_LIGHTING);
211     else
212       glEnable (GL_LIGHTING);
213
214     if (!toDrawVbo())
215     {
216       if (myPArray->vertices != NULL)
217       {
218         glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
219         glEnableClientState (GL_VERTEX_ARRAY);
220       }
221       if (myPArray->vnormals != NULL)
222       {
223         glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals
224         glEnableClientState (GL_NORMAL_ARRAY);
225       }
226       if (myPArray->vtexels != NULL)
227       {
228         glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates
229         glEnableClientState (GL_TEXTURE_COORD_ARRAY);
230       }
231
232       if (pvc != NULL)
233       {
234         glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc);  // array of colors
235         glEnableClientState (GL_COLOR_ARRAY);
236         glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
237         glEnable (GL_COLOR_MATERIAL);
238       }
239     }
240     else
241     {
242       // Bindings concrete pointer in accordance with VBO buffer
243       myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
244       if (!myVbos[VBOVnormals].IsNull())
245       {
246         myVbos[VBOVnormals]->BindFixed (aGlContext, GL_NORMAL_ARRAY);
247       }
248       if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
249       {
250         myVbos[VBOVtexels]->BindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
251       }
252       if (!myVbos[VBOVcolours].IsNull())
253       {
254         myVbos[VBOVcolours]->BindFixed (aGlContext, GL_COLOR_ARRAY);
255         glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
256         glEnable (GL_COLOR_MATERIAL);
257       }
258     }
259
260     /// OCC22236 NOTE: draw for all situations:
261     /// 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array
262     /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
263     /// 3) draw primitive by vertexes if no edges and bounds array is specified
264     if (toDrawVbo())
265     {
266       if (!myVbos[VBOEdges].IsNull())
267       {
268         myVbos[VBOEdges]->Bind (aGlContext);
269         if (myPArray->num_bounds > 0)
270         {
271           // draw primitives by vertex count with the indicies
272           Tint* anOffset = NULL;
273           for (i = 0; i < myPArray->num_bounds; ++i)
274           {
275             if (pfc != NULL) glColor3fv (pfc[i].rgb);
276             glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), anOffset);
277             anOffset += myPArray->bounds[i];
278           }
279         }
280         else
281         {
282           // draw one (or sequential) primitive by the indicies
283           glDrawElements (myDrawMode, myPArray->num_edges, myVbos[VBOEdges]->GetDataType(), NULL);
284         }
285         myVbos[VBOEdges]->Unbind (aGlContext);
286       }
287       else if (myPArray->num_bounds > 0)
288       {
289         for (i = n = 0; i < myPArray->num_bounds; ++i)
290         {
291           if (pfc != NULL) glColor3fv (pfc[i].rgb);
292           glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
293           n += myPArray->bounds[i];
294         }
295       }
296       else
297       {
298         glDrawArrays (myDrawMode, 0, myVbos[VBOVertices]->GetElemsNb());
299       }
300
301       // bind with 0
302       myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
303       if (!myVbos[VBOVnormals].IsNull())
304       {
305         myVbos[VBOVnormals]->UnbindFixed (aGlContext, GL_NORMAL_ARRAY);
306       }
307       if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
308       {
309         myVbos[VBOVtexels]->UnbindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
310       }
311       if (!myVbos[VBOVcolours].IsNull())
312       {
313         myVbos[VBOVcolours]->UnbindFixed (aGlContext, GL_COLOR_ARRAY);
314         glDisable (GL_COLOR_MATERIAL);
315         theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
316       }
317     }
318     else
319     {
320       if (myPArray->num_bounds > 0)
321       {
322         if (myPArray->num_edges > 0)
323         {
324           for (i = n = 0; i < myPArray->num_bounds; ++i)
325           {
326             if (pfc != NULL) glColor3fv (pfc[i].rgb);
327             glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
328             n += myPArray->bounds[i];
329           }
330         }
331         else
332         {
333           for (i = n = 0; i < myPArray->num_bounds; ++i)
334           {
335             if (pfc != NULL) glColor3fv (pfc[i].rgb);
336             glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
337             n += myPArray->bounds[i];
338           }
339         }
340       }
341       else if (myPArray->num_edges > 0)
342       {
343         glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
344       }
345       else
346       {
347         glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
348       }
349
350       if (pvc != NULL)
351       {
352         glDisable (GL_COLOR_MATERIAL);
353         theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
354       }
355
356       glDisableClientState (GL_VERTEX_ARRAY);
357       if (myPArray->vcolours != NULL)
358         glDisableClientState (GL_COLOR_ARRAY);
359       if (myPArray->vnormals != NULL)
360         glDisableClientState (GL_NORMAL_ARRAY);
361       if (myPArray->vtexels != NULL)
362         glDisableClientState (GL_TEXTURE_COORD_ARRAY);
363     }
364   }
365
366   // On some NVIDIA graphic cards, using glEdgeFlagPointer() in
367   // combination with VBO (edge flag data put into a VBO buffer)
368   // leads to a crash in a driver. Therefore, edge flags are simply
369   // igonored when VBOs are enabled, so all the edges are drawn if
370   // edge visibility is turned on. In order to draw edges selectively,
371   // either disable VBO or turn off edge visibilty in the current
372   // primitive array and create a separate primitive array (segments)
373   // and put edges to be drawn into it.
374   if (theEdgeFlag && myDrawMode > GL_LINE_STRIP)
375   {
376     DrawEdges (theEdgeColour, theWorkspace);
377   }
378
379   if (myDrawMode <= GL_LINE_STRIP)
380     glPopAttrib();
381 }
382
383 // =======================================================================
384 // function : DrawEdges
385 // purpose  :
386 // =======================================================================
387 void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR*               theEdgeColour,
388                                        const Handle(OpenGl_Workspace)& theWorkspace) const
389 {
390   glDisable (GL_LIGHTING);
391
392   const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
393   const OpenGl_AspectLine* anAspectLineOld = NULL;
394   if (myDrawMode > GL_LINE_STRIP)
395   {
396     anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
397     theWorkspace->AspectLine (Standard_True);
398
399     glPushAttrib (GL_POLYGON_BIT);
400     glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
401   }
402
403   Tint i, j, n;
404
405   /// OCC22236 NOTE: draw edges for all situations:
406   /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array
407   /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
408   /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
409   if (toDrawVbo())
410   {
411     myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
412     glColor3fv (theEdgeColour->rgb);
413     if (!myVbos[VBOEdges].IsNull())
414     {
415       myVbos[VBOEdges]->Bind (aGlContext);
416
417       // draw primitives by vertex count with the indicies
418       if (myPArray->num_bounds > 0)
419       {
420         Tint* offset = 0;
421         for (i = 0, offset = 0; i < myPArray->num_bounds; ++i)
422         {
423           glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), offset);
424           offset += myPArray->bounds[i];
425         }
426       }
427       // draw one (or sequential) primitive by the indicies
428       else
429       {
430         glDrawElements (myDrawMode, myVbos[VBOEdges]->GetElemsNb(), myVbos[VBOEdges]->GetDataType(), NULL);
431       }
432       myVbos[VBOEdges]->Unbind (aGlContext);
433     }
434     else if (myPArray->num_bounds > 0)
435     {
436       for (i = n = 0; i < myPArray->num_bounds; ++i)
437       {
438         glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
439         n += myPArray->bounds[i];
440       }
441     }
442     else
443     {
444       glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
445     }
446
447     // unbind buffers
448     myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
449   }
450   else
451   {
452     glEnableClientState (GL_VERTEX_ARRAY);
453     glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
454
455     glColor3fv (theEdgeColour->rgb);
456     if (myPArray->num_bounds > 0)
457     {
458       if (myPArray->num_edges > 0)
459       {
460         for (i = n = 0; i < myPArray->num_bounds; ++i)
461         {
462           if (myPArray->edge_vis)
463           {
464             glBegin (myDrawMode);
465             for (j = 0; j < myPArray->bounds[i]; ++j)
466             {
467               glEdgeFlag (myPArray->edge_vis[n+j]);
468               glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]);
469             }
470             glEnd();
471           }
472           else
473           {
474             glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
475           }
476           n += myPArray->bounds[i];
477         }
478       }
479       else
480       {
481         for (i = n = 0 ; i < myPArray->num_bounds; ++i)
482         {
483           glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
484           n += myPArray->bounds[i];
485         }
486       }
487     }
488     else if (myPArray->num_edges > 0)
489     {
490       if (myPArray->edge_vis)
491       {
492         glBegin (myDrawMode);
493         for (i = 0; i < myPArray->num_edges; ++i)
494         {
495           glEdgeFlag (myPArray->edge_vis[i]);
496           glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]);
497         }
498         glEnd();
499       }
500       else
501       {
502         glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
503       }
504     }
505     else
506     {
507       glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
508     }
509   }
510
511   if (myDrawMode > GL_LINE_STRIP)
512   {
513     // Restore line context
514     theWorkspace->SetAspectLine (anAspectLineOld);
515     glPopAttrib();
516   }
517 }
518
519 // =======================================================================
520 // function : OpenGl_PrimitiveArray
521 // purpose  :
522 // =======================================================================
523 OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray)
524 : myPArray (thePArray),
525   myDrawMode (DRAW_MODE_NONE),
526   myIsVboInit (Standard_False)
527 {
528   switch (myPArray->type)
529   {
530     case TelPointsArrayType:
531       myDrawMode = GL_POINTS;
532       break;
533     case TelPolylinesArrayType:
534       myDrawMode = GL_LINE_STRIP;
535       break;
536     case TelSegmentsArrayType:
537       myDrawMode = GL_LINES;
538       break;
539     case TelPolygonsArrayType:
540       myDrawMode = GL_POLYGON;
541       break;
542     case TelTrianglesArrayType:
543       myDrawMode = GL_TRIANGLES;
544       break;
545     case TelQuadranglesArrayType:
546       myDrawMode = GL_QUADS;
547       break;
548     case TelTriangleStripsArrayType:
549       myDrawMode = GL_TRIANGLE_STRIP;
550       break;
551     case TelQuadrangleStripsArrayType:
552       myDrawMode = GL_QUAD_STRIP;
553       break;
554     case TelTriangleFansArrayType:
555       myDrawMode = GL_TRIANGLE_FAN;
556       break;
557   }
558 }
559
560 // =======================================================================
561 // function : ~OpenGl_PrimitiveArray
562 // purpose  :
563 // =======================================================================
564 OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
565 {
566   //
567 }
568
569 // =======================================================================
570 // function : Release
571 // purpose  :
572 // =======================================================================
573 void OpenGl_PrimitiveArray::Release (const Handle(OpenGl_Context)& theContext)
574 {
575   for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
576   {
577     if (!myVbos[anIter].IsNull())
578     {
579       if (!theContext.IsNull())
580       {
581         theContext->DelayedRelease (myVbos[anIter]);
582       }
583       myVbos[anIter].Nullify();
584     }
585   }
586 }
587
588 // =======================================================================
589 // function : Render
590 // purpose  :
591 // =======================================================================
592 void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
593 {
594   if (myPArray == NULL || myDrawMode == DRAW_MODE_NONE || myPArray->num_vertexs <= 0)
595   {
596     return;
597   }
598
599   // create VBOs on first render call
600   if (!myIsVboInit && OpenGl_GraphicDriver::ToUseVBO() && theWorkspace->GetGlContext()->core15 != NULL)
601   {
602     BuildVBO (theWorkspace);
603     myIsVboInit = Standard_True;
604   }
605
606   switch (myPArray->type)
607   {
608     case TelPointsArrayType:
609     case TelPolylinesArrayType:
610     case TelSegmentsArrayType:
611     {
612       glDisable (GL_LIGHTING);
613       break;
614     }
615     default:
616       break;
617   }
618
619   const OpenGl_AspectFace*   anAspectFace   = theWorkspace->AspectFace   (Standard_True);
620   const OpenGl_AspectLine*   anAspectLine   = theWorkspace->AspectLine   (Standard_True);
621   const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myPArray->type == TelPointsArrayType);
622
623   Tint aFrontLightingModel = anAspectFace->IntFront.color_mask;
624   const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront.matcol;
625   const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
626   const TEL_COLOUR* aLineColor = (myPArray->type == TelPointsArrayType) ? &anAspectMarker->Color() : &anAspectLine->Color();
627
628   // Use highlight colors
629   if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
630   {
631     anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
632     aFrontLightingModel = 0;
633   }
634
635   DrawArray (aFrontLightingModel,
636              anAspectFace->InteriorStyle,
637              anAspectFace->Edge,
638              anInteriorColor,
639              aLineColor,
640              anEdgeColor,
641              &anAspectFace->IntFront,
642              theWorkspace);
643 }