0029528: Visualization, TKOpenGl - allow defining sRGB textures
[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 <OpenGl_ShaderManager.hxx>
21 #include <Precision.hxx>
22
23 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingPlaneResource,OpenGl_Resource)
24
25 namespace
26 {
27   //! 12 plane vertices, interleaved:
28   //!  - 4 floats, position
29   //!  - 4 floats, normal
30   //!  - 4 floats, UV texture coordinates
31   static const GLfloat THE_CAPPING_PLN_VERTS[12 * (4 + 4 + 4)] =
32   {
33     0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
34     0.0f, 0.0f, 1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
35     1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f,
36
37     0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
38    -1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
39     0.0f, 0.0f, 1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f,-1.0f, 0.0f, 0.0f,
40
41     0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
42     0.0f, 0.0f,-1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f,
43    -1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,  -1.0f, 0.0f, 0.0f, 0.0f,
44
45     0.0f, 0.0f, 0.0f, 1.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f, 1.0f,
46     1.0f, 0.0f, 0.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   1.0f, 0.0f, 0.0f, 0.0f,
47     0.0f, 0.0f,-1.0f, 0.0f,  0.0f,-1.0f, 0.0f, 0.0f,   0.0f, 1.0f, 0.0f, 0.0f
48   };
49
50   static const OpenGl_Matrix OpenGl_IdentityMatrix =
51   {
52     // mat[4][4]
53     { { 1.0f, 0.0f, 0.0f, 0.0f },
54       { 0.0f, 1.0f, 0.0f, 0.0f },
55       { 0.0f, 0.0f, 1.0f, 0.0f },
56       { 0.0f, 0.0f, 0.0f, 1.0f } }
57   };
58
59 }
60
61
62 // =======================================================================
63 // function : OpenGl_CappingPlaneResource
64 // purpose  :
65 // =======================================================================
66 OpenGl_CappingPlaneResource::OpenGl_CappingPlaneResource (const Handle(Graphic3d_ClipPlane)& thePlane)
67 : myPrimitives  (NULL),
68   myOrientation (OpenGl_IdentityMatrix),
69   myAspect      (NULL),
70   myPlaneRoot   (thePlane),
71   myEquationMod ((unsigned int )-1),
72   myAspectMod   ((unsigned int )-1)
73 {
74   // Fill primitive array
75   Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
76   Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (anAlloc);
77   Graphic3d_Attribute anAttribInfo[] =
78   {
79     { Graphic3d_TOA_POS,  Graphic3d_TOD_VEC4 },
80     { Graphic3d_TOA_NORM, Graphic3d_TOD_VEC4 },
81     { Graphic3d_TOA_UV,   Graphic3d_TOD_VEC4 }
82   };
83   if (anAttribs->Init (12, anAttribInfo, 3))
84   {
85     memcpy (anAttribs->ChangeData(), THE_CAPPING_PLN_VERTS, sizeof(THE_CAPPING_PLN_VERTS));
86     myPrimitives.InitBuffers (NULL, Graphic3d_TOPA_TRIANGLES, NULL, anAttribs, NULL);
87   }
88 }
89
90 // =======================================================================
91 // function : OpenGl_CappingPlaneResource
92 // purpose  :
93 // =======================================================================
94 OpenGl_CappingPlaneResource::~OpenGl_CappingPlaneResource()
95 {
96   Release (NULL);
97 }
98
99 // =======================================================================
100 // function : Update
101 // purpose  :
102 // =======================================================================
103 void OpenGl_CappingPlaneResource::Update (const Handle(OpenGl_Context)& theCtx,
104                                           const Handle(Graphic3d_Aspects)& theObjAspect)
105 {
106   updateTransform (theCtx);
107   updateAspect (theObjAspect);
108 }
109
110 // =======================================================================
111 // function : Release
112 // purpose  :
113 // =======================================================================
114 void OpenGl_CappingPlaneResource::Release (OpenGl_Context* theContext)
115 {
116   OpenGl_Element::Destroy (theContext, myAspect);
117   myPrimitives.Release (theContext);
118   myEquationMod = (unsigned int )-1;
119   myAspectMod   = (unsigned int )-1;
120 }
121
122 // =======================================================================
123 // function : updateAspect
124 // purpose  :
125 // =======================================================================
126 void OpenGl_CappingPlaneResource::updateAspect (const Handle(Graphic3d_Aspects)& theObjAspect)
127 {
128   if (myAspect == NULL)
129   {
130     myAspect = new OpenGl_Aspects();
131     myAspectMod = myPlaneRoot->MCountAspect() - 1; // mark out of sync
132   }
133
134   if (theObjAspect.IsNull())
135   {
136     if (myAspectMod != myPlaneRoot->MCountAspect())
137     {
138       myAspect->SetAspect (myPlaneRoot->CappingAspect());
139       myAspectMod = myPlaneRoot->MCountAspect();
140     }
141     return;
142   }
143
144   if (myFillAreaAspect.IsNull())
145   {
146     myFillAreaAspect = new Graphic3d_AspectFillArea3d();
147   }
148   if (myAspectMod != myPlaneRoot->MCountAspect())
149   {
150     *myFillAreaAspect = *myPlaneRoot->CappingAspect();
151   }
152
153   if (myPlaneRoot->ToUseObjectMaterial())
154   {
155     // only front material currently supported by capping rendering
156     myFillAreaAspect->SetFrontMaterial (theObjAspect->FrontMaterial());
157     myFillAreaAspect->SetInteriorColor (theObjAspect->InteriorColor());
158   }
159   if (myPlaneRoot->ToUseObjectTexture())
160   {
161     myFillAreaAspect->SetTextureSet (theObjAspect->TextureSet());
162     if (theObjAspect->ToMapTexture())
163     {
164       myFillAreaAspect->SetTextureMapOn();
165     }
166     else
167     {
168       myFillAreaAspect->SetTextureMapOff();
169     }
170   }
171   if (myPlaneRoot->ToUseObjectShader())
172   {
173     myFillAreaAspect->SetShaderProgram (theObjAspect->ShaderProgram());
174   }
175
176   myAspect->SetAspect (myFillAreaAspect);
177 }
178
179 // =======================================================================
180 // function : updateTransform
181 // purpose  :
182 // =======================================================================
183 void OpenGl_CappingPlaneResource::updateTransform (const Handle(OpenGl_Context)& theCtx)
184 {
185   if (myEquationMod == myPlaneRoot->MCountEquation()
186    && myLocalOrigin.IsEqual (theCtx->ShaderManager()->LocalOrigin(), gp::Resolution()))
187   {
188     return; // nothing to update
189   }
190
191   myEquationMod = myPlaneRoot->MCountEquation();
192   myLocalOrigin = theCtx->ShaderManager()->LocalOrigin();
193
194   const Graphic3d_ClipPlane::Equation& anEq = myPlaneRoot->GetEquation();
195   const Standard_Real anEqW = theCtx->ShaderManager()->LocalClippingPlaneW (*myPlaneRoot);
196
197   // re-evaluate infinite plane transformation matrix
198   const Graphic3d_Vec3 aNorm (anEq.xyz());
199   const Graphic3d_Vec3 T (anEq.xyz() * -anEqW);
200
201   // project plane normal onto OX to find left vector
202   const Standard_ShortReal aProjLen = sqrt ((Standard_ShortReal)anEq.xz().SquareModulus());
203   Graphic3d_Vec3 aLeft;
204   if (aProjLen < ShortRealSmall())
205   {
206     aLeft[0] = 1.0f;
207   }
208   else
209   {
210     aLeft[0] =  aNorm[2] / aProjLen;
211     aLeft[2] = -aNorm[0] / aProjLen;
212   }
213
214   const Graphic3d_Vec3 F = Graphic3d_Vec3::Cross (-aLeft, aNorm);
215
216   myOrientation.mat[0][0] = aLeft[0];
217   myOrientation.mat[0][1] = aLeft[1];
218   myOrientation.mat[0][2] = aLeft[2];
219   myOrientation.mat[0][3] = 0.0f;
220
221   myOrientation.mat[1][0] = aNorm[0];
222   myOrientation.mat[1][1] = aNorm[1];
223   myOrientation.mat[1][2] = aNorm[2];
224   myOrientation.mat[1][3] = 0.0f;
225
226   myOrientation.mat[2][0] = F[0];
227   myOrientation.mat[2][1] = F[1];
228   myOrientation.mat[2][2] = F[2];
229   myOrientation.mat[2][3] = 0.0f;
230
231   myOrientation.mat[3][0] = T[0];
232   myOrientation.mat[3][1] = T[1];
233   myOrientation.mat[3][2] = T[2];
234   myOrientation.mat[3][3] = 1.0f;
235 }