0026122: Visualization, TKOpenGl - clipping and capping is broken when ffp is disable...
[occt.git] / src / OpenGl / OpenGl_CappingPlaneResource.cxx
1 // Created on: 2013-08-15
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <NCollection_AlignedAllocator.hxx>
17 #include <OpenGl_CappingPlaneResource.hxx>
18 #include <OpenGl_Context.hxx>
19 #include <OpenGl_Vec.hxx>
20 #include <Precision.hxx>
21
22 namespace
23 {
24   //! 12 plane vertices, interleaved:
25   //!  - 4 floats, position
26   //!  - 4 floats, normal
27   //!  - 4 floats, UV texture coordinates
28   static const GLfloat THE_CAPPING_PLN_VERTS[12 * (4 + 4 + 4)] =
29   {
30     0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
31     1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f,
32     0.0f, 0.0f, 1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
33
34     0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
35     0.0f, 0.0f, 1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
36    -1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
37
38     0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
39    -1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
40     0.0f, 0.0f,-1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f,
41
42     0.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
43     0.0f, 0.0f,-1.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f,
44     1.0f, 0.0f, 0.0f, 0.0f,  0.0f, 1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f
45   };
46
47   static const OpenGl_Matrix OpenGl_IdentityMatrix =
48   {
49     // mat[4][4]
50     { { 1.0f, 0.0f, 0.0f, 0.0f },
51       { 0.0f, 1.0f, 0.0f, 0.0f },
52       { 0.0f, 0.0f, 1.0f, 0.0f },
53       { 0.0f, 0.0f, 0.0f, 1.0f } }
54   };
55
56 }
57
58
59 // =======================================================================
60 // function : OpenGl_CappingPlaneResource
61 // purpose  :
62 // =======================================================================
63 OpenGl_CappingPlaneResource::OpenGl_CappingPlaneResource (const Handle(Graphic3d_ClipPlane)& thePlane)
64 : myPrimitives  (NULL),
65   myOrientation (OpenGl_IdentityMatrix),
66   myAspect      (NULL),
67   myPlaneRoot   (thePlane),
68   myEquationMod ((unsigned int )-1),
69   myAspectMod   ((unsigned int )-1)
70 {
71   // Fill primitive array
72   Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
73   Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (anAlloc);
74   Graphic3d_Attribute anAttribInfo[] =
75   {
76     { Graphic3d_TOA_POS,  Graphic3d_TOD_VEC4 },
77     { Graphic3d_TOA_NORM, Graphic3d_TOD_VEC4 },
78     { Graphic3d_TOA_UV,   Graphic3d_TOD_VEC4 }
79   };
80   if (anAttribs->Init (12, anAttribInfo, 3))
81   {
82     memcpy (anAttribs->ChangeData(), THE_CAPPING_PLN_VERTS, sizeof(THE_CAPPING_PLN_VERTS));
83     myPrimitives.InitBuffers (NULL, Graphic3d_TOPA_TRIANGLES, NULL, anAttribs, NULL);
84   }
85 }
86
87 // =======================================================================
88 // function : OpenGl_CappingPlaneResource
89 // purpose  :
90 // =======================================================================
91 OpenGl_CappingPlaneResource::~OpenGl_CappingPlaneResource()
92 {
93   Release (NULL);
94 }
95
96 // =======================================================================
97 // function : Update
98 // purpose  :
99 // =======================================================================
100 void OpenGl_CappingPlaneResource::Update (const Handle(OpenGl_Context)& theContext)
101 {
102   UpdateTransform();
103   UpdateAspect (theContext);
104 }
105
106 // =======================================================================
107 // function : Release
108 // purpose  :
109 // =======================================================================
110 void OpenGl_CappingPlaneResource::Release (OpenGl_Context* theContext)
111 {
112   OpenGl_Element::Destroy (theContext, myAspect);
113   myPrimitives.Release (theContext);
114   myEquationMod = (unsigned int )-1;
115   myAspectMod   = (unsigned int )-1;
116 }
117
118 // =======================================================================
119 // function : UpdateAspect
120 // purpose  :
121 // =======================================================================
122 void OpenGl_CappingPlaneResource::UpdateAspect (const Handle(OpenGl_Context)& theContext)
123 {
124   Handle(Graphic3d_AspectFillArea3d) aCappingAsp = myPlaneRoot->CappingAspect();
125   if (myAspect != NULL && !aCappingAsp.IsNull())
126   {
127     if (myAspectMod == myPlaneRoot->MCountAspect())
128       return; // noting to update
129     
130     myAspect->SetAspect (aCappingAsp);
131     myAspectMod = myPlaneRoot->MCountAspect();
132     return;
133   }
134
135   // no more used
136   if (myAspect != NULL && aCappingAsp.IsNull())
137   {
138     OpenGl_Element::Destroy (theContext.operator->(), myAspect);
139     myAspectMod = myPlaneRoot->MCountAspect();
140     return;
141   }
142
143   // first created
144   if (myAspect == NULL && !aCappingAsp.IsNull())
145   {
146     myAspect = new OpenGl_AspectFace();
147     myAspect->SetAspect (aCappingAsp);
148     myAspectMod = myPlaneRoot->MCountAspect();
149   }
150 }
151
152 // =======================================================================
153 // function : UpdateTransform
154 // purpose  :
155 // =======================================================================
156 void OpenGl_CappingPlaneResource::UpdateTransform()
157 {
158   const Graphic3d_ClipPlane::Equation& anEquation = myPlaneRoot->GetEquation();
159   if (myEquationMod == myPlaneRoot->MCountEquation())
160   {
161     return; // nothing to update
162   }
163
164   // re-evaluate infinite plane transformation matrix
165   Standard_ShortReal N[3] = 
166     { (Standard_ShortReal)anEquation[0],
167       (Standard_ShortReal)anEquation[1],
168       (Standard_ShortReal)anEquation[2] };
169
170   Standard_ShortReal T[3] = 
171     { (Standard_ShortReal)(anEquation[0] * -anEquation[3]),
172       (Standard_ShortReal)(anEquation[1] * -anEquation[3]),
173       (Standard_ShortReal)(anEquation[2] * -anEquation[3]) };
174
175   Standard_ShortReal L[3] = { 0.0f, 0.0f, 0.0f };
176   Standard_ShortReal F[3] = { 0.0f, 0.0f, 0.0f };
177
178   // project plane normal onto OX to find left vector
179   Standard_ShortReal aProjLen = 
180     sqrt (  (Standard_ShortReal)(anEquation[0] * anEquation[0])
181           + (Standard_ShortReal)(anEquation[2] * anEquation[2]));
182   if (aProjLen < ShortRealSmall())
183   {
184     L[0] = 1.0f;
185   }
186   else
187   {
188     L[0] =  N[2] / aProjLen;
189     L[2] = -N[0] / aProjLen;
190   }
191
192   // (-aLeft) x aNorm
193   F[0] = (-L[1])*N[2] - (-L[2])*N[1];
194   F[1] = (-L[2])*N[0] - (-L[0])*N[2];
195   F[2] = (-L[0])*N[1] - (-L[1])*N[0];
196
197   myOrientation.mat[0][0] = L[0];
198   myOrientation.mat[0][1] = L[1];
199   myOrientation.mat[0][2] = L[2];
200   myOrientation.mat[0][3] = 0.0f;
201
202   myOrientation.mat[1][0] = N[0];
203   myOrientation.mat[1][1] = N[1];
204   myOrientation.mat[1][2] = N[2];
205   myOrientation.mat[1][3] = 0.0f;
206
207   myOrientation.mat[2][0] = F[0];
208   myOrientation.mat[2][1] = F[1];
209   myOrientation.mat[2][2] = F[2];
210   myOrientation.mat[2][3] = 0.0f;
211
212   myOrientation.mat[3][0] = T[0];
213   myOrientation.mat[3][1] = T[1];
214   myOrientation.mat[3][2] = T[2];
215   myOrientation.mat[3][3] = 1.0f;
216
217   myEquationMod = myPlaneRoot->MCountEquation();
218 }