0023791: Remove obsolete functionality - animation mode and degeneration presentation...
[occt.git] / src / OpenGl / OpenGl_View.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 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_GlCore11.hxx>
21
22 #include <OpenGl_View.hxx>
23 #include <OpenGl_Context.hxx>
24 #include <OpenGl_Workspace.hxx>
25 #include <OpenGl_Display.hxx>
26
27 #include <OpenGl_Texture.hxx>
28 #include <OpenGl_Trihedron.hxx>
29 #include <OpenGl_GraduatedTrihedron.hxx>
30
31 #include <OpenGl_transform_persistence.hxx>
32
33 #include <Graphic3d_TextureEnv.hxx>
34
35 IMPLEMENT_STANDARD_HANDLE(OpenGl_View,MMgt_TShared)
36 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,MMgt_TShared)
37
38 /*----------------------------------------------------------------------*/
39
40 static const OPENGL_BG_TEXTURE myDefaultBgTexture = { 0, 0, 0, Aspect_FM_CENTERED };
41 static const OPENGL_BG_GRADIENT myDefaultBgGradient = { {{ 0.F, 0.F, 0.F, 1.F }}, {{ 0.F, 0.F, 0.F, 1.F }}, Aspect_GFM_NONE };
42 static const Tmatrix3 myDefaultMatrix = { { 1.F, 0.F, 0.F, 0.F }, { 0.F, 1.F, 0.F, 0.F }, { 0.F, 0.F, 1.F, 0.F }, { 0.F, 0.F, 0.F, 1.F } };
43 static const OPENGL_ZCLIP myDefaultZClip = { { Standard_True, 0.F }, { Standard_True, 1.F } };
44 static const OPENGL_EXTRA_REP myDefaultExtra =
45 {
46   //vrp
47   { 0.F, 0.F, 0.F },
48   //vpn
49   { 0.F, 0.F, 1.F },
50   //vup
51   { 0.F, 1.F, 0.F },
52   //map
53   {
54     //window
55     { 0.F, 0.F, 1.F, 1.F },
56     //viewport
57     { 0.F, 0.F, 0.F, 1.F, 1.F, 1.F },
58     //proj
59     TelParallel,
60     //prp
61     { 0.F, 0.F, 0.F },
62     //vpd
63     0.F,
64     //fpd
65     0.F,
66     //bpd
67     -1.F
68   },
69   //scaleFactors
70   { 1.F, 1.F, 1.F }
71 };
72
73 static const OPENGL_FOG myDefaultFog = { Standard_False, 0.F, 1.F, { { 0.F, 0.F, 0.F, 1.F } } };
74 static const TEL_TRANSFORM_PERSISTENCE myDefaultTransPers = { 0, 0.F, 0.F, 0.F };
75 static const GLdouble THE_IDENTITY_MATRIX[4][4] =
76 {
77   {1.0, 0.0, 0.0, 0.0},
78   {0.0, 1.0, 0.0, 0.0},
79   {0.0, 0.0, 1.0, 0.0},
80   {0.0, 0.0, 0.0, 1.0}
81 };
82
83 /*----------------------------------------------------------------------*/
84
85 OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext)
86 : mySurfaceDetail(Visual3d_TOD_NONE),
87   myBackfacing(0),
88   myBgTexture(myDefaultBgTexture),
89   myBgGradient(myDefaultBgGradient),
90   //myOrientationMatrix(myDefaultMatrix),
91   //myMappingMatrix(myDefaultMatrix),
92   //shield_indicator = TOn,
93   //shield_colour = { { 0.F, 0.F, 0.F, 1.F } },
94   //border_indicator = TOff,
95   //border_colour = { { 0.F, 0.F, 0.F, 1.F } },
96   //active_status = TOn,
97   myZClip(myDefaultZClip),
98   myExtra(myDefaultExtra),
99   myFog(myDefaultFog),
100   myVisualization(AContext.Visualization),
101   myIntShadingMethod(TEL_SM_GOURAUD),
102   myAntiAliasing(Standard_False),
103   myTransPers(&myDefaultTransPers),
104   myIsTransPers(Standard_False)
105 {
106   // Initialize matrices
107   memcpy(myOrientationMatrix,myDefaultMatrix,sizeof(Tmatrix3));
108   memcpy(myMappingMatrix,myDefaultMatrix,sizeof(Tmatrix3));
109
110   // Shading method
111   switch (AContext.Model)
112   {
113     case 1 : /* VISUAL3D_TOM_INTERP_COLOR */
114     case 3 : /* VISUAL3D_TOM_VERTEX */
115       myIntShadingMethod = TEL_SM_GOURAUD;
116       break;
117     default :
118       myIntShadingMethod = TEL_SM_FLAT;
119       break;
120   }
121 }
122
123 /*----------------------------------------------------------------------*/
124
125 OpenGl_View::~OpenGl_View ()
126 {
127   ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
128 }
129
130 void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
131 {
132   OpenGl_Element::Destroy (theCtx, myTrihedron);
133   OpenGl_Element::Destroy (theCtx, myGraduatedTrihedron);
134   if (!myTextureEnv.IsNull())
135   {
136     theCtx->DelayedRelease (myTextureEnv);
137     myTextureEnv.Nullify();
138   }
139   if (myBgTexture.TexId != 0)
140   {
141     glDeleteTextures (1, (GLuint*)&(myBgTexture.TexId));
142     myBgTexture.TexId = 0;
143   }
144 }
145
146 void OpenGl_View::SetTextureEnv (const Handle(OpenGl_Context)&       theCtx,
147                                  const Handle(Graphic3d_TextureEnv)& theTexture)
148 {
149   if (!myTextureEnv.IsNull())
150   {
151     theCtx->DelayedRelease (myTextureEnv);
152     myTextureEnv.Nullify();
153   }
154
155   if (theTexture.IsNull())
156   {
157     return;
158   }
159
160   myTextureEnv = new OpenGl_Texture (theTexture->GetParams());
161   Handle(Image_PixMap) anImage = theTexture->GetImage();
162   myTextureEnv->Init (theCtx, *anImage.operator->(), theTexture->Type());
163 }
164
165 /*----------------------------------------------------------------------*/
166
167 void OpenGl_View::SetBackfacing (const Standard_Integer theMode)
168 {
169   myBackfacing = theMode;
170 }
171
172 /*----------------------------------------------------------------------*/
173
174 //call_togl_setlight
175 void OpenGl_View::SetLights (const CALL_DEF_VIEWCONTEXT &AContext)
176 {
177   myLights.Clear();
178
179   const int nb_lights = AContext.NbActiveLight;
180
181   int i = 0;
182   const CALL_DEF_LIGHT *alight = &(AContext.ActiveLight[0]);
183   for ( ; i < nb_lights; i++, alight++ )
184   {
185     OpenGl_Light rep;
186
187         switch( alight->LightType )
188     {
189       case 0 : /* TOLS_AMBIENT */
190         rep.type = TLightAmbient;
191         rep.col.rgb[0] = alight->Color.r;
192         rep.col.rgb[1] = alight->Color.g;
193         rep.col.rgb[2] = alight->Color.b;
194         break;
195
196       case 1 : /* TOLS_DIRECTIONAL */
197         rep.type = TLightDirectional;
198         rep.col.rgb[0] = alight->Color.r;
199         rep.col.rgb[1] = alight->Color.g;
200         rep.col.rgb[2] = alight->Color.b;
201         rep.dir[0] = alight->Direction.x;
202         rep.dir[1] = alight->Direction.y;
203         rep.dir[2] = alight->Direction.z;
204         break;
205
206       case 2 : /* TOLS_POSITIONAL */
207         rep.type = TLightPositional;
208         rep.col.rgb[0] = alight->Color.r;
209         rep.col.rgb[1] = alight->Color.g;
210         rep.col.rgb[2] = alight->Color.b;
211         rep.pos[0] = alight->Position.x;
212         rep.pos[1] = alight->Position.y;
213         rep.pos[2] = alight->Position.z;
214         rep.atten[0] = alight->Attenuation[0];
215         rep.atten[1] = alight->Attenuation[1];
216         break;
217
218       case 3 : /* TOLS_SPOT */
219         rep.type = TLightSpot;
220         rep.col.rgb[0] = alight->Color.r;
221         rep.col.rgb[1] = alight->Color.g;
222         rep.col.rgb[2] = alight->Color.b;
223         rep.pos[0] = alight->Position.x;
224         rep.pos[1] = alight->Position.y;
225         rep.pos[2] = alight->Position.z;
226         rep.dir[0] = alight->Direction.x;
227         rep.dir[1] = alight->Direction.y;
228         rep.dir[2] = alight->Direction.z;
229         rep.shine = alight->Concentration;
230         rep.atten[0] = alight->Attenuation[0];
231         rep.atten[1] = alight->Attenuation[1];
232         rep.angle = alight->Angle;
233         break;
234     }
235
236     rep.HeadLight = alight->Headlight;
237
238     myLights.Append(rep);
239   }
240 }
241
242 /*----------------------------------------------------------------------*/
243
244 //call_togl_setplane
245 void OpenGl_View::SetClippingPlanes (const CALL_DEF_VIEWCONTEXT &AContext)
246 {
247   // clear clipping planes information
248   myClippingPlanes.Clear();
249   // update information
250   int i = 0;
251   for (; i < AContext.NbActivePlane; i++)
252   {
253     const CALL_DEF_PLANE &aCPlane = AContext.ActivePlane[i];
254     if ( aCPlane.Active && aCPlane.PlaneId > 0 )
255     {
256       OPENGL_CLIP_REP aPlane;
257       aPlane.equation[0] = aCPlane.CoefA;
258       aPlane.equation[1] = aCPlane.CoefB;
259       aPlane.equation[2] = aCPlane.CoefC;
260       aPlane.equation[3] = aCPlane.CoefD;
261       myClippingPlanes.Append( aPlane );
262     }
263   }
264 }
265
266 /*----------------------------------------------------------------------*/
267
268 //call_togl_setvisualisation
269 void OpenGl_View::SetVisualisation (const CALL_DEF_VIEWCONTEXT &AContext)
270 {
271   myVisualization = AContext.Visualization;
272   // Shading method
273   switch (AContext.Model)
274   {
275     case 1 : /* VISUAL3D_TOM_INTERP_COLOR */
276     case 3 : /* VISUAL3D_TOM_VERTEX */
277       myIntShadingMethod = TEL_SM_GOURAUD;
278       break;
279     default :
280       myIntShadingMethod = TEL_SM_FLAT;
281       break;
282   }
283 }
284
285 /*----------------------------------------------------------------------*/
286
287 //call_togl_cliplimit
288 void OpenGl_View::SetClipLimit (const Graphic3d_CView& theCView)
289 {
290   myZClip.Back.Limit =
291     (theCView.Context.ZClipBackPlane     - theCView.Mapping.BackPlaneDistance) /
292     (theCView.Mapping.FrontPlaneDistance - theCView.Mapping.BackPlaneDistance);
293   myZClip.Front.Limit =
294     (theCView.Context.ZClipFrontPlane    - theCView.Mapping.BackPlaneDistance) /
295     (theCView.Mapping.FrontPlaneDistance - theCView.Mapping.BackPlaneDistance);
296   if (myZClip.Back.Limit < 0.0f)
297     myZClip.Back.Limit = 0.0f;
298   if (myZClip.Front.Limit > 1.0f)
299     myZClip.Front.Limit = 1.0f;
300   if (myZClip.Back.Limit > myZClip.Front.Limit)
301   {
302     myZClip.Back.Limit  = 0.0f;
303     myZClip.Front.Limit = 1.0f;
304   }
305
306   myZClip.Back.IsOn  = (theCView.Context.BackZClipping  != 0);
307   myZClip.Front.IsOn = (theCView.Context.FrontZClipping != 0);
308 }
309
310 /*----------------------------------------------------------------------*/
311
312 //call_togl_viewmapping
313 void OpenGl_View::SetMapping (const Graphic3d_CView& theCView)
314 {
315   const float ratio   = theCView.DefWindow.dy / theCView.DefWindow.dx;
316   const float r_ratio = theCView.DefWindow.dx / theCView.DefWindow.dy;
317
318   TEL_VIEW_MAPPING Map;
319
320   Map.window.xmin = theCView.Mapping.WindowLimit.um;
321   Map.window.ymin = theCView.Mapping.WindowLimit.vm;
322   Map.window.xmax = theCView.Mapping.WindowLimit.uM;
323   Map.window.ymax = theCView.Mapping.WindowLimit.vM;
324
325   Map.viewport.xmin = 0.F;
326   Map.viewport.xmax = ( 1.F < r_ratio ? 1.F : r_ratio );
327   Map.viewport.ymin = 0.F;
328   Map.viewport.ymax = ( 1.F < ratio ? 1.F : ratio );
329   Map.viewport.zmin = 0.F;
330   Map.viewport.zmax = 1.F;
331
332   // projection type
333   switch (theCView.Mapping.Projection)
334   {
335     case 0 :
336       Map.proj = TelPerspective;
337       break;
338     case 1 :
339       Map.proj = TelParallel;
340       break;
341   }
342
343   // projection reference point
344   Map.prp[0] = theCView.Mapping.ProjectionReferencePoint.x;
345   Map.prp[1] = theCView.Mapping.ProjectionReferencePoint.y;
346   Map.prp[2] = theCView.Mapping.ProjectionReferencePoint.z;
347   if (!openglDisplay.IsNull() && !openglDisplay->Walkthrough())
348     Map.prp[2] += theCView.Mapping.FrontPlaneDistance;
349
350   // view plane distance
351   Map.vpd = theCView.Mapping.ViewPlaneDistance;
352
353   // back plane distance
354   Map.bpd = theCView.Mapping.BackPlaneDistance;
355
356   // front plane distance
357   Map.fpd = theCView.Mapping.FrontPlaneDistance;
358
359   Tint err_ind = 0;
360
361   // use user-defined matrix
362   if (theCView.Mapping.IsCustomMatrix)
363   {
364     int i, j;
365     for( i = 0; i < 4; i++ )
366       for( j = 0; j < 4; j++ )
367         myMappingMatrix[i][j] = theCView.Mapping.ProjectionMatrix[i][j];
368   }
369   else
370     TelEvalViewMappingMatrix( &Map, &err_ind, myMappingMatrix );
371
372   if (!err_ind)
373     myExtra.map = Map;
374 }
375
376 /*----------------------------------------------------------------------*/
377
378 //call_togl_vieworientation
379 void OpenGl_View::SetOrientation (const Graphic3d_CView& theCView)
380 {
381   Tfloat Vrp[3];
382   Tfloat Vpn[3];
383   Tfloat Vup[3];
384   Tfloat ScaleFactors[3];
385
386   Vrp[0] = theCView.Orientation.ViewReferencePoint.x;
387   Vrp[1] = theCView.Orientation.ViewReferencePoint.y;
388   Vrp[2] = theCView.Orientation.ViewReferencePoint.z;
389
390   Vpn[0] = theCView.Orientation.ViewReferencePlane.x;
391   Vpn[1] = theCView.Orientation.ViewReferencePlane.y;
392   Vpn[2] = theCView.Orientation.ViewReferencePlane.z;
393
394   Vup[0] = theCView.Orientation.ViewReferenceUp.x;
395   Vup[1] = theCView.Orientation.ViewReferenceUp.y;
396   Vup[2] = theCView.Orientation.ViewReferenceUp.z;
397
398   ScaleFactors[0] = theCView.Orientation.ViewScaleX;
399   ScaleFactors[1] = theCView.Orientation.ViewScaleY;
400   ScaleFactors[2] = theCView.Orientation.ViewScaleZ;
401
402   Tint err_ind = 0;
403
404   // use user-defined matrix
405   if (theCView.Orientation.IsCustomMatrix)
406   {
407     int i, j;
408     for( i = 0; i < 4; i++ )
409       for( j = 0; j < 4; j++ )
410         myOrientationMatrix[i][j] = theCView.Orientation.ModelViewMatrix[i][j];
411   }
412   else
413   {
414     TelEvalViewOrientationMatrix (Vrp, Vpn, Vup, ScaleFactors, &err_ind, myOrientationMatrix);
415   }
416
417   if (!err_ind)
418   {
419     myExtra.vrp[0] = Vrp[0];
420     myExtra.vrp[1] = Vrp[1];
421     myExtra.vrp[2] = Vrp[2];
422
423     myExtra.vpn[0] = Vpn[0];
424     myExtra.vpn[1] = Vpn[1];
425     myExtra.vpn[2] = Vpn[2];
426
427     myExtra.vup[0] = Vup[0];
428     myExtra.vup[1] = Vup[1];
429     myExtra.vup[2] = Vup[2];
430
431     myExtra.scaleFactors[0] = ScaleFactors[0],
432     myExtra.scaleFactors[1] = ScaleFactors[1],
433     myExtra.scaleFactors[2] = ScaleFactors[2];
434   }
435 }
436
437 /*----------------------------------------------------------------------*/
438
439 void OpenGl_View::SetFog (const Graphic3d_CView& theCView,
440                           const Standard_Boolean theFlag)
441 {
442   if (!theFlag)
443   {
444     myFog.IsOn = Standard_False;
445   }
446   else
447   {
448     myFog.IsOn = Standard_True;
449
450     myFog.Front =
451       (theCView.Context.DepthFrontPlane    - theCView.Mapping.BackPlaneDistance) /
452       (theCView.Mapping.FrontPlaneDistance - theCView.Mapping.BackPlaneDistance);
453
454     myFog.Back =
455       (theCView.Context.DepthBackPlane     - theCView.Mapping.BackPlaneDistance) /
456       (theCView.Mapping.FrontPlaneDistance - theCView.Mapping.BackPlaneDistance);
457
458     if (myFog.Front < 0.F)
459       myFog.Front = 0.F;
460     else if (myFog.Front > 1.F)
461       myFog.Front = 1.F;
462
463     if (myFog.Back < 0.F)
464       myFog.Back = 0.F;
465     else if (myFog.Back > 1.F)
466       myFog.Back = 1.F;
467
468     if (myFog.Back > myFog.Front)
469     {
470       myFog.Front = 1.F;
471       myFog.Back = 0.F;
472     }
473
474     myFog.Color.rgb[0] = theCView.DefWindow.Background.r;
475     myFog.Color.rgb[1] = theCView.DefWindow.Background.g;
476     myFog.Color.rgb[2] = theCView.DefWindow.Background.b;
477     myFog.Color.rgb[3] = 1.0f;
478   }
479 }
480
481 /*----------------------------------------------------------------------*/
482
483 void OpenGl_View::TriedronDisplay (const Handle(OpenGl_Context)&       theCtx,
484                                    const Aspect_TypeOfTriedronPosition thePosition,
485                                    const Quantity_NameOfColor          theColor,
486                                    const Standard_Real                 theScale,
487                                    const Standard_Boolean              theAsWireframe)
488 {
489   OpenGl_Element::Destroy (theCtx, myTrihedron);
490   myTrihedron = new OpenGl_Trihedron (thePosition, theColor, theScale, theAsWireframe);
491 }
492
493 /*----------------------------------------------------------------------*/
494
495 void OpenGl_View::TriedronErase (const Handle(OpenGl_Context)& theCtx)
496 {
497   OpenGl_Element::Destroy (theCtx, myTrihedron);
498 }
499
500 /*----------------------------------------------------------------------*/
501
502 void OpenGl_View::GraduatedTrihedronDisplay (const Handle(OpenGl_Context)&        theCtx,
503                                              const Graphic3d_CGraduatedTrihedron& theData)
504 {
505   OpenGl_Element::Destroy (theCtx, myGraduatedTrihedron);
506   myGraduatedTrihedron = new OpenGl_GraduatedTrihedron (theData);
507 }
508
509 /*----------------------------------------------------------------------*/
510
511 void OpenGl_View::GraduatedTrihedronErase (const Handle(OpenGl_Context)& theCtx)
512 {
513   OpenGl_Element::Destroy (theCtx, myGraduatedTrihedron);
514 }
515
516 /*----------------------------------------------------------------------*/
517
518 //transform_persistence_end
519 void OpenGl_View::EndTransformPersistence()
520 {
521   if (myIsTransPers)
522   {
523     // restore matrix
524     glMatrixMode (GL_PROJECTION);
525     glPopMatrix();
526     glMatrixMode (GL_MODELVIEW);
527     glPopMatrix();
528     myIsTransPers = Standard_False;
529   }
530 }
531
532 /*----------------------------------------------------------------------*/
533
534 //transform_persistence_begin
535 const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const TEL_TRANSFORM_PERSISTENCE* theTransPers)
536 {
537   const TEL_TRANSFORM_PERSISTENCE* aTransPersPrev = myTransPers;
538   myTransPers = theTransPers;
539   if (theTransPers->mode == 0)
540   {
541     EndTransformPersistence();
542     return aTransPersPrev;
543   }
544
545   GLint aViewport[4];
546   GLdouble aModelMatrix[4][4];
547   GLdouble aProjMatrix[4][4];
548   glGetIntegerv (GL_VIEWPORT,          aViewport);
549   glGetDoublev  (GL_MODELVIEW_MATRIX,  (GLdouble* )aModelMatrix);
550   glGetDoublev  (GL_PROJECTION_MATRIX, (GLdouble *)aProjMatrix);
551   const GLdouble aViewportW = (GLdouble )aViewport[2];
552   const GLdouble aViewportH = (GLdouble )aViewport[3];
553
554   if (myIsTransPers)
555   {
556     // pop matrix stack - it will be overridden later
557     glMatrixMode (GL_PROJECTION);
558     glPopMatrix();
559     glMatrixMode (GL_MODELVIEW);
560     glPopMatrix();
561   }
562   else
563   {
564     myIsTransPers = Standard_True;
565   }
566
567   // push matrices into stack and reset them
568   glMatrixMode (GL_MODELVIEW);
569   glPushMatrix();
570   glLoadIdentity();
571
572   glMatrixMode (GL_PROJECTION);
573   glPushMatrix();
574   glLoadIdentity();
575
576   // get the window's (fixed) coordinates for theTransPers->point before matrixes modifications
577   GLdouble aWinX = 0.0, aWinY = 0.0, aWinZ = 0.0;
578   if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
579   {
580     gluProject (theTransPers->pointX, theTransPers->pointY, theTransPers->pointZ,
581                 (GLdouble* )aModelMatrix, (GLdouble* )aProjMatrix, aViewport,
582                 &aWinX, &aWinY, &aWinZ);
583   }
584
585   // prevent zooming
586   if ((theTransPers->mode & TPF_ZOOM)
587    || (theTransPers->mode == TPF_TRIEDRON))
588   {
589     // compute fixed-zoom multiplier
590     // actually function works ugly with TelPerspective!
591     const GLdouble aDet2 = 0.002 / (aViewportW > aViewportH ? aProjMatrix[1][1] : aProjMatrix[0][0]);
592     aProjMatrix[0][0] *= aDet2;
593     aProjMatrix[1][1] *= aDet2;
594     aProjMatrix[2][2] *= aDet2;
595   }
596
597   // prevent translation - annulate translate matrix
598   if ((theTransPers->mode & TPF_PAN)
599    || (theTransPers->mode == TPF_TRIEDRON))
600   {
601     aModelMatrix[3][0] = 0.0;
602     aModelMatrix[3][1] = 0.0;
603     aModelMatrix[3][2] = 0.0;
604     aProjMatrix [3][0] = 0.0;
605     aProjMatrix [3][1] = 0.0;
606     aProjMatrix [3][2] = 0.0;
607   }
608
609   // prevent scaling-on-axis
610   if (theTransPers->mode & TPF_ZOOM)
611   {
612     const double aScaleX = myExtra.scaleFactors[0];
613     const double aScaleY = myExtra.scaleFactors[1];
614     const double aScaleZ = myExtra.scaleFactors[2];
615     for (int i = 0; i < 3; ++i)
616     {
617       aModelMatrix[0][i] /= aScaleX;
618       aModelMatrix[1][i] /= aScaleY;
619       aModelMatrix[2][i] /= aScaleZ;
620     }
621   }
622
623   // prevent rotating - annulate rotate matrix
624   if (theTransPers->mode & TPF_ROTATE)
625   {
626     aModelMatrix[0][0] = 1.0;
627     aModelMatrix[1][1] = 1.0;
628     aModelMatrix[2][2] = 1.0;
629
630     aModelMatrix[1][0] = 0.0;
631     aModelMatrix[2][0] = 0.0;
632     aModelMatrix[0][1] = 0.0;
633     aModelMatrix[2][1] = 0.0;
634     aModelMatrix[0][2] = 0.0;
635     aModelMatrix[1][2] = 0.0;
636   }
637
638   // load computed matrices
639   glMatrixMode (GL_MODELVIEW);
640   glMultMatrixd ((GLdouble* )aModelMatrix);
641
642   glMatrixMode (GL_PROJECTION);
643   glMultMatrixd ((GLdouble* )aProjMatrix);
644
645   if (theTransPers->mode == TPF_TRIEDRON)
646   {
647     // move to the window corner
648     if (theTransPers->pointX != 0.0
649      && theTransPers->pointY != 0.0)
650     {
651       GLdouble aW1, aH1, aW2, aH2, aDummy;
652       glMatrixMode (GL_PROJECTION);
653       gluUnProject ( 0.5 * aViewportW,  0.5 * aViewportH, 0.0,
654                     (GLdouble* )THE_IDENTITY_MATRIX, (GLdouble* )aProjMatrix, aViewport,
655                     &aW1, &aH1, &aDummy);
656       gluUnProject (-0.5 * aViewportW, -0.5 * aViewportH, 0.0,
657                     (GLdouble* )THE_IDENTITY_MATRIX, (GLdouble* )aProjMatrix, aViewport,
658                     &aW2, &aH2, &aDummy);
659       GLdouble aMoveX = 0.5 * (aW1 - aW2 - theTransPers->pointZ);
660       GLdouble aMoveY = 0.5 * (aH1 - aH2 - theTransPers->pointZ);
661       aMoveX = (theTransPers->pointX > 0.0) ? aMoveX : -aMoveX;
662       aMoveY = (theTransPers->pointY > 0.0) ? aMoveY : -aMoveY;
663       glTranslated (aMoveX, aMoveY, 0.0);
664     }
665   }
666   else if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
667   {
668     // move to thePoint using saved win-coordinates ('marker-behaviour')
669     GLdouble aMoveX, aMoveY, aMoveZ;
670     glGetDoublev (GL_MODELVIEW_MATRIX,  (GLdouble* )aModelMatrix);
671     glGetDoublev (GL_PROJECTION_MATRIX, (GLdouble* )aProjMatrix);
672     gluUnProject (aWinX, aWinY, aWinZ,
673                   (GLdouble* )aModelMatrix, (GLdouble* )aProjMatrix, aViewport,
674                   &aMoveX, &aMoveY, &aMoveZ);
675
676     glMatrixMode (GL_MODELVIEW);
677     glTranslated (aMoveX, aMoveY, aMoveZ);
678   }
679
680   return aTransPersPrev;
681 }