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