7857ccbe7fe644dabaeb7838120fe08f6cbb33f0
[occt.git] / src / OpenGl / OpenGl_BackgroundArray.cxx
1 // Created on: 2015-01-16
2 // Created by: Anastasia BORISOVA
3 // Copyright (c) 2015 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 <OpenGl_BackgroundArray.hxx>
17
18 #include <Aspect_FillMethod.hxx>
19 #include <NCollection_AlignedAllocator.hxx>
20 #include <OpenGl_Texture.hxx>
21
22 // =======================================================================
23 // method  : Constructor
24 // purpose :
25 // =======================================================================
26 OpenGl_BackgroundArray::OpenGl_BackgroundArray (const Graphic3d_TypeOfBackground theType)
27 : OpenGl_PrimitiveArray (NULL, Graphic3d_TOPA_TRIANGLESTRIPS, NULL, NULL, NULL),
28   myToUpdate (Standard_False),
29   myType (theType),
30   myViewWidth (0),
31   myViewHeight (0),
32   myFillMethod (Aspect_FM_NONE)
33 {
34   Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
35   myAttribs = new Graphic3d_Buffer (anAlloc);
36
37   myDrawMode = GL_TRIANGLE_STRIP;
38
39   myGradientParams.color1 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
40   myGradientParams.color2 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
41   myGradientParams.type   = Aspect_GFM_NONE;
42 }
43
44 // =======================================================================
45 // method  : SetTextureParameters
46 // purpose :
47 // =======================================================================
48 void OpenGl_BackgroundArray::SetTextureParameters (const Aspect_FillMethod theFillMethod)
49 {
50   if (myType != Graphic3d_TOB_TEXTURE)
51   {
52     return;
53   }
54
55   myFillMethod = theFillMethod;
56   invalidateData();
57 }
58
59 // =======================================================================
60 // method  : SetTextureFillMethod
61 // purpose :
62 // =======================================================================
63 void OpenGl_BackgroundArray::SetTextureFillMethod (const Aspect_FillMethod theFillMethod)
64 {
65   myFillMethod = theFillMethod;
66   invalidateData();
67 }
68
69 // =======================================================================
70 // method  : SetGradientParameters
71 // purpose :
72 // =======================================================================
73 void OpenGl_BackgroundArray::SetGradientParameters (const Quantity_Color&           theColor1,
74                                                     const Quantity_Color&           theColor2,
75                                                     const Aspect_GradientFillMethod theType)
76 {
77   if (myType != Graphic3d_TOB_GRADIENT)
78   {
79     return;
80   }
81
82   Standard_Real anR, aG, aB;
83   theColor1.Values (anR, aG, aB, Quantity_TOC_RGB);
84   myGradientParams.color1 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f);
85
86   theColor2.Values (anR, aG, aB, Quantity_TOC_RGB);
87   myGradientParams.color2 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f);
88
89   myGradientParams.type = theType;
90   invalidateData();
91 }
92
93 // =======================================================================
94 // method  : SetGradientFillMethod
95 // purpose :
96 // =======================================================================
97 void OpenGl_BackgroundArray::SetGradientFillMethod (const Aspect_GradientFillMethod theType)
98 {
99   if (myType != Graphic3d_TOB_GRADIENT)
100   {
101     return;
102   }
103
104   myGradientParams.type = theType;
105   invalidateData();
106 }
107
108 // =======================================================================
109 // method  : IsDefined
110 // purpose :
111 // =======================================================================
112 bool OpenGl_BackgroundArray::IsDefined() const
113 {
114   switch (myType)
115   {
116     case Graphic3d_TOB_GRADIENT: return myGradientParams.type != Aspect_GFM_NONE;
117     case Graphic3d_TOB_TEXTURE:  return myFillMethod          != Aspect_FM_NONE;
118     case Graphic3d_TOB_NONE:     return Standard_False;
119   }
120   return Standard_False;
121 }
122
123 // =======================================================================
124 // method  : invalidateData
125 // purpose :
126 // =======================================================================
127 void OpenGl_BackgroundArray::invalidateData()
128 {
129   myToUpdate = Standard_True;
130 }
131
132 // =======================================================================
133 // method  : Init
134 // purpose :
135 // =======================================================================
136 Standard_Boolean OpenGl_BackgroundArray::Init (const Handle(OpenGl_Workspace)& theWorkspace)
137 {
138   switch (myType)
139   {
140     case Graphic3d_TOB_GRADIENT:
141     {
142       if (!createGradientArray())
143       {
144         return Standard_False;
145       }
146       break;
147     }
148     case Graphic3d_TOB_TEXTURE:
149     {
150       myViewWidth  = theWorkspace->Width();
151       myViewHeight = theWorkspace->Height();
152       if (!createTextureArray (theWorkspace))
153       {
154         return Standard_False;
155       }
156       break;
157     }
158     case Graphic3d_TOB_NONE:
159     default:
160     {
161       return Standard_False;
162     }
163   }
164
165   // Init VBO
166   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
167   if (myIsVboInit)
168   {
169     clearMemoryGL (aCtx);
170   }
171   buildVBO (aCtx, Standard_True);
172   myIsVboInit = Standard_True;
173
174   // Data is up-to-date
175   myToUpdate = Standard_False;
176   return Standard_True;
177 }
178
179 // =======================================================================
180 // method  : createGradientArray
181 // purpose :
182 // =======================================================================
183 Standard_Boolean OpenGl_BackgroundArray::createGradientArray()
184 {
185   // Initialize data for primitive array
186   Graphic3d_Attribute aGragientAttribInfo[] =
187   {
188     { Graphic3d_TOA_POS,   Graphic3d_TOD_VEC2 },
189     { Graphic3d_TOA_COLOR, Graphic3d_TOD_VEC3 }
190   };
191
192   if (!myAttribs->Init (4, aGragientAttribInfo, 2))
193   {
194     return Standard_False;
195   }
196
197   OpenGl_Vec2 aVertices[4] =
198   {
199     OpenGl_Vec2( 1.0f, -1.0f),
200     OpenGl_Vec2( 1.0f,  1.0f),
201     OpenGl_Vec2(-1.0f, -1.0f),
202     OpenGl_Vec2(-1.0f,  1.0f)
203   };
204
205   Tfloat* aCorners[4]     = {};
206   Tfloat  aDiagCorner1[3] = {};
207   Tfloat  aDiagCorner2[3] = {};
208
209   switch (myGradientParams.type)
210   {
211     case Aspect_GFM_HOR:
212     {
213       aCorners[0] = myGradientParams.color2.xyz().ChangeData();
214       aCorners[1] = myGradientParams.color2.xyz().ChangeData();
215       aCorners[2] = myGradientParams.color1.xyz().ChangeData();
216       aCorners[3] = myGradientParams.color1.xyz().ChangeData();
217       break;
218     }
219     case Aspect_GFM_VER:
220     {
221       aCorners[0] = myGradientParams.color2.xyz().ChangeData();
222       aCorners[1] = myGradientParams.color1.xyz().ChangeData();
223       aCorners[2] = myGradientParams.color2.xyz().ChangeData();
224       aCorners[3] = myGradientParams.color1.xyz().ChangeData();
225       break;
226     }
227     case Aspect_GFM_DIAG1:
228     {
229       aCorners[0] = myGradientParams.color2.xyz().ChangeData();
230       aCorners[3] = myGradientParams.color1.xyz().ChangeData();
231       aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[0][0] + aCorners[3][0]);
232       aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[0][1] + aCorners[3][1]);
233       aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[0][2] + aCorners[3][2]);
234       aCorners[1] = aDiagCorner1;
235       aCorners[2] = aDiagCorner2;
236       break;
237     }
238     case Aspect_GFM_DIAG2:
239     {
240       aCorners[1] = myGradientParams.color1.xyz().ChangeData();
241       aCorners[2] = myGradientParams.color2.xyz().ChangeData();
242       aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[1][0] + aCorners[2][0]);
243       aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[1][1] + aCorners[2][1]);
244       aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[1][2] + aCorners[2][2]);
245       aCorners[0] = aDiagCorner1;
246       aCorners[3] = aDiagCorner2;
247       break;
248     }
249     case Aspect_GFM_CORNER1:
250     {
251       aVertices[0] = OpenGl_Vec2( 1.0f,  1.0f);
252       aVertices[1] = OpenGl_Vec2(-1.0f,  1.0f);
253       aVertices[2] = OpenGl_Vec2( 1.0f, -1.0f);
254       aVertices[3] = OpenGl_Vec2(-1.0f, -1.0f);
255
256       aCorners[0] = myGradientParams.color2.xyz().ChangeData();
257       aCorners[1] = myGradientParams.color1.xyz().ChangeData();
258       aCorners[2] = myGradientParams.color2.xyz().ChangeData();
259       aCorners[3] = myGradientParams.color2.xyz().ChangeData();
260       break;
261     }
262     case Aspect_GFM_CORNER2:
263     {
264       aCorners[0] = myGradientParams.color2.xyz().ChangeData();
265       aCorners[1] = myGradientParams.color1.xyz().ChangeData();
266       aCorners[2] = myGradientParams.color2.xyz().ChangeData();
267       aCorners[3] = myGradientParams.color2.xyz().ChangeData();
268       break;
269     }
270     case Aspect_GFM_CORNER3:
271     {
272       aVertices[0] = OpenGl_Vec2( 1.0f,  1.0f);
273       aVertices[1] = OpenGl_Vec2(-1.0f,  1.0f);
274       aVertices[2] = OpenGl_Vec2( 1.0f, -1.0f);
275       aVertices[3] = OpenGl_Vec2(-1.0f, -1.0f);
276
277       aCorners[0] = myGradientParams.color2.xyz().ChangeData();
278       aCorners[1] = myGradientParams.color2.xyz().ChangeData();
279       aCorners[2] = myGradientParams.color1.xyz().ChangeData();
280       aCorners[3] = myGradientParams.color2.xyz().ChangeData();
281       break;
282     }
283     case Aspect_GFM_CORNER4:
284     {
285       aCorners[0] = myGradientParams.color2.xyz().ChangeData();
286       aCorners[1] = myGradientParams.color2.xyz().ChangeData();
287       aCorners[2] = myGradientParams.color1.xyz().ChangeData();
288       aCorners[3] = myGradientParams.color2.xyz().ChangeData();
289       break;
290     }
291     case Aspect_GFM_NONE:
292     {
293       break;
294     }
295   }
296
297   for (Standard_Integer anIt = 0; anIt < 4; ++anIt)
298   {
299     OpenGl_Vec2* aVertData  = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (anIt));
300     *aVertData = aVertices[anIt];
301
302     OpenGl_Vec3* aColorData = reinterpret_cast<OpenGl_Vec3* >(myAttribs->changeValue (anIt) + myAttribs->AttributeOffset (1));
303     *aColorData = OpenGl_Vec3(aCorners[anIt][0], aCorners[anIt][1], aCorners[anIt][2]);
304   }
305
306   return Standard_True;
307 }
308
309 // =======================================================================
310 // method  : createTextureArray
311 // purpose :
312 // =======================================================================
313 Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace)
314 {
315   Graphic3d_Attribute aTextureAttribInfo[] =
316   {
317     { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2 },
318     { Graphic3d_TOA_UV,  Graphic3d_TOD_VEC2 }
319   };
320
321   if (!myAttribs->Init (4, aTextureAttribInfo, 2))
322   {
323     return Standard_False;
324   }
325
326   GLfloat aTexRangeX = 1.0f; // texture <s> coordinate
327   GLfloat aTexRangeY = 1.0f; // texture <t> coordinate
328
329   // Set up for stretching or tiling
330   GLfloat anOffsetX = 1.0f;
331   GLfloat anOffsetY = 1.0f;
332
333   // Setting this coefficient to -1.0f allows to tile textures relatively to the top-left corner of the view
334   // (value 1.0f corresponds to the initial behavior - tiling from the bottom-left corner)
335   GLfloat aCoef = -1.0f;
336
337   // Get texture parameters
338   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
339   const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_False);
340   GLfloat aTextureWidth  = (GLfloat )anAspectFace->TextureRes (aCtx)->SizeX();
341   GLfloat aTextureHeight = (GLfloat )anAspectFace->TextureRes (aCtx)->SizeY();
342
343   if (myFillMethod == Aspect_FM_CENTERED)
344   {
345     anOffsetX = aTextureWidth  / (GLfloat )myViewWidth;
346     anOffsetY = aTextureHeight / (GLfloat )myViewHeight;
347   }
348   else if (myFillMethod == Aspect_FM_TILED)
349   {
350     aTexRangeX = (GLfloat )myViewWidth  / aTextureWidth;
351     aTexRangeY = (GLfloat )myViewHeight / aTextureHeight;
352   }
353
354   // NOTE: texture is mapped using GL_REPEAT wrapping mode so integer part
355   // is simply ignored, and negative multiplier is here for convenience only
356   // and does not result e.g. in texture mirroring
357
358
359   OpenGl_Vec2* aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (0));
360   aData[0] = OpenGl_Vec2 (anOffsetX, -aCoef * anOffsetY);
361   aData[1] = OpenGl_Vec2 (aTexRangeX, 0.0f);
362
363   aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (1));
364   aData[0] = OpenGl_Vec2 (anOffsetX,  aCoef * anOffsetY);
365   aData[1] = OpenGl_Vec2 (aTexRangeX, aCoef * aTexRangeY);
366
367   aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (2));
368   aData[0] = OpenGl_Vec2 (-anOffsetX, -aCoef * anOffsetY);
369   aData[1] = OpenGl_Vec2 (0.0f, 0.0f);
370
371   aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (3));
372   aData[0] = OpenGl_Vec2 (-anOffsetX, aCoef * anOffsetY);
373   aData[1] = OpenGl_Vec2 (0.0f, aCoef * aTexRangeY);
374
375   return Standard_True;
376 }