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