0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[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 #include <OpenGl_View.hxx>
22 #include <Graphic3d_TextureParams.hxx>
23
24 // =======================================================================
25 // method  : Constructor
26 // purpose :
27 // =======================================================================
28 OpenGl_BackgroundArray::OpenGl_BackgroundArray (const Graphic3d_TypeOfBackground theType)
29 : OpenGl_PrimitiveArray (NULL, Graphic3d_TOPA_TRIANGLESTRIPS, NULL, NULL, NULL),
30   myTrsfPers (Graphic3d_TMF_2d, theType == Graphic3d_TOB_TEXTURE ? Aspect_TOTP_CENTER : Aspect_TOTP_LEFT_LOWER),
31   myType (theType),
32   myFillMethod (Aspect_FM_NONE),
33   myViewWidth (0),
34   myViewHeight (0),
35   myToUpdate (Standard_False)
36 {
37   Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
38   myAttribs = new Graphic3d_Buffer (anAlloc);
39
40   myDrawMode = GL_TRIANGLE_STRIP;
41   myIsFillType = true;
42
43   myGradientParams.color1 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
44   myGradientParams.color2 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
45   myGradientParams.type   = Aspect_GFM_NONE;
46 }
47
48 // =======================================================================
49 // method  : SetTextureParameters
50 // purpose :
51 // =======================================================================
52 void OpenGl_BackgroundArray::SetTextureParameters (const Aspect_FillMethod theFillMethod)
53 {
54   if (myType != Graphic3d_TOB_TEXTURE)
55   {
56     return;
57   }
58
59   myFillMethod = theFillMethod;
60   invalidateData();
61 }
62
63 // =======================================================================
64 // method  : SetTextureFillMethod
65 // purpose :
66 // =======================================================================
67 void OpenGl_BackgroundArray::SetTextureFillMethod (const Aspect_FillMethod theFillMethod)
68 {
69   myFillMethod = theFillMethod;
70   invalidateData();
71 }
72
73 // =======================================================================
74 // method  : SetGradientParameters
75 // purpose :
76 // =======================================================================
77 void OpenGl_BackgroundArray::SetGradientParameters (const Quantity_Color&           theColor1,
78                                                     const Quantity_Color&           theColor2,
79                                                     const Aspect_GradientFillMethod theType)
80 {
81   if (myType != Graphic3d_TOB_GRADIENT)
82   {
83     return;
84   }
85
86   Standard_Real anR, aG, aB;
87   theColor1.Values (anR, aG, aB, Quantity_TOC_RGB);
88   myGradientParams.color1 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f);
89
90   theColor2.Values (anR, aG, aB, Quantity_TOC_RGB);
91   myGradientParams.color2 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f);
92
93   myGradientParams.type = theType;
94   invalidateData();
95 }
96
97 // =======================================================================
98 // method  : SetGradientFillMethod
99 // purpose :
100 // =======================================================================
101 void OpenGl_BackgroundArray::SetGradientFillMethod (const Aspect_GradientFillMethod theType)
102 {
103   if (myType != Graphic3d_TOB_GRADIENT)
104   {
105     return;
106   }
107
108   myGradientParams.type = theType;
109   invalidateData();
110 }
111
112 // =======================================================================
113 // method  : IsDefined
114 // purpose :
115 // =======================================================================
116 bool OpenGl_BackgroundArray::IsDefined() const
117 {
118   switch (myType)
119   {
120     case Graphic3d_TOB_GRADIENT: return myGradientParams.type != Aspect_GFM_NONE;
121     case Graphic3d_TOB_TEXTURE:  return myFillMethod          != Aspect_FM_NONE;
122     case Graphic3d_TOB_CUBEMAP:  return Standard_True;
123     case Graphic3d_TOB_NONE:     return Standard_False;
124   }
125   return Standard_False;
126 }
127
128 // =======================================================================
129 // method  : invalidateData
130 // purpose :
131 // =======================================================================
132 void OpenGl_BackgroundArray::invalidateData()
133 {
134   myToUpdate = Standard_True;
135 }
136
137 // =======================================================================
138 // method  : init
139 // purpose :
140 // =======================================================================
141 Standard_Boolean OpenGl_BackgroundArray::init (const Handle(OpenGl_Workspace)& theWorkspace) const
142 {
143   switch (myType)
144   {
145     case Graphic3d_TOB_GRADIENT:
146     {
147       if (!createGradientArray())
148       {
149         return Standard_False;
150       }
151       break;
152     }
153     case Graphic3d_TOB_TEXTURE:
154     {
155       if (!createTextureArray (theWorkspace))
156       {
157         return Standard_False;
158       }
159       break;
160     }
161     case Graphic3d_TOB_CUBEMAP:
162     {
163       if (!createCubeMapArray())
164       {
165         return Standard_False;
166       }
167       break;
168     }
169     case Graphic3d_TOB_NONE:
170     default:
171     {
172       return Standard_False;
173     }
174   }
175
176   // Init VBO
177   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
178   if (myIsVboInit)
179   {
180     clearMemoryGL (aCtx);
181   }
182   buildVBO (aCtx, Standard_True);
183   myIsVboInit = Standard_True;
184
185   // Data is up-to-date
186   myToUpdate = Standard_False;
187   return Standard_True;
188 }
189
190 // =======================================================================
191 // method  : createGradientArray
192 // purpose :
193 // =======================================================================
194 Standard_Boolean OpenGl_BackgroundArray::createGradientArray() const
195 {
196   // Initialize data for primitive array
197   Graphic3d_Attribute aGragientAttribInfo[] =
198   {
199     { Graphic3d_TOA_POS,   Graphic3d_TOD_VEC2 },
200     { Graphic3d_TOA_COLOR, Graphic3d_TOD_VEC3 }
201   };
202
203   if (!myAttribs->Init (4, aGragientAttribInfo, 2))
204   {
205     return Standard_False;
206   }
207
208   OpenGl_Vec2 aVertices[4] =
209   {
210     OpenGl_Vec2(float(myViewWidth), 0.0f),
211     OpenGl_Vec2(float(myViewWidth), float(myViewHeight)),
212     OpenGl_Vec2(0.0f,               0.0f),
213     OpenGl_Vec2(0.0f,               float(myViewHeight))
214   };
215
216   float* aCorners[4]     = {};
217   float  aDiagCorner1[3] = {};
218   float  aDiagCorner2[3] = {};
219
220   switch (myGradientParams.type)
221   {
222     case Aspect_GFM_HOR:
223     {
224       aCorners[0] = myGradientParams.color2.ChangeData();
225       aCorners[1] = myGradientParams.color2.ChangeData();
226       aCorners[2] = myGradientParams.color1.ChangeData();
227       aCorners[3] = myGradientParams.color1.ChangeData();
228       break;
229     }
230     case Aspect_GFM_VER:
231     {
232       aCorners[0] = myGradientParams.color2.ChangeData();
233       aCorners[1] = myGradientParams.color1.ChangeData();
234       aCorners[2] = myGradientParams.color2.ChangeData();
235       aCorners[3] = myGradientParams.color1.ChangeData();
236       break;
237     }
238     case Aspect_GFM_DIAG1:
239     {
240       aCorners[0] = myGradientParams.color2.ChangeData();
241       aCorners[3] = myGradientParams.color1.ChangeData();
242       aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[0][0] + aCorners[3][0]);
243       aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[0][1] + aCorners[3][1]);
244       aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[0][2] + aCorners[3][2]);
245       aCorners[1] = aDiagCorner1;
246       aCorners[2] = aDiagCorner2;
247       break;
248     }
249     case Aspect_GFM_DIAG2:
250     {
251       aCorners[1] = myGradientParams.color1.ChangeData();
252       aCorners[2] = myGradientParams.color2.ChangeData();
253       aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[1][0] + aCorners[2][0]);
254       aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[1][1] + aCorners[2][1]);
255       aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[1][2] + aCorners[2][2]);
256       aCorners[0] = aDiagCorner1;
257       aCorners[3] = aDiagCorner2;
258       break;
259     }
260     case Aspect_GFM_CORNER1:
261     {
262       aVertices[0] = OpenGl_Vec2(float(myViewWidth), float(myViewHeight));
263       aVertices[1] = OpenGl_Vec2(0.0f,               float(myViewHeight));
264       aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f);
265       aVertices[3] = OpenGl_Vec2(0.0f,               0.0f);
266
267       aCorners[0] = myGradientParams.color2.ChangeData();
268       aCorners[1] = myGradientParams.color1.ChangeData();
269       aCorners[2] = myGradientParams.color2.ChangeData();
270       aCorners[3] = myGradientParams.color2.ChangeData();
271       break;
272     }
273     case Aspect_GFM_CORNER2:
274     {
275       aCorners[0] = myGradientParams.color2.ChangeData();
276       aCorners[1] = myGradientParams.color1.ChangeData();
277       aCorners[2] = myGradientParams.color2.ChangeData();
278       aCorners[3] = myGradientParams.color2.ChangeData();
279       break;
280     }
281     case Aspect_GFM_CORNER3:
282     {
283       aVertices[0] = OpenGl_Vec2(float(myViewWidth), float(myViewHeight));
284       aVertices[1] = OpenGl_Vec2(0.0f,               float(myViewHeight));
285       aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f);
286       aVertices[3] = OpenGl_Vec2(0.0f,               0.0f);
287
288       aCorners[0] = myGradientParams.color2.ChangeData();
289       aCorners[1] = myGradientParams.color2.ChangeData();
290       aCorners[2] = myGradientParams.color1.ChangeData();
291       aCorners[3] = myGradientParams.color2.ChangeData();
292       break;
293     }
294     case Aspect_GFM_CORNER4:
295     {
296       aCorners[0] = myGradientParams.color2.ChangeData();
297       aCorners[1] = myGradientParams.color2.ChangeData();
298       aCorners[2] = myGradientParams.color1.ChangeData();
299       aCorners[3] = myGradientParams.color2.ChangeData();
300       break;
301     }
302     case Aspect_GFM_NONE:
303     {
304       break;
305     }
306   }
307
308   for (Standard_Integer anIt = 0; anIt < 4; ++anIt)
309   {
310     OpenGl_Vec2* aVertData  = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (anIt));
311     *aVertData = aVertices[anIt];
312
313     OpenGl_Vec3* aColorData = reinterpret_cast<OpenGl_Vec3* >(myAttribs->changeValue (anIt) + myAttribs->AttributeOffset (1));
314     *aColorData = OpenGl_Vec3(aCorners[anIt][0], aCorners[anIt][1], aCorners[anIt][2]);
315   }
316
317   return Standard_True;
318 }
319
320 // =======================================================================
321 // method  : createTextureArray
322 // purpose :
323 // =======================================================================
324 Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace) const
325 {
326   Graphic3d_Attribute aTextureAttribInfo[] =
327   {
328     { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2 },
329     { Graphic3d_TOA_UV,  Graphic3d_TOD_VEC2 }
330   };
331
332   if (!myAttribs->Init (4, aTextureAttribInfo, 2))
333   {
334     return Standard_False;
335   }
336
337   GLfloat aTexRangeX = 1.0f; // texture <s> coordinate
338   GLfloat aTexRangeY = 1.0f; // texture <t> coordinate
339
340   // Set up for stretching or tiling
341   GLfloat anOffsetX = 0.5f * (float )myViewWidth;
342   GLfloat anOffsetY = 0.5f * (float )myViewHeight;
343
344   // Setting this coefficient to -1.0f allows to tile textures relatively to the top-left corner of the view
345   // (value 1.0f corresponds to the initial behavior - tiling from the bottom-left corner)
346   GLfloat aCoef = -1.0f;
347
348   // Get texture parameters
349   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
350   const OpenGl_Aspects* anAspectFace = theWorkspace->Aspects();
351   GLfloat aTextureWidth  = (GLfloat )anAspectFace->TextureSet (aCtx)->First()->SizeX();
352   GLfloat aTextureHeight = (GLfloat )anAspectFace->TextureSet (aCtx)->First()->SizeY();
353
354   if (myFillMethod == Aspect_FM_CENTERED)
355   {
356     anOffsetX = 0.5f * aTextureWidth;
357     anOffsetY = 0.5f * aTextureHeight;
358   }
359   else if (myFillMethod == Aspect_FM_TILED)
360   {
361     aTexRangeX = (GLfloat )myViewWidth  / aTextureWidth;
362     aTexRangeY = (GLfloat )myViewHeight / aTextureHeight;
363   }
364
365   // NOTE: texture is mapped using GL_REPEAT wrapping mode so integer part
366   // is simply ignored, and negative multiplier is here for convenience only
367   // and does not result e.g. in texture mirroring
368
369
370   OpenGl_Vec2* aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (0));
371   aData[0] = OpenGl_Vec2 (anOffsetX, -aCoef * anOffsetY);
372   aData[1] = OpenGl_Vec2 (aTexRangeX, 0.0f);
373
374   aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (1));
375   aData[0] = OpenGl_Vec2 (anOffsetX,  aCoef * anOffsetY);
376   aData[1] = OpenGl_Vec2 (aTexRangeX, aCoef * aTexRangeY);
377
378   aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (2));
379   aData[0] = OpenGl_Vec2 (-anOffsetX, -aCoef * anOffsetY);
380   aData[1] = OpenGl_Vec2 (0.0f, 0.0f);
381
382   aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (3));
383   aData[0] = OpenGl_Vec2 (-anOffsetX, aCoef * anOffsetY);
384   aData[1] = OpenGl_Vec2 (0.0f, aCoef * aTexRangeY);
385
386   return Standard_True;
387 }
388
389 // =======================================================================
390 // method  : createCubeMapArray
391 // purpose :
392 // =======================================================================
393 Standard_Boolean OpenGl_BackgroundArray::createCubeMapArray() const
394 {
395   Graphic3d_Attribute aCubeMapAttribInfo[] =
396   {
397     { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2}
398   };
399
400   if (!myAttribs->Init(4, aCubeMapAttribInfo, 1))
401   {
402     return Standard_False;
403   }
404
405   OpenGl_Vec2* aData = reinterpret_cast<OpenGl_Vec2*>(myAttribs->changeValue(0));
406
407   for (unsigned int i = 0; i < 4; ++i)
408   {
409     aData[i] = (OpenGl_Vec2(Standard_ShortReal(i / 2), Standard_ShortReal(i % 2)) - OpenGl_Vec2(0.5f)) * 2.f;
410   }
411
412   return Standard_True;
413 }
414
415 // =======================================================================
416 // method  : Render
417 // purpose :
418 // =======================================================================
419 void OpenGl_BackgroundArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
420 {
421   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
422   Standard_Integer aViewSizeX = aCtx->Viewport()[2];
423   Standard_Integer aViewSizeY = aCtx->Viewport()[3];
424   if (theWorkspace->View()->Camera()->Tile().IsValid())
425   {
426     aViewSizeX = theWorkspace->View()->Camera()->Tile().TotalSize.x();
427     aViewSizeY = theWorkspace->View()->Camera()->Tile().TotalSize.y();
428   }
429   if (myToUpdate
430    || myViewWidth  != aViewSizeX
431    || myViewHeight != aViewSizeY)
432   {
433     myViewWidth  = aViewSizeX;
434     myViewHeight = aViewSizeY;
435     init (theWorkspace);
436   }
437
438   OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current();
439   OpenGl_Mat4 aWorldView  = aCtx->WorldViewState.Current();
440
441   if (myType != Graphic3d_TOB_CUBEMAP)
442   {
443     myTrsfPers.Apply(theWorkspace->View()->Camera(), aProjection, aWorldView,
444       aCtx->Viewport()[2], aCtx->Viewport()[3]);
445   }
446
447   aCtx->ProjectionState.Push();
448   aCtx->WorldViewState.Push();
449   aCtx->ProjectionState.SetCurrent (aProjection);
450   aCtx->WorldViewState.SetCurrent (aWorldView);
451   aCtx->ApplyProjectionMatrix();
452   aCtx->ApplyModelViewMatrix();
453
454   OpenGl_PrimitiveArray::Render (theWorkspace);
455
456   aCtx->ProjectionState.Pop();
457   aCtx->WorldViewState.Pop();
458   aCtx->ApplyProjectionMatrix();
459 }