summaryrefslogtreecommitdiffstats
path: root/demos/qt3d/photobrowser3d/qfocusadaptor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'demos/qt3d/photobrowser3d/qfocusadaptor.cpp')
-rw-r--r--demos/qt3d/photobrowser3d/qfocusadaptor.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/demos/qt3d/photobrowser3d/qfocusadaptor.cpp b/demos/qt3d/photobrowser3d/qfocusadaptor.cpp
new file mode 100644
index 000000000..cf96f3a01
--- /dev/null
+++ b/demos/qt3d/photobrowser3d/qfocusadaptor.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtQuick3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfocusadaptor.h"
+#include "qglscenenode.h"
+#include "qglview.h"
+#include "qglcamera.h"
+#include "thumbnailnode.h"
+
+class QFocusAdaptorPrivate
+{
+public:
+ QFocusAdaptorPrivate()
+ : progress(0.0)
+ , reset(true)
+ , target(0)
+ , view(0)
+ {}
+ qreal progress;
+ QVector3D targetEye;
+ QVector3D targetCenter;
+ QVector3D sourceEye;
+ QVector3D sourceCenter;
+ bool reset;
+ QGLSceneNode *target;
+ QGLView *view;
+};
+
+QFocusAdaptor::QFocusAdaptor(QObject *parent)
+ : QObject(parent)
+ , d(new QFocusAdaptorPrivate)
+{
+ QGLView *v = qobject_cast<QGLView*>(parent);
+ if (v)
+ d->view = v;
+}
+
+QFocusAdaptor::~QFocusAdaptor()
+{
+ delete d;
+}
+
+qreal QFocusAdaptor::progress() const
+{
+ return d->progress;
+}
+
+void QFocusAdaptor::setProgress(qreal progress)
+{
+ if (d->progress != progress)
+ {
+ d->progress = progress;
+ calculateValues();
+ emit progressChanged();
+ }
+}
+
+QGLView *QFocusAdaptor::view() const
+{
+ return d->view;
+}
+
+void QFocusAdaptor::setView(QGLView *view)
+{
+ d->view = view;
+ d->reset = true;
+}
+
+QGLSceneNode *QFocusAdaptor::target() const
+{
+ return d->target;
+}
+
+void QFocusAdaptor::setTarget(QGLSceneNode *target)
+{
+ if (d->target != target)
+ {
+ d->target = target;
+ d->reset = true;
+ }
+}
+
+void QFocusAdaptor::calculateValues()
+{
+ if (d->target && d->view)
+ {
+ QGLCamera *cam = d->view->camera();
+ Q_ASSERT(cam);
+ if (d->reset)
+ {
+ QGeometryData data = d->target->geometry();
+ if (data.count() == 0 || d->target->count() == 0)
+ {
+ qWarning("Could not setup focus animation");
+ return;
+ }
+ // assume that the first triangle referenced by this node is the one
+ // you want to focus on - works for simple rects and like cases
+ QGL::IndexArray ixs = data.indices();
+ QVector3D a = data.vertexAt(ixs.at(d->target->start()));
+ QVector3D b = data.vertexAt(ixs.at(d->target->start() + 1));
+ QVector3D c = data.vertexAt(ixs.at(d->target->start() + 2));
+
+ // assumes that first triangle is facing the camera
+ QVector3D toCam = QVector3D::normal(a, b, c);
+
+ // wont work very well if the target is not axis-aligned
+ // find the distance q for the eye to be away from this object
+ // in order that it is a tight fit in the viewport
+ QGeometryData g = d->target->geometry();
+ QGL::IndexArray inxs = g.indices();
+ QBox3D box;
+ for (int i = d->target->start(); i < (d->target->start() + d->target->count()); ++i)
+ box.unite(g.vertexAt(inxs.at(i)));
+ QVector3D sz = box.size();
+
+ qreal nearDist = cam->nearPlane();
+
+ QSizeF v = cam->viewSize();
+
+ qreal vh = d->view->rect().height();
+ qreal vw = d->view->rect().width();
+ if (!qFuzzyIsNull(vw - vh))
+ {
+ qreal asp = vh / vw;
+ if (vh > vw)
+ v.setHeight(v.height() * asp);
+ else
+ v.setWidth(v.width() / asp);
+ }
+
+ qreal qh = (nearDist * sz.y()) / v.height();
+ qreal qw = (nearDist * sz.x()) / v.width();
+
+ qreal q = qMax(qh, qw);
+
+ d->sourceCenter = cam->center();
+ d->sourceEye = cam->eye();
+
+ d->targetCenter = d->target->position();
+ d->targetEye = d->targetCenter + (toCam * q);
+
+ d->reset = false;
+ }
+ cam->setCenter(d->sourceCenter + ((d->targetCenter - d->sourceCenter) * d->progress));
+ cam->setEye(d->sourceEye + ((d->targetEye - d->sourceEye) * d->progress));
+ }
+}