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