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