summaryrefslogtreecommitdiffstats
path: root/src/datavis3d/engine/q3dcamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavis3d/engine/q3dcamera.cpp')
-rw-r--r--src/datavis3d/engine/q3dcamera.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/datavis3d/engine/q3dcamera.cpp b/src/datavis3d/engine/q3dcamera.cpp
new file mode 100644
index 00000000..480af9b6
--- /dev/null
+++ b/src/datavis3d/engine/q3dcamera.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVis3D module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "q3dcamera.h"
+#include "q3dcamera_p.h"
+#include "q3dscene.h"
+#include "q3dbox.h"
+#include "q3dobject.h"
+
+#include <qmath.h>
+#include <QVector3D>
+
+QT_DATAVIS3D_BEGIN_NAMESPACE
+
+Q3DCamera::Q3DCamera(QObject *parent) :
+ Q3DObject(parent),
+ d_ptr(new Q3DCameraPrivate(this))
+{
+}
+
+Q3DCamera::~Q3DCamera()
+{
+}
+
+void Q3DCamera::copyValuesFrom(const Q3DCamera &source)
+{
+ Q3DObject::copyValuesFrom(source);
+
+ d_ptr->m_target.setX(source.d_ptr->m_target.x());
+ d_ptr->m_target.setY(source.d_ptr->m_target.y());
+ d_ptr->m_target.setZ(source.d_ptr->m_target.z());
+
+ d_ptr->m_up.setX(source.d_ptr->m_up.x());
+ d_ptr->m_up.setY(source.d_ptr->m_up.y());
+ d_ptr->m_up.setZ(source.d_ptr->m_up.z());
+
+ float *values = new float[16];
+ source.d_ptr->m_viewMatrix.copyDataTo(values);
+ d_ptr->m_viewMatrix = QMatrix4x4(values);
+ delete values;
+
+ d_ptr->m_xRotation = source.d_ptr->m_xRotation;
+ d_ptr->m_yRotation = source.d_ptr->m_yRotation;
+
+ d_ptr->m_zoomLevel = source.d_ptr->m_zoomLevel;
+ d_ptr->m_activePreset = source.d_ptr->m_activePreset;
+}
+
+void Q3DCamera::setRotations(const QPointF &rotation)
+{
+ setRotationsPrivate(rotation);
+ d_ptr->m_activePreset = QDataVis::NoPreset;
+}
+
+void Q3DCamera::setDefaultOrientation(const QVector3D &defaultPosition,
+ const QVector3D &defaultTarget,
+ const QVector3D &defaultUp)
+{
+ Q3DObject::setPosition(defaultPosition);
+ d_ptr->m_target = defaultTarget;
+ d_ptr->m_up = defaultUp;
+}
+
+QPointF Q3DCamera::rotations() const
+{
+ QPointF rotations(d_ptr->m_xRotation, d_ptr->m_yRotation);
+ return rotations;
+}
+
+void Q3DCamera::setViewMatrix(const QMatrix4x4 &viewMatrix)
+{
+ d_ptr->m_viewMatrix = viewMatrix;
+}
+
+QMatrix4x4 Q3DCamera::viewMatrix() const
+{
+ return d_ptr->m_viewMatrix;
+}
+
+void Q3DCamera::updateViewMatrix(GLfloat zoomAdjustment)
+{
+ bool showUnder = parentScene()->isUnderSideCameraEnabled();
+ int zoom = zoomLevel() * zoomAdjustment;
+ QMatrix4x4 viewMatrix;
+ GLfloat lowerLimit = 0.0f;
+ if (showUnder)
+ lowerLimit = -90.0f;
+
+ // Reset at 360 in x and limit to 0...90 in y
+ if (qAbs(d_ptr->m_xRotation) >= 360.0f)
+ d_ptr->m_xRotation = 0.0f;
+ if (d_ptr->m_yRotation >= 90.0f)
+ d_ptr->m_yRotation = 90.0f;
+ else if (d_ptr->m_yRotation <= lowerLimit)
+ d_ptr->m_yRotation = lowerLimit;
+
+ // Apply to view matrix
+ viewMatrix.lookAt(position(), d_ptr->m_target, d_ptr->m_up);
+ // Compensate for translation (if d_ptr->m_target is off origin)
+ viewMatrix.translate(d_ptr->m_target.x(), d_ptr->m_target.y(), d_ptr->m_target.z());
+ // Apply rotations
+ // Handle x and z rotation when y -angle is other than 0
+ viewMatrix.rotate(d_ptr->m_xRotation, 0, qCos(qDegreesToRadians(d_ptr->m_yRotation)),
+ qSin(qDegreesToRadians(d_ptr->m_yRotation)));
+ // y rotation is always "clean"
+ viewMatrix.rotate(d_ptr->m_yRotation, 1.0f, 0.0f, 0.0f);
+ // handle zoom by scaling
+ viewMatrix.scale((GLfloat)zoom / 100.0f);
+ // Compensate for translation (if d_ptr->m_target is off origin)
+ viewMatrix.translate(-d_ptr->m_target.x(), -d_ptr->m_target.y(), -d_ptr->m_target.z());
+
+ setViewMatrix(viewMatrix);
+}
+
+QDataVis::CameraPreset Q3DCamera::cameraPreset()
+{
+ return d_ptr->m_activePreset;
+}
+
+void Q3DCamera::setCameraPreset(QDataVis::CameraPreset preset)
+{
+ switch (preset) {
+ case QDataVis::PresetFrontLow: {
+ Q3DCamera::setRotationsPrivate(QPointF(0.0f, 0.0f));
+ break;
+ }
+ case QDataVis::PresetFront: {
+ Q3DCamera::setRotationsPrivate(QPointF(0.0f, 22.5f));
+ break;
+ }
+ case QDataVis::PresetFrontHigh: {
+ Q3DCamera::setRotationsPrivate(QPointF(0.0f, 45.0f));
+ break;
+ }
+ case QDataVis::PresetLeftLow: {
+ Q3DCamera::setRotationsPrivate(QPointF(90.0f, 0.0f));
+ break;
+ }
+ case QDataVis::PresetLeft: {
+ Q3DCamera::setRotationsPrivate(QPointF(90.0f, 22.5f));
+ break;
+ }
+ case QDataVis::PresetLeftHigh: {
+ Q3DCamera::setRotationsPrivate(QPointF(90.0f, 45.0f));
+ break;
+ }
+ case QDataVis::PresetRightLow: {
+ Q3DCamera::setRotationsPrivate(QPointF(-90.0f, 0.0f));
+ break;
+ }
+ case QDataVis::PresetRight: {
+ Q3DCamera::setRotationsPrivate(QPointF(-90.0f, 22.5f));
+ break;
+ }
+ case QDataVis::PresetRightHigh: {
+ Q3DCamera::setRotationsPrivate(QPointF(-90.0f, 45.0f));
+ break;
+ }
+ case QDataVis::PresetBehindLow: {
+ Q3DCamera::setRotationsPrivate(QPointF(180.0f, 0.0f));
+ break;
+ }
+ case QDataVis::PresetBehind: {
+ Q3DCamera::setRotationsPrivate(QPointF(180.0f, 22.5f));
+ break;
+ }
+ case QDataVis::PresetBehindHigh: {
+ Q3DCamera::setRotationsPrivate(QPointF(180.0f, 45.0f));
+ break;
+ }
+ case QDataVis::PresetIsometricLeft: {
+ Q3DCamera::setRotationsPrivate(QPointF(45.0f, 22.5f));
+ break;
+ }
+ case QDataVis::PresetIsometricLeftHigh: {
+ Q3DCamera::setRotationsPrivate(QPointF(45.0f, 45.0f));
+ break;
+ }
+ case QDataVis::PresetIsometricRight: {
+ Q3DCamera::setRotationsPrivate(QPointF(-45.0f, 22.5f));
+ break;
+ }
+ case QDataVis::PresetIsometricRightHigh: {
+ Q3DCamera::setRotationsPrivate(QPointF(-45.0f, 45.0f));
+ break;
+ }
+ case QDataVis::PresetDirectlyAbove: {
+ Q3DCamera::setRotationsPrivate(QPointF(0.0f, 90.0f));
+ break;
+ }
+ case QDataVis::PresetDirectlyAboveCW45: {
+ Q3DCamera::setRotationsPrivate(QPointF(-45.0f, 90.0f));
+ break;
+ }
+ case QDataVis::PresetDirectlyAboveCCW45: {
+ Q3DCamera::setRotationsPrivate(QPointF(45.0f, 90.0f));
+ break;
+ }
+ case QDataVis::PresetFrontBelow: {
+ Q3DCamera::setRotationsPrivate(QPointF(0.0f, -45.0f));
+ break;
+ }
+ case QDataVis::PresetLeftBelow: {
+ Q3DCamera::setRotationsPrivate(QPointF(90.0f, -45.0f));
+ break;
+ }
+ case QDataVis::PresetRightBelow: {
+ Q3DCamera::setRotationsPrivate(QPointF(-90.0f, -45.0f));
+ break;
+ }
+ case QDataVis::PresetBehindBelow: {
+ Q3DCamera::setRotationsPrivate(QPointF(180.0f, -45.0f));
+ break;
+ }
+ case QDataVis::PresetDirectlyBelow: {
+ Q3DCamera::setRotationsPrivate(QPointF(0.0f, -90.0f));
+ break;
+ }
+ default:
+ preset = QDataVis::NoPreset;
+ break;
+ }
+
+ d_ptr->m_activePreset = preset;
+}
+
+void Q3DCamera::setRotationsPrivate(const QPointF &rotation)
+{
+ d_ptr->m_xRotation = rotation.x();
+ d_ptr->m_yRotation = rotation.y();
+}
+
+void Q3DCamera::setZoomLevel(int zoomLevel)
+{
+ d_ptr->m_zoomLevel = zoomLevel;
+}
+
+int Q3DCamera::zoomLevel()
+{
+ return d_ptr->m_zoomLevel;
+}
+
+QVector3D Q3DCamera::calculatePositionRelativeToCamera(const QVector3D &relativePosition,
+ GLfloat fixedRotation,
+ GLfloat distanceModifier) const
+{
+ // Move the position with camera
+ GLfloat radiusFactor = relativePosition.z() * (1.5f + distanceModifier);
+ GLfloat xAngle;
+ GLfloat yAngle;
+ if (!fixedRotation) {
+ xAngle = qDegreesToRadians(d_ptr->m_xRotation);
+ yAngle = qDegreesToRadians(d_ptr->m_yRotation);
+ } else {
+ xAngle = qDegreesToRadians(fixedRotation);
+ yAngle = 0;
+ }
+ GLfloat radius = (radiusFactor + relativePosition.y()); // set radius to match the highest height of the position
+ GLfloat zPos = radius * qCos(xAngle) * qCos(yAngle);
+ GLfloat xPos = radius * qSin(xAngle) * qCos(yAngle);
+ GLfloat yPos = (radiusFactor + relativePosition.y()) * qSin(yAngle);
+ // Keep in the set position in relation to camera
+ return QVector3D(-xPos + relativePosition.x(),
+ yPos + relativePosition.y(),
+ zPos + relativePosition.z());
+}
+
+
+Q3DCameraPrivate::Q3DCameraPrivate(Q3DCamera *q) :
+ q_ptr(q),
+ m_zoomLevel(100)
+{
+}
+
+
+Q3DCameraPrivate::~Q3DCameraPrivate()
+{
+}
+
+QT_DATAVIS3D_END_NAMESPACE