1 // Created on: 2015-01-16
2 // Created by: Anastasia BORISOVA
3 // Copyright (c) 2015 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_BackgroundArray.hxx>
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>
24 // =======================================================================
25 // method : Constructor
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),
32 myFillMethod (Aspect_FM_NONE),
35 myToUpdate (Standard_False)
37 Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
38 myAttribs = new Graphic3d_Buffer (anAlloc);
40 myDrawMode = GL_TRIANGLE_STRIP;
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;
48 // =======================================================================
49 // method : SetTextureParameters
51 // =======================================================================
52 void OpenGl_BackgroundArray::SetTextureParameters (const Aspect_FillMethod theFillMethod)
54 if (myType != Graphic3d_TOB_TEXTURE)
59 myFillMethod = theFillMethod;
63 // =======================================================================
64 // method : SetTextureFillMethod
66 // =======================================================================
67 void OpenGl_BackgroundArray::SetTextureFillMethod (const Aspect_FillMethod theFillMethod)
69 myFillMethod = theFillMethod;
73 // =======================================================================
74 // method : SetGradientParameters
76 // =======================================================================
77 void OpenGl_BackgroundArray::SetGradientParameters (const Quantity_Color& theColor1,
78 const Quantity_Color& theColor2,
79 const Aspect_GradientFillMethod theType)
81 if (myType != Graphic3d_TOB_GRADIENT)
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);
90 theColor2.Values (anR, aG, aB, Quantity_TOC_RGB);
91 myGradientParams.color2 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f);
93 myGradientParams.type = theType;
97 // =======================================================================
98 // method : SetGradientFillMethod
100 // =======================================================================
101 void OpenGl_BackgroundArray::SetGradientFillMethod (const Aspect_GradientFillMethod theType)
103 if (myType != Graphic3d_TOB_GRADIENT)
108 myGradientParams.type = theType;
112 // =======================================================================
113 // method : IsDefined
115 // =======================================================================
116 bool OpenGl_BackgroundArray::IsDefined() const
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;
125 return Standard_False;
128 // =======================================================================
129 // method : invalidateData
131 // =======================================================================
132 void OpenGl_BackgroundArray::invalidateData()
134 myToUpdate = Standard_True;
137 // =======================================================================
140 // =======================================================================
141 Standard_Boolean OpenGl_BackgroundArray::init (const Handle(OpenGl_Workspace)& theWorkspace) const
145 case Graphic3d_TOB_GRADIENT:
147 if (!createGradientArray())
149 return Standard_False;
153 case Graphic3d_TOB_TEXTURE:
155 if (!createTextureArray (theWorkspace))
157 return Standard_False;
161 case Graphic3d_TOB_CUBEMAP:
163 if (!createCubeMapArray())
165 return Standard_False;
169 case Graphic3d_TOB_NONE:
172 return Standard_False;
177 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
180 clearMemoryGL (aCtx);
182 buildVBO (aCtx, Standard_True);
183 myIsVboInit = Standard_True;
185 // Data is up-to-date
186 myToUpdate = Standard_False;
187 return Standard_True;
190 // =======================================================================
191 // method : createGradientArray
193 // =======================================================================
194 Standard_Boolean OpenGl_BackgroundArray::createGradientArray() const
196 // Initialize data for primitive array
197 Graphic3d_Attribute aGragientAttribInfo[] =
199 { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2 },
200 { Graphic3d_TOA_COLOR, Graphic3d_TOD_VEC3 }
203 if (!myAttribs->Init (4, aGragientAttribInfo, 2))
205 return Standard_False;
208 OpenGl_Vec2 aVertices[4] =
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))
216 float* aCorners[4] = {};
217 float aDiagCorner1[3] = {};
218 float aDiagCorner2[3] = {};
220 switch (myGradientParams.type)
224 aCorners[0] = myGradientParams.color2.ChangeData();
225 aCorners[1] = myGradientParams.color2.ChangeData();
226 aCorners[2] = myGradientParams.color1.ChangeData();
227 aCorners[3] = myGradientParams.color1.ChangeData();
232 aCorners[0] = myGradientParams.color2.ChangeData();
233 aCorners[1] = myGradientParams.color1.ChangeData();
234 aCorners[2] = myGradientParams.color2.ChangeData();
235 aCorners[3] = myGradientParams.color1.ChangeData();
238 case Aspect_GFM_DIAG1:
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;
249 case Aspect_GFM_DIAG2:
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;
260 case Aspect_GFM_CORNER1:
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);
267 aCorners[0] = myGradientParams.color2.ChangeData();
268 aCorners[1] = myGradientParams.color1.ChangeData();
269 aCorners[2] = myGradientParams.color2.ChangeData();
270 aCorners[3] = myGradientParams.color2.ChangeData();
273 case Aspect_GFM_CORNER2:
275 aCorners[0] = myGradientParams.color2.ChangeData();
276 aCorners[1] = myGradientParams.color1.ChangeData();
277 aCorners[2] = myGradientParams.color2.ChangeData();
278 aCorners[3] = myGradientParams.color2.ChangeData();
281 case Aspect_GFM_CORNER3:
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);
288 aCorners[0] = myGradientParams.color2.ChangeData();
289 aCorners[1] = myGradientParams.color2.ChangeData();
290 aCorners[2] = myGradientParams.color1.ChangeData();
291 aCorners[3] = myGradientParams.color2.ChangeData();
294 case Aspect_GFM_CORNER4:
296 aCorners[0] = myGradientParams.color2.ChangeData();
297 aCorners[1] = myGradientParams.color2.ChangeData();
298 aCorners[2] = myGradientParams.color1.ChangeData();
299 aCorners[3] = myGradientParams.color2.ChangeData();
302 case Aspect_GFM_NONE:
308 for (Standard_Integer anIt = 0; anIt < 4; ++anIt)
310 OpenGl_Vec2* aVertData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (anIt));
311 *aVertData = aVertices[anIt];
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]);
317 return Standard_True;
320 // =======================================================================
321 // method : createTextureArray
323 // =======================================================================
324 Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace) const
326 Graphic3d_Attribute aTextureAttribInfo[] =
328 { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2 },
329 { Graphic3d_TOA_UV, Graphic3d_TOD_VEC2 }
332 if (!myAttribs->Init (4, aTextureAttribInfo, 2))
334 return Standard_False;
337 GLfloat aTexRangeX = 1.0f; // texture <s> coordinate
338 GLfloat aTexRangeY = 1.0f; // texture <t> coordinate
340 // Set up for stretching or tiling
341 GLfloat anOffsetX = 0.5f * (float )myViewWidth;
342 GLfloat anOffsetY = 0.5f * (float )myViewHeight;
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;
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();
354 if (myFillMethod == Aspect_FM_CENTERED)
356 anOffsetX = 0.5f * aTextureWidth;
357 anOffsetY = 0.5f * aTextureHeight;
359 else if (myFillMethod == Aspect_FM_TILED)
361 aTexRangeX = (GLfloat )myViewWidth / aTextureWidth;
362 aTexRangeY = (GLfloat )myViewHeight / aTextureHeight;
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
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);
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);
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);
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);
386 return Standard_True;
389 // =======================================================================
390 // method : createCubeMapArray
392 // =======================================================================
393 Standard_Boolean OpenGl_BackgroundArray::createCubeMapArray() const
395 Graphic3d_Attribute aCubeMapAttribInfo[] =
397 { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2}
400 if (!myAttribs->Init(4, aCubeMapAttribInfo, 1))
402 return Standard_False;
405 OpenGl_Vec2* aData = reinterpret_cast<OpenGl_Vec2*>(myAttribs->changeValue(0));
407 for (unsigned int i = 0; i < 4; ++i)
409 aData[i] = (OpenGl_Vec2(Standard_ShortReal(i / 2), Standard_ShortReal(i % 2)) - OpenGl_Vec2(0.5f)) * 2.f;
412 return Standard_True;
415 // =======================================================================
418 // =======================================================================
419 void OpenGl_BackgroundArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
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())
426 aViewSizeX = theWorkspace->View()->Camera()->Tile().TotalSize.x();
427 aViewSizeY = theWorkspace->View()->Camera()->Tile().TotalSize.y();
430 || myViewWidth != aViewSizeX
431 || myViewHeight != aViewSizeY)
433 myViewWidth = aViewSizeX;
434 myViewHeight = aViewSizeY;
438 OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current();
439 OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current();
441 if (myType != Graphic3d_TOB_CUBEMAP)
443 myTrsfPers.Apply(theWorkspace->View()->Camera(), aProjection, aWorldView,
444 aCtx->Viewport()[2], aCtx->Viewport()[3]);
447 aCtx->ProjectionState.Push();
448 aCtx->WorldViewState.Push();
449 aCtx->ProjectionState.SetCurrent (aProjection);
450 aCtx->WorldViewState.SetCurrent (aWorldView);
451 aCtx->ApplyProjectionMatrix();
452 aCtx->ApplyModelViewMatrix();
454 OpenGl_PrimitiveArray::Render (theWorkspace);
456 aCtx->ProjectionState.Pop();
457 aCtx->WorldViewState.Pop();
458 aCtx->ApplyProjectionMatrix();