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> |
c04c30b3 |
21 | #include <Graphic3d_TextureParams.hxx> |
0b0320e7 |
22 | |
23 | // ======================================================================= |
24 | // method : Constructor |
25 | // purpose : |
26 | // ======================================================================= |
27 | OpenGl_BackgroundArray::OpenGl_BackgroundArray (const Graphic3d_TypeOfBackground theType) |
28 | : OpenGl_PrimitiveArray (NULL, Graphic3d_TOPA_TRIANGLESTRIPS, NULL, NULL, NULL), |
29 | myToUpdate (Standard_False), |
30 | myType (theType), |
31 | myViewWidth (0), |
32 | myViewHeight (0), |
33 | myFillMethod (Aspect_FM_NONE) |
34 | { |
35 | Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16); |
36 | myAttribs = new Graphic3d_Buffer (anAlloc); |
37 | |
d5846489 |
38 | myDrawMode = GL_TRIANGLE_STRIP; |
0b0320e7 |
39 | |
40 | myGradientParams.color1 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f); |
41 | myGradientParams.color2 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f); |
42 | myGradientParams.type = Aspect_GFM_NONE; |
43 | } |
44 | |
45 | // ======================================================================= |
46 | // method : SetTextureParameters |
47 | // purpose : |
48 | // ======================================================================= |
49 | void OpenGl_BackgroundArray::SetTextureParameters (const Aspect_FillMethod theFillMethod) |
50 | { |
51 | if (myType != Graphic3d_TOB_TEXTURE) |
52 | { |
53 | return; |
54 | } |
55 | |
56 | myFillMethod = theFillMethod; |
57 | invalidateData(); |
58 | } |
59 | |
60 | // ======================================================================= |
61 | // method : SetTextureFillMethod |
62 | // purpose : |
63 | // ======================================================================= |
64 | void OpenGl_BackgroundArray::SetTextureFillMethod (const Aspect_FillMethod theFillMethod) |
65 | { |
66 | myFillMethod = theFillMethod; |
67 | invalidateData(); |
68 | } |
69 | |
70 | // ======================================================================= |
71 | // method : SetGradientParameters |
72 | // purpose : |
73 | // ======================================================================= |
74 | void OpenGl_BackgroundArray::SetGradientParameters (const Quantity_Color& theColor1, |
75 | const Quantity_Color& theColor2, |
76 | const Aspect_GradientFillMethod theType) |
77 | { |
78 | if (myType != Graphic3d_TOB_GRADIENT) |
79 | { |
80 | return; |
81 | } |
82 | |
83 | Standard_Real anR, aG, aB; |
84 | theColor1.Values (anR, aG, aB, Quantity_TOC_RGB); |
85 | myGradientParams.color1 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f); |
86 | |
87 | theColor2.Values (anR, aG, aB, Quantity_TOC_RGB); |
88 | myGradientParams.color2 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f); |
89 | |
90 | myGradientParams.type = theType; |
91 | invalidateData(); |
92 | } |
93 | |
94 | // ======================================================================= |
95 | // method : SetGradientFillMethod |
96 | // purpose : |
97 | // ======================================================================= |
98 | void OpenGl_BackgroundArray::SetGradientFillMethod (const Aspect_GradientFillMethod theType) |
99 | { |
100 | if (myType != Graphic3d_TOB_GRADIENT) |
101 | { |
102 | return; |
103 | } |
104 | |
105 | myGradientParams.type = theType; |
106 | invalidateData(); |
107 | } |
108 | |
109 | // ======================================================================= |
110 | // method : IsDefined |
111 | // purpose : |
112 | // ======================================================================= |
113 | bool OpenGl_BackgroundArray::IsDefined() const |
114 | { |
115 | switch (myType) |
116 | { |
117 | case Graphic3d_TOB_GRADIENT: return myGradientParams.type != Aspect_GFM_NONE; |
118 | case Graphic3d_TOB_TEXTURE: return myFillMethod != Aspect_FM_NONE; |
119 | case Graphic3d_TOB_NONE: return Standard_False; |
120 | } |
121 | return Standard_False; |
122 | } |
123 | |
124 | // ======================================================================= |
125 | // method : invalidateData |
126 | // purpose : |
127 | // ======================================================================= |
128 | void OpenGl_BackgroundArray::invalidateData() |
129 | { |
130 | myToUpdate = Standard_True; |
131 | } |
132 | |
133 | // ======================================================================= |
134 | // method : Init |
135 | // purpose : |
136 | // ======================================================================= |
137 | Standard_Boolean OpenGl_BackgroundArray::Init (const Handle(OpenGl_Workspace)& theWorkspace) |
138 | { |
139 | switch (myType) |
140 | { |
141 | case Graphic3d_TOB_GRADIENT: |
142 | { |
143 | if (!createGradientArray()) |
144 | { |
145 | return Standard_False; |
146 | } |
147 | break; |
148 | } |
149 | case Graphic3d_TOB_TEXTURE: |
150 | { |
151 | myViewWidth = theWorkspace->Width(); |
152 | myViewHeight = theWorkspace->Height(); |
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 | // ======================================================================= |
184 | Standard_Boolean OpenGl_BackgroundArray::createGradientArray() |
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 | { |
0b0320e7 |
200 | OpenGl_Vec2( 1.0f, -1.0f), |
201 | OpenGl_Vec2( 1.0f, 1.0f), |
d5846489 |
202 | OpenGl_Vec2(-1.0f, -1.0f), |
0b0320e7 |
203 | OpenGl_Vec2(-1.0f, 1.0f) |
204 | }; |
205 | |
206 | Tfloat* aCorners[4] = {}; |
207 | Tfloat aDiagCorner1[3] = {}; |
208 | Tfloat aDiagCorner2[3] = {}; |
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 | { |
d5846489 |
252 | aVertices[0] = OpenGl_Vec2( 1.0f, 1.0f); |
253 | aVertices[1] = OpenGl_Vec2(-1.0f, 1.0f); |
254 | aVertices[2] = OpenGl_Vec2( 1.0f, -1.0f); |
255 | aVertices[3] = OpenGl_Vec2(-1.0f, -1.0f); |
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 | { |
d5846489 |
273 | aVertices[0] = OpenGl_Vec2( 1.0f, 1.0f); |
274 | aVertices[1] = OpenGl_Vec2(-1.0f, 1.0f); |
275 | aVertices[2] = OpenGl_Vec2( 1.0f, -1.0f); |
276 | aVertices[3] = OpenGl_Vec2(-1.0f, -1.0f); |
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 | // ======================================================================= |
314 | Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace) |
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 |
331 | GLfloat anOffsetX = 1.0f; |
332 | GLfloat anOffsetY = 1.0f; |
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(); |
340 | const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_False); |
341 | GLfloat aTextureWidth = (GLfloat )anAspectFace->TextureRes (aCtx)->SizeX(); |
342 | GLfloat aTextureHeight = (GLfloat )anAspectFace->TextureRes (aCtx)->SizeY(); |
343 | |
344 | if (myFillMethod == Aspect_FM_CENTERED) |
345 | { |
346 | anOffsetX = aTextureWidth / (GLfloat )myViewWidth; |
347 | anOffsetY = aTextureHeight / (GLfloat )myViewHeight; |
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 | } |