/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html >
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vcl/opengl/OpenGLHelper.hxx>
#include <vcl/opengl/OpenGLContext.hxx>
#include <sal/log.hxx>
#include <algorithm>
#include <array>
#include <comphelper/random.hxx>
#include "Operation.hxx"
#include "TransitionImpl.hxx"
#include <cmath>
TransitionScene::TransitionScene(TransitionScene
const & rOther)
: maLeavingSlidePrimitives(rOther.maLeavingSlidePrimitives)
, maEnteringSlidePrimitives(rOther.maEnteringSlidePrimitives)
, maOverallOperations(rOther.maOverallOperations)
, maSceneObjects(rOther.maSceneObjects)
{
}
TransitionScene& TransitionScene::
operator =(
const TransitionScene& rOther)
{
TransitionScene aTmp(rOther);
swap(aTmp);
return *
this ;
}
void TransitionScene::swap(TransitionScene& rOther)
{
using std::swap;
swap(maLeavingSlidePrimitives, rOther.maLeavingSlidePrimitives);
swap(maEnteringSlidePrimitives, rOther.maEnteringSlidePrimitives);
swap(maOverallOperations, rOther.maOverallOperations);
swap(maSceneObjects, rOther.maSceneObjects);
}
OGLTransitionImpl::~OGLTransitionImpl()
{
}
void OGLTransitionImpl::uploadModelViewProjectionMatrices()
{
double EyePos(10.0);
double const RealF(1.0);
double const RealN(-1.0);
double const RealL(-1.0);
double RealR(1.0);
double const RealB(-1.0);
double RealT(1.0);
double ClipN(EyePos+5.0*RealN);
double ClipF(EyePos+15.0*RealF);
double ClipL(RealL*8.0);
double ClipR(RealR*8.0);
double ClipB(RealB*8.0);
double ClipT(RealT*8.0);
glm::mat4 projection = glm::frustum<
float >(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
//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.
glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (C
lipR - ClipL))),
1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
1.0);
projection = glm::scale(projection, scale);
glm::mat4 modelview = glm::translate(glm::mat4(), glm::vec3(0, 0, -EyePos));
GLint location = glGetUniformLocation( m_nProgramObject, "u_projectionMatrix" );
if ( location != -1 ) {
glUniformMatrix4fv(location, 1, false , glm::value_ptr(projection));
CHECK_GL_ERROR();
}
location = glGetUniformLocation( m_nProgramObject, "u_modelViewMatrix" );
if ( location != -1 ) {
glUniformMatrix4fv(location, 1, false , glm::value_ptr(modelview));
CHECK_GL_ERROR();
}
}
static std::vector<int > uploadPrimitives(const Primitives_t& primitives)
{
int size = 0;
for (const Primitive& primitive: primitives)
size += primitive.getVerticesByteSize();
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
CHECK_GL_ERROR();
Vertex *buf = static_cast <Vertex*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
std::vector<int > indices;
int last_pos = 0;
for (const Primitive& primitive: primitives) {
indices.push_back(last_pos);
int num = primitive.writeVertices(buf);
buf += num;
last_pos += num;
}
CHECK_GL_ERROR();
glUnmapBuffer(GL_ARRAY_BUFFER);
CHECK_GL_ERROR();
return indices;
}
bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
{
m_nProgramObject = makeShader();
if (!m_nProgramObject)
return false ;
CHECK_GL_ERROR();
glUseProgram( m_nProgramObject );
CHECK_GL_ERROR();
const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
for (const auto & rSceneObject : rSceneObjects) {
rSceneObject->prepare(m_nProgramObject);
}
GLint location = glGetUniformLocation( m_nProgramObject, "leavingSlideTexture" );
if ( location != -1 ) {
glUniform1i( location, 0 ); // texture unit 0
CHECK_GL_ERROR();
}
location = glGetUniformLocation( m_nProgramObject, "enteringSlideTexture" );
if ( location != -1 ) {
glUniform1i( location, 2 ); // texture unit 2
CHECK_GL_ERROR();
}
uploadModelViewProjectionMatrices();
m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
m_nTimeLocation = glGetUniformLocation( m_nProgramObject, "time" );
glGenVertexArrays(1, &m_nVertexArrayObject);
glBindVertexArray(m_nVertexArrayObject);
glGenBuffers(1, &m_nVertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
// In practice both leaving and entering slides share the same primitives.
m_nFirstIndices = uploadPrimitives(getScene().getLeavingSlide());
// Attribute bindings
m_nPositionLocation = glGetAttribLocation(m_nProgramObject, "a_position" );
if (m_nPositionLocation != -1) {
glEnableVertexAttribArray(m_nPositionLocation);
glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false , sizeof (Vertex), reinterpret_cast <void *>(offsetof(Vertex, position)) );
CHECK_GL_ERROR();
}
m_nNormalLocation = glGetAttribLocation(m_nProgramObject, "a_normal" );
if (m_nNormalLocation != -1) {
glEnableVertexAttribArray(m_nNormalLocation);
glVertexAttribPointer( m_nNormalLocation, 3, GL_FLOAT, false , sizeof (Vertex), reinterpret_cast <void *>(offsetof(Vertex, normal)) );
CHECK_GL_ERROR();
}
m_nTexCoordLocation = glGetAttribLocation(m_nProgramObject, "a_texCoord" );
if (m_nTexCoordLocation != -1) {
glEnableVertexAttribArray(m_nTexCoordLocation);
glVertexAttribPointer( m_nTexCoordLocation, 2, GL_FLOAT, false , sizeof (Vertex), reinterpret_cast <void *>(offsetof(Vertex, texcoord)) );
CHECK_GL_ERROR();
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
return true ;
}
void OGLTransitionImpl::finish()
{
const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
for (const auto & rSceneObject : rSceneObjects) {
rSceneObject->finish();
}
finishTransition();
CHECK_GL_ERROR();
if ( m_nProgramObject ) {
glDeleteBuffers(1, &m_nVertexBufferObject);
m_nVertexBufferObject = 0;
glDeleteVertexArrays(1, &m_nVertexArrayObject);
m_nVertexArrayObject = 0;
glDeleteProgram( m_nProgramObject );
m_nProgramObject = 0;
}
CHECK_GL_ERROR();
}
void OGLTransitionImpl::prepare( double , double )
{
}
void OGLTransitionImpl::cleanup()
{
}
void OGLTransitionImpl::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
{
}
void OGLTransitionImpl::finishTransition()
{
}
void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
{
CHECK_GL_ERROR();
applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
glUniform1f( m_nTimeLocation, nTime );
glActiveTexture( GL_TEXTURE2 );
glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex );
glActiveTexture( GL_TEXTURE0 );
displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
CHECK_GL_ERROR();
}
void OGLTransitionImpl::display( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
double SlideWidth, double SlideHeight, double DispWidth, double DispHeight, OpenGLContext *pContext )
{
const double SlideWidthScale = SlideWidth/DispWidth;
const double SlideHeightScale = SlideHeight/DispHeight;
CHECK_GL_ERROR();
glBindVertexArray(m_nVertexArrayObject);
prepare( SlideWidth, SlideHeight );
CHECK_GL_ERROR();
displaySlides_( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale, pContext );
CHECK_GL_ERROR();
displayScene( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
CHECK_GL_ERROR();
}
void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale )
{
const Operations_t& rOverallOperations(maScene.getOperations());
glm::mat4 matrix;
for (const auto & rOperation : rOverallOperations)
rOperation->interpolate(matrix, nTime, SlideWidthScale, SlideHeightScale);
CHECK_GL_ERROR();
if (m_nOperationsTransformLocation != -1) {
glUniformMatrix4fv(m_nOperationsTransformLocation, 1, false , glm::value_ptr(matrix));
CHECK_GL_ERROR();
}
}
static void displayPrimitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, std::vector<int >::const_iterator first)
{
for (const Primitive& primitive: primitives)
primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++);
}
void
OGLTransitionImpl::displaySlide(
const double nTime,
const sal_Int32 glSlideTex, const Primitives_t& primitives,
double SlideWidthScale, double SlideHeightScale )
{
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, glSlideTex);
CHECK_GL_ERROR();
if (m_nSceneTransformLocation != -1) {
glUniformMatrix4fv(m_nSceneTransformLocation, 1, false , glm::value_ptr(glm::mat4()));
CHECK_GL_ERROR();
}
displayPrimitives(primitives, m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale, m_nFirstIndices.cbegin());
CHECK_GL_ERROR();
}
void
OGLTransitionImpl::displayUnbufferedSlide(
const double nTime,
const sal_Int32 glSlideTex, const Primitives_t& primitives,
double SlideWidthScale, double SlideHeightScale )
{
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, glSlideTex);
CHECK_GL_ERROR();
glBindVertexArray(0);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
if (m_nSceneTransformLocation != -1) {
glUniformMatrix4fv(m_nSceneTransformLocation, 1, false , glm::value_ptr(glm::mat4()));
CHECK_GL_ERROR();
}
for (const Primitive& primitive: primitives)
primitive.display(m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale);
CHECK_GL_ERROR();
glBindVertexArray(m_nVertexArrayObject);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
CHECK_GL_ERROR();
}
void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight )
{
const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
CHECK_GL_ERROR();
for (const auto & rSceneObject : rSceneObjects)
rSceneObject->display(m_nSceneTransformLocation, m_nPrimitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
CHECK_GL_ERROR();
}
void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale) const
{
glm::mat4 matrix;
applyOperations( matrix, nTime, WidthScale, HeightScale );
CHECK_GL_ERROR();
if (primitiveTransformLocation != -1) {
glUniformMatrix4fv(primitiveTransformLocation, 1, false , glm::value_ptr(matrix));
CHECK_GL_ERROR();
}
GLuint nVertexArrayObject;
glGenVertexArrays(1, &nVertexArrayObject);
CHECK_GL_ERROR();
glBindVertexArray(nVertexArrayObject);
CHECK_GL_ERROR();
GLuint nBuffer;
glGenBuffers(1, &nBuffer);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, nBuffer);
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, getVerticesByteSize(), Vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
CHECK_GL_ERROR();
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), nullptr);
CHECK_GL_ERROR();
glDrawArrays( GL_TRIANGLES, 0, Vertices.size() );
CHECK_GL_ERROR();
glDeleteBuffers(1, &nBuffer);
CHECK_GL_ERROR();
glDeleteVertexArrays(1, &nVertexArrayObject);
CHECK_GL_ERROR();
}
void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const
{
glm::mat4 matrix;
applyOperations( matrix, nTime, WidthScale, HeightScale );
CHECK_GL_ERROR();
if (primitiveTransformLocation != -1) {
glUniformMatrix4fv(primitiveTransformLocation, 1, false , glm::value_ptr(matrix));
CHECK_GL_ERROR();
}
glDrawArrays( GL_TRIANGLES, first, Vertices.size() );
CHECK_GL_ERROR();
}
void Primitive::applyOperations(glm::mat4& matrix, double nTime, double WidthScale, double HeightScale) const
{
for (const auto & rOperation : Operations)
rOperation->interpolate(matrix, nTime, WidthScale, HeightScale);
matrix = glm::scale(matrix, glm::vec3(WidthScale, HeightScale, 1));
}
void SceneObject::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double /* SlideWidth */, double /* SlideHeight */, double DispWidth, double DispHeight ) const
{
// fixme: allow various model spaces, now we make it so that
// it is regular -1,-1 to 1,1, where the whole display fits in
glm::mat4 matrix;
if (DispHeight > DispWidth)
matrix = glm::scale(matrix, glm::vec3(DispHeight/DispWidth, 1, 1));
else
matrix = glm::scale(matrix, glm::vec3(1, DispWidth/DispHeight, 1));
CHECK_GL_ERROR();
if (sceneTransformLocation != -1) {
glUniformMatrix4fv(sceneTransformLocation, 1, false , glm::value_ptr(matrix));
CHECK_GL_ERROR();
}
displayPrimitives(maPrimitives, primitiveTransformLocation, nTime, 1, 1, maFirstIndices.cbegin());
CHECK_GL_ERROR();
}
void SceneObject::pushPrimitive(const Primitive &p)
{
maPrimitives.push_back(p);
}
SceneObject::SceneObject()
: maPrimitives()
{
}
SceneObject::~SceneObject()
{
}
namespace
{
class Iris : public SceneObject
{
public :
Iris() = default ;
virtual void prepare(GLuint program) override;
virtual void display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight) const override;
virtual void finish() override;
private :
GLuint maTexture = 0;
GLuint maBuffer = 0;
GLuint maVertexArray = 0;
};
void Iris::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) const
{
glBindVertexArray(maVertexArray);
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, maTexture);
CHECK_GL_ERROR();
SceneObject::display(sceneTransformLocation, primitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
}
void Iris::prepare(GLuint program)
{
CHECK_GL_ERROR();
static const GLubyte img[3] = { 80, 80, 80 };
glGenTextures(1, &maTexture);
glBindTexture(GL_TEXTURE_2D, maTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
CHECK_GL_ERROR();
glGenVertexArrays(1, &maVertexArray);
glBindVertexArray(maVertexArray);
glGenBuffers(1, &maBuffer);
glBindBuffer(GL_ARRAY_BUFFER, maBuffer);
maFirstIndices = uploadPrimitives(maPrimitives);
// Attribute bindings
GLint location = glGetAttribLocation(program, "a_position" );
if (location != -1) {
glEnableVertexAttribArray(location);
glVertexAttribPointer( location, 3, GL_FLOAT, false , sizeof (Vertex), reinterpret_cast <void *>(offsetof(Vertex, position)) );
CHECK_GL_ERROR();
}
location = glGetAttribLocation(program, "a_normal" );
if (location != -1) {
glEnableVertexAttribArray(location);
glVertexAttribPointer( location, 3, GL_FLOAT, false , sizeof (Vertex), reinterpret_cast <void *>(offsetof(Vertex, normal)) );
CHECK_GL_ERROR();
}
location = glGetAttribLocation(program, "a_texCoord" );
if (location != -1) {
glEnableVertexAttribArray(location);
glVertexAttribPointer( location, 2, GL_FLOAT, false , sizeof (Vertex), reinterpret_cast <void *>(offsetof(Vertex, texcoord)) );
CHECK_GL_ERROR();
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Iris::finish()
{
CHECK_GL_ERROR();
glDeleteBuffers(1, &maBuffer);
CHECK_GL_ERROR();
glDeleteVertexArrays(1, &maVertexArray);
CHECK_GL_ERROR();
glDeleteTextures(1, &maTexture);
CHECK_GL_ERROR();
}
}
namespace
{
class ReflectionTransition : public OGLTransitionImpl
{
public :
ReflectionTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: OGLTransitionImpl(rScene, rSettings)
{}
private :
virtual GLuint makeShader() const override;
virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
virtual void prepareTransition( sal_Int32, sal_Int32, OpenGLContext* ) override {
glDisable(GL_CULL_FACE);
}
virtual void finishTransition() override {
glEnable(GL_CULL_FACE);
}
};
GLuint ReflectionTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( u"reflectionVertexShader" _ustr, u"reflectionFragmentShader" _ustr );
}
void ReflectionTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
{
CHECK_GL_ERROR();
applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
sal_Int32 texture;
Primitives_t slide;
if (nTime < 0.5) {
texture = glLeavingSlideTex;
slide = getScene().getLeavingSlide();
} else {
texture = glEnteringSlideTex;
slide = getScene().getEnteringSlide();
}
displaySlide( nTime, texture, slide, SlideWidthScale, SlideHeightScale );
CHECK_GL_ERROR();
}
std::shared_ptr<OGLTransitionImpl>
makeReflectionTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
Operations_t&& rOverallOperations,
const TransitionSettings& rSettings)
{
return std::make_shared<ReflectionTransition>(
TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives), std::move(rOverallOperations), SceneObjects_t()),
rSettings);
}
}
namespace
{
class SimpleTransition : public OGLTransitionImpl
{
public :
SimpleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: OGLTransitionImpl(rScene, rSettings)
{
}
private :
virtual GLuint makeShader() const override;
virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
};
GLuint SimpleTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( u"basicVertexShader" _ustr, u"basicFragmentShader" _ustr );
}
void SimpleTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
{
CHECK_GL_ERROR();
applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
CHECK_GL_ERROR();
displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
CHECK_GL_ERROR();
}
std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
Operations_t&& rOverallOperations,
SceneObjects_t&& rSceneObjects,
const TransitionSettings& rSettings)
{
return std::make_shared<SimpleTransition>(
TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
std::move(rOverallOperations), std::move(rSceneObjects)),
rSettings);
}
std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
Operations_t&& rOverallOperations,
const TransitionSettings& rSettings = TransitionSettings())
{
return makeSimpleTransition(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
std::move(rOverallOperations), SceneObjects_t(), rSettings);
}
std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
SceneObjects_t&& rSceneObjects,
const TransitionSettings& rSettings)
{
return makeSimpleTransition(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
Operations_t(), std::move(rSceneObjects), rSettings);
}
std::shared_ptr<OGLTransitionImpl>
makeSimpleTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
const TransitionSettings& rSettings = TransitionSettings())
{
return makeSimpleTransition(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives),
Operations_t(), SceneObjects_t(), rSettings);
}
}
std::shared_ptr<OGLTransitionImpl> makeOutsideCubeFaceToLeft()
{
Primitive Slide;
Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
Primitives_t aLeavingPrimitives;
aLeavingPrimitives.push_back(Slide);
Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),90,false ,false ,0.0,1.0));
Primitives_t aEnteringPrimitives;
aEnteringPrimitives.push_back(Slide);
Operations_t aOperations;
aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),-90,false ,true ,0.0,1.0));
return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aOperations));
}
std::shared_ptr<OGLTransitionImpl> makeInsideCubeFaceToLeft()
{
Primitive Slide;
Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
Primitives_t aLeavingPrimitives;
aLeavingPrimitives.push_back(Slide);
Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),-90,false ,false ,0.0,1.0));
Primitives_t aEnteringPrimitives;
aEnteringPrimitives.push_back(Slide);
Operations_t aOperations;
aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),90,false ,true ,0.0,1.0));
return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aOperations));
}
std::shared_ptr<OGLTransitionImpl> makeFallLeaving()
{
Primitive Slide;
Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
Primitives_t aEnteringPrimitives;
aEnteringPrimitives.push_back(Slide);
Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(1,0,0),glm::vec3(0,-1,0), 90,true ,true ,0.0,1.0));
Primitives_t aLeavingPrimitives;
aLeavingPrimitives.push_back(Slide);
TransitionSettings aSettings;
aSettings.mbUseMipMapEntering = false ;
return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), aSettings);
}
std::shared_ptr<OGLTransitionImpl> makeTurnAround()
{
Primitive Slide;
TransitionSettings aSettings;
Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
Primitives_t aLeavingPrimitives;
aLeavingPrimitives.push_back(Slide);
Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false , -1, 0));
aLeavingPrimitives.push_back(Slide);
Slide.Operations.clear();
Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0),-180,true ,false ,0.0,1.0));
Primitives_t aEnteringPrimitives;
aEnteringPrimitives.push_back(Slide);
Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false , -1, 0));
aEnteringPrimitives.push_back(Slide);
Operations_t aOperations;
aOperations.push_back(makeSTranslate(glm::vec3(0, 0, -1.5),true , 0, 0.5));
aOperations.push_back(makeSTranslate(glm::vec3(0, 0, 1.5), true , 0.5, 1));
aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0, 1, 0),glm::vec3(0, 0, 0), -180, true , true , 0.0, 1.0));
return makeReflectionTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aOperations), aSettings);
}
std::shared_ptr<OGLTransitionImpl> makeTurnDown()
{
Primitive Slide;
Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
Primitives_t aLeavingPrimitives;
aLeavingPrimitives.push_back(Slide);
Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 0.0001), false , -1.0, 0.0));
Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), -90, true , 0.0, 1.0));
Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), 90, false , -1.0, 0.0));
Primitives_t aEnteringPrimitives;
aEnteringPrimitives.push_back(Slide);
TransitionSettings aSettings;
aSettings.mbUseMipMapLeaving = false ;
return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), aSettings);
}
std::shared_ptr<OGLTransitionImpl> makeIris()
{
Primitive Slide;
Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
Primitives_t aEnteringPrimitives;
aEnteringPrimitives.push_back (Slide);
Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.000001), false , -1, 0));
Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, -0.000002), false , 0.5, 1));
Primitives_t aLeavingPrimitives;
aLeavingPrimitives.push_back (Slide);
Primitive irisPart;
int i, nSteps = 24, nParts = 7;
double t = 1.0/nSteps, lx = 1, ly = 0, of=2.2, f=1.42;
for (i=1; i<=nSteps; i++) {
double x = cos ((3*2*M_PI*t)/nParts);
double y = -sin ((3*2*M_PI*t)/nParts);
double cx = (f*x + 1)/2;
double cy = (f*y + 1)/2;
double lcx = (f*lx + 1)/2;
double lcy = (f*ly + 1)/2;
double cxo = (of*x + 1)/2;
double cyo = (of*y + 1)/2;
double lcxo = (of*lx + 1)/2;
double lcyo = (of*ly + 1)/2;
irisPart.pushTriangle (glm::vec2 (lcx, lcy),
glm::vec2 (lcxo, lcyo),
glm::vec2 (cx, cy));
irisPart.pushTriangle (glm::vec2 (cx, cy),
glm::vec2 (lcxo, lcyo),
glm::vec2 (cxo, cyo));
lx = x;
ly = y;
t += 1.0/nSteps;
}
std::shared_ptr<Iris> pIris = std::make_shared<Iris>();
double angle = 87;
for (i = 0; i < nParts; i++) {
irisPart.Operations.clear ();
double rx, ry;
rx = cos ((2*M_PI*i)/nParts);
ry = sin ((2*M_PI*i)/nParts);
irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), angle, true , 0.0, 0.5));
irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), -angle, true , 0.5, 1));
if (i > 0) {
irisPart.Operations.push_back (makeSTranslate (glm::vec3(rx, ry, 0), false , -1, 0));
irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), i*360.0/nParts, false , -1, 0));
irisPart.Operations.push_back (makeSTranslate (glm::vec3(-1, 0, 0), false , -1, 0));
}
irisPart.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 1), false , -2, 0.0));
irisPart.Operations.push_back (makeSRotate (glm::vec3(1, .5, 0), glm::vec3(1, 0, 0), -30, false , -1, 0));
pIris->pushPrimitive (irisPart);
}
SceneObjects_t aSceneObjects;
aSceneObjects.push_back (pIris);
TransitionSettings aSettings;
aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false ;
return makeSimpleTransition(std::move(aLeavingPrimitives), std::move(aEnteringPrimitives), std::move(aSceneObjects), aSettings);
}
namespace
{
class RochadeTransition : public ReflectionTransition
{
public :
RochadeTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: ReflectionTransition(rScene, rSettings)
{}
private :
virtual void displaySlides_(double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext) override;
};
void RochadeTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
{
applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
if ( nTime > .5) {
displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
} else {
displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
}
}
std::shared_ptr<OGLTransitionImpl>
makeRochadeTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
const TransitionSettings& rSettings)
{
return std::make_shared<RochadeTransition>(
TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
rSettings)
;
}
}
std::shared_ptr<OGLTransitionImpl> makeRochade()
{
Primitive Slide;
TransitionSettings aSettings;
double w, h;
w = 2.2;
h = 10;
Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1));
Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1));
Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.25, -0.25, true , 0, 1));
Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true , true , 0, 1));
Primitives_t aLeavingSlide;
aLeavingSlide.push_back(Slide);
Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false , -1, 0));
aLeavingSlide.push_back(Slide);
Slide.Operations.clear();
Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.75, 0.25, true , 0, 1));
Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, -h), false , -1, 0));
Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true , true , 0, 1));
Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), 45, true , false , -1, 0));
Primitives_t aEnteringSlide;
aEnteringSlide.push_back(Slide);
Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false , -1, 0));
aEnteringSlide.push_back(Slide);
return makeRochadeTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
}
static double randFromNeg1to1()
{
return comphelper::rng::uniform_real_distribution(-1.0, std::nextafter(1.0, DBL_MAX));
}
// TODO(Q3): extract to basegfx
static glm::vec3 randNormVectorInXYPlane()
{
glm::vec3 toReturn(randFromNeg1to1(),randFromNeg1to1(),0.0);
return glm::normalize(toReturn);
}
template <typename T>
static T clamp(const T& rIn)
{
return glm::clamp(rIn, T(-1.0), T(1.0));
}
std::shared_ptr<OGLTransitionImpl> makeRevolvingCircles( sal_uInt16 nCircles , sal_uInt16 nPointsOnCircles )
{
double dAngle(2*M_PI/static_cast <double >( nPointsOnCircles ));
if (nCircles < 2 || nPointsOnCircles < 4)
return makeNByMTileFlip(1,1);
float Radius(1.0/static_cast <double >( nCircles ));
float dRadius(Radius);
float LastRadius(0.0);
float NextRadius(2*Radius);
/// now we know there is at least two circles
/// the first will always be a full circle
/// the last will always be the outer shell of the slide with a circle hole
//add the full circle
std::vector<glm::vec2> unScaledTexCoords;
float TempAngle(0.0);
for (unsigned int Point(0); Point < nPointsOnCircles; ++Point)
{
unScaledTexCoords.emplace_back( cos(TempAngle - M_PI_2) , sin(TempAngle- M_PI_2) );
TempAngle += dAngle;
}
Primitives_t aLeavingSlide;
Primitives_t aEnteringSlide;
{
Primitive EnteringSlide;
Primitive LeavingSlide;
for (int Point(0); Point + 1 < nPointsOnCircles; ++Point)
{
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 ) );
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) );
}
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 ) );
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) );
glm::vec3 axis(randNormVectorInXYPlane());
EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true , Radius/2.0 , (NextRadius + 1)/2.0 ) );
LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true , Radius/2.0 , (NextRadius + 1)/2.0 ) );
EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false ,0.0,1.0) );
aEnteringSlide.push_back(EnteringSlide);
aLeavingSlide.push_back(LeavingSlide);
LastRadius = Radius;
Radius = NextRadius;
NextRadius += dRadius;
}
for (int i(1); i < nCircles - 1; ++i)
{
Primitive LeavingSlide;
Primitive EnteringSlide;
for (int Side(0); Side < nPointsOnCircles - 1; ++Side)
{
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) );
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) );
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) );
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) );
}
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) );
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) );
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) );
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) );
glm::vec3 axis(randNormVectorInXYPlane());
EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true , Radius/2.0 , (NextRadius + 1)/2.0 ) );
LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true , Radius/2.0 , (NextRadius + 1)/2.0 ) );
EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false ,0.0,1.0) );
aEnteringSlide.push_back(EnteringSlide);
aLeavingSlide.push_back(LeavingSlide);
LastRadius = Radius;
Radius = NextRadius;
NextRadius += dRadius;
}
{
Radius = sqrt(2.0);
Primitive LeavingSlide;
Primitive EnteringSlide;
for (int Side(0); Side < nPointsOnCircles - 1; ++Side)
{
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) );
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) );
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) );
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) );
}
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) );
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) );
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) );
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) );
glm::vec3 axis(randNormVectorInXYPlane());
EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true , (LastRadius + dRadius)/2.0 , 1.0 ) );
LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true , (LastRadius + dRadius)/2.0 , 1.0 ) );
EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false ,0.0,1.0) );
aEnteringSlide.push_back(EnteringSlide);
aLeavingSlide.push_back(LeavingSlide);
}
return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
}
std::shared_ptr<OGLTransitionImpl> makeHelix( sal_uInt16 nRows )
{
double invN(1.0/static_cast <double >(nRows));
double iDn = 0.0;
double iPDn = invN;
Primitives_t aLeavingSlide;
Primitives_t aEnteringSlide;
for (unsigned int i(0); i < nRows; ++i)
{
Primitive Tile;
Tile.pushTriangle(glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iDn ) , glm::vec2( 0.0 , iPDn ));
Tile.pushTriangle(glm::vec2( 1.0 , iPDn ) , glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iPDn ));
Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , 180 ,
true , std::min(std::max(static_cast <double >(i - nRows/2.0)*invN/2.0,0.0),1.0),
std::min(std::max(static_cast <double >(i + nRows/2.0)*invN/2.0,0.0),1.0) ) );
aLeavingSlide.push_back(Tile);
Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , -180 , false ,0.0,1.0) );
aEnteringSlide.push_back(Tile);
iDn += invN;
iPDn += invN;
}
return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
}
static float fdiv(int a, int b)
{
return static_cast <float >(a)/b;
}
static glm::vec2 vec(float x, float y, float nx, float ny)
{
x = x < 0.0 ? 0.0 : x;
x = std::min(x, nx);
y = y < 0.0 ? 0.0 : y;
y = std::min(y, ny);
return glm::vec2(fdiv(x, nx), fdiv(y, ny));
}
std::shared_ptr<OGLTransitionImpl> makeNByMTileFlip( sal_uInt16 n, sal_uInt16 m )
{
Primitives_t aLeavingSlide;
Primitives_t aEnteringSlide;
for (int x = 0; x < n; x++)
{
for (int y = 0; y < n; y++)
{
Primitive aTile;
glm::vec2 x11 = vec(x, y, n, m);
glm::vec2 x12 = vec(x, y+1, n, m);
glm::vec2 x21 = vec(x+1, y, n, m);
glm::vec2 x22 = vec(x+1, y+1, n, m);
aTile.pushTriangle(x21, x11, x12);
aTile.pushTriangle(x22, x21, x12);
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));
aLeavingSlide.push_back(aTile);
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));
aEnteringSlide.push_back(aTile);
}
}
return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
}
Primitive& Primitive::operator =(const Primitive& rvalue)
{
Primitive aTmp(rvalue);
swap(aTmp);
return *this ;
}
Primitive::Primitive(const Primitive& rvalue)
: Operations(rvalue.Operations)
, Vertices(rvalue.Vertices)
{
}
void Primitive::swap(Primitive& rOther)
{
using std::swap;
swap(Operations, rOther.Operations);
swap(Vertices, rOther.Vertices);
}
void Primitive::pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2)
{
std::vector<glm::vec3> Verts;
std::vector<glm::vec2> Texs;
Verts.reserve(3);
Texs.reserve(3);
Verts.emplace_back( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 );
Verts.emplace_back( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 );
Verts.emplace_back( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 );
//figure out if they're facing the correct way, and make them face the correct way.
glm::vec3 Normal( glm::cross( Verts[0] - Verts[1] , Verts[1] - Verts[2] ) );
if (Normal.z >= 0.0)//if the normal is facing us
{
Texs.push_back(SlideLocation0);
Texs.push_back(SlideLocation1);
Texs.push_back(SlideLocation2);
}
else // if the normal is facing away from us, make it face us
{
Texs.push_back(SlideLocation0);
Texs.push_back(SlideLocation2);
Texs.push_back(SlideLocation1);
Verts.clear();
Verts.emplace_back( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 );
Verts.emplace_back( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 );
Verts.emplace_back( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 );
}
Vertices.push_back({Verts[0], glm::vec3(0, 0, 1), Texs[0]}); //all normals always face the screen when untransformed.
Vertices.push_back({Verts[1], glm::vec3(0, 0, 1), Texs[1]}); //all normals always face the screen when untransformed.
Vertices.push_back({Verts[2], glm::vec3(0, 0, 1), Texs[2]}); //all normals always face the screen when untransformed.
}
namespace
{
class DiamondTransition : public SimpleTransition
{
public :
DiamondTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: SimpleTransition(rScene, rSettings)
{}
private :
virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
};
Primitives_t makeLeavingSlide(double nTime)
{
Primitive Slide2;
if ( nTime >= 0.5 ) {
double m = 1 - nTime;
Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (m,0), glm::vec2 (0,m));
Slide2.pushTriangle (glm::vec2 (nTime,0), glm::vec2 (1,0), glm::vec2 (1,m));
Slide2.pushTriangle (glm::vec2 (1,nTime), glm::vec2 (1,1), glm::vec2 (nTime,1));
Slide2.pushTriangle (glm::vec2 (0,nTime), glm::vec2 (m,1), glm::vec2 (0,1));
} else {
double l = 0.5 - nTime;
double h = 0.5 + nTime;
Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0.5,l));
Slide2.pushTriangle (glm::vec2 (0.5,l), glm::vec2 (1,0), glm::vec2 (h,0.5));
Slide2.pushTriangle (glm::vec2 (1,0), glm::vec2 (1,1), glm::vec2 (h,0.5));
Slide2.pushTriangle (glm::vec2 (h,0.5), glm::vec2 (1,1), glm::vec2 (0.5,h));
Slide2.pushTriangle (glm::vec2 (0.5,h), glm::vec2 (1,1), glm::vec2 (0,1));
Slide2.pushTriangle (glm::vec2 (l,0.5), glm::vec2 (0.5,h), glm::vec2 (0,1));
Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (l,0.5), glm::vec2 (0,1));
Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (0.5,l), glm::vec2 (l,0.5));
}
Slide2.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.00000001), false , -1, 0));
Primitives_t aLeavingSlidePrimitives;
aLeavingSlidePrimitives.push_back (Slide2);
return aLeavingSlidePrimitives;
}
void DiamondTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
double SlideWidthScale, double SlideHeightScale, OpenGLContext * )
{
CHECK_GL_ERROR();
applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
CHECK_GL_ERROR();
displayUnbufferedSlide( nTime, glLeavingSlideTex, makeLeavingSlide(nTime), SlideWidthScale, SlideHeightScale );
displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
CHECK_GL_ERROR();
}
std::shared_ptr<OGLTransitionImpl>
makeDiamondTransition(const TransitionSettings& rSettings)
{
Primitive Slide1;
Slide1.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
Slide1.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
Primitives_t aEnteringSlidePrimitives;
aEnteringSlidePrimitives.push_back (Slide1);
Primitives_t aLeavingSlidePrimitives;
aLeavingSlidePrimitives.push_back (Slide1);
return std::make_shared<DiamondTransition>(TransitionScene(std::move(aLeavingSlidePrimitives), std::move(aEnteringSlidePrimitives)), rSettings);
}
}
std::shared_ptr<OGLTransitionImpl> makeDiamond()
{
TransitionSettings aSettings;
aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false ;
return makeDiamondTransition(aSettings);
}
std::shared_ptr<OGLTransitionImpl> makeVenetianBlinds( bool vertical, int parts )
{
static double t30 = tan( M_PI/6.0 );
double ln = 0;
double p = 1.0/parts;
Primitives_t aLeavingSlide;
Primitives_t aEnteringSlide;
for ( int i=0; i<parts; i++ ) {
Primitive Slide;
double n = (i + 1)/static_cast <double >(parts);
if ( vertical ) {
Slide.pushTriangle (glm::vec2 (ln,0), glm::vec2 (n,0), glm::vec2 (ln,1));
Slide.pushTriangle (glm::vec2 (n,0), glm::vec2 (ln,1), glm::vec2 (n,1));
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));
} else {
Slide.pushTriangle (glm::vec2 (0,ln), glm::vec2 (1,ln), glm::vec2 (0,n));
Slide.pushTriangle (glm::vec2 (1,ln), glm::vec2 (0,n), glm::vec2 (1,n));
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));
}
aLeavingSlide.push_back (Slide);
if ( vertical ) {
Slide.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), glm::vec3(2*n - 1, 0, 0), -60, false , -1, 0));
Slide.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), glm::vec3(n + ln - 1, 0, 0), 180, false , -1, 0));
} else {
Slide.Operations.push_back(makeSRotate(glm::vec3(1, 0, 0), glm::vec3(0, 1 - 2*n, 0), -60, false , -1, 0));
Slide.Operations.push_back(makeSRotate(glm::vec3(1, 0, 0), glm::vec3(0, 1 - n - ln, 0), 180, false , -1, 0));
}
aEnteringSlide.push_back (Slide);
ln = n;
}
return makeSimpleTransition(std::move(aLeavingSlide), std::move(aEnteringSlide));
}
namespace
{
class FadeSmoothlyTransition : public OGLTransitionImpl
{
public :
FadeSmoothlyTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: OGLTransitionImpl(rScene, rSettings)
{}
private :
virtual GLuint makeShader() const override;
};
GLuint FadeSmoothlyTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( u"basicVertexShader" _ustr, u"fadeFragmentShader" _ustr );
}
std::shared_ptr<OGLTransitionImpl>
makeFadeSmoothlyTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
const TransitionSettings& rSettings)
{
return std::make_shared<FadeSmoothlyTransition>(
TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
rSettings)
;
}
}
std::shared_ptr<OGLTransitionImpl> makeFadeSmoothly()
{
Primitive Slide;
Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
Primitives_t aLeavingSlide;
aLeavingSlide.push_back (Slide);
Primitives_t aEnteringSlide;
aEnteringSlide.push_back (Slide);
TransitionSettings aSettings;
aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false ;
return makeFadeSmoothlyTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
}
namespace
{
class FadeThroughColorTransition : public OGLTransitionImpl
{
public :
FadeThroughColorTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, bool white)
: OGLTransitionImpl(rScene, rSettings), useWhite( white )
{}
private :
virtual GLuint makeShader() const override;
bool useWhite;
};
GLuint FadeThroughColorTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( u"basicVertexShader" _ustr, u"fadeBlackFragmentShader" _ustr,
useWhite ? "#define use_white" : "" , "" );
}
std::shared_ptr<OGLTransitionImpl>
makeFadeThroughColorTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
const TransitionSettings& rSettings,
bool white)
{
return std::make_shared<FadeThroughColorTransition>(
TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
rSettings, white)
;
}
}
std::shared_ptr<OGLTransitionImpl> makeFadeThroughColor( bool white )
{
Primitive Slide;
Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
Primitives_t aLeavingSlide;
aLeavingSlide.push_back (Slide);
Primitives_t aEnteringSlide;
aEnteringSlide.push_back (Slide);
TransitionSettings aSettings;
aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false ;
return makeFadeThroughColorTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings, white);
}
namespace
{
class PermTextureTransition : public OGLTransitionImpl
{
protected :
PermTextureTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: OGLTransitionImpl(rScene, rSettings)
, m_nHelperTexture(0)
{}
virtual void finishTransition() override;
virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
private :
/** various data */
GLuint m_nHelperTexture;
};
void PermTextureTransition::finishTransition()
{
CHECK_GL_ERROR();
if ( m_nHelperTexture )
{
glDeleteTextures( 1, &m_nHelperTexture );
m_nHelperTexture = 0;
}
CHECK_GL_ERROR();
}
constexpr auto permutation2D = []() constexpr {
int permutation256 [256]= {
215, 100, 200, 204, 233, 50, 85, 196,
71, 141, 122, 160, 93, 131, 243, 234,
162, 183, 36, 155, 4, 62, 35, 205,
40, 102, 33, 27, 255, 55, 214, 156,
75, 163, 134, 126, 249, 74, 197, 228,
72, 90, 206, 235, 17, 22, 49, 169,
227, 89, 16, 5, 117, 60, 248, 230,
217, 68, 138, 96, 194, 170, 136, 10,
112, 238, 184, 189, 176, 42, 225, 212,
84, 58, 175, 244, 150, 168, 219, 236,
101, 208, 123, 37, 164, 110, 158, 201,
78, 114, 57, 48, 70, 142, 106, 43,
232, 26, 32, 252, 239, 98, 191, 94,
59, 149, 39, 187, 203, 190, 19, 13,
133, 45, 61, 247, 23, 34, 20, 52,
118, 209, 146, 193, 222, 18, 1, 152,
46, 41, 91, 148, 115, 25, 135, 77,
254, 147, 224, 161, 9, 213, 223, 250,
231, 251, 127, 166, 63, 179, 81, 130,
139, 28, 120, 151, 241, 86, 111, 0,
88, 153, 172, 182, 159, 105, 178, 47,
51, 167, 65, 66, 92, 73, 198, 211,
245, 195, 31, 220, 140, 76, 221, 186,
154, 185, 56, 83, 38, 165, 109, 67,
124, 226, 132, 53, 229, 29, 12, 181,
121, 24, 207, 199, 177, 113, 30, 80,
3, 97, 188, 79, 216, 173, 8, 145,
87, 128, 180, 237, 240, 137, 125, 104,
15, 242, 119, 246, 103, 143, 95, 144,
2, 44, 69, 157, 192, 174, 14, 54,
218, 82, 64, 210, 11, 6, 129, 21,
116, 171, 99, 202, 7, 107, 253, 108
};
std::array<unsigned char , 256 * 256> a{};
for (int y = 0; y < 256; y++)
for (int x = 0; x < 256; x++)
a[x + y * 256] = permutation256[(y + permutation256[x]) & 0xff];
return a;
}();
void initPermTexture(GLuint *texID)
{
CHECK_GL_ERROR();
glGenTextures(1, texID);
glBindTexture(GL_TEXTURE_2D, *texID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RED, GL_UNSIGNED_BYTE,
permutation2D.data());
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
CHECK_GL_ERROR();
}
void PermTextureTransition::prepareTransition( sal_Int32, sal_Int32, OpenGLContext* )
{
CHECK_GL_ERROR();
GLint location = glGetUniformLocation( m_nProgramObject, "permTexture" );
if ( location != -1 ) {
glActiveTexture(GL_TEXTURE1);
CHECK_GL_ERROR();
if ( !m_nHelperTexture )
initPermTexture( &m_nHelperTexture );
glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR();
glUniform1i( location, 1 ); // texture unit 1
CHECK_GL_ERROR();
}
CHECK_GL_ERROR();
}
}
namespace
{
class StaticNoiseTransition : public PermTextureTransition
{
public :
StaticNoiseTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: PermTextureTransition(rScene, rSettings)
{}
private :
virtual GLuint makeShader() const override;
};
GLuint StaticNoiseTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( u"basicVertexShader" _ustr, u"staticFragmentShader" _ustr );
}
std::shared_ptr<OGLTransitionImpl>
makeStaticNoiseTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
const TransitionSettings& rSettings)
{
return std::make_shared<StaticNoiseTransition>(
TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
rSettings)
;
}
}
std::shared_ptr<OGLTransitionImpl> makeStatic()
{
Primitive Slide;
Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
Primitives_t aLeavingSlide;
aLeavingSlide.push_back (Slide);
Primitives_t aEnteringSlide;
aEnteringSlide.push_back (Slide);
TransitionSettings aSettings;
aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false ;
return makeStaticNoiseTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
}
namespace
{
class DissolveTransition : public PermTextureTransition
{
public :
DissolveTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
: PermTextureTransition(rScene, rSettings)
{}
private :
virtual GLuint makeShader() const override;
};
GLuint DissolveTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( u"basicVertexShader" _ustr, u"dissolveFragmentShader" _ustr );
}
std::shared_ptr<OGLTransitionImpl>
makeDissolveTransition(
Primitives_t&& rLeavingSlidePrimitives,
Primitives_t&& rEnteringSlidePrimitives,
const TransitionSettings& rSettings)
{
return std::make_shared<DissolveTransition>(
TransitionScene(std::move(rLeavingSlidePrimitives), std::move(rEnteringSlidePrimitives)),
rSettings)
;
}
}
std::shared_ptr<OGLTransitionImpl> makeDissolve()
{
Primitive Slide;
Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1));
Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1));
Primitives_t aLeavingSlide;
aLeavingSlide.push_back (Slide);
Primitives_t aEnteringSlide;
aEnteringSlide.push_back (Slide);
TransitionSettings aSettings;
aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false ;
return makeDissolveTransition(std::move(aLeavingSlide), std::move(aEnteringSlide), aSettings);
}
namespace
{
class VortexTransition : public PermTextureTransition
{
public :
VortexTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, int nNX, int nNY)
: PermTextureTransition(rScene, rSettings)
, maNumTiles(nNX,nNY)
{
mvTileInfo.resize(6*maNumTiles.x*maNumTiles.y);
mnFramebuffers[0] = 0;
mnFramebuffers[1] = 0;
mnDepthTextures[0] = 0;
mnDepthTextures[1] = 0;
}
private :
virtual void finishTransition() override;
virtual GLuint makeShader() const override;
virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext ) override;
virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale, OpenGLContext *pContext ) override;
GLint mnSlideLocation = -1;
GLint mnTileInfoLocation = -1;
GLuint mnTileInfoBuffer = 0u;
GLint mnShadowLocation = -1;
std::array<GLuint, 2> mnFramebuffers;
std::array<GLuint, 2> mnDepthTextures;
glm::ivec2 maNumTiles;
std::vector<GLfloat> mvTileInfo;
};
void VortexTransition::finishTransition()
{
PermTextureTransition::finishTransition();
CHECK_GL_ERROR();
glDeleteTextures(2, mnDepthTextures.data());
mnDepthTextures = {0u, 0u};
CHECK_GL_ERROR();
glDeleteFramebuffers(2, mnFramebuffers.data());
mnFramebuffers = {0u, 0u};
glDeleteBuffers(1, &mnTileInfoBuffer);
mnTileInfoBuffer = 0u;
mnSlideLocation = -1;
mnTileInfoLocation = -1;
mnShadowLocation = -1;
CHECK_GL_ERROR();
}
GLuint VortexTransition::makeShader() const
{
return OpenGLHelper::LoadShaders( u"vortexVertexShader" _ustr, u"vortexFragmentShader" _ustr, u"vortexGeometryShader" _ustr );
}
glm::mat4 lookAt(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up) {
glm::vec3 f = glm::normalize(center - eye);
glm::vec3 u = glm::normalize(up);
glm::vec3 s = glm::normalize(glm::cross(f, u));
u = glm::cross(s, f);
return glm::mat4(s.x, u.x, -f.x, 0,
s.y, u.y, -f.y, 0,
s.z, u.z, -f.z, 0,
-glm::dot(s, eye), -glm::dot(u, eye), glm::dot(f, eye), 1);
}
void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, OpenGLContext *pContext )
{
CHECK_GL_ERROR();
PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex, pContext );
CHECK_GL_ERROR();
mnSlideLocation = glGetUniformLocation(m_nProgramObject, "slide" );
mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo" );
GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles" );
mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow" );
GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix" );
GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix" );
GLint location = glGetUniformLocation(m_nProgramObject, "leavingShadowTexture" );
glUniform1i(location, 2);
location = glGetUniformLocation(m_nProgramObject, "enteringShadowTexture" );
glUniform1i(location, 3);
CHECK_GL_ERROR();
glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles));
CHECK_GL_ERROR();
glGenBuffers(1, &mnTileInfoBuffer);
CHECK_GL_ERROR();
// We store the (x,y) indexes of the tile each vertex belongs to in a float, so they must fit.
assert(maNumTiles.x < 256);
assert(maNumTiles.y < 256);
// Two triangles, i.e. six vertices, per tile
{
int n = 0;
for (int x = 0; x < maNumTiles.x; x++)
{
for (int y = 0; y < maNumTiles.y; y++)
{
for (int v = 0; v < 6; v++)
{
mvTileInfo[n] = x + (y << 8) + (v << 16);
n++;
}
}
}
}
glBindBuffer(GL_ARRAY_BUFFER, mnTileInfoBuffer);
CHECK_GL_ERROR();
glEnableVertexAttribArray(mnTileInfoLocation);
CHECK_GL_ERROR();
glVertexAttribPointer(mnTileInfoLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, mvTileInfo.size()*sizeof (GLfloat), mvTileInfo.data(), GL_STATIC_DRAW);
CHECK_GL_ERROR();
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=98 H=93 G=95
¤ Dauer der Verarbeitung: 0.35 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland