diff options
Diffstat (limited to 'src/Runtime/Source/runtimerender/graphobjects')
33 files changed, 4200 insertions, 0 deletions
diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCamera.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCamera.cpp new file mode 100644 index 00000000..062a36c5 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCamera.cpp @@ -0,0 +1,486 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderCamera.h" +#include "Qt3DSRenderPresentation.h" +#include "foundation/Qt3DSVec2.h" +#include "render/Qt3DSRenderTexture2D.h" +#include "render/Qt3DSRenderContext.h" +#include "Qt3DSTextRenderer.h" + +#include <qmath.h> + +using namespace qt3ds::render; + +namespace { + +QT3DSF32 GetAspectRatio(const NVRenderRectF &inViewport) +{ + return inViewport.m_Height != 0 ? inViewport.m_Width / inViewport.m_Height : 0.0f; +} + +QT3DSF32 GetAspectRatio(const QT3DSVec2 &inDimensions) +{ + return inDimensions.y != 0 ? inDimensions.x / inDimensions.y : 0.0f; +} + +bool IsCameraVerticalAdjust(CameraScaleModes::Enum inMode, QT3DSF32 inDesignAspect, + QT3DSF32 inActualAspect) +{ + return (inMode == CameraScaleModes::Fit && inActualAspect >= inDesignAspect) + || inMode == CameraScaleModes::FitVertical; +} + +bool IsCameraHorizontalAdjust(CameraScaleModes::Enum inMode, QT3DSF32 inDesignAspect, + QT3DSF32 inActualAspect) +{ + return (inMode == CameraScaleModes::Fit && inActualAspect < inDesignAspect) + || inMode == CameraScaleModes::FitHorizontal; +} + +bool IsFitTypeScaleMode(CameraScaleModes::Enum inMode) +{ + return inMode == CameraScaleModes::Fit || inMode == CameraScaleModes::FitHorizontal + || inMode == CameraScaleModes::FitVertical; +} + +struct SPinCameraResult +{ + NVRenderRectF m_Viewport; + NVRenderRectF m_VirtualViewport; + SPinCameraResult(NVRenderRectF v, NVRenderRectF vv) + : m_Viewport(v) + , m_VirtualViewport(vv) + { + } +}; +// Scale and transform the projection matrix to respect the camera anchor attribute +// and the scale mode. +SPinCameraResult PinCamera(const NVRenderRectF &inViewport, QT3DSVec2 inDesignDims, + QT3DSMat44 &ioPerspectiveMatrix, CameraScaleModes::Enum inScaleMode, + CameraScaleAnchors::Enum inPinLocation) +{ + NVRenderRectF viewport(inViewport); + NVRenderRectF idealViewport(inViewport.m_X, inViewport.m_Y, inDesignDims.x, inDesignDims.y); + QT3DSF32 designAspect = GetAspectRatio(inDesignDims); + QT3DSF32 actualAspect = GetAspectRatio(inViewport); + if (IsFitTypeScaleMode(inScaleMode)) { + idealViewport.m_Width = viewport.m_Width; + idealViewport.m_Height = viewport.m_Height; + } + // We move the viewport such that the left, top of the presentation sits against the left top + // edge + // We only need to translate in X *if* our actual aspect > design aspect + // And then we only need to account for whatever centering would happen. + + bool pinLeft = inPinLocation == CameraScaleAnchors::SouthWest + || inPinLocation == CameraScaleAnchors::West + || inPinLocation == CameraScaleAnchors::NorthWest; + bool pinRight = inPinLocation == CameraScaleAnchors::SouthEast + || inPinLocation == CameraScaleAnchors::East + || inPinLocation == CameraScaleAnchors::NorthEast; + bool pinTop = inPinLocation == CameraScaleAnchors::NorthWest + || inPinLocation == CameraScaleAnchors::North + || inPinLocation == CameraScaleAnchors::NorthEast; + bool pinBottom = inPinLocation == CameraScaleAnchors::SouthWest + || inPinLocation == CameraScaleAnchors::South + || inPinLocation == CameraScaleAnchors::SouthEast; + + if (inScaleMode == CameraScaleModes::SameSize) { + // In this case the perspective transform does not center the view, + // it places it in the lower-left of the viewport. + QT3DSF32 idealWidth = inDesignDims.x; + QT3DSF32 idealHeight = inDesignDims.y; + if (pinRight) + idealViewport.m_X -= ((idealWidth - inViewport.m_Width)); + else if (!pinLeft) + idealViewport.m_X -= ((idealWidth - inViewport.m_Width) / 2.0f); + + if (pinTop) + idealViewport.m_Y -= ((idealHeight - inViewport.m_Height)); + else if (!pinBottom) + idealViewport.m_Y -= ((idealHeight - inViewport.m_Height) / 2.0f); + } else { + // In this case our perspective matrix will center the view and we need to decenter + // it as necessary + // if we are wider than we are high + if (IsCameraVerticalAdjust(inScaleMode, designAspect, actualAspect)) { + if (pinLeft || pinRight) { + QT3DSF32 idealWidth = inViewport.m_Height * designAspect; + QT3DSI32 halfOffset = (QT3DSI32)((idealWidth - inViewport.m_Width) / 2.0f); + halfOffset = pinLeft ? halfOffset : -1 * halfOffset; + idealViewport.m_X += halfOffset; + } + } else { + if (pinTop || pinBottom) { + QT3DSF32 idealHeight = inViewport.m_Width / designAspect; + QT3DSI32 halfOffset = (QT3DSI32)((idealHeight - inViewport.m_Height) / 2.0f); + halfOffset = pinBottom ? halfOffset : -1 * halfOffset; + idealViewport.m_Y += halfOffset; + } + } + } + + ioPerspectiveMatrix = NVRenderContext::ApplyVirtualViewportToProjectionMatrix( + ioPerspectiveMatrix, viewport, idealViewport); + return SPinCameraResult(viewport, idealViewport); +} +} + +SCamera::SCamera() + : SNode(GraphObjectTypes::Camera) + , m_ClipNear(10) + , m_ClipFar(10000) + , m_FOV(60) + , m_FOVHorizontal(false) + , m_ScaleMode(CameraScaleModes::Fit) + , m_ScaleAnchor(CameraScaleAnchors::Center) +{ + TORAD(m_FOV); + m_Projection = QT3DSMat44::createIdentity(); + m_Position = QT3DSVec3(0, 0, -600); +} + +// Code for testing +SCameraGlobalCalculationResult SCamera::CalculateGlobalVariables(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) +{ + bool wasDirty = SNode::CalculateGlobalVariables(); + return SCameraGlobalCalculationResult(wasDirty, + CalculateProjection(inViewport, inDesignDimensions)); +} + +bool SCamera::CalculateProjection(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions) +{ + bool retval = false; + if (m_Flags.IsOrthographic()) + retval = ComputeFrustumOrtho(inViewport, inDesignDimensions); + else + retval = ComputeFrustumPerspective(inViewport, inDesignDimensions); + if (retval) { + QT3DSF32 *writePtr(m_Projection.front()); + m_FrustumScale.x = writePtr[0]; + m_FrustumScale.y = writePtr[5]; + PinCamera(inViewport, inDesignDimensions, m_Projection, m_ScaleMode, m_ScaleAnchor); + } + return retval; +} + +//============================================================================== +/** + * Compute the projection matrix for a perspective camera + * @return true if the computed projection matrix is valid + */ +bool SCamera::ComputeFrustumPerspective(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) +{ + m_Projection = QT3DSMat44::createIdentity(); + QT3DSF32 theAngleInRadians = verticalFov(inViewport) / 2.0f; + QT3DSF32 theDeltaZ = m_ClipFar - m_ClipNear; + QT3DSF32 theSine = sinf(theAngleInRadians); + QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions); + QT3DSF32 theAspectRatio = designAspect; + if (IsFitTypeScaleMode(m_ScaleMode)) + theAspectRatio = GetAspectRatio(inViewport); + + if ((theDeltaZ != 0) && (theSine != 0) && (theAspectRatio != 0)) { + QT3DSF32 *writePtr(m_Projection.front()); + writePtr[10] = -(m_ClipFar + m_ClipNear) / theDeltaZ; + writePtr[11] = -1; + writePtr[14] = -2 * m_ClipNear * m_ClipFar / theDeltaZ; + writePtr[15] = 0; + + if (IsCameraVerticalAdjust(m_ScaleMode, designAspect, theAspectRatio)) { + QT3DSF32 theCotangent = cosf(theAngleInRadians) / theSine; + writePtr[0] = theCotangent / theAspectRatio; + writePtr[5] = theCotangent; + } else { + QT3DSF32 theCotangent = cosf(theAngleInRadians) / theSine; + writePtr[0] = theCotangent / designAspect; + writePtr[5] = theCotangent * (theAspectRatio / designAspect); + } + return true; + } else { + QT3DS_ASSERT(false); + return false; + } +} + +//============================================================================== +/** + * Compute the projection matrix for a orthographic camera + * @return true if the computed projection matrix is valid + */ +bool SCamera::ComputeFrustumOrtho(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions) +{ + m_Projection = QT3DSMat44::createIdentity(); + + QT3DSF32 theDeltaZ = m_ClipFar - m_ClipNear; + QT3DSF32 halfWidth = inDesignDimensions.x / 2.0f; + QT3DSF32 halfHeight = inDesignDimensions.y / 2.0f; + QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions); + QT3DSF32 theAspectRatio = designAspect; + if (IsFitTypeScaleMode(m_ScaleMode)) + theAspectRatio = GetAspectRatio(inViewport); + if (theDeltaZ != 0) { + QT3DSF32 *writePtr(m_Projection.front()); + writePtr[10] = -2.0f / theDeltaZ; + writePtr[11] = 0.0f; + writePtr[14] = -(m_ClipNear + m_ClipFar) / theDeltaZ; + writePtr[15] = 1.0f; + if (IsCameraVerticalAdjust(m_ScaleMode, designAspect, theAspectRatio)) { + writePtr[0] = 1.0f / (halfHeight * theAspectRatio); + writePtr[5] = 1.0f / halfHeight; + } else { + writePtr[0] = 1.0f / halfWidth; + writePtr[5] = 1.0f / (halfWidth / theAspectRatio); + } + return true; + } else { + QT3DS_ASSERT(false); + return false; + } +} + +QT3DSF32 SCamera::GetOrthographicScaleFactor(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const +{ + if (m_ScaleMode == CameraScaleModes::SameSize) + return 1.0f; + QT3DSMat44 temp(QT3DSMat44::createIdentity()); + QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions); + QT3DSF32 theAspectRatio = GetAspectRatio(inViewport); + if (m_ScaleMode == CameraScaleModes::Fit) { + if (theAspectRatio >= designAspect) { + return inViewport.m_Width < inDesignDimensions.x ? theAspectRatio / designAspect : 1.0f; + + } else { + return inViewport.m_Height < inDesignDimensions.y ? designAspect / theAspectRatio + : 1.0f; + } + } else if (m_ScaleMode == CameraScaleModes::FitVertical) { + return (QT3DSF32)inDesignDimensions.y / (QT3DSF32)inViewport.m_Height; + } else { + return (QT3DSF32)inDesignDimensions.x / (QT3DSF32)inViewport.m_Width; + } +} + +QT3DSF32 SCamera::GetTextScaleFactor(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const +{ + return NVMax(1.0f, 1.0f / GetOrthographicScaleFactor(inViewport, inDesignDimensions)); +} + +QT3DSMat33 SCamera::GetLookAtMatrix(const QT3DSVec3 &inUpDir, const QT3DSVec3 &inDirection) const +{ + QT3DSVec3 theDirection(inDirection); + + theDirection.normalize(); + + const QT3DSVec3 &theUpDir(inUpDir); + + // gram-shmidt orthogonalization + QT3DSVec3 theCrossDir(theDirection.cross(theUpDir)); + theCrossDir.normalize(); + QT3DSVec3 theFinalDir(theCrossDir.cross(theDirection)); + theFinalDir.normalize(); + QT3DSF32 multiplier = 1.0f; + if (m_Flags.IsLeftHanded()) + multiplier = -1.0f; + + QT3DSMat33 theResultMatrix(theCrossDir, theFinalDir, multiplier * theDirection); + return theResultMatrix; +} + +void SCamera::LookAt(const QT3DSVec3 &inCameraPos, const QT3DSVec3 &inUpDir, const QT3DSVec3 &inTargetPos) +{ + QT3DSVec3 theDirection = inTargetPos - inCameraPos; + if (m_Flags.IsLeftHanded()) + theDirection.z *= -1.0f; + m_Rotation = GetRotationVectorFromRotationMatrix(GetLookAtMatrix(inUpDir, theDirection)); + m_Position = inCameraPos; + MarkDirty(qt3ds::render::NodeTransformDirtyFlag::TransformIsDirty); +} + +void SCamera::CalculateViewProjectionMatrix(QT3DSMat44 &outMatrix) const +{ + QT3DSMat44 globalInverse = m_GlobalTransform.getInverse(); + outMatrix = m_Projection * globalInverse; +} + +SCuboidRect SCamera::GetCameraBounds(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const +{ + QT3DSMat44 unused(QT3DSMat44::createIdentity()); + SPinCameraResult theResult = + PinCamera(inViewport, inDesignDimensions, unused, m_ScaleMode, m_ScaleAnchor); + // find the normalized edges of the view frustum given the renormalization that happens when + // pinning the camera. + SCuboidRect normalizedCuboid(-1, 1, 1, -1); + QT3DSVec2 translation(theResult.m_Viewport.m_X - theResult.m_VirtualViewport.m_X, + theResult.m_Viewport.m_Y - theResult.m_VirtualViewport.m_Y); + if (m_ScaleMode == CameraScaleModes::SameSize) { + // the cuboid ranges are the actual divided by the ideal in this case + QT3DSF32 xRange = 2.0f * (theResult.m_Viewport.m_Width / theResult.m_VirtualViewport.m_Width); + QT3DSF32 yRange = + 2.0f * (theResult.m_Viewport.m_Height / theResult.m_VirtualViewport.m_Height); + normalizedCuboid = SCuboidRect(-1, -1 + yRange, -1 + xRange, -1); + translation.x /= (theResult.m_VirtualViewport.m_Width / 2.0f); + translation.y /= (theResult.m_VirtualViewport.m_Height / 2.0f); + normalizedCuboid.Translate(translation); + } + // fit. This means that two parameters of the normalized cuboid will be -1, 1. + else { + // In this case our perspective matrix will center the view and we need to decenter + // it as necessary + QT3DSF32 actualAspect = GetAspectRatio(inViewport); + QT3DSF32 designAspect = GetAspectRatio(inDesignDimensions); + // if we are wider than we are high + QT3DSF32 idealWidth = inViewport.m_Width; + QT3DSF32 idealHeight = inViewport.m_Height; + + if (IsCameraVerticalAdjust(m_ScaleMode, designAspect, actualAspect)) { + // then we just need to setup the left, right parameters of the cuboid because we know + // the top + // bottom are -1,1 due to how fit works. + idealWidth = (QT3DSF32)ITextRenderer::NextMultipleOf4( + (QT3DSU32)(inViewport.m_Height * designAspect + .5f)); + // halfRange should always be greater than 1.0f. + QT3DSF32 halfRange = inViewport.m_Width / idealWidth; + normalizedCuboid.m_Left = -halfRange; + normalizedCuboid.m_Right = halfRange; + translation.x = translation.x / (idealWidth / 2.0f); + } else { + idealHeight = (QT3DSF32)ITextRenderer::NextMultipleOf4( + (QT3DSU32)(inViewport.m_Width / designAspect + .5f)); + QT3DSF32 halfRange = inViewport.m_Height / idealHeight; + normalizedCuboid.m_Bottom = -halfRange; + normalizedCuboid.m_Top = halfRange; + translation.y = translation.y / (idealHeight / 2.0f); + } + normalizedCuboid.Translate(translation); + } + // Given no adjustment in the virtual rect, then this is what we would have. + + return normalizedCuboid; +} + +void SCamera::SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture, + QT3DSMat44 &outVP) +{ + STextureDetails theDetails(inTexture.GetTextureDetails()); + SCamera theTempCamera; + SetupOrthographicCameraForOffscreenRender(inTexture, outVP, theTempCamera); +} + +void SCamera::SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture, + QT3DSMat44 &outVP, SCamera &outCamera) +{ + STextureDetails theDetails(inTexture.GetTextureDetails()); + SCamera theTempCamera; + theTempCamera.m_Flags.SetOrthographic(true); + theTempCamera.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty); + QT3DSVec2 theDimensions((QT3DSF32)theDetails.m_Width, (QT3DSF32)theDetails.m_Height); + theTempCamera.CalculateGlobalVariables( + NVRenderRect(0, 0, theDetails.m_Width, theDetails.m_Height), theDimensions); + theTempCamera.CalculateViewProjectionMatrix(outVP); + outCamera = theTempCamera; +} + +SRay SCamera::Unproject(const QT3DSVec2 &inViewportRelativeCoords, const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const +{ + SRay theRay; + QT3DSMat44 tempVal(QT3DSMat44::createIdentity()); + SPinCameraResult result = + PinCamera(inViewport, inDesignDimensions, tempVal, m_ScaleMode, m_ScaleAnchor); + QT3DSVec2 globalCoords = inViewport.ToAbsoluteCoords(inViewportRelativeCoords); + QT3DSVec2 normalizedCoords = + result.m_VirtualViewport.AbsoluteToNormalizedCoordinates(globalCoords); + QT3DSVec3 &outOrigin(theRay.m_Origin); + QT3DSVec3 &outDir(theRay.m_Direction); + QT3DSVec2 inverseFrustumScale(1.0f / m_FrustumScale.x, 1.0f / m_FrustumScale.y); + QT3DSVec2 scaledCoords(inverseFrustumScale.x * normalizedCoords.x, + inverseFrustumScale.y * normalizedCoords.y); + + if (m_Flags.IsOrthographic()) { + outOrigin.x = scaledCoords.x; + outOrigin.y = scaledCoords.y; + outOrigin.z = 0.0f; + + outDir.x = 0.0f; + outDir.y = 0.0f; + outDir.z = -1.0f; + } else { + outOrigin.x = 0.0f; + outOrigin.y = 0.0f; + outOrigin.z = 0.0f; + + outDir.x = scaledCoords.x; + outDir.y = scaledCoords.y; + outDir.z = -1.0f; + } + + outOrigin = m_GlobalTransform.transform(outOrigin); + QT3DSMat33 theNormalMatrix; + CalculateNormalMatrix(theNormalMatrix); + + outDir = theNormalMatrix.transform(outDir); + outDir.normalize(); + /* + char printBuf[2000]; + sprintf_s( printBuf, "normCoords %f %f outDir %f %f %f\n" + , normalizedCoords.x, normalizedCoords.y, outDir.x, outDir.y, outDir.z ); + OutputDebugStringA( printBuf ); + */ + + return theRay; +} + +QT3DSVec3 SCamera::UnprojectToPosition(const QT3DSVec3 &inGlobalPos, const SRay &inRay) const +{ + QT3DSVec3 theCameraDir = GetDirection(); + QT3DSVec3 theObjGlobalPos = inGlobalPos; + QT3DSF32 theDistance = -1.0f * theObjGlobalPos.dot(theCameraDir); + NVPlane theCameraPlane(theCameraDir, theDistance); + return inRay.Intersect(theCameraPlane); +} + +QT3DSF32 SCamera::verticalFov(QT3DSF32 aspectRatio) const +{ + if (m_FOVHorizontal) + return 2.0f * qAtan(qTan(qreal(m_FOV) / 2.0) / qreal(aspectRatio)); + else + return m_FOV; +} + +QT3DSF32 SCamera::verticalFov(const NVRenderRectF &inViewport) const +{ + return verticalFov(GetAspectRatio(inViewport)); +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCamera.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCamera.h new file mode 100644 index 00000000..d6d8ce82 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCamera.h @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_CAMERA_H +#define QT3DS_RENDER_CAMERA_H +#include "Qt3DSRenderNode.h" +#include "Qt3DSRenderRay.h" + +namespace qt3ds { +namespace render { + + struct SCameraGlobalCalculationResult + { + bool m_WasDirty; + bool m_ComputeFrustumSucceeded; + SCameraGlobalCalculationResult(bool inWasDirty, bool inComputeSucceeded = true) + : m_WasDirty(inWasDirty) + , m_ComputeFrustumSucceeded(inComputeSucceeded) + { + } + }; + + struct CameraScaleModes + { + enum Enum { + Fit = 0, + SameSize, + FitHorizontal, + FitVertical, + }; + }; + + struct CameraScaleAnchors + { + enum Enum { + Center = 0, + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest, + }; + }; + + struct SCuboidRect + { + QT3DSF32 m_Left; + QT3DSF32 m_Top; + QT3DSF32 m_Right; + QT3DSF32 m_Bottom; + SCuboidRect(QT3DSF32 l = 0.0f, QT3DSF32 t = 0.0f, QT3DSF32 r = 0.0f, QT3DSF32 b = 0.0f) + : m_Left(l) + , m_Top(t) + , m_Right(r) + , m_Bottom(b) + { + } + void Translate(QT3DSVec2 inTranslation) + { + m_Left += inTranslation.x; + m_Right += inTranslation.x; + m_Top += inTranslation.y; + m_Bottom += inTranslation.y; + } + }; + + struct SCamera : public SNode + { + + // Setting these variables should set dirty on the camera. + QT3DSF32 m_ClipNear; + QT3DSF32 m_ClipFar; + + QT3DSF32 m_FOV; // Radians + bool m_FOVHorizontal; + + QT3DSMat44 m_Projection; + CameraScaleModes::Enum m_ScaleMode; + CameraScaleAnchors::Enum m_ScaleAnchor; + // Record some values from creating the projection matrix + // to use during mouse picking. + QT3DSVec2 m_FrustumScale; + + SCamera(); + + QT3DSMat33 GetLookAtMatrix(const QT3DSVec3 &inUpDir, const QT3DSVec3 &inDirection) const; + // Set our position, rotation member variables based on the lookat target + // Marks this object as dirty. + // Need to test this when the camera's local transform is null. + // Assumes parent's local transform is the identity, meaning our local transform is + // our global transform. + void LookAt(const QT3DSVec3 &inCameraPos, const QT3DSVec3 &inUpDir, const QT3DSVec3 &inTargetPos); + + SCameraGlobalCalculationResult CalculateGlobalVariables(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions); + bool CalculateProjection(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions); + bool ComputeFrustumOrtho(const NVRenderRectF &inViewport, const QT3DSVec2 &inDesignDimensions); + // Used when rendering the widgets in studio. This scales the widget when in orthographic + // mode in order to have + // constant size on screen regardless. + // Number is always greater than one + QT3DSF32 GetOrthographicScaleFactor(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const; + bool ComputeFrustumPerspective(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions); + // Text may be scaled so that it doesn't appear pixellated when the camera itself is doing + // the scaling. + QT3DSF32 GetTextScaleFactor(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const; + + void CalculateViewProjectionMatrix(QT3DSMat44 &outMatrix) const; + + // If this is an orthographic camera, the cuboid properties are the distance from the center + // point + // to the left, top, right, and bottom edges of the view frustum in world units. + // If this is a perspective camera, the cuboid properties are the FOV angles + // (left,top,right,bottom) + // of the view frustum. + + // Return a normalized rect that describes the area the camera is rendering to. + // This takes into account the various camera properties (scale mode, scale anchor). + SCuboidRect GetCameraBounds(const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const; + + // Setup a camera VP projection for rendering offscreen. + static void SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture, + QT3DSMat44 &outVP); + static void SetupOrthographicCameraForOffscreenRender(NVRenderTexture2D &inTexture, + QT3DSMat44 &outVP, SCamera &outCamera); + + // Unproject a point (x,y) in viewport relative coordinates meaning + // left, bottom is 0,0 and values are increasing right,up respectively. + SRay Unproject(const QT3DSVec2 &inLayerRelativeMouseCoords, const NVRenderRectF &inViewport, + const QT3DSVec2 &inDesignDimensions) const; + + // Unproject a given coordinate to a 3d position that lies on the same camera + // plane as inGlobalPos. + // Expects CalculateGlobalVariables has been called or doesn't need to be. + QT3DSVec3 UnprojectToPosition(const QT3DSVec3 &inGlobalPos, const SRay &inRay) const; + + QT3DSF32 verticalFov(QT3DSF32 aspectRatio) const; + QT3DSF32 verticalFov(const NVRenderRectF &inViewport) const; + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h new file mode 100644 index 00000000..593c7573 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_CUSTOM_MATERIAL_H +#define QT3DS_RENDER_CUSTOM_MATERIAL_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderDynamicObject.h" +#include "Qt3DSRenderImage.h" +#include "Qt3DSRenderLightmaps.h" +#include "foundation/Qt3DSFlags.h" + +namespace qt3ds { +namespace render { + + // IMPORTANT: These flags matches the key produced by a MDL export file + struct SCustomMaterialShaderKeyValues + { + enum Enum { + diffuse = 1 << 0, + specular = 1 << 1, + glossy = 1 << 2, + cutout = 1 << 3, + refraction = 1 << 4, + transparent = 1 << 5, + displace = 1 << 6, + volumetric = 1 << 7, + transmissive = 1 << 8, + }; + }; + + typedef NVFlags<SCustomMaterialShaderKeyValues::Enum, QT3DSU32> SCustomMaterialShaderKeyFlags; + + struct SCustomMaterial : public SDynamicObject + { + private: + // These objects are only created via the dynamic object system. + SCustomMaterial(const SCustomMaterial &); + SCustomMaterial &operator=(const SCustomMaterial &); + SCustomMaterial(); + + public: + // lightmap section + SLightmaps m_Lightmaps; + // material section + bool m_hasTransparency; + bool m_hasRefraction; + bool m_hasVolumetricDF; + SImage *m_IblProbe; + SImage *m_EmissiveMap2; + SImage *m_DisplacementMap; + QT3DSF32 m_DisplaceAmount; ///< depends on the object size + + SGraphObject *m_NextSibling; + + SCustomMaterialShaderKeyFlags m_ShaderKeyValues; ///< input from MDL files + QT3DSU32 m_LayerCount; ///< input from MDL files + + void Initialize(QT3DSU32 inKey, QT3DSU32 inLayerCount) + { + m_Lightmaps.m_LightmapIndirect = NULL; + m_Lightmaps.m_LightmapRadiosity = NULL; + m_Lightmaps.m_LightmapShadow = NULL; + m_hasTransparency = false; + m_hasRefraction = false; + m_hasVolumetricDF = false; + m_NextSibling = NULL; + m_DirtyFlagWithInFrame = m_Flags.IsDirty(); + m_IblProbe = NULL; + m_EmissiveMap2 = NULL; + m_DisplacementMap = NULL; + m_DisplaceAmount = 0.0; + m_ShaderKeyValues = (SCustomMaterialShaderKeyFlags)inKey; + m_LayerCount = inLayerCount; + } + + bool IsDielectric() const + { + return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::diffuse; + } + bool IsSpecularEnabled() const + { + return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::specular; + } + bool IsCutOutEnabled() const + { + return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::cutout; + } + bool IsVolumetric() const + { + return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::volumetric; + } + bool IsTransmissive() const + { + return m_ShaderKeyValues & SCustomMaterialShaderKeyValues::transmissive; + } + bool HasLighting() const { return true; } + + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SDynamicObject::Remap(inRemapper); + m_Lightmaps.Remap(inRemapper); + inRemapper.Remap(m_IblProbe); + inRemapper.RemapMaterial(m_NextSibling); + inRemapper.Remap(m_EmissiveMap2); + inRemapper.Remap(m_DisplacementMap); + } + + // Dirty + bool m_DirtyFlagWithInFrame; + bool IsDirty() const { return m_Flags.IsDirty() || m_DirtyFlagWithInFrame; } + void UpdateDirtyForFrame() + { + m_DirtyFlagWithInFrame = m_Flags.IsDirty(); + m_Flags.SetDirty(false); + } + }; +} +} +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp new file mode 100644 index 00000000..06f3649a --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderDefaultMaterial.h" + +using namespace qt3ds::render; + +SDefaultMaterial::SDefaultMaterial() + : SGraphObject(GraphObjectTypes::DefaultMaterial) + , m_IblProbe(NULL) + , m_Lighting(DefaultMaterialLighting::VertexLighting) + , m_BlendMode(DefaultMaterialBlendMode::Normal) + , m_DiffuseColor(1, 1, 1) + , m_EmissivePower(0) + , m_EmissiveMap(NULL) + , m_EmissiveMap2(NULL) + , m_EmissiveColor(1, 1, 1) + , m_SpecularReflection(NULL) + , m_SpecularMap(NULL) + , m_SpecularModel(DefaultMaterialSpecularModel::Default) + , m_SpecularTint(1, 1, 1) + , m_IOR(.2f) + , m_FresnelPower(0.0f) + , m_SpecularAmount(0) + , m_SpecularRoughness(50) + , m_RoughnessMap(NULL) + , m_Opacity(1) + , m_OpacityMap(NULL) + , m_BumpMap(NULL) + , m_BumpAmount(0.f) + , m_NormalMap(NULL) + , m_DisplacementMap(NULL) + , m_DisplaceAmount(0.f) + , m_TranslucencyMap(NULL) + , m_TranslucentFalloff(0.f) + , m_DiffuseLightWrap(0.f) + , m_VertexColors(false) + , m_NextSibling(NULL) + , m_Parent(NULL) +{ + m_Lightmaps.m_LightmapIndirect = NULL; + m_Lightmaps.m_LightmapRadiosity = NULL; + m_Lightmaps.m_LightmapShadow = NULL; + + m_DiffuseMaps[0] = NULL; + m_DiffuseMaps[2] = NULL; + m_DiffuseMaps[1] = NULL; +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h new file mode 100644 index 00000000..09595236 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2015 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_DEFAULT_MATERIAL_H +#define QT3DS_RENDER_DEFAULT_MATERIAL_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" +#include "foundation/Qt3DSFlags.h" +#include "foundation/StringTable.h" +#include "foundation/Qt3DSVec3.h" +#include "Qt3DSRenderMaterialDirty.h" +#include "Qt3DSRenderLightmaps.h" + +namespace qt3ds { +namespace render { + struct DefaultMaterialLighting + { + enum Enum { + NoLighting = 0, + VertexLighting, + FragmentLighting + }; + }; + struct DefaultMaterialBlendMode + { + enum Enum { + Normal = 0, + Screen, + Multiply, + Overlay, + ColorBurn, + ColorDodge + }; + }; + + struct DefaultMaterialSpecularModel + { + enum Enum { + Default = 0, + KGGX, + KWard + }; + }; + + struct SImage; + + struct QT3DS_AUTOTEST_EXPORT SDefaultMaterial : SGraphObject + { + CMaterialDirty m_Dirty; + // lightmap section + SLightmaps m_Lightmaps; + // material section + SImage *m_IblProbe; + DefaultMaterialLighting::Enum m_Lighting; // defaults to vertex + DefaultMaterialBlendMode::Enum m_BlendMode; // defaults to normal + QT3DSVec3 m_DiffuseColor; // colors are 0-1 normalized + SImage *m_DiffuseMaps[3]; + QT3DSF32 m_EmissivePower; // 0-100, defaults to 0 + QT3DSVec3 m_EmissiveColor; + SImage *m_EmissiveMap; + SImage *m_EmissiveMap2; + SImage *m_SpecularReflection; + SImage *m_SpecularMap; + DefaultMaterialSpecularModel::Enum m_SpecularModel; + QT3DSVec3 m_SpecularTint; + QT3DSF32 m_IOR; + QT3DSF32 m_FresnelPower; + QT3DSF32 m_SpecularAmount; // 0-??, defaults to 0 + QT3DSF32 m_SpecularRoughness; // 0-??, defaults to 50 + SImage *m_RoughnessMap; + QT3DSF32 m_Opacity; // 0-1 + SImage *m_OpacityMap; + SImage *m_BumpMap; + QT3DSF32 m_BumpAmount; // 0-?? + SImage *m_NormalMap; + SImage *m_DisplacementMap; + QT3DSF32 m_DisplaceAmount; // 0-?? + SImage *m_TranslucencyMap; + QT3DSF32 m_TranslucentFalloff; // 0 - ?? + QT3DSF32 m_DiffuseLightWrap; // 0 - 1 + bool m_VertexColors; + // Materials are stored as a linked list on models. + SGraphObject *m_NextSibling; + SModel *m_Parent; + + SDefaultMaterial(); + + bool IsSpecularEnabled() const { return m_SpecularAmount > .01f; } + bool IsFresnelEnabled() const { return m_FresnelPower > 0.0f; } + bool IsVertexColorsEnabled() const { return m_VertexColors; } + bool HasLighting() const { return m_Lighting != DefaultMaterialLighting::NoLighting; } + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + m_Lightmaps.Remap(inRemapper); + inRemapper.Remap(m_IblProbe); + inRemapper.Remap(m_DiffuseMaps[0]); + inRemapper.Remap(m_DiffuseMaps[1]); + inRemapper.Remap(m_DiffuseMaps[2]); + inRemapper.Remap(m_EmissiveMap); + inRemapper.Remap(m_EmissiveMap2); + inRemapper.Remap(m_SpecularReflection); + inRemapper.Remap(m_SpecularMap); + inRemapper.Remap(m_RoughnessMap); + inRemapper.Remap(m_OpacityMap); + inRemapper.Remap(m_BumpMap); + inRemapper.Remap(m_NormalMap); + inRemapper.Remap(m_DisplacementMap); + inRemapper.Remap(m_TranslucencyMap); + inRemapper.RemapMaterial(m_NextSibling); + inRemapper.Remap(m_Parent); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp new file mode 100644 index 00000000..3d7c6ff5 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** 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 "Qt3DSRender.h" +#include "Qt3DSRenderDynamicObject.h" +#include "Qt3DSRenderDynamicObjectSystem.h" +#include "foundation/FileTools.h" +#include "Qt3DSRenderString.h" + +#include <QtCore/qdir.h> + +using namespace qt3ds; +using namespace qt3ds::render; + +SDynamicObject::SDynamicObject(GraphObjectTypes::Enum inType, CRegisteredString inObjName, + QT3DSU32 inDSByteSize, QT3DSU32 thisObjSize) + : SGraphObject(inType) + , m_ClassName(inObjName) + , m_DataSectionByteSize(inDSByteSize) + , m_ThisObjectSize(thisObjSize) +{ +} + +template <typename TDataType> +void SDynamicObject::SetPropertyValueT(const dynamic::SPropertyDefinition &inDefinition, + const TDataType &inValue) +{ + if (sizeof(inValue) != inDefinition.m_ByteSize) { + QT3DS_ASSERT(false); + return; + } + memCopy(GetDataSectionBegin() + inDefinition.m_Offset, &inValue, sizeof(inValue)); +} + +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + bool inValue) +{ + SetPropertyValueT(inDefinition, inValue); +} + +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + QT3DSF32 inValue) +{ + SetPropertyValueT(inDefinition, inValue); +} +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + QT3DSF32 inValue, QT3DSU32 inOffset) +{ + if (sizeof(QT3DSF32) > (inDefinition.m_ByteSize - inOffset)) { + QT3DS_ASSERT(false); + return; + } + memCopy(GetDataSectionBegin() + inDefinition.m_Offset + inOffset, &inValue, sizeof(inValue)); +} +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const QT3DSVec2 &inValue) +{ + SetPropertyValueT(inDefinition, inValue); +} +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const QT3DSVec3 &inValue) +{ + SetPropertyValueT(inDefinition, inValue); +} +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const QT3DSVec4 &inValue) +{ + SetPropertyValueT(inDefinition, inValue); +} +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + QT3DSI32 inValue) +{ + SetPropertyValueT(inDefinition, inValue); +} +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + CRegisteredString inValue) +{ + QT3DS_ASSERT(inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr); + SetPropertyValueT(inDefinition, inValue); +} +template <typename TStrType> +void SDynamicObject::SetStrPropertyValueT(dynamic::SPropertyDefinition &inDefinition, + const char8_t *inValue, const char8_t *inProjectDir, + TStrType &ioWorkspace, IStringTable &inStrTable) +{ + if (inValue == NULL) + inValue = ""; + if (inDefinition.m_DataType == NVRenderShaderDataTypes::QT3DSI32) { + NVConstDataRef<CRegisteredString> theEnumValues = inDefinition.m_EnumValueNames; + for (QT3DSI32 idx = 0, end = (QT3DSI32)theEnumValues.size(); idx < end; ++idx) { + if (strcmp(theEnumValues[idx].c_str(), inValue) == 0) { + SetPropertyValueT(inDefinition, idx); + break; + } + } + } else if (inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) { + if (inProjectDir == NULL) + inProjectDir = ""; + if (CFileTools::RequiresCombineBaseAndRelative(inValue)) { + QString absolute = QDir(inProjectDir).filePath(inValue); + ioWorkspace.assign(absolute.toLatin1().constData()); + SetPropertyValueT(inDefinition, inStrTable.RegisterStr(ioWorkspace.c_str())); + // We also adjust the image path in the definition + // I could not find a better place + inDefinition.m_ImagePath = inStrTable.RegisterStr(ioWorkspace.c_str()); + } else { + SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue)); + } + } else if (inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderImage2DPtr) { + SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue)); + } else if (inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderDataBufferPtr) { + SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue)); + } else { + QT3DS_ASSERT(false); + } +} + +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const char8_t *inValue, const char8_t *inProjectDir, + CRenderString &ioWorkspace, IStringTable &inStrTable) +{ + SetStrPropertyValueT(const_cast<dynamic::SPropertyDefinition &>(inDefinition), inValue, + inProjectDir, ioWorkspace, inStrTable); +} + +void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const char8_t *inValue, const char8_t *inProjectDir, + eastl::string &ioWorkspace, IStringTable &inStrTable) +{ + SetStrPropertyValueT(const_cast<dynamic::SPropertyDefinition &>(inDefinition), inValue, + inProjectDir, ioWorkspace, inStrTable); +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h new file mode 100644 index 00000000..a275e572 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_DYNAMIC_OBJECT_H +#define QT3DS_RENDER_DYNAMIC_OBJECT_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" +#include "Qt3DSRenderNode.h" +#include "EASTL/string.h" + +namespace qt3ds { +namespace render { + + namespace dynamic { + struct SPropertyDefinition; + } + + // Dynamic objects are objects that have variable number of properties during runtime. + struct SDynamicObject : public SGraphObject + { + CRegisteredString m_ClassName; + NodeFlags m_Flags; + QT3DSU32 m_DataSectionByteSize; + QT3DSU32 m_ThisObjectSize; + + SDynamicObject(GraphObjectTypes::Enum inType, CRegisteredString inClassName, + QT3DSU32 inDSByteSize, QT3DSU32 thisObjSize); + + QT3DSU8 *GetDataSectionBegin() + { + QT3DSU8 *thisObjectStart = reinterpret_cast<QT3DSU8 *>(this); + QT3DSU8 *retval = thisObjectStart + m_ThisObjectSize; + QT3DS_ASSERT((reinterpret_cast<size_t>(retval) % 4 == 0)); + return retval; + } + + const QT3DSU8 *GetDataSectionBegin() const + { + return const_cast<SDynamicObject *>(this)->GetDataSectionBegin(); + } + + QT3DSU8 *GetDataSectionEnd() { return GetDataSectionBegin() + m_DataSectionByteSize; } + + template <typename TDataType> + void SetPropertyValueT(const dynamic::SPropertyDefinition &inDefinition, + const TDataType &inType); + template <typename TStrType> + void SetStrPropertyValueT(dynamic::SPropertyDefinition &inDefinition, + const char8_t *inValue, const char8_t *inProjectDir, + TStrType &ioWorkspace, IStringTable &inStrTable); + + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, bool inValue); + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, QT3DSF32 inValue); + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, QT3DSF32 inValue, + QT3DSU32 inOffset); + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const QT3DSVec2 &inValue); + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const QT3DSVec3 &inValue); + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const QT3DSVec4 &inValue); + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, QT3DSI32 inValue); + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + CRegisteredString inValue); + + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const char8_t *inValue, const char8_t *inProjectDir, + CRenderString &ioWorkspace, IStringTable &inStrTable); + + void SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition, + const char8_t *inValue, const char8_t *inProjectDir, + eastl::string &ioWorkspace, IStringTable &inStrTable); + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.Remap(m_ClassName); + } + }; +} +} +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderEffect.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderEffect.cpp new file mode 100644 index 00000000..97cddd9d --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderEffect.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderEffect.h" +#include "Qt3DSRenderEffectSystem.h" +#include "foundation/Qt3DSVec2.h" +#include "foundation/Qt3DSVec3.h" +#include "Qt3DSRenderString.h" +#include "foundation/FileTools.h" + +using namespace qt3ds::render; + +void SEffect::Initialize() +{ + m_Layer = NULL; + m_NextEffect = NULL; + m_Context = NULL; +} + +void SEffect::SetActive(bool inActive, IEffectSystem &inManager) +{ + if (m_Flags.IsActive() != inActive) { + m_Flags.SetActive(inActive); + if (m_Context) + inManager.ResetEffectFrameData(*m_Context); + m_Flags.SetDirty(true); + } +} + +void SEffect::Reset(IEffectSystem &inSystem) +{ + if (m_Context) + inSystem.ResetEffectFrameData(*m_Context); + m_Flags.SetDirty(true); +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderEffect.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderEffect.h new file mode 100644 index 00000000..c11c214c --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderEffect.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_EFFECT_H +#define QT3DS_RENDER_EFFECT_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" +#include "Qt3DSRenderNode.h" +#include "EASTL/string.h" +#include "Qt3DSRenderDynamicObject.h" + +namespace qt3ds { +namespace render { + struct SLayer; + struct SEffectContext; + + // Effects are post-render effect applied to the layer. There can be more than one of + // them and they have completely variable properties. + // see IEffectManager in order to create these effects. + // The data for the effect immediately follows the effect + struct SEffect : public SDynamicObject + { + private: + // These objects are only created via the dynamic object system. + SEffect(const SEffect &); + SEffect &operator=(const SEffect &); + SEffect(); + + public: + SLayer *m_Layer; + SEffect *m_NextEffect; + // Opaque pointer to context type implemented by the effect system. + // May be null in which case the effect system will generate a new context + // the first time it needs to render this effect. + SEffectContext *m_Context; + + void Initialize(); + + // If our active flag value changes, then we ask the effect manager + // to reset our context. + void SetActive(bool inActive, IEffectSystem &inSystem); + + void Reset(IEffectSystem &inSystem); + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SDynamicObject::Remap(inRemapper); + inRemapper.Remap(m_Layer); + inRemapper.Remap(m_NextEffect); + inRemapper.NullPtr(m_Context); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderGraphObject.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderGraphObject.h new file mode 100644 index 00000000..58c48ed1 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderGraphObject.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_GRAPH_OBJECT_H +#define QT3DS_RENDER_GRAPH_OBJECT_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderTaggedPointer.h" +#include "Qt3DSRenderGraphObjectTypes.h" + +namespace qt3ds { +namespace render { + + // Types should be setup on construction. Change the type + // at your own risk as the type is used for RTTI purposes. + struct QT3DS_AUTOTEST_EXPORT SGraphObject + { + // Id's help debugging the object and are optionally set + CRegisteredString m_Id; + // Type is used for RTTI purposes down the road. + GraphObjectTypes::Enum m_Type; + STaggedPointer m_UserData; + + SGraphObject(GraphObjectTypes::Enum inType) + : m_Type(inType) + { + } + SGraphObject(const SGraphObject &inCloningObject, NVAllocatorCallback & /*inAllocator*/) + : m_Id(inCloningObject.m_Id) + , m_Type(inCloningObject.m_Type) + { + } + + // If you change any detail of the scene graph, or even *breath* on a + // scene graph object, you need to bump this binary version so at least + // we know if we can load a file or not. + static QT3DSU32 GetSceneGraphBinaryVersion() { return 1; } + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + inRemapper.Remap(m_Id); + inRemapper.NullPtr(m_UserData.m_UserData); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp new file mode 100644 index 00000000..eaa98c77 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderImage.h" +#include "Qt3DSRenderBufferManager.h" +#include "Qt3DSOffscreenRenderManager.h" +#include "Qt3DSOffscreenRenderKey.h" +#include "Qt3DSRenderPlugin.h" +#include "Qt3DSRenderPluginGraphObject.h" + +using namespace qt3ds::render; + +SImage::SImage() + : SGraphObject(GraphObjectTypes::Image) + , m_RenderPlugin(NULL) + , m_LastFrameOffscreenRenderer(NULL) + , m_Parent(NULL) + , m_Scale(1, 1) + , m_Pivot(0, 0) + , m_Rotation(0) + , m_Position(0, 0) + , m_MappingMode(ImageMappingModes::Normal) + , m_HorizontalTilingMode(NVRenderTextureCoordOp::ClampToEdge) + , m_VerticalTilingMode(NVRenderTextureCoordOp::ClampToEdge) +{ + m_Flags.SetActive(true); + m_Flags.SetDirty(true); + m_Flags.SetTransformDirty(true); +} + +static void HandleOffscreenResult(SImage &theImage, SImageTextureData &newImage, + SOffscreenRenderResult &theResult, bool &replaceTexture, + bool &wasDirty) +{ + newImage.m_Texture = theResult.m_Texture; + newImage.m_TextureFlags.SetHasTransparency(theResult.m_HasTransparency); + newImage.m_TextureFlags.SetPreMultiplied(true); + wasDirty = wasDirty || theResult.m_HasChangedSinceLastFrame; + theImage.m_LastFrameOffscreenRenderer = theResult.m_Renderer; + replaceTexture = true; +} + +bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager, + IRenderPluginManager &inPluginManager, bool forIbl) +{ + + bool wasDirty = m_Flags.IsDirty(); + m_Flags.SetDirty(false); + SImageTextureData newImage; + bool replaceTexture(false); + if (m_RenderPlugin && m_RenderPlugin->m_Flags.IsActive()) { + IRenderPluginInstance *theInstance = inPluginManager.GetOrCreateRenderPluginInstance( + m_RenderPlugin->m_PluginPath, m_RenderPlugin); + if (theInstance) { + inRenderManager.MaybeRegisterOffscreenRenderer(theInstance, *theInstance); + SOffscreenRenderResult theResult = inRenderManager.GetRenderedItem(theInstance); + HandleOffscreenResult(*this, newImage, theResult, replaceTexture, wasDirty); + } + } + + if (newImage.m_Texture == NULL) { + if (m_OffscreenRendererId.IsValid()) { + SOffscreenRenderResult theResult = + inRenderManager.GetRenderedItem(m_OffscreenRendererId); + HandleOffscreenResult(*this, newImage, theResult, replaceTexture, wasDirty); + } + } + + if (newImage.m_Texture == NULL) { + m_LastFrameOffscreenRenderer = NULL; + newImage = inBufferManager.LoadRenderImage(m_ImagePath, false, forIbl); + replaceTexture = newImage.m_Texture != m_TextureData.m_Texture; + } + + if (replaceTexture) { + wasDirty = true; + m_TextureData = newImage; + } + + if (m_Flags.IsTransformDirty()) { + wasDirty = true; + CalculateTextureTransform(); + } + return wasDirty; +} + +void SImage::CalculateTextureTransform() +{ + m_Flags.SetTransformDirty(false); + + m_TextureTransform = QT3DSMat44::createIdentity(); + + QT3DSMat44 translation(QT3DSMat44::createIdentity()); + QT3DSMat44 rotation(QT3DSMat44::createIdentity()); + QT3DSMat44 scale(QT3DSMat44::createIdentity()); + + translation.column3[0] = m_Position.x; + translation.column3[1] = m_Position.y; + scale.column0[0] = m_Scale.x; + scale.column1[1] = m_Scale.y; + rotation.rotate(m_Rotation, QT3DSVec3(0, 0, 1)); + + // Setup the pivot. + m_TextureTransform.column3[0] = m_Pivot.x; + m_TextureTransform.column3[1] = m_Pivot.y; + m_TextureTransform = m_TextureTransform * rotation; + m_TextureTransform = m_TextureTransform * scale; + m_TextureTransform = m_TextureTransform * translation; +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h new file mode 100644 index 00000000..47993e73 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderImage.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_IMAGE_H +#define QT3DS_RENDER_IMAGE_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" +#include "foundation/StringTable.h" +#include "render/Qt3DSRenderTexture2D.h" +#include "Qt3DSRenderNode.h" +#include "foundation/Qt3DSVec2.h" +#include "Qt3DSRenderImageTextureData.h" +#include "EASTL/utility.h" + +namespace qt3ds { +namespace render { + class IQt3DSRenderContext; + class IOffscreenRenderManager; + class IOffscreenRenderer; + struct ImageMappingModes + { + enum Enum { + Normal = 0, // UV mapping + Environment = 1, + LightProbe = 2, + }; + }; + + struct QT3DS_AUTOTEST_EXPORT SImage : public SGraphObject + { + // Complete path to the file; + //*not* relative to the presentation directory + CRegisteredString m_ImagePath; + CRegisteredString m_ImageShaderName; ///< for custom materials we don't generate the name + + // Presentation id. + CRegisteredString m_OffscreenRendererId; // overrides source path if available + SRenderPlugin *m_RenderPlugin; // Overrides everything if available. + IOffscreenRenderer *m_LastFrameOffscreenRenderer; + SGraphObject *m_Parent; + + SImageTextureData m_TextureData; + + NodeFlags m_Flags; // only dirty, transform dirty, and active apply + + QT3DSVec2 m_Scale; + QT3DSVec2 m_Pivot; + QT3DSF32 m_Rotation; // Radians. + QT3DSVec2 m_Position; + ImageMappingModes::Enum m_MappingMode; + NVRenderTextureCoordOp::Enum m_HorizontalTilingMode; + NVRenderTextureCoordOp::Enum m_VerticalTilingMode; + + // Setting any of the above variables means this object is dirty. + // Setting any of the vec2 properties means this object's transform is dirty + + QT3DSMat44 m_TextureTransform; + + SImage(); + // Renders the sub presentation + // Or finds the image. + // and sets up the texture transform + bool ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager, + IRenderPluginManager &pluginManager, bool forIbl = false); + + void CalculateTextureTransform(); + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.Remap(m_ImagePath); + inRemapper.Remap(m_OffscreenRendererId); + // Null out objects that should be null when loading from file. + inRemapper.NullPtr(m_LastFrameOffscreenRenderer); + inRemapper.NullPtr(m_TextureData.m_Texture); + inRemapper.Remap(m_RenderPlugin); + inRemapper.Remap(m_Parent); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLayer.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLayer.cpp new file mode 100644 index 00000000..ee146624 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLayer.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderLayer.h" +#include "Qt3DSRenderEffect.h" + +using namespace qt3ds::render; + +SLayer::SLayer() + : SNode(GraphObjectTypes::Layer) + , m_Scene(NULL) + , m_FirstEffect(NULL) + , m_RenderPlugin(NULL) + , m_ProgressiveAAMode(AAModeValues::NoAA) + , m_MultisampleAAMode(AAModeValues::NoAA) + , m_Background(LayerBackground::Transparent) + , m_ClearColor(0) + , m_BlendType(LayerBlendTypes::Normal) + , m_HorizontalFieldValues(HorizontalFieldValues::LeftWidth) + , m_Left(0) + , m_LeftUnits(LayerUnitTypes::Percent) + , m_Width(100.0f) + , m_WidthUnits(LayerUnitTypes::Percent) + , m_Right(0) + , m_RightUnits(LayerUnitTypes::Percent) + , m_VerticalFieldValues(VerticalFieldValues::TopHeight) + , m_Top(0) + , m_TopUnits(LayerUnitTypes::Percent) + , m_Height(100.0f) + , m_HeightUnits(LayerUnitTypes::Percent) + , m_Bottom(0) + , m_BottomUnits(LayerUnitTypes::Percent) + , m_AoStrength(0) + , m_AoDistance(5.0f) + , m_AoSoftness(50.0f) + , m_AoBias(0) + , m_AoSamplerate(2) + , m_AoDither(false) + , m_ShadowStrength(0) + , m_ShadowDist(10) + , m_ShadowSoftness(100.0f) + , m_ShadowBias(0) + , m_LightProbe(NULL) + , m_ProbeBright(100.0f) + , m_FastIbl(false) + , m_ProbeHorizon(-1.0f) + , m_ProbeFov(180.0f) + , m_LightProbe2(NULL) + , m_Probe2Fade(1.0f) + , m_Probe2Window(1.0f) + , m_Probe2Pos(0.5f) + , m_TemporalAAEnabled(false) +{ + m_Flags.SetLayerRenderToTarget(true); + m_Flags.SetLayerEnableDepthTest(true); + m_Flags.SetLayerEnableDepthPrepass(true); +} + +void SLayer::AddEffect(SEffect &inEffect) +{ + // Effects need to be rendered in reverse order as described in the file. + inEffect.m_NextEffect = m_FirstEffect; + m_FirstEffect = &inEffect; + inEffect.m_Layer = this; +} + +SEffect *SLayer::GetLastEffect() +{ + if (m_FirstEffect) { + SEffect *theEffect = m_FirstEffect; + // Empty loop intentional + for (; theEffect->m_NextEffect; theEffect = theEffect->m_NextEffect) { + } + QT3DS_ASSERT(theEffect->m_NextEffect == NULL); + return theEffect; + } + return NULL; +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLayer.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLayer.h new file mode 100644 index 00000000..3759fe12 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLayer.h @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_LAYER_H +#define QT3DS_RENDER_LAYER_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderNode.h" +#include "foundation/Qt3DSContainers.h" +#include "Qt3DSRenderer.h" + +namespace qt3ds { +namespace render { + class IQt3DSRenderContext; + struct SPresentation; + struct SScene; + struct SEffect; + + struct AAModeValues + { + enum Enum { + NoAA = 0, + SSAA = 1, + X2 = 2, + X4 = 4, + X8 = 8 + }; + }; + + struct HorizontalFieldValues + { + enum Enum { + LeftWidth = 0, + LeftRight, + WidthRight + }; + }; + + struct VerticalFieldValues + { + enum Enum { + TopHeight = 0, + TopBottom, + HeightBottom + }; + }; + + struct LayerUnitTypes + { + enum Enum { + Percent = 0, + Pixels + }; + }; + + struct LayerBackground + { + enum Enum { + Transparent = 0, + Unspecified, + Color + }; + }; + + struct LayerBlendTypes + { + enum Enum { + Normal = 0, + Screen, + Multiply, + Add, + Subtract, + Overlay, + ColorBurn, + ColorDodge + }; + }; + + // A layer is a special node. It *always* presents its global transform + // to children as the identity. It also can optionally have a width or height + // different than the overlying context. You can think of layers as the transformation + // between a 3d scene graph and a 2D texture. + struct QT3DS_AUTOTEST_EXPORT SLayer : public SNode + { + SScene *m_Scene; + + // First effect in a list of effects. + SEffect *m_FirstEffect; + + // If a layer has a valid texture path (one that resolves to either a + // an on-disk image or a offscreen renderer), then it does not render its + // own source path. Instead, it renders the offscreen renderer. Used in this manner, + // offscreen renderer's also have the option (if they support it) to render directly to the + // render target given a specific viewport (that is also scissored if necessary). + qt3ds::foundation::CRegisteredString m_TexturePath; + + SRenderPlugin *m_RenderPlugin; // Overrides texture path if available. + + AAModeValues::Enum m_ProgressiveAAMode; + AAModeValues::Enum m_MultisampleAAMode; + LayerBackground::Enum m_Background; + QT3DSVec3 m_ClearColor; + + LayerBlendTypes::Enum m_BlendType; + + HorizontalFieldValues::Enum m_HorizontalFieldValues; + QT3DSF32 m_Left; + LayerUnitTypes::Enum m_LeftUnits; + QT3DSF32 m_Width; + LayerUnitTypes::Enum m_WidthUnits; + QT3DSF32 m_Right; + LayerUnitTypes::Enum m_RightUnits; + + VerticalFieldValues::Enum m_VerticalFieldValues; + QT3DSF32 m_Top; + LayerUnitTypes::Enum m_TopUnits; + QT3DSF32 m_Height; + LayerUnitTypes::Enum m_HeightUnits; + QT3DSF32 m_Bottom; + LayerUnitTypes::Enum m_BottomUnits; + + // Ambient occlusion + QT3DSF32 m_AoStrength; + QT3DSF32 m_AoDistance; + QT3DSF32 m_AoSoftness; + QT3DSF32 m_AoBias; + QT3DSI32 m_AoSamplerate; + bool m_AoDither; + + // Direct occlusion + QT3DSF32 m_ShadowStrength; + QT3DSF32 m_ShadowDist; + QT3DSF32 m_ShadowSoftness; + QT3DSF32 m_ShadowBias; + + // IBL + SImage *m_LightProbe; + QT3DSF32 m_ProbeBright; + bool m_FastIbl; + QT3DSF32 m_ProbeHorizon; + QT3DSF32 m_ProbeFov; + SImage *m_LightProbe2; + QT3DSF32 m_Probe2Fade; + QT3DSF32 m_Probe2Window; + QT3DSF32 m_Probe2Pos; + + bool m_TemporalAAEnabled; + + SLayer(); + + void AddEffect(SEffect &inEffect); + + SEffect *GetLastEffect(); + + LayerBlendTypes::Enum GetLayerBlend() + { + return m_BlendType; + } + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SNode::Remap(inRemapper); + inRemapper.Remap(m_Scene); + inRemapper.Remap(m_FirstEffect); + inRemapper.Remap(m_TexturePath); + inRemapper.Remap(m_RenderPlugin); + inRemapper.Remap(m_LightProbe); + inRemapper.Remap(m_LightProbe2); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLight.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLight.cpp new file mode 100644 index 00000000..3b45e8c9 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLight.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderLight.h" + +using namespace qt3ds::render; + +SLight::SLight() + : SNode(GraphObjectTypes::Light) + , m_LightType(RenderLightTypes::Directional) + , m_Scope(NULL) + , m_DiffuseColor(1, 1, 1) + , m_SpecularColor(1, 1, 1) + , m_AmbientColor(0, 0, 0) + , m_Brightness(100) + , m_LinearFade(0) + , m_ExponentialFade(0) + , m_AreaWidth(0) + , m_AreaHeight(0) + , m_CastShadow(false) + , m_ShadowBias(0.0f) + , m_ShadowFactor(5.0f) + , m_ShadowMapRes(9) + , m_ShadowMapFar(5000.0f) + , m_ShadowMapFov(90.0f) + , m_ShadowFilter(35.0f) +{ + m_Flags.SetPointLight(0); +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLight.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLight.h new file mode 100644 index 00000000..549e3e26 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLight.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_LIGHT_H +#define QT3DS_RENDER_LIGHT_H +#include "Qt3DSRenderNode.h" + +namespace qt3ds { +namespace render { + + struct RenderLightTypes + { + enum Enum { + Unknown = 0, + Directional, + Point, + Area, + }; + }; + + struct SImage; + + struct QT3DS_AUTOTEST_EXPORT SLight : public SNode + { + RenderLightTypes::Enum m_LightType; // Directional + SNode *m_Scope; + QT3DSVec3 m_DiffuseColor; // colors are 0-1 normalized + QT3DSVec3 m_SpecularColor; // colors are 0-1 normalized + QT3DSVec3 m_AmbientColor; // colors are 0-1 normalized + + // The variables below are in the same range as Studio + // Only valid if node is a point light + QT3DSF32 m_Brightness; // 0-200 + QT3DSF32 m_LinearFade; // 0-200 + QT3DSF32 m_ExponentialFade; // 0-200 + + QT3DSF32 m_AreaWidth; // 0.01-inf + QT3DSF32 m_AreaHeight; // 0.01-inf + + bool m_CastShadow; // true if this light produce shadows + QT3DSF32 m_ShadowBias; // depth shift to avoid self-shadowing artifacts + QT3DSF32 m_ShadowFactor; // Darkening factor for ESMs + QT3DSU32 m_ShadowMapRes; // Resolution of shadow map + QT3DSF32 m_ShadowMapFar; // Far clip plane for the shadow map + QT3DSF32 m_ShadowMapFov; // Field of View for the shadow map + QT3DSF32 m_ShadowFilter; // Shadow map filter step size + + // Defaults to directional light + SLight(); + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SNode::Remap(inRemapper); + inRemapper.Remap(m_Scope); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLightmaps.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLightmaps.cpp new file mode 100644 index 00000000..0e5e6c60 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLightmaps.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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 "Qt3DSRenderLightmaps.h" + +using namespace qt3ds::render; + +SLightmaps::SLightmaps() + : SGraphObject(GraphObjectTypes::Lightmaps) + , m_LightmapIndirect(NULL) + , m_LightmapRadiosity(NULL) + , m_LightmapShadow(NULL) +{ +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLightmaps.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLightmaps.h new file mode 100644 index 00000000..4480aea4 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderLightmaps.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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$ +** +****************************************************************************/ + +#pragma once +#ifndef QT3DS_RENDER_LIGHTMAPS_H +#define QT3DS_RENDER_LIGHTMAPS_H + +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" +#include "foundation/StringTable.h" +#include "Qt3DSRenderer.h" +#include "Qt3DSRenderMaterialDirty.h" + +namespace qt3ds { +namespace render { + + struct MaterialLightmapsUsage + { + enum Enum { + Dynamic = 0, + Baked, + DynamicAndBaked, + }; + }; + + struct QT3DS_AUTOTEST_EXPORT SLightmaps : public SGraphObject + { + CMaterialDirty m_Dirty; + + SImage *m_LightmapIndirect; + SImage *m_LightmapRadiosity; + SImage *m_LightmapShadow; + + SLightmaps(); + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.Remap(m_LightmapIndirect); + inRemapper.Remap(m_LightmapRadiosity); + inRemapper.Remap(m_LightmapShadow); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderMaterialDirty.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderMaterialDirty.h new file mode 100644 index 00000000..c04c1b6b --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderMaterialDirty.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_MATERIAL_DIRTY_H +#define QT3DS_RENDER_MATERIAL_DIRTY_H + +namespace qt3ds { +namespace render { + class CMaterialDirty + { + private: + bool m_Dirty; + bool m_DirtyFlagWithInFrame; + + public: + CMaterialDirty() + : m_Dirty(true) + , m_DirtyFlagWithInFrame(m_Dirty) + { + } + + void SetDirty() { m_Dirty = m_DirtyFlagWithInFrame = true; } + bool IsDirty() const { return m_Dirty || m_DirtyFlagWithInFrame; } + void ClearDirty() { m_DirtyFlagWithInFrame = m_Dirty = false; } + void UpdateDirtyForFrame() + { + m_DirtyFlagWithInFrame = m_Dirty; + m_Dirty = false; + } + }; +} +} + +#endif // QT3DS_RENDER_MATERIAL_DIRTY_H diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderModel.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderModel.cpp new file mode 100644 index 00000000..a78396c5 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderModel.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderModel.h" +#include "Qt3DSRenderMaterialHelpers.h" +#include "Qt3DSRenderBufferManager.h" +#include "Qt3DSRenderMesh.h" + +using namespace qt3ds::render; + +SModel::SModel() + : SNode(GraphObjectTypes::Model) + , m_FirstMaterial(NULL) + , m_SkeletonRoot(-1) + , m_TessellationMode(TessModeValues::NoTess) + , m_EdgeTess(1.0) + , m_InnerTess(1.0) + , m_WireframeMode(false) + , m_ShadowCaster(true) +{ +} + +void SModel::AddMaterial(SGraphObject &inMaterial) +{ + if (m_FirstMaterial == NULL) + m_FirstMaterial = &inMaterial; + else { + SGraphObject *lastMaterial; + // empty loop intentional + for (lastMaterial = m_FirstMaterial; lastMaterial && GetNextMaterialSibling(lastMaterial); + lastMaterial = GetNextMaterialSibling(lastMaterial)) { + } + SetNextMaterialSibling(*lastMaterial, &inMaterial); + } + if (inMaterial.m_Type == GraphObjectTypes::DefaultMaterial) + static_cast<SDefaultMaterial &>(inMaterial).m_Parent = this; +} + +NVBounds3 SModel::GetModelBounds(IBufferManager &inManager) const +{ + NVBounds3 retval; + retval.setEmpty(); + SRenderMesh *theMesh = inManager.LoadMesh(m_MeshPath); + if (theMesh) { + for (QT3DSU32 idx = 0, end = theMesh->m_Subsets.size(); idx < end; ++idx) + retval.include(theMesh->m_Subsets[idx].m_Bounds); + } + return retval; +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderModel.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderModel.h new file mode 100644 index 00000000..cc5c4e27 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderModel.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_MODEL_H +#define QT3DS_RENDER_MODEL_H + +#include "Qt3DSRenderNode.h" +#include "foundation/StringTable.h" +#include "Qt3DSRenderTessModeValues.h" + +namespace qt3ds { +namespace render { + + struct SDefaultMaterial; + class IBufferManager; + + struct QT3DS_AUTOTEST_EXPORT SModel : public SNode + { + // Complete path to the file; + //*not* relative to the presentation directory + CRegisteredString m_MeshPath; + SGraphObject *m_FirstMaterial; + QT3DSI32 m_SkeletonRoot; + TessModeValues::Enum m_TessellationMode; + QT3DSF32 m_EdgeTess; + QT3DSF32 m_InnerTess; + bool m_WireframeMode; + bool m_ShadowCaster; + + SModel(); + + void AddMaterial(SGraphObject &inMaterial); + + NVBounds3 GetModelBounds(IBufferManager &inManager) const; + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SNode::Remap(inRemapper); + inRemapper.RemapMaterial(m_FirstMaterial); + inRemapper.Remap(m_MeshPath); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderNode.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderNode.cpp new file mode 100644 index 00000000..bf47bb8d --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderNode.cpp @@ -0,0 +1,499 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderModel.h" +#include "Qt3DSRenderNode.h" +#include "Qt3DSRenderText.h" +#include "Qt3DSRenderer.h" +#include "Qt3DSRenderPathManager.h" +#include "Qt3DSRenderPath.h" + +using namespace qt3ds::render; + +SNode::SNode(GraphObjectTypes::Enum inGraphObjectType) + : SGraphObject(inGraphObjectType) + , m_Rotation(0, 0, 0) // Radians + , m_Position(0, 0, 0) + , m_Scale(1, 1, 1) + , m_Pivot(0, 0, 0) + , m_RotationOrder(EulOrdYXZs) + , m_LocalOpacity(1.0f) + , m_GlobalOpacity(1.0f) + , m_SkeletonId(-1) + , m_Parent(NULL) + , m_NextSibling(NULL) + , m_PreviousSibling(NULL) + , m_FirstChild(NULL) + , m_DFSIndex(0) +{ + m_Flags.SetDirty(true); + m_Flags.SetTransformDirty(true); + m_Flags.SetLeftHanded(true); + m_Flags.SetActive(true); + m_Flags.SetLocallyPickable(true); +} + +SNode::SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator) + : SGraphObject(inCloningObject, inAllocator) + , m_Rotation(inCloningObject.m_Rotation) // Radians + , m_Position(inCloningObject.m_Position) + , m_Scale(inCloningObject.m_Scale) + , m_Pivot(inCloningObject.m_Pivot) + , m_RotationOrder(inCloningObject.m_RotationOrder) + , m_LocalOpacity(inCloningObject.m_LocalOpacity) + , m_LocalTransform(inCloningObject.m_LocalTransform) + , m_GlobalTransform(inCloningObject.m_GlobalTransform) + , m_GlobalOpacity(inCloningObject.m_GlobalOpacity) + , m_SkeletonId(inCloningObject.m_SkeletonId) + , m_Parent(NULL) + , m_NextSibling(NULL) + , m_PreviousSibling(NULL) + , m_FirstChild(NULL) + , m_DFSIndex(0) +{ + m_Flags.SetDirty(true); + m_Flags.SetTransformDirty(true); + m_Flags.SetLeftHanded(true); + m_Flags.SetActive(true); + m_Flags.SetLocallyPickable(true); + + // for ( SNode* theChild = m_FirstChild; theChild != NULL; theChild = theChild->m_NextSibling ) + //{ + // SNode* theClonedChild = static_cast<SNode*>( CGraphObjectFactory::CloneGraphObject( + //*theChild, inAllocator ) ); + // AddChild( *theClonedChild ); + //} +} + +// Sets this object dirty and walks down the graph setting all +// children who are not dirty to be dirty. +void SNode::MarkDirty(NodeTransformDirtyFlag::Enum inTransformDirty) +{ + if (m_Flags.IsTransformDirty() == false) + m_Flags.SetTransformDirty(inTransformDirty != NodeTransformDirtyFlag::TransformNotDirty); + if (m_Flags.IsDirty() == false) { + m_Flags.SetDirty(true); + for (SNode *child = m_FirstChild; child; child = child->m_NextSibling) + child->MarkDirty(inTransformDirty); + } +} + +// Calculate global transform and opacity +// Walks up the graph ensure all parents are not dirty so they have +// valid global transforms. + +bool SNode::CalculateGlobalVariables() +{ + bool retval = m_Flags.IsDirty(); + if (retval) { + m_Flags.SetDirty(false); + if (m_Flags.IsTransformDirty()) + CalculateLocalTransform(); + m_GlobalOpacity = m_LocalOpacity; + if (m_Parent) { + // Layer transforms do not flow down but affect the final layer's rendered + // representation. + retval = m_Parent->CalculateGlobalVariables() || retval; + if (m_Parent->m_Type != GraphObjectTypes::Layer) { + m_GlobalOpacity *= m_Parent->m_GlobalOpacity; + if (m_Flags.IsIgnoreParentTransform() == false) + m_GlobalTransform = m_Parent->m_GlobalTransform * m_LocalTransform; + else + m_GlobalTransform = m_LocalTransform; + } else + m_GlobalTransform = m_LocalTransform; + + m_Flags.SetGlobalActive(m_Flags.IsActive() && m_Parent->m_Flags.IsGloballyActive()); + m_Flags.SetGloballyPickable(m_Flags.IsLocallyPickable() + || m_Parent->m_Flags.IsGloballyPickable()); + } else { + m_GlobalTransform = m_LocalTransform; + m_Flags.SetGlobalActive(m_Flags.IsActive()); + m_Flags.SetGloballyPickable(m_Flags.IsLocallyPickable()); + } + } + // We always clear dirty in a reasonable manner but if we aren't active + // there is no reason to tell the universe if we are dirty or not. + return retval && m_Flags.IsActive(); +} + +// Create some mapping of euler angles to their axis mapping. +#define ITERATE_POSSIBLE_EULER_ANGLES \ + HANDLE_EULER_ANGLE(EulOrdXYZs, X, Y, Z) \ + HANDLE_EULER_ANGLE(EulOrdXYXs, X, Y, X) \ + HANDLE_EULER_ANGLE(EulOrdXZYs, X, Z, Y) \ + HANDLE_EULER_ANGLE(EulOrdXZXs, X, Z, X) \ + HANDLE_EULER_ANGLE(EulOrdYZXs, Y, Z, X) \ + HANDLE_EULER_ANGLE(EulOrdYZYs, Y, Z, Y) \ + HANDLE_EULER_ANGLE(EulOrdYXZs, Y, X, Z) \ + HANDLE_EULER_ANGLE(EulOrdYXYs, Y, X, Y) \ + HANDLE_EULER_ANGLE(EulOrdZXYs, Z, X, Y) \ + HANDLE_EULER_ANGLE(EulOrdZXZs, Z, X, Z) \ + HANDLE_EULER_ANGLE(EulOrdZYXs, Z, Y, X) \ + HANDLE_EULER_ANGLE(EulOrdZYZs, Z, Y, Z) \ + HANDLE_EULER_ANGLE(EulOrdZYXr, Z, Y, X) \ + HANDLE_EULER_ANGLE(EulOrdXYXr, X, Y, X) \ + HANDLE_EULER_ANGLE(EulOrdYZXr, Y, Z, X) \ + HANDLE_EULER_ANGLE(EulOrdXZXr, X, Z, X) \ + HANDLE_EULER_ANGLE(EulOrdXZYr, X, Z, Y) \ + HANDLE_EULER_ANGLE(EulOrdYZYr, Y, Z, Y) \ + HANDLE_EULER_ANGLE(EulOrdZXYr, Z, X, Y) \ + HANDLE_EULER_ANGLE(EulOrdYXYr, Y, X, Y) \ + HANDLE_EULER_ANGLE(EulOrdYXZr, Y, X, Z) \ + HANDLE_EULER_ANGLE(EulOrdZXZr, Z, X, Z) \ + HANDLE_EULER_ANGLE(EulOrdXYZr, X, Y, Z) \ + HANDLE_EULER_ANGLE(EulOrdZYZr, Z, Y, Z) + +inline EulerAngles RotationAndOrderToShoemake(QT3DSVec3 inRotation, QT3DSU32 inOrder) +{ + EulerAngles retval; + retval.w = (QT3DSF32)inOrder; + int X = 0; + int Y = 1; + int Z = 2; + + switch (inOrder) { +#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \ + case order: \ + retval.x = -inRotation[xIdx]; \ + retval.y = -inRotation[yIdx]; \ + retval.z = -inRotation[zIdx]; \ + break; + ITERATE_POSSIBLE_EULER_ANGLES +#undef HANDLE_EULER_ANGLE + default: + QT3DS_ASSERT(false); + retval.x = inRotation[X]; + retval.y = inRotation[Y]; + retval.z = inRotation[Z]; + break; + } + return retval; +} + +QT3DSVec3 SNode::GetRotationVectorFromRotationMatrix(const QT3DSMat33 &inMatrix) const +{ + QT3DSMat44 theConvertMatrix(inMatrix, QT3DSVec3(0, 0, 0)); + if (m_Flags.IsLeftHanded()) + SNode::FlipCoordinateSystem(theConvertMatrix); + qt3ds::render::CEulerAngleConverter theConverter; + qt3ds::render::HMatrix *theHMatrix = + reinterpret_cast<qt3ds::render::HMatrix *>(theConvertMatrix.front()); + qt3ds::render::EulerAngles theAngles = theConverter.Eul_FromHMatrix(*theHMatrix, m_RotationOrder); + return GetRotationVectorFromEulerAngles(theAngles); +} + +QT3DSVec3 SNode::GetRotationVectorFromEulerAngles(const EulerAngles &inAngles) +{ + QT3DSVec3 retval(0, 0, 0); + int X = 0; + int Y = 1; + int Z = 2; + switch ((int)inAngles.w) { +#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \ + case order: \ + retval[xIdx] = -inAngles.x; \ + retval[yIdx] = -inAngles.y; \ + retval[zIdx] = -inAngles.z; \ + break; + ITERATE_POSSIBLE_EULER_ANGLES +#undef HANDLE_EULER_ANGLE + default: + QT3DS_ASSERT(false); + retval.x = inAngles.x; + retval.y = inAngles.y; + retval.z = inAngles.z; + break; + } + + return retval; +} + +void SNode::CalculateRotationMatrix(QT3DSMat44 &outMatrix) const +{ + StaticAssert<sizeof(QT3DSMat44) == sizeof(HMatrix)>::valid_expression(); + CEulerAngleConverter theConverter; + EulerAngles theAngles(RotationAndOrderToShoemake(m_Rotation, (int)m_RotationOrder)); + HMatrix *theMatrix = reinterpret_cast<HMatrix *>(&outMatrix); + theConverter.Eul_ToHMatrix(theAngles, *theMatrix); +} + +void SNode::FlipCoordinateSystem(QT3DSMat44 &inMatrix) +{ + QT3DSF32 *writePtr(inMatrix.front()); + // rotation conversion + writePtr[0 * 4 + 2] *= -1; + writePtr[1 * 4 + 2] *= -1; + writePtr[2 * 4 + 0] *= -1; + writePtr[2 * 4 + 1] *= -1; + + // translation conversion + writePtr[3 * 4 + 2] *= -1; +} + +void SNode::CalculateLocalTransform() +{ + m_Flags.SetTransformDirty(false); + bool leftHanded = m_Flags.IsLeftHanded(); + m_LocalTransform = QT3DSMat44::createIdentity(); + m_GlobalTransform = m_LocalTransform; + QT3DSF32 *writePtr = m_LocalTransform.front(); + QT3DSVec3 theScaledPivot(-m_Pivot[0] * m_Scale[0], -m_Pivot[1] * m_Scale[1], + -m_Pivot[2] * m_Scale[2]); + m_LocalTransform.column0[0] = m_Scale[0]; + m_LocalTransform.column1[1] = m_Scale[1]; + m_LocalTransform.column2[2] = m_Scale[2]; + + writePtr[12] = theScaledPivot[0]; + writePtr[13] = theScaledPivot[1]; + if (leftHanded) + writePtr[14] = theScaledPivot[2]; + else + writePtr[14] = -theScaledPivot[2]; + + QT3DSMat44 theRotationTransform; + CalculateRotationMatrix(theRotationTransform); + // may need column conversion in here somewhere. + m_LocalTransform = theRotationTransform * m_LocalTransform; + + writePtr[12] += m_Position[0]; + writePtr[13] += m_Position[1]; + if (leftHanded) + writePtr[14] = writePtr[14] + m_Position[2]; + else + writePtr[14] = writePtr[14] - m_Position[2]; + + if (leftHanded) { + FlipCoordinateSystem(m_LocalTransform); + } +} + +void SNode::SetLocalTransformFromMatrix(QT3DSMat44 &inTransform) +{ + m_Flags.SetTransformDirty(true); + + // clear pivot + m_Pivot[0] = m_Pivot[1] = m_Pivot[2] = 0.0f; + + // set translation + m_Position[0] = inTransform[3][0]; + m_Position[1] = inTransform[3][1]; + m_Position[2] = inTransform[3][2]; + // set scale + m_Scale[0] = inTransform.column0.magnitude(); + m_Scale[1] = inTransform.column1.magnitude(); + m_Scale[2] = inTransform.column2.magnitude(); + + // make sure there is no zero value + m_Scale[0] = (m_Scale[0] == 0.0) ? 1.0f : m_Scale[0]; + m_Scale[1] = (m_Scale[1] == 0.0) ? 1.0f : m_Scale[1]; + m_Scale[2] = (m_Scale[2] == 0.0) ? 1.0f : m_Scale[2]; + + // extract rotation by first dividing through scale value + float invScaleX = 1.0f / m_Scale[0]; + float invScaleY = 1.0f / m_Scale[1]; + float invScaleZ = 1.0f / m_Scale[2]; + + inTransform[0][0] *= invScaleX; + inTransform[0][1] *= invScaleX; + inTransform[0][2] *= invScaleX; + inTransform[1][0] *= invScaleY; + inTransform[1][1] *= invScaleY; + inTransform[1][2] *= invScaleY; + inTransform[2][0] *= invScaleZ; + inTransform[2][1] *= invScaleZ; + inTransform[2][2] *= invScaleZ; + + QT3DSMat33 theRotationMatrix(inTransform.column0.getXYZ(), inTransform.column1.getXYZ(), + inTransform.column2.getXYZ()); + m_Rotation = GetRotationVectorFromRotationMatrix(theRotationMatrix); +} + +void SNode::AddChild(SNode &inChild) +{ + if (inChild.m_Parent) + inChild.m_Parent->RemoveChild(inChild); + inChild.m_Parent = this; + if (m_FirstChild == nullptr) { + m_FirstChild = &inChild; + inChild.m_NextSibling = nullptr; + inChild.m_PreviousSibling = nullptr; + } else { + SNode *lastChild = GetLastChild(); + if (lastChild) { + lastChild->m_NextSibling = &inChild; + inChild.m_PreviousSibling = lastChild; + inChild.m_NextSibling = nullptr; + } else { + QT3DS_ASSERT(false); // no last child but first child isn't null? + } + } +} + +void SNode::RemoveChild(SNode &inChild) +{ + if (inChild.m_Parent != this) { + QT3DS_ASSERT(false); + return; + } + for (SNode *child = m_FirstChild; child; child = child->m_NextSibling) { + if (child == &inChild) { + if (child->m_PreviousSibling) + child->m_PreviousSibling->m_NextSibling = child->m_NextSibling; + if (child->m_NextSibling) + child->m_NextSibling->m_PreviousSibling = child->m_PreviousSibling; + child->m_Parent = NULL; + if (m_FirstChild == child) + m_FirstChild = child->m_NextSibling; + child->m_NextSibling = NULL; + child->m_PreviousSibling = NULL; + return; + } + } + QT3DS_ASSERT(false); +} + +SNode *SNode::GetLastChild() +{ + SNode *lastChild = NULL; + // empty loop intentional + for (lastChild = m_FirstChild; lastChild && lastChild->m_NextSibling; + lastChild = lastChild->m_NextSibling) { + } + return lastChild; +} + +void SNode::RemoveFromGraph() +{ + if (m_Parent) + m_Parent->RemoveChild(*this); + + m_NextSibling = NULL; + + // Orphan all of my children. + SNode *nextSibling = NULL; + for (SNode *child = m_FirstChild; child != NULL; child = nextSibling) { + child->m_PreviousSibling = NULL; + child->m_Parent = NULL; + nextSibling = child->m_NextSibling; + child->m_NextSibling = NULL; + } +} + +NVBounds3 SNode::GetBounds(IBufferManager &inManager, IPathManager &inPathManager, + bool inIncludeChildren, IQt3DSRenderNodeFilter *inChildFilter) const +{ + NVBounds3 retval; + retval.setEmpty(); + if (inIncludeChildren) + retval = GetChildBounds(inManager, inPathManager, inChildFilter); + + if (m_Type == GraphObjectTypes::Model) + retval.include(static_cast<const SModel *>(this)->GetModelBounds(inManager)); + else if (m_Type == GraphObjectTypes::Text) + retval.include(static_cast<const SText *>(this)->GetTextBounds()); + else if (m_Type == GraphObjectTypes::Path) + retval.include(inPathManager.GetBounds(*static_cast<const SPath *>(this))); + return retval; +} + +NVBounds3 SNode::GetChildBounds(IBufferManager &inManager, IPathManager &inPathManager, + IQt3DSRenderNodeFilter *inChildFilter) const +{ + NVBounds3 retval; + retval.setEmpty(); + for (SNode *child = m_FirstChild; child != NULL; child = child->m_NextSibling) { + if (inChildFilter == NULL || inChildFilter->IncludeNode(*child)) { + NVBounds3 childBounds; + if (child->m_Flags.IsTransformDirty()) + child->CalculateLocalTransform(); + childBounds = child->GetBounds(inManager, inPathManager); + if (childBounds.isEmpty() == false) { + // Transform the bounds into our local space. + childBounds.transform(child->m_LocalTransform); + retval.include(childBounds); + } + } + } + return retval; +} + +QT3DSVec3 SNode::GetGlobalPos() const +{ + return m_GlobalTransform.getPosition(); +} + +QT3DSVec3 SNode::GetDirection() const +{ + const QT3DSF32 *dataPtr(m_GlobalTransform.front()); + QT3DSVec3 retval(dataPtr[8], dataPtr[9], dataPtr[10]); + retval.normalize(); + return retval; +} + +QT3DSVec3 SNode::GetScalingCorrectDirection() const +{ + QT3DSMat33 theDirMatrix(m_GlobalTransform.getUpper3x3().getInverse().getTranspose()); + QT3DSVec3 theOriginalDir(0, 0, -1); + QT3DSVec3 retval = theDirMatrix.transform(theOriginalDir); + retval.normalize(); + return retval; +} + +QT3DSVec3 SNode::GetGlobalPivot() const +{ + QT3DSVec3 retval(m_Position); + retval.z *= -1; + + if (m_Parent && m_Parent->m_Type != GraphObjectTypes::Layer) + return m_Parent->m_GlobalTransform.transform(retval); + + return retval; +} + +void SNode::CalculateMVPAndNormalMatrix(const QT3DSMat44 &inViewProjection, QT3DSMat44 &outMVP, + QT3DSMat33 &outNormalMatrix) const +{ + outMVP = inViewProjection * m_GlobalTransform; + CalculateNormalMatrix(outNormalMatrix); +} + +void SNode::GetMatrixUpper3x3(QT3DSMat33 &outDest, const QT3DSMat44 &inSrc) +{ + outDest.column0 = QT3DSVec3(inSrc.column0[0], inSrc.column0[1], inSrc.column0[2]); + outDest.column1 = QT3DSVec3(inSrc.column1[0], inSrc.column1[1], inSrc.column1[2]); + outDest.column2 = QT3DSVec3(inSrc.column2[0], inSrc.column2[1], inSrc.column2[2]); +} + +void SNode::CalculateNormalMatrix(QT3DSMat33 &outNormalMatrix) const +{ + GetMatrixUpper3x3(outNormalMatrix, m_GlobalTransform); + outNormalMatrix = outNormalMatrix.getInverse().getTranspose(); +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderNode.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderNode.h new file mode 100644 index 00000000..87a1500c --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderNode.h @@ -0,0 +1,307 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_NODE_H +#define QT3DS_RENDER_NODE_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" +#include "foundation/Qt3DSMat44.h" +#include "foundation/Qt3DSVec3.h" +#include "foundation/Qt3DSBounds3.h" +#include "foundation/Qt3DSFlags.h" +#include "foundation/Qt3DSNoCopy.h" +#include "Qt3DSRenderEulerAngles.h" +#include "foundation/StringTable.h" + +namespace qt3ds { +namespace render { + + struct SModel; + struct SLight; + struct SCamera; + struct SText; + struct SNode; + class IBufferManager; + + class INodeQueue + { + protected: + virtual ~INodeQueue() {} + public: + virtual void Enqueue(SModel &inModel) = 0; + virtual void Enqueue(SLight &inLight) = 0; + virtual void Enqueue(SCamera &inCamera) = 0; + // virtual void Enqueue( SText& inText ) = 0; + }; + + struct NodeFlagValues + { + enum Enum { + Dirty = 1, + TransformDirty = 1 << 1, + Active = 1 << 2, ///< Is this exact object active + LeftHanded = 1 << 3, + Orthographic = 1 << 4, + PointLight = 1 << 5, + GlobalActive = 1 << 6, ///< set based in Active and if a parent is active. + TextDirty = 1 << 7, + LocallyPickable = 1 << 8, + GloballyPickable = 1 << 9, + LayerEnableDepthTest = 1 << 10, + LayerRenderToTarget = 1 << 11, ///< Does this layer render to the normal render target, + ///or is it offscreen-only + ForceLayerOffscreen = 1 << 12, ///< Forces a layer to always use the offscreen rendering + ///mechanism. This can be usefulf or caching purposes. + IgnoreParentTransform = 1 << 13, + LayerEnableDepthPrePass = 1 << 14, ///< True when we render a depth pass before + }; + }; + + struct NodeTransformDirtyFlag + { + enum Enum { + TransformNotDirty, + TransformIsDirty, + }; + }; + struct NodeFlags : public NVFlags<NodeFlagValues::Enum, QT3DSU32> + { + NodeFlags() + : NVFlags<NodeFlagValues::Enum, QT3DSU32>((QT3DSU32)0) + { + } + void ClearOrSet(bool value, NodeFlagValues::Enum enumVal) { clearOrSet(value, enumVal); } + void SetActive(bool value) { ClearOrSet(value, NodeFlagValues::Active); } + bool IsActive() const { return this->operator&(NodeFlagValues::Active); } + + void SetGlobalActive(bool value) { ClearOrSet(value, NodeFlagValues::GlobalActive); } + bool IsGloballyActive() const { return this->operator&(NodeFlagValues::GlobalActive); } + + void SetTransformDirty(bool value) { ClearOrSet(value, NodeFlagValues::TransformDirty); } + bool IsTransformDirty() const { return this->operator&(NodeFlagValues::TransformDirty); } + + void SetDirty(bool value) { ClearOrSet(value, NodeFlagValues::Dirty); } + bool IsDirty() const { return this->operator&(NodeFlagValues::Dirty); } + + bool IsLeftHanded() const { return this->operator&(NodeFlagValues::LeftHanded); } + void SetLeftHanded(bool value) { ClearOrSet(value, NodeFlagValues::LeftHanded); } + + bool IsOrthographic() const { return this->operator&(NodeFlagValues::Orthographic); } + void SetOrthographic(bool value) { ClearOrSet(value, NodeFlagValues::Orthographic); } + + bool IsPointLight() const { return this->operator&(NodeFlagValues::PointLight); } + void SetPointLight(bool value) { ClearOrSet(value, NodeFlagValues::PointLight); } + + bool IsTextDirty() const { return this->operator&(NodeFlagValues::TextDirty); } + void SetTextDirty(bool value) { ClearOrSet(value, NodeFlagValues::TextDirty); } + + bool IsLocallyPickable() const { return this->operator&(NodeFlagValues::LocallyPickable); } + void SetLocallyPickable(bool value) { ClearOrSet(value, NodeFlagValues::LocallyPickable); } + + bool IsGloballyPickable() const + { + return this->operator&(NodeFlagValues::GloballyPickable); + } + void SetGloballyPickable(bool value) + { + ClearOrSet(value, NodeFlagValues::GloballyPickable); + } + + bool IsLayerRenderToTarget() const + { + return this->operator&(NodeFlagValues::LayerRenderToTarget); + } + void SetLayerRenderToTarget(bool value) + { + ClearOrSet(value, NodeFlagValues::LayerRenderToTarget); + } + + bool IsLayerEnableDepthTest() const + { + return this->operator&(NodeFlagValues::LayerEnableDepthTest); + } + void SetLayerEnableDepthTest(bool value) + { + ClearOrSet(value, NodeFlagValues::LayerEnableDepthTest); + } + + bool IsForceLayerOffscreen() const + { + return this->operator&(NodeFlagValues::ForceLayerOffscreen); + } + void SetForceLayerOffscreen(bool value) + { + ClearOrSet(value, NodeFlagValues::ForceLayerOffscreen); + } + + bool IsIgnoreParentTransform() const + { + return this->operator&(NodeFlagValues::IgnoreParentTransform); + } + void SetIgnoreParentTransform(bool value) + { + ClearOrSet(value, NodeFlagValues::IgnoreParentTransform); + } + + bool IsLayerEnableDepthPrepass() const + { + return this->operator&(NodeFlagValues::LayerEnableDepthPrePass); + } + void SetLayerEnableDepthPrepass(bool value) + { + ClearOrSet(value, NodeFlagValues::LayerEnableDepthPrePass); + } + }; + + struct QT3DS_AUTOTEST_EXPORT SNode : public SGraphObject + { + // changing any one of these means you have to + // set this object dirty + QT3DSVec3 m_Rotation; // Radians + QT3DSVec3 m_Position; + QT3DSVec3 m_Scale; + QT3DSVec3 m_Pivot; + QT3DSU32 m_RotationOrder; // UICEulerOrder::EulOrd, defaults YXZs + + // This only sets dirty, not transform dirty + // Opacity of 1 means opaque, opacity of zero means transparent. + QT3DSF32 m_LocalOpacity; + + // results of clearing dirty. + NodeFlags m_Flags; + // These end up right handed + QT3DSMat44 m_LocalTransform; + QT3DSMat44 m_GlobalTransform; + QT3DSF32 m_GlobalOpacity; + QT3DSI32 m_SkeletonId; + + // node graph members. + SNode *m_Parent; + SNode *m_NextSibling; + SNode *m_PreviousSibling; + SNode *m_FirstChild; + // Property maintained solely by the render system. + // Depth-first-search index assigned and maintained by render system. + QT3DSU32 m_DFSIndex; + + SNode(GraphObjectTypes::Enum inType = GraphObjectTypes::Node); + SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator); + ~SNode() {} + + // Sets this object dirty and walks down the graph setting all + // children who are not dirty to be dirty. + void MarkDirty(NodeTransformDirtyFlag::Enum inTransformDirty = + NodeTransformDirtyFlag::TransformNotDirty); + + void AddChild(SNode &inChild); + void RemoveChild(SNode &inChild); + SNode *GetLastChild(); + + // Remove this node from the graph. + // It is no longer the the parent's child lists + // and all of its children no longer have a parent + // finally they are no longer siblings of each other. + void RemoveFromGraph(); + + // Calculate global transform and opacity + // Walks up the graph ensure all parents are not dirty so they have + // valid global transforms. + bool CalculateGlobalVariables(); + + // Given our rotation order and handedness, calculate the final rotation matrix + // Only the upper 3x3 of this matrix is filled in. + // If this object is left handed, then you need to call FlipCoordinateSystem + // to get a result identical to the result produced in CalculateLocalTransform + void CalculateRotationMatrix(QT3DSMat44 &outMatrix) const; + + // Get a rotation vector that would produce the given 3x.3 matrix. + // Takes m_RotationOrder and m_Flags.IsLeftHandled into account. + // Returns a rotation vector in radians. + QT3DSVec3 GetRotationVectorFromRotationMatrix(const QT3DSMat33 &inMatrix) const; + + static QT3DSVec3 GetRotationVectorFromEulerAngles(const EulerAngles &inAngles); + + // Flip a matrix from left-handed to right-handed and vice versa + static void FlipCoordinateSystem(QT3DSMat44 &ioMatrix); + + // Force the calculation of the local transform + void CalculateLocalTransform(); + + /** + * @brief setup local tranform from a matrix. + * This function decomposes a SRT matrix. + * This will fail if this matrix contains non-affine transformations + * + * @param inTransform[in] input transformation + * + * @return true backend type + */ + void SetLocalTransformFromMatrix(QT3DSMat44 &inTransform); + + // Get the bounds of us and our children in our local space. + NVBounds3 GetBounds(IBufferManager &inManager, IPathManager &inPathManager, + bool inIncludeChildren = true, + IQt3DSRenderNodeFilter *inChildFilter = NULL) const; + NVBounds3 GetChildBounds(IBufferManager &inManager, IPathManager &inPathManager, + IQt3DSRenderNodeFilter *inChildFilter = NULL) const; + // Assumes CalculateGlobalVariables has already been called. + QT3DSVec3 GetGlobalPos() const; + QT3DSVec3 GetGlobalPivot() const; + // Pulls the 3rd column out of the global transform. + QT3DSVec3 GetDirection() const; + // Multiplies (0,0,-1) by the inverse transpose of the upper 3x3 of the global transform. + // This is correct w/r/t to scaling and which the above getDirection is not. + QT3DSVec3 GetScalingCorrectDirection() const; + + // outMVP and outNormalMatrix are returned ready to upload to openGL, meaning they are + // row-major. + void CalculateMVPAndNormalMatrix(const QT3DSMat44 &inViewProjection, QT3DSMat44 &outMVP, + QT3DSMat33 &outNormalMatrix) const; + + // This should be in a utility file somewhere + static void GetMatrixUpper3x3(QT3DSMat33 &inDest, const QT3DSMat44 &inSrc); + void CalculateNormalMatrix(QT3DSMat33 &outNormalMatrix) const; + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.Remap(m_Parent); + inRemapper.Remap(m_FirstChild); + inRemapper.Remap(m_NextSibling); + inRemapper.Remap(m_PreviousSibling); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPath.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPath.cpp new file mode 100644 index 00000000..bc637680 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPath.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderPath.h" +#include "Qt3DSRenderPathSubPath.h" + +using namespace qt3ds::render; + +void SPath::AddSubPath(SPathSubPath &inSegment) +{ + SPathSubPath *lastSegment = NULL; + inSegment.m_Path = this; + inSegment.m_NextSubPath = NULL; + if (m_FirstSubPath) { + // find last segment + for (lastSegment = m_FirstSubPath; lastSegment && lastSegment->m_NextSubPath; + lastSegment = lastSegment->m_NextSubPath) + ; + lastSegment->m_NextSubPath = &inSegment; + } else + m_FirstSubPath = &inSegment; +} + +void SPath::ClearSubPaths() +{ + SPathSubPath *nextSegment = NULL; + for (SPathSubPath *theSegment = m_FirstSubPath; theSegment; theSegment = nextSegment) { + nextSegment = theSegment->m_NextSubPath; + theSegment->m_Path = NULL; + theSegment->m_NextSubPath = NULL; + } + m_FirstSubPath = NULL; +}
\ No newline at end of file diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPath.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPath.h new file mode 100644 index 00000000..7db3ef50 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPath.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_PATH_H +#define QT3DS_RENDER_PATH_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderNode.h" + +namespace qt3ds { +namespace render { + struct PathCapping + { + enum Enum { + Noner = 0, + Taper = 1, + }; + }; + + struct PathTypes + { + enum Enum { + Noner = 0, + Painted, + Geometry, + }; + }; + + struct PathPaintStyles + { + enum Enum { + Noner = 0, + FilledAndStroked, + Filled, + Stroked, + }; + }; + + struct SPath : public SNode + { + PathTypes::Enum m_PathType; + QT3DSF32 m_Width; + QT3DSF32 m_LinearError; + QT3DSF32 m_EdgeTessAmount; + QT3DSF32 m_InnerTessAmount; + PathCapping::Enum m_BeginCapping; + QT3DSF32 m_BeginCapOffset; + QT3DSF32 m_BeginCapOpacity; + QT3DSF32 m_BeginCapWidth; + PathCapping::Enum m_EndCapping; + QT3DSF32 m_EndCapOffset; + QT3DSF32 m_EndCapOpacity; + QT3DSF32 m_EndCapWidth; + SGraphObject *m_Material; + SGraphObject *m_SecondMaterial; + // Paths can either be immediate - children attached define path + // or they can link to a path buffer that defines the path. + SPathSubPath *m_FirstSubPath; + CRegisteredString m_PathBuffer; + PathPaintStyles::Enum m_PaintStyle; + + bool m_WireframeMode; + // Loaded onto the card just as data. + SPath() + : SNode(GraphObjectTypes::Path) + , m_PathType(PathTypes::Geometry) + , m_Width(5.0f) + , m_LinearError(100.0f) + , m_EdgeTessAmount(8.0f) + , m_InnerTessAmount(1.0f) + , m_BeginCapping(PathCapping::Noner) + , m_BeginCapOffset(10.0f) + , m_BeginCapOpacity(.2f) + , m_BeginCapWidth(0.0f) + , m_EndCapping(PathCapping::Noner) + , m_EndCapOffset(10.0f) + , m_EndCapOpacity(.2f) + , m_EndCapWidth(0.0f) + , m_Material(NULL) + , m_SecondMaterial(NULL) + , m_FirstSubPath(NULL) + , m_PaintStyle(PathPaintStyles::Stroked) + , m_WireframeMode(false) + { + } + + bool IsStroked() const + { + return m_PaintStyle == PathPaintStyles::Stroked + || m_PaintStyle == PathPaintStyles::FilledAndStroked; + } + + bool IsFilled() const + { + return m_PaintStyle == PathPaintStyles::Filled + || m_PaintStyle == PathPaintStyles::FilledAndStroked; + } + + void AddMaterial(SGraphObject *inMaterial) + { + if (m_Material == NULL) + m_Material = inMaterial; + else + m_SecondMaterial = inMaterial; + } + + void ClearMaterials() + { + m_Material = NULL; + m_SecondMaterial = NULL; + } + + void AddSubPath(SPathSubPath &inSubPath); + void ClearSubPaths(); + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SNode::Remap(inRemapper); + inRemapper.Remap(m_PathBuffer); + inRemapper.RemapMaterial(m_Material); + inRemapper.RemapMaterial(m_SecondMaterial); + inRemapper.Remap(m_FirstSubPath); + } + }; +} +} +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPathSubPath.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPathSubPath.h new file mode 100644 index 00000000..ed1f9beb --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPathSubPath.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_PATH_SEGMENT_H +#define QT3DS_RENDER_PATH_SEGMENT_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" + +namespace qt3ds { +namespace render { + struct SPathSubPath : public SGraphObject + { + SPath *m_Path; + SPathSubPath *m_NextSubPath; + bool m_Closed; + + SPathSubPath() + : SGraphObject(GraphObjectTypes::PathSubPath) + , m_Path(NULL) + , m_NextSubPath(NULL) + , m_Closed(false) + { + } + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.Remap(m_Path); + inRemapper.Remap(m_NextSubPath); + } + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPresentation.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPresentation.cpp new file mode 100644 index 00000000..6403959e --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPresentation.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderPresentation.h" +#include "render/Qt3DSRenderContext.h" +#include "Qt3DSRenderContextCore.h" + +using namespace qt3ds::render; + +void SPresentation::Render(IQt3DSRenderContext &inContext) +{ + if (m_Scene) { + NVRenderRect theViewportSize(inContext.GetRenderContext().GetViewport()); + m_Scene->Render(QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height), + inContext); + } +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPresentation.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPresentation.h new file mode 100644 index 00000000..2403e3b8 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderPresentation.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_PRESENTATION_H +#define QT3DS_RENDER_PRESENTATION_H + +#include "foundation/StringTable.h" +#include "Qt3DSRenderGraphObject.h" +#include "Qt3DSRenderScene.h" +#include "foundation/Qt3DSVec2.h" + +namespace qt3ds { +namespace render { + + struct RenderRotationValues + { + enum Enum { + NoRotation = 0, + Clockwise90, + Clockwise180, + Clockwise270, + }; + }; + + struct SPresentation : public SGraphObject + { + QT3DSVec2 m_PresentationDimensions; + RenderRotationValues::Enum m_PresentationRotation; + bool m_preferKTX; + SScene *m_Scene; + + CRegisteredString m_PresentationDirectory; + + SPresentation() + : SGraphObject(GraphObjectTypes::Presentation) + , m_PresentationDimensions(800, 400) + , m_PresentationRotation(RenderRotationValues::NoRotation) + , m_preferKTX(false) + , m_Scene(NULL) + { + } + + SPresentation(QT3DSF32 w, QT3DSF32 h, bool preferKTX, CRegisteredString presDir) + : SGraphObject(GraphObjectTypes::Presentation) + , m_PresentationDimensions(w, h) + , m_PresentationRotation(RenderRotationValues::NoRotation) + , m_preferKTX(preferKTX) + , m_Scene(NULL) + , m_PresentationDirectory(presDir) + { + } + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.Remap(m_Scene); + inRemapper.Remap(m_PresentationDirectory); + } + + void Render(IQt3DSRenderContext &inContext); + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderReferencedMaterial.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderReferencedMaterial.h new file mode 100644 index 00000000..d2043f0d --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderReferencedMaterial.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_REFERENCED_MATERIAL_H +#define QT3DS_RENDER_REFERENCED_MATERIAL_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderGraphObject.h" +#include "Qt3DSRenderMaterialDirty.h" + +namespace qt3ds { +namespace render { + + struct SReferencedMaterial : SGraphObject + { + CMaterialDirty m_Dirty; + SGraphObject *m_ReferencedMaterial; + SGraphObject *m_NextSibling; + SReferencedMaterial() + : SGraphObject(GraphObjectTypes::ReferencedMaterial) + , m_ReferencedMaterial(NULL) + , m_NextSibling(NULL) + { + } + + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.RemapMaterial(m_ReferencedMaterial); + inRemapper.RemapMaterial(m_NextSibling); + } + }; +} +} + +#endif // QT3DS_RENDER_REFERENCED_MATERIAL_H diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderScene.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderScene.cpp new file mode 100644 index 00000000..8d206e69 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderScene.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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 "Qt3DSRender.h" +#include "Qt3DSRenderScene.h" +#include "Qt3DSRenderLayer.h" +#include "Qt3DSRenderContextCore.h" +#include "render/Qt3DSRenderContext.h" + +using namespace qt3ds::render; + +SScene::SScene() + : SGraphObject(GraphObjectTypes::Scene) + , m_Presentation(NULL) + , m_FirstChild(NULL) + , m_ClearColor(0, 0, 0) + , m_UseClearColor(true) + , m_Dirty(true) +{ +} + +void SScene::AddChild(SLayer &inLayer) +{ + if (m_FirstChild == NULL) + m_FirstChild = &inLayer; + else + GetLastChild()->m_NextSibling = &inLayer; + inLayer.m_Scene = this; +} + +SLayer *SScene::GetLastChild() +{ + // empty loop intentional + SLayer *child; + for (child = m_FirstChild; child && child->m_NextSibling; + child = (SLayer *)child->m_NextSibling) { + } + + return child; +} + +bool SScene::PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, + const SRenderInstanceId id) +{ + // We need to iterate through the layers in reverse order and ask them to render. + bool wasDirty = m_Dirty; + m_Dirty = false; + if (m_FirstChild) { + wasDirty |= + inContext.GetRenderer().PrepareLayerForRender(*m_FirstChild, inViewportDimensions, + true, id); + } + return wasDirty; +} + +void SScene::Render(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, + RenderClearCommand inClearColorBuffer, const SRenderInstanceId id) +{ + if ((inClearColorBuffer == SScene::ClearIsOptional && m_UseClearColor) + || inClearColorBuffer == SScene::AlwaysClear) { + QT3DSF32 clearColorAlpha + = inContext.IsInSubPresentation() && !m_UseClearColor ? 0.0f : 1.0f; + QT3DSVec4 clearColor(0.0f, 0.0f, 0.0f, clearColorAlpha); + if (m_UseClearColor) { + clearColor.x = m_ClearColor.x; + clearColor.y = m_ClearColor.y; + clearColor.z = m_ClearColor.z; + } + // Maybe clear and reset to previous clear color after we leave. + qt3ds::render::NVRenderContextScopedProperty<QT3DSVec4> __clearColor( + inContext.GetRenderContext(), &NVRenderContext::GetClearColor, + &NVRenderContext::SetClearColor, clearColor); + inContext.GetRenderContext().Clear(qt3ds::render::NVRenderClearValues::Color); + } + if (m_FirstChild) { + inContext.GetRenderer().RenderLayer(*m_FirstChild, inViewportDimensions, m_UseClearColor, + m_ClearColor, true, id); + } +} +void SScene::RenderWithClear(const QT3DSVec2 &inViewportDimensions, + IQt3DSRenderContext &inContext, + RenderClearCommand inClearColorBuffer, + QT3DSVec3 inClearColor, + const SRenderInstanceId id) +{ + // If this scene is not using clear color, we set the color + // to background color from parent layer. This allows + // fully transparent subpresentations (both scene and layer(s) transparent) + // to inherit color from the layer that contains them. + if (!m_UseClearColor) { + m_ClearColor = inClearColor; + m_UseClearColor = true; + } + Render(inViewportDimensions, inContext, inClearColorBuffer, id); +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderScene.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderScene.h new file mode 100644 index 00000000..57887199 --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderScene.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_SCENE_H +#define QT3DS_RENDER_SCENE_H +#include "Qt3DSRender.h" +#include "foundation/Qt3DSVec3.h" +#include "Qt3DSRenderGraphObject.h" + +namespace qt3ds { +namespace render { + struct SLayer; + struct SPresentation; + typedef void *SRenderInstanceId; + + struct SScene : public SGraphObject + { + SPresentation *m_Presentation; + SLayer *m_FirstChild; + QT3DSVec3 m_ClearColor; + bool m_UseClearColor; + bool m_Dirty; + + enum RenderClearCommand { + ClearIsOptional = 0, + DoNotClear = 1, + AlwaysClear = 2, + }; + + SScene(); + + void AddChild(SLayer &inLayer); + SLayer *GetLastChild(); + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SGraphObject::Remap(inRemapper); + inRemapper.Remap(m_Presentation); + inRemapper.Remap(m_FirstChild); + } + // returns true if any of the layers were dirty or if this object was dirty + bool PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, + const SRenderInstanceId id = nullptr); + void Render(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, + RenderClearCommand command = ClearIsOptional, + const SRenderInstanceId id = nullptr); + void RenderWithClear(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext, + RenderClearCommand inClearColorBuffer, + QT3DSVec3 inclearColor, const SRenderInstanceId id = nullptr); + }; +} +} + +#endif diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderText.cpp b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderText.cpp new file mode 100644 index 00000000..8b44e00f --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderText.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 "Qt3DSRenderText.h" + +using namespace qt3ds::render; + +STextRenderInfo::STextRenderInfo() + : m_FontSize(24) + , m_HorizontalAlignment(TextHorizontalAlignment::Center) + , m_VerticalAlignment(TextVerticalAlignment::Middle) + , m_Leading(0) + , m_Tracking(0) + , m_DropShadow(false) + , m_DropShadowStrength(80) + , m_DropShadowOffset(10) + , m_DropShadowOffsetX(0) + , m_DropShadowOffsetY(0) + , m_DropShadowHorizontalAlignment(TextHorizontalAlignment::Right) + , m_DropShadowVerticalAlignment(TextVerticalAlignment::Bottom) + , m_WordWrap(TextWordWrap::WrapWord) + , m_BoundingBox(QT3DSVec2(0 ,0)) + , m_Elide(TextElide::ElideNone) + , m_ScaleX(0) + , m_ScaleY(0) + , m_EnableAcceleratedFont(false) +{ +} + +STextRenderInfo::~STextRenderInfo() +{ +} + +SText::SText() + : SNode(GraphObjectTypes::Text) + , m_TextColor(1, 1, 1) + , m_TextTexture(NULL) +{ + m_Bounds.setEmpty(); +} + +NVBounds3 SText::GetTextBounds() const +{ + NVBounds3 retval; + retval.setEmpty(); + if (m_TextTexture != NULL) { + retval.include(m_Bounds); + } + return retval; +} diff --git a/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderText.h b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderText.h new file mode 100644 index 00000000..56a2a9bf --- /dev/null +++ b/src/Runtime/Source/runtimerender/graphobjects/Qt3DSRenderText.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#pragma once +#ifndef QT3DS_RENDER_TEXT_H +#define QT3DS_RENDER_TEXT_H +#include "Qt3DSRender.h" +#include "Qt3DSRenderNode.h" +#include "Qt3DSRenderTextTypes.h" + +namespace qt3ds { +namespace render { + + struct SText : public SNode, public STextRenderInfo + { + // Change any of these properties and you can expect + // that the text will force an expensive re-layer and render. + // For these you need to set TextDirty. + + // These properties can change every frame with no additional cost. + QT3DSVec3 m_TextColor; + // Setup and utilized by the rendering system + NVRenderTexture2D *m_TextTexture; + STextTextureDetails m_TextTextureDetails; + // used for nv path rendering + NVRenderPathFontItem *m_PathFontItem; + NVRenderPathFontSpecification *m_PathFontDetails; + + NVBounds3 m_Bounds; + + SText(); + + NVBounds3 GetTextBounds() const; + + // Generic method used during serialization + // to remap string and object pointers + template <typename TRemapperType> + void Remap(TRemapperType &inRemapper) + { + SNode::Remap(inRemapper); + inRemapper.Remap(m_Text); + inRemapper.Remap(m_Font); + inRemapper.NullPtr(m_TextTexture); + inRemapper.NullPtr(m_PathFontItem); + inRemapper.NullPtr(m_PathFontDetails); + } + }; +} +} +#endif |