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 | // ======================================================================= |
28 | OpenGl_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 | // ======================================================================= |
62 | void 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 | // ======================================================================= |
77 | void OpenGl_BackgroundArray::SetTextureFillMethod (const Aspect_FillMethod theFillMethod) |
78 | { |
79 | myFillMethod = theFillMethod; |
80 | invalidateData(); |
81 | } |
82 | |
83 | // ======================================================================= |
84 | // method : SetGradientParameters |
85 | // purpose : |
86 | // ======================================================================= |
87 | void 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 | // ======================================================================= |
111 | void 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 | // ======================================================================= |
126 | bool 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 | // ======================================================================= |
141 | void OpenGl_BackgroundArray::invalidateData() |
142 | { |
143 | myToUpdate = Standard_True; |
144 | } |
145 | |
146 | // ======================================================================= |
3bffef55 |
147 | // method : init |
0b0320e7 |
148 | // purpose : |
149 | // ======================================================================= |
3bffef55 |
150 | Standard_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 |
195 | Standard_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 |
325 | Standard_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 | // ======================================================================= |
394 | void 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 | } |