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> |
0b0320e7 |
19 | #include <OpenGl_Texture.hxx> |
3bffef55 |
20 | #include <OpenGl_View.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) |
9af0d66b |
28 | : OpenGl_PrimitiveArray (NULL, Graphic3d_TOPA_TRIANGLES, NULL, NULL, NULL), |
0b0320e7 |
29 | myType (theType), |
3bffef55 |
30 | myFillMethod (Aspect_FM_NONE), |
0b0320e7 |
31 | myViewWidth (0), |
32 | myViewHeight (0), |
3bffef55 |
33 | myToUpdate (Standard_False) |
0b0320e7 |
34 | { |
9af0d66b |
35 | myDrawMode = GL_TRIANGLES; |
6ef0d6f1 |
36 | myIsFillType = true; |
0b0320e7 |
37 | |
38 | myGradientParams.color1 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f); |
39 | myGradientParams.color2 = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 1.0f); |
9af0d66b |
40 | myGradientParams.type = Aspect_GradientFillMethod_None; |
0b0320e7 |
41 | } |
42 | |
43 | // ======================================================================= |
44 | // method : SetTextureParameters |
45 | // purpose : |
46 | // ======================================================================= |
47 | void OpenGl_BackgroundArray::SetTextureParameters (const Aspect_FillMethod theFillMethod) |
48 | { |
49 | if (myType != Graphic3d_TOB_TEXTURE) |
50 | { |
51 | return; |
52 | } |
53 | |
54 | myFillMethod = theFillMethod; |
55 | invalidateData(); |
56 | } |
57 | |
58 | // ======================================================================= |
59 | // method : SetTextureFillMethod |
60 | // purpose : |
61 | // ======================================================================= |
62 | void OpenGl_BackgroundArray::SetTextureFillMethod (const Aspect_FillMethod theFillMethod) |
63 | { |
64 | myFillMethod = theFillMethod; |
65 | invalidateData(); |
66 | } |
67 | |
68 | // ======================================================================= |
69 | // method : SetGradientParameters |
70 | // purpose : |
71 | // ======================================================================= |
72 | void OpenGl_BackgroundArray::SetGradientParameters (const Quantity_Color& theColor1, |
73 | const Quantity_Color& theColor2, |
74 | const Aspect_GradientFillMethod theType) |
75 | { |
76 | if (myType != Graphic3d_TOB_GRADIENT) |
77 | { |
78 | return; |
79 | } |
80 | |
81 | Standard_Real anR, aG, aB; |
82 | theColor1.Values (anR, aG, aB, Quantity_TOC_RGB); |
83 | myGradientParams.color1 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f); |
84 | |
85 | theColor2.Values (anR, aG, aB, Quantity_TOC_RGB); |
86 | myGradientParams.color2 = OpenGl_Vec4 ((float)anR, (float)aG, (float)aB, 0.0f); |
87 | |
88 | myGradientParams.type = theType; |
89 | invalidateData(); |
90 | } |
91 | |
92 | // ======================================================================= |
93 | // method : SetGradientFillMethod |
94 | // purpose : |
95 | // ======================================================================= |
96 | void OpenGl_BackgroundArray::SetGradientFillMethod (const Aspect_GradientFillMethod theType) |
97 | { |
98 | if (myType != Graphic3d_TOB_GRADIENT) |
99 | { |
100 | return; |
101 | } |
102 | |
103 | myGradientParams.type = theType; |
104 | invalidateData(); |
105 | } |
106 | |
107 | // ======================================================================= |
108 | // method : IsDefined |
109 | // purpose : |
110 | // ======================================================================= |
111 | bool OpenGl_BackgroundArray::IsDefined() const |
112 | { |
113 | switch (myType) |
114 | { |
9af0d66b |
115 | case Graphic3d_TOB_GRADIENT: return myGradientParams.type != Aspect_GradientFillMethod_None; |
0b0320e7 |
116 | case Graphic3d_TOB_TEXTURE: return myFillMethod != Aspect_FM_NONE; |
077a220c |
117 | case Graphic3d_TOB_CUBEMAP: return Standard_True; |
0b0320e7 |
118 | case Graphic3d_TOB_NONE: return Standard_False; |
119 | } |
120 | return Standard_False; |
121 | } |
122 | |
123 | // ======================================================================= |
124 | // method : invalidateData |
125 | // purpose : |
126 | // ======================================================================= |
127 | void OpenGl_BackgroundArray::invalidateData() |
128 | { |
129 | myToUpdate = Standard_True; |
130 | } |
131 | |
132 | // ======================================================================= |
3bffef55 |
133 | // method : init |
0b0320e7 |
134 | // purpose : |
135 | // ======================================================================= |
3bffef55 |
136 | Standard_Boolean OpenGl_BackgroundArray::init (const Handle(OpenGl_Workspace)& theWorkspace) const |
0b0320e7 |
137 | { |
ba00aab7 |
138 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
9af0d66b |
139 | |
140 | if (myIndices.IsNull()) |
141 | { |
142 | myIndices = new Graphic3d_IndexBuffer (Graphic3d_Buffer::DefaultAllocator()); |
143 | } |
144 | if (myAttribs.IsNull()) |
145 | { |
146 | myAttribs = new Graphic3d_Buffer (Graphic3d_Buffer::DefaultAllocator()); |
147 | } |
148 | |
0b0320e7 |
149 | switch (myType) |
150 | { |
151 | case Graphic3d_TOB_GRADIENT: |
152 | { |
ba00aab7 |
153 | if (!createGradientArray (aCtx)) |
0b0320e7 |
154 | { |
155 | return Standard_False; |
156 | } |
157 | break; |
158 | } |
159 | case Graphic3d_TOB_TEXTURE: |
160 | { |
0b0320e7 |
161 | if (!createTextureArray (theWorkspace)) |
162 | { |
163 | return Standard_False; |
164 | } |
165 | break; |
166 | } |
077a220c |
167 | case Graphic3d_TOB_CUBEMAP: |
168 | { |
169 | if (!createCubeMapArray()) |
170 | { |
171 | return Standard_False; |
172 | } |
173 | break; |
174 | } |
0b0320e7 |
175 | case Graphic3d_TOB_NONE: |
176 | default: |
177 | { |
178 | return Standard_False; |
179 | } |
180 | } |
181 | |
182 | // Init VBO |
0b0320e7 |
183 | if (myIsVboInit) |
184 | { |
185 | clearMemoryGL (aCtx); |
186 | } |
187 | buildVBO (aCtx, Standard_True); |
188 | myIsVboInit = Standard_True; |
189 | |
190 | // Data is up-to-date |
191 | myToUpdate = Standard_False; |
192 | return Standard_True; |
193 | } |
194 | |
195 | // ======================================================================= |
196 | // method : createGradientArray |
197 | // purpose : |
198 | // ======================================================================= |
ba00aab7 |
199 | Standard_Boolean OpenGl_BackgroundArray::createGradientArray (const Handle(OpenGl_Context)& theCtx) const |
0b0320e7 |
200 | { |
201 | // Initialize data for primitive array |
202 | Graphic3d_Attribute aGragientAttribInfo[] = |
203 | { |
204 | { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2 }, |
205 | { Graphic3d_TOA_COLOR, Graphic3d_TOD_VEC3 } |
206 | }; |
207 | |
208 | if (!myAttribs->Init (4, aGragientAttribInfo, 2)) |
209 | { |
210 | return Standard_False; |
211 | } |
956d9157 |
212 | if (!myIndices->Init<unsigned short>(6)) |
213 | { |
214 | return Standard_False; |
215 | } |
216 | const unsigned short THE_FS_QUAD_TRIS[6] = {0, 1, 3, 1, 2, 3}; |
217 | for (unsigned int aVertIter = 0; aVertIter < 6; ++aVertIter) |
218 | { |
219 | myIndices->SetIndex (aVertIter, THE_FS_QUAD_TRIS[aVertIter]); |
220 | } |
0b0320e7 |
221 | |
222 | OpenGl_Vec2 aVertices[4] = |
223 | { |
3bffef55 |
224 | OpenGl_Vec2(float(myViewWidth), 0.0f), |
225 | OpenGl_Vec2(float(myViewWidth), float(myViewHeight)), |
956d9157 |
226 | OpenGl_Vec2(0.0f, float(myViewHeight)), |
227 | OpenGl_Vec2(0.0f, 0.0f) |
0b0320e7 |
228 | }; |
229 | |
b6472664 |
230 | float* aCorners[4] = {}; |
231 | float aDiagCorner1[3] = {}; |
232 | float aDiagCorner2[3] = {}; |
0b0320e7 |
233 | |
234 | switch (myGradientParams.type) |
235 | { |
9af0d66b |
236 | case Aspect_GradientFillMethod_Horizontal: |
0b0320e7 |
237 | { |
bc379358 |
238 | aCorners[0] = myGradientParams.color2.ChangeData(); |
239 | aCorners[1] = myGradientParams.color2.ChangeData(); |
240 | aCorners[2] = myGradientParams.color1.ChangeData(); |
241 | aCorners[3] = myGradientParams.color1.ChangeData(); |
0b0320e7 |
242 | break; |
243 | } |
9af0d66b |
244 | case Aspect_GradientFillMethod_Vertical: |
0b0320e7 |
245 | { |
bc379358 |
246 | aCorners[0] = myGradientParams.color2.ChangeData(); |
247 | aCorners[1] = myGradientParams.color1.ChangeData(); |
956d9157 |
248 | aCorners[2] = myGradientParams.color1.ChangeData(); |
249 | aCorners[3] = myGradientParams.color2.ChangeData(); |
0b0320e7 |
250 | break; |
251 | } |
9af0d66b |
252 | case Aspect_GradientFillMethod_Diagonal1: |
0b0320e7 |
253 | { |
bc379358 |
254 | aCorners[0] = myGradientParams.color2.ChangeData(); |
956d9157 |
255 | aCorners[2] = myGradientParams.color1.ChangeData(); |
256 | aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[0][0] + aCorners[2][0]); |
257 | aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[0][1] + aCorners[2][1]); |
258 | aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[0][2] + aCorners[2][2]); |
d5846489 |
259 | aCorners[1] = aDiagCorner1; |
956d9157 |
260 | aCorners[3] = aDiagCorner2; |
0b0320e7 |
261 | break; |
262 | } |
9af0d66b |
263 | case Aspect_GradientFillMethod_Diagonal2: |
0b0320e7 |
264 | { |
bc379358 |
265 | aCorners[1] = myGradientParams.color1.ChangeData(); |
956d9157 |
266 | aCorners[3] = myGradientParams.color2.ChangeData(); |
267 | aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[1][0] + aCorners[3][0]); |
268 | aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[1][1] + aCorners[3][1]); |
269 | aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[1][2] + aCorners[3][2]); |
d5846489 |
270 | aCorners[0] = aDiagCorner1; |
956d9157 |
271 | aCorners[2] = aDiagCorner2; |
0b0320e7 |
272 | break; |
273 | } |
9af0d66b |
274 | case Aspect_GradientFillMethod_Corner1: |
9af0d66b |
275 | case Aspect_GradientFillMethod_Corner2: |
9af0d66b |
276 | case Aspect_GradientFillMethod_Corner3: |
9af0d66b |
277 | case Aspect_GradientFillMethod_Corner4: |
0b0320e7 |
278 | { |
956d9157 |
279 | Graphic3d_Attribute aCornerAttribInfo[] = |
280 | { |
281 | { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2 }, |
282 | { Graphic3d_TOA_UV, Graphic3d_TOD_VEC2 } |
283 | }; |
284 | |
285 | OpenGl_Vec2 anUVs[4] = |
286 | { |
287 | OpenGl_Vec2 (1.0f, 0.0f), |
288 | OpenGl_Vec2 (1.0f, 1.0f), |
289 | OpenGl_Vec2 (0.0f, 1.0f), |
290 | OpenGl_Vec2 (0.0f, 0.0f) |
291 | }; |
292 | |
293 | if (!myAttribs->Init (4, aCornerAttribInfo, 2)) |
294 | { |
295 | return Standard_False; |
296 | } |
297 | for (Standard_Integer anIt = 0; anIt < 4; ++anIt) |
298 | { |
299 | OpenGl_Vec2* aVertData = reinterpret_cast<OpenGl_Vec2*>(myAttribs->changeValue (anIt)); |
300 | *aVertData = aVertices[anIt]; |
301 | |
302 | OpenGl_Vec2* anUvData = reinterpret_cast<OpenGl_Vec2*>(myAttribs->changeValue (anIt) + myAttribs->AttributeOffset (1)); |
303 | // cyclically move highlighted corner depending on myGradientParams.type |
304 | *anUvData = anUVs[(anIt + myGradientParams.type - Aspect_GradientFillMethod_Corner1) % 4]; |
305 | } |
306 | return Standard_True; |
0b0320e7 |
307 | } |
9af0d66b |
308 | case Aspect_GradientFillMethod_Elliptical: |
309 | { |
310 | // construction of a circle circumscribed about a view rectangle |
311 | // using parametric equation (scaled by aspect ratio and centered) |
312 | const Standard_Integer aSubdiv = 64; |
313 | if (!myAttribs->Init (aSubdiv + 2, aGragientAttribInfo, 2)) |
314 | { |
315 | return Standard_False; |
316 | } |
317 | |
318 | OpenGl_Vec2 anEllipVerts[aSubdiv + 2]; |
319 | anEllipVerts[0] = OpenGl_Vec2 (float (myViewWidth) / 2.0f, float (myViewHeight) / 2.0f); |
320 | Standard_Real aTetta = (M_PI * 2.0) / aSubdiv; |
321 | Standard_Real aParam = 0.0; |
322 | for (Standard_Integer anIt = 1; anIt < aSubdiv + 2; ++anIt) |
323 | { |
324 | anEllipVerts[anIt] = OpenGl_Vec2 (float (Cos (aParam) * Sqrt (2.0) * myViewWidth / 2.0 + myViewWidth / 2.0f), |
325 | float (Sin (aParam) * Sqrt (2.0) * myViewHeight / 2.0 + myViewHeight / 2.0f)); |
326 | |
327 | aParam += aTetta; |
328 | } |
329 | for (Standard_Integer anIt = 0; anIt < aSubdiv + 2; ++anIt) |
330 | { |
331 | OpenGl_Vec2* aVertData = reinterpret_cast<OpenGl_Vec2*>(myAttribs->changeValue (anIt)); |
332 | *aVertData = anEllipVerts[anIt]; |
333 | |
334 | OpenGl_Vec3* aColorData = reinterpret_cast<OpenGl_Vec3*>(myAttribs->changeValue (anIt) + myAttribs->AttributeOffset (1)); |
335 | *aColorData = myGradientParams.color2.rgb(); |
336 | } |
337 | // the central vertex is colored in different way |
338 | OpenGl_Vec3* aColorData = reinterpret_cast<OpenGl_Vec3*>(myAttribs->changeValue (0) + myAttribs->AttributeOffset (1)); |
339 | *aColorData = myGradientParams.color1.rgb(); |
340 | |
341 | if (!myIndices->Init<unsigned short> (3 * aSubdiv)) |
342 | { |
343 | return Standard_False; |
344 | } |
345 | for (Standard_Integer aCurTri = 0; aCurTri < aSubdiv; aCurTri++) |
346 | { |
347 | myIndices->SetIndex (aCurTri * 3 + 0, 0); |
348 | myIndices->SetIndex (aCurTri * 3 + 1, aCurTri + 1); |
349 | myIndices->SetIndex (aCurTri * 3 + 2, aCurTri + 2); |
350 | } |
351 | |
352 | return Standard_True; |
353 | } |
354 | case Aspect_GradientFillMethod_None: |
0b0320e7 |
355 | { |
356 | break; |
357 | } |
358 | } |
359 | |
d5846489 |
360 | for (Standard_Integer anIt = 0; anIt < 4; ++anIt) |
0b0320e7 |
361 | { |
d5846489 |
362 | OpenGl_Vec2* aVertData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (anIt)); |
363 | *aVertData = aVertices[anIt]; |
0b0320e7 |
364 | |
d5846489 |
365 | OpenGl_Vec3* aColorData = reinterpret_cast<OpenGl_Vec3* >(myAttribs->changeValue (anIt) + myAttribs->AttributeOffset (1)); |
ba00aab7 |
366 | *aColorData = theCtx->Vec4FromQuantityColor (OpenGl_Vec4(aCorners[anIt][0], aCorners[anIt][1], aCorners[anIt][2], 1.0f)).rgb(); |
0b0320e7 |
367 | } |
368 | |
369 | return Standard_True; |
370 | } |
371 | |
372 | // ======================================================================= |
373 | // method : createTextureArray |
374 | // purpose : |
375 | // ======================================================================= |
3bffef55 |
376 | Standard_Boolean OpenGl_BackgroundArray::createTextureArray (const Handle(OpenGl_Workspace)& theWorkspace) const |
0b0320e7 |
377 | { |
378 | Graphic3d_Attribute aTextureAttribInfo[] = |
379 | { |
380 | { Graphic3d_TOA_POS, Graphic3d_TOD_VEC2 }, |
381 | { Graphic3d_TOA_UV, Graphic3d_TOD_VEC2 } |
382 | }; |
383 | |
384 | if (!myAttribs->Init (4, aTextureAttribInfo, 2)) |
385 | { |
386 | return Standard_False; |
387 | } |
388 | |
389 | GLfloat aTexRangeX = 1.0f; // texture <s> coordinate |
390 | GLfloat aTexRangeY = 1.0f; // texture <t> coordinate |
391 | |
392 | // Set up for stretching or tiling |
3bffef55 |
393 | GLfloat anOffsetX = 0.5f * (float )myViewWidth; |
394 | GLfloat anOffsetY = 0.5f * (float )myViewHeight; |
0b0320e7 |
395 | |
396 | // Setting this coefficient to -1.0f allows to tile textures relatively to the top-left corner of the view |
397 | // (value 1.0f corresponds to the initial behavior - tiling from the bottom-left corner) |
398 | GLfloat aCoef = -1.0f; |
399 | |
400 | // Get texture parameters |
401 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
bf5f0ca2 |
402 | const OpenGl_Aspects* anAspectFace = theWorkspace->Aspects(); |
cc8cbabe |
403 | GLfloat aTextureWidth = (GLfloat )anAspectFace->TextureSet (aCtx)->First()->SizeX(); |
404 | GLfloat aTextureHeight = (GLfloat )anAspectFace->TextureSet (aCtx)->First()->SizeY(); |
0b0320e7 |
405 | |
406 | if (myFillMethod == Aspect_FM_CENTERED) |
407 | { |
3bffef55 |
408 | anOffsetX = 0.5f * aTextureWidth; |
409 | anOffsetY = 0.5f * aTextureHeight; |
0b0320e7 |
410 | } |
411 | else if (myFillMethod == Aspect_FM_TILED) |
412 | { |
413 | aTexRangeX = (GLfloat )myViewWidth / aTextureWidth; |
414 | aTexRangeY = (GLfloat )myViewHeight / aTextureHeight; |
415 | } |
416 | |
417 | // NOTE: texture is mapped using GL_REPEAT wrapping mode so integer part |
418 | // is simply ignored, and negative multiplier is here for convenience only |
419 | // and does not result e.g. in texture mirroring |
420 | |
0b0320e7 |
421 | |
d5846489 |
422 | OpenGl_Vec2* aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (0)); |
0b0320e7 |
423 | aData[0] = OpenGl_Vec2 (anOffsetX, -aCoef * anOffsetY); |
424 | aData[1] = OpenGl_Vec2 (aTexRangeX, 0.0f); |
425 | |
d5846489 |
426 | aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (1)); |
0b0320e7 |
427 | aData[0] = OpenGl_Vec2 (anOffsetX, aCoef * anOffsetY); |
428 | aData[1] = OpenGl_Vec2 (aTexRangeX, aCoef * aTexRangeY); |
429 | |
d5846489 |
430 | aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (2)); |
431 | aData[0] = OpenGl_Vec2 (-anOffsetX, -aCoef * anOffsetY); |
432 | aData[1] = OpenGl_Vec2 (0.0f, 0.0f); |
433 | |
0b0320e7 |
434 | aData = reinterpret_cast<OpenGl_Vec2* >(myAttribs->changeValue (3)); |
435 | aData[0] = OpenGl_Vec2 (-anOffsetX, aCoef * anOffsetY); |
436 | aData[1] = OpenGl_Vec2 (0.0f, aCoef * aTexRangeY); |
437 | |
9af0d66b |
438 | if (!myIndices->Init<unsigned short>(6)) |
439 | { |
440 | return Standard_False; |
441 | } |
442 | const unsigned short THE_FS_QUAD_TRIS[6] = {0, 1, 2, 1, 3, 2}; |
443 | for (unsigned int aVertIter = 0; aVertIter < 6; ++aVertIter) |
444 | { |
445 | myIndices->SetIndex (aVertIter, THE_FS_QUAD_TRIS[aVertIter]); |
446 | } |
447 | |
0b0320e7 |
448 | return Standard_True; |
449 | } |
3bffef55 |
450 | |
451 | // ======================================================================= |
077a220c |
452 | // method : createCubeMapArray |
453 | // purpose : |
454 | // ======================================================================= |
455 | Standard_Boolean OpenGl_BackgroundArray::createCubeMapArray() const |
456 | { |
cdc54fb0 |
457 | const Graphic3d_Attribute aCubeMapAttribInfo[] = |
077a220c |
458 | { |
cdc54fb0 |
459 | { Graphic3d_TOA_POS, Graphic3d_TOD_VEC3 } |
077a220c |
460 | }; |
461 | |
ba00aab7 |
462 | if (myAttribs.IsNull()) |
463 | { |
02a2beaa |
464 | myAttribs = new Graphic3d_Buffer (Graphic3d_Buffer::DefaultAllocator()); |
465 | myIndices = new Graphic3d_IndexBuffer (Graphic3d_Buffer::DefaultAllocator()); |
ba00aab7 |
466 | } |
cdc54fb0 |
467 | if (!myAttribs->Init (8, aCubeMapAttribInfo, 1) |
9af0d66b |
468 | || !myIndices->Init<unsigned short> (6 * 3 * 2)) |
077a220c |
469 | { |
470 | return Standard_False; |
471 | } |
472 | |
077a220c |
473 | { |
cdc54fb0 |
474 | OpenGl_Vec3* aData = reinterpret_cast<OpenGl_Vec3*>(myAttribs->changeValue(0)); |
475 | aData[0].SetValues (-1.0, -1.0, 1.0); |
476 | aData[1].SetValues ( 1.0, -1.0, 1.0); |
477 | aData[2].SetValues (-1.0, 1.0, 1.0); |
478 | aData[3].SetValues ( 1.0, 1.0, 1.0); |
479 | aData[4].SetValues (-1.0, -1.0, -1.0); |
480 | aData[5].SetValues ( 1.0, -1.0, -1.0); |
481 | aData[6].SetValues (-1.0, 1.0, -1.0); |
482 | aData[7].SetValues ( 1.0, 1.0, -1.0); |
483 | } |
484 | { |
9af0d66b |
485 | const unsigned short THE_BOX_TRIS[] = |
486 | { |
487 | 0, 1, 2, 2, 1, 3, // top face |
488 | 1, 5, 7, 1, 7, 3, // right face |
489 | 0, 6, 4, 0, 2, 6, // left face |
490 | 4, 6, 5, 6, 7, 5, // bottom face |
491 | 0, 5, 1, 0, 4, 5, // front face |
492 | 2, 7, 6, 2, 3, 7 // back face |
493 | }; |
494 | for (unsigned int aVertIter = 0; aVertIter < 6 * 3 * 2; ++aVertIter) |
cdc54fb0 |
495 | { |
9af0d66b |
496 | myIndices->SetIndex (aVertIter, THE_BOX_TRIS[aVertIter]); |
cdc54fb0 |
497 | } |
077a220c |
498 | } |
499 | |
500 | return Standard_True; |
501 | } |
502 | |
503 | // ======================================================================= |
504 | // method : Render |
3bffef55 |
505 | // purpose : |
506 | // ======================================================================= |
cdc54fb0 |
507 | void OpenGl_BackgroundArray::Render (const Handle(OpenGl_Workspace)& theWorkspace, |
508 | Graphic3d_Camera::Projection theProjection) const |
3bffef55 |
509 | { |
510 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
511 | Standard_Integer aViewSizeX = aCtx->Viewport()[2]; |
512 | Standard_Integer aViewSizeY = aCtx->Viewport()[3]; |
f051908e |
513 | Graphic3d_Vec2i aTileOffset, aTileSize; |
514 | |
008210c3 |
515 | if (aCtx->Camera()->Tile().IsValid()) |
3bffef55 |
516 | { |
008210c3 |
517 | aViewSizeX = aCtx->Camera()->Tile().TotalSize.x(); |
518 | aViewSizeY = aCtx->Camera()->Tile().TotalSize.y(); |
f051908e |
519 | |
008210c3 |
520 | aTileOffset = aCtx->Camera()->Tile().OffsetLowerLeft(); |
521 | aTileSize = aCtx->Camera()->Tile().TileSize; |
3bffef55 |
522 | } |
523 | if (myToUpdate |
524 | || myViewWidth != aViewSizeX |
ba00aab7 |
525 | || myViewHeight != aViewSizeY |
526 | || myAttribs.IsNull() |
527 | || myVboAttribs.IsNull()) |
3bffef55 |
528 | { |
529 | myViewWidth = aViewSizeX; |
530 | myViewHeight = aViewSizeY; |
531 | init (theWorkspace); |
532 | } |
533 | |
534 | OpenGl_Mat4 aProjection = aCtx->ProjectionState.Current(); |
535 | OpenGl_Mat4 aWorldView = aCtx->WorldViewState.Current(); |
077a220c |
536 | |
cdc54fb0 |
537 | if (myType == Graphic3d_TOB_CUBEMAP) |
538 | { |
008210c3 |
539 | Graphic3d_Camera aCamera (aCtx->Camera()); |
cdc54fb0 |
540 | aCamera.SetZRange (0.01, 1.0); // is needed to avoid perspective camera exception |
541 | |
542 | // cancel translation |
543 | aCamera.MoveEyeTo (gp_Pnt (0.0, 0.0, 0.0)); |
544 | |
545 | // Handle projection matrix: |
546 | // - Cancel any head-to-eye translation for HMD display; |
547 | // - Ignore stereoscopic projection in case of non-HMD 3D display |
548 | // (ideally, we would need a stereoscopic cubemap image; adding a parallax makes no sense); |
549 | // - Force perspective projection when orthographic camera is active |
550 | // (orthographic projection makes no sense for cubemap). |
551 | const bool isCustomProj = aCamera.IsCustomStereoFrustum() |
552 | || aCamera.IsCustomStereoProjection(); |
553 | aCamera.SetProjectionType (theProjection == Graphic3d_Camera::Projection_Orthographic || !isCustomProj |
554 | ? Graphic3d_Camera::Projection_Perspective |
555 | : theProjection); |
556 | |
557 | aProjection = aCamera.ProjectionMatrixF(); |
558 | aWorldView = aCamera.OrientationMatrixF(); |
559 | if (isCustomProj) |
560 | { |
561 | // get projection matrix without pre-multiplied stereoscopic head-to-eye translation |
562 | if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye) |
563 | { |
564 | Graphic3d_Mat4 aMatProjL, aMatHeadToEyeL, aMatProjR, aMatHeadToEyeR; |
565 | aCamera.StereoProjectionF (aMatProjL, aMatHeadToEyeL, aMatProjR, aMatHeadToEyeR); |
566 | aProjection = aMatProjL; |
567 | } |
568 | else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye) |
569 | { |
570 | Graphic3d_Mat4 aMatProjL, aMatHeadToEyeL, aMatProjR, aMatHeadToEyeR; |
571 | aCamera.StereoProjectionF (aMatProjL, aMatHeadToEyeL, aMatProjR, aMatHeadToEyeR); |
572 | aProjection = aMatProjR; |
573 | } |
574 | } |
575 | } |
576 | else |
077a220c |
577 | { |
f051908e |
578 | aProjection.InitIdentity(); |
579 | aWorldView.InitIdentity(); |
008210c3 |
580 | if (aCtx->Camera()->Tile().IsValid()) |
f051908e |
581 | { |
582 | aWorldView.SetDiagonal (OpenGl_Vec4 (2.0f / aTileSize.x(), 2.0f / aTileSize.y(), 1.0f, 1.0f)); |
583 | if (myType == Graphic3d_TOB_GRADIENT) |
584 | { |
585 | aWorldView.SetColumn (3, OpenGl_Vec4 (-1.0f - 2.0f * aTileOffset.x() / aTileSize.x(), |
586 | -1.0f - 2.0f * aTileOffset.y() / aTileSize.y(), 0.0f, 1.0f)); |
587 | } |
588 | else |
589 | { |
590 | aWorldView.SetColumn (3, OpenGl_Vec4 (-1.0f + (float) aViewSizeX / aTileSize.x() - 2.0f * aTileOffset.x() / aTileSize.x(), |
591 | -1.0f + (float) aViewSizeY / aTileSize.y() - 2.0f * aTileOffset.y() / aTileSize.y(), 0.0f, 1.0f)); |
592 | } |
593 | } |
594 | else |
595 | { |
596 | aWorldView.SetDiagonal (OpenGl_Vec4 (2.0f / myViewWidth, 2.0f / myViewHeight, 1.0f, 1.0f)); |
597 | if (myType == Graphic3d_TOB_GRADIENT) |
598 | { |
599 | aWorldView.SetColumn (3, OpenGl_Vec4 (-1.0f, -1.0f, 0.0f, 1.0f)); |
600 | } |
601 | } |
077a220c |
602 | } |
3bffef55 |
603 | |
604 | aCtx->ProjectionState.Push(); |
605 | aCtx->WorldViewState.Push(); |
606 | aCtx->ProjectionState.SetCurrent (aProjection); |
607 | aCtx->WorldViewState.SetCurrent (aWorldView); |
608 | aCtx->ApplyProjectionMatrix(); |
609 | aCtx->ApplyModelViewMatrix(); |
610 | |
611 | OpenGl_PrimitiveArray::Render (theWorkspace); |
612 | |
613 | aCtx->ProjectionState.Pop(); |
614 | aCtx->WorldViewState.Pop(); |
615 | aCtx->ApplyProjectionMatrix(); |
616 | } |