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