1 // File: OpenGl_Trihedron.cxx
2 // Created: 20 September 2011
3 // Author: Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
6 #include <OpenGl_GlCore11.hxx>
12 #include <OpenGl_TextureBox.hxx>
14 #include <InterfaceGraphic_Graphic3d.hxx> /* pour CALL_DEF_STRUCTURE */
15 #include <InterfaceGraphic_Aspect.hxx> /* pour CALL_DEF_VIEW */
16 #include <InterfaceGraphic_Visual3d.hxx>
18 #include <OpenGl_transform_persistence.hxx>
20 #include <OpenGl_Workspace.hxx>
21 #include <OpenGl_View.hxx>
22 #include <OpenGl_Trihedron.hxx>
24 #include <GL/glu.h> // gluNewQuadric()
26 IMPLEMENT_STANDARD_HANDLE(OpenGl_Trihedron,MMgt_TShared)
27 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Trihedron,MMgt_TShared)
29 static const CALL_DEF_CONTEXTLINE myDefaultContextLine =
33 { 1.F, 1.F, 1.F }, //Color
34 Aspect_TOL_SOLID, //LineType
38 static const CALL_DEF_CONTEXTTEXT myDefaultContextText =
45 { 1.F, 1.F, 1.F }, //Color
46 Aspect_TOST_NORMAL, //Style
47 Aspect_TODT_NORMAL, //DisplayType
48 { 1.F, 1.F, 1.F }, //ColorSubTitle
51 OSD_FA_Regular //TextFontAspect
54 /*----------------------------------------------------------------------*/
59 /* Default parameters for ZBUFFER triheron */
60 static TEL_COLOUR theXColor = {{ 1.F, 0.F, 0.F, 0.6F }};
61 static TEL_COLOUR theYColor = {{ 0.F, 1.F, 0.F, 0.6F }};
62 static TEL_COLOUR theZColor = {{ 0.F, 0.F, 1.F, 0.6F }};
63 static float theRatio = 0.8f;
64 static float theDiameter = 0.05f;
65 static int theNbFacettes = 12;
67 /*----------------------------------------------------------------------*/
70 * affichage d'un triedre non zoomable a partir des index dans les tables
71 * des structures non zoomables.
73 * Triedre = Objet non Zoomable :
74 * on recalcule ses dimensions et son origine en fonction de la taille
75 * de la fenetre; on positionne selon le choix de l'init;
76 * et on inhibe seulement les translations.
80 //call_triedron_redraw
81 void OpenGl_Trihedron::Redraw (const Handle(OpenGl_Workspace) &AWorkspace) const
83 const Standard_Real U = AWorkspace->ActiveView()->Height();
84 const Standard_Real V = AWorkspace->ActiveView()->Width();
86 /* la taille des axes est 1 proportion (fixee a l'init du triedre) */
87 /* de la dimension la plus petite de la window. */
88 const GLdouble L = ( U < V ? U : V ) * myScale;
91 * On inhibe les translations; on conserve les autres transformations.
94 /* on lit les matrices de transformation et de projection de la vue */
95 /* pour annuler les translations (dernieres colonnes des matrices). */
96 GLdouble modelMatrix[4][4];
97 glGetDoublev( GL_MODELVIEW_MATRIX, (GLdouble *) modelMatrix );
98 GLdouble projMatrix[4][4];
99 glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble *) projMatrix );
101 /* on annule la translation qui peut etre affectee a la vue */
102 modelMatrix[3][0] = 0.;
103 modelMatrix[3][1] = 0.;
104 modelMatrix[3][2] = 0.;
105 projMatrix[3][0] = 0.;
106 projMatrix[3][1] = 0.;
107 projMatrix[3][2] = 0.;
109 /* sauvegarde du contexte des matrices avant chargement */
110 glMatrixMode (GL_MODELVIEW);
112 glLoadMatrixd( (GLdouble *) modelMatrix );
113 glMatrixMode ( GL_PROJECTION );
115 glLoadMatrixd( (GLdouble *) projMatrix );
118 * Positionnement de l'origine du triedre selon le choix de l'init
121 /* on fait uniquement une translation de l'origine du Triedre */
125 case Aspect_TOTP_LEFT_LOWER :
126 glTranslated( -0.5*U + L , -0.5*V + L , 0. );
129 case Aspect_TOTP_LEFT_UPPER :
130 glTranslated( -0.5*U + L , +0.5*V - L -L/3., 0. );
133 case Aspect_TOTP_RIGHT_LOWER :
134 glTranslated( 0.5*U - L -L/3. , -0.5*V + L , 0. );
137 case Aspect_TOTP_RIGHT_UPPER :
138 glTranslated( 0.5*U - L -L/3. , +0.5*V - L -L/3. , 0. );
141 //case Aspect_TOTP_CENTER :
147 * Creation du triedre
149 const OpenGl_AspectLine *AspectLine = AWorkspace->AspectLine( Standard_True );
151 /* Fotis Sioutis 2007-11-14 15:06
152 I have also seen in previous posts that the view trihedron in V3d_WIREFRAME mode
153 changes colors depending on the state of the view. This behaviour can be easily
154 corrected by altering call_triedron_redraw function in OpenGl_triedron.c of TKOpengl.
155 The only change needed is to erase glDisable(GL_LIGHTING) that is called before the
156 Axis name drawing and move this function call just before the initial axis drawing.
157 Below is the code portion with the modification.I don't know if this is considered to
158 be a bug but anyway i believe it might help some of you out there.*/
159 glDisable(GL_LIGHTING);
161 /* Position de l'origine */
162 const GLdouble TriedronOrigin[3] = { 0.0, 0.0, 0.0 };
164 /* Position des Axes */
165 GLdouble TriedronAxeX[3] = { 1.0, 0.0, 0.0 };
166 GLdouble TriedronAxeY[3] = { 0.0, 1.0, 0.0 };
167 GLdouble TriedronAxeZ[3] = { 0.0, 0.0, 1.0 };
168 TriedronAxeX[0] = L ;
169 TriedronAxeY[1] = L ;
170 TriedronAxeZ[2] = L ;
172 /* dessin des axes */
174 glVertex3dv( TriedronOrigin );
175 glVertex3dv( TriedronAxeX );
177 glVertex3dv( TriedronOrigin );
178 glVertex3dv( TriedronAxeY );
180 glVertex3dv( TriedronOrigin );
181 glVertex3dv( TriedronAxeZ );
184 /* fleches au bout des axes (= cones de la couleur demandee) */
185 const GLdouble l = 0.75*L; /* distance a l'origine */
186 const GLdouble rayon = L/30. ; /* rayon de la base du cone */
187 const int NbFacettes = 12; /* le cone sera compose de 12 facettes triangulaires */
188 const double Angle = 2. * M_PI/ NbFacettes;
191 GLdouble TriedronCoord[3] = { 1.0, 0.0, 0.0 };
193 /* solution FILAIRE des cones au bout des axes : une seule ligne */
194 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
195 /* (la couleur est deja initialisee dans AspectLine) */
196 /* FIN de la solution FILAIRE CHOISIE pour les cones des axes */
199 glBegin(GL_TRIANGLE_FAN);
200 glVertex3dv( TriedronAxeX );
201 TriedronCoord[0] = l;
204 TriedronCoord[1] = rayon * sin(ii * Angle);
205 TriedronCoord[2] = rayon * cos(ii * Angle);
206 glVertex3dv( TriedronCoord );
212 glBegin(GL_TRIANGLE_FAN);
213 glVertex3dv( TriedronAxeY );
214 TriedronCoord[1] = l;
217 TriedronCoord[0] = rayon * cos(ii * Angle);
218 TriedronCoord[2] = rayon * sin(ii * Angle);
219 glVertex3dv( TriedronCoord );
225 glBegin(GL_TRIANGLE_FAN);
226 glVertex3dv( TriedronAxeZ );
227 TriedronCoord[2] = l;
230 TriedronCoord[0] = rayon * sin(ii * Angle);
231 TriedronCoord[1] = rayon * cos(ii * Angle);
232 glVertex3dv( TriedronCoord );
237 /* dessin de l'origine */
238 TriedronCoord[2] = 0.0 ;
240 const double Angle1 = 2. * M_PI/ ii;
241 glBegin(GL_LINE_LOOP);
243 TriedronCoord[0] = rayon * sin(ii * Angle1);
244 TriedronCoord[1] = rayon * cos(ii * Angle1);
245 glVertex3dv( TriedronCoord );
251 * Noms des axes et de l'origine
253 const OpenGl_AspectText *AspectText = AWorkspace->AspectText( Standard_True );
254 glColor3fv (AspectText->Color().rgb);
256 AWorkspace->RenderText (L"X", 0, float(L + rayon), 0.0f, float(-rayon));
257 AWorkspace->RenderText (L"Y", 0, float(rayon), float(L + 3.0 * rayon), float(2.0 * rayon));
258 AWorkspace->RenderText (L"Z", 0, float(-2.0 * rayon), float(0.5 * rayon), float(L + 3.0 * rayon));
261 * restauration du contexte des matrices
263 glMatrixMode (GL_PROJECTION);
265 glMatrixMode (GL_MODELVIEW);
270 /*******************************************************
271 * Draws ZBUFFER trihedron mode
272 *******************************************************/
273 //call_zbuffer_triedron_redraw
274 void OpenGl_Trihedron::RedrawZBuffer (const Handle(OpenGl_Workspace) &AWorkspace) const
276 const Standard_Real U = AWorkspace->ActiveView()->Height();
277 const Standard_Real V = AWorkspace->ActiveView()->Width();
279 GLdouble modelMatrix[4][4];
280 glGetDoublev( GL_MODELVIEW_MATRIX, (GLdouble *) modelMatrix );
281 GLdouble projMatrix[4][4];
282 glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble *) projMatrix );
284 /* Check position in the ViewPort */
286 /* Simple code modification recommended by Fotis Sioutis and Peter Dolbey */
287 /* to remove the irritating default behaviour of triedrons using V3d_ZBUFFER */
288 /* which causes the glyph to jump around the screen when the origin moves offscreen. */
289 GLboolean isWithinView = GL_FALSE;
291 /* la taille des axes est 1 proportion (fixee a l'init du triedre) */
292 /* de la dimension la plus petite de la window. */
293 GLdouble L = ( U < V ? U : V ) * myScale;
297 /* Annulate translation matrix */
298 modelMatrix[3][0] = 0.;
299 modelMatrix[3][1] = 0.;
300 modelMatrix[3][2] = 0.;
301 projMatrix[3][0] = 0.;
302 projMatrix[3][1] = 0.;
303 projMatrix[3][2] = 0.;
306 glMatrixMode (GL_MODELVIEW);
309 glLoadMatrixd( (GLdouble *) modelMatrix);
310 glMatrixMode ( GL_PROJECTION );
313 glLoadMatrixd( (GLdouble *) projMatrix);
316 * Define position in the view
320 case Aspect_TOTP_LEFT_LOWER :
321 glTranslated( -0.5*U + L , -0.5*V + L , 0. );
324 case Aspect_TOTP_LEFT_UPPER :
325 glTranslated( -0.5*U + L , +0.5*V - L -L/3. , 0. );
328 case Aspect_TOTP_RIGHT_LOWER :
329 glTranslated( 0.5*U - L -L/3. , -0.5*V + L , 0. );
332 case Aspect_TOTP_RIGHT_UPPER :
333 glTranslated( 0.5*U - L -L/3. , +0.5*V - L -L/3. , 0. );
336 //case Aspect_TOTP_CENTER :
343 const OpenGl_AspectLine *AspectLine = AWorkspace->AspectLine( Standard_True );
344 const TEL_COLOUR &aLineColor = AspectLine->Color();
347 * Creation the trihedron
349 #define CYLINDER_LENGTH 0.75f
351 const GLuint startList = glGenLists(4);
352 GLUquadricObj* aQuadric = gluNewQuadric();
354 const GLboolean aIsDepthEnabled = glIsEnabled(GL_DEPTH_TEST);
356 GLboolean aIsDepthMaskEnabled;
358 /* GL_DEPTH_WRITEMASK is not a valid argument to glIsEnabled, the */
359 /* original code is shown to be broken when run under an OpenGL debugger */
360 /* like GLIntercept. This is the correct way to retrieve the mask value. */
361 glGetBooleanv(GL_DEPTH_WRITEMASK, &aIsDepthMaskEnabled);
363 const GLdouble aCylinderLength = L * CYLINDER_LENGTH;
364 const GLdouble aCylinderDiametr = L * myDiameter;
365 const GLdouble aConeDiametr = aCylinderDiametr * 2.;
366 const GLdouble aConeLength = L * (1 - CYLINDER_LENGTH);
367 /* Correct for owerlapping */
368 /* aCylinderLength += aConeLength - 1.2*aCylinderDiametr*aConeLength/aConeDiametr;*/
370 /* Create cylinder for axis */
371 gluQuadricDrawStyle(aQuadric, GLU_FILL); /* smooth shaded */
372 gluQuadricNormals(aQuadric, GLU_FLAT);
374 glNewList(startList, GL_COMPILE);
375 gluCylinder(aQuadric, aCylinderDiametr, aCylinderDiametr, aCylinderLength, myNbFacettes, 1);
378 glNewList(startList + 1, GL_COMPILE);
379 gluCylinder(aQuadric, aConeDiametr, 0., aConeLength, myNbFacettes, 1);
382 glNewList(startList + 2, GL_COMPILE);
383 gluSphere(aQuadric, aCylinderDiametr * 2., myNbFacettes, myNbFacettes);
386 gluQuadricOrientation(aQuadric,GLU_INSIDE); /*szv*/
387 glNewList(startList + 3, GL_COMPILE);
388 gluDisk(aQuadric, aCylinderDiametr, aConeDiametr, myNbFacettes, 1/*szv:2*/);
391 /* Store previous attributes */
392 glPushAttrib(GL_LIGHTING_BIT | GL_POLYGON_BIT);
393 glEnable(GL_LIGHTING);
396 glEnable(GL_CULL_FACE);
398 /*Fotis Sioutis | 2008-01-21 10:55
399 In the function call_zbuffer_triedron_redraw of TKOpengl,
400 the z buffered trihedron changes colors in case there
401 is an object in the scene that has an explicit material
402 attached to it.In the trihedron display loop,
403 GL_COLOR_MATERIAL is enabled, but only the GL_DIFFUSE
404 parameter is utilized in glColorMaterial(...).
405 This causes the last ambient,specular and emission values
406 used, to stay at the stack and applied to the trihedron
407 (which causes the color change).
408 A fix is proposed , to change GL_DIFFUSE to
409 GL_AMBIENT_AND_DIFFUSE in glColorMaterial call in
410 line 946.The above of course will leave unchanged
411 the SPECULAR and EMISSION values.
412 Another proposal which would fix 100% the problem
413 is to use glMaterial instead of glColor on the trihedron
415 const GLfloat aNULLColor[] = { 0.f, 0.f, 0.f, 0.f }; /* FS 21/01/08 */
416 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, aNULLColor);
417 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, aNULLColor);
418 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, aNULLColor);
419 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.f);
421 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
422 glEnable(GL_COLOR_MATERIAL);
424 if (!aIsDepthEnabled) {
425 glEnable(GL_DEPTH_TEST);
426 glClear(GL_DEPTH_BUFFER_BIT);
429 if (!aIsDepthMaskEnabled) {
430 /* This is how the depthmask needs to be re-enabled...*/
431 glDepthMask(GL_TRUE);
432 /* ...and not this stuff below */
435 /* Position des Axes */
436 GLdouble TriedronAxeX[3] = { 1.0, 0.0, 0.0 };
437 GLdouble TriedronAxeY[3] = { 0.0, 1.0, 0.0 };
438 GLdouble TriedronAxeZ[3] = { 0.0, 0.0, 1.0 };
443 glMatrixMode(GL_MODELVIEW);
447 glGetIntegerv (GL_DEPTH_FUNC, &df);
450 for (i = 0; i < 2; i++) /* PCD 11/02/08 Two pass method */
452 if (i == 0) /* First pass */
454 glDepthFunc(GL_ALWAYS);
458 glDepthFunc(GL_LEQUAL);
465 glColor3fv(aLineColor.rgb);
466 glCallList(startList+2);
469 glColor4fv(myZColor.rgb);
470 glCallList(startList);
471 glTranslated(0, 0, L * CYLINDER_LENGTH);
472 glCallList(startList + 3);
473 glCallList(startList + 1);
477 glRotated(90.0, TriedronAxeY[0], TriedronAxeY[1], TriedronAxeY[2]);
478 glColor4fv(myXColor.rgb);
479 glCallList(startList);
480 glTranslated(0, 0, L * CYLINDER_LENGTH);
481 glCallList(startList + 3);
482 glCallList(startList + 1);
486 glRotated(-90.0, TriedronAxeX[0], TriedronAxeX[1], TriedronAxeX[2]);
487 glColor4fv(myYColor.rgb);
488 glCallList(startList);
489 glTranslated(0, 0, L * CYLINDER_LENGTH);
490 glCallList(startList + 3);
491 glCallList(startList + 1);
495 if (!aIsDepthEnabled)
496 glDisable(GL_DEPTH_TEST);
498 if (!aIsDepthMaskEnabled)
499 glDepthMask(GL_FALSE);
501 glDisable(GL_CULL_FACE);
502 glDisable(GL_COLOR_MATERIAL);
504 gluDeleteQuadric(aQuadric);
505 glColor3fv (aLineColor.rgb);
507 /* Always write the text */
508 glDepthFunc(GL_ALWAYS);
512 /* fleches au bout des axes (= cones de la couleur demandee) */
513 //const GLdouble l = 0.75*L; /* distance a l'origine */
514 const GLdouble rayon = L/30. ; /* rayon de la base du cone */
515 //const double Angle = 2. * M_PI/ myNbFacettes;
517 glDeleteLists(startList, 4);
519 glDisable(GL_LIGHTING);
524 const OpenGl_AspectText *AspectText = AWorkspace->AspectText( Standard_True );
525 glColor3fv (AspectText->Color().rgb);
527 AWorkspace->RenderText (L"X", 0, float(L + rayon), 0.0f, float(-rayon));
528 AWorkspace->RenderText (L"Y", 0, float(rayon), float(L + 3.0 * rayon), float(2.0 * rayon));
529 AWorkspace->RenderText (L"Z", 0, float(-2.0 * rayon), float(0.5 * rayon), float(L + 3.0 * rayon));
534 if (!isWithinView) { /* restore matrix */
535 glMatrixMode (GL_PROJECTION);
537 glMatrixMode (GL_MODELVIEW);
543 /*----------------------------------------------------------------------*/
545 /*----------------------------------------------------------------------*/
547 * Fonctions publiques
552 * initialisation d'un triedre non zoomable dans une vue.
553 * ou modification des valeurs deja initialisees.
557 OpenGl_Trihedron::OpenGl_Trihedron (const Aspect_TypeOfTriedronPosition APosition, const Quantity_NameOfColor AColor,
558 const Standard_Real AScale, const Standard_Boolean AsWireframe)
561 myIsWireframe(AsWireframe)
564 Quantity_Color Color(AColor);
565 Color.Values(R,G,B,Quantity_TOC_RGB);
567 CALL_DEF_CONTEXTLINE aContextLine = myDefaultContextLine;
568 aContextLine.Color.r = (float)R;
569 aContextLine.Color.g = (float)G;
570 aContextLine.Color.b = (float)B;
571 myAspectLine.SetContext(aContextLine);
573 CALL_DEF_CONTEXTTEXT aContextText = myDefaultContextText;
574 aContextText.Color.r = (float)R;
575 aContextText.Color.g = (float)G;
576 aContextText.Color.b = (float)B;
577 myAspectText.SetContext(aContextText);
579 myXColor = theXColor;
580 myYColor = theYColor;
581 myZColor = theZColor;
584 myDiameter = theDiameter;
585 myNbFacettes = theNbFacettes;
588 /*----------------------------------------------------------------------*/
591 * destruction du triedre non zoomable d'une vue.
594 //call_triedron_erase
595 OpenGl_Trihedron::~OpenGl_Trihedron ()
599 /*----------------------------------------------------------------------*/
602 * affichage d'un triedre non zoomable dans la wks awsid
604 * Triedre = Objet non Zoomable;
605 * on cree cette fonction pour pouvoir travailler par les structures
606 * utilisees par les fonctions Tsm* et TEL_VIEW_REP
610 //call_triedron_redraw_from_wsid
611 void OpenGl_Trihedron::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
613 const OpenGl_AspectLine *oldAspectLine = AWorkspace->SetAspectLine(&myAspectLine);
614 const OpenGl_AspectText *oldAspectText = AWorkspace->SetAspectText(&myAspectText);
616 /* check if GL_LIGHTING should be disabled
617 no enabling 'cause it will be done (if necessary: kinda Polygon types )
618 during redrawing structures
620 if (!AWorkspace->UseGLLight())
621 glDisable( GL_LIGHTING );
623 /* sauvegarde du contexte (on reste dans le buffer courant) */
624 const GLboolean save_texture_state = IsTextureEnabled();
627 /* affichage du Triedre Non Zoomable */
628 AWorkspace->ActiveView()->EndTransformPersistence();
633 RedrawZBuffer (AWorkspace);
635 /* restauration du contexte */
636 if (save_texture_state) EnableTexture();
638 AWorkspace->SetAspectText(oldAspectText);
639 AWorkspace->SetAspectLine(oldAspectLine);
642 /*----------------------------------------------------------------------*/
643 //call_ztriedron_setup
644 void OpenGl_Trihedron::Setup (const Quantity_NameOfColor XColor, const Quantity_NameOfColor YColor, const Quantity_NameOfColor ZColor,
645 const Standard_Real SizeRatio, const Standard_Real AxisDiametr, const Standard_Integer NbFacettes)
649 Quantity_Color(XColor).Values(R, G, B, Quantity_TOC_RGB);
650 theXColor.rgb[0] = float (R);
651 theXColor.rgb[1] = float (G);
652 theXColor.rgb[2] = float (B);
654 Quantity_Color(YColor).Values(R, G, B, Quantity_TOC_RGB);
655 theYColor.rgb[0] = float (R);
656 theYColor.rgb[1] = float (G);
657 theYColor.rgb[2] = float (B);
659 Quantity_Color(ZColor).Values(R, G, B, Quantity_TOC_RGB);
660 theZColor.rgb[0] = float (R);
661 theZColor.rgb[1] = float (G);
662 theZColor.rgb[2] = float (B);
664 theRatio = float (SizeRatio);
665 theDiameter = float (AxisDiametr);
666 theNbFacettes = NbFacettes;