summaryrefslogtreecommitdiffstats
path: root/src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp')
-rw-r--r--src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp b/src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
new file mode 100644
index 00000000..07ee5132
--- /dev/null
+++ b/src/Runtime/ogl-runtime/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSRendererImplLayerRenderHelper.h"
+#include "Qt3DSRenderLayer.h"
+#include "Qt3DSTextRenderer.h"
+
+using namespace qt3ds::render;
+
+namespace {
+// left/top
+QT3DSF32 GetMinValue(QT3DSF32 start, QT3DSF32 width, QT3DSF32 value, LayerUnitTypes::Enum units)
+{
+ if (units == LayerUnitTypes::Pixels)
+ return start + value;
+
+ return start + (value * width / 100.0f);
+}
+
+// width/height
+QT3DSF32 GetValueLen(QT3DSF32 width, QT3DSF32 value, LayerUnitTypes::Enum units)
+{
+ if (units == LayerUnitTypes::Pixels)
+ return value;
+
+ return width * value / 100.0f;
+}
+
+// right/bottom
+QT3DSF32 GetMaxValue(QT3DSF32 start, QT3DSF32 width, QT3DSF32 value, LayerUnitTypes::Enum units)
+{
+ if (units == LayerUnitTypes::Pixels)
+ return start + width - value;
+
+ return start + width - (value * width / 100.0f);
+}
+
+QT3DSVec2 ToRectRelativeCoords(const QT3DSVec2 &inCoords, const NVRenderRectF &inRect)
+{
+ return QT3DSVec2(inCoords.x - inRect.m_X, inCoords.y - inRect.m_Y);
+}
+}
+
+SLayerRenderHelper::SLayerRenderHelper()
+ : m_Layer(NULL)
+ , m_Camera(NULL)
+ , m_Offscreen(false)
+{
+}
+
+SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewport,
+ const NVRenderRectF &inPresentationScissor,
+ const QT3DSVec2 &inPresentationDesignDimensions,
+ SLayer &inLayer, bool inOffscreen,
+ qt3ds::render::ScaleModes::Enum inScaleMode,
+ qt3ds::QT3DSVec2 inScaleFactor)
+ : m_PresentationViewport(inPresentationViewport)
+ , m_PresentationScissor(inPresentationScissor)
+ , m_PresentationDesignDimensions(inPresentationDesignDimensions)
+ , m_Layer(&inLayer)
+ , m_Offscreen(inOffscreen)
+ , m_ScaleMode(inScaleMode)
+ , m_ScaleFactor(inScaleFactor)
+{
+ {
+ QT3DSF32 left = m_Layer->m_Left;
+ QT3DSF32 right = m_Layer->m_Right;
+ QT3DSF32 width = m_Layer->m_Width;
+
+ if (m_ScaleMode == qt3ds::render::ScaleModes::FitSelected) {
+ if (m_Layer->m_LeftUnits == LayerUnitTypes::Pixels)
+ left *= m_ScaleFactor.x;
+
+ if (m_Layer->m_RightUnits == LayerUnitTypes::Pixels)
+ right *= m_ScaleFactor.x;
+
+ if (m_Layer->m_WidthUnits == LayerUnitTypes::Pixels)
+ width *= m_ScaleFactor.x;
+ }
+
+ QT3DSF32 horzMin = GetMinValue(inPresentationViewport.m_X, inPresentationViewport.m_Width,
+ left, m_Layer->m_LeftUnits);
+ QT3DSF32 horzWidth = GetValueLen(inPresentationViewport.m_Width, width, m_Layer->m_WidthUnits);
+ QT3DSF32 horzMax = GetMaxValue(inPresentationViewport.m_X, inPresentationViewport.m_Width,
+ right, m_Layer->m_RightUnits);
+
+ switch (inLayer.m_HorizontalFieldValues) {
+ case HorizontalFieldValues::LeftWidth:
+ m_Viewport.m_X = horzMin;
+ m_Viewport.m_Width = horzWidth;
+ break;
+ case HorizontalFieldValues::LeftRight:
+ m_Viewport.m_X = horzMin;
+ m_Viewport.m_Width = horzMax - horzMin;
+ break;
+ case HorizontalFieldValues::WidthRight:
+ m_Viewport.m_Width = horzWidth;
+ m_Viewport.m_X = horzMax - horzWidth;
+ break;
+ }
+ }
+ {
+ QT3DSF32 top = m_Layer->m_Top;
+ QT3DSF32 bottom = m_Layer->m_Bottom;
+ QT3DSF32 height = m_Layer->m_Height;
+
+ if (m_ScaleMode == qt3ds::render::ScaleModes::FitSelected) {
+
+ if (m_Layer->m_TopUnits == LayerUnitTypes::Pixels)
+ top *= m_ScaleFactor.y;
+
+ if (m_Layer->m_BottomUnits == LayerUnitTypes::Pixels)
+ bottom *= m_ScaleFactor.y;
+
+ if (m_Layer->m_HeightUnits == LayerUnitTypes::Pixels)
+ height *= m_ScaleFactor.y;
+ }
+
+ QT3DSF32 vertMin = GetMinValue(inPresentationViewport.m_Y, inPresentationViewport.m_Height,
+ bottom, m_Layer->m_BottomUnits);
+ QT3DSF32 vertWidth =
+ GetValueLen(inPresentationViewport.m_Height, height, m_Layer->m_HeightUnits);
+ QT3DSF32 vertMax = GetMaxValue(inPresentationViewport.m_Y, inPresentationViewport.m_Height,
+ top, m_Layer->m_TopUnits);
+
+ switch (inLayer.m_VerticalFieldValues) {
+ case VerticalFieldValues::HeightBottom:
+ m_Viewport.m_Y = vertMin;
+ m_Viewport.m_Height = vertWidth;
+ break;
+ case VerticalFieldValues::TopBottom:
+ m_Viewport.m_Y = vertMin;
+ m_Viewport.m_Height = vertMax - vertMin;
+ break;
+ case VerticalFieldValues::TopHeight:
+ m_Viewport.m_Height = vertWidth;
+ m_Viewport.m_Y = vertMax - vertWidth;
+ break;
+ }
+ }
+
+ m_Viewport.m_Width = NVMax(1.0f, m_Viewport.m_Width);
+ m_Viewport.m_Height = NVMax(1.0f, m_Viewport.m_Height);
+ // Now force the viewport to be a multiple of four in width and height. This is because
+ // when rendering to a texture we have to respect this and not forcing it causes scaling issues
+ // that are noticeable especially in situations where customers are using text and such.
+ QT3DSF32 originalWidth = m_Viewport.m_Width;
+ QT3DSF32 originalHeight = m_Viewport.m_Height;
+
+ m_Viewport.m_Width = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Width);
+ m_Viewport.m_Height = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Height);
+
+ // Now fudge the offsets to account for this slight difference
+ m_Viewport.m_X += (originalWidth - m_Viewport.m_Width) / 2.0f;
+ m_Viewport.m_Y += (originalHeight - m_Viewport.m_Height) / 2.0f;
+
+ m_Scissor = m_Viewport;
+ m_Scissor.EnsureInBounds(inPresentationScissor);
+ QT3DS_ASSERT(m_Scissor.m_Width >= 0.0f);
+ QT3DS_ASSERT(m_Scissor.m_Height >= 0.0f);
+}
+
+// This is the viewport the camera will use to setup the projection.
+NVRenderRectF SLayerRenderHelper::GetLayerRenderViewport() const
+{
+ if (m_Offscreen)
+ return NVRenderRectF(0, 0, m_Viewport.m_Width, (QT3DSF32)m_Viewport.m_Height);
+ else
+ return m_Viewport;
+}
+
+QSize SLayerRenderHelper::GetTextureDimensions() const
+{
+ QT3DSU32 width = (QT3DSU32)m_Viewport.m_Width;
+ QT3DSU32 height = (QT3DSU32)m_Viewport.m_Height;
+ return QSize(ITextRenderer::NextMultipleOf4(width),
+ ITextRenderer::NextMultipleOf4(height));
+}
+
+SCameraGlobalCalculationResult SLayerRenderHelper::SetupCameraForRender(SCamera &inCamera)
+{
+ m_Camera = &inCamera;
+ NVRenderRectF rect = GetLayerRenderViewport();
+ if (m_ScaleMode == ScaleModes::FitSelected) {
+ rect.m_Width =
+ (QT3DSF32)(ITextRenderer::NextMultipleOf4((QT3DSU32)(rect.m_Width / m_ScaleFactor.x)));
+ rect.m_Height =
+ (QT3DSF32)(ITextRenderer::NextMultipleOf4((QT3DSU32)(rect.m_Height / m_ScaleFactor.y)));
+ }
+ return m_Camera->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+}
+
+Option<QT3DSVec2> SLayerRenderHelper::GetLayerMouseCoords(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inWindowDimensions,
+ bool inForceIntersect) const
+{
+ // First invert the y so we are dealing with numbers in a normal coordinate space.
+ // Second, move into our layer's coordinate space
+ QT3DSVec2 correctCoords(inMouseCoords.x, inWindowDimensions.y - inMouseCoords.y);
+ QT3DSVec2 theLocalMouse = m_Viewport.ToRectRelative(correctCoords);
+
+ QT3DSF32 theRenderRectWidth = m_Viewport.m_Width;
+ QT3DSF32 theRenderRectHeight = m_Viewport.m_Height;
+ // Crop the mouse to the rect. Apply no further translations.
+ if (inForceIntersect == false
+ && (theLocalMouse.x < 0.0f || theLocalMouse.x >= theRenderRectWidth
+ || theLocalMouse.y < 0.0f || theLocalMouse.y >= theRenderRectHeight)) {
+ return Empty();
+ }
+ return theLocalMouse;
+}
+
+Option<SRay> SLayerRenderHelper::GetPickRay(const QT3DSVec2 &inMouseCoords,
+ const QT3DSVec2 &inWindowDimensions,
+ bool inForceIntersect,
+ bool sceneCameraView) const
+{
+ if (m_Camera == NULL)
+ return Empty();
+ Option<QT3DSVec2> theCoords(
+ GetLayerMouseCoords(inMouseCoords, inWindowDimensions, inForceIntersect));
+ if (theCoords.hasValue()) {
+ // The cameras projection is different if we are onscreen vs. offscreen.
+ // When offscreen, we need to move the mouse coordinates into a local space
+ // to the layer.
+ return m_Camera->Unproject(*theCoords, m_Viewport, m_PresentationDesignDimensions,
+ sceneCameraView);
+ }
+ return Empty();
+}
+
+bool SLayerRenderHelper::IsLayerVisible() const
+{
+ return m_Scissor.m_Height >= 2.0f && m_Scissor.m_Width >= 2.0f;
+}