0023544: Texture management in TKOpenGl should be redesigned
[occt.git] / src / OpenGl / OpenGl_AspectFace.cxx
1 // Created on: 2011-07-13
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_AspectFace.hxx>
21 #include <OpenGl_Texture.hxx>
22 #include <OpenGl_Workspace.hxx>
23 #include <OpenGl_Context.hxx>
24
25 #include <Aspect_PolygonOffsetMode.hxx>
26 #include <Graphic3d_CGroup.hxx>
27 #include <Graphic3d_TextureMap.hxx>
28
29 namespace
30 {
31
32   static OPENGL_SURF_PROP THE_DEFAULT_MATERIAL =
33   {
34     0.2F,  0.8F, 0.1F, 0.0F, // amb, diff, spec, emsv
35     1.0F, 10.0F, 0.0F,       // trans, shine, env_reflexion
36     0, // isphysic
37     (OPENGL_AMBIENT_MASK | OPENGL_DIFFUSE_MASK | OPENGL_SPECULAR_MASK), // color_mask
38     {{ 1.0F, 1.0F, 1.0F, 1.0F }}, // ambient color
39     {{ 1.0F, 1.0F, 1.0F, 1.0F }}, // diffuse color
40     {{ 1.0F, 1.0F, 1.0F, 1.0F }}, // specular color
41     {{ 1.0F, 1.0F, 1.0F, 1.0F }}, // emissive color
42     {{ 1.0F, 1.0F, 1.0F, 1.0F }}  // material color
43   };
44
45   static TEL_POFFSET_PARAM THE_DEFAULT_POFFSET = { Aspect_POM_Fill, 1.0F, 0.0F };
46
47 };
48
49 // =======================================================================
50 // function : convertMaterial
51 // purpose  :
52 // =======================================================================
53 void OpenGl_AspectFace::convertMaterial (const CALL_DEF_MATERIAL& theMat,
54                                          OPENGL_SURF_PROP&        theSurf)
55 {
56   theSurf.amb  = theMat.IsAmbient  ? theMat.Ambient  : 0.0f;
57   theSurf.diff = theMat.IsDiffuse  ? theMat.Diffuse  : 0.0f;
58   theSurf.spec = theMat.IsSpecular ? theMat.Specular : 0.0f;
59   theSurf.emsv = theMat.IsEmission ? theMat.Emission : 0.0f;
60
61   theSurf.isphysic = theMat.IsPhysic ? 1 : 0; // type of material
62
63   // color of material
64   theSurf.color_mask = 0;
65   if (theMat.IsAmbient)
66   {
67     theSurf.color_mask |= OPENGL_AMBIENT_MASK;
68   }
69   if (theMat.IsDiffuse)
70   {
71     theSurf.color_mask |= OPENGL_DIFFUSE_MASK;
72   }
73   if (theMat.IsSpecular)
74   {
75     theSurf.color_mask |= OPENGL_SPECULAR_MASK;
76   }
77   if (theMat.IsEmission)
78   {
79     theSurf.color_mask |= OPENGL_EMISSIVE_MASK;
80   }
81
82   // ambient color
83   theSurf.ambcol.rgb[0] = theMat.ColorAmb.r;
84   theSurf.ambcol.rgb[1] = theMat.ColorAmb.g;
85   theSurf.ambcol.rgb[2] = theMat.ColorAmb.b;
86   theSurf.ambcol.rgb[3] = 1.0f;
87
88   // diffuse color
89   theSurf.difcol.rgb[0] = theMat.ColorDif.r;
90   theSurf.difcol.rgb[1] = theMat.ColorDif.g;
91   theSurf.difcol.rgb[2] = theMat.ColorDif.b;
92   theSurf.difcol.rgb[3] = 1.0f;
93
94   // specular color
95   theSurf.speccol.rgb[0] = theMat.ColorSpec.r;
96   theSurf.speccol.rgb[1] = theMat.ColorSpec.g;
97   theSurf.speccol.rgb[2] = theMat.ColorSpec.b;
98   theSurf.speccol.rgb[3] = 1.0f;
99
100   // emission color
101   theSurf.emscol.rgb[0] = theMat.ColorEms.r;
102   theSurf.emscol.rgb[1] = theMat.ColorEms.g;
103   theSurf.emscol.rgb[2] = theMat.ColorEms.b;
104   theSurf.emscol.rgb[3] = 1.0f;
105
106   theSurf.shine = 128.0f * float(theMat.Shininess);
107   theSurf.env_reflexion = theMat.EnvReflexion;
108
109   // trans = 0. => opaque
110   // trans = 1. => transparent
111   // in OpenGl it is opposite.
112   theSurf.trans = 1.0f - theMat.Transparency;
113 }
114
115 // =======================================================================
116 // function : OpenGl_AspectFace
117 // purpose  :
118 // =======================================================================
119 OpenGl_AspectFace::OpenGl_AspectFace()
120 : InteriorStyle (Aspect_IS_SOLID),
121   Edge (Aspect_IS_SOLID),
122   Hatch (TOn),
123   DistinguishingMode (TEL_HS_SOLID),
124   CullingMode (TelCullNone),
125   doTextureMap (0)
126 {
127   IntFront      = THE_DEFAULT_MATERIAL;
128   IntBack       = THE_DEFAULT_MATERIAL;
129   PolygonOffset = THE_DEFAULT_POFFSET;
130 }
131
132 // =======================================================================
133 // function : Init
134 // purpose  :
135 // =======================================================================
136 void OpenGl_AspectFace::Init (const Handle(OpenGl_Context)&   theContext,
137                               const CALL_DEF_CONTEXTFILLAREA& theAspect)
138 {
139   InteriorStyle = (Aspect_InteriorStyle )theAspect.Style;
140   Edge = theAspect.Edge ? TOn : TOff;
141
142   //TelInteriorStyleIndex
143   switch (theAspect.Hatch)
144   {
145     case 0: /* Aspect_HS_HORIZONTAL */
146       Hatch = TEL_HS_HORIZONTAL;
147       break;
148     case 1: /* Aspect_HS_HORIZONTAL_WIDE */
149       Hatch = TEL_HS_HORIZONTAL_SPARSE;
150       break;
151     case 2: /* Aspect_HS_VERTICAL */
152       Hatch = TEL_HS_VERTICAL;
153       break;
154     case 3: /* Aspect_HS_VERTICAL_WIDE */
155       Hatch = TEL_HS_VERTICAL_SPARSE;
156       break;
157     case 4: /* Aspect_HS_DIAGONAL_45 */
158       Hatch = TEL_HS_DIAG_45;
159       break;
160     case 5: /* Aspect_HS_DIAGONAL_45_WIDE */
161       Hatch = TEL_HS_DIAG_45_SPARSE;
162       break;
163     case 6: /* Aspect_HS_DIAGONAL_135 */
164       Hatch = TEL_HS_DIAG_135;
165       break;
166     case 7: /* Aspect_HS_DIAGONAL_135_WIDE */
167       Hatch = TEL_HS_DIAG_135_SPARSE;
168       break;
169     case 8: /* Aspect_HS_GRID */
170       Hatch = TEL_HS_GRID;
171       break;
172     case 9: /* Aspect_HS_GRID_WIDE */
173       Hatch = TEL_HS_GRID_SPARSE;
174       break;
175     case 10: /* Aspect_HS_GRID_DIAGONAL */
176       Hatch = TEL_HS_CROSS;
177       break;
178     case 11: /* Aspect_HS_GRID_DIAGONAL_WIDE */
179       Hatch = TEL_HS_CROSS_SPARSE;
180       break;
181     default:
182       Hatch = 0;
183       break;
184   }
185
186   DistinguishingMode = theAspect.Distinguish ? TOn : TOff;
187   CullingMode = theAspect.BackFace ? TelCullBack : TelCullNone;
188
189   convertMaterial (theAspect.Front, IntFront);
190   convertMaterial (theAspect.Back,  IntBack);
191
192   //TelInteriorColour
193   IntFront.matcol.rgb[0] = (float )theAspect.IntColor.r;
194   IntFront.matcol.rgb[1] = (float )theAspect.IntColor.g;
195   IntFront.matcol.rgb[2] = (float )theAspect.IntColor.b;
196   IntFront.matcol.rgb[3] = 1.0f;
197
198   //TelBackInteriorColour
199   IntBack.matcol.rgb[0] = (float )theAspect.BackIntColor.r;
200   IntBack.matcol.rgb[1] = (float )theAspect.BackIntColor.g;
201   IntBack.matcol.rgb[2] = (float )theAspect.BackIntColor.b;
202   IntBack.matcol.rgb[3] = 1.0f;
203
204   // setup texture
205   doTextureMap = theAspect.Texture.doTextureMap;
206   const Handle(Graphic3d_TextureMap)& aNewTexture = theAspect.Texture.TextureMap;
207   TCollection_AsciiString aNewKey = aNewTexture.IsNull() ? TCollection_AsciiString() : aNewTexture->GetId();
208   TextureParams = aNewTexture.IsNull() ? NULL : aNewTexture->GetParams();
209   if (aNewKey.IsEmpty()
210    || myTextureId != aNewKey)
211   {
212     if (!TextureRes.IsNull())
213     {
214       if (myTextureId.IsEmpty())
215       {
216         theContext->DelayedRelease (TextureRes);
217         TextureRes.Nullify();
218       }
219       else
220       {
221         TextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call
222         theContext->ReleaseResource (myTextureId);
223       }
224     }
225     myTextureId = aNewKey;
226
227     if (!aNewTexture.IsNull())
228     {
229       if (aNewKey.IsEmpty() || !theContext->GetResource<Handle(OpenGl_Texture)> (aNewKey, TextureRes))
230       {
231         TextureRes = new OpenGl_Texture (TextureParams);
232         Handle(Image_PixMap) anImage = aNewTexture->GetImage();
233         if (!anImage.IsNull())
234         {
235           TextureRes->Init (theContext, *anImage.operator->(), aNewTexture->Type());
236         }
237         if (!aNewKey.IsEmpty())
238         {
239           theContext->ShareResource (aNewKey, TextureRes);
240         }
241       }
242     }
243   }
244
245   //TelPolygonOffset
246   PolygonOffset.mode   = (Aspect_PolygonOffsetMode )theAspect.PolygonOffsetMode;
247   PolygonOffset.factor = theAspect.PolygonOffsetFactor;
248   PolygonOffset.units  = theAspect.PolygonOffsetUnits;
249
250   CALL_DEF_CONTEXTLINE anEdgeContext;
251   anEdgeContext.Color.r  = (float )theAspect.EdgeColor.r;
252   anEdgeContext.Color.g  = (float )theAspect.EdgeColor.g;
253   anEdgeContext.Color.b  = (float )theAspect.EdgeColor.b;
254   anEdgeContext.LineType = (Aspect_TypeOfLine )theAspect.LineType;
255   anEdgeContext.Width    = (float )theAspect.Width;
256   myAspectEdge.SetContext (anEdgeContext);
257 }
258
259 // =======================================================================
260 // function : Render
261 // purpose  :
262 // =======================================================================
263 void OpenGl_AspectFace::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
264 {
265   theWorkspace->SetAspectFace (this);
266 }
267
268 // =======================================================================
269 // function : Release
270 // purpose  :
271 // =======================================================================
272 void OpenGl_AspectFace::Release (const Handle(OpenGl_Context)& theContext)
273 {
274   if (!TextureRes.IsNull())
275   {
276     if (!theContext.IsNull())
277     {
278       if (myTextureId.IsEmpty())
279       {
280         theContext->DelayedRelease (TextureRes);
281       }
282       else
283       {
284         TextureRes.Nullify(); // we need nullify all handles before ReleaseResource() call
285         theContext->ReleaseResource (myTextureId);
286       }
287     }
288     TextureRes.Nullify();
289   }
290   myTextureId.Clear();
291 }