1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * Copyright 2008 by Sun Microsystems, Inc.
7  *
8  * OpenOffice.org - a multi-platform office productivity suite
9  *
10  * This file is part of OpenOffice.org.
11  *
12  * OpenOffice.org is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Lesser General Public License version 3
14  * only, as published by the Free Software Foundation.
15  *
16  * OpenOffice.org is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Lesser General Public License version 3 for more details
20  * (a copy is included in the LICENSE file that accompanied this code).
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * version 3 along with OpenOffice.org.  If not, see
24  * <http://www.openoffice.org/license.html>
25  * for a copy of the LGPLv3 License.
26  *
27  ************************************************************************/
28 
29 #include <glm/gtc/matrix_transform.hpp>
30 #include <glm/gtc/type_ptr.hpp>
31 #include <vcl/opengl/OpenGLHelper.hxx>
32 #include <vcl/opengl/OpenGLContext.hxx>
33 #include <sal/log.hxx>
34 
35 #include <algorithm>
36 #include <array>
37 #include <utility>
38 
39 #include <comphelper/random.hxx>
40 
41 #include "TransitionImpl.hxx"
42 #include "Operation.hxx"
43 #include <math.h>
44 
TransitionScene(TransitionScene const & rOther)45 TransitionScene::TransitionScene(TransitionScene const& rOther)
46     : maLeavingSlidePrimitives(rOther.maLeavingSlidePrimitives)
47     , maEnteringSlidePrimitives(rOther.maEnteringSlidePrimitives)
48     , maOverallOperations(rOther.maOverallOperations)
49     , maSceneObjects(rOther.maSceneObjects)
50 {
51 }
52 
operator =(const TransitionScene & rOther)53 TransitionScene& TransitionScene::operator=(const TransitionScene& rOther)
54 {
55     TransitionScene aTmp(rOther);
56     swap(aTmp);
57     return *this;
58 }
59 
swap(TransitionScene & rOther)60 void TransitionScene::swap(TransitionScene& rOther)
61 {
62     using std::swap;
63 
64     swap(maLeavingSlidePrimitives, rOther.maLeavingSlidePrimitives);
65     swap(maEnteringSlidePrimitives, rOther.maEnteringSlidePrimitives);
66     swap(maOverallOperations, rOther.maOverallOperations);
67     swap(maSceneObjects, rOther.maSceneObjects);
68 }
69 
~OGLTransitionImpl()70 OGLTransitionImpl::~OGLTransitionImpl()
71 {
72 }
73 
uploadModelViewProjectionMatrices()74 void OGLTransitionImpl::uploadModelViewProjectionMatrices()
75 {
76     double EyePos(10.0);
77     double const RealF(1.0);
78     double const RealN(-1.0);
79     double const RealL(-1.0);
80     double RealR(1.0);
81     double const RealB(-1.0);
82     double RealT(1.0);
83     double ClipN(EyePos+5.0*RealN);
84     double ClipF(EyePos+15.0*RealF);
85     double ClipL(RealL*8.0);
86     double ClipR(RealR*8.0);
87     double ClipB(RealB*8.0);
88     double ClipT(RealT*8.0);
89 
90     glm::mat4 projection = glm::frustum<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
91     //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
92     glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
93                     1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
94                     1.0);
95     projection = glm::scale(projection, scale);
96     glm::mat4 modelview = glm::translate(glm::mat4(), glm::vec3(0, 0, -EyePos));
97 
98     GLint location = glGetUniformLocation( m_nProgramObject, "u_projectionMatrix" );
99     if( location != -1 ) {
100         glUniformMatrix4fv(location, 1, false, glm::value_ptr(projection));
101         CHECK_GL_ERROR();
102     }
103 
104     location = glGetUniformLocation( m_nProgramObject, "u_modelViewMatrix" );
105     if( location != -1 ) {
106         glUniformMatrix4fv(location, 1, false, glm::value_ptr(modelview));
107         CHECK_GL_ERROR();
108     }
109 }
110 
uploadPrimitives(const Primitives_t & primitives)111 static std::vector<int> uploadPrimitives(const Primitives_t& primitives)
112 {
113     int size = 0;
114     for (const Primitive& primitive: primitives)
115         size += primitive.getVerticesByteSize();
116 
117     CHECK_GL_ERROR();
118     glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
119     CHECK_GL_ERROR();
120     Vertex *buf = static_cast<Vertex*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
121 
122     std::vector<int> indices;
123     int last_pos = 0;
124     for (const Primitive& primitive: primitives) {
125         indices.push_back(last_pos);
126         int num = primitive.writeVertices(buf);
127         buf += num;
128         last_pos += num;
129     }
130 
131     CHECK_GL_ERROR();
132     glUnmapBuffer(GL_ARRAY_BUFFER);
133     CHECK_GL_ERROR();
134     return indices;
135 }
136 
prepare(sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,OpenGLContext * pContext)137 bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
138 {
139     m_nProgramObject = makeShader();
140     if (!m_nProgramObject)
141         return false;
142 
143     CHECK_GL_ERROR();
144     glUseProgram( m_nProgramObject );
145     CHECK_GL_ERROR();
146 
147     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
148     for(size_t i(0); i != rSceneObjects.size(); ++i) {
149         rSceneObjects[i]->prepare(m_nProgramObject);
150     }
151 
152     GLint location = glGetUniformLocation( m_nProgramObject, "leavingSlideTexture" );
153     if( location != -1 ) {
154         glUniform1i( location, 0 );  // texture unit 0
155         CHECK_GL_ERROR();
156     }
157 
158     location = glGetUniformLocation( m_nProgramObject, "enteringSlideTexture" );
159     if( location != -1 ) {
160         glUniform1i( location, 2 );  // texture unit 2
161         CHECK_GL_ERROR();
162     }
163 
164     uploadModelViewProjectionMatrices();
165 
166     m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
167     m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
168     m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
169     m_nTimeLocation = glGetUniformLocation( m_nProgramObject, "time" );
170 
171     glGenVertexArrays(1, &m_nVertexArrayObject);
172     glBindVertexArray(m_nVertexArrayObject);
173 
174     glGenBuffers(1, &m_nVertexBufferObject);
175     glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
176 
177     // In practice both leaving and entering slides share the same primitives.
178     m_nFirstIndices = uploadPrimitives(getScene().getLeavingSlide());
179 
180     // Attribute bindings
181     m_nPositionLocation = glGetAttribLocation(m_nProgramObject, "a_position");
182     if (m_nPositionLocation != -1) {
183         glEnableVertexAttribArray(m_nPositionLocation);
184         glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
185         CHECK_GL_ERROR();
186     }
187 
188     m_nNormalLocation = glGetAttribLocation(m_nProgramObject, "a_normal");
189     if (m_nNormalLocation != -1) {
190         glEnableVertexAttribArray(m_nNormalLocation);
191         glVertexAttribPointer( m_nNormalLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
192         CHECK_GL_ERROR();
193     }
194 
195     m_nTexCoordLocation = glGetAttribLocation(m_nProgramObject, "a_texCoord");
196     if (m_nTexCoordLocation != -1) {
197         glEnableVertexAttribArray(m_nTexCoordLocation);
198         glVertexAttribPointer( m_nTexCoordLocation, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
199         CHECK_GL_ERROR();
200     }
201 
202     glBindBuffer(GL_ARRAY_BUFFER, 0);
203     CHECK_GL_ERROR();
204 
205     prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
206     return true;
207 }
208 
finish()209 void OGLTransitionImpl::finish()
210 {
211     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
212     for(size_t i(0); i != rSceneObjects.size(); ++i) {
213         rSceneObjects[i]->finish();
214     }
215 
216     finishTransition();
217 
218     CHECK_GL_ERROR();
219     if( m_nProgramObject ) {
220         glDeleteBuffers(1, &m_nVertexBufferObject);
221         m_nVertexBufferObject = 0;
222         glDeleteVertexArrays(1, &m_nVertexArrayObject);
223         m_nVertexArrayObject = 0;
224         glDeleteProgram( m_nProgramObject );
225         m_nProgramObject = 0;
226     }
227     CHECK_GL_ERROR();
228 }
229 
prepare(double,double)230 void OGLTransitionImpl::prepare( double, double )
231 {
232 }
233 
cleanup()234 void OGLTransitionImpl::cleanup()
235 {
236 }
237 
prepareTransition(sal_Int32,sal_Int32,OpenGLContext *)238 void OGLTransitionImpl::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
239 {
240 }
241 
finishTransition()242 void OGLTransitionImpl::finishTransition()
243 {
244 }
245 
displaySlides_(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidthScale,double SlideHeightScale,OpenGLContext *)246 void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
247 {
248     CHECK_GL_ERROR();
249     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
250 
251     glUniform1f( m_nTimeLocation, nTime );
252 
253     glActiveTexture( GL_TEXTURE2 );
254     glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex );
255     glActiveTexture( GL_TEXTURE0 );
256 
257     displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
258     CHECK_GL_ERROR();
259 }
260 
display(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidth,double SlideHeight,double DispWidth,double DispHeight,OpenGLContext * pContext)261 void OGLTransitionImpl::display( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
262                                  double SlideWidth, double SlideHeight, double DispWidth, double DispHeight, OpenGLContext *pContext )
263 {
264     const double SlideWidthScale = SlideWidth/DispWidth;
265     const double SlideHeightScale = SlideHeight/DispHeight;
266 
267     CHECK_GL_ERROR();
268     glBindVertexArray(m_nVertexArrayObject);
269     prepare( SlideWidth, SlideHeight );
270 
271     CHECK_GL_ERROR();
272     displaySlides_( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale, pContext );
273     CHECK_GL_ERROR();
274     displayScene( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
275     CHECK_GL_ERROR();
276 }
277 
applyOverallOperations(double nTime,double SlideWidthScale,double SlideHeightScale)278 void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale )
279 {
280     const Operations_t& rOverallOperations(maScene.getOperations());
281     glm::mat4 matrix;
282     for(size_t i(0); i != rOverallOperations.size(); ++i)
283         rOverallOperations[i]->interpolate(matrix, nTime, SlideWidthScale, SlideHeightScale);
284     CHECK_GL_ERROR();
285     if (m_nOperationsTransformLocation != -1) {
286         glUniformMatrix4fv(m_nOperationsTransformLocation, 1, false, glm::value_ptr(matrix));
287         CHECK_GL_ERROR();
288     }
289 }
290 
displayPrimitives(const Primitives_t & primitives,GLint primitiveTransformLocation,double nTime,double WidthScale,double HeightScale,std::vector<int>::const_iterator first)291 static void displayPrimitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, std::vector<int>::const_iterator first)
292 {
293     for (const Primitive& primitive: primitives)
294         primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++);
295 }
296 
297 void
displaySlide(const double nTime,const sal_Int32 glSlideTex,const Primitives_t & primitives,double SlideWidthScale,double SlideHeightScale)298 OGLTransitionImpl::displaySlide(
299         const double nTime,
300         const sal_Int32 glSlideTex, const Primitives_t& primitives,
301         double SlideWidthScale, double SlideHeightScale )
302 {
303     CHECK_GL_ERROR();
304     glBindTexture(GL_TEXTURE_2D, glSlideTex);
305     CHECK_GL_ERROR();
306     if (m_nSceneTransformLocation != -1) {
307         glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
308         CHECK_GL_ERROR();
309     }
310     displayPrimitives(primitives, m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale, m_nFirstIndices.cbegin());
311     CHECK_GL_ERROR();
312 }
313 
314 void
displayUnbufferedSlide(const double nTime,const sal_Int32 glSlideTex,const Primitives_t & primitives,double SlideWidthScale,double SlideHeightScale)315 OGLTransitionImpl::displayUnbufferedSlide(
316         const double nTime,
317         const sal_Int32 glSlideTex, const Primitives_t& primitives,
318         double SlideWidthScale, double SlideHeightScale )
319 {
320     CHECK_GL_ERROR();
321     glBindTexture(GL_TEXTURE_2D, glSlideTex);
322     CHECK_GL_ERROR();
323     glBindVertexArray(0);
324     CHECK_GL_ERROR();
325     glBindBuffer(GL_ARRAY_BUFFER, 0);
326     CHECK_GL_ERROR();
327     if (m_nSceneTransformLocation != -1) {
328         glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
329         CHECK_GL_ERROR();
330     }
331     for (const Primitive& primitive: primitives)
332         primitive.display(m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale);
333     CHECK_GL_ERROR();
334     glBindVertexArray(m_nVertexArrayObject);
335     CHECK_GL_ERROR();
336     glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
337     CHECK_GL_ERROR();
338 }
339 
displayScene(double nTime,double SlideWidth,double SlideHeight,double DispWidth,double DispHeight)340 void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight )
341 {
342     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
343     CHECK_GL_ERROR();
344     for(size_t i(0); i != rSceneObjects.size(); ++i)
345         rSceneObjects[i]->display(m_nSceneTransformLocation, m_nPrimitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
346     CHECK_GL_ERROR();
347 }
348 
display(GLint primitiveTransformLocation,double nTime,double WidthScale,double HeightScale) const349 void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale) const
350 {
351     glm::mat4 matrix;
352     applyOperations( matrix, nTime, WidthScale, HeightScale );
353 
354     CHECK_GL_ERROR();
355     if (primitiveTransformLocation != -1) {
356         glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix));
357         CHECK_GL_ERROR();
358     }
359 
360     GLuint nVertexArrayObject;
361     glGenVertexArrays(1, &nVertexArrayObject);
362     CHECK_GL_ERROR();
363     glBindVertexArray(nVertexArrayObject);
364     CHECK_GL_ERROR();
365 
366     GLuint nBuffer;
367     glGenBuffers(1, &nBuffer);
368     CHECK_GL_ERROR();
369     glBindBuffer(GL_ARRAY_BUFFER, nBuffer);
370     CHECK_GL_ERROR();
371     glBufferData(GL_ARRAY_BUFFER, getVerticesByteSize(), Vertices.data(), GL_STATIC_DRAW);
372 
373     glEnableVertexAttribArray(0);
374     CHECK_GL_ERROR();
375     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
376     CHECK_GL_ERROR();
377     glDrawArrays( GL_TRIANGLES, 0, Vertices.size() );
378     CHECK_GL_ERROR();
379 
380     glDeleteBuffers(1, &nBuffer);
381     CHECK_GL_ERROR();
382 
383     glDeleteVertexArrays(1, &nVertexArrayObject);
384     CHECK_GL_ERROR();
385 }
386 
display(GLint primitiveTransformLocation,double nTime,double WidthScale,double HeightScale,int first) const387 void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const
388 {
389     glm::mat4 matrix;
390     applyOperations( matrix, nTime, WidthScale, HeightScale );
391 
392     CHECK_GL_ERROR();
393     if (primitiveTransformLocation != -1) {
394         glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix));
395         CHECK_GL_ERROR();
396     }
397     glDrawArrays( GL_TRIANGLES, first, Vertices.size() );
398 
399     CHECK_GL_ERROR();
400 }
401 
applyOperations(glm::mat4 & matrix,double nTime,double WidthScale,double HeightScale) const402 void Primitive::applyOperations(glm::mat4& matrix, double nTime, double WidthScale, double HeightScale) const
403 {
404     for(const auto & rOperation : Operations)
405         rOperation->interpolate(matrix, nTime, WidthScale, HeightScale);
406     matrix = glm::scale(matrix, glm::vec3(WidthScale, HeightScale, 1));
407 }
408 
display(GLint sceneTransformLocation,GLint primitiveTransformLocation,double nTime,double,double,double DispWidth,double DispHeight) const409 void SceneObject::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double /* SlideWidth */, double /* SlideHeight */, double DispWidth, double DispHeight ) const
410 {
411     // fixme: allow various model spaces, now we make it so that
412     // it is regular -1,-1 to 1,1, where the whole display fits in
413     glm::mat4 matrix;
414     if (DispHeight > DispWidth)
415         matrix = glm::scale(matrix, glm::vec3(DispHeight/DispWidth, 1, 1));
416     else
417         matrix = glm::scale(matrix, glm::vec3(1, DispWidth/DispHeight, 1));
418     CHECK_GL_ERROR();
419     if (sceneTransformLocation != -1) {
420         glUniformMatrix4fv(sceneTransformLocation, 1, false, glm::value_ptr(matrix));
421         CHECK_GL_ERROR();
422     }
423     displayPrimitives(maPrimitives, primitiveTransformLocation, nTime, 1, 1, maFirstIndices.cbegin());
424     CHECK_GL_ERROR();
425 }
426 
pushPrimitive(const Primitive & p)427 void SceneObject::pushPrimitive(const Primitive &p)
428 {
429     maPrimitives.push_back(p);
430 }
431 
SceneObject()432 SceneObject::SceneObject()
433     : maPrimitives()
434 {
435 }
436 
~SceneObject()437 SceneObject::~SceneObject()
438 {
439 }
440 
441 namespace
442 {
443 
444 class Iris : public SceneObject
445 {
446 public:
447     Iris() = default;
448 
449     virtual void prepare(GLuint program) override;
450     virtual void display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight) const override;
451     virtual void finish() override;
452 
453 private:
454     GLuint maTexture = 0;
455     GLuint maBuffer = 0;
456     GLuint maVertexArray = 0;
457 };
458 
display(GLint sceneTransformLocation,GLint primitiveTransformLocation,double nTime,double SlideWidth,double SlideHeight,double DispWidth,double DispHeight) const459 void Iris::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) const
460 {
461     glBindVertexArray(maVertexArray);
462     CHECK_GL_ERROR();
463     glBindTexture(GL_TEXTURE_2D, maTexture);
464     CHECK_GL_ERROR();
465     SceneObject::display(sceneTransformLocation, primitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
466 }
467 
prepare(GLuint program)468 void Iris::prepare(GLuint program)
469 {
470     CHECK_GL_ERROR();
471     static const GLubyte img[3] = { 80, 80, 80 };
472 
473     glGenTextures(1, &maTexture);
474     glBindTexture(GL_TEXTURE_2D, maTexture);
475     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
476     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
477     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
478     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
479     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
480     CHECK_GL_ERROR();
481 
482     glGenVertexArrays(1, &maVertexArray);
483     glBindVertexArray(maVertexArray);
484 
485     glGenBuffers(1, &maBuffer);
486     glBindBuffer(GL_ARRAY_BUFFER, maBuffer);
487     maFirstIndices = uploadPrimitives(maPrimitives);
488 
489     // Attribute bindings
490     GLint location = glGetAttribLocation(program, "a_position");
491     if (location != -1) {
492         glEnableVertexAttribArray(location);
493         glVertexAttribPointer( location, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
494         CHECK_GL_ERROR();
495     }
496 
497     location = glGetAttribLocation(program, "a_normal");
498     if (location != -1) {
499         glEnableVertexAttribArray(location);
500         glVertexAttribPointer( location, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
501         CHECK_GL_ERROR();
502     }
503 
504     location = glGetAttribLocation(program, "a_texCoord");
505     if (location != -1) {
506         glEnableVertexAttribArray(location);
507         glVertexAttribPointer( location, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
508         CHECK_GL_ERROR();
509     }
510 
511     glBindBuffer(GL_ARRAY_BUFFER, 0);
512 }
513 
finish()514 void Iris::finish()
515 {
516     CHECK_GL_ERROR();
517     glDeleteBuffers(1, &maBuffer);
518     CHECK_GL_ERROR();
519     glDeleteVertexArrays(1, &maVertexArray);
520     CHECK_GL_ERROR();
521     glDeleteTextures(1, &maTexture);
522     CHECK_GL_ERROR();
523 }
524 
525 }
526 
527 namespace
528 {
529 
530 class ReflectionTransition : public OGLTransitionImpl
531 {
532 public:
ReflectionTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)533     ReflectionTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
534         : OGLTransitionImpl(rScene, rSettings)
535     {}
536 
537 private:
538     virtual GLuint makeShader() const override;
539     virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
540 
prepareTransition(sal_Int32,sal_Int32,OpenGLContext *)541     virtual void prepareTransition( sal_Int32, sal_Int32, OpenGLContext* ) override {
542         glDisable(GL_CULL_FACE);
543     }
544 
finishTransition()545     virtual void finishTransition() override {
546         glEnable(GL_CULL_FACE);
547     }
548 };
549 
makeShader() const550 GLuint ReflectionTransition::makeShader() const
551 {
552     return OpenGLHelper::LoadShaders( "reflectionVertexShader", "reflectionFragmentShader" );
553 }
554 
displaySlides_(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidthScale,double SlideHeightScale,OpenGLContext *)555 void ReflectionTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
556                                               double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
557 {
558     CHECK_GL_ERROR();
559     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
560 
561     sal_Int32 texture;
562     Primitives_t slide;
563     if (nTime < 0.5) {
564         texture = glLeavingSlideTex;
565         slide = getScene().getLeavingSlide();
566     } else {
567         texture = glEnteringSlideTex;
568         slide = getScene().getEnteringSlide();
569     }
570 
571     displaySlide( nTime, texture, slide, SlideWidthScale, SlideHeightScale );
572     CHECK_GL_ERROR();
573 }
574 
575 std::shared_ptr<OGLTransitionImpl>
makeReflectionTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const Operations_t & rOverallOperations,const TransitionSettings & rSettings)576 makeReflectionTransition(
577         const Primitives_t& rLeavingSlidePrimitives,
578         const Primitives_t& rEnteringSlidePrimitives,
579         const Operations_t& rOverallOperations,
580         const TransitionSettings& rSettings)
581 {
582     return std::make_shared<ReflectionTransition>(
583             TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, SceneObjects_t()),
584             rSettings);
585 }
586 
587 }
588 
589 namespace
590 {
591 
592 class SimpleTransition : public OGLTransitionImpl
593 {
594 public:
SimpleTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)595     SimpleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
596         : OGLTransitionImpl(rScene, rSettings)
597     {
598     }
599 
600 private:
601     virtual GLuint makeShader() const override;
602 
603     virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
604 };
605 
makeShader() const606 GLuint SimpleTransition::makeShader() const
607 {
608     return OpenGLHelper::LoadShaders( "basicVertexShader", "basicFragmentShader" );
609 }
610 
displaySlides_(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidthScale,double SlideHeightScale,OpenGLContext *)611 void SimpleTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
612                                        double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
613 {
614     CHECK_GL_ERROR();
615     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
616 
617     CHECK_GL_ERROR();
618     displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
619     displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
620     CHECK_GL_ERROR();
621 }
622 
623 std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const Operations_t & rOverallOperations,const SceneObjects_t & rSceneObjects,const TransitionSettings & rSettings)624 makeSimpleTransition(
625         const Primitives_t& rLeavingSlidePrimitives,
626         const Primitives_t& rEnteringSlidePrimitives,
627         const Operations_t& rOverallOperations,
628         const SceneObjects_t& rSceneObjects,
629         const TransitionSettings& rSettings)
630 {
631     return std::make_shared<SimpleTransition>(
632             TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, rSceneObjects),
633             rSettings);
634 }
635 
636 std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const Operations_t & rOverallOperations,const TransitionSettings & rSettings=TransitionSettings ())637 makeSimpleTransition(
638         const Primitives_t& rLeavingSlidePrimitives,
639         const Primitives_t& rEnteringSlidePrimitives,
640         const Operations_t& rOverallOperations,
641         const TransitionSettings& rSettings = TransitionSettings())
642 {
643     return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, SceneObjects_t(), rSettings);
644 }
645 
646 std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const SceneObjects_t & rSceneObjects,const TransitionSettings & rSettings)647 makeSimpleTransition(
648         const Primitives_t& rLeavingSlidePrimitives,
649         const Primitives_t& rEnteringSlidePrimitives,
650         const SceneObjects_t& rSceneObjects,
651         const TransitionSettings& rSettings)
652 {
653     return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, Operations_t(), rSceneObjects, rSettings);
654 }
655 
656 std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings=TransitionSettings ())657 makeSimpleTransition(
658         const Primitives_t& rLeavingSlidePrimitives,
659         const Primitives_t& rEnteringSlidePrimitives,
660         const TransitionSettings& rSettings = TransitionSettings())
661 {
662     return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, Operations_t(), SceneObjects_t(), rSettings);
663 }
664 
665 }
666 
makeOutsideCubeFaceToLeft()667 std::shared_ptr<OGLTransitionImpl> makeOutsideCubeFaceToLeft()
668 {
669     Primitive Slide;
670 
671     Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
672     Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
673 
674     Primitives_t aLeavingPrimitives;
675     aLeavingPrimitives.push_back(Slide);
676 
677     Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),90,false,false,0.0,1.0));
678 
679     Primitives_t aEnteringPrimitives;
680     aEnteringPrimitives.push_back(Slide);
681 
682     Operations_t aOperations;
683     aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),-90,false,true,0.0,1.0));
684 
685     return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations);
686 }
687 
makeInsideCubeFaceToLeft()688 std::shared_ptr<OGLTransitionImpl> makeInsideCubeFaceToLeft()
689 {
690     Primitive Slide;
691 
692     Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
693     Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
694 
695     Primitives_t aLeavingPrimitives;
696     aLeavingPrimitives.push_back(Slide);
697 
698     Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),-90,false,false,0.0,1.0));
699 
700     Primitives_t aEnteringPrimitives;
701     aEnteringPrimitives.push_back(Slide);
702 
703     Operations_t aOperations;
704     aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),90,false,true,0.0,1.0));
705 
706     return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations);
707 }
708 
makeFallLeaving()709 std::shared_ptr<OGLTransitionImpl> makeFallLeaving()
710 {
711     Primitive Slide;
712 
713     Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
714     Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
715 
716     Primitives_t aEnteringPrimitives;
717     aEnteringPrimitives.push_back(Slide);
718 
719     Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(1,0,0),glm::vec3(0,-1,0), 90,true,true,0.0,1.0));
720     Primitives_t aLeavingPrimitives;
721     aLeavingPrimitives.push_back(Slide);
722 
723     TransitionSettings aSettings;
724     aSettings.mbUseMipMapEntering = false;
725 
726     return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSettings);
727 }
728 
makeTurnAround()729 std::shared_ptr<OGLTransitionImpl> makeTurnAround()
730 {
731     Primitive Slide;
732     TransitionSettings aSettings;
733 
734     Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
735     Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
736     Primitives_t aLeavingPrimitives;
737     aLeavingPrimitives.push_back(Slide);
738 
739     Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
740     aLeavingPrimitives.push_back(Slide);
741 
742     Slide.Operations.clear();
743     Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0),-180,true,false,0.0,1.0));
744     Primitives_t aEnteringPrimitives;
745     aEnteringPrimitives.push_back(Slide);
746 
747     Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
748     aEnteringPrimitives.push_back(Slide);
749 
750     Operations_t aOperations;
751     aOperations.push_back(makeSTranslate(glm::vec3(0, 0, -1.5),true, 0, 0.5));
752     aOperations.push_back(makeSTranslate(glm::vec3(0, 0, 1.5), true, 0.5, 1));
753     aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0, 1, 0),glm::vec3(0, 0, 0), -180, true, true, 0.0, 1.0));
754 
755     return makeReflectionTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations, aSettings);
756 }
757 
makeTurnDown()758 std::shared_ptr<OGLTransitionImpl> makeTurnDown()
759 {
760     Primitive Slide;
761 
762     Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
763     Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
764     Primitives_t aLeavingPrimitives;
765     aLeavingPrimitives.push_back(Slide);
766 
767     Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 0.0001), false, -1.0, 0.0));
768     Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), -90, true, 0.0, 1.0));
769     Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), 90, false, -1.0, 0.0));
770     Primitives_t aEnteringPrimitives;
771     aEnteringPrimitives.push_back(Slide);
772 
773     TransitionSettings aSettings;
774     aSettings.mbUseMipMapLeaving = false;
775 
776     return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSettings);
777 }
778 
makeIris()779 std::shared_ptr<OGLTransitionImpl> makeIris()
780 {
781     Primitive Slide;
782 
783     Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
784     Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
785     Primitives_t aEnteringPrimitives;
786     aEnteringPrimitives.push_back (Slide);
787 
788     Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0,  0.000001), false, -1, 0));
789     Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, -0.000002), false, 0.5, 1));
790     Primitives_t aLeavingPrimitives;
791     aLeavingPrimitives.push_back (Slide);
792 
793 
794     Primitive irisPart, part;
795     int i, nSteps = 24, nParts = 7;
796     double t = 1.0/nSteps, lx = 1, ly = 0, of=2.2, f=1.42;
797 
798     for (i=1; i<=nSteps; i++) {
799         double x = cos ((3*2*M_PI*t)/nParts);
800         double y = -sin ((3*2*M_PI*t)/nParts);
801         double cx = (f*x + 1)/2;
802         double cy = (f*y + 1)/2;
803         double lcx = (f*lx + 1)/2;
804         double lcy = (f*ly + 1)/2;
805         double cxo = (of*x + 1)/2;
806         double cyo = (of*y + 1)/2;
807         double lcxo = (of*lx + 1)/2;
808         double lcyo = (of*ly + 1)/2;
809         irisPart.pushTriangle (glm::vec2 (lcx, lcy),
810                                glm::vec2 (lcxo, lcyo),
811                                glm::vec2 (cx, cy));
812         irisPart.pushTriangle (glm::vec2 (cx, cy),
813                                glm::vec2 (lcxo, lcyo),
814                                glm::vec2 (cxo, cyo));
815         lx = x;
816         ly = y;
817         t += 1.0/nSteps;
818     }
819 
820     std::shared_ptr<Iris> pIris = std::make_shared<Iris>();
821     double angle = 87;
822 
823     for (i = 0; i < nParts; i++) {
824         irisPart.Operations.clear ();
825         double rx, ry;
826 
827         rx = cos ((2*M_PI*i)/nParts);
828         ry = sin ((2*M_PI*i)/nParts);
829         irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0),  angle, true, 0.0, 0.5));
830         irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), -angle, true, 0.5, 1));
831         if (i > 0) {
832             irisPart.Operations.push_back (makeSTranslate (glm::vec3(rx, ry, 0),  false, -1, 0));
833             irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), i*360.0/nParts, false, -1, 0));
834             irisPart.Operations.push_back (makeSTranslate (glm::vec3(-1, 0, 0),  false, -1, 0));
835         }
836         irisPart.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 1), false, -2, 0.0));
837         irisPart.Operations.push_back (makeSRotate (glm::vec3(1, .5, 0), glm::vec3(1, 0, 0), -30, false, -1, 0));
838         pIris->pushPrimitive (irisPart);
839     }
840 
841     SceneObjects_t aSceneObjects;
842     aSceneObjects.push_back (pIris);
843 
844     TransitionSettings aSettings;
845     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
846 
847     return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSceneObjects, aSettings);
848 }
849 
850 namespace
851 {
852 
853 class RochadeTransition : public ReflectionTransition
854 {
855 public:
RochadeTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)856     RochadeTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
857         : ReflectionTransition(rScene, rSettings)
858     {}
859 
860 private:
861     virtual void displaySlides_(double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext) override;
862 };
863 
displaySlides_(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidthScale,double SlideHeightScale,OpenGLContext *)864 void RochadeTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
865 {
866     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
867 
868     if( nTime > .5) {
869         displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
870         displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
871     } else {
872         displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
873         displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
874     }
875 }
876 
877 std::shared_ptr<OGLTransitionImpl>
makeRochadeTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)878 makeRochadeTransition(
879         const Primitives_t& rLeavingSlidePrimitives,
880         const Primitives_t& rEnteringSlidePrimitives,
881         const TransitionSettings& rSettings)
882 {
883     return std::make_shared<RochadeTransition>(
884             TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
885             rSettings)
886         ;
887 
888 }
889 }
890 
makeRochade()891 std::shared_ptr<OGLTransitionImpl> makeRochade()
892 {
893     Primitive Slide;
894     TransitionSettings aSettings;
895 
896     double w, h;
897 
898     w = 2.2;
899     h = 10;
900 
901     Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
902     Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
903 
904     Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.25, -0.25, true, 0, 1));
905     Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1));
906     Primitives_t aLeavingSlide;
907     aLeavingSlide.push_back(Slide);
908 
909     Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
910     aLeavingSlide.push_back(Slide);
911 
912     Slide.Operations.clear();
913     Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.75, 0.25, true, 0, 1));
914     Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, -h), false, -1, 0));
915     Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1));
916     Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), 45, true, false, -1, 0));
917     Primitives_t aEnteringSlide;
918     aEnteringSlide.push_back(Slide);
919 
920     Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0));
921     aEnteringSlide.push_back(Slide);
922 
923     return makeRochadeTransition(aLeavingSlide, aEnteringSlide, aSettings);
924 }
925 
randFromNeg1to1()926 static double randFromNeg1to1()
927 {
928     return comphelper::rng::uniform_real_distribution(-1.0, std::nextafter(1.0, DBL_MAX));
929 }
930 
931 // TODO(Q3): extract to basegfx
randNormVectorInXYPlane()932 static glm::vec3 randNormVectorInXYPlane()
933 {
934     glm::vec3 toReturn(randFromNeg1to1(),randFromNeg1to1(),0.0);
935     return glm::normalize(toReturn);
936 }
937 
938 template<typename T>
clamp(const T & rIn)939 static T clamp(const T& rIn)
940 {
941     return glm::clamp(rIn, T(-1.0), T(1.0));
942 }
943 
makeRevolvingCircles(sal_uInt16 nCircles,sal_uInt16 nPointsOnCircles)944 std::shared_ptr<OGLTransitionImpl> makeRevolvingCircles( sal_uInt16 nCircles , sal_uInt16 nPointsOnCircles )
945 {
946     double dAngle(2*3.1415926/static_cast<double>( nPointsOnCircles ));
947     if(nCircles < 2 || nPointsOnCircles < 4)
948         return makeNByMTileFlip(1,1);
949     float Radius(1.0/static_cast<double>( nCircles ));
950     float dRadius(Radius);
951     float LastRadius(0.0);
952     float NextRadius(2*Radius);
953 
954     /// now we know there is at least two circles
955     /// the first will always be a full circle
956     /// the last will always be the outer shell of the slide with a circle hole
957 
958     //add the full circle
959     std::vector<glm::vec2> unScaledTexCoords;
960     float TempAngle(0.0);
961     for(unsigned int Point(0); Point < nPointsOnCircles; ++Point)
962     {
963         unScaledTexCoords.emplace_back( cos(TempAngle - 3.1415926/2.0) , sin(TempAngle- 3.1415926/2.0) );
964 
965         TempAngle += dAngle;
966     }
967 
968     Primitives_t aLeavingSlide;
969     Primitives_t aEnteringSlide;
970     {
971         Primitive EnteringSlide;
972         Primitive LeavingSlide;
973         for(int Point(0); Point + 1 < nPointsOnCircles; ++Point)
974         {
975             EnteringSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5 , 0.5 ) );
976             LeavingSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5, 0.5) );
977         }
978         EnteringSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius * unScaledTexCoords[ 0 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ nPointsOnCircles - 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) );
979         LeavingSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) );
980 
981         glm::vec3 axis(randNormVectorInXYPlane());
982         EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
983         LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
984         EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) );
985 
986         aEnteringSlide.push_back(EnteringSlide);
987         aLeavingSlide.push_back(LeavingSlide);
988         LastRadius = Radius;
989         Radius = NextRadius;
990         NextRadius += dRadius;
991     }
992 
993     for(int i(1); i < nCircles - 1; ++i)
994     {
995         Primitive LeavingSlide;
996         Primitive EnteringSlide;
997         for(int Side(0); Side < nPointsOnCircles - 1; ++Side)
998         {
999             EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1000             EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1001 
1002             LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1003             LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1004         }
1005 
1006         EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1007         EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1008 
1009         LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1010         LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1011 
1012         glm::vec3 axis(randNormVectorInXYPlane());
1013         EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
1014         LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
1015         EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) );
1016 
1017         aEnteringSlide.push_back(EnteringSlide);
1018         aLeavingSlide.push_back(LeavingSlide);
1019 
1020         LastRadius = Radius;
1021         Radius = NextRadius;
1022         NextRadius += dRadius;
1023     }
1024     {
1025         Radius = sqrt(2.0);
1026         Primitive LeavingSlide;
1027         Primitive EnteringSlide;
1028         for(int Side(0); Side < nPointsOnCircles - 1; ++Side)
1029         {
1030 
1031             EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1032             EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) );
1033 
1034             LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) );
1035             LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) );
1036         }
1037 
1038         EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1039         EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) );
1040 
1041         LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) );
1042         LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) );
1043 
1044         glm::vec3 axis(randNormVectorInXYPlane());
1045         EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) );
1046         LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) );
1047         EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) );
1048 
1049         aEnteringSlide.push_back(EnteringSlide);
1050         aLeavingSlide.push_back(LeavingSlide);
1051     }
1052 
1053     return makeSimpleTransition(aLeavingSlide, aEnteringSlide);
1054 }
1055 
makeHelix(sal_uInt16 nRows)1056 std::shared_ptr<OGLTransitionImpl> makeHelix( sal_uInt16 nRows )
1057 {
1058     double invN(1.0/static_cast<double>(nRows));
1059     double iDn = 0.0;
1060     double iPDn = invN;
1061     Primitives_t aLeavingSlide;
1062     Primitives_t aEnteringSlide;
1063     for(unsigned int i(0); i < nRows; ++i)
1064     {
1065         Primitive Tile;
1066 
1067         Tile.pushTriangle(glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iDn ) , glm::vec2( 0.0 , iPDn ));
1068 
1069         Tile.pushTriangle(glm::vec2( 1.0 , iPDn ) , glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iPDn ));
1070 
1071         Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , 180 ,
1072                                                 true, std::min(std::max(static_cast<double>(i - nRows/2.0)*invN/2.0,0.0),1.0),
1073                                                 std::min(std::max(static_cast<double>(i + nRows/2.0)*invN/2.0,0.0),1.0) ) );
1074 
1075         aLeavingSlide.push_back(Tile);
1076 
1077         Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , -180 , false,0.0,1.0) );
1078 
1079         aEnteringSlide.push_back(Tile);
1080 
1081         iDn += invN;
1082         iPDn += invN;
1083     }
1084 
1085     return makeSimpleTransition(aLeavingSlide, aEnteringSlide);
1086 }
1087 
fdiv(int a,int b)1088 static float fdiv(int a, int b)
1089 {
1090     return static_cast<float>(a)/b;
1091 }
1092 
vec(float x,float y,float nx,float ny)1093 static glm::vec2 vec(float x, float y, float nx, float ny)
1094 {
1095     x = x < 0.0 ? 0.0 : x;
1096     x = std::min(x, nx);
1097     y = y < 0.0 ? 0.0 : y;
1098     y = std::min(y, ny);
1099     return glm::vec2(fdiv(x, nx), fdiv(y, ny));
1100 }
1101 
makeNByMTileFlip(sal_uInt16 n,sal_uInt16 m)1102 std::shared_ptr<OGLTransitionImpl> makeNByMTileFlip( sal_uInt16 n, sal_uInt16 m )
1103 {
1104     Primitives_t aLeavingSlide;
1105     Primitives_t aEnteringSlide;
1106 
1107     for (int x = 0; x < n; x++)
1108     {
1109         for (int y = 0; y < n; y++)
1110         {
1111             Primitive aTile;
1112             glm::vec2 x11 = vec(x,   y,   n, m);
1113             glm::vec2 x12 = vec(x,   y+1, n, m);
1114             glm::vec2 x21 = vec(x+1, y,   n, m);
1115             glm::vec2 x22 = vec(x+1, y+1, n, m);
1116 
1117             aTile.pushTriangle(x21, x11, x12);
1118             aTile.pushTriangle(x22, x21, x12);
1119 
1120             aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, 180 , true, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f));
1121             aLeavingSlide.push_back(aTile);
1122 
1123             aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, -180, false, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f));
1124             aEnteringSlide.push_back(aTile);
1125         }
1126     }
1127 
1128     return makeSimpleTransition(aLeavingSlide, aEnteringSlide);
1129 }
1130 
operator =(const Primitive & rvalue)1131 Primitive& Primitive::operator=(const Primitive& rvalue)
1132 {
1133     Primitive aTmp(rvalue);
1134     swap(aTmp);
1135     return *this;
1136 }
1137 
Primitive(const Primitive & rvalue)1138 Primitive::Primitive(const Primitive& rvalue)
1139     : Operations(rvalue.Operations)
1140     , Vertices(rvalue.Vertices)
1141 {
1142 }
1143 
swap(Primitive & rOther)1144 void Primitive::swap(Primitive& rOther)
1145 {
1146     using std::swap;
1147 
1148     swap(Operations, rOther.Operations);
1149     swap(Vertices, rOther.Vertices);
1150 }
1151 
pushTriangle(const glm::vec2 & SlideLocation0,const glm::vec2 & SlideLocation1,const glm::vec2 & SlideLocation2)1152 void Primitive::pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2)
1153 {
1154     std::vector<glm::vec3> Verts;
1155     std::vector<glm::vec2> Texs;
1156     Verts.reserve(3);
1157     Texs.reserve(3);
1158 
1159     Verts.emplace_back( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 );
1160     Verts.emplace_back( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 );
1161     Verts.emplace_back( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 );
1162 
1163     //figure out if they're facing the correct way, and make them face the correct way.
1164     glm::vec3 Normal( glm::cross( Verts[0] - Verts[1] , Verts[1] - Verts[2] ) );
1165     if(Normal.z >= 0.0)//if the normal is facing us
1166     {
1167         Texs.push_back(SlideLocation0);
1168         Texs.push_back(SlideLocation1);
1169         Texs.push_back(SlideLocation2);
1170     }
1171     else // if the normal is facing away from us, make it face us
1172     {
1173         Texs.push_back(SlideLocation0);
1174         Texs.push_back(SlideLocation2);
1175         Texs.push_back(SlideLocation1);
1176         Verts.clear();
1177         Verts.emplace_back( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 );
1178         Verts.emplace_back( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 );
1179         Verts.emplace_back( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 );
1180     }
1181 
1182     Vertices.push_back({Verts[0], glm::vec3(0, 0, 1), Texs[0]}); //all normals always face the screen when untransformed.
1183     Vertices.push_back({Verts[1], glm::vec3(0, 0, 1), Texs[1]}); //all normals always face the screen when untransformed.
1184     Vertices.push_back({Verts[2], glm::vec3(0, 0, 1), Texs[2]}); //all normals always face the screen when untransformed.
1185 }
1186 
1187 namespace
1188 {
1189 
1190 class DiamondTransition : public SimpleTransition
1191 {
1192 public:
DiamondTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)1193     DiamondTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1194         : SimpleTransition(rScene, rSettings)
1195         {}
1196 
1197 private:
1198     virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
1199 };
1200 
makeLeavingSlide(double nTime)1201 Primitives_t makeLeavingSlide(double nTime)
1202 {
1203     Primitive Slide2;
1204     if( nTime >= 0.5 ) {
1205         double m = 1 - nTime;
1206 
1207         Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (m,0), glm::vec2 (0,m));
1208         Slide2.pushTriangle (glm::vec2 (nTime,0), glm::vec2 (1,0), glm::vec2 (1,m));
1209         Slide2.pushTriangle (glm::vec2 (1,nTime), glm::vec2 (1,1), glm::vec2 (nTime,1));
1210         Slide2.pushTriangle (glm::vec2 (0,nTime), glm::vec2 (m,1), glm::vec2 (0,1));
1211     } else {
1212         double l = 0.5 - nTime;
1213         double h = 0.5 + nTime;
1214 
1215         Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0.5,l));
1216         Slide2.pushTriangle (glm::vec2 (0.5,l), glm::vec2 (1,0), glm::vec2 (h,0.5));
1217         Slide2.pushTriangle (glm::vec2 (1,0), glm::vec2 (1,1), glm::vec2 (h,0.5));
1218         Slide2.pushTriangle (glm::vec2 (h,0.5), glm::vec2 (1,1), glm::vec2 (0.5,h));
1219         Slide2.pushTriangle (glm::vec2 (0.5,h), glm::vec2 (1,1), glm::vec2 (0,1));
1220         Slide2.pushTriangle (glm::vec2 (l,0.5), glm::vec2 (0.5,h), glm::vec2 (0,1));
1221         Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (l,0.5), glm::vec2 (0,1));
1222         Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (0.5,l), glm::vec2 (l,0.5));
1223     }
1224     Slide2.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.00000001), false, -1, 0));
1225     Primitives_t aLeavingSlidePrimitives;
1226     aLeavingSlidePrimitives.push_back (Slide2);
1227 
1228     return aLeavingSlidePrimitives;
1229 }
1230 
displaySlides_(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidthScale,double SlideHeightScale,OpenGLContext *)1231 void DiamondTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
1232                                         double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
1233 {
1234     CHECK_GL_ERROR();
1235     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
1236 
1237     CHECK_GL_ERROR();
1238     displayUnbufferedSlide( nTime, glLeavingSlideTex, makeLeavingSlide(nTime), SlideWidthScale, SlideHeightScale );
1239     displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
1240     CHECK_GL_ERROR();
1241 }
1242 
1243 std::shared_ptr<OGLTransitionImpl>
makeDiamondTransition(const TransitionSettings & rSettings)1244 makeDiamondTransition(const TransitionSettings& rSettings)
1245 {
1246     Primitive Slide1;
1247     Slide1.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1248     Slide1.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1249     Primitives_t aEnteringSlidePrimitives;
1250     aEnteringSlidePrimitives.push_back (Slide1);
1251     Primitives_t aLeavingSlidePrimitives;
1252     aLeavingSlidePrimitives.push_back (Slide1);
1253     return std::make_shared<DiamondTransition>(TransitionScene(aLeavingSlidePrimitives, aEnteringSlidePrimitives), rSettings);
1254 }
1255 
1256 }
1257 
makeDiamond()1258 std::shared_ptr<OGLTransitionImpl> makeDiamond()
1259 {
1260     TransitionSettings aSettings;
1261     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1262 
1263     return makeDiamondTransition(aSettings);
1264 }
1265 
makeVenetianBlinds(bool vertical,int parts)1266 std::shared_ptr<OGLTransitionImpl> makeVenetianBlinds( bool vertical, int parts )
1267 {
1268     static double t30 = tan( M_PI/6.0 );
1269     double ln = 0;
1270     double p = 1.0/parts;
1271 
1272     Primitives_t aLeavingSlide;
1273     Primitives_t aEnteringSlide;
1274     for( int i=0; i<parts; i++ ) {
1275         Primitive Slide;
1276         double n = (i + 1)/static_cast<double>(parts);
1277         if( vertical ) {
1278             Slide.pushTriangle (glm::vec2 (ln,0), glm::vec2 (n,0), glm::vec2 (ln,1));
1279             Slide.pushTriangle (glm::vec2 (n,0), glm::vec2 (ln,1), glm::vec2 (n,1));
1280             Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0, 1, 0), glm::vec3(n + ln - 1, 0, -t30*p), -120, true, true, 0.0, 1.0));
1281         } else {
1282             Slide.pushTriangle (glm::vec2 (0,ln), glm::vec2 (1,ln), glm::vec2 (0,n));
1283             Slide.pushTriangle (glm::vec2 (1,ln), glm::vec2 (0,n), glm::vec2 (1,n));
1284             Slide.Operations.push_back(makeRotateAndScaleDepthByHeight(glm::vec3(1, 0, 0), glm::vec3(0, 1 - n - ln, -t30*p), -120, true, true, 0.0, 1.0));
1285         }
1286         aLeavingSlide.push_back (Slide);
1287 
1288         if( vertical ) {
1289             Slide.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), glm::vec3(2*n - 1, 0, 0), -60, false, -1, 0));
1290             Slide.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), glm::vec3(n + ln - 1, 0, 0), 180, false, -1, 0));
1291         } else {
1292             Slide.Operations.push_back(makeSRotate(glm::vec3(1, 0, 0), glm::vec3(0, 1 - 2*n, 0), -60, false, -1, 0));
1293             Slide.Operations.push_back(makeSRotate(glm::vec3(1, 0, 0), glm::vec3(0, 1 - n - ln, 0), 180, false, -1, 0));
1294         }
1295         aEnteringSlide.push_back (Slide);
1296         ln = n;
1297     }
1298 
1299     return makeSimpleTransition(aLeavingSlide, aEnteringSlide);
1300 }
1301 
1302 namespace
1303 {
1304 
1305 class FadeSmoothlyTransition : public OGLTransitionImpl
1306 {
1307 public:
FadeSmoothlyTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)1308     FadeSmoothlyTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1309         : OGLTransitionImpl(rScene, rSettings)
1310     {}
1311 
1312 private:
1313     virtual GLuint makeShader() const override;
1314 };
1315 
makeShader() const1316 GLuint FadeSmoothlyTransition::makeShader() const
1317 {
1318     return OpenGLHelper::LoadShaders( "basicVertexShader", "fadeFragmentShader" );
1319 }
1320 
1321 std::shared_ptr<OGLTransitionImpl>
makeFadeSmoothlyTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)1322 makeFadeSmoothlyTransition(
1323         const Primitives_t& rLeavingSlidePrimitives,
1324         const Primitives_t& rEnteringSlidePrimitives,
1325         const TransitionSettings& rSettings)
1326 {
1327     return std::make_shared<FadeSmoothlyTransition>(
1328             TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
1329             rSettings)
1330         ;
1331 }
1332 
1333 }
1334 
makeFadeSmoothly()1335 std::shared_ptr<OGLTransitionImpl> makeFadeSmoothly()
1336 {
1337     Primitive Slide;
1338 
1339     Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1340     Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1341     Primitives_t aLeavingSlide;
1342     aLeavingSlide.push_back (Slide);
1343     Primitives_t aEnteringSlide;
1344     aEnteringSlide.push_back (Slide);
1345 
1346     TransitionSettings aSettings;
1347     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1348 
1349     return makeFadeSmoothlyTransition(aLeavingSlide, aEnteringSlide, aSettings);
1350 }
1351 
1352 namespace
1353 {
1354 
1355 class FadeThroughBlackTransition : public OGLTransitionImpl
1356 {
1357 public:
FadeThroughBlackTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)1358     FadeThroughBlackTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1359         : OGLTransitionImpl(rScene, rSettings)
1360     {}
1361 
1362 private:
1363     virtual GLuint makeShader() const override;
1364 };
1365 
makeShader() const1366 GLuint FadeThroughBlackTransition::makeShader() const
1367 {
1368     return OpenGLHelper::LoadShaders( "basicVertexShader", "fadeBlackFragmentShader" );
1369 }
1370 
1371 std::shared_ptr<OGLTransitionImpl>
makeFadeThroughBlackTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)1372 makeFadeThroughBlackTransition(
1373         const Primitives_t& rLeavingSlidePrimitives,
1374         const Primitives_t& rEnteringSlidePrimitives,
1375         const TransitionSettings& rSettings)
1376 {
1377     return std::make_shared<FadeThroughBlackTransition>(
1378             TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
1379             rSettings)
1380         ;
1381 }
1382 
1383 }
1384 
makeFadeThroughBlack()1385 std::shared_ptr<OGLTransitionImpl> makeFadeThroughBlack()
1386 {
1387     Primitive Slide;
1388 
1389     Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1390     Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1391     Primitives_t aLeavingSlide;
1392     aLeavingSlide.push_back (Slide);
1393     Primitives_t aEnteringSlide;
1394     aEnteringSlide.push_back (Slide);
1395 
1396     TransitionSettings aSettings;
1397     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1398 
1399     return makeFadeThroughBlackTransition(aLeavingSlide, aEnteringSlide, aSettings);
1400 }
1401 
1402 namespace
1403 {
1404 
1405 class PermTextureTransition : public OGLTransitionImpl
1406 {
1407 protected:
PermTextureTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)1408     PermTextureTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1409         : OGLTransitionImpl(rScene, rSettings)
1410         , m_nHelperTexture(0)
1411     {}
1412 
1413     virtual void finishTransition() override;
1414     virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1415 
1416 private:
1417     /** various data */
1418     GLuint m_nHelperTexture;
1419 };
1420 
finishTransition()1421 void PermTextureTransition::finishTransition()
1422 {
1423     CHECK_GL_ERROR();
1424     if ( m_nHelperTexture )
1425     {
1426         glDeleteTextures( 1, &m_nHelperTexture );
1427         m_nHelperTexture = 0;
1428     }
1429     CHECK_GL_ERROR();
1430 }
1431 
1432 int permutation256 [256]= {
1433 215, 100, 200, 204, 233,  50,  85, 196,
1434  71, 141, 122, 160,  93, 131, 243, 234,
1435 162, 183,  36, 155,   4,  62,  35, 205,
1436  40, 102,  33,  27, 255,  55, 214, 156,
1437  75, 163, 134, 126, 249,  74, 197, 228,
1438  72,  90, 206, 235,  17,  22,  49, 169,
1439 227,  89,  16,   5, 117,  60, 248, 230,
1440 217,  68, 138,  96, 194, 170, 136,  10,
1441 112, 238, 184, 189, 176,  42, 225, 212,
1442  84,  58, 175, 244, 150, 168, 219, 236,
1443 101, 208, 123,  37, 164, 110, 158, 201,
1444  78, 114,  57,  48,  70, 142, 106,  43,
1445 232,  26,  32, 252, 239,  98, 191,  94,
1446  59, 149,  39, 187, 203, 190,  19,  13,
1447 133,  45,  61, 247,  23,  34,  20,  52,
1448 118, 209, 146, 193, 222,  18,   1, 152,
1449  46,  41,  91, 148, 115,  25, 135,  77,
1450 254, 147, 224, 161,   9, 213, 223, 250,
1451 231, 251, 127, 166,  63, 179,  81, 130,
1452 139,  28, 120, 151, 241,  86, 111,   0,
1453  88, 153, 172, 182, 159, 105, 178,  47,
1454  51, 167,  65,  66,  92,  73, 198, 211,
1455 245, 195,  31, 220, 140,  76, 221, 186,
1456 154, 185,  56,  83,  38, 165, 109,  67,
1457 124, 226, 132,  53, 229,  29,  12, 181,
1458 121,  24, 207, 199, 177, 113,  30,  80,
1459   3,  97, 188,  79, 216, 173,   8, 145,
1460  87, 128, 180, 237, 240, 137, 125, 104,
1461  15, 242, 119, 246, 103, 143,  95, 144,
1462   2,  44,  69, 157, 192, 174,  14,  54,
1463 218,  82,  64, 210,  11,   6, 129,  21,
1464 116, 171,  99, 202,   7, 107, 253, 108
1465 };
1466 
initPermTexture(GLuint * texID)1467 void initPermTexture(GLuint *texID)
1468 {
1469     CHECK_GL_ERROR();
1470     glGenTextures(1, texID);
1471     glBindTexture(GL_TEXTURE_2D, *texID);
1472 
1473     static bool initialized = false;
1474     static unsigned char permutation2D[256*256*4];
1475     if( !initialized ) {
1476       int x, y;
1477 
1478       for( y=0; y < 256; y++ )
1479           for( x=0; x < 256; x++ )
1480               permutation2D[x*4 + y*1024] = permutation256[(y + permutation256[x]) & 0xff];
1481 
1482       initialized = true;
1483     }
1484 
1485     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, permutation2D );
1486     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1487     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1488     CHECK_GL_ERROR();
1489 }
1490 
prepareTransition(sal_Int32,sal_Int32,OpenGLContext *)1491 void PermTextureTransition::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
1492 {
1493     CHECK_GL_ERROR();
1494     GLint location = glGetUniformLocation( m_nProgramObject, "permTexture" );
1495     if( location != -1 ) {
1496         glActiveTexture(GL_TEXTURE1);
1497         CHECK_GL_ERROR();
1498         if( !m_nHelperTexture )
1499             initPermTexture( &m_nHelperTexture );
1500 
1501         glActiveTexture(GL_TEXTURE0);
1502         CHECK_GL_ERROR();
1503 
1504         glUniform1i( location, 1 );  // texture unit 1
1505         CHECK_GL_ERROR();
1506     }
1507     CHECK_GL_ERROR();
1508 }
1509 
1510 }
1511 
1512 namespace
1513 {
1514 
1515 class StaticNoiseTransition : public PermTextureTransition
1516 {
1517 public:
StaticNoiseTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)1518     StaticNoiseTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1519         : PermTextureTransition(rScene, rSettings)
1520     {}
1521 
1522 private:
1523     virtual GLuint makeShader() const override;
1524 };
1525 
makeShader() const1526 GLuint StaticNoiseTransition::makeShader() const
1527 {
1528     return OpenGLHelper::LoadShaders( "basicVertexShader", "staticFragmentShader" );
1529 }
1530 
1531 std::shared_ptr<OGLTransitionImpl>
makeStaticNoiseTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)1532 makeStaticNoiseTransition(
1533         const Primitives_t& rLeavingSlidePrimitives,
1534         const Primitives_t& rEnteringSlidePrimitives,
1535         const TransitionSettings& rSettings)
1536 {
1537     return std::make_shared<StaticNoiseTransition>(
1538             TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
1539             rSettings)
1540         ;
1541 }
1542 
1543 }
1544 
makeStatic()1545 std::shared_ptr<OGLTransitionImpl> makeStatic()
1546 {
1547     Primitive Slide;
1548 
1549     Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1550     Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1551     Primitives_t aLeavingSlide;
1552     aLeavingSlide.push_back (Slide);
1553     Primitives_t aEnteringSlide;
1554     aEnteringSlide.push_back (Slide);
1555 
1556     TransitionSettings aSettings;
1557     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1558 
1559     return makeStaticNoiseTransition(aLeavingSlide, aEnteringSlide, aSettings);
1560 }
1561 
1562 namespace
1563 {
1564 
1565 class DissolveTransition : public PermTextureTransition
1566 {
1567 public:
DissolveTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)1568     DissolveTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1569         : PermTextureTransition(rScene, rSettings)
1570     {}
1571 
1572 private:
1573     virtual GLuint makeShader() const override;
1574 };
1575 
makeShader() const1576 GLuint DissolveTransition::makeShader() const
1577 {
1578     return OpenGLHelper::LoadShaders( "basicVertexShader", "dissolveFragmentShader" );
1579 }
1580 
1581 std::shared_ptr<OGLTransitionImpl>
makeDissolveTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)1582 makeDissolveTransition(
1583         const Primitives_t& rLeavingSlidePrimitives,
1584         const Primitives_t& rEnteringSlidePrimitives,
1585         const TransitionSettings& rSettings)
1586 {
1587     return std::make_shared<DissolveTransition>(
1588             TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
1589             rSettings)
1590         ;
1591 }
1592 
1593 }
1594 
makeDissolve()1595 std::shared_ptr<OGLTransitionImpl> makeDissolve()
1596 {
1597     Primitive Slide;
1598 
1599     Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1600     Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1601     Primitives_t aLeavingSlide;
1602     aLeavingSlide.push_back (Slide);
1603     Primitives_t aEnteringSlide;
1604     aEnteringSlide.push_back (Slide);
1605 
1606     TransitionSettings aSettings;
1607     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1608 
1609     return makeDissolveTransition(aLeavingSlide, aEnteringSlide, aSettings);
1610 }
1611 
1612 namespace
1613 {
1614 
1615 class VortexTransition : public PermTextureTransition
1616 {
1617 public:
VortexTransition(const TransitionScene & rScene,const TransitionSettings & rSettings,int nNX,int nNY)1618     VortexTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, int nNX, int nNY)
1619         : PermTextureTransition(rScene, rSettings)
1620         , maNumTiles(nNX,nNY)
1621     {
1622         mvTileInfo.resize(6*maNumTiles.x*maNumTiles.y);
1623         mnFramebuffers[0] = 0;
1624         mnFramebuffers[1] = 0;
1625         mnDepthTextures[0] = 0;
1626         mnDepthTextures[1] = 0;
1627     }
1628 
1629 private:
1630     virtual void finishTransition() override;
1631     virtual GLuint makeShader() const override;
1632     virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1633     virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
1634 
1635     GLint mnSlideLocation = -1;
1636     GLint mnTileInfoLocation = -1;
1637     GLuint mnTileInfoBuffer = 0u;
1638     GLint mnShadowLocation = -1;
1639     std::array<GLuint, 2> mnFramebuffers;
1640     std::array<GLuint, 2> mnDepthTextures;
1641 
1642     glm::ivec2 maNumTiles;
1643 
1644     std::vector<GLfloat> mvTileInfo;
1645 };
1646 
finishTransition()1647 void VortexTransition::finishTransition()
1648 {
1649     PermTextureTransition::finishTransition();
1650 
1651     CHECK_GL_ERROR();
1652     glDeleteTextures(2, mnDepthTextures.data());
1653     mnDepthTextures = {0u, 0u};
1654     CHECK_GL_ERROR();
1655     glDeleteFramebuffers(2, mnFramebuffers.data());
1656     mnFramebuffers = {0u, 0u};
1657     glDeleteBuffers(1, &mnTileInfoBuffer);
1658     mnTileInfoBuffer = 0u;
1659     mnSlideLocation = -1;
1660     mnTileInfoLocation = -1;
1661     mnShadowLocation = -1;
1662     CHECK_GL_ERROR();
1663 }
1664 
makeShader() const1665 GLuint VortexTransition::makeShader() const
1666 {
1667     return OpenGLHelper::LoadShaders( "vortexVertexShader", "vortexFragmentShader", "vortexGeometryShader" );
1668 }
1669 
lookAt(const glm::vec3 & eye,const glm::vec3 & center,const glm::vec3 & up)1670 glm::mat4 lookAt(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up) {
1671     glm::vec3 f = glm::normalize(center - eye);
1672     glm::vec3 u = glm::normalize(up);
1673     glm::vec3 s = glm::normalize(glm::cross(f, u));
1674     u = glm::cross(s, f);
1675 
1676     return glm::mat4(s.x, u.x, -f.x, 0,
1677                      s.y, u.y, -f.y, 0,
1678                      s.z, u.z, -f.z, 0,
1679                      -glm::dot(s, eye), -glm::dot(u, eye), glm::dot(f, eye), 1);
1680 }
1681 
prepareTransition(sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,OpenGLContext * pContext)1682 void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
1683 {
1684     CHECK_GL_ERROR();
1685     PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
1686     CHECK_GL_ERROR();
1687 
1688     mnSlideLocation = glGetUniformLocation(m_nProgramObject, "slide");
1689     mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo");
1690     GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles");
1691     mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow");
1692     GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix");
1693     GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix");
1694     GLint location = glGetUniformLocation(m_nProgramObject, "leavingShadowTexture");
1695     glUniform1i(location, 2);
1696     location = glGetUniformLocation(m_nProgramObject, "enteringShadowTexture");
1697     glUniform1i(location, 3);
1698     CHECK_GL_ERROR();
1699 
1700     glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles));
1701     CHECK_GL_ERROR();
1702 
1703     glGenBuffers(1, &mnTileInfoBuffer);
1704     CHECK_GL_ERROR();
1705 
1706     // We store the (x,y) indexes of the tile each vertex belongs to in a float, so they must fit.
1707     assert(maNumTiles.x < 256);
1708     assert(maNumTiles.y < 256);
1709 
1710     // Two triangles, i.e. six vertices, per tile
1711     {
1712         int n = 0;
1713         for (int x = 0; x < maNumTiles.x; x++)
1714         {
1715             for (int y = 0; y < maNumTiles.y; y++)
1716             {
1717                 for (int v = 0; v < 6; v++)
1718                 {
1719                     mvTileInfo[n] = x + (y << 8) + (v << 16);
1720                     n++;
1721                 }
1722             }
1723         }
1724     }
1725 
1726     glBindBuffer(GL_ARRAY_BUFFER, mnTileInfoBuffer);
1727     CHECK_GL_ERROR();
1728     glEnableVertexAttribArray(mnTileInfoLocation);
1729     CHECK_GL_ERROR();
1730     glVertexAttribPointer(mnTileInfoLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1731     CHECK_GL_ERROR();
1732     glBufferData(GL_ARRAY_BUFFER, mvTileInfo.size()*sizeof(GLfloat), mvTileInfo.data(), GL_STATIC_DRAW);
1733     CHECK_GL_ERROR();
1734 
1735     glBindBuffer(GL_ARRAY_BUFFER, 0);
1736     CHECK_GL_ERROR();
1737 
1738     double EyePos(10.0);
1739     double const RealF(1.0);
1740     double const RealN(-1.0);
1741     double const RealL(-2.0);
1742     double RealR(2.0);
1743     double const RealB(-2.0);
1744     double RealT(2.0);
1745     double ClipN(EyePos+5.0*RealN);
1746     double ClipF(EyePos+15.0*RealF);
1747     double ClipL(RealL*8.0);
1748     double ClipR(RealR*8.0);
1749     double ClipB(RealB*8.0);
1750     double ClipT(RealT*8.0);
1751 
1752     glm::mat4 projection = glm::ortho<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
1753     //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
1754     glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
1755                     1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
1756                     1.0);
1757     projection = glm::scale(projection, scale);
1758     glUniformMatrix4fv(nOrthoProjectionMatrix, 1, false, glm::value_ptr(projection));
1759 
1760     glm::mat4 view = lookAt(glm::vec3(-1, 1, EyePos), glm::vec3(-0.5, 0.5, 0), glm::vec3(0, 1, 0));
1761     glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view));
1762 
1763     // Generate the framebuffers and textures for the shadows.
1764     glGenTextures(2, mnDepthTextures.data());
1765     glGenFramebuffers(2, mnFramebuffers.data());
1766 
1767     for (int i : {0, 1}) {
1768         glBindTexture(GL_TEXTURE_2D, mnDepthTextures[i]);
1769         glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
1770         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1771         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1772         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1773         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1774 
1775         glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[i]);
1776         glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[i], 0);
1777         glDrawBuffer(GL_NONE); // No color buffer is drawn to.
1778 
1779         // Always check that our framebuffer is ok
1780         if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
1781             SAL_WARN("slideshow.opengl", "Wrong framebuffer!");
1782             return;
1783         }
1784     }
1785 
1786     pContext->restoreDefaultFramebuffer();
1787     glBindTexture(GL_TEXTURE_2D, 0);
1788 
1789     glActiveTexture( GL_TEXTURE2 );
1790     glBindTexture( GL_TEXTURE_2D, mnDepthTextures[0] );
1791     glActiveTexture( GL_TEXTURE3 );
1792     glBindTexture( GL_TEXTURE_2D, mnDepthTextures[1] );
1793     glActiveTexture( GL_TEXTURE0 );
1794 }
1795 
displaySlides_(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidthScale,double SlideHeightScale,OpenGLContext * pContext)1796 void VortexTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * pContext )
1797 {
1798     CHECK_GL_ERROR();
1799     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
1800     glUniform1f( m_nTimeLocation, nTime );
1801     glUniform1f( mnShadowLocation, 1.0 );
1802 
1803     std::array<GLint, 4> viewport;
1804     glGetIntegerv(GL_VIEWPORT, viewport.data());
1805     glViewport(0, 0, 2048, 2048);
1806 
1807     glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[0]);
1808     glClear(GL_DEPTH_BUFFER_BIT);
1809     glUniform1f( mnSlideLocation, 0.0 );
1810     displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
1811 
1812     glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[1]);
1813     glClear(GL_DEPTH_BUFFER_BIT);
1814     glUniform1f( mnSlideLocation, 1.0 );
1815     displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
1816 
1817     glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
1818     pContext->restoreDefaultFramebuffer();
1819     glUniform1f( mnShadowLocation, 0.0 );
1820     glUniform1f( mnSlideLocation, 0.0 );
1821     displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
1822     glUniform1f( mnSlideLocation, 1.0 );
1823     displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
1824     CHECK_GL_ERROR();
1825 }
1826 
1827 std::shared_ptr<OGLTransitionImpl>
makeVortexTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings,int NX,int NY)1828 makeVortexTransition(const Primitives_t& rLeavingSlidePrimitives,
1829                      const Primitives_t& rEnteringSlidePrimitives,
1830                      const TransitionSettings& rSettings,
1831                      int NX,
1832                      int NY)
1833 {
1834     return std::make_shared<VortexTransition>(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
1835                                               rSettings,
1836                                               NX, NY);
1837 }
1838 
1839 }
1840 
makeVortex()1841 std::shared_ptr<OGLTransitionImpl> makeVortex()
1842 {
1843     const int NX = 96, NY = 96;
1844     Primitive Slide;
1845 
1846     for (int x = 0; x < NX; x++)
1847     {
1848         for (int y = 0; y < NY; y++)
1849         {
1850             Slide.pushTriangle (glm::vec2 (fdiv(x,NX),fdiv(y,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY)));
1851             Slide.pushTriangle (glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y+1,NY)));
1852         }
1853     }
1854     Primitives_t aLeavingSlide;
1855     aLeavingSlide.push_back (Slide);
1856     Primitives_t aEnteringSlide;
1857     aEnteringSlide.push_back (Slide);
1858 
1859     TransitionSettings aSettings;
1860     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1861     aSettings.mnRequiredGLVersion = 3.2f;
1862 
1863     return makeVortexTransition(aLeavingSlide, aEnteringSlide, aSettings, NX, NY);
1864 }
1865 
1866 namespace
1867 {
1868 
1869 class RippleTransition : public OGLTransitionImpl
1870 {
1871 public:
RippleTransition(const TransitionScene & rScene,const TransitionSettings & rSettings,const glm::vec2 & rCenter)1872     RippleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, const glm::vec2& rCenter)
1873         : OGLTransitionImpl(rScene, rSettings),
1874           maCenter(rCenter)
1875     {
1876     }
1877 
1878 private:
1879     virtual GLuint makeShader() const override;
1880     virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1881     virtual void prepare( double SlideWidth, double SlideHeight ) override;
1882 
1883     glm::vec2 maCenter;
1884     GLint maSlideRatioLocation = -1;
1885 };
1886 
makeShader() const1887 GLuint RippleTransition::makeShader() const
1888 {
1889     return OpenGLHelper::LoadShaders( "basicVertexShader", "rippleFragmentShader" );
1890 }
1891 
prepareTransition(sal_Int32,sal_Int32,OpenGLContext *)1892 void RippleTransition::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
1893 {
1894     GLint nCenterLocation = glGetUniformLocation(m_nProgramObject, "center");
1895     CHECK_GL_ERROR();
1896 
1897     glUniform2fv(nCenterLocation, 1, glm::value_ptr(maCenter));
1898     CHECK_GL_ERROR();
1899 
1900     maSlideRatioLocation = glGetUniformLocation(m_nProgramObject, "slideRatio");
1901     CHECK_GL_ERROR();
1902 }
1903 
prepare(double SlideWidth,double SlideHeight)1904 void RippleTransition::prepare( double SlideWidth, double SlideHeight )
1905 {
1906     if( maSlideRatioLocation != -1 )
1907         glUniform1f( maSlideRatioLocation, SlideWidth / SlideHeight );
1908 }
1909 
1910 std::shared_ptr<OGLTransitionImpl>
makeRippleTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)1911 makeRippleTransition(const Primitives_t& rLeavingSlidePrimitives,
1912                      const Primitives_t& rEnteringSlidePrimitives,
1913                      const TransitionSettings& rSettings)
1914 {
1915     // The center point should be adjustable by the user, but we have no way to do that in the UI
1916     return std::make_shared<RippleTransition>(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
1917                                               rSettings,
1918                                               glm::vec2(0.5, 0.5));
1919 }
1920 
1921 }
1922 
makeRipple()1923 std::shared_ptr<OGLTransitionImpl> makeRipple()
1924 {
1925     Primitive Slide;
1926 
1927     Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
1928     Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
1929 
1930     Primitives_t aLeavingSlide;
1931     aLeavingSlide.push_back (Slide);
1932 
1933     Primitives_t aEnteringSlide;
1934     aEnteringSlide.push_back (Slide);
1935 
1936     TransitionSettings aSettings;
1937     aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false;
1938 
1939     return makeRippleTransition(aLeavingSlide, aEnteringSlide, aSettings);
1940 }
1941 
createHexagon(Primitive & aHexagon,const int x,const int y,const int NX,const int NY)1942 static void createHexagon(Primitive& aHexagon, const int x, const int y, const int NX, const int NY)
1943 {
1944     if (y % 4 == 0)
1945     {
1946         aHexagon.pushTriangle(vec(x-1, y-1, NX, NY), vec(x,   y-2, NX, NY), vec(x, y+0.5, NX, NY));
1947         aHexagon.pushTriangle(vec(x,   y-2, NX, NY), vec(x+1, y-1, NX, NY), vec(x, y+0.5, NX, NY));
1948         aHexagon.pushTriangle(vec(x+1, y-1, NX, NY), vec(x+1, y,   NX, NY), vec(x, y+0.5, NX, NY));
1949         aHexagon.pushTriangle(vec(x+1, y,   NX, NY), vec(x,   y+1, NX, NY), vec(x, y+0.5, NX, NY));
1950         aHexagon.pushTriangle(vec(x,   y+1, NX, NY), vec(x-1, y,   NX, NY), vec(x, y+0.5, NX, NY));
1951         aHexagon.pushTriangle(vec(x-1, y,   NX, NY), vec(x-1, y-1, NX, NY), vec(x, y+0.5, NX, NY));
1952     }
1953     else
1954     {
1955         aHexagon.pushTriangle(vec(x-2, y-1, NX, NY), vec(x-1, y-2, NX, NY), vec(x, y+0.5, NX, NY));
1956         aHexagon.pushTriangle(vec(x-1, y-2, NX, NY), vec(x,   y-1, NX, NY), vec(x, y+0.5, NX, NY));
1957         aHexagon.pushTriangle(vec(x,   y-1, NX, NY), vec(x,   y,   NX, NY), vec(x, y+0.5, NX, NY));
1958         aHexagon.pushTriangle(vec(x,   y,   NX, NY), vec(x-1, y+1, NX, NY), vec(x, y+0.5, NX, NY));
1959         aHexagon.pushTriangle(vec(x-1, y+1, NX, NY), vec(x-2, y,   NX, NY), vec(x, y+0.5, NX, NY));
1960         aHexagon.pushTriangle(vec(x-2, y,   NX, NY), vec(x-2, y-1, NX, NY), vec(x, y+0.5, NX, NY));
1961     }
1962 }
1963 
1964 namespace
1965 {
1966 
1967 class GlitterTransition : public PermTextureTransition
1968 {
1969 public:
GlitterTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)1970     GlitterTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
1971         : PermTextureTransition(rScene, rSettings)
1972     {
1973     }
1974 
1975 private:
1976     virtual GLuint makeShader() const override;
1977     virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
1978     virtual void cleanup() override;
1979 
1980     GLuint maBuffer = 0;
1981 };
1982 
makeShader() const1983 GLuint GlitterTransition::makeShader() const
1984 {
1985     return OpenGLHelper::LoadShaders( "glitterVertexShader", "glitterFragmentShader" );
1986 }
1987 
1988 struct ThreeFloats
1989 {
1990     GLfloat x, y, z;
1991 };
1992 
prepareTransition(sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,OpenGLContext * pContext)1993 void GlitterTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
1994 {
1995     CHECK_GL_ERROR();
1996     PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
1997     CHECK_GL_ERROR();
1998 
1999     GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles");
2000     if (nNumTilesLocation != -1) {
2001         glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(glm::ivec2(41, 41 * 4 / 3)));
2002         CHECK_GL_ERROR();
2003     }
2004 
2005     glGenBuffers(1, &maBuffer);
2006     glBindBuffer(GL_ARRAY_BUFFER, maBuffer);
2007 
2008     // Upload the center of each hexagon.
2009     const Primitive& primitive = getScene().getLeavingSlide()[0];
2010     std::vector<ThreeFloats> vertices;
2011     for (int i = 2; i < primitive.getVerticesCount(); i += 18) {
2012         const glm::vec3& center = primitive.getVertex(i);
2013         for (int j = 0; j < 18; ++j)
2014             vertices.push_back({center.x, center.y, center.z});
2015     }
2016     glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);
2017 
2018     GLint location = glGetAttribLocation(m_nProgramObject, "center");
2019     if (location != -1) {
2020         glEnableVertexAttribArray(location);
2021         glVertexAttribPointer( location, 3, GL_FLOAT, false, 0, nullptr );
2022         CHECK_GL_ERROR();
2023     }
2024 
2025     glBindBuffer(GL_ARRAY_BUFFER, 0);
2026 }
2027 
cleanup()2028 void GlitterTransition::cleanup()
2029 {
2030     CHECK_GL_ERROR();
2031     glDeleteBuffers(1, &maBuffer);
2032     CHECK_GL_ERROR();
2033 }
2034 
2035 std::shared_ptr<OGLTransitionImpl>
makeGlitterTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)2036 makeGlitterTransition(const Primitives_t& rLeavingSlidePrimitives,
2037                       const Primitives_t& rEnteringSlidePrimitives,
2038                       const TransitionSettings& rSettings)
2039 {
2040     return std::make_shared<GlitterTransition>(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
2041                                                rSettings);
2042 }
2043 
2044 }
2045 
makeGlitter()2046 std::shared_ptr<OGLTransitionImpl> makeGlitter()
2047 {
2048     const int NX = 80;
2049     const int NY = NX * 4 / 3;
2050 
2051     Primitives_t aSlide;
2052     Primitives_t aEmptySlide;
2053     Primitive aHexagon;
2054 
2055     for (int y = 0; y < NY+2; y+=2)
2056         for (int x = 0; x < NX+2; x+=2)
2057             createHexagon(aHexagon, x, y, NX, NY);
2058 
2059     aSlide.push_back(aHexagon);
2060 
2061     return makeGlitterTransition(aSlide, aEmptySlide, TransitionSettings());
2062 }
2063 
2064 namespace
2065 {
2066 
2067 class HoneycombTransition : public PermTextureTransition
2068 {
2069 public:
HoneycombTransition(const TransitionScene & rScene,const TransitionSettings & rSettings)2070     HoneycombTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
2071         : PermTextureTransition(rScene, rSettings)
2072     {
2073         mnDepthTextures[0] = 0;
2074         mnDepthTextures[1] = 0;
2075     }
2076 
2077 private:
2078     virtual void finishTransition() override;
2079     virtual GLuint makeShader() const override;
2080     virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
2081     virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
2082 
2083     GLint maHexagonSizeLocation = -1;
2084     GLint maSelectedTextureLocation = -1;
2085     GLint mnShadowLocation = -1;
2086     GLuint mnFramebuffer = 0u;
2087     std::array<GLuint, 2> mnDepthTextures;
2088 };
2089 
finishTransition()2090 void HoneycombTransition::finishTransition()
2091 {
2092     PermTextureTransition::finishTransition();
2093 
2094     CHECK_GL_ERROR();
2095     glActiveTexture( GL_TEXTURE2 );
2096     glBindTexture( GL_TEXTURE_2D, 0 );
2097     glActiveTexture( GL_TEXTURE3 );
2098     glBindTexture( GL_TEXTURE_2D, 0 );
2099     glActiveTexture( GL_TEXTURE0 );
2100     CHECK_GL_ERROR();
2101     glDeleteTextures(2, mnDepthTextures.data());
2102     mnDepthTextures = {0u, 0u};
2103     CHECK_GL_ERROR();
2104     glDeleteFramebuffers(1, &mnFramebuffer);
2105     mnFramebuffer = 0u;
2106     CHECK_GL_ERROR();
2107 }
2108 
makeShader() const2109 GLuint HoneycombTransition::makeShader() const
2110 {
2111     return OpenGLHelper::LoadShaders( "honeycombVertexShader", "honeycombFragmentShader", "honeycombGeometryShader" );
2112 }
2113 
prepareTransition(sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,OpenGLContext * pContext)2114 void HoneycombTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
2115 {
2116     CHECK_GL_ERROR();
2117     PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
2118 
2119     CHECK_GL_ERROR();
2120     maHexagonSizeLocation = glGetUniformLocation(m_nProgramObject, "hexagonSize");
2121     maSelectedTextureLocation = glGetUniformLocation( m_nProgramObject, "selectedTexture" );
2122     mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow");
2123     GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix");
2124     GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix");
2125     GLint location = glGetUniformLocation(m_nProgramObject, "colorShadowTexture");
2126     glUniform1i(location, 2);
2127     location = glGetUniformLocation(m_nProgramObject, "depthShadowTexture");
2128     glUniform1i(location, 3);
2129     CHECK_GL_ERROR();
2130 
2131     // We want to see the entering slide behind the leaving one.
2132     glEnable(GL_BLEND);
2133     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2134     CHECK_GL_ERROR();
2135 
2136     double EyePos(10.0);
2137     double const RealF(1.0);
2138     double const RealN(-1.0);
2139     double const RealL(-4.0);
2140     double RealR(4.0);
2141     double const RealB(-4.0);
2142     double RealT(4.0);
2143     double ClipN(EyePos+5.0*RealN);
2144     double ClipF(EyePos+15.0*RealF);
2145     double ClipL(RealL*8.0);
2146     double ClipR(RealR*8.0);
2147     double ClipB(RealB*8.0);
2148     double ClipT(RealT*8.0);
2149 
2150     glm::mat4 projection = glm::ortho<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
2151     //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
2152     glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
2153                     1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
2154                     1.0);
2155     projection = glm::scale(projection, scale);
2156     glUniformMatrix4fv(nOrthoProjectionMatrix, 1, false, glm::value_ptr(projection));
2157 
2158     glm::mat4 view = lookAt(glm::vec3(0, 0, EyePos), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
2159     glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view));
2160 
2161     // Generate the framebuffer and textures for the shadows.
2162     glGenTextures(2, mnDepthTextures.data());
2163     glActiveTexture(GL_TEXTURE2);
2164     glBindTexture(GL_TEXTURE_2D, mnDepthTextures[0]);
2165     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2048, 2048, 0, GL_RGBA, GL_FLOAT, nullptr);
2166     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2167     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2168     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2169     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2170 
2171     glActiveTexture(GL_TEXTURE3);
2172     glBindTexture(GL_TEXTURE_2D, mnDepthTextures[1]);
2173     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
2174     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2175     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2176     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2177     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2178 
2179     glActiveTexture(GL_TEXTURE0);
2180     glGenFramebuffers(1, &mnFramebuffer);
2181     glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffer);
2182     glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mnDepthTextures[0], 0);
2183     glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[1], 0);
2184 
2185     // Always check that our framebuffer is ok
2186     if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
2187         SAL_WARN("slideshow.opengl", "Wrong framebuffer!");
2188         return;
2189     }
2190 
2191     pContext->restoreDefaultFramebuffer();
2192 }
2193 
displaySlides_(double nTime,sal_Int32 glLeavingSlideTex,sal_Int32 glEnteringSlideTex,double SlideWidthScale,double SlideHeightScale,OpenGLContext * pContext)2194 void HoneycombTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
2195                                           double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext )
2196 {
2197     CHECK_GL_ERROR();
2198     applyOverallOperations(nTime, SlideWidthScale, SlideHeightScale);
2199     glUniform1f(m_nTimeLocation, nTime);
2200     glUniform1f(mnShadowLocation, 1.0);
2201     CHECK_GL_ERROR();
2202 
2203     const float borderSize = 0.15f;
2204 
2205     std::array<GLint, 4> viewport;
2206     glGetIntegerv(GL_VIEWPORT, viewport.data());
2207     glViewport(0, 0, 2048, 2048);
2208     glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffer);
2209     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2210     glUniform1f(mnShadowLocation, 1.0);
2211     glUniform1f(maSelectedTextureLocation, 1.0);
2212     glUniform1f(maHexagonSizeLocation, 1.0f - borderSize);
2213     displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2214     glUniform1f(maHexagonSizeLocation, 1.0f + borderSize);
2215     displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2216 
2217     // The back (entering) slide needs to be drawn before the front (leaving) one in order for blending to work.
2218     glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
2219     pContext->restoreDefaultFramebuffer();
2220     glUniform1f(mnShadowLocation, 0.0);
2221     glUniform1f(maSelectedTextureLocation, 0.0);
2222     glUniform1f(maHexagonSizeLocation, 1.0f - borderSize);
2223     displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale);
2224     glUniform1f(maHexagonSizeLocation, 1.0f + borderSize);
2225     displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale);
2226     glUniform1f(maSelectedTextureLocation, 1.0);
2227     glUniform1f(maHexagonSizeLocation, 1.0f - borderSize);
2228     displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2229     glUniform1f(maHexagonSizeLocation, 1.0f + borderSize);
2230     displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
2231     CHECK_GL_ERROR();
2232 }
2233 
2234 std::shared_ptr<OGLTransitionImpl>
makeHoneycombTransition(const Primitives_t & rLeavingSlidePrimitives,const Primitives_t & rEnteringSlidePrimitives,const TransitionSettings & rSettings)2235 makeHoneycombTransition(const Primitives_t& rLeavingSlidePrimitives,
2236                         const Primitives_t& rEnteringSlidePrimitives,
2237                         const TransitionSettings& rSettings)
2238 {
2239     // The center point should be adjustable by the user, but we have no way to do that in the UI
2240     return std::make_shared<HoneycombTransition>(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
2241                                                  rSettings);
2242 }
2243 
2244 }
2245 
makeHoneycomb()2246 std::shared_ptr<OGLTransitionImpl> makeHoneycomb()
2247 {
2248     const int NX = 21;
2249     const int NY = 21;
2250 
2251     TransitionSettings aSettings;
2252     aSettings.mnRequiredGLVersion = 3.2f;
2253 
2254     Primitives_t aSlide;
2255     Primitive aHexagon;
2256     for (int y = 0; y < NY+2; y+=2)
2257         for (int x = 0; x < NX+2; x+=2)
2258             aHexagon.pushTriangle(glm::vec2((y % 4) ? fdiv(x, NX) : fdiv(x + 1, NX), fdiv(y, NY)), glm::vec2(1, 0), glm::vec2(0, 0));
2259     aSlide.push_back(aHexagon);
2260 
2261     return makeHoneycombTransition(aSlide, aSlide, aSettings);
2262 }
2263 
makeNewsflash()2264 std::shared_ptr<OGLTransitionImpl> makeNewsflash()
2265 {
2266     Primitive Slide;
2267 
2268     Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
2269     Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
2270     Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),3000,true,0,0.5));
2271     Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),true,0,0.5));
2272     Slide.Operations.push_back(makeSTranslate(glm::vec3(-10000, 0, 0),false, 0.5, 2));
2273     Primitives_t aLeavingSlide;
2274     aLeavingSlide.push_back(Slide);
2275 
2276     Slide.Operations.clear();
2277     Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),-3000,true,0.5,1));
2278     Slide.Operations.push_back(makeSTranslate(glm::vec3(-100, 0, 0),false, -1, 1));
2279     Slide.Operations.push_back(makeSTranslate(glm::vec3(100, 0, 0),false, 0.5, 1));
2280     Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),false,-1,1));
2281     Slide.Operations.push_back(makeSScale(glm::vec3(100,100,100),glm::vec3(0,0,0),true,0.5,1));
2282     Primitives_t aEnteringSlide;
2283     aEnteringSlide.push_back(Slide);
2284 
2285     Operations_t aOverallOperations;
2286     aOverallOperations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0.2,0.2,0),1080,true,0,1));
2287 
2288     return makeSimpleTransition(aLeavingSlide, aEnteringSlide, aOverallOperations);
2289 }
2290 
2291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2292