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