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