From b4954701093739e7a4e54a0669f306922d0d4605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20Kera=CC=88nen?= Date: Thu, 6 Jun 2019 16:22:02 +0300 Subject: Long live the slayer! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial commit of OpenGL Runtime to repository. Based on SHA1 61823aaccc6510699a54b34a2fe3f7523dab3b4e of qt3dstudio repository. Task-number: QT3DS-3600 Change-Id: Iaeb80237399f0e5656a19ebec9d1ab3a681d8832 Reviewed-by: Pasi Keränen --- src/engine/EnginePrefix.h | 143 ++ src/engine/NVImageScaler.h | 311 ++++ src/engine/OpenKodeInclude.h | 49 + src/engine/Qt3DSEGLInfo.h | 60 + src/engine/Qt3DSEGLWindowSystem.h | 81 + src/engine/Qt3DSPluginDLL.h | 128 ++ src/engine/Qt3DSRenderRuntimeBinding.cpp | 1858 ++++++++++++++++++++ src/engine/Qt3DSRenderRuntimeBinding.h | 82 + src/engine/Qt3DSRenderRuntimeBindingImpl.h | 218 +++ .../Qt3DSRenderRuntimeBindingImplRenderer.cpp | 224 +++ .../Qt3DSRenderRuntimeBindingImplTranslation.cpp | 1841 +++++++++++++++++++ src/engine/Qt3DSRuntimeView.cpp | 862 +++++++++ src/engine/Qt3DSRuntimeView.h | 238 +++ src/engine/Qt3DSTegraInputEngine.cpp | 124 ++ src/engine/Qt3DSTegraInputEngine.h | 81 + src/engine/Qt3DSWindowSystem.h | 57 + 16 files changed, 6357 insertions(+) create mode 100644 src/engine/EnginePrefix.h create mode 100644 src/engine/NVImageScaler.h create mode 100644 src/engine/OpenKodeInclude.h create mode 100644 src/engine/Qt3DSEGLInfo.h create mode 100644 src/engine/Qt3DSEGLWindowSystem.h create mode 100644 src/engine/Qt3DSPluginDLL.h create mode 100644 src/engine/Qt3DSRenderRuntimeBinding.cpp create mode 100644 src/engine/Qt3DSRenderRuntimeBinding.h create mode 100644 src/engine/Qt3DSRenderRuntimeBindingImpl.h create mode 100644 src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp create mode 100644 src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp create mode 100644 src/engine/Qt3DSRuntimeView.cpp create mode 100644 src/engine/Qt3DSRuntimeView.h create mode 100644 src/engine/Qt3DSTegraInputEngine.cpp create mode 100644 src/engine/Qt3DSTegraInputEngine.h create mode 100644 src/engine/Qt3DSWindowSystem.h (limited to 'src/engine') diff --git a/src/engine/EnginePrefix.h b/src/engine/EnginePrefix.h new file mode 100644 index 0000000..d901785 --- /dev/null +++ b/src/engine/EnginePrefix.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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 + +#include "render/backends/gl/Qt3DSOpenGLPrefix.h" + +#ifdef _WIN32 +//============================================================================== +// DEFINES +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +//============================================================================== +// DISABLED WARNINGS +// +// Note that most of these warnings are tuned off by default by the compiler +// even at warning level 4. Using option /Wall turns on all warnings and makes +// even standard Microsoft include files cry. We had to turn off these or +// turn off warnings individually for each standard include file which was +// too much work. Point is that /Wall is like Warning Level 5 and this brings +// it down to about Warning level 4.5, still way above /W4. +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union +//#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list +//#pragma warning( disable : 4511 ) // copy constructor could not be generated +#pragma warning(disable : 4512) // assignment operator could not be generated +#pragma warning(disable : 4514) // unreferenced inline function has been removed +//#pragma warning( disable : 4619 ) // #pragma warning : there is no warning number '4619' (in +//string.h) +#pragma warning(disable : 4625) // copy constructor could not be generated because a base class copy + // constructor is inaccessible +#pragma warning(disable : 4626) // assignment operator could not be generated because a base class + // assignment operator is inaccessible +//#pragma warning( disable : 4640 ) // TODO MF Remove - construction of local static object is +//not thread-safe +#pragma warning(disable : 4710) // function not inlined +#pragma warning(disable : 4711) // function selected for automatic inline expansion +#pragma warning( \ + disable : 4738) // storing 32-bit float result in memory, possible loss of performance +#pragma warning(disable : 4826) // Conversion from 'const void *' to 'void *' is sign-extended +//#pragma warning( disable : 4996 ) // _snprintf' was declared deprecated + +#endif //_WIN32 + +//============================================================================== +// Non-windows environments need to declare this +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif + +//============================================================================== +// STD - Standard includes MUST come first +#ifdef _WIN32 +#pragma warning(push, 3) +#pragma warning( \ + disable : 4548) // expression before comma has no effect; expected expression with side-effect +#endif + +#include +#include + +#if defined(_PCPLATFORM) || defined(_TEGRAPLATFORM) +#include +#endif + +#ifdef _WIN32 +#pragma warning(pop) +#endif + +//============================================================================== +// Runtime +//============================================================================== +#include "Qt3DSAssert.h" +#include "Qt3DSMacros.h" +#include "Qt3DSElementSystem.h" +#include "Qt3DSQmlEngine.h" +#include "Qt3DSAttributeHashes.h" + +//============================================================================== +// Additional Linux only dependencies +//============================================================================== +#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM) + +#pragma pack(1) +struct BITMAPFILEHEADER +{ + Q3DStudio::UINT16 bfType; + Q3DStudio::UINT32 bfSize; + Q3DStudio::UINT16 bfReserved1; + Q3DStudio::UINT16 bfReserved2; + Q3DStudio::UINT32 bfOffBits; +}; +#pragma pack() + +#pragma pack(1) + +typedef struct tagBITMAPINFOHEADER +{ + Q3DStudio::UINT32 biSize; + Q3DStudio::INT32 biWidth; + Q3DStudio::INT32 biHeight; + Q3DStudio::UINT16 biPlanes; + Q3DStudio::UINT16 biBitCount; + Q3DStudio::UINT32 biCompression; + Q3DStudio::UINT32 biSizeImage; + Q3DStudio::INT32 biXPelsPerMeter; + Q3DStudio::INT32 biYPelsPerMeter; + Q3DStudio::UINT32 biClrUsed; + Q3DStudio::UINT32 biClrImportant; +} BITMAPINFOHEADER; + +#pragma pack() + +#define UNREFERENCED_PARAMETER(theParam) theParam; + +#endif diff --git a/src/engine/NVImageScaler.h b/src/engine/NVImageScaler.h new file mode 100644 index 0000000..069604a --- /dev/null +++ b/src/engine/NVImageScaler.h @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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 + +namespace Q3DStudio { +namespace ImageScaler { + + //============================================================================== + /** + * + */ + template + inline void BilinearReduceRows(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight, + CHAR *outDstBuffer, INT32 inDstHeight) + { + INT32 theDDAConst = static_cast(1024.0 * inDstHeight / inSrcHeight); + INT32 theDDAAccum = 0; + INT32 thePixelCount; + + INT32 theSrcRow; + INT32 theSrcCol; + INT32 theDstRow; + + INT32 theChannelAccum[TNumChannels] = { 0 }; + + CHAR *theDstPointer = outDstBuffer; + const CHAR *theSrcPointer = inSrcBuffer; + const CHAR *theSrcColPointer = NULL; + CHAR *theDstColPointer = NULL; + + INT32 theStepSize = TNumChannels; + INT32 theSrcStride = TNumChannels * inSrcWidth; + INT32 theDstStride = TNumChannels * inSrcWidth; + + for (theSrcCol = 0; theSrcCol < inSrcWidth; ++theSrcCol) { + theSrcColPointer = theSrcPointer + (theSrcCol * theStepSize); + theDstColPointer = theDstPointer + (theSrcCol * theStepSize); + + theSrcRow = 0L; + theDstRow = 0L; + thePixelCount = 0L; + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] = 0L; + + theDDAAccum = 0L; + + while (theSrcRow < inSrcHeight) { + while ((theDDAAccum < 1024L) && (theSrcRow < inSrcHeight)) { + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] += + 1024L * theSrcColPointer[(theSrcRow * theSrcStride) + idx]; + + theDDAAccum += theDDAConst; + thePixelCount += 1024L; + ++theSrcRow; + } + + theDDAAccum = (theSrcRow < inSrcHeight) ? (theDDAAccum - 1024L) : (0L); + thePixelCount -= theDDAAccum; + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] -= theDDAAccum + * (INT32)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + idx]; + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theDstColPointer[(theDstRow * theDstStride) + idx] = + (CHAR)(theChannelAccum[idx] / thePixelCount); + + thePixelCount = 1024L - theDDAAccum; + ++theDstRow; + + if (theDstRow >= inDstHeight) + break; + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] = thePixelCount + * (INT32)theSrcColPointer[((theSrcRow - 1) * theSrcStride) + idx]; + } + } + } + + inline void BilinearReduceRows(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight, + INT32 inChannels, CHAR *outDstBuffer, INT32 inDstHeight) + { + switch (inChannels) { + case 4: + BilinearReduceRows<4>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight); + break; + case 3: + BilinearReduceRows<3>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight); + break; + case 2: + BilinearReduceRows<2>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight); + break; + case 1: + BilinearReduceRows<1>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstHeight); + break; + } + } + + template + inline void BilinearReduceCols(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight, + CHAR *outDstBuffer, INT32 inDstWidth) + { + INT32 theDDAConst = static_cast(1024.0 * inDstWidth / inSrcWidth); + INT32 theDDAAccum = 0L; + INT32 thePixelCount; + + INT32 theSrcRow; + INT32 theSrcCol; + INT32 theDstCol; + + INT32 theChannelAccum[TNumChannels]; + + CHAR *theDstPointer = outDstBuffer; + const CHAR *theSrcPointer = inSrcBuffer; + const CHAR *theSrcRowPointer; + CHAR *theDstRowPointer; + + INT32 theSrcStepSize = TNumChannels; + INT32 theDstStepSize = TNumChannels; + + for (theSrcRow = 0; theSrcRow < inSrcHeight; ++theSrcRow) { + + theSrcRowPointer = theSrcPointer + (theSrcRow * inSrcWidth * theSrcStepSize); + theDstRowPointer = theDstPointer + (theSrcRow * inDstWidth * theDstStepSize); + + theSrcCol = 0L; + theDstCol = 0L; + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] = 0L; + thePixelCount = 0L; + theDDAAccum = 0L; + + while (theSrcCol < inSrcWidth) { + while ((theDDAAccum < 1024L) && (theSrcCol < inSrcWidth)) { + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] += + 1024L * theSrcRowPointer[(theSrcCol * theSrcStepSize) + idx]; + + theDDAAccum += theDDAConst; + thePixelCount += 1024L; + ++theSrcCol; + } + + theDDAAccum = (theSrcCol < inSrcWidth) ? (theDDAAccum - 1024L) : (0L); + thePixelCount -= theDDAAccum; + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] -= theDDAAccum + * (INT32)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + idx]; + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theDstRowPointer[(theDstCol * theDstStepSize) + idx] = + (CHAR)(theChannelAccum[idx] / thePixelCount); + + thePixelCount = 1024L - theDDAAccum; + ++theDstCol; + + if (theDstCol >= inDstWidth) { + break; + } + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theChannelAccum[idx] = thePixelCount + * (INT32)theSrcRowPointer[((theSrcCol - 1) * theSrcStepSize) + idx]; + } + } + } + + inline void BilinearReduceCols(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight, + INT32 inChannels, CHAR *&outDstBuffer, INT32 inDstWidth) + { + switch (inChannels) { + case 4: + BilinearReduceCols<4>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth); + break; + case 3: + BilinearReduceCols<3>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth); + break; + case 2: + BilinearReduceCols<2>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth); + break; + case 1: + BilinearReduceCols<1>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth); + break; + } + } + + template + inline void BilinearReduceImage(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight, + CHAR *outDstBuffer, INT32 inDstWidth, INT32 inDstHeight) + { + // Number larger than 1024 + // One pixel in the source image is equivalent to this much of a pixel + // in terms of dest pixels. + INT32 theXIncrement = static_cast(1024.f * inSrcWidth / inDstWidth); + // How many rows do we skip, in fixed point arithmetic, when we bump lines + INT32 theYIncrement = static_cast(1024.f * inSrcHeight / inDstHeight); + // We are starting at position .5 in textel space + INT32 theSrcYPtr = 0; + CHAR *theDstPtr = outDstBuffer; + for (INT32 theHeightIndex = 0; theHeightIndex < inDstHeight; + ++theHeightIndex, theSrcYPtr += theYIncrement) { + INT32 theSrcXPtr = 0; + for (INT32 theWidthIndex = 0; theWidthIndex < inDstWidth; + ++theWidthIndex, theSrcXPtr += theXIncrement, theDstPtr += TNumChannels) { + INT32 theAccum[TNumChannels] = { 0 }; + INT32 theNumPixels = 0; + // Pull all reasonable pixels from the source image. + INT32 theStartRow = (theSrcYPtr / 1024); + INT32 theStopRow = (theSrcYPtr + theYIncrement) / 1024; + INT32 theStartColumn = theSrcXPtr / 1024; + INT32 theStopColumn = (theSrcXPtr + theXIncrement) / 1024; + // Average everything between the columns + for (INT32 theRow = theStartRow; theRow < theStopRow; ++theRow) { + INT32 theSrcAddr = (theRow * inSrcWidth + theStartColumn) * TNumChannels; + for (INT32 theCol = theStartColumn; theCol < theStopColumn; + ++theCol, theSrcAddr += TNumChannels) { + ++theNumPixels; + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theAccum[idx] += inSrcBuffer[theSrcAddr + idx]; + } + } + + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theDstPtr[idx] = theAccum[idx] / theNumPixels; + } + } + } + + template + inline void NearestReduceImage(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight, + CHAR *outDstBuffer, INT32 inDstWidth, INT32 inDstHeight) + { + // Number larger than 1024 + // One pixel in the source image is equivalent to this much of a pixel + // in terms of dest pixels. + INT32 theXIncrement = static_cast(1024.f * inSrcWidth / inDstWidth); + // How many rows do we skip, in fixed point arithmetic, when we bump lines + INT32 theYIncrement = static_cast(1024.f * inSrcHeight / inDstHeight); + // We are starting at position .5 in textel space + INT32 theSrcYPtr = theYIncrement / 2; + CHAR *theDstPtr = outDstBuffer; + for (INT32 theHeightIndex = 0; theHeightIndex < inDstHeight; + ++theHeightIndex, theSrcYPtr += theYIncrement) { + INT32 theSrcRow = (theSrcYPtr / 1024) * inSrcWidth * TNumChannels; + INT32 theSrcXPtr = theXIncrement / 2; + for (INT32 theWidthIndex = 0; theWidthIndex < inDstWidth; + ++theWidthIndex, theSrcXPtr += theXIncrement, theDstPtr += TNumChannels) { + INT32 theSrcPtr = theSrcRow + (theSrcXPtr >> 10) * TNumChannels; + for (INT32 idx = 0; idx < TNumChannels; ++idx) + theDstPtr[idx] = inSrcBuffer[theSrcPtr + idx]; + } + } + } + + inline void NearestReduceImage(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight, + INT32 inChannels, CHAR *outDstBuffer, INT32 inDstWidth, + INT32 inDstHeight) + { + switch (inChannels) { + case 4: + NearestReduceImage<4>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth, + inDstHeight); + break; + case 3: + NearestReduceImage<3>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth, + inDstHeight); + break; + case 2: + NearestReduceImage<2>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth, + inDstHeight); + break; + case 1: + NearestReduceImage<1>(inSrcBuffer, inSrcWidth, inSrcHeight, outDstBuffer, inDstWidth, + inDstHeight); + break; + } + } +} +} \ No newline at end of file diff --git a/src/engine/OpenKodeInclude.h b/src/engine/OpenKodeInclude.h new file mode 100644 index 0000000..06bdf00 --- /dev/null +++ b/src/engine/OpenKodeInclude.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2008 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$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== + +// Wrap the include so we can ensure it gets compiled with 8 byte alignment +// also, this means we need to compile nv_main.c (via right click -> properties) with 8 byte +// alignment too! + +#pragma pack(push) +#pragma pack(8) +#include +#pragma pack(pop) + +//============================================================================== +// Namespace +//============================================================================== +namespace NVUI { + +} // namespace NVUI diff --git a/src/engine/Qt3DSEGLInfo.h b/src/engine/Qt3DSEGLInfo.h new file mode 100644 index 0000000..7be2c09 --- /dev/null +++ b/src/engine/Qt3DSEGLInfo.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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$ +** +****************************************************************************/ +#ifndef QT3DS_EGLINFO_H +#define QT3DS_EGLINFO_H + +#ifdef _PLATFORM_USE_EGL +#include + +namespace Q3DStudio { +struct SEGLInfo +{ + EGLDisplay display; + EGLSurface surface; + EGLContext context; + EGLConfig config; + EGLNativeWindowType nativewin; +}; +}; + +#else +namespace Q3DStudio { +struct SEGLInfo +{ + void *display; + void *surface; + void *context; + void *config; + void *nativewin; +}; +}; +#endif + +#endif diff --git a/src/engine/Qt3DSEGLWindowSystem.h b/src/engine/Qt3DSEGLWindowSystem.h new file mode 100644 index 0000000..770f5c9 --- /dev/null +++ b/src/engine/Qt3DSEGLWindowSystem.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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$ +** +****************************************************************************/ +#ifndef QT3DS_EGL_WINDOW_SYSTEM_H +#define QT3DS_EGL_WINDOW_SYSTEM_H +#include "Qt3DSEGLInfo.h" +#include "Qt3DSWindowSystem.h" +#include "nv_main/nv_main.h" + +namespace Q3DStudio { +struct SEGLWindowSystemImpl : public IWindowSystem +{ + SEGLInfo m_EGLInfo; + + virtual QSize GetWindowDimensions() + { + int w, h; + + eglQuerySurface(gEGLHandles[0].display, gEGLHandles[0].surface, EGL_WIDTH, &w); + eglQuerySurface(gEGLHandles[0].display, gEGLHandles[0].surface, EGL_HEIGHT, &h); + + return QSize(w, h); + } + virtual void SetWindowDimensions(const QSize &) {} + // For platforms that support it, we get the egl info for render plugins + // Feel free to return NULL. + virtual SEGLInfo *GetEGLInfo() + { + m_EGLInfo.display = gEGLHandles[0].display; + m_EGLInfo.surface = gEGLHandles[0].surface; + m_EGLInfo.context = gEGLHandles[0].context; + m_EGLInfo.config = gEGLHandles[0].config; + m_EGLInfo.nativewin = gEGLHandles[0].nativewin; + return &m_EGLInfo; + } + // on some systems we allow our default render target to be a offscreen buffer + // otherwise return 0; + virtual int GetDefaultRenderTargetID() { return 0; } + // returns the depth buffer bit count for the render window + // overwrite this one for your own needs + virtual int GetDepthBitCount() + { + EGLint depth = 16; +#ifdef _PLATFORM_USE_EGL + if (gEGLHandles[0].display && gEGLHandles[0].config) + eglGetConfigAttrib(gEGLHandles[0].display, gEGLHandles[0].config, EGL_DEPTH_SIZE, + &depth); +#endif + + return depth; + } +}; +}; + +#endif diff --git a/src/engine/Qt3DSPluginDLL.h b/src/engine/Qt3DSPluginDLL.h new file mode 100644 index 0000000..1ba7cf0 --- /dev/null +++ b/src/engine/Qt3DSPluginDLL.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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$ +** +****************************************************************************/ +//============================================================================== +// Includes +//============================================================================== +#pragma once +#include "Qt3DSBasicPluginDLL.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//============================================================================== +// Enums +//============================================================================== +// Texture format +typedef enum _ETEXTUREFORMAT { + ETEXTUREFORMAT_Unknown = 0, + ETEXTUREFORMAT_RGBA8, + ETEXTUREFORMAT_RGB8, + ETEXTUREFORMAT_RGB565, + ETEXTUREFORMAT_RGBA5551, + ETEXTUREFORMAT_Alpha8, + ETEXTUREFORMAT_Luminance8, + ETEXTUREFORMAT_LuminanceAlpha8, + ETEXTUREFORMAT_RGBA_DXT1, + ETEXTUREFORMAT_RGB_DXT1, + ETEXTUREFORMAT_RGBA_DXT3, + ETEXTUREFORMAT_RGBA_DXT5, +} ETEXTUREFORMAT; + +//============================================================================== +// Functions declarations +//============================================================================== + +//============================================================================== +/** + * Perform plugin initialization. + * @param inArgs string arguments from XIF arg parameter + * @return EDLLSTATUS_OK if initialization suceeds + */ +typedef long (*PROC_Initialize)(const char *inArgs); +Q_DECL_EXPORT long Initialize(const char *inArgs); + +//============================================================================== +/** + * Passes the current screen size and format to the plugin. + * Plugin should override with it's own desired settings. + * This affects the size and format of the allocated offscreen texture. + * When resources are allocated, SetAllocatedRenderInfo will be called to + * inform the plugin of the allocated resources + * @param ioWidth width + * @param ioHeight height + * @param ioTextureFormat See ETEXTUREFORMAT + */ +typedef void (*PROC_GetDesiredTextureSize)(long *ioWidth, long *ioHeight, + ETEXTUREFORMAT *ioTextureFormat); +Q_DECL_EXPORT void GetDesiredTextureSize(long *ioWidth, long *ioHeight, + ETEXTUREFORMAT *ioTextureFormat); + +//============================================================================== +/** + * Information about the current EGL environment. + * Useful if plugin wishes to switch EGLContext to manage it's own state. + * Optional + * @param inEGLDisplay pointer to EGLDisplay + * @param inEGLCurrentContext pointer to current EGLContext + * @param inEGLSurface pointer to EGLSurface + * @param inEGLConfig pointer to EGLConfig attributes + */ +typedef void (*PROC_SetEGLInfo)(void *inEGLDisplay, void *inEGLCurrentContext, void *inEGLSurface, + void *inEGLConfig); +Q_DECL_EXPORT void SetEGLInfo(void *inEGLDisplay, void *inEGLCurrentContext, + void *inEGLSurface, void *inEGLConfig); + +//============================================================================== +/** + * Render pulse whenever the runtime requires a frame from the plugin. + * Note that if plugin wishes to switch EGLContext, + * it should restore the previous EGLContext(obtained from SetEGLInfo) at the end of this + *function. + * @param inHostWidth width of the host rectangle + * @param inHostHeight height of the host rectangle + * @param inDrawTime current time in milliseconds + */ +typedef void (*PROC_Render)(long inHostWidth, long inHostHeight, long inDrawTime); +Q_DECL_EXPORT void Render(long inHostWidth, long inHostHeight, long inDrawTime); + +//============================================================================== +/** + * Perform plugin uninitialization. + * @return EDLLSTATUS_OK if successful + */ +typedef long (*PROC_Uninitialize)(); +Q_DECL_EXPORT long Uninitialize(); + +#ifdef __cplusplus +} +#endif diff --git a/src/engine/Qt3DSRenderRuntimeBinding.cpp b/src/engine/Qt3DSRenderRuntimeBinding.cpp new file mode 100644 index 0000000..4507c74 --- /dev/null +++ b/src/engine/Qt3DSRenderRuntimeBinding.cpp @@ -0,0 +1,1858 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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 "EnginePrefix.h" +#include "Qt3DSRenderRuntimeBindingImpl.h" +#include "Qt3DSSceneManager.h" +#include "Qt3DSIScene.h" +#include "Qt3DSRuntimeView.h" +#include "Qt3DSQmlEngine.h" +#include "Qt3DSRenderUIPLoader.h" +#include "Qt3DSPresentationFrameData.h" +#include "foundation/AutoDeallocatorAllocator.h" +#include "Qt3DSRenderSubpresentation.h" +#include "Qt3DSIScriptBridge.h" +#include "Qt3DSFileStream.h" +#include "Qt3DSDMPrefix.h" +#include "foundation/IOStreams.h" +#include "Qt3DSDMStringTable.h" +#include "Qt3DSDMXML.h" +#include "Qt3DSRenderBufferManager.h" +#include "foundation/SerializationTypes.h" +#include "Qt3DSRenderGraphObjectSerializer.h" +#include "Qt3DSRenderShaderCache.h" +#include "Qt3DSRenderImageBatchLoader.h" +#include "Qt3DSPresentation.h" + +#include "Qt3DSDLLManager.h" +#include "Qt3DSBasicPluginDLL.h" +#include "Qt3DSPluginDLL.h" +#include "Qt3DSRenderPlugin.h" +#include "foundation/FileTools.h" +#include "Qt3DSStateVisualBindingContextCommands.h" +#include "Qt3DSStateScriptContext.h" +#include "EventPollingSystem.h" +#include "EventSystem.h" +#include "Qt3DSApplication.h" +#include "Qt3DSMatrix.h" +#include "Qt3DSWindowSystem.h" +#if !defined (Q_OS_MACOS) +#include "Qt3DSEGLInfo.h" +#endif +#include "Qt3DSOffscreenRenderKey.h" +#include "Qt3DSOldNBustedRenderPlugin.h" +#include "Qt3DSRenderCustomMaterialSystem.h" +#include "foundation/Qt3DSPerfTimer.h" +#include "Qt3DSRenderBufferLoader.h" +#include "Qt3DSRenderRenderList.h" +#include "Qt3DSRenderPrefilterTexture.h" +#include "foundation/PoolingAllocator.h" +#include "q3dsqmlrender.h" + +#ifdef EA_PLATFORM_WINDOWS +#pragma warning(disable : 4355) +#endif + +using namespace qt3ds::render; +using eastl::make_pair; +using eastl::pair; +using qt3ds::runtime::IApplication; + +#ifndef _WIN32 +#define stricmp strcasecmp +#endif +namespace qt3ds { +namespace render { + qt3ds::foundation::MallocAllocator g_BaseAllocator; +} +} +namespace { +struct Qt3DSRenderScene; + +struct Qt3DSRenderSceneSubPresRenderer : public CSubPresentationRenderer +{ + Qt3DSRenderScene &m_Scene; + Qt3DSRenderSceneSubPresRenderer(Qt3DSRenderScene &inScene, IQt3DSRenderContext &inRenderContext, + SPresentation &inPresentation) + : CSubPresentationRenderer(inRenderContext, inPresentation) + , m_Scene(inScene) + { + } + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_RenderContext.GetAllocator()) + SOffscreenRenderFlags NeedsRender(const SOffscreenRendererEnvironment &inEnvironment, + QT3DSVec2 inPresScale, + const SRenderInstanceId instanceId) override; + void Render(const SOffscreenRendererEnvironment &inEnvironment, + NVRenderContext &inRenderContext, QT3DSVec2 inPresScale, + SScene::RenderClearCommand inClearBuffer, + const SRenderInstanceId instanceId) override; + void RenderWithClear(const SOffscreenRendererEnvironment &inEnvironment, + NVRenderContext &inRenderContext, QT3DSVec2 inPresScale, + SScene::RenderClearCommand inClearBuffer, QT3DSVec4 inClearColor, + const SRenderInstanceId instanceId) override; +}; + +struct SSceneLoadData +{ + NVAllocatorCallback &m_Allocator; + NVScopedRefCounted m_Data; + SPresentation *m_Presentation; + NVDataRef m_TranslatorData; + NVDataRef m_SceneGraphData; + eastl::vector m_Translators; + SPoolingAllocator m_AutoAllocator; + Q3DStudio::IPresentation *m_RuntimePresentation; + QT3DSI32 mRefCount; + + SSceneLoadData(NVAllocatorCallback &alloc) + : m_Allocator(alloc) + , m_Presentation(nullptr) + , m_AutoAllocator(alloc) + , m_RuntimePresentation(nullptr) + , mRefCount(0) + { + } + + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator) +}; + +struct Qt3DSRenderScene : public Q3DStudio::IScene +{ + SBindingCore &m_BindingCore; + NVScopedRefCounted m_Context; + NVScopedRefCounted m_LoadData; + // The scene graph gets allocated kind of on its own + // So do the smaller translation objects that translate TElement properties + // into the graph. + SPresentation *m_Presentation; + Q3DStudio::IPresentation *m_RuntimePresentation; + void *m_UserData; + TTranslatorDirytSet m_DirtySet; + CRegisteredString m_OffscreenRendererId; + IOffscreenRenderer *m_OffscreenRenderer; + CRegisteredString m_SubPresentationType; + nvvector m_GraphObjectList; + bool m_LoggedPickLastFrame; + NVRenderRect m_LastRenderViewport; + CRegisteredString m_PathSubPathType; + + Qt3DSRenderScene(SBindingCore &inBindingCore, IQt3DSRenderContext &inContext, + SSceneLoadData &inLoadData) + : m_BindingCore(inBindingCore) + , m_Context(inContext) + , m_LoadData(inLoadData) + , m_Presentation(inLoadData.m_Presentation) + , m_RuntimePresentation(inLoadData.m_RuntimePresentation) + , m_UserData(nullptr) + , m_DirtySet(inContext.GetAllocator(), "Qt3DSRenderScene::m_DirtySet") + , m_OffscreenRenderer(nullptr) + , m_SubPresentationType( + inContext.GetStringTable().RegisterStr(CSubPresentationRenderer::GetRendererName())) + , m_GraphObjectList(inContext.GetAllocator(), "Qt3DSDSRenderScene::m_GraphObjectList") + , m_LoggedPickLastFrame(false) + { + for (QT3DSU32 idx = 0, end = inLoadData.m_Translators.size(); idx < end; ++idx) { + m_DirtySet.insert(*inLoadData.m_Translators[idx]); + } + m_PathSubPathType = inContext.GetStringTable().RegisterStr("PathAnchorPoint"); + } + + virtual ~Qt3DSRenderScene() override + { + if (m_OffscreenRenderer) + m_Context->GetOffscreenRenderManager().ReleaseOffscreenRenderer(m_OffscreenRendererId); + m_OffscreenRenderer = nullptr; + if (m_Presentation && m_Presentation->m_Scene) { + for (SLayer *theLayer = m_Presentation->m_Scene->m_FirstChild; theLayer; + theLayer = static_cast(theLayer->m_NextSibling)) { + m_Context->GetRenderer().ReleaseLayerRenderResources(*theLayer, nullptr); + } + } + } + + qt3ds::NVAllocatorCallback &allocator() override { return m_LoadData->m_AutoAllocator; } + Q3DStudio::IPresentation &GetPresentation() override { return *m_RuntimePresentation; } + + bool preferKtx() const override + { + return m_Presentation->m_preferKTX; + } + + // Update really just adds objects to the dirty set + bool Update() + { + Q3DStudio::TElementList &theDirtyList = + m_RuntimePresentation->GetFrameData().GetDirtyList(); + for (int idx = 0, end = theDirtyList.GetCount(); idx < end; ++idx) { + Q3DStudio::TElement &theElement = *theDirtyList[idx]; + Qt3DSTranslator *theTranslator = + reinterpret_cast(theElement.GetAssociation()); + if (!theTranslator && theElement.GetType() == m_PathSubPathType) { + Q3DStudio::TElement *theParent = theElement.GetParent(); + if (theParent) { + theTranslator = reinterpret_cast(theParent->GetAssociation()); + // The path translator responds to anchor point changes as well as its own data + // changes. + if (theTranslator + && theTranslator->RenderObject().m_Type != GraphObjectTypes::PathSubPath) + theTranslator = nullptr; + } + } + if (theTranslator) + m_DirtySet.insert(*theTranslator); + } + return m_DirtySet.size() > 0; + } + + void TransferDirtyProperties() + { + if (m_Presentation) { + for (QT3DSU32 idx = 0, end = m_DirtySet.size(); idx < end; ++idx) { + QT3DS_ASSERT(m_DirtySet.size() == end); + m_DirtySet[idx]->OnElementChanged(*m_Presentation, *m_Context, + *m_RuntimePresentation); + } + m_DirtySet.clear(); + } + } + + bool PrepareForRender() + { + TransferDirtyProperties(); + m_LastRenderViewport = m_Context->GetRenderList().GetViewport(); + if (m_Presentation && m_Presentation->m_Scene) { + NVRenderRect theViewportSize(m_LastRenderViewport); + return m_Presentation->m_Scene->PrepareForRender( + QT3DSVec2(QT3DSF32(theViewportSize.m_Width), QT3DSF32(theViewportSize.m_Height)), + *m_Context); + } + return false; + } + + void Render() + { + if (m_Presentation && m_Presentation->m_Scene) { + NVRenderRect theViewportSize(m_LastRenderViewport); + m_Presentation->m_Scene->Render( + QT3DSVec2(QT3DSF32(theViewportSize.m_Width), QT3DSF32(theViewportSize.m_Height)), + *m_Context, SScene::DoNotClear); + } + } + + // Note that we do not need to call WindowToPresentation on the mouse coordinates because they + // are specifically + // supposed to be the return values from getMousePosition which applies that transformation. We + // do, however need + // to reverse part of this transformation; whatever part happens after + // m_Context->GetMousePickMouseCoords + Q3DStudio::TElement *UserPick(float mouseX, float mouseY) + { + // Note that the pick code below only calls GetMousePickMouseCoords + // while windowToPresentation subtracts the window positional offset from + // the mouse position. + // Thus we have to add it back. + QT3DSVec2 mousePos(mouseX + m_LastRenderViewport.m_X, mouseY + m_LastRenderViewport.m_Y); + + Qt3DSRenderPickResult thePickResult = m_Context->GetRenderer().Pick( + *m_Presentation->m_Scene->m_FirstChild, m_Context->GetMousePickViewport() + // GetMousePickMouseCoords is called by the renderer to setup the pick frame. + // This is so that the presentation's lastMouseX and lastMouseY variables are correctly + // setup. + , + mousePos, true, true); + + if (thePickResult.m_HitObject != nullptr) { + SModel *theHitModel = + static_cast(const_cast(thePickResult.m_HitObject)); + return &Qt3DSTranslator::GetTranslatorFromGraphNode(*theHitModel)->Element(); + } + return nullptr; + } + + virtual Option FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY, + NVDataRef inMapperElements, + Q3DStudio::FacePositionPlanes::Enum inPlane) + { + if (inElement.GetBelongedPresentation() != this->m_RuntimePresentation + && inMapperElements.size() == 0) { + return Empty(); + } + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement.GetAssociation()); + if (theTranslator == nullptr) + return Empty(); + bool isValidPickObject = + GraphObjectTypes::IsNodeType(theTranslator->m_RenderObject->m_Type); + if (isValidPickObject == false) + return Empty(); + SNode &theNode = static_cast(*theTranslator->m_RenderObject); + NVBounds3 theBounds = GetNodeLocalBoundingBox(&inElement, false); + // See commens in UserPick + QT3DSVec2 mousePos(mouseX + m_LastRenderViewport.m_X, mouseY + m_LastRenderViewport.m_Y); + eastl::vector theMapperObjects(inMapperElements.size()); + for (QT3DSU32 idx = 0, end = inMapperElements.size(); idx < end; ++idx) { + Qt3DSTranslator *theMapperTranslator = + reinterpret_cast(inMapperElements[idx]->GetAssociation()); + SGraphObject *theMapperObject = nullptr; + if (theMapperTranslator) { + theMapperObject = theMapperTranslator->m_RenderObject; + } + if (theMapperObject == nullptr) { + QT3DS_ASSERT(false); + } else { + theMapperObjects[idx] = theMapperObject; + } + } + qt3ds::render::SBasisPlanes::Enum thePlane(qt3ds::render::SBasisPlanes::XY); + switch (inPlane) { + case Q3DStudio::FacePositionPlanes::XY: + thePlane = qt3ds::render::SBasisPlanes::XY; + break; + case Q3DStudio::FacePositionPlanes::YZ: + thePlane = qt3ds::render::SBasisPlanes::YZ; + break; + case Q3DStudio::FacePositionPlanes::XZ: + thePlane = qt3ds::render::SBasisPlanes::XZ; + break; + } + if (theBounds.isEmpty() == false) { + return m_Context->GetRenderer().FacePosition( + theNode, theBounds, theNode.m_GlobalTransform, m_Context->GetMousePickViewport(), + mousePos, NVDataRef(theMapperObjects.data(), + QT3DSU32(theMapperObjects.size())), thePlane); + } + return Empty(); + } + + void Pick(Q3DStudio::SPickFrame &ioPickFrame) + { + // Presentation's m_Hide can disable rendering + bool wasPickLoggedLastFrame = m_LoggedPickLastFrame; + m_LoggedPickLastFrame = false; + if (ioPickFrame.m_InputFrame.m_PickValid) { + // If we have not already found a valid pick on a previous layer + if (!ioPickFrame.m_ResultValid && m_Presentation && m_Presentation->m_Scene + && m_Presentation->m_Scene->m_FirstChild) { + Qt3DSRenderPickResult thePickResult = m_Context->GetRenderer().Pick( + *m_Presentation->m_Scene->m_FirstChild, m_Context->GetMousePickViewport() + // GetMousePickMouseCoords is called by the renderer to setup the pick frame. + // This is so that the presentation's lastMouseX and lastMouseY variables are + // correctly setup. + , + m_Context->GetMousePickMouseCoords( + QT3DSVec2(ioPickFrame.m_InputFrame.m_PickX, ioPickFrame.m_InputFrame.m_PickY)), + true); + if (thePickResult.m_HitObject != nullptr) { + SModel *theHitModel = static_cast( + const_cast(thePickResult.m_HitObject)); + ioPickFrame.m_Model = + &Qt3DSTranslator::GetTranslatorFromGraphNode(*theHitModel)->Element(); + // I don't think local hit is used any more, but not sure. If they are used, + // then the code below is probably wrong. + ioPickFrame.m_LocalHit[0] = thePickResult.m_LocalUVCoords.x; + ioPickFrame.m_LocalHit[1] = thePickResult.m_LocalUVCoords.y; + ioPickFrame.m_SquaredDistance = thePickResult.m_CameraDistanceSq; + ioPickFrame.m_ResultValid = true; + if (wasPickLoggedLastFrame == false) { + m_LoggedPickLastFrame = true; + Q3DStudio::IPresentation *thePresentation = + ioPickFrame.m_Model->GetBelongedPresentation(); + IApplication &theRuntime = thePresentation->GetApplication(); + // We are picking against the previous frame of information. + qCInfo(TRACE_INFO, "Model Picked: %s on frame %d", + theHitModel->m_Id.c_str(), + theRuntime.GetFrameCount() - 1); + } + } else { + // The scene is always picked if it is pickable; nothing else really makes + // sense. + Qt3DSTranslator *theTranslator = + Qt3DSTranslator::GetTranslatorFromGraphNode(*m_Presentation->m_Scene); + + if (theTranslator) { + ioPickFrame.m_Model = &theTranslator->Element(); + // I don't think local hit is used any more, but not sure. If they are + // used, then the code below is probably wrong. + ioPickFrame.m_LocalHit[0] = ioPickFrame.m_InputFrame.m_PickX + / m_Presentation->m_PresentationDimensions.x; + ioPickFrame.m_LocalHit[1] = 1.0f + - ioPickFrame.m_InputFrame.m_PickY + / m_Presentation->m_PresentationDimensions.y; + ioPickFrame.m_SquaredDistance = 0; + ioPickFrame.m_ResultValid = true; + } + } + } + } + } + + void SetUserData(void *inUserData) override { m_UserData = inUserData; } + void *GetUserData() override { return m_UserData; } + + // Unfortunately, you should expect the node to be dirty at this point so we may need to force + // an update + void CalculateGlobalTransform(Q3DStudio::TElement *inElement, + Q3DStudio::RuntimeMatrix &outTransform) override + { + if (inElement == nullptr) { + QT3DS_ASSERT(false); + return; + } + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement->GetAssociation()); + if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) { + Update(); + TransferDirtyProperties(); + SNode *theNode = static_cast(&theTranslator->RenderObject()); + // Ensure the node stays dirty + bool wasDirty = theNode->m_Flags.IsDirty(); + theNode->CalculateGlobalVariables(); + theNode->m_Flags.SetDirty(wasDirty); + memCopy(outTransform.m_Data, theNode->m_GlobalTransform.front(), sizeof(QT3DSMat44)); + } else { + qCCritical(INVALID_OPERATION, "Calculate global transform called on invalide object"); + QT3DS_ASSERT(false); + } + } + + void SetLocalTransformMatrix(Q3DStudio::TElement *inElement, + const Q3DStudio::RuntimeMatrix &inTransform) override + { + if (inElement == nullptr) { + QT3DS_ASSERT(false); + return; + } + + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement->GetAssociation()); + if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) { + SNode *theNode = static_cast(&theTranslator->RenderObject()); + QT3DSMat44 transform; + memCopy(transform.front(), inTransform.m_Data, sizeof(QT3DSMat44)); + theNode->SetLocalTransformFromMatrix(transform); + theNode->MarkDirty(NodeTransformDirtyFlag::TransformIsDirty); + } + } + + void EnsureNodeIsUpToDate(SNode &inNode, bool inIncludeChildren) + { + bool wasDirty = inNode.m_Flags.IsDirty(); + if (wasDirty) { + inNode.CalculateGlobalVariables(); + inNode.m_Flags.SetDirty(wasDirty); + if (inIncludeChildren) { + for (SNode *theChild = inNode.m_FirstChild; theChild; + theChild = theChild->m_NextSibling) + EnsureNodeIsUpToDate(*theChild, inIncludeChildren); + } + } + } + + NVBounds3 GetNodeLocalBoundingBox(Q3DStudio::TElement *inElement, bool inSelfOnly) + { + NVBounds3 retval(NVBounds3::empty()); + if (inElement == nullptr) { + QT3DS_ASSERT(false); + return retval; + } + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement->GetAssociation()); + if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) { + Update(); + TransferDirtyProperties(); + SNode *theNode = static_cast(&theTranslator->RenderObject()); + bool theIncludeChildren = !inSelfOnly; + EnsureNodeIsUpToDate(*theNode, theIncludeChildren); + IBufferManager &theBufferManager(m_Context->GetBufferManager()); + return theNode->GetBounds(theBufferManager, m_Context->GetPathManager(), + theIncludeChildren); + } else { + qCCritical(INVALID_OPERATION, "GetBoundingBox called on invalid object"); + QT3DS_ASSERT(false); + } + return retval; + } + + static void Assign(Q3DStudio::CBoundingBox &lhs, NVBounds3 &rhs) + { + lhs.m_Min.m_X = rhs.minimum.x; + lhs.m_Min.m_Y = rhs.minimum.y; + lhs.m_Min.m_Z = rhs.minimum.z; + + lhs.m_Max.m_X = rhs.maximum.x; + lhs.m_Max.m_Y = rhs.maximum.y; + lhs.m_Max.m_Z = rhs.maximum.z; + } + + Q3DStudio::CBoundingBox GetBoundingBox(Q3DStudio::TElement *inElement, bool inSelfOnly) override + { + Q3DStudio::CBoundingBox retval; + retval.SetEmpty(); + NVBounds3 theLocalBox = GetNodeLocalBoundingBox(inElement, inSelfOnly); + if (theLocalBox.isEmpty() == false) { + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement->GetAssociation()); + if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) { + SNode *theNode = static_cast(&theTranslator->RenderObject()); + theLocalBox.transform(theNode->m_GlobalTransform); + Assign(retval, theLocalBox); + // Left handed nodes need to return values in their space, not in the global space + // This is a hack fix due to a bug. + if (theNode->m_Flags.IsLeftHanded()) { + eastl::swap(retval.m_Min.m_Z, retval.m_Max.m_Z); + retval.m_Min.m_Z *= -1; + retval.m_Max.m_Z *= -1; + } + } + } + return retval; + } + + Q3DStudio::CBoundingBox GetLocalBoundingBox(Q3DStudio::TElement *inElement, + bool inSelfOnly) override + { + Q3DStudio::CBoundingBox retval; + retval.SetEmpty(); + if (inElement == nullptr) { + QT3DS_ASSERT(false); + return retval; + } + NVBounds3 theLocalBounds = GetNodeLocalBoundingBox(inElement, inSelfOnly); + if (theLocalBounds.isEmpty() == false) + Assign(retval, theLocalBounds); + + return retval; + } + + Q3DStudio::SCameraRect GetCameraBounds(Q3DStudio::TElement &inElem) override + { + Qt3DSTranslator *theTranslator = reinterpret_cast(inElem.GetAssociation()); + if (theTranslator && theTranslator->m_RenderObject) { + Option theRectOpt = + m_Context->GetRenderer().GetCameraBounds(*theTranslator->m_RenderObject); + if (theRectOpt.hasValue()) { + qt3ds::render::SCuboidRect theRect(*theRectOpt); + return Q3DStudio::SCameraRect(theRect.m_Left, theRect.m_Top, theRect.m_Right, + theRect.m_Bottom); + } + } + return Q3DStudio::SCameraRect(); + } + + void PositionToScreen(Q3DStudio::TElement &inElement, QT3DSVec3 &inPos, QT3DSVec3 &outScreen) override + { + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement.GetAssociation()); + if (theTranslator && theTranslator->m_RenderObject) { + SNode *theNode = reinterpret_cast(theTranslator->m_RenderObject); + QT3DSVec3 thePos = theNode->m_GlobalTransform.transform(inPos); + outScreen = m_Context->GetRenderer().ProjectPosition(*theNode, thePos); + } + } + + void ScreenToPosition(Q3DStudio::TElement &inElement, QT3DSVec3 &inScreen, QT3DSVec3 &outPos) override + { + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement.GetAssociation()); + if (theTranslator && theTranslator->m_RenderObject) { + SNode *theNode = reinterpret_cast(theTranslator->m_RenderObject); + QT3DSVec3 objPos = theNode->GetGlobalPos(); + outPos = m_Context->GetRenderer().UnprojectWithDepth(*(theNode), objPos, inScreen); + } + } + + static void GenerateBsdfMipmaps(SImage *theImage, const unsigned char *inBuffer, + Q3DStudio::INT32 inBufferLength, Q3DStudio::INT32 inWidth, + Q3DStudio::INT32 inHeight, + qt3ds::render::NVRenderTextureFormats::Enum inFormat, + IQt3DSRenderContext *theContext) + { + NVRenderTextureFormats::Enum destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F; + + Qt3DSRenderPrefilterTexture *theBSDFMipMap = theImage->m_TextureData.m_BSDFMipMap; + if (theBSDFMipMap == nullptr) { + theBSDFMipMap = Qt3DSRenderPrefilterTexture::Create( + &theContext->GetRenderContext(), inWidth, inHeight, + *theImage->m_TextureData.m_Texture, destFormat, theContext->GetFoundation()); + theImage->m_TextureData.m_BSDFMipMap = theBSDFMipMap; + } + + if (theBSDFMipMap) + theBSDFMipMap->Build((void *)(inBuffer), inBufferLength, inFormat); + } + + // This could cause some significant drama. + void SetTextureData(Q3DStudio::TElement *inElement, const unsigned char *inBuffer, + Q3DStudio::INT32 inBufferLength, Q3DStudio::INT32 inWidth, + Q3DStudio::INT32 inHeight, + qt3ds::render::NVRenderTextureFormats::Enum inFormat, + Q3DStudio::INT32 inHasTransparency) override + { + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement->GetAssociation()); + if (theTranslator && theTranslator->GetUIPType() == GraphObjectTypes::Image) { + SImage *theImage = static_cast(&theTranslator->RenderObject()); + // Attempt to resolve the image's path + if (!theImage->m_TextureData.m_Texture) { + if (theImage->m_ImagePath.IsValid()) + theImage->m_TextureData = m_Context->GetBufferManager().LoadRenderImage( + theImage->m_ImagePath, false, + theImage->m_MappingMode == ImageMappingModes::LightProbe); + } + // Here we go, updating the texture. + if (theImage->m_TextureData.m_Texture) { + + if (theImage->m_MappingMode == ImageMappingModes::LightProbe) { + // theImage->m_TextureData.m_Texture->GenerateMipmaps(); + GenerateBsdfMipmaps(theImage, inBuffer, inBufferLength, inWidth, inHeight, + inFormat, m_Context); + } else + theImage->m_TextureData.m_Texture->SetTextureData( + NVDataRef((QT3DSU8 *)inBuffer, (QT3DSU32)inBufferLength), 0, inWidth, + inHeight, inFormat); + + if (inHasTransparency >= 0) { + bool hasTransparency = inHasTransparency ? true : false; + theImage->m_TextureData.m_TextureFlags.SetHasTransparency(hasTransparency); + m_Context->GetBufferManager().SetImageHasTransparency(theImage->m_ImagePath, + hasTransparency); + } + theImage->m_Flags.SetDirty(true); + } + } else { + qCCritical(INVALID_OPERATION, "SetTextureData called on object that is not an image"); + QT3DS_ASSERT(false); + } + } + + bool CreateOrSetMeshData(const char *inPathStr, unsigned char *vertData, + unsigned int numVerts, unsigned int vertStride, + unsigned int *indexData, unsigned int numIndices, + qt3ds::NVBounds3 &objBounds) override + { + SRenderMesh *theMesh = nullptr; + + if (inPathStr && vertData && indexData) { + theMesh = m_Context->GetBufferManager().CreateMesh( + inPathStr, vertData, numVerts, vertStride, indexData, numIndices, objBounds); + } else { + qCCritical(INVALID_OPERATION, + "CreateOrSetMeshData was not supplied necessary buffers or object path"); + } + + return (theMesh != nullptr); + } + + Q3DStudio::STextSizes MeasureText(Q3DStudio::TElement *inElement, const char *inTextStr) override + { + Qt3DSTranslator *theTranslator = + reinterpret_cast(inElement->GetAssociation()); + Q3DStudio::STextSizes retval; + if (theTranslator && theTranslator->GetUIPType() == GraphObjectTypes::Text) { + if (inElement->IsDirty()) { + theTranslator->OnElementChanged(*m_Presentation, *m_Context, + *m_RuntimePresentation); + } + SText *theText = static_cast(&theTranslator->RenderObject()); + if (theText) { + + STextDimensions theDimensions = + m_Context->GetTextRenderer()->MeasureText(*theText, 1.0f, inTextStr); + + retval = Q3DStudio::STextSizes(Q3DStudio::INT32(theDimensions.m_TextWidth), + Q3DStudio::INT32(theDimensions.m_TextHeight)); + } + } else { + qCCritical(INVALID_OPERATION, "MeasureText called on object that is not text"); + QT3DS_ASSERT(false); + + } + return retval; + } + + Q3DStudio::STextSizes GetPresentationDesignDimensions() override + { + if (m_Presentation) { + return Q3DStudio::STextSizes( + static_cast(m_Presentation->m_PresentationDimensions.x), + static_cast(m_Presentation->m_PresentationDimensions.y)); + } + QT3DS_ASSERT(false); + return Q3DStudio::STextSizes(); + } + + virtual Q3DStudio::SMousePosition + WindowToPresentation(const Q3DStudio::SMousePosition &inWindowCoords) override + { + // If there aren't any rotations, then account for the difference in width/height of the + // presentation and the window + QT3DSVec2 theCoords = m_Context->GetMousePickMouseCoords( + QT3DSVec2(QT3DSF32(inWindowCoords.m_X), QT3DSF32(inWindowCoords.m_Y))); + theCoords.x -= m_LastRenderViewport.m_X; + // Note that the mouse Y is reversed. Thus a positive offset of the viewport will reduce + // the mouse value. + theCoords.y -= m_LastRenderViewport.m_Y; + return Q3DStudio::SMousePosition(theCoords.x, theCoords.y); + } + + qt3ds::foundation::CRegisteredString RegisterStr(const char *inStr) override + { + return m_Context->GetStringTable().RegisterStr(inStr); + } + + void RegisterOffscreenRenderer(const char *inKey) override + { + m_OffscreenRenderer = QT3DS_NEW(m_Context->GetAllocator(), Qt3DSRenderSceneSubPresRenderer)( + *this, *m_Context, *m_Presentation); + m_OffscreenRendererId = m_Context->GetStringTable().RegisterStr(inKey); + m_Context->GetOffscreenRenderManager().RegisterOffscreenRenderer(m_OffscreenRendererId, + *m_OffscreenRenderer); + } + + template + void forAllObjects(nvvector &vec, GraphObjectTypes::Enum type, C callable) + { + nvvector::iterator it = vec.begin(); + nvvector::iterator end = vec.end(); + while (it != end) { + if ((*it)->m_Type == type) + callable(static_cast(*it)); + ++it; + } + } + + void PostLoadStep() + { + IBufferManager &mgr = m_Context->GetBufferManager(); + forAllObjects(m_GraphObjectList, GraphObjectTypes::Image, [&mgr](SImage *image){ + if (image->m_ImagePath.IsValid() && qt3ds::runtime::isImagePath( + image->m_ImagePath.c_str())) { + const bool ibl = image->m_MappingMode == ImageMappingModes::LightProbe; + image->m_LoadedTextureData = mgr.CreateReloadableImage(image->m_ImagePath, + false, ibl); + image->m_LoadedTextureData->m_callbacks.push_back(image); + } + }); + } + + void Release() override { NVDelete(m_Context->GetAllocator(), this); } +}; + +SOffscreenRenderFlags +Qt3DSRenderSceneSubPresRenderer::NeedsRender(const SOffscreenRendererEnvironment &inEnvironment, + QT3DSVec2 inPresScale, + const SRenderInstanceId instanceId) +{ + m_Scene.TransferDirtyProperties(); + return CSubPresentationRenderer::NeedsRender(inEnvironment, inPresScale, instanceId); +} + +void Qt3DSRenderSceneSubPresRenderer::Render(const SOffscreenRendererEnvironment &inEnvironment, + NVRenderContext &inRenderContext, + QT3DSVec2 inPresScale, + SScene::RenderClearCommand inClearBuffer, + const SRenderInstanceId instanceId) +{ + CSubPresentationRenderer::Render(inEnvironment, inRenderContext, inPresScale, inClearBuffer, + instanceId); +} + +void Qt3DSRenderSceneSubPresRenderer::RenderWithClear( + const SOffscreenRendererEnvironment &inEnvironment, + NVRenderContext &inRenderContext, QT3DSVec2 inPresScale, + SScene::RenderClearCommand inClearBuffer, QT3DSVec4 inClearColor, + const SRenderInstanceId id) +{ + CSubPresentationRenderer::RenderWithClear(inEnvironment, inRenderContext, + inPresScale, inClearBuffer, + inClearColor, id); +} + +////////////////////////////////////////////////////////////////// +// Scene Manager +////////////////////////////////////////////////////////////////// + +struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager, + public Q3DStudio::ISceneBinaryLoader +{ + typedef nvhash_map TStrBoolMap; + + NVScopedRefCounted m_Context; + nvvector> m_Scenes; + nvvector> m_RenderPlugins; + Q3DStudio::INT32 m_ViewWidth; + Q3DStudio::INT32 m_ViewHeight; + Q3DStudio::SPickFrame m_PickFrame; + NVDataRef m_StrTableData; + // The boolean is to mark transparent images and ibl images + nvvector>> m_SourcePaths; + eastl::hash_set m_SourcePathSet; + + Qt3DSRenderScene *m_LastRenderedScene; + Q3DStudio::IWindowSystem &m_WindowSystem; + Mutex m_LoadingScenesMutex; + eastl::vector> m_LoadingScenes; + CRegisteredString m_ProjectDir; + CRegisteredString m_BinaryDir; + bool m_ProjectInitialized; + QT3DSI32 mRefCount; + + Qt3DSRenderSceneManager(SBindingCore &ctx, Q3DStudio::IWindowSystem &inWindowSystem) + : m_Context(ctx) + , m_Scenes(ctx.GetAllocator(), "Qt3DSRenderSceneManager::m_Scenes") + , m_RenderPlugins(ctx.GetAllocator(), "Qt3DSRenderSceneManager::m_RenderPlugins") + , m_ViewWidth(0) + , m_ViewHeight(0) + , m_SourcePaths(ctx.GetAllocator(), "Qt3DSRenderSceneManager::m_SourcePaths") + , m_LastRenderedScene(nullptr) + , m_WindowSystem(inWindowSystem) + , m_LoadingScenesMutex(ctx.GetAllocator()) + , m_ProjectInitialized(false) + , mRefCount(0) + { + memZero(&m_PickFrame, sizeof(m_PickFrame)); + } + virtual ~Qt3DSRenderSceneManager() override + { + for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end; ++idx) + m_Scenes[idx].second->Release(); + m_Scenes.clear(); + } + + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Context->GetAllocator()) + + static QT3DSU32 GetFileTag() + { + const char *fileTag = "Qt3DSS"; + const QT3DSU32 *theTagPtr = reinterpret_cast(fileTag); + return *theTagPtr; + } + + void FinalizeScene(Q3DStudio::IPresentation &inPresentation, Qt3DSRenderScene &inScene) + { + inPresentation.SetScene(&inScene); + if (m_ProjectInitialized == false) { + m_ProjectInitialized = true; + // For QT3DS-3353 assume project fonts are in a subdirectory relative to presentation. + QString projectFontDir = inPresentation.getProjectPath() + QStringLiteral("/fonts"); + if (m_Context->m_Context->GetTextRenderer()) { + m_Context->m_Context->GetTextRenderer()->AddProjectFontDirectory( + projectFontDir.toUtf8().data()); + } + if (m_Context->m_Context->getDistanceFieldRenderer()) { + m_Context->m_Context->getDistanceFieldRenderer()->AddProjectFontDirectory( + projectFontDir.toUtf8().data()); + } + eastl::string theBinaryPath(inPresentation.GetFilePath().toLatin1().constData()); + qt3ds::foundation::CFileTools::AppendDirectoryInPathToFile(theBinaryPath, "binary"); + eastl::string theBinaryDir(theBinaryPath); + qt3ds::foundation::CFileTools::GetDirectory(theBinaryDir); + if (m_Context->m_WriteOutShaderCache) + qt3ds::foundation::CFileTools::CreateDir(theBinaryDir.c_str()); + } + inScene.m_RuntimePresentation = &inPresentation; + m_Scenes.push_back(make_pair(&inPresentation, &inScene)); + Qt3DSTranslator::AssignUserData(inPresentation, *inScene.m_Presentation); + } + + static const char *GetBinaryExtension() { return "uibsg"; } + + struct SPluginInstanceTableProvider : public Q3DStudio::IScriptTableProvider + { + IRenderPluginInstance &m_Instance; + SPluginInstanceTableProvider(IRenderPluginInstance &ins) + : m_Instance(ins) + { + } + void CreateTable(script_State *inState) override { m_Instance.CreateScriptProxy(inState); } + }; + + void InitializeTranslator(Qt3DSTranslator &inTranslator, Q3DStudio::IScriptBridge &inBridge) + { + if (inTranslator.m_RenderObject->m_Type == GraphObjectTypes::RenderPlugin) { + SRenderPlugin &theRenderPlugin = + static_cast(*inTranslator.m_RenderObject); + IRenderPluginInstance *thePluginInstance = + m_Context->m_Context->GetRenderPluginManager().GetOrCreateRenderPluginInstance( + theRenderPlugin.m_PluginPath, &theRenderPlugin); + if (thePluginInstance) { + SPluginInstanceTableProvider theProvider(*thePluginInstance); + inBridge.SetTableForElement(*inTranslator.m_Element, theProvider); + } + } + } + + struct SResolver : public qt3ds::render::IUIPReferenceResolver + { + IStringTable &m_StringTable; + Q3DStudio::IUIPParser &m_Parser; + SResolver(IStringTable &strt, Q3DStudio::IUIPParser &p) + : m_StringTable(strt) + , m_Parser(p) + { + } + + CRegisteredString ResolveReference(CRegisteredString inStart, + const char *inReference) override + { + eastl::string theResolvedId = m_Parser.ResolveReference(inStart, inReference); + if (theResolvedId.size()) + return m_StringTable.RegisterStr(theResolvedId.c_str()); + return CRegisteredString(); + } + }; + + Q3DStudio::IScene *LoadScene(Q3DStudio::IPresentation *inPresentation, + Q3DStudio::IUIPParser *inParser, + Q3DStudio::IScriptBridge &inBridge, + const qt3ds::Q3DSVariantConfig &variantConfig) override + { + // We have to initialize the tags late so that we can load flow data before adding anything + // to the string table. + Qt3DSTranslator::InitializePointerTags(m_Context->m_RenderContext->GetStringTable()); + NVScopedRefCounted theScene = + QT3DS_NEW(m_Context->GetAllocator(), SSceneLoadData)(m_Context->GetAllocator()); + Qt3DSRenderScene *theIScene = nullptr; + if (inParser) { + QString thePath(inPresentation->GetFilePath()); + QFileInfo fileInfo(thePath); + TIdObjectMap theObjMap(m_Context->GetAllocator(), "LoadScene::theObjMap"); + SResolver theResolver(m_Context->m_CoreContext->GetStringTable(), *inParser); + + theScene->m_Presentation = IUIPLoader::LoadUIPFile( + inParser->GetDOMReader(), + fileInfo.absoluteFilePath().toLatin1().constData(), + inParser->GetMetaData(), + m_Context->m_CoreContext->GetStringTable(), + m_Context->m_RenderContext->GetFoundation(), + theScene->m_AutoAllocator, theObjMap, + m_Context->m_Context->GetBufferManager(), + m_Context->m_Context->GetEffectSystem(), + fileInfo.path().toLatin1().constData(), + m_Context->m_Context->GetRenderPluginManager(), + m_Context->m_Context->GetCustomMaterialSystem(), + m_Context->m_Context->GetDynamicObjectSystem(), + m_Context->m_Context->GetPathManager(), &theResolver, + variantConfig, false); + if (!theScene->m_Presentation) { + QT3DS_ASSERT(false); + return nullptr; + } + + NVConstDataRef theSourcePathData(inParser->GetSourcePaths()); + const QVector slideSourcePaths = inParser->GetSlideSourcePaths(); + IBufferManager &theManager(m_Context->m_Context->GetBufferManager()); + // List of image paths to be loaded in parallel at the end. + eastl::vector theSourcePathList; + eastl::vector iblList; + for (QT3DSU32 idx = 0, end = theSourcePathData.size(); idx < end; ++idx) { + const eastl::string &theValue = theSourcePathData[idx]; + CRegisteredString theSourcePath = + m_Context->m_CoreContext->GetStringTable().RegisterStr(theValue.c_str()); + size_t theValueSize = theValue.size(); + if (theValueSize > 3) { + CRegisteredString theObjectPath = theSourcePath; + if (qt3ds::runtime::isImagePath(theValue.c_str())) { + // load only images not on any slide + if (!theManager.isReloadableResourcesEnabled() || + !slideSourcePaths.contains(QString::fromLatin1(theValue.c_str()))) { + theManager.SetImageTransparencyToFalseIfNotSet(theObjectPath); + bool ibl = inParser->isIblImage(theObjectPath.c_str()); + bool transparent = theManager.GetImageHasTransparency(theObjectPath); + if (m_SourcePathSet.insert(theSourcePath).second) { + + m_SourcePaths.push_back(eastl::make_pair(theSourcePath, + eastl::make_pair(transparent, ibl))); + } + if (ibl) + iblList.push_back(theObjectPath); + else + theSourcePathList.push_back(theObjectPath); + + } + } else if (theValue.find(".mesh") != eastl::string::npos) { + theManager.LoadMesh(theObjectPath); + } + } + } + + // Fire off parallel loading of the source paths + QT3DSU64 imageBatchId = m_Context->m_Context->GetImageBatchLoader().LoadImageBatch( + toConstDataRef(theSourcePathList.data(), theSourcePathList.size()), + CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext() + .GetRenderContextType(), + theScene->m_Presentation->m_preferKTX, false); + QT3DSU64 iblImageBatchId = m_Context->m_Context->GetImageBatchLoader().LoadImageBatch( + toConstDataRef(iblList.data(), iblList.size()), + CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext() + .GetRenderContextType(), + theScene->m_Presentation->m_preferKTX, true); + m_Context->m_Context->GetImageBatchLoader().BlockUntilLoaded( + static_cast(imageBatchId)); + m_Context->m_Context->GetImageBatchLoader().BlockUntilLoaded( + static_cast(iblImageBatchId)); + + theIScene = QT3DS_NEW(m_Context->GetAllocator(), + Qt3DSRenderScene)(*m_Context, *m_Context->m_Context, *theScene); + // Now we need to associate the presentation with everything else. + NVAllocatorCallback &translatorAllocator = theScene->m_AutoAllocator; + for (TIdObjectMap::iterator iter = theObjMap.begin(), end = theObjMap.end(); + iter != end; ++iter) { + theIScene->m_GraphObjectList.push_back(iter->second); + Q3DStudio::SElementAndType theElement = + inParser->GetElementForID(iter->first.c_str()); + if (theElement.m_Element + && theElement.m_Type != Q3DStudio::UIPElementTypes::Unknown) { + Qt3DSTranslator *theTranslator = Qt3DSTranslator::CreateTranslatorForElement( + *theElement.m_Element, *iter->second, translatorAllocator); + if (theTranslator) { + theIScene->m_DirtySet.insert(*theTranslator); + InitializeTranslator(*theTranslator, inBridge); + } + } + } + theIScene->PostLoadStep(); + } else { + // Binary load path is quite different than normal load path and + // nothing else will load here. + QT3DS_ASSERT(false); + } + if (inPresentation && theIScene) + FinalizeScene(*inPresentation, *theIScene); + return theIScene; + } + + // threadsafe + // Can be called from any thread + bool GetBinaryLoadFileName(eastl::string &inPresentationFilename, + eastl::string &outResult) override + { + eastl::string theBinaryPath(inPresentationFilename.c_str()); + qt3ds::foundation::CFileTools::AppendDirectoryInPathToFile(theBinaryPath, "binary"); + qt3ds::foundation::CFileTools::SetExtension( + theBinaryPath, GetBinaryExtension()); // uibb: short for ui binary binding + outResult = theBinaryPath; + return true; + } + + // threadsafe + // returns a handle to the loaded object. Return value of zero means error. + qt3ds::QT3DSU32 LoadSceneStage1(CRegisteredString inPresentationDirectory, + qt3ds::render::ILoadedBuffer &inData) override + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load Scene Graph Stage 1"); + NVDataRef theLoadedData(inData.Data()); + SDataReader theReader(theLoadedData.begin(), theLoadedData.end()); + + QT3DSU32 theFileSig = theReader.LoadRef(); + QT3DSU32 theBinaryVersion = theReader.LoadRef(); + QT3DSU32 theDataSectionSize = QT3DSU32(theReader.m_EndPtr - theReader.m_CurrentPtr); + + if (theFileSig != GetFileTag() + || theBinaryVersion != SGraphObject::GetSceneGraphBinaryVersion()) { + QT3DS_ASSERT(false); + return 0; + } + QT3DSU32 theLoadingSceneIndex = 0; + SSceneLoadData *theScene; + { + Mutex::ScopedLock __locker(m_LoadingScenesMutex); + theLoadingSceneIndex = QT3DSU32(m_LoadingScenes.size()) + 1; + m_LoadingScenes.push_back( + QT3DS_NEW(m_Context->GetAllocator(), SSceneLoadData)(m_Context->GetAllocator())); + theScene = m_LoadingScenes.back(); + } + // preserve the data buffer because we run directly from it; there isn't a memcopy. + theScene->m_Data = inData; + + QT3DSU32 theTranslatorOffset = theReader.LoadRef(); + + NVDataRef theSGData = NVDataRef(theReader.m_CurrentPtr, theTranslatorOffset); + NVDataRef theTranslatorData = NVDataRef( + theReader.m_CurrentPtr + theTranslatorOffset, theDataSectionSize - theTranslatorOffset); + + CStrTableOrDataRef theStrTableData(m_Context->m_CoreContext->GetStringTable()); + if (m_StrTableData.size()) + theStrTableData = CStrTableOrDataRef(m_StrTableData); + + theScene->m_Presentation = SGraphObjectSerializer::Load( + theSGData, m_StrTableData, m_Context->m_CoreContext->GetDynamicObjectSystemCore(), + m_Context->m_CoreContext->GetPathManagerCore(), m_Context->GetAllocator(), + inPresentationDirectory); + if (theScene->m_Presentation) + theScene->m_Presentation->m_PresentationDirectory = inPresentationDirectory; + + theScene->m_TranslatorData = theTranslatorData; + theScene->m_SceneGraphData = theSGData; + + { + Mutex::ScopedLock __locker(m_LoadingScenesMutex); + m_LoadingScenes[theLoadingSceneIndex - 1] = theScene; + } + return theLoadingSceneIndex; + } + + // threadsafe + // still does not require openGL context but has dependency on a few other things. + void LoadSceneStage2(qt3ds::QT3DSU32 inSceneHandle, Q3DStudio::IPresentation &inPresentation, + size_t inElementMemoryOffset, Q3DStudio::IScriptBridge &inBridge) override + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load Scene Graph Stage 2"); + QT3DSU32 theSceneIndex = QT3DS_MAX_U32; + SSceneLoadData *theScene; + { + Mutex::ScopedLock __locker(m_LoadingScenesMutex); + QT3DSU32 numLoadingScenes = QT3DSU32(m_LoadingScenes.size()); + if (inSceneHandle && inSceneHandle <= numLoadingScenes) { + theSceneIndex = inSceneHandle - 1; + theScene = m_LoadingScenes[theSceneIndex]; + } else { + QT3DS_ASSERT(false); + return; + } + } + SDataReader theReader(theScene->m_TranslatorData.begin(), theScene->m_TranslatorData.end()); + QT3DSU32 theNumTranslators = theReader.LoadRef(); + theScene->m_Translators.resize(theNumTranslators); + theScene->m_RuntimePresentation = &inPresentation; + for (QT3DSU32 idx = 0, end = theNumTranslators; idx < end; ++idx) { + Qt3DSTranslator *theTranslator = Qt3DSTranslator::LoadTranslator( + theReader, inElementMemoryOffset, theScene->m_SceneGraphData, + theScene->m_AutoAllocator); + if (theTranslator) { + InitializeTranslator(*theTranslator, inBridge); + } + theScene->m_Translators[idx] = theTranslator; + } + } + + void OnGraphicsInitialized() + { + QT3DS_ASSERT(m_Context->m_Context.mPtr); + // this means graphics have been initialized + eastl::string theSourcePathStr; + IBufferManager &theManager(m_Context->m_Context->GetBufferManager()); + nvvector imagePathList(m_Context->GetAllocator(), + "imagePathList"); + nvvector iblImagePathList(m_Context->GetAllocator(), + "iblImagePathList"); + for (QT3DSU32 idx = 0, end = m_SourcePaths.size(); idx < end; ++idx) { + theSourcePathStr.assign(m_SourcePaths[idx].first); + bool hasTransparency = m_SourcePaths[idx].second.first; + bool isIbl = m_SourcePaths[idx].second.second; + if (theSourcePathStr.size() > 4) { + CRegisteredString theObjectPath = m_SourcePaths[idx].first; + if (qt3ds::runtime::isImagePath(theSourcePathStr.c_str())) { + theManager.SetImageHasTransparency(theObjectPath, hasTransparency); + if (isIbl) + iblImagePathList.push_back(theObjectPath); + else + imagePathList.push_back(theObjectPath); + } else { + if (theSourcePathStr.find(".mesh") != eastl::string::npos) + theManager.LoadMesh(theObjectPath); + } + } + } + + bool pktx = false; + for (unsigned int i = 0; i < m_Scenes.size(); ++i) { + if (m_Scenes[i].second->m_Presentation->m_preferKTX) { + pktx = true; + break; + } + } + + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Initial Batch Image Load"); + + m_Context->m_Context->GetImageBatchLoader().LoadImageBatch( + toConstDataRef(imagePathList.data(), imagePathList.size()), + CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext() + .GetRenderContextType(), pktx, false); + m_Context->m_Context->GetImageBatchLoader().LoadImageBatch( + toConstDataRef(iblImagePathList.data(), iblImagePathList.size()), + CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext() + .GetRenderContextType(), pktx, true); + } + + { + + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Initialize Scenes"); + for (QT3DSU32 idx = 0, end = m_LoadingScenes.size(); idx < end; ++idx) { + SSceneLoadData &theScene = *m_LoadingScenes[idx]; + // m_Context->m_Foundation->error( QT3DS_WARN, "Finalizing scene %d", (int)idx+1 ); + if (theScene.m_RuntimePresentation) { + Qt3DSRenderScene *theIScene = QT3DS_NEW(m_Context->GetAllocator(), Qt3DSRenderScene)( + *m_Context, *m_Context->m_Context, theScene); + FinalizeScene(*theScene.m_RuntimePresentation, *theIScene); + theIScene->PostLoadStep(); + } else { + qCWarning(WARNING, "Failed to finalize scene %d", int(idx + 1)); + } + } + } + } + + void LoadRenderPlugin(const char *inAssetIDString, const char *inPath, + const char *inArgs) override + { + Q3DStudio::CDLLManager &theDLLManager = Q3DStudio::CDLLManager::GetDLLManager(); + long theHandle = theDLLManager.LoadLibrary(inPath, EDLLTYPE_RENDERABLE_PLUGIN); + if (theHandle >= 0) { + qt3ds::render::IOffscreenRenderer *theOffscreenRenderer = + QT3DS_NEW(m_Context->GetAllocator(), + qt3ds::render::COldNBustedPluginRenderer)(*m_Context->m_Context, theHandle); + qt3ds::foundation::CRegisteredString theAssetString = + m_Context->m_CoreContext->GetStringTable().RegisterStr(inAssetIDString); + + m_Context->m_Context->GetOffscreenRenderManager().RegisterOffscreenRenderer( + theAssetString, *theOffscreenRenderer); + + PROC_Initialize theInitializeProc = + reinterpret_cast(theDLLManager.GetProc("Initialize", theHandle)); + Q3DStudio_ASSERT(theInitializeProc); +#if !defined (Q_OS_MACOS) + PROC_SetEGLInfo theSetEGLInfoProc = + reinterpret_cast(theDLLManager.GetProc("SetEGLInfo", theHandle)); + // Set EGL parameters used for optional context creation + if (theSetEGLInfoProc) { + Q3DStudio::SEGLInfo *theInfo = m_WindowSystem.GetEGLInfo(); + if (theInfo) + theSetEGLInfoProc(theInfo->display, theInfo->context, theInfo->surface, + theInfo->config); + } +#endif + if (theInitializeProc && theInitializeProc(inArgs) == EDLLSTATUS_OK) + m_RenderPlugins.push_back(make_pair(theAssetString, theHandle)); + else + qCWarning(qt3ds::INVALID_OPERATION) << "Unable to load plugin " << inAssetIDString; + } else + qCWarning(qt3ds::INVALID_OPERATION) << "Unable to load plugin " << inAssetIDString; + + return; + } + + void LoadQmlStreamerPlugin(const char *inAssetIDString) override + { + qt3ds::render::IOffscreenRenderer *theOffscreenRenderer = + QT3DS_NEW(m_Context->GetAllocator(), + Q3DSQmlRender)(*m_Context->m_Context, inAssetIDString); + if (theOffscreenRenderer) { + qt3ds::foundation::CRegisteredString theAssetString = + m_Context->m_CoreContext->GetStringTable().RegisterStr(inAssetIDString); + m_Context->m_Context->GetOffscreenRenderManager().RegisterOffscreenRenderer( + SOffscreenRendererKey(theAssetString), *theOffscreenRenderer); + + m_RenderPlugins.push_back(make_pair(theAssetString, 0)); + } + } + + void BinarySave(Q3DStudio::IScene &inScene) override + { + Qt3DSRenderScene &theScene = static_cast(inScene); + qt3ds::render::SWriteBuffer theWriteBuffer(m_Context->GetAllocator(), "BinarySaveBuffer"); + qt3ds::render::SPtrOffsetMap theSGOffsetMap(m_Context->GetAllocator(), "PointerOffsetMap"); + // Start with some versioning and sanity checks. + theWriteBuffer.write(GetFileTag()); + theWriteBuffer.write(SGraphObject::GetSceneGraphBinaryVersion()); + QT3DSU32 theTranslatorOffsetAddress = theWriteBuffer.size(); + // Now the data section starts. Offsets should be relative to here, not the first + // 8 bytes. + theWriteBuffer.writeZeros(4); // offset where the translator data starts; + QT3DSU32 theDataSectionStart = theWriteBuffer.size(); + + // These offsets are after we have read in the data section + SGraphObjectSerializer::Save( + m_Context->m_RenderContext->GetFoundation(), *theScene.m_Presentation, theWriteBuffer, + m_Context->m_Context->GetDynamicObjectSystem(), + m_Context->m_Context->GetPathManager(), theSGOffsetMap, + m_Context->m_CoreContext->GetStringTable(), theScene.m_GraphObjectList); + + theWriteBuffer.align(sizeof(void *)); + QT3DSU32 theTranslatorCountAddress = theWriteBuffer.size(); + QT3DSU32 theTranslatorOffset = theTranslatorCountAddress - theDataSectionStart; + + theWriteBuffer.writeZeros(4); + // Now write out the translators verbatim. We get an adjustment parameter on save that + // allows a translation + // from old element ptr->new element ptr. + QT3DSU32 theTranslatorCount = 0; + for (QT3DSU32 idx = 0, end = theScene.m_GraphObjectList.size(); idx < end; ++idx) { + Qt3DSTranslator *theTranslator = + Qt3DSTranslator::GetTranslatorFromGraphNode(*theScene.m_GraphObjectList[idx]); + // Presentation nodes don't have translator + if (theTranslator) { + qt3ds::render::SPtrOffsetMap::iterator theIter = + theSGOffsetMap.find(theScene.m_GraphObjectList[idx]); + if (theIter != theSGOffsetMap.end()) { + QT3DSU32 theOffset = theIter->second; + theTranslator->Save(theWriteBuffer, theOffset); + ++theTranslatorCount; + } else { + QT3DS_ASSERT(false); + } + } + } + QT3DSU32 *theTranslatorCountPtr = + reinterpret_cast(theWriteBuffer.begin() + theTranslatorCountAddress); + *theTranslatorCountPtr = theTranslatorCount; + QT3DSU32 *theTranslatorOffsetPtr = + reinterpret_cast(theWriteBuffer.begin() + theTranslatorOffsetAddress); + *theTranslatorOffsetPtr = theTranslatorOffset; + + Q3DStudio::IPresentation &thePresentation = *theScene.m_RuntimePresentation; + eastl::string theBinaryPath(thePresentation.GetFilePath().toLatin1().constData()); + qt3ds::foundation::CFileTools::AppendDirectoryInPathToFile(theBinaryPath, "binary"); + eastl::string theBinaryDir(theBinaryPath); + qt3ds::foundation::CFileTools::GetDirectory(theBinaryDir); + qt3ds::foundation::CFileTools::SetExtension( + theBinaryPath, GetBinaryExtension()); // uibb: short for ui binary binding + + Q3DStudio::CFileStream theStream(theBinaryPath.c_str(), "wb"); + if (theStream.IsOpen() == false) { + QT3DS_ASSERT(false); + } + + theStream.WriteRaw(theWriteBuffer.begin(), theWriteBuffer.size()); + theStream.Close(); + } + + // We save in the reverse order that we load because the effect system may add strings + // to the string table when it is writing its data out, this the string table needs to come + // last. + // Loading, obviously, the string table needs to be the first object loaded. + void BinarySaveManagerData(qt3ds::foundation::IOutStream &inStream, + const char *inBinaryDir) override + { + qt3ds::render::SWriteBuffer theWriteBuffer(m_Context->GetAllocator(), "BinarySaveBuffer"); + IStringTable &theStrTable = m_Context->m_CoreContext->GetStringTable(); + eastl::string theProjectDir(inBinaryDir); + qt3ds::foundation::CFileTools::GetDirectory(theProjectDir); + + // We save everything before the string table because often times saving something creates + // new strings. + theWriteBuffer.writeZeros(4); // Total data size + // Dynamic object system + theWriteBuffer.writeZeros(4); // Effect system offset + // effect system + theWriteBuffer.writeZeros(4); // Material system offset + // material system + theWriteBuffer.writeZeros(4); // Binary path offset + // binary path data + theWriteBuffer.writeZeros(4); // Plugin manager offset + // plugin manager + theWriteBuffer.writeZeros(4); // String system offset + // string system last. + QT3DSU32 theOffsetStart = theWriteBuffer.size(); + m_Context->m_Context->GetDynamicObjectSystem().Save( + theWriteBuffer, theStrTable.GetRemapMap(), theProjectDir.c_str()); + theWriteBuffer.align(sizeof(void *)); + QT3DSU32 theEffectSystemOffset = theWriteBuffer.size() - theOffsetStart; + m_Context->m_Context->GetEffectSystem().Save(theWriteBuffer, theStrTable.GetRemapMap(), + theProjectDir.c_str()); + theWriteBuffer.align(sizeof(void *)); + QT3DSU32 theMaterialSystemOffset = theWriteBuffer.size() - theOffsetStart; + m_Context->m_Context->GetCustomMaterialSystem().Save( + theWriteBuffer, theStrTable.GetRemapMap(), theProjectDir.c_str()); + QT3DSU32 theBinaryPathOffset = theWriteBuffer.size() - theOffsetStart; + + theWriteBuffer.write(QT3DSU32(m_SourcePaths.size())); + for (nvvector>>::iterator iter + = m_SourcePaths.begin(), end = m_SourcePaths.end(); + iter != end; ++iter) { + CRegisteredString theStr(iter->first); + theStr.Remap(theStrTable.GetRemapMap()); + theWriteBuffer.write(size_t(theStr.c_str())); + QT3DSU32 theSourcePathFlags = iter->second.first ? 1 : 0; + theSourcePathFlags |= iter->second.second ? 2 : 0; + theWriteBuffer.write(theSourcePathFlags); + } + + QT3DSU32 thePluginManagerOffset = theWriteBuffer.size() - theOffsetStart; + + m_Context->m_Context->GetRenderPluginManager().Save( + theWriteBuffer, theStrTable.GetRemapMap(), theProjectDir.c_str()); + + QT3DSU32 theStringTableOffset = theWriteBuffer.size() - theOffsetStart; + + theStrTable.Save(theWriteBuffer); + + QT3DSU32 *theSizePtr = reinterpret_cast(theWriteBuffer.begin()); + + theSizePtr[0] = theWriteBuffer.size() - 4; // overall size + theSizePtr[1] = theEffectSystemOffset; + theSizePtr[2] = theMaterialSystemOffset; + theSizePtr[3] = theBinaryPathOffset; // thePathOffset + theSizePtr[4] = thePluginManagerOffset; + theSizePtr[5] = theStringTableOffset; + + inStream.Write(theWriteBuffer.begin(), theWriteBuffer.size()); + } + + NVDataRef BinaryLoadManagerData(qt3ds::foundation::IInStream &inStream, + const char *inBinaryDir) override + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load UIAB - String Table + Render Objects"); + QT3DS_ASSERT(m_Context->m_FlowData == nullptr); + QT3DSU32 dataSize = 0; + inStream.Read(dataSize); + m_Context->m_FlowData = (QT3DSU8 *)m_Context->m_CoreContext->GetAllocator().allocate( + dataSize, "SceneManager::BinaryFlowData", __FILE__, __LINE__); + + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load UIAB - Initial Data Load"); + inStream.Read(m_Context->m_FlowData, dataSize); + } + SDataReader theReader(m_Context->m_FlowData, m_Context->m_FlowData + dataSize); + QT3DSU32 theEffectSystemOffset = theReader.LoadRef(); + QT3DSU32 theMaterialSystemOffset = theReader.LoadRef(); + QT3DSU32 theBinaryPathOffset = theReader.LoadRef(); + QT3DSU32 thePluginManagerOffset = theReader.LoadRef(); + QT3DSU32 theStringTableOffset = theReader.LoadRef(); + QT3DSU8 *theStartOffset = theReader.m_CurrentPtr; + IStringTable &theStrTable = m_Context->m_CoreContext->GetStringTable(); + + // Load string table. + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load UIAB - Load String Table"); + m_StrTableData = toDataRef(theReader.m_CurrentPtr + theStringTableOffset, + dataSize - theStringTableOffset); + theStrTable.Load(m_StrTableData); + } + + // Load source paths to preload heavy data + theReader.m_CurrentPtr = theStartOffset + theBinaryPathOffset; + QT3DSU32 theNumSourcePaths = theReader.LoadRef(); + eastl::string theSourcePathStr; + eastl::string theProjectDir(inBinaryDir); + eastl::string theShaderCacheDir(inBinaryDir); + + // Up one moves to the project directory. + qt3ds::foundation::CFileTools::GetDirectory(theProjectDir); + const char8_t *theBasePath(theProjectDir.c_str()); + + m_ProjectDir = theStrTable.RegisterStr(theProjectDir.c_str()); + m_BinaryDir = theStrTable.RegisterStr(theShaderCacheDir.c_str()); + + // Preload the heavy buffers + m_SourcePaths.resize(theNumSourcePaths); + for (QT3DSU32 idx = 0, end = theNumSourcePaths; idx < end; ++idx) { + CRegisteredString thePath = theReader.LoadRef(); + QT3DSU32 theFlags = theReader.LoadRef(); + thePath.Remap(m_StrTableData); + bool theBoolFlagValue = theFlags ? true : false; + m_SourcePaths[idx] = eastl::make_pair(thePath, theBoolFlagValue); + } + + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load UIAB - Base Dynamic System"); + // Load effect system. + NVDataRef theDynamicSystemData(theStartOffset, theEffectSystemOffset); + m_Context->m_CoreContext->GetDynamicObjectSystemCore().Load( + theDynamicSystemData, m_StrTableData, theBasePath); + } + + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load UIAB - Effect System"); + NVDataRef theEffectSystemData(theStartOffset + theEffectSystemOffset, + theMaterialSystemOffset - theEffectSystemOffset); + m_Context->m_CoreContext->GetEffectSystemCore().Load(theEffectSystemData, + m_StrTableData, theBasePath); + } + + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load UIAB - Material System"); + NVDataRef theMaterialSystemData(theStartOffset + theMaterialSystemOffset, + thePluginManagerOffset - theMaterialSystemOffset); + m_Context->m_CoreContext->GetMaterialSystemCore().Load(theMaterialSystemData, + m_StrTableData, theBasePath); + } + + { + SStackPerfTimer __perfTimer(m_Context->m_CoreContext->GetPerfTimer(), + "Load UIAB - Plugin Manager Data"); + NVDataRef thePluginManagerData(theStartOffset + thePluginManagerOffset, + theStringTableOffset - thePluginManagerOffset); + m_Context->m_CoreContext->GetRenderPluginCore().Load(thePluginManagerData, + m_StrTableData, theBasePath); + } + + return m_StrTableData; + } + + virtual void DeleteScene(Q3DStudio::IPresentation *inPresentation) + { + QT3DSU32 idx; + QT3DSU32 end; + for (idx = 0, end = m_Scenes.size(); idx < end; ++idx) { + if (m_Scenes[idx].first == inPresentation) + break; + } + if (idx < m_Scenes.size()) { + m_Scenes[idx].second->Release(); + m_Scenes.erase(m_Scenes.begin() + idx); + } + } + + Q3DStudio::BOOL Update() override + { + bool theResult = false; + long theSceneCount = m_Scenes.size(); + for (size_t theSceneIndex = 0; theSceneIndex < theSceneCount; ++theSceneIndex) { + Qt3DSRenderScene *theScene = m_Scenes[theSceneIndex].second; + theResult |= theScene->Update(); + } + return theResult; + } + + Q3DStudio::BOOL RenderPresentation(Q3DStudio::IPresentation *inPresentation, + bool firstFrame) override + { + Qt3DSRenderScene *theFirstScene = nullptr; + for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == nullptr; ++idx) + if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation) + theFirstScene = m_Scenes[idx].second; + + if (theFirstScene && theFirstScene->m_Presentation) { + m_LastRenderedScene = theFirstScene; + if (theFirstScene->m_Presentation->m_Scene + && theFirstScene->m_Presentation->m_Scene->m_UseClearColor) { + m_Context->m_Context->SetSceneColor( + theFirstScene->m_Presentation->m_Scene->m_ClearColor); + } else + m_Context->m_Context->SetSceneColor(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f)); + + // Setup the render rotation *before* rendering so that the magic can happen on begin + // render. + if (m_Context->m_RenderRotationsEnabled) + m_Context->m_Context->SetRenderRotation( + theFirstScene->m_Presentation->m_PresentationRotation); + else + m_Context->m_Context->SetRenderRotation(RenderRotationValues::NoRotation); + + m_Context->m_Context->SetPresentationDimensions(QSize( + int(theFirstScene->m_Presentation->m_PresentationDimensions.x), + int(theFirstScene->m_Presentation->m_PresentationDimensions.y))); + } + + m_Context->m_Context->BeginFrame(firstFrame); + m_Context->m_RenderContext->ResetBlendState(); + + // How exactly does this work, I have no idea. + // Should we only render the first scene and not every scene, perhaps? + bool wasDirty = false; + if (theFirstScene) + wasDirty = theFirstScene->PrepareForRender(); + else { + m_Context->m_RenderContext->SetClearColor(QT3DSVec4(0, 0, 0, 0)); + m_Context->m_RenderContext->Clear(qt3ds::render::NVRenderClearFlags( + NVRenderClearValues::Color | NVRenderClearValues::Depth)); + } + m_Context->m_Context->RunRenderTasks(); + if (theFirstScene) + theFirstScene->Render(); + + m_Context->m_Context->EndFrame(); + + return wasDirty; + } + // I think render::check resize is called so this isn't necessary + void OnViewResize(Q3DStudio::INT32 inViewWidth, Q3DStudio::INT32 inViewHeight) override + { + m_ViewWidth = inViewWidth; + m_ViewHeight = inViewHeight; + } + void GetViewSize(Q3DStudio::INT32 &outWidth, Q3DStudio::INT32 &outHeight) override + { + outWidth = m_ViewWidth; + outHeight = m_ViewHeight; + } + + Q3DStudio::STextSizes GetDisplayDimensions(Q3DStudio::IPresentation *inPresentation) override + { + Qt3DSRenderScene *theFirstScene = nullptr; + for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == nullptr; ++idx) + if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation) + theFirstScene = m_Scenes[idx].second; + if (theFirstScene) { + m_Context->m_Context->SetPresentationDimensions(QSize( + int(theFirstScene->m_Presentation->m_PresentationDimensions.x), + int(theFirstScene->m_Presentation->m_PresentationDimensions.y))); + render::NVRenderRectF theDisplayViewport = + m_Context->m_Context->GetDisplayViewport(); + return Q3DStudio::STextSizes( + static_cast(theDisplayViewport.m_Width), + static_cast(theDisplayViewport.m_Height)); + } + return Q3DStudio::STextSizes(static_cast(0), + static_cast(0)); + } + + Q3DStudio::TElement *UserPick(float mouseX, float mouseY) override + { + if (m_LastRenderedScene) { + return m_LastRenderedScene->UserPick(mouseX, mouseY); + } + return nullptr; + } + + Option FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY, + NVDataRef inElements, + Q3DStudio::FacePositionPlanes::Enum inPlane) override + { + if (m_LastRenderedScene) { + + return m_LastRenderedScene->FacePosition(inElement, mouseX, mouseY, inElements, + inPlane); + } + return Empty(); + } + + Q3DStudio::SPickFrame AdvancePickFrame(const Q3DStudio::SInputFrame &inInputFrame) override + { + // We now have a new input frame, and our results are invalid but ready to be filled + m_PickFrame.m_InputFrame = inInputFrame; + m_PickFrame.m_Model = nullptr; + m_PickFrame.m_ResultValid = false; + if (m_LastRenderedScene) { + if (m_PickFrame.m_InputFrame.m_PickValid) + m_LastRenderedScene->Pick(m_PickFrame); + } + return m_PickFrame; + } + + void Release() override + { + long theRenderPluginSize = m_RenderPlugins.size(); + Q3DStudio::CDLLManager &theDLLManager = Q3DStudio::CDLLManager::GetDLLManager(); + for (int theRenderPluginIndex = 0; theRenderPluginIndex < theRenderPluginSize; + ++theRenderPluginIndex) { + long theDLLHandle = m_RenderPlugins[theRenderPluginIndex].second; + PROC_Uninitialize theUninitializeProc = reinterpret_cast( + theDLLManager.GetProc("Uninitialize", theDLLHandle)); + Q3DStudio_ASSERT(theUninitializeProc); + theUninitializeProc &&theUninitializeProc(); + + theDLLManager.UnloadLibrary(theDLLHandle); + } + + // Ensure the binding core doesn't get released until after we get released. + NVScopedRefCounted theContext(m_Context); + NVDelete(m_Context->GetAllocator(), this); + } +}; + +struct SRenderFactory; + +struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFactory +{ + NVScopedRefCounted m_Context; + + NVScopedRefCounted m_ScriptBridgeQml; + NVScopedRefCounted m_SceneManager; + NVScopedRefCounted m_EventSystem; + qt3ds::runtime::IApplication *m_Application; + QT3DSI32 m_RefCount; + + SRenderFactory(SBindingCore &inCore) + : m_Context(inCore) + , m_ScriptBridgeQml(nullptr) + , m_SceneManager(nullptr) + , m_Application(nullptr) + , m_RefCount(0) + { + } + + ~SRenderFactory() + { + using namespace Q3DStudio; + // Release the event system, it must be released before script engine + m_EventSystem = nullptr; + m_ScriptBridgeQml->Shutdown(*m_Context->m_Foundation); + } + + void addRef() override { atomicIncrement(&m_RefCount); } + + void release() override + { + atomicDecrement(&m_RefCount); + if (m_RefCount <= 0) { + NVScopedRefCounted theContext(m_Context); + NVDelete(m_Context->GetAllocator(), this); + } + } + + qt3ds::render::IQt3DSRenderContextCore &GetRenderContextCore() override + { + return *m_Context->m_CoreContext; + } + + qt3ds::runtime::IApplication *GetApplicationCore() override { return m_Application; } + void SetApplicationCore(qt3ds::runtime::IApplication *app) override + { + m_Application = app; + } + + Q3DStudio::ISceneBinaryLoader &GetSceneLoader() override + { + if (m_SceneManager == nullptr) + m_SceneManager = QT3DS_NEW(m_Context->GetAllocator(), + Qt3DSRenderSceneManager)(*m_Context, m_Context->m_WindowSystem); + return *m_SceneManager; + } + + Q3DStudio::ITegraApplicationRenderEngine &CreateRenderEngine() override + { + return m_Context->CreateRenderer(); + } + Q3DStudio::ISceneManager &GetSceneManager() override + { + if (m_SceneManager == nullptr) + m_SceneManager = QT3DS_NEW(m_Context->GetAllocator(), + Qt3DSRenderSceneManager)(*m_Context, m_Context->m_WindowSystem); + return *m_SceneManager; + } + Q3DStudio::IScriptBridge &GetScriptEngineQml() override + { + if (m_ScriptBridgeQml == nullptr) { + m_ScriptBridgeQml = + Q3DStudio::CQmlEngine::Create(*m_Context->m_Foundation, m_Context->m_TimeProvider); + } + + return *m_ScriptBridgeQml; + } + qt3ds::render::IInputStreamFactory &GetInputStreamFactory() override + { + return m_Context->m_CoreContext->GetInputStreamFactory(); + } + + qt3ds::render::IQt3DSRenderContext &GetQt3DSRenderContext() override + { + return *m_Context->m_Context; + } + + qt3ds::evt::IEventSystem &GetEventSystem() override + { + if (!m_EventSystem) { + m_EventSystem = qt3ds::evt::IEventSystem::Create(*m_Context->m_Foundation); + } + return *m_EventSystem; + } + Q3DStudio::ITimeProvider &GetTimeProvider() override { return m_Context->m_TimeProvider; } + qt3ds::foundation::IStringTable &GetStringTable() override + { + return m_Context->m_CoreContext->GetStringTable(); + } + qt3ds::NVFoundationBase &GetFoundation() override { return *m_Context->m_Foundation.mPtr; } + qt3ds::foundation::IPerfTimer &GetPerfTimer() override + { + return m_Context->m_CoreContext->GetPerfTimer(); + } + qt3ds::runtime::IApplication *GetApplication() override { return m_Application; } + void SetApplication(qt3ds::runtime::IApplication *app) override + { + m_Application = app; + if (app) { + // QML engine + GetScriptEngineQml(); + m_ScriptBridgeQml->SetApplication(*app); + m_ScriptBridgeQml->Initialize(); + } + } + void SetDllDir(const char *dllDir) override + { + m_Context->m_CoreContext->GetRenderPluginCore().SetDllDir(dllDir); + } + + void AddSearchPath(const char8_t *inFile) override + { + m_Context->m_CoreContext->GetInputStreamFactory().AddSearchDirectory(inFile); + } + virtual void Release() { NVDelete(m_Context->GetAllocator(), this); } + + struct SContextTypeRenderFactory : public IRuntimeFactoryRenderFactory + { + QSurfaceFormat format; + SContextTypeRenderFactory(const QSurfaceFormat &fmt) + : format(fmt) + { + } + + qt3ds::render::NVRenderContext *CreateRenderContext(qt3ds::NVFoundationBase &foundat, + IStringTable &strt) override + { +#ifndef Qt3DS_NO_RENDER_SYMBOLS + qt3ds::render::NVRenderContext &retval = NVRenderContext::CreateGL(foundat, strt, format); + return &retval; +#else + qt3ds::render::NVRenderContext &retval = NVRenderContext::Createnullptr(foundat, strt); + return &retval; +#endif + } + }; + + IQt3DSRenderFactory &CreateRenderFactory(const QSurfaceFormat& format, + bool delayedLoading) override + { + + SContextTypeRenderFactory theContextFactory(format); + m_Context->CreateRenderContext(theContextFactory, delayedLoading); + + GetSceneLoader(); + { + SStackPerfTimer __loadTimer(GetPerfTimer(), "SceneManager OnGraphicsInitialized"); + m_SceneManager->OnGraphicsInitialized(); + } + return *this; + } +}; + +} + +IQt3DSRenderFactoryCore &IQt3DSRenderFactoryCore::CreateRenderFactoryCore( + const char8_t *inApplicationDirectory, + Q3DStudio::IWindowSystem &inWindowSystem, + Q3DStudio::ITimeProvider &inTimeProvider) +{ + SBindingCore *theCore = reinterpret_cast(malloc(sizeof(SBindingCore))); + new (theCore) SBindingCore(inApplicationDirectory, inWindowSystem, inTimeProvider); + return *QT3DS_NEW(theCore->GetAllocator(), SRenderFactory)(*theCore); +} diff --git a/src/engine/Qt3DSRenderRuntimeBinding.h b/src/engine/Qt3DSRenderRuntimeBinding.h new file mode 100644 index 0000000..ad0c4e6 --- /dev/null +++ b/src/engine/Qt3DSRenderRuntimeBinding.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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$ +** +****************************************************************************/ + +#ifndef QT3DS_RENDER_RUNTIME_BINDING_H +#define QT3DS_RENDER_RUNTIME_BINDING_H + +#include "Qt3DSRuntimeFactory.h" +#include "EABase/eabase.h" +#include "render/Qt3DSRenderBaseTypes.h" +#include "render/Qt3DSRenderContext.h" + +#include + +namespace Q3DStudio { +class ITegraApplicationRenderEngine; +class ITimeProvider; +class IWindowSystem; +} + +namespace qt3ds { +namespace render { + + class ITextRenderer; + class IRuntimeFactoryRenderFactory + { + protected: + virtual ~IRuntimeFactoryRenderFactory() {} + public: + virtual qt3ds::render::NVRenderContext * + CreateRenderContext(qt3ds::NVFoundationBase &foundat, qt3ds::foundation::IStringTable &strt) = 0; + }; + + class IQt3DSRenderFactory; + + class QT3DS_AUTOTEST_EXPORT IQt3DSRenderFactoryCore : public Q3DStudio::IRuntimeFactoryCore + { + public: + virtual IQt3DSRenderFactory & + CreateRenderFactory(const QSurfaceFormat &format, bool delayedLoading) = 0; + + static IQt3DSRenderFactoryCore & + CreateRenderFactoryCore(const char8_t *inApplicationDirectory, + Q3DStudio::IWindowSystem &inWindowSystem, + Q3DStudio::ITimeProvider &inTimeProvider); + }; + + class IQt3DSRenderFactory : public Q3DStudio::IRuntimeFactory + { + public: + virtual Q3DStudio::ITegraApplicationRenderEngine &CreateRenderEngine() = 0; + }; +} +} + +#endif diff --git a/src/engine/Qt3DSRenderRuntimeBindingImpl.h b/src/engine/Qt3DSRenderRuntimeBindingImpl.h new file mode 100644 index 0000000..92cb865 --- /dev/null +++ b/src/engine/Qt3DSRenderRuntimeBindingImpl.h @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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$ +** +****************************************************************************/ + +#ifndef QT3DS_RENDER_RUNTIME_BINDING_IMPL_H +#define QT3DS_RENDER_RUNTIME_BINDING_IMPL_H + +#include "Qt3DSRenderRuntimeBinding.h" +#include "foundation/TrackingAllocator.h" +#include "foundation/Utils.h" +#include "foundation/Qt3DSRefCounted.h" +#include "Qt3DSRender.h" +#include "Qt3DSRenderContextCore.h" +#include "render/Qt3DSRenderContext.h" +#include "foundation/Qt3DSAtomic.h" +#include "Qt3DSIPresentation.h" +#include "foundation/Qt3DSFoundation.h" +#include "foundation/Qt3DSBroadcastingAllocator.h" +#include "Qt3DSRenderPresentation.h" +#include "Qt3DSRenderScene.h" +#include "Qt3DSRenderLayer.h" +#include "Qt3DSRenderLight.h" +#include "Qt3DSRenderCamera.h" +#include "Qt3DSRenderModel.h" +#include "Qt3DSRenderDefaultMaterial.h" +#include "Qt3DSRenderImage.h" +#include "Qt3DSUIPParser.h" +#include "Qt3DSRenderEffect.h" +#include "Qt3DSRenderCustomMaterial.h" +#include "Qt3DSRenderEffectSystem.h" +#include "foundation/Qt3DSInvasiveSet.h" +#include "Qt3DSIPresentation.h" +#include "Qt3DSTextRenderer.h" +#include "Qt3DSRenderText.h" +#include "foundation/StrConvertUTF.h" +#include "Qt3DSMetadata.h" +#include "Qt3DSRenderInputStreamFactory.h" +#include "Qt3DSRenderContextCore.h" +#include "Qt3DSWindowSystem.h" +#include "Qt3DSRenderPluginGraphObject.h" +#include "Qt3DSRenderReferencedMaterial.h" +#include "Qt3DSRenderText.h" +#include "foundation/Qt3DSMutex.h" + +#ifdef EA_PLATFORM_WINDOWS +#pragma warning(disable : 4355) +#else +#define stricmp strcasecmp +#endif + +using namespace qt3ds::render; +using eastl::make_pair; +using eastl::pair; + +namespace qt3ds { +namespace render { + + extern qt3ds::foundation::MallocAllocator g_BaseAllocator; + // Small core object shared between the larger objects. + // creates the object stack needed by the rest of the system. + struct SBindingCore : public NVRefCounted + { + qt3ds::render::CAllocator m_Allocator; + QT3DSU8 *m_FlowData; + NVScopedRefCounted m_Foundation; + NVScopedRefCounted m_StringTable; + NVScopedRefCounted m_CoreContext; + NVScopedRefCounted m_RenderContext; + NVScopedRefCounted m_Context; + QSize m_WindowDimensions; + eastl::string m_PrimitivePath; + bool m_RenderRotationsEnabled; + bool m_WriteOutShaderCache; + volatile QT3DSI32 mRefCount; + Q3DStudio::IWindowSystem &m_WindowSystem; + Q3DStudio::ITimeProvider &m_TimeProvider; + + SBindingCore(const char8_t *inPrimitivePath, Q3DStudio::IWindowSystem &inWindowSystem, + Q3DStudio::ITimeProvider &inTimeProvider) + : m_Allocator() + , m_FlowData(NULL) + , m_Foundation(NVCreateFoundation(QT3DS_FOUNDATION_VERSION, m_Allocator)) + , m_StringTable(IStringTable::CreateStringTable(m_Foundation->getAllocator())) + , m_CoreContext(IQt3DSRenderContextCore::Create(*m_Foundation, *m_StringTable)) + , m_PrimitivePath(inPrimitivePath) + , m_RenderRotationsEnabled(false) + , m_WriteOutShaderCache(false) + , mRefCount(0) + , m_WindowSystem(inWindowSystem) + , m_TimeProvider(inTimeProvider) + { + m_CoreContext->SetTextRendererCore( + ITextRendererCore::CreateQtTextRenderer(*m_Foundation, *m_StringTable)); + +#if QT_VERSION >= QT_VERSION_CHECK(5,12,2) + m_CoreContext->setDistanceFieldRenderer( + ITextRendererCore::createDistanceFieldRenderer(*m_Foundation)); +#endif + + m_CoreContext->SetOnscreenTextRendererCore( + ITextRendererCore::CreateOnscreenTextRenderer(*m_Foundation)); + } + virtual ~SBindingCore() + { + m_CoreContext = NULL; + m_Context = NULL; + m_RenderContext = NULL; + if (m_FlowData) + m_Allocator.deallocate(m_FlowData); + m_FlowData = NULL; + } + + void CreateRenderContext(qt3ds::render::IRuntimeFactoryRenderFactory &inContextFactory, + bool delayedLoading) + { + m_RenderContext = inContextFactory.CreateRenderContext(*m_Foundation, *m_StringTable); + if (m_RenderContext) { + m_Context = + m_CoreContext->CreateRenderContext(*m_RenderContext, m_PrimitivePath.c_str(), + delayedLoading); + } + } + + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(g_BaseAllocator) + + NVAllocatorCallback &GetAllocator() { return m_Allocator; } + + Q3DStudio::ITegraApplicationRenderEngine &CreateRenderer(); + }; + struct STranslatorContext + { + }; + + //////////////////////////////////////// + // Translators are the set of objects that translate + // changes in the elements to changes in the scene graph. + // TODO - get rid of the virtual functions and just do dispatch + // on the m_RenderObject.m_Type. + //////////////////////////////////////// + class Qt3DSTranslator + { + public: + QT3DSU32 m_DirtyIndex; + Q3DStudio::TElement *m_Element; + SGraphObject *m_RenderObject; + STranslatorContext *m_TranslatorContext; + + Qt3DSTranslator(Q3DStudio::TElement &inElement, SGraphObject &inRenderObject); + GraphObjectTypes::Enum GetUIPType() const { return m_RenderObject->m_Type; } + Q3DStudio::TElement &Element() { return *m_Element; } + SGraphObject &RenderObject() { return *m_RenderObject; } + + // This function is done via a dispatch mechanism on the graph object type. + void OnElementChanged(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &inStudioPresentation); + + void Save(SWriteBuffer &inWriteBuffer, QT3DSU32 inGraphObjectOffset); + // Most translators don't need an extra allocation but effects due because the mapping from + // effect property + // to runtime property is too complex to do quickly. + static Qt3DSTranslator *LoadTranslator(SDataReader &inReader, size_t inElemOffset, + NVDataRef inSGSection, + NVAllocatorCallback &inAllocator); + + static Qt3DSTranslator *GetTranslatorFromGraphNode(SGraphObject &inObject); + static Qt3DSTranslator *CreateTranslatorForElement(Q3DStudio::TElement &inElement, + SGraphObject &inGraphObject, + NVAllocatorCallback &inAlloc); + static Q3DStudio::IPresentation * + GetPresentationFromPresentation(SPresentation &inPresentation); + static void InitializePointerTags(IStringTable &inTable); + static void AssignUserData(Q3DStudio::IPresentation &inPresentation, + SPresentation &inGraphPresentation); + }; + + struct STranslatorGetOp + { + QT3DSU32 operator()(const Qt3DSTranslator &translator) { return translator.m_DirtyIndex; } + }; + struct STranslatorSetOp + { + void operator()(Qt3DSTranslator &translator, QT3DSU32 value) + { + translator.m_DirtyIndex = value; + } + }; + + typedef InvasiveSet TTranslatorDirytSet; +} +} + +#endif diff --git a/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp b/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp new file mode 100644 index 0000000..b41c83b --- /dev/null +++ b/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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 "EnginePrefix.h" +#include "Qt3DSRenderRuntimeBindingImpl.h" +#include "Qt3DSRuntimeView.h" +#include "Qt3DSWindowSystem.h" +#include "Qt3DSRenderLoadedTexture.h" + +struct SRenderer; +struct SRendererRSM : public Q3DStudio::ITegraRenderStateManager +{ + SRenderer &m_Renderer; + +public: + SRendererRSM(SRenderer &renderer) + : m_Renderer(renderer) + { + } + + void SetViewport(Q3DStudio::INT32 inX, Q3DStudio::INT32 inY, Q3DStudio::INT32 inWidth, + Q3DStudio::INT32 inHeight) override; + void PushState() override; + void PopState() override; + void SetScissorTestEnabled(bool inValue) override; + void SaveAllState() override; + void RestoreAllState() override; +}; + +struct SRenderer : public Q3DStudio::ITegraApplicationRenderEngine +{ + NVScopedRefCounted m_BindingCore; + NVScopedRefCounted m_Context; + NVRenderRect m_Viewport; + nvvector m_StateStack; + QSize m_PresentationDimensions; + SRendererRSM m_RSM; + Q3DStudio::IWindowSystem &m_WindowSystem; + + SRenderer(SBindingCore &inCore, Q3DStudio::IWindowSystem &inWindowSystem) + : m_BindingCore(inCore) + , m_Context(*inCore.m_Context) + , m_StateStack(inCore.m_Context->GetAllocator(), "SRenderer::m_StateStack") + , m_RSM(*this) + , m_WindowSystem(inWindowSystem) + { + m_Context->SetSceneColor(QT3DSVec4(0, 0, 0, 0.0f)); + if (m_BindingCore->m_RenderContext) { + m_BindingCore->m_RenderContext->SetDefaultRenderTarget( + m_WindowSystem.GetDefaultRenderTargetID()); + m_BindingCore->m_RenderContext->SetDefaultDepthBufferBitCount( + m_WindowSystem.GetDepthBitCount()); + } + } + + void ensureRenderTarget() override + { + m_BindingCore->m_RenderContext->SetDefaultRenderTarget( + m_WindowSystem.GetDefaultRenderTargetID()); + } + + void CheckResize(bool, Q3DStudio::IPresentation & /*inPresentation*/) override + { + QSize theWindowDims(m_WindowSystem.GetWindowDimensions()); + m_BindingCore->m_WindowDimensions = theWindowDims; + m_BindingCore->m_Context->SetWindowDimensions(m_BindingCore->m_WindowDimensions); + } + Q3DStudio::BOOL LoadShaderCache(const char * /*inFilePath*/) override { return true; } + + void AbandonLoadingImages(Q3DStudio::IScene & /*inScene*/) override {} + + Q3DStudio::BOOL IsPickValid(Q3DStudio::FLOAT &outX, Q3DStudio::FLOAT &outY, + const Q3DStudio::IPresentation & /*inPresentation*/) const override + { + Q3DStudio::FLOAT theX = outX; + Q3DStudio::FLOAT theY = outY; + theX = theX / static_cast(m_BindingCore->m_WindowDimensions.width()); + theY = theY / static_cast(m_BindingCore->m_WindowDimensions.height()); + Q3DStudio::BOOL theValid = false; + + if ((theX >= 0.0f) && (theY >= 0.0f) && (theX <= 1.0f) && (theY <= 1.0f)) + theValid = true; + return theValid; + } + + void SetScaleMode(Q3DStudio::TegraRenderScaleModes::Enum inScale) override + { + if (m_BindingCore && m_BindingCore->m_Context) + m_BindingCore->m_Context->SetScaleMode(static_cast(inScale)); + } + Q3DStudio::TegraRenderScaleModes::Enum GetScaleMode() const override + { + if (m_BindingCore && m_BindingCore->m_Context) + return static_cast( + const_cast(*this).m_BindingCore->m_Context->GetScaleMode()); + + QT3DS_ASSERT(false); + return Q3DStudio::TegraRenderScaleModes::ExactSize; + } + + void SetShadeMode(Q3DStudio::TegraRenderShadeModes::Enum inShade) override + { + if (m_BindingCore && m_BindingCore->m_Context) { + m_BindingCore->m_Context->SetWireframeMode( + (inShade == Q3DStudio::TegraRenderShadeModes::Shaded) ? false : true); + } + } + + void EnableRenderRotation(bool inEnable) override + { + m_BindingCore->m_RenderRotationsEnabled = inEnable; + } + + void SetWriteOutShaderCache(bool inWriteOutShaderCache) override + { + m_BindingCore->m_WriteOutShaderCache = inWriteOutShaderCache; + } + + Q3DStudio::ITegraRenderStateManager &GetTegraRenderStateManager() override { return m_RSM; } + qt3ds::render::NVRenderContext &GetRenderContext() override + { + return *m_BindingCore->m_RenderContext; + } + + void Release() override + { + // Ensure the core doesn't die until after we do. + NVScopedRefCounted theContext(m_BindingCore); + NVDelete(m_Context->GetAllocator(), this); + } + + void SetViewport(Q3DStudio::INT32 inX, Q3DStudio::INT32 inY, Q3DStudio::INT32 inWidth, + Q3DStudio::INT32 inHeight) override + { + m_Viewport = NVRenderRect(inX, inY, inWidth, inHeight); + m_BindingCore->m_RenderContext->SetViewport(m_Viewport); + } + void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) override + { + m_BindingCore->m_Context->SetViewport(inViewport); + } + + void SetMatteColor(Option inColor) override { m_Context->SetMatteColor(inColor); } + virtual void PushState() { m_StateStack.push_back(m_Viewport); } + virtual void PopState() + { + m_Viewport = m_StateStack.back(); + m_StateStack.pop_back(); + SetViewport(m_Viewport.m_X, m_Viewport.m_Y, m_Viewport.m_Width, m_Viewport.m_Height); + } + + void RenderText2D(Q3DStudio::FLOAT x, Q3DStudio::FLOAT y, + qt3ds::foundation::Option inColor, const char *text) override + { + m_Context->RenderText2D(x, y, inColor, text); + } + + void RenderGpuProfilerStats(Q3DStudio::FLOAT x, Q3DStudio::FLOAT y, + qt3ds::foundation::Option inColor) override + { + m_Context->RenderGpuProfilerStats(x, y, inColor); + } +}; + +void SRendererRSM::SetViewport(Q3DStudio::INT32 inX, Q3DStudio::INT32 inY, Q3DStudio::INT32 inWidth, + Q3DStudio::INT32 inHeight) +{ + m_Renderer.SetViewport(inX, inY, inWidth, inHeight); +} +void SRendererRSM::PushState() +{ + m_Renderer.PushState(); +} +void SRendererRSM::PopState() +{ + m_Renderer.PopState(); +} +void SRendererRSM::SetScissorTestEnabled(bool inValue) +{ + m_Renderer.m_BindingCore->m_RenderContext->SetScissorTestEnabled(inValue); +} +void SRendererRSM::SaveAllState() +{ + m_Renderer.m_BindingCore->m_RenderContext->PushPropertySet(); +} +void SRendererRSM::RestoreAllState() +{ + m_Renderer.m_BindingCore->m_RenderContext->PopPropertySet(true); +} + +Q3DStudio::ITegraApplicationRenderEngine &SBindingCore::CreateRenderer() +{ + SRenderer *retval = NULL; + if (m_Context) + retval = QT3DS_NEW(m_Context->GetAllocator(), SRenderer)(*this, this->m_WindowSystem); + + return *retval; +} diff --git a/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp b/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp new file mode 100644 index 0000000..a4b3bc7 --- /dev/null +++ b/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp @@ -0,0 +1,1841 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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 "EnginePrefix.h" +#include "Qt3DSRenderRuntimeBindingImpl.h" +#include "Qt3DSRenderUIPSharedTranslation.h" +#include "Qt3DSRenderBufferManager.h" +#include "foundation/SerializationTypes.h" +#include "StringTools.h" +#include "foundation/FileTools.h" +#include "Qt3DSHash.h" +#include "Qt3DSRenderPlugin.h" +#include "Qt3DSRenderPluginPropertyValue.h" +#include "Qt3DSElementHelper.h" +#include "Qt3DSPresentation.h" +#include "Qt3DSApplication.h" +#include "Qt3DSRenderCustomMaterialSystem.h" +#include "Qt3DSRenderPath.h" +#include "Qt3DSRenderPathSubPath.h" +#include "Qt3DSRenderPathManager.h" + +using namespace qt3ds::foundation; + +namespace Q3DStudio { +enum ExtendedAttributes { + ATTRIBUTE_NONE = 0, + ATTRIBUTE_NONE_R, + ATTRIBUTE_NONE_G, + ATTRIBUTE_NONE_B +}; +} + +namespace { +QT3DSU32 g_TranslatorTag; +QT3DSU32 g_PresentationTag; +} + +// Add specializations for the tagged pointer operations to make casting +// a bit safer and more transparent. +namespace qt3ds { +namespace render { + template <> + struct SPointerTag + { + static QT3DSU32 GetTag() { return g_TranslatorTag; } + }; + template <> + struct SPointerTag + { + static QT3DSU32 GetTag() { return g_PresentationTag; } + }; +} +} + +namespace { + +template +struct SDirtySetter +{ +}; + +template <> +struct SDirtySetter +{ + static void Set(bool &dirty, bool & /*transformDirty*/, bool & /*textDirty*/) { dirty = true; } +}; +template <> +struct SDirtySetter +{ + static void Set(bool &dirty, bool &transformDirty, bool & /*textDirty*/) + { + dirty = true; + transformDirty = true; + } +}; +template <> +struct SDirtySetter +{ + static void Set(bool &dirty, bool & /*transformDirty*/, bool &textDirty) + { + dirty = true; + textDirty = true; + } +}; +template <> +struct SDirtySetter +{ + static void Set(bool & /*dirty*/, bool & /*transformDirty*/, bool & /*textDirty*/) {} +}; + +// Translates individual property values from the runtime into the rendering system. +struct SRuntimePropertyParser +{ + QT3DSI32 m_PropertyName; + Q3DStudio::UVariant m_Value; + Q3DStudio::EAttributeType m_Type; + Q3DStudio::TElement &m_Element; + SPresentation &m_Presentation; + IQt3DSRenderContext &m_RenderContext; + bool m_Dirty; + bool m_TransformDirty; + bool m_TextDirty; + + SRuntimePropertyParser(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext, + Q3DStudio::TElement &inElement) + : m_PropertyName(0) + , m_Type((Q3DStudio::EAttributeType)0) + , m_Element(inElement) + , m_Presentation(inPresentation) + , m_RenderContext(inRenderContext) + , m_Dirty(false) + , m_TransformDirty(false) + , m_TextDirty(false) + { + } + + void Setup(QT3DSI32 inPropName, Q3DStudio::UVariant inValue, Q3DStudio::EAttributeType inType) + { + m_PropertyName = inPropName; + m_Value = inValue; + m_Type = inType; + } + template + void SetDirty() + { + SDirtySetter::Set(m_Dirty, m_TransformDirty, m_TextDirty); + } + template + bool ParseProperty(QT3DSF32 &outValue) + { + if (m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT) { + QT3DSF32 newValue = m_Value.m_FLOAT; + if (outValue != newValue) { + outValue = newValue; + SetDirty(); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + }; + template + bool ParseProperty(QT3DSU32 &outValue) + { + if (m_Type == Q3DStudio::ATTRIBUTETYPE_INT32) { + QT3DSU32 newValue = (QT3DSU32)m_Value.m_INT32; + if (outValue != newValue) { + outValue = newValue; + SetDirty(); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + }; + template + bool ParseProperty(SGraphObject *&outValue) + { + Q3DStudio::TElement *theElem = NULL; + if (m_Type == Q3DStudio::ATTRIBUTETYPE_ELEMENTREF) { + theElem = m_Element.GetBelongedPresentation()->GetApplication().GetElementByHandle( + m_Value.m_ElementHandle); + } else if (m_Type == Q3DStudio::ATTRIBUTETYPE_STRING) { + CRegisteredString theString = + m_RenderContext.GetStringTable().HandleToStr(m_Value.m_StringHandle); + theElem = Q3DStudio::CElementHelper::GetElement( + m_Element.GetBelongedPresentation()->GetApplication(), + m_Element.GetBelongedPresentation(), theString.c_str(), &m_Element); + } + + SGraphObject *newValue = NULL; + if (theElem) { + Qt3DSTranslator *theTranslator = + reinterpret_cast(theElem->GetAssociation()); + if (theTranslator) + newValue = theTranslator->m_RenderObject; + } + if (outValue != newValue) { + outValue = newValue; + SetDirty(); + return true; + } + return false; + }; + template + bool ParseRadianProperty(QT3DSF32 &outValue) + { + if (ParseProperty(outValue)) { + TORAD(outValue); + return true; + } + return false; + } + template + bool ParseOpacityProperty(QT3DSF32 &outValue) + { + if (ParseProperty(outValue)) { + outValue *= 1.0f / 100.0f; + return true; + } + return false; + } + + template + bool ParseOrientationProperty(bool &ioCurrent) + { + if (m_Type == Q3DStudio::ATTRIBUTETYPE_STRING) { + CRegisteredString strValue = + m_RenderContext.GetStringTable().HandleToStr(m_Value.m_StringHandle); + bool newValue = AreEqual(strValue.c_str(), "Left Handed") ? true : false; + if (ioCurrent != newValue) { + ioCurrent = newValue; + SetDirty(); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + } + + template + bool ParseProperty(bool &ioCurrent) + { + if (m_Type == Q3DStudio::ATTRIBUTETYPE_BOOL || m_Type == Q3DStudio::ATTRIBUTETYPE_INT32) { + bool newValue = m_Value.m_INT32 ? true : false; + if (ioCurrent != newValue) { + ioCurrent = newValue; + SetDirty(); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + } + template + bool ParseInverseBoolean(bool &ioCurrent) + { + bool temp = !ioCurrent; + if (ParseProperty(temp)) { + ioCurrent = temp; + return true; + } + return false; + } + template + bool ParseProperty(QT3DSVec3 &outValue) + { + if (m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT3) { + QT3DSVec3 newValue(m_Value.m_FLOAT3[0], m_Value.m_FLOAT3[1], m_Value.m_FLOAT3[2]); + if (outValue != newValue) { + outValue = newValue; + SetDirty(); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + } + template + bool ParseProperty(QT3DSVec4 &outValue) + { + if (m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT4) { + QT3DSVec4 newValue(m_Value.m_FLOAT4[0], m_Value.m_FLOAT4[1], m_Value.m_FLOAT4[2], + m_Value.m_FLOAT4[3]); + if (outValue != newValue) { + outValue = newValue; + SetDirty(); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + } + + + template + bool ParseProperty(CRegisteredString &outValue) + { + if (m_Type == Q3DStudio::ATTRIBUTETYPE_STRING) { + CRegisteredString newValue = + m_RenderContext.GetStringTable().HandleToStr(m_Value.m_StringHandle); + if (newValue.c_str() != outValue.c_str()) { + outValue = newValue; + SetDirty(); + return true; + } + } else { + QT3DS_ASSERT(false); + } + return false; + } + + template + bool ParseRotationOrder(QT3DSU32 &outValue) + { + CRegisteredString theString; + ParseProperty(theString); + if (theString.IsValid()) { + QT3DSU32 newRotationOrder = MapRotationOrder(theString); + if (newRotationOrder != outValue) { + outValue = newRotationOrder; + SetDirty(); + return true; + } + } + return false; + } + + template + bool ParseOrientation(NodeFlags &outValue) + { + bool temp = false; + ParseOrientationProperty(temp); + bool wasLeftHanded = outValue.IsLeftHanded(); + if (wasLeftHanded != temp) { + outValue.SetLeftHanded(temp); + SetDirty(); + return true; + } + return false; + } + template + bool ParseNodeFlagsProperty(NodeFlags &outValue, NodeFlagValues::Enum inFlag) + { + bool temp = false; + ParseProperty(temp); + bool wasSet = outValue & inFlag; + if (temp != wasSet) { + outValue.ClearOrSet(temp, inFlag); + SetDirty(); + return true; + } + return false; + } + + template + bool ParseNodeFlagsInverseProperty(NodeFlags &outValue, NodeFlagValues::Enum inFlag) + { + bool temp = false; + ParseProperty(temp); + temp = !temp; + bool wasSet = outValue & inFlag; + if (temp != wasSet) { + outValue.ClearOrSet(temp, inFlag); + SetDirty(); + return true; + } + return false; + } + + template + bool ParseEnumProperty(TEnumType &outValue) + { + CRegisteredString theString; + ParseProperty(theString); + if (theString.IsValid()) { + SEnumNameMap *theMap = SEnumParseMap::GetMap(); + for (SEnumNameMap *theItem = theMap; theItem->m_Name && *theItem->m_Name; ++theItem) { + // hack to match advanced overlay types, whose name start with a '*' + const char8_t *p = theString.c_str(); + if (*p == '*') + ++p; + if (strcmp(p, theItem->m_Name) == 0) { + TEnumType theNewValue = static_cast(theItem->m_Enum); + if (outValue != theNewValue) { + outValue = theNewValue; + SetDirty(); + return true; + } + } + } + } + return false; + } + template + bool ParseAndResolveSourcePath(CRegisteredString &outValue) + { + CRegisteredString theTemp; + ParseProperty(theTemp); + CRegisteredString theNewStr = theTemp; + if (outValue.c_str() != theNewStr.c_str()) { + SetDirty(); + outValue = theNewStr; + return true; + } + return false; + } + + template + bool ParseProperty(SImage *&ioImagePtr) + { + Q3DStudio::TElement *theElem = + m_Element.GetBelongedPresentation()->GetApplication().GetElementByHandle( + m_Value.m_ElementHandle); + // Try to be very careful in here as casting things around like crazy is a sure + // way to crash the runtime at a bad point. + if (theElem != NULL) { + Qt3DSTranslator *theTranslator = + reinterpret_cast(theElem->GetAssociation()); + if (theTranslator != NULL && theTranslator->GetUIPType() == GraphObjectTypes::Image) { + SImage *theImage = static_cast(theTranslator->m_RenderObject); + if (ioImagePtr != theImage) { + ioImagePtr = theImage; + SetDirty(); + return true; + } + } + } + return false; + } + + template + bool ParseProperty(SNode *&ioNodePtr) + { + Q3DStudio::TElement *theElem = + m_Element.GetBelongedPresentation()->GetApplication().GetElementByHandle( + m_Value.m_ElementHandle); + // Try to be very careful in here as casting things around like crazy is a sure + // way to crash the runtime at a bad point. + SNode *theNode = NULL; + if (theElem != NULL + && theElem->GetBelongedPresentation() == m_Element.GetBelongedPresentation()) { + Qt3DSTranslator *theTranslator = + reinterpret_cast(theElem->GetAssociation()); + if (theTranslator != NULL + && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) { + theNode = static_cast(theTranslator->m_RenderObject); + } + } + if (ioNodePtr != theNode) { + ioNodePtr = theNode; + SetDirty(); + return true; + } + return false; + } +}; + +// Fill out parse name table. +#define Scene_ClearColor_R ATTRIBUTE_BACKGROUNDCOLOR_R +#define Scene_ClearColor_G ATTRIBUTE_BACKGROUNDCOLOR_G +#define Scene_ClearColor_B ATTRIBUTE_BACKGROUNDCOLOR_B +#define Scene_ClearColor_A ATTRIBUTE_BACKGROUNDCOLOR_A +#define Scene_UseClearColor ATTRIBUTE_BGCOLORENABLE +#define Node_Rotation ATTRIBUTE_ROTATION +#define Node_Rotation_X ATTRIBUTE_ROTATION_X +#define Node_Rotation_Y ATTRIBUTE_ROTATION_Y +#define Node_Rotation_Z ATTRIBUTE_ROTATION_Z +#define Node_Position ATTRIBUTE_POSITION +#define Node_Position_X ATTRIBUTE_POSITION_X +#define Node_Position_Y ATTRIBUTE_POSITION_Y +#define Node_Position_Z ATTRIBUTE_POSITION_Z +#define Node_Scale ATTRIBUTE_SCALE +#define Node_Scale_X ATTRIBUTE_SCALE_X +#define Node_Scale_Y ATTRIBUTE_SCALE_Y +#define Node_Scale_Z ATTRIBUTE_SCALE_Z +#define Node_Pivot ATTRIBUTE_PIVOT +#define Node_Pivot_X ATTRIBUTE_PIVOT_X +#define Node_Pivot_Y ATTRIBUTE_PIVOT_Y +#define Node_Pivot_Z ATTRIBUTE_PIVOT_Z +#define Node_LocalOpacity ATTRIBUTE_OPACITY +#define Node_RotationOrder ATTRIBUTE_ROTATIONORDER +#define Node_LeftHanded ATTRIBUTE_ORIENTATION +#define Layer_TemporalAAEnabled ATTRIBUTE_TEMPORALAA +#define Layer_LayerEnableDepthTest ATTRIBUTE_DISABLEDEPTHTEST +#define Layer_LayerEnableDepthPrePass ATTRIBUTE_DISABLEDEPTHPREPASS +#define Layer_ClearColor_R ATTRIBUTE_BACKGROUNDCOLOR_R +#define Layer_ClearColor_G ATTRIBUTE_BACKGROUNDCOLOR_G +#define Layer_ClearColor_B ATTRIBUTE_BACKGROUNDCOLOR_B +#define Layer_ClearColor_A ATTRIBUTE_BACKGROUNDCOLOR_A +#define Layer_Background ATTRIBUTE_BACKGROUND +#define Layer_BlendType ATTRIBUTE_BLENDTYPE +#define Layer_ProgressiveAAMode ATTRIBUTE_PROGRESSIVEAA +#define Layer_MultisampleAAMode ATTRIBUTE_MULTISAMPLEAA +#define Layer_HorizontalFieldValues ATTRIBUTE_HORZFIELDS +#define Layer_Left ATTRIBUTE_LEFT +#define Layer_LeftUnits ATTRIBUTE_LEFTUNITS +#define Layer_Width ATTRIBUTE_WIDTH +#define Layer_WidthUnits ATTRIBUTE_WIDTHUNITS +#define Layer_Right ATTRIBUTE_RIGHT +#define Layer_RightUnits ATTRIBUTE_RIGHTUNITS +#define Layer_VerticalFieldValues ATTRIBUTE_VERTFIELDS +#define Layer_Top ATTRIBUTE_TOP +#define Layer_TopUnits ATTRIBUTE_TOPUNITS +#define Layer_Height ATTRIBUTE_HEIGHT +#define Layer_HeightUnits ATTRIBUTE_HEIGHTUNITS +#define Layer_Bottom ATTRIBUTE_BOTTOM +#define Layer_BottomUnits ATTRIBUTE_BOTTOMUNITS +#define Layer_AoStrength ATTRIBUTE_AOSTRENGTH +#define Layer_AoDistance ATTRIBUTE_AODISTANCE +#define Layer_AoSoftness ATTRIBUTE_AOSOFTNESS +#define Layer_AoBias ATTRIBUTE_AOBIAS +#define Layer_AoSamplerate ATTRIBUTE_AOSAMPLERATE +#define Layer_AoDither ATTRIBUTE_AODITHER +#define Layer_ShadowStrength ATTRIBUTE_SHADOWSTRENGTH +#define Layer_ShadowDist ATTRIBUTE_SHADOWDIST +#define Layer_ShadowSoftness ATTRIBUTE_SHADOWSOFTNESS +#define Layer_ShadowBias ATTRIBUTE_SHADOWBIAS +#define Layer_LightProbe ATTRIBUTE_LIGHTPROBE +#define Layer_ProbeBright ATTRIBUTE_PROBEBRIGHT +#define Layer_FastIbl ATTRIBUTE_FASTIBL +#define Layer_ProbeTheta ATTRIBUTE_PROBETHETA +#define Layer_ProbePhi ATTRIBUTE_PROBEPHI +#define Layer_ProbeHorizon ATTRIBUTE_PROBEHORIZON +#define Layer_LightProbe2 ATTRIBUTE_LIGHTPROBE2 +#define Layer_Probe2Fade ATTRIBUTE_PROBE2FADE +#define Layer_Probe2Window ATTRIBUTE_PROBE2WINDOW +#define Layer_Probe2Pos ATTRIBUTE_PROBE2POS +#define Layer_ProbeFov ATTRIBUTE_PROBEFOV +#define Layer_TexturePath ATTRIBUTE_SOURCEPATH +#define Camera_ClipNear ATTRIBUTE_CLIPNEAR +#define Camera_ClipFar ATTRIBUTE_CLIPFAR +#define Camera_FOV ATTRIBUTE_FOV +#define Camera_FOVHorizontal ATTRIBUTE_FOVHORIZONTAL +#define Camera_Orthographic ATTRIBUTE_ORTHOGRAPHIC +#define Camera_ScaleMode ATTRIBUTE_SCALEMODE +#define Camera_ScaleAnchor ATTRIBUTE_SCALEANCHOR +#define Light_ImageSource ATTRIBUTE_IMAGESOURCE +#define Light_Scope ATTRIBUTE_SCOPE +#define Light_ImageSetsColor ATTRIBUTE_IMAGESETSCOLOR +#define Light_ImageSetsRotation ATTRIBUTE_IMAGESETSROTATION +#define Light_ImageHFov ATTRIBUTE_IMAGEHFOV +#define Light_ImageIsFisheye ATTRIBUTE_IMAGEISFISHEYE +#define Light_LightType ATTRIBUTE_LIGHTTYPE +#define Light_DiffuseColor ATTRIBUTE_LIGHTDIFFUSE +#define Light_DiffuseColor_R ATTRIBUTE_LIGHTDIFFUSE_R +#define Light_DiffuseColor_G ATTRIBUTE_LIGHTDIFFUSE_G +#define Light_DiffuseColor_B ATTRIBUTE_LIGHTDIFFUSE_B +#define Light_DiffuseColor_A ATTRIBUTE_LIGHTDIFFUSE_A +#define Light_SpecularColor ATTRIBUTE_LIGHTSPECULAR +#define Light_SpecularColor_R ATTRIBUTE_LIGHTSPECULAR_R +#define Light_SpecularColor_G ATTRIBUTE_LIGHTSPECULAR_G +#define Light_SpecularColor_B ATTRIBUTE_LIGHTSPECULAR_B +#define Light_SpecularColor_A ATTRIBUTE_LIGHTSPECULAR_A +#define Light_AmbientColor ATTRIBUTE_LIGHTAMBIENT +#define Light_AmbientColor_R ATTRIBUTE_LIGHTAMBIENT_R +#define Light_AmbientColor_G ATTRIBUTE_LIGHTAMBIENT_G +#define Light_AmbientColor_B ATTRIBUTE_LIGHTAMBIENT_B +#define Light_AmbientColor_A ATTRIBUTE_LIGHTAMBIENT_A +#define Light_Brightness ATTRIBUTE_BRIGHTNESS +#define Light_LinearFade ATTRIBUTE_LINEARFADE +#define Light_ExponentialFade ATTRIBUTE_EXPFADE +#define Light_AreaWidth ATTRIBUTE_AREAWIDTH +#define Light_AreaHeight ATTRIBUTE_AREAHEIGHT +#define Light_CastShadow ATTRIBUTE_CASTSHADOW +#define Light_ShadowBias ATTRIBUTE_SHDWBIAS +#define Light_ShadowFactor ATTRIBUTE_SHDWFACTOR +#define Light_ShadowMapRes ATTRIBUTE_SHDWMAPRES +#define Light_ShadowMapFar ATTRIBUTE_SHDWMAPFAR +#define Light_ShadowMapFov ATTRIBUTE_SHDWMAPFOV +#define Light_ShadowFilter ATTRIBUTE_SHDWFILTER +#define Model_MeshPath ATTRIBUTE_SOURCEPATH +#define Model_ShadowCaster ATTRIBUTE_SHADOWCASTER +#define Model_TessellationMode ATTRIBUTE_TESSELLATION +#define Model_EdgeTess ATTRIBUTE_EDGETESS +#define Model_InnerTess ATTRIBUTE_INNERTESS +#define Lightmaps_LightmapIndirect ATTRIBUTE_LIGHTMAPINDIRECT +#define Lightmaps_LightmapRadiosity ATTRIBUTE_LIGHTMAPRADIOSITY +#define Lightmaps_LightmapShadow ATTRIBUTE_LIGHTMAPSHADOW +#define Material_Lighting ATTRIBUTE_SHADERLIGHTING +#define Material_BlendMode ATTRIBUTE_BLENDMODE +#define MaterialBase_IblProbe ATTRIBUTE_IBLPROBE +#define Material_DiffuseColor ATTRIBUTE_DIFFUSE +#define Material_DiffuseColor_R ATTRIBUTE_DIFFUSE_R +#define Material_DiffuseColor_G ATTRIBUTE_DIFFUSE_G +#define Material_DiffuseColor_B ATTRIBUTE_DIFFUSE_B +#define Material_DiffuseColor_A ATTRIBUTE_DIFFUSE_A +#define Material_DiffuseMaps_0 ATTRIBUTE_DIFFUSEMAP +#define Material_DiffuseMaps_1 ATTRIBUTE_DIFFUSEMAP2 +#define Material_DiffuseMaps_2 ATTRIBUTE_DIFFUSEMAP3 +#define Material_EmissivePower ATTRIBUTE_EMISSIVEPOWER +#define Material_EmissiveColor ATTRIBUTE_EMISSIVECOLOR +#define Material_EmissiveColor_R ATTRIBUTE_EMISSIVECOLOR_R +#define Material_EmissiveColor_G ATTRIBUTE_EMISSIVECOLOR_G +#define Material_EmissiveColor_B ATTRIBUTE_EMISSIVECOLOR_B +#define Material_EmissiveColor_A ATTRIBUTE_EMISSIVECOLOR_A +#define Material_EmissiveMap ATTRIBUTE_EMISSIVEMAP +#define Material_EmissiveMap2 ATTRIBUTE_EMISSIVEMAP2 +#define Material_SpecularReflection ATTRIBUTE_SPECULARREFLECTION +#define Material_SpecularMap ATTRIBUTE_SPECULARMAP +#define Material_SpecularModel ATTRIBUTE_SPECULARMODEL +#define Material_SpecularTint ATTRIBUTE_SPECULARTINT +#define Material_SpecularTint_R ATTRIBUTE_SPECULARTINT_R +#define Material_SpecularTint_G ATTRIBUTE_SPECULARTINT_G +#define Material_SpecularTint_B ATTRIBUTE_SPECULARTINT_B +#define Material_SpecularTint_A ATTRIBUTE_SPECULARTINT_A +#define Material_IOR ATTRIBUTE_IOR +#define Material_FresnelPower ATTRIBUTE_FRESNELPOWER +#define Material_SpecularAmount ATTRIBUTE_SPECULARAMOUNT +#define Material_SpecularRoughness ATTRIBUTE_SPECULARROUGHNESS +#define Material_RoughnessMap ATTRIBUTE_ROUGHNESSMAP +#define Material_Opacity ATTRIBUTE_OPACITY +#define Material_OpacityMap ATTRIBUTE_OPACITYMAP +#define Material_BumpAmount ATTRIBUTE_BUMPAMOUNT +#define Material_BumpMap ATTRIBUTE_BUMPMAP +#define Material_NormalMap ATTRIBUTE_NORMALMAP +#define Material_DisplaceAmount ATTRIBUTE_DISPLACEAMOUNT +#define Material_DisplacementMap ATTRIBUTE_DISPLACEMENTMAP +#define Material_TranslucentFalloff ATTRIBUTE_TRANSLUCENTFALLOFF +#define Material_TranslucencyMap ATTRIBUTE_TRANSLUCENCYMAP +#define Material_DiffuseLightWrap ATTRIBUTE_DIFFUSELIGHTWRAP +#define Material_ReferencedMaterial ATTRIBUTE_REFERENCEDMATERIAL +#define Material_VertexColors ATTRIBUTE_VERTEXCOLORS +#define Image_ImagePath ATTRIBUTE_SOURCEPATH +#define Image_OffscreenRendererId ATTRIBUTE_SUBPRESENTATION +#define Image_Scale_X ATTRIBUTE_SCALEU +#define Image_Scale_Y ATTRIBUTE_SCALEV +#define Image_Pivot_X ATTRIBUTE_PIVOTU +#define Image_Pivot_Y ATTRIBUTE_PIVOTV +#define Image_Rotation ATTRIBUTE_ROTATIONUV +#define Image_Position_X ATTRIBUTE_POSITIONU +#define Image_Position_Y ATTRIBUTE_POSITIONV +#define Image_MappingMode ATTRIBUTE_MAPPINGMODE +#define Image_HorizontalTilingMode ATTRIBUTE_TILINGMODEHORZ +#define Image_VerticalTilingMode ATTRIBUTE_TILINGMODEVERT +#define Text_Text ATTRIBUTE_TEXTSTRING +#define Text_Font ATTRIBUTE_FONT +#define Text_FontSize ATTRIBUTE_SIZE +#define Text_HorizontalAlignment ATTRIBUTE_HORZALIGN +#define Text_VerticalAlignment ATTRIBUTE_VERTALIGN +#define Text_Leading ATTRIBUTE_LEADING +#define Text_Tracking ATTRIBUTE_TRACKING +#define Text_DropShadow ATTRIBUTE_DROPSHADOW +#define Text_DropShadowStrength ATTRIBUTE_DROPSHADOWSTRENGTH +#define Text_DropShadowOffsetX ATTRIBUTE_DROPSHADOWOFFSETX +#define Text_DropShadowOffsetY ATTRIBUTE_DROPSHADOWOFFSETY +#define Text_WordWrap ATTRIBUTE_WORDWRAP +#define Text_BoundingBox ATTRIBUTE_BOUNDINGBOX +#define Text_BoundingBox_X ATTRIBUTE_BOUNDINGBOX_X +#define Text_BoundingBox_Y ATTRIBUTE_BOUNDINGBOX_Y +#define Text_Elide ATTRIBUTE_ELIDE +#define Text_TextColor ATTRIBUTE_TEXTCOLOR +#define Text_TextColor_R ATTRIBUTE_TEXTCOLOR_R +#define Text_TextColor_G ATTRIBUTE_TEXTCOLOR_G +#define Text_TextColor_B ATTRIBUTE_TEXTCOLOR_B +#define Text_TextColor_A ATTRIBUTE_TEXTCOLOR_A +#define Text_BackColor_R ATTRIBUTE_BACKCOLOR_R +#define Text_BackColor_G ATTRIBUTE_BACKCOLOR_G +#define Text_BackColor_B ATTRIBUTE_BACKCOLOR_B +#define Text_BackColor_A ATTRIBUTE_BACKCOLOR_A +#define Text_UseBackColor ATTRIBUTE_USEBACKCOLOR +#define Text_EnableAcceleratedFont ATTRIBUTE_ENABLEACCELERATEDFONT +#define Path_PathType ATTRIBUTE_PATHTYPE +#define Path_Width ATTRIBUTE_WIDTH +#define Path_LinearError ATTRIBUTE_LINEARERROR +#define Path_EdgeTessAmount ATTRIBUTE_EDGETESSAMOUNT +#define Path_InnerTessAmount ATTRIBUTE_INNERTESSAMOUNT +#define Path_BeginCapping ATTRIBUTE_BEGINCAP +#define Path_BeginCapOffset ATTRIBUTE_BEGINCAPOFFSET +#define Path_BeginCapOpacity ATTRIBUTE_BEGINCAPOPACITY +#define Path_BeginCapWidth ATTRIBUTE_BEGINCAPWIDTH +#define Path_EndCapping ATTRIBUTE_ENDCAP +#define Path_EndCapOffset ATTRIBUTE_ENDCAPOFFSET +#define Path_EndCapOpacity ATTRIBUTE_ENDCAPOPACITY +#define Path_EndCapWidth ATTRIBUTE_ENDCAPWIDTH +#define Path_PaintStyle ATTRIBUTE_PAINTSTYLE +#define Path_PathBuffer ATTRIBUTE_SOURCEPATH +#define SubPath_Closed ATTRIBUTE_CLOSED + +// Fill in implementations for the actual parse tables. +#define HANDLE_QT3DS_RENDER_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseProperty(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_RENDER_VEC3_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name##_X: \ + inParser.ParseProperty(theItem.m_##name.x); \ + break; \ + case Q3DStudio::type##_##name##_Y: \ + inParser.ParseProperty(theItem.m_##name.y); \ + break; \ + case Q3DStudio::type##_##name##_Z: \ + inParser.ParseProperty(theItem.m_##name.z); \ + break; + +#define HANDLE_QT3DS_RENDER_REAL_VEC2_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name##_X: \ + inParser.ParseProperty(theItem.m_##name.x); \ + break; \ + case Q3DStudio::type##_##name##_Y: \ + inParser.ParseProperty(theItem.m_##name.y); \ + break; + +#define HANDLE_QT3DS_RENDER_COLOR_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name##_R: \ + inParser.ParseProperty(theItem.m_##name.x); \ + break; \ + case Q3DStudio::type##_##name##_G: \ + inParser.ParseProperty(theItem.m_##name.y); \ + break; \ + case Q3DStudio::type##_##name##_B: \ + inParser.ParseProperty(theItem.m_##name.z); \ + break; \ + case Q3DStudio::type##_##name##_A: \ + inParser.ParseProperty(theItem.m_##name.w); \ + break; + +#define HANDLE_QT3DS_RENDER_COLOR_VEC3_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseProperty(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_RENDER_TRANSFORM_VEC3_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseProperty(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_RENDER_RADIAN_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseRadianProperty(theItem.m_##name); \ + break; + +// The runtime converts rotations for us. +#define HANDLE_QT3DS_RENDER_VEC3_RADIAN_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name##_X: \ + inParser.ParseProperty(theItem.m_##name.x); \ + break; \ + case Q3DStudio::type##_##name##_Y: \ + inParser.ParseProperty(theItem.m_##name.y); \ + break; \ + case Q3DStudio::type##_##name##_Z: \ + inParser.ParseProperty(theItem.m_##name.z); \ + break; + +#define HANDLE_QT3DS_RENDER_OPACITY_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseOpacityProperty(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_ROTATION_ORDER_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseRotationOrder(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_NODE_ORIENTATION_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseOrientation(theItem.m_Flags); \ + break; + +#define HANDLE_QT3DS_RENDER_DEPTH_TEST_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseInverseBoolean(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_NODE_FLAGS_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseNodeFlagsProperty(theItem.m_Flags, \ + NodeFlagValues::name); \ + break; + +#define HANDLE_QT3DS_NODE_FLAGS_INVERSE_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseNodeFlagsInverseProperty(theItem.m_Flags, \ + NodeFlagValues::name); \ + break; + +#define HANDLE_QT3DS_RENDER_ENUM_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseEnumProperty(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_RENDER_SOURCEPATH_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name: \ + inParser.ParseAndResolveSourcePath(theItem.m_##name); \ + break; + +#define HANDLE_QT3DS_RENDER_ARRAY_PROPERTY(type, name, index, dirty) \ + case Q3DStudio::type##_##name##_##index: \ + inParser.ParseProperty(theItem.m_##name[index]); \ + break; + +#define HANDLE_QT3DS_RENDER_VEC2_PROPERTY(type, name, dirty) \ + case Q3DStudio::type##_##name##_X: \ + inParser.ParseProperty(theItem.m_##name.x); \ + break; \ + case Q3DStudio::type##_##name##_Y: \ + inParser.ParseProperty(theItem.m_##name.y); \ + break; + +struct SSceneTranslator : public Qt3DSTranslator +{ + typedef SScene TNodeType; + SSceneTranslator(Q3DStudio::TElement &inElement, SScene &inRenderObject) + : Qt3DSTranslator(inElement, inRenderObject) + { + } + // Ignored, scenes are always active + void SetActive(bool /*inElementActive*/) {} + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SScene &theItem = *static_cast(m_RenderObject); + + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_SCENE_PROPERTIES + // These are ignored by the renderer + case Q3DStudio::ATTRIBUTE_NAME: + case Q3DStudio::ATTRIBUTE_STARTTIME: + case Q3DStudio::ATTRIBUTE_ENDTIME: + case Q3DStudio::ATTRIBUTE_IMPORTID: + case Q3DStudio::ATTRIBUTE_EYEBALL: + break; + default: + // Unknown attribute + // QT3DS_ASSERT( false ); + break; + } + } + void PostPropertyChanged(const SRuntimePropertyParser &, Q3DStudio::IPresentation &) {} +}; + +struct SNodeTranslator : public Qt3DSTranslator +{ + typedef SNode TNodeType; + SNodeTranslator(Q3DStudio::TElement &inElement, SNode &inRenderObject) + : Qt3DSTranslator(inElement, inRenderObject) + { + SNode &theItem = *static_cast(m_RenderObject); + theItem.m_Flags.SetLocallyPickable(false); + } + void SetActive(bool inElementActive) + { + SNode &theItem = *static_cast(m_RenderObject); + if (theItem.m_Flags.IsActive() != inElementActive) { + theItem.m_Flags.SetActive(inElementActive); + theItem.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty); + } + } + + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SNode &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_NODE_PROPERTIES + case Q3DStudio::ATTRIBUTE_NAME: + case Q3DStudio::ATTRIBUTE_STARTTIME: + case Q3DStudio::ATTRIBUTE_ENDTIME: + case Q3DStudio::ATTRIBUTE_IMPORTID: + case Q3DStudio::ATTRIBUTE_EYEBALL: + // Groups have a source path property on them that we like to ignore. + case Q3DStudio::ATTRIBUTE_SOURCEPATH: + break; + default: + // Unknown attribute + // QT3DS_ASSERT( false ); + break; + } + } + void PostPropertyChanged(const SRuntimePropertyParser &inParser, + Q3DStudio::IPresentation & /*inStudioPresentation*/) + { + SNode &theItem = *static_cast(m_RenderObject); + if (inParser.m_TransformDirty) + theItem.MarkDirty(NodeTransformDirtyFlag::TransformIsDirty); + else if (inParser.m_Dirty) + theItem.MarkDirty(NodeTransformDirtyFlag::TransformNotDirty); + if (inParser.m_TextDirty) + theItem.m_Flags.SetTextDirty(true); + SetActive(Element().GetActive()); + bool isNodePickable = m_Element->IsPickEnabled(); + if (theItem.m_Flags.IsLocallyPickable() != isNodePickable) { + theItem.m_Flags.SetLocallyPickable(isNodePickable); + theItem.MarkDirty(NodeTransformDirtyFlag::TransformNotDirty); + } + } +}; + +struct SLayerTranslator : public SNodeTranslator +{ + typedef SLayer TNodeType; + SLayerTranslator(Q3DStudio::TElement &inElement, SLayer &inRenderObject) + : SNodeTranslator(inElement, inRenderObject) + { + } + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + const char *propName = + Q3DStudio::GetAttributeString((Q3DStudio::EAttribute)inParser.m_PropertyName); + (void)propName; + SLayer &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_LAYER_PROPERTIES + // Ignored + default: + SNodeTranslator::OnSpecificPropertyChange(inParser); + } + } +}; + +struct SLightTranslator : public SNodeTranslator +{ + typedef SLight TNodeType; + SLightTranslator(Q3DStudio::TElement &inElement, SLight &inRenderObject) + : SNodeTranslator(inElement, inRenderObject) + { + } + + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SLight &theItem = *static_cast(m_RenderObject); + // I guess there is no switching of light type in the runtime right now. + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_LIGHT_PROPERTIES + default: + SNodeTranslator::OnSpecificPropertyChange(inParser); + break; + } + } +}; +struct SCameraTranslator : public SNodeTranslator +{ + typedef SCamera TNodeType; + SCameraTranslator(Q3DStudio::TElement &inElement, SCamera &inRenderObject) + : SNodeTranslator(inElement, inRenderObject) + { + } + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SCamera &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_CAMERA_PROPERTIES + default: + SNodeTranslator::OnSpecificPropertyChange(inParser); + break; + } + } +}; + +struct SModelTranslator : public SNodeTranslator +{ + typedef SModel TNodeType; + SModelTranslator(Q3DStudio::TElement &inElement, SModel &inRenderObject) + : SNodeTranslator(inElement, inRenderObject) + { + } + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SModel &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_MODEL_PROPERTIES + default: + SNodeTranslator::OnSpecificPropertyChange(inParser); + break; + } + } +}; + +struct SPathTranslator : public SNodeTranslator +{ + typedef SPath TNodeType; + SPathTranslator(Q3DStudio::TElement &inElement, SPath &inRenderObject) + : SNodeTranslator(inElement, inRenderObject) + { + } + + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SPath &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_PATH_PROPERTIES + default: + SNodeTranslator::OnSpecificPropertyChange(inParser); + break; + } + } +}; + +struct SPathSubPathTranslator : public Qt3DSTranslator +{ + + typedef SPathSubPath TNodeType; + + SPathSubPathTranslator(Q3DStudio::TElement &inElement, SPathSubPath &inRenderObject) + : Qt3DSTranslator(inElement, inRenderObject) + { + } + + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SPathSubPath &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_PATH_SUBPATH_PROPERTIES + default: + break; + } + } + + void PostPropertyChanged(const SRuntimePropertyParser &inParser, + Q3DStudio::IPresentation & /*inStudioPresentation*/) + { + SPathSubPath &theItem = *static_cast(m_RenderObject); + qt3ds::render::IPathManager &theManager = inParser.m_RenderContext.GetPathManager(); + QT3DSU32 numAnchors = 0; + bool updatePath = false; + CRegisteredString theAnchorType = + inParser.m_RenderContext.GetStringTable().RegisterStr("PathAnchorPoint"); + for (Q3DStudio::TElement *theChild = Element().GetChild(); theChild; + theChild = theChild->GetSibling()) { + if (theChild->GetType() == theAnchorType) { + ++numAnchors; + if (theChild->IsDirty()) + updatePath = true; + } + } + if (updatePath) { + NVDataRef thePathBuffer = + theManager.ResizePathSubPathBuffer(theItem, numAnchors); + if (thePathBuffer.size()) { + QT3DSU32 anchorIndex = 0; + for (Q3DStudio::TElement *theChild = Element().GetChild(); theChild; + theChild = theChild->GetSibling()) { + if (theChild->GetType() == theAnchorType) { + if (theChild->IsDirty()) { + qt3ds::render::SPathAnchorPoint &thePoint(thePathBuffer[anchorIndex]); + + for (QT3DSI32 idx = 0, end = theChild->GetAttributeCount(); idx < end; + ++idx) { + qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo = + theChild->GetPropertyByIndex(idx); + switch (thePropInfo.first.GetNameHash()) { + case Q3DStudio::ATTRIBUTE_POSITION_X: + thePoint.m_Position.x = thePropInfo.second->m_FLOAT; + break; + case Q3DStudio::ATTRIBUTE_POSITION_Y: + thePoint.m_Position.y = thePropInfo.second->m_FLOAT; + break; + case Q3DStudio::ATTRIBUTE_INCOMINGANGLE: + thePoint.m_IncomingAngle = thePropInfo.second->m_FLOAT; + thePoint.m_OutgoingAngle = thePoint.m_IncomingAngle + 180.0f; + break; + case Q3DStudio::ATTRIBUTE_INCOMINGDISTANCE: + thePoint.m_IncomingDistance = thePropInfo.second->m_FLOAT; + break; + case Q3DStudio::ATTRIBUTE_OUTGOINGDISTANCE: + thePoint.m_OutgoingDistance = thePropInfo.second->m_FLOAT; + break; + default: // ignored + break; + } + } + } + ++anchorIndex; + } + } + } + } + } +}; + +struct SDefaultMaterialTranslator : public Qt3DSTranslator +{ + typedef SDefaultMaterial TNodeType; + SDefaultMaterialTranslator(Q3DStudio::TElement &inElement, SDefaultMaterial &inRenderObject) + : Qt3DSTranslator(inElement, inRenderObject) + { + } + // Right now materials do not respect the active flag + void SetActive(bool) {} + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SDefaultMaterial &theItem = *static_cast(m_RenderObject); + // There is no render-time caching on a material, so the dirty flag doesn't do much. + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_MATERIAL_PROPERTIES + + case Q3DStudio::ATTRIBUTE_NAME: + case Q3DStudio::ATTRIBUTE_STARTTIME: + case Q3DStudio::ATTRIBUTE_ENDTIME: + case Q3DStudio::ATTRIBUTE_IMPORTID: + case Q3DStudio::ATTRIBUTE_EYEBALL: + case Q3DStudio::ATTRIBUTE_SOURCEPATH: + break; + default: + // Unknown attribute + // QT3DS_ASSERT( false ); + break; + } + } + + void PostPropertyChanged(const SRuntimePropertyParser &, Q3DStudio::IPresentation &) + { + SDefaultMaterial &theItem = *static_cast(m_RenderObject); + theItem.m_Dirty.SetDirty(); + } +}; + +struct SImageTranslator : public Qt3DSTranslator +{ + typedef SImage TNodeType; + SImageTranslator(Q3DStudio::TElement &inElement, SImage &inRenderObject) + : Qt3DSTranslator(inElement, inRenderObject) + { + } + + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SImage &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_IMAGE_PROPERTIES + case Q3DStudio::ATTRIBUTE_STARTTIME: + case Q3DStudio::ATTRIBUTE_ENDTIME: + case Q3DStudio::ATTRIBUTE_NAME: + case Q3DStudio::ATTRIBUTE_EYEBALL: + break; + default: + // Unknown attribute + // QT3DS_ASSERT( false ); + break; + } + } + void PostPropertyChanged(const SRuntimePropertyParser &inParser, Q3DStudio::IPresentation &) + { + SImage &theItem = *static_cast(m_RenderObject); + if (inParser.m_Dirty) + theItem.m_Flags.SetDirty(true); + if (inParser.m_TransformDirty) + theItem.m_Flags.SetTransformDirty(true); + } +}; + +struct SReferencedMaterialTranslator : public Qt3DSTranslator +{ + typedef SReferencedMaterial TNodeType; + SReferencedMaterialTranslator(Q3DStudio::TElement &inElement, TNodeType &inRenderObject) + : Qt3DSTranslator(inElement, inRenderObject) + { + } + + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + TNodeType &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_REFERENCED_MATERIAL_PROPERTIES + case Q3DStudio::ATTRIBUTE_STARTTIME: + case Q3DStudio::ATTRIBUTE_ENDTIME: + case Q3DStudio::ATTRIBUTE_NAME: + case Q3DStudio::ATTRIBUTE_EYEBALL: + break; + default: + // Unknown attribute + // QT3DS_ASSERT( false ); + break; + } + } + void PostPropertyChanged(const SRuntimePropertyParser &inParser, Q3DStudio::IPresentation &) + { + TNodeType &theItem = *static_cast(m_RenderObject); + if (inParser.m_Dirty) + theItem.m_Dirty.SetDirty(); + } +}; + +struct STextTranslator : public SNodeTranslator +{ + typedef SText TNodeType; + STextTranslator(Q3DStudio::TElement &inElement, SText &inRenderObject) + : SNodeTranslator(inElement, inRenderObject) + { + } + void OnSpecificPropertyChange(SRuntimePropertyParser &inParser) + { + SText &theItem = *static_cast(m_RenderObject); + switch (inParser.m_PropertyName) { + ITERATE_QT3DS_RENDER_TEXT_PROPERTIES + case Q3DStudio::ATTRIBUTE_TEXTTYPE: + case Q3DStudio::ATTRIBUTE_RENDERSTYLE: + case Q3DStudio::ATTRIBUTE_HORZSCROLL: + case Q3DStudio::ATTRIBUTE_VERTSCROLL: + case Q3DStudio::ATTRIBUTE_BOXHEIGHT: + case Q3DStudio::ATTRIBUTE_BOXWIDTH: + case Q3DStudio::ATTRIBUTE_REMOTESTRINGSOURCE: + case Q3DStudio::ATTRIBUTE_CACHEDTEXTSTRING: + // These text properties are ignored for now. + break; + default: + SNodeTranslator::OnSpecificPropertyChange(inParser); + break; + } + } +}; + +struct SEffectPropertyEntry +{ + Q3DStudio::EAttributeType m_AttributeType; + QT3DSU32 m_PropertyOffset; // offset into the property array for the property def + QT3DSU32 m_DataOffset; + SEffectPropertyEntry(Q3DStudio::EAttributeType attType, QT3DSU32 poff, QT3DSU32 doff = 0) + : m_AttributeType(attType) + , m_PropertyOffset(poff) + , m_DataOffset(doff) + { + } +}; + +struct SDynamicObjectTranslatorContext : public STranslatorContext +{ + typedef nvhash_map THashToOffsetMap; + THashToOffsetMap m_PropertyHashes; + NVAllocatorCallback &m_Allocator; + Qt3DSString m_Workspace; + SDynamicObjectTranslatorContext(NVAllocatorCallback &inCallback) + : m_PropertyHashes(inCallback, "SEffectTranslatorContext::PropertyHashes") + , m_Allocator(inCallback) + { + } + ~SDynamicObjectTranslatorContext() {} + void AddEffectExtendedProperty(const qt3ds::render::dynamic::SPropertyDefinition &thePropDef, + const char *inExtension, Q3DStudio::EAttributeType inType, + Qt3DSString &ioStringBuilder, QT3DSU32 inOffset, QT3DSU32 dataOffset) + { + ioStringBuilder.fromUtf8(thePropDef.m_Name.c_str()); + ioStringBuilder.append(inExtension); + Q3DStudio::INT32 theHash = Q3DStudio::CHash::HashAttribute( + ioStringBuilder.toUtf8().constData()); + m_PropertyHashes.insert( + eastl::make_pair(theHash, SEffectPropertyEntry(inType, inOffset, dataOffset))); + } + void BuildPropertyHashes(NVConstDataRef inProperties) + { + if (m_PropertyHashes.size() == 0) { + qt3ds::foundation::Qt3DSString theNameBuilder; + for (QT3DSU32 idx = 0, end = inProperties.size(); idx < end; ++idx) { + const qt3ds::render::dynamic::SPropertyDefinition &thePropDef = inProperties[idx]; + switch (thePropDef.m_DataType) { + case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32: + m_PropertyHashes.insert(eastl::make_pair( + Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()), + SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_FLOAT, idx))); + break; + case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool: + m_PropertyHashes.insert( + eastl::make_pair(Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()), + SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_BOOL, idx))); + break; + case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32: + if (thePropDef.m_IsEnumProperty == false) { + m_PropertyHashes.insert(eastl::make_pair( + Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()), + SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_INT32, idx))); + } else { + m_PropertyHashes.insert(eastl::make_pair( + Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()), + SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_STRING, idx))); + } + break; + case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2: + AddEffectExtendedProperty(thePropDef, ".x", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 0); + AddEffectExtendedProperty(thePropDef, ".y", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, sizeof(QT3DSF32)); + break; + case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3: + AddEffectExtendedProperty(thePropDef, ".x", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 0); + AddEffectExtendedProperty(thePropDef, ".y", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, sizeof(QT3DSF32)); + AddEffectExtendedProperty(thePropDef, ".z", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 2 * sizeof(QT3DSF32)); + + AddEffectExtendedProperty(thePropDef, ".r", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 0); + AddEffectExtendedProperty(thePropDef, ".g", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, sizeof(QT3DSF32)); + AddEffectExtendedProperty(thePropDef, ".b", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 2 * sizeof(QT3DSF32)); + break; + case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4: + AddEffectExtendedProperty(thePropDef, ".x", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 0); + AddEffectExtendedProperty(thePropDef, ".y", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, sizeof(QT3DSF32)); + AddEffectExtendedProperty(thePropDef, ".z", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 2 * sizeof(QT3DSF32)); + AddEffectExtendedProperty(thePropDef, ".w", Q3DStudio::ATTRIBUTETYPE_FLOAT, + theNameBuilder, idx, 3 * sizeof(QT3DSF32)); + break; + case qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr: + case qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr: + m_PropertyHashes.insert(eastl::make_pair( + Q3DStudio::CHash::HashAttribute(thePropDef.m_Name.c_str()), + SEffectPropertyEntry(Q3DStudio::ATTRIBUTETYPE_STRING, idx))); + break; + case qt3ds::render::NVRenderShaderDataTypes::NVRenderDataBufferPtr: + break; + default: + QT3DS_ASSERT(false); + break; + } + } + } + } + void ApplyChanges(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext, + SDynamicObject &inObject, Q3DStudio::TElement &element, + IDynamicObjectSystem &inSystem) + { + if (element.GetActive()) { + NVConstDataRef theProperties = + inSystem.GetProperties(inObject.m_ClassName); + BuildPropertyHashes(theProperties); + SDynamicObject &theItem(inObject); + for (long idx = 0, end = element.GetAttributeCount(); idx < end; ++idx) { + qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo = + *element.GetPropertyByIndex(idx); + THashToOffsetMap::iterator theFind = + m_PropertyHashes.find(thePropInfo.first.GetNameHash()); + if (theFind != m_PropertyHashes.end()) { + const SEffectPropertyEntry &theEntry(theFind->second); + const qt3ds::render::dynamic::SPropertyDefinition &theDefinition( + theProperties[theEntry.m_PropertyOffset]); + if (theEntry.m_AttributeType + == (Q3DStudio::EAttributeType)thePropInfo.first.m_Type) { + switch (theEntry.m_AttributeType) { + case Q3DStudio::ATTRIBUTETYPE_BOOL: + theItem.SetPropertyValue(theDefinition, + thePropInfo.second->m_INT32 ? true : false); + break; + case Q3DStudio::ATTRIBUTETYPE_FLOAT: + theItem.SetPropertyValue(theDefinition, thePropInfo.second->m_FLOAT, + theEntry.m_DataOffset); + break; + case Q3DStudio::ATTRIBUTETYPE_INT32: + theItem.SetPropertyValue(theDefinition, + (QT3DSI32)thePropInfo.second->m_INT32); + break; + case Q3DStudio::ATTRIBUTETYPE_STRING: { + CRegisteredString theStr = + element.GetBelongedPresentation()->GetStringTable().HandleToStr( + thePropInfo.second->m_StringHandle); + theItem.SetPropertyValue(theDefinition, theStr.c_str(), + inPresentation.m_PresentationDirectory.c_str(), + m_Workspace, inRenderContext.GetStringTable()); + } break; + default: + // QT3DS_ASSERT( false ); + break; + } + } else { + // QT3DS_ASSERT( false ); + } + } + } + theItem.m_Flags.SetDirty(true); + } + } +}; + +struct SEffectTranslator : public Qt3DSTranslator +{ + typedef SEffect TNodeType; + SEffectTranslator(Q3DStudio::TElement &inElement, SEffect &inRenderObject, + NVAllocatorCallback &inCallback) + : Qt3DSTranslator(inElement, inRenderObject) + { + m_TranslatorContext = QT3DS_NEW(inCallback, SDynamicObjectTranslatorContext)(inCallback); + } + + void OnElementChanged(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &) + { + SRuntimePropertyParser theParser(inPresentation, inRenderContext, *m_Element); + SEffect &theItem = *static_cast(m_RenderObject); + static_cast(m_TranslatorContext) + ->ApplyChanges(inPresentation, inRenderContext, theItem, Element(), + inRenderContext.GetDynamicObjectSystem()); + theItem.SetActive(Element().GetActive(), inRenderContext.GetEffectSystem()); + } +}; + +struct SCustomMaterialTranslator : public Qt3DSTranslator +{ + typedef SCustomMaterial TNodeType; + SCustomMaterialTranslator(Q3DStudio::TElement &inElement, SCustomMaterial &inRenderObject, + NVAllocatorCallback &inCallback) + : Qt3DSTranslator(inElement, inRenderObject) + { + m_TranslatorContext = QT3DS_NEW(inCallback, SDynamicObjectTranslatorContext)(inCallback); + } + + void OnElementChanged(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &) + { + SRuntimePropertyParser theParser(inPresentation, inRenderContext, *m_Element); + SCustomMaterial &theItem = *static_cast(m_RenderObject); + static_cast(m_TranslatorContext) + ->ApplyChanges(inPresentation, inRenderContext, theItem, Element(), + inRenderContext.GetDynamicObjectSystem()); + bool active = m_Element->GetActive(); + if (active != theItem.m_Flags.IsActive()) { + theItem.m_Flags.SetActive(active); + ICustomMaterialSystem &theSystem(inRenderContext.GetCustomMaterialSystem()); + theSystem.OnMaterialActivationChange(theItem, active); + } + } +}; + +struct SRenderPluginTranslatorContext : public STranslatorContext +{ + NVAllocatorCallback &m_Allocator; + nvhash_map m_AttribHashIndexMap; + nvvector m_PropertyUpdates; + SRenderPluginTranslatorContext(NVAllocatorCallback &alloc) + : m_Allocator(alloc) + , m_AttribHashIndexMap(alloc, "SRenderPluginTranslatorContext::AttribIndexMap") + , m_PropertyUpdates(alloc, "SRenderPluginTranslatorContext::m_PropertyUpdates") + { + } + void ReverseMap(CRegisteredString str) + { + m_AttribHashIndexMap.insert( + eastl::make_pair(Q3DStudio::CHash::HashAttribute(str.c_str()), str)); + } +}; + +struct SRenderPluginTranslator : public Qt3DSTranslator +{ + typedef SRenderPlugin TNodeType; + SRenderPluginTranslator(Q3DStudio::TElement &inElement, SRenderPlugin &inRenderObject, + NVAllocatorCallback &inCallback) + : Qt3DSTranslator(inElement, inRenderObject) + { + m_TranslatorContext = QT3DS_NEW(inCallback, SRenderPluginTranslatorContext)(inCallback); + } + + void OnElementChanged(SPresentation & /*inPresentation*/, IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &) + { + SRenderPlugin &theItem = *static_cast(m_RenderObject); + theItem.m_Flags.SetActive(Element().GetActive()); + IRenderPluginInstance *theInstance = + inRenderContext.GetRenderPluginManager().GetOrCreateRenderPluginInstance( + theItem.m_PluginPath, &theItem); + if (theInstance != NULL) { + IRenderPluginClass &theClass(theInstance->GetPluginClass()); + SRenderPluginTranslatorContext &theTransContext = + static_cast(*m_TranslatorContext); + if (theTransContext.m_AttribHashIndexMap.empty()) { + NVConstDataRef theProperties( + theClass.GetRegisteredProperties()); + for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) { + const SRenderPluginPropertyDeclaration &theDec(theProperties[idx]); + switch (theDec.m_Type) { + case SRenderPluginPropertyTypes::Boolean: + theTransContext.ReverseMap(theDec.m_Name); + break; + case SRenderPluginPropertyTypes::Float: + theTransContext.ReverseMap(theDec.m_Name); + break; + case SRenderPluginPropertyTypes::Long: + theTransContext.ReverseMap(theDec.m_Name); + break; + case SRenderPluginPropertyTypes::String: + theTransContext.ReverseMap(theDec.m_Name); + break; + case SRenderPluginPropertyTypes::Vector2: + theTransContext.ReverseMap( + theClass.GetPropertyValueInfo(theDec.m_StartOffset).first); + theTransContext.ReverseMap( + theClass.GetPropertyValueInfo(theDec.m_StartOffset + 1).first); + break; + case SRenderPluginPropertyTypes::Vector3: + case SRenderPluginPropertyTypes::Color: + theTransContext.ReverseMap( + theClass.GetPropertyValueInfo(theDec.m_StartOffset).first); + theTransContext.ReverseMap( + theClass.GetPropertyValueInfo(theDec.m_StartOffset + 1).first); + theTransContext.ReverseMap( + theClass.GetPropertyValueInfo(theDec.m_StartOffset + 2).first); + break; + default: + // QT3DS_ASSERT( false ); + break; + } + } + } // ok, now we have an efficient mapping from attribute to plugin value name. + theTransContext.m_PropertyUpdates.clear(); + for (long idx = 0, end = Element().GetAttributeCount(); idx < end; ++idx) { + qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo = + *Element().GetPropertyByIndex(idx); + nvhash_map::iterator theFind = + theTransContext.m_AttribHashIndexMap.find(thePropInfo.first.GetNameHash()); + if (theFind != theTransContext.m_AttribHashIndexMap.end()) { + CRegisteredString thePropName(theFind->second); + Q3DStudio::EAttributeType theType = + (Q3DStudio::EAttributeType)thePropInfo.first.m_Type; + switch (theType) { + case Q3DStudio::ATTRIBUTETYPE_BOOL: + theTransContext.m_PropertyUpdates.push_back(SRenderPropertyValueUpdate( + thePropName, thePropInfo.second->m_INT32 ? true : false)); + break; + case Q3DStudio::ATTRIBUTETYPE_FLOAT: + theTransContext.m_PropertyUpdates.push_back( + SRenderPropertyValueUpdate(thePropName, thePropInfo.second->m_FLOAT)); + break; + case Q3DStudio::ATTRIBUTETYPE_INT32: + theTransContext.m_PropertyUpdates.push_back(SRenderPropertyValueUpdate( + thePropName, (QT3DSI32)thePropInfo.second->m_INT32)); + break; + case Q3DStudio::ATTRIBUTETYPE_STRING: { + CRegisteredString theStr = inRenderContext.GetStringTable().HandleToStr( + thePropInfo.second->m_StringHandle); + theTransContext.m_PropertyUpdates.push_back( + SRenderPropertyValueUpdate(thePropName, theStr)); + } break; + default: + // QT3DS_ASSERT( false ); + break; + } + } + } + if (theTransContext.m_PropertyUpdates.empty() == false) { + theInstance->Update(toConstDataRef(theTransContext.m_PropertyUpdates.data(), + theTransContext.m_PropertyUpdates.size())); + } + } + } +}; +} + +Qt3DSTranslator::Qt3DSTranslator(Q3DStudio::TElement &inElement, SGraphObject &inRenderObject) + : m_DirtyIndex(QT3DS_MAX_U32) + , m_Element(&inElement) + , m_RenderObject(&inRenderObject) + , m_TranslatorContext(NULL) +{ + Element().SetAssociation(reinterpret_cast(this)); + inRenderObject.m_UserData = STaggedPointer(this); +} + +void Qt3DSTranslator::Save(SWriteBuffer &inWriteBuffer, QT3DSU32 inGraphObjectOffset) +{ + // We have to start on pointer aligned boundaries. + QT3DS_ASSERT(inWriteBuffer.size() % 4 == 0); + QT3DSU32 theOffset = inWriteBuffer.size(); + inWriteBuffer.write(*this); + Qt3DSTranslator *theNewTranslator = + reinterpret_cast(inWriteBuffer.begin() + theOffset); + theNewTranslator->m_DirtyIndex = QT3DS_MAX_U32; + if (theNewTranslator->m_Element) + theNewTranslator->m_Element = m_Element->GetBelongedPresentation() + ->GetApplication() + .GetElementAllocator() + .GetRemappedElementAddress(m_Element); + size_t *graphObjPtr = reinterpret_cast(&theNewTranslator->m_RenderObject); + *graphObjPtr = inGraphObjectOffset; +} + +Qt3DSTranslator *Qt3DSTranslator::GetTranslatorFromGraphNode(SGraphObject &inObject) +{ + return inObject.m_UserData.DynamicCast(); +} + +namespace { +struct SPresentationTranslator; +struct SEffectTranslator; +template +struct STranslatorCreator +{ + static TTranslatorType *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject, + NVAllocatorCallback &inAllocator) + { + typedef typename TTranslatorType::TNodeType TNodeType; + // This assert needs to be here because we serialize all translators generically without + // regard for type. + StaticAssert::valid_expression(); + return QT3DS_NEW(inAllocator, TTranslatorType)(inElement, static_cast(inObject)); + } + static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &) + { + typedef typename TTranslatorType::TNodeType TNodeType; + // Initialize the vtable. + new (&inTranslator) TTranslatorType(inTranslator.Element(), + static_cast(inTranslator.RenderObject())); + } + + static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation, + IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &inStudioPresentation) + { + TTranslatorType &theTranslator(static_cast(inTranslator)); + SRuntimePropertyParser theParser(inPresentation, inRenderContext, *theTranslator.m_Element); + if (theTranslator.Element().GetActive()) { + // Don't push properties from inactive elements. + for (long idx = 0, end = theTranslator.Element().GetAttributeCount(); idx < end; + ++idx) { + qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo = + *theTranslator.Element().GetPropertyByIndex(idx); + theParser.Setup(thePropInfo.first.GetNameHash(), *thePropInfo.second, + (Q3DStudio::EAttributeType)thePropInfo.first.m_Type); + // right now, this is the best we can do because the attribute's dirty system + // is all jacked up. + theTranslator.OnSpecificPropertyChange(theParser); + } + // same for dynamic properties + for (long idx = 0, end = theTranslator.Element().GetDynamicAttributeCount(); idx < end; + ++idx) { + qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo = + *theTranslator.Element().GetDynamicPropertyByIndex(idx); + theParser.Setup(thePropInfo.first.GetNameHash(), *thePropInfo.second, + (Q3DStudio::EAttributeType)thePropInfo.first.m_Type); + // right now, this is the best we can do because the attribute's dirty system + // is all jacked up. + theTranslator.OnSpecificPropertyChange(theParser); + } + // Set appropriate dirty flags + } + theTranslator.PostPropertyChanged(theParser, inStudioPresentation); + } +}; + +template <> +struct STranslatorCreator +{ + static Qt3DSTranslator *Create(Q3DStudio::TElement &, SGraphObject &, NVAllocatorCallback &) + { + return NULL; + } + static void InitializeTranslator(Qt3DSTranslator &, NVAllocatorCallback &) {} + static void OnElementChanged(Qt3DSTranslator & /*inTranslator*/, + SPresentation & /*inPresentation*/ + , + IQt3DSRenderContext & /*inRenderContext*/, + Q3DStudio::IPresentation & /*inStudioPresentation*/) + { + QT3DS_ASSERT(false); + } +}; + +template <> +struct STranslatorCreator +{ + static SEffectTranslator *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject, + NVAllocatorCallback &inAllocator) + { + typedef SEffectTranslator::TNodeType TNodeType; + // This assert needs to be here because we serialize all translators generically without + // regard for type. + StaticAssert::valid_expression(); + return QT3DS_NEW(inAllocator, SEffectTranslator)(inElement, static_cast(inObject), + inAllocator); + } + + static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &inAllocator) + { + typedef SEffectTranslator::TNodeType TNodeType; + // Initialize the vtable. + new (&inTranslator) + SEffectTranslator(inTranslator.Element(), + static_cast(inTranslator.RenderObject()), inAllocator); + } + static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation, + IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &inStudioPresentation) + { + static_cast(inTranslator) + .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation); + } +}; + +template <> +struct STranslatorCreator +{ + static SCustomMaterialTranslator *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject, + NVAllocatorCallback &inAllocator) + { + typedef SCustomMaterialTranslator::TNodeType TNodeType; + // This assert needs to be here because we serialize all translators generically without + // regard for type. + StaticAssert::valid_expression(); + return QT3DS_NEW(inAllocator, SCustomMaterialTranslator)( + inElement, static_cast(inObject), inAllocator); + } + + static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &inAllocator) + { + typedef SCustomMaterialTranslator::TNodeType TNodeType; + // Initialize the vtable. + new (&inTranslator) SCustomMaterialTranslator( + inTranslator.Element(), static_cast(inTranslator.RenderObject()), + inAllocator); + } + + static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation, + IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &inStudioPresentation) + { + static_cast(inTranslator) + .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation); + } +}; + +template <> +struct STranslatorCreator +{ + static SRenderPluginTranslator *Create(Q3DStudio::TElement &inElement, SGraphObject &inObject, + NVAllocatorCallback &inAllocator) + { + typedef SRenderPluginTranslator::TNodeType TNodeType; + // This assert needs to be here because we serialize all translators generically without + // regard for type. + StaticAssert::valid_expression(); + return QT3DS_NEW(inAllocator, SRenderPluginTranslator)( + inElement, static_cast(inObject), inAllocator); + } + + static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &inAllocator) + { + typedef SRenderPluginTranslator::TNodeType TNodeType; + // Initialize the vtable. + new (&inTranslator) SRenderPluginTranslator( + inTranslator.Element(), static_cast(inTranslator.RenderObject()), + inAllocator); + } + static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation, + IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &inStudioPresentation) + { + static_cast(inTranslator) + .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation); + } +}; +} +Qt3DSTranslator *Qt3DSTranslator::CreateTranslatorForElement(Q3DStudio::TElement &inElement, + SGraphObject &inObject, + NVAllocatorCallback &inAlloc) +{ + Qt3DSTranslator *theTranslator = NULL; + switch (inObject.m_Type) { +#define QT3DS_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \ + case GraphObjectTypes::type: \ + theTranslator = \ + STranslatorCreator::Create(inElement, inObject, inAlloc); \ + break; + QT3DS_RENDER_ITERATE_GRAPH_OBJECT_TYPES +#undef QT3DS_RENDER_HANDL_GRAPH_OBJECT_TYPE + default: + QT3DS_ASSERT(false); + break; + } + return theTranslator; +} + +void Qt3DSTranslator::OnElementChanged(SPresentation &inPresentation, + IQt3DSRenderContext &inRenderContext, + Q3DStudio::IPresentation &inStudioPresentation) +{ + switch (m_RenderObject->m_Type) { +#define QT3DS_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \ + case GraphObjectTypes::type: \ + STranslatorCreator::OnElementChanged( \ + *this, inPresentation, inRenderContext, inStudioPresentation); \ + break; + QT3DS_RENDER_ITERATE_GRAPH_OBJECT_TYPES +#undef QT3DS_RENDER_HANDL_GRAPH_OBJECT_TYPE + default: + QT3DS_ASSERT(false); + break; + } +} + +Qt3DSTranslator *Qt3DSTranslator::LoadTranslator(SDataReader &inReader, size_t inElemOffset, + NVDataRef inSGSection, + NVAllocatorCallback &inAllocator) +{ + // Reader points to a new translator but we don't know what type + QT3DSU8 *theTranslatorStart = inReader.m_CurrentPtr; + // Make sure things are aligned + (void)theTranslatorStart; + QT3DS_ASSERT((size_t)theTranslatorStart % 4 == 0); + Qt3DSTranslator *theTranslator = inReader.Load(); + if (theTranslator) { + size_t *elemPtr = reinterpret_cast(&theTranslator->m_Element); + *elemPtr += inElemOffset; + size_t *graphObjPtr = reinterpret_cast(&theTranslator->m_RenderObject); + size_t sgSectionStart = reinterpret_cast(inSGSection.begin()); + *graphObjPtr += sgSectionStart; + // Call actual constructor to initialize vtable. + switch (theTranslator->RenderObject().m_Type) { +#define QT3DS_RENDER_HANDL_GRAPH_OBJECT_TYPE(type) \ + case GraphObjectTypes::type: \ + STranslatorCreator::InitializeTranslator(*theTranslator, \ + inAllocator); \ + break; + QT3DS_RENDER_ITERATE_GRAPH_OBJECT_TYPES +#undef QT3DS_RENDER_HANDL_GRAPH_OBJECT_TYPE + default: + QT3DS_ASSERT(false); + break; + } + } + return theTranslator; +} +Q3DStudio::IPresentation * +Qt3DSTranslator::GetPresentationFromPresentation(SPresentation &inPresentation) +{ + return inPresentation.m_UserData.DynamicCast(); +} + +void Qt3DSTranslator::InitializePointerTags(IStringTable &) +{ + g_TranslatorTag = 0x0044FEED; + g_PresentationTag = 0x0022ABBA; +} + +void Qt3DSTranslator::AssignUserData(Q3DStudio::IPresentation &inPresentation, + SPresentation &inGraphPresentation) +{ + inGraphPresentation.m_UserData = STaggedPointer(&inPresentation); +} diff --git a/src/engine/Qt3DSRuntimeView.cpp b/src/engine/Qt3DSRuntimeView.cpp new file mode 100644 index 0000000..c1f3b3d --- /dev/null +++ b/src/engine/Qt3DSRuntimeView.cpp @@ -0,0 +1,862 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#include "Qt3DSRuntimeView.h" +#include "Qt3DSTegraInputEngine.h" +#include "Qt3DSDataLogger.h" +#include "Qt3DSFileStream.h" +#include "Qt3DSArray.h" +#include "Qt3DSApplication.h" +#include "foundation/FileTools.h" +#include "Qt3DSIPresentation.h" +#include "Qt3DSPresentation.h" +#include "EASTL/string.h" +#include "Qt3DSMemory.h" +#include "Qt3DSKernelTypes.h" +#include "Qt3DSRenderContextCore.h" +#include "Qt3DSRenderer.h" +#include "Qt3DSRenderBufferManager.h" +#include "Qt3DSRenderRuntimeBindingImpl.h" +#include "Qt3DSImportMesh.h" + +#include "Qt3DSDLLManager.h" +#include "foundation/Qt3DSSimpleTypes.h" +#include "foundation/TrackingAllocator.h" +// For perf log timestamp +#include +#include "Qt3DSArray.h" +// For perf log timestamp +#include + +#ifdef _LINUXPLATFORM +#include +#include +#endif + +#ifdef ANDROID +#include +#endif + +#include +#include + +//============================================================================== +// Namespace +//============================================================================== +namespace qt3ds { +namespace render { +extern qt3ds::foundation::MallocAllocator g_BaseAllocator; +} +} + +namespace Q3DStudio { + +namespace { + +bool CaselessEqual(const char *lhs, const char *rhs) +{ + if (lhs == nullptr) + lhs = ""; + if (rhs == nullptr) + rhs = ""; + return Q3DStudio_stricmp(lhs, rhs) == 0; +} + +CInputEngine *CreateInputEngine() +{ + return Q3DStudio_virtual_new(CTegraInputEngine) CTegraInputEngine(); +} + +static eastl::string *theAppDir = nullptr; +const eastl::string &GetAppDir(const eastl::string &inAppExe) +{ + if (!theAppDir) + theAppDir = new eastl::string; +#ifndef __ANDROID__ + theAppDir->assign(inAppExe.empty() == false ? inAppExe : ""); +#ifdef Qt3DS_OS_LINUX + char theBuf[1024] = { 0 }; + int rc = readlink("/proc/self/exe", theBuf, sizeof(theBuf)); + if (rc > 0) + theAppDir->assign(theBuf); +#endif +#ifdef Qt3DS_OS_QNX + char theBuf[1024] = { 0 }; + FILE *exefile = fopen("/proc/self/exefile", "r"); + if (exefile != nullptr) { + fgets(theBuf, sizeof(theBuf), exefile); + fclose(exefile); + theAppDir->assign(theBuf); + } +#endif + eastl::string::size_type pos = theAppDir->find_last_of("\\/"); + if (pos != eastl::string::npos) + *theAppDir = theAppDir->substr(0, pos); + theAppDir->append("\\"); +#endif + return *theAppDir; +} +} + +using namespace qt3ds; +using namespace qt3ds::foundation; + +class CRuntimeView : public IRuntimeView +{ + //============================================================================== + // Fields + //============================================================================== +private: + ITegraApplicationRenderEngine *m_RenderEngine; ///< Handles all rendering functions + CTegraInputEngine *m_InputEngine; ///< Handles all user input events + // Pre graphics init objects + NVScopedRefCounted m_RuntimeFactoryCore; + ///< Base application before graphics + NVScopedRefCounted m_ApplicationCore; + + // Post graphics init objects + NVScopedRefCounted m_RuntimeFactory; + NVScopedRefCounted m_Application; ///< Application after graphics + ///< Currently loaded presentation, this should be removed in the future + CPresentation *m_Presentation; + + CPausingTimeProvider m_TimeProvider; + IWindowSystem &m_WindowSystem; + IAudioPlayer *m_AudioPlayer; + + volatile QT3DSI32 mRefCount; + + qt3ds::Qt3DSAssetVisitor *m_visitor; + bool m_showOnScreenStats; + QElapsedTimer *m_startupTimer; + qint64 m_startupTime; + +public: + CRuntimeView(ITimeProvider &inTimeProvider, IWindowSystem &inWindowSystem, + IAudioPlayer *inAudioPlayer, QElapsedTimer *startupTimer); + ~CRuntimeView() override; + + QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(qt3ds::render::g_BaseAllocator) + + bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override; + bool HasOfflineLoadingCompleted() override; + bool InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading) override; + + void Cleanup() override; + + bool CanRender() override; + void Render() override; + bool WasLastFrameDirty() override; + + bool HandleMessage(const QEvent *inEvent) override; + + void Pause() override; + void UnPause() override; + bool IsPaused() override; + void setAssetVisitor(qt3ds::Qt3DSAssetVisitor *) override; + + INT32 GetFrameCount() override; + void showOnScreenStats(bool) override; + + CInputEngine *GetInputEngine() override; + // Only valid after InitializeGraphics + ITegraApplicationRenderEngine *GetTegraRenderEngine() override { return m_RenderEngine; } + + void GoToSlideByName(const char *elementPath, const char *slideName) override; + void GoToSlideByIndex(const char *elementPath, const int slideIndex) override; + void GoToSlideRelative(const char *elementPath, const bool next, const bool wrap) override; + bool GetSlideInfo(const char *elementPath, int ¤tIndex, int &previousIndex, + QString ¤tName, QString &previousName) override; + void SetPresentationAttribute(const char *presId, const char *, const char *value) override; + void GoToTime(const char *elementPath, const float time) override; + void SetGlobalAnimationTime(qint64 inMilliSecs) override; + void SetDataInputValue(const QString &name, const QVariant &value, + int property) override; + + void setPresentationId(const QString &id) override + { + m_Application->setPresentationId(id); + } + + QList dataInputs() const override; + QList dataOutputs() const override; + float dataInputMax(const QString &name) const override; + float dataInputMin(const QString &name) const override; + QHash dataInputMetadata(const QString &name) const override; + + void createElements(const QString &parentElementPath, const QString &slideName, + const QVector> &properties) override; + void deleteElements(const QStringList &elementPaths) override; + void createMaterials(const QString &subPresId, + const QStringList &materialDefinitions) override; + void deleteMaterials(const QStringList &materialNames) override; + void createMesh(const QString &name, qt3dsimp::Mesh *mesh) override; + void deleteMeshes(const QStringList &meshNames) override; + void SetAttribute(const char *elementPath, const char *attributeName, + const char *value) override; + bool GetAttribute(const char *elementPath, const char *attributeName, void *value) override; + void FireEvent(const char *element, const char *evtName) override; + bool PeekCustomAction(char *&outElementPath, char *&outActionName) override; + bool RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData) override; + void FireEvent(const TEventCommandHash inEventType, eastl::string inArgument) override; + qt3ds::foundation::Option GetPresentationSize() override; + void preloadSlide(const QString &slide) override; + void unloadSlide(const QString &slide) override; + void setDelayedLoading(bool enable) override; + void BootupPreGraphicsInitObjects(); +}; + +CRuntimeView::CRuntimeView(ITimeProvider &inTimeProvider, IWindowSystem &inWindowSystem, + IAudioPlayer *inAudioPlayer, QElapsedTimer *startupTimer) + : m_RenderEngine(nullptr) + , m_InputEngine(nullptr) + , m_Application(nullptr) + , m_Presentation(nullptr) + , m_TimeProvider(inTimeProvider) + , m_WindowSystem(inWindowSystem) + , m_AudioPlayer(inAudioPlayer) + , mRefCount(0) + , m_visitor(nullptr) + , m_showOnScreenStats(false) + , m_startupTimer(startupTimer) + , m_startupTime(-1) +{ +} + +CRuntimeView::~CRuntimeView() +{ +} + +bool CRuntimeView::BeginLoad(const QString &sourcePath, const QStringList &variantList) +{ + bool theResult = false; + + // boot up the application + BootupPreGraphicsInitObjects(); + + // If there was a presentation file then we have to load it or something failed. + if (m_ApplicationCore->BeginLoad(sourcePath.toUtf8(), variantList)) + theResult = true; + else + theResult = false; + + // If Initialize wasn't successful - this means the CShaderFactory failed to initialize + // or, the presentation failed to load. + // + // NOTE: if no presentation was passed, this is 'ok' + if (!theResult) + Cleanup(); + + return theResult; +} + +bool CRuntimeView::HasOfflineLoadingCompleted() +{ + if (m_Application.mPtr == nullptr) { + if (m_ApplicationCore) + return m_ApplicationCore->HasCompletedLoading(); + else + return false; + } + return true; +} + +bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading) +{ + m_ApplicationCore->EndLoad(); + // Next call will initialize the render portion of the scenes. This *must* have a loaded + // application to go further as it will bind scene graph data to application data. + m_RuntimeFactory = m_RuntimeFactoryCore->CreateRenderFactory(format, delayedLoading); + m_Application + = m_ApplicationCore->CreateApplication(*m_InputEngine, m_AudioPlayer, + *m_RuntimeFactory); + if (!m_Application->createSuccessful()) + return false; + + m_Application->ResetTime(); + m_RenderEngine = &m_RuntimeFactory->CreateRenderEngine(); + m_Presentation = m_Application->GetPrimaryPresentation(); + + QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigSlideEntered, + signalProxy(), &QRuntimeViewSignalProxy::SigSlideEntered); + QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigSlideExited, + signalProxy(), &QRuntimeViewSignalProxy::SigSlideExited); + QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigCustomSignal, + signalProxy(), &QRuntimeViewSignalProxy::SigCustomSignal); + QObject::connect(m_Presentation->signalProxy(), + &QPresentationSignalProxy::SigPresentationReady, + signalProxy(), &QRuntimeViewSignalProxy::SigPresentationReady); + QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigElementsCreated, + signalProxy(), &QRuntimeViewSignalProxy::SigElementsCreated); + QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigMaterialsCreated, + signalProxy(), &QRuntimeViewSignalProxy::SigMaterialsCreated); + QObject::connect(m_Presentation->signalProxy(), + &QPresentationSignalProxy::SigDataOutputValueUpdated, + signalProxy(), + &QRuntimeViewSignalProxy::SigDataOutputValueUpdated); + + m_TimeProvider.Reset(); + return true; +} + +void CRuntimeView::Cleanup() +{ + // Q3DStudio_virtual_delete( m_Timer, CTimer ); + // Q3DStudio_virtual_delete( m_PerfFileStream, CFileStream ); + m_Application = nullptr; + Q3DStudio_virtual_delete(m_InputEngine, CTegraInputEngine); + if (m_RenderEngine) { + m_RenderEngine->Release(); + m_RenderEngine = nullptr; + } + + CDLLManager &theDLLManager = CDLLManager::GetDLLManager(); + theDLLManager.Cleanup(); + if (m_Presentation) + QObject::disconnect(m_Presentation->signalProxy(), 0, signalProxy(), 0); + + m_InputEngine = nullptr; + m_RenderEngine = nullptr; + m_Presentation = nullptr; +} + +bool CRuntimeView::CanRender() +{ + return m_Application.mPtr != nullptr; +} + +//============================================================================== +/** + * nv_main APP-SPECIFIC rendering call + * returns KD_TRUE to call egl_render and swap properly, KD_FALSE if there has been no scene update + *or redraw. + */ +void CRuntimeView::Render() +{ + if (m_Application.mPtr == nullptr) { + // InitializeGraphics has not been called + QT3DS_ASSERT(false); + } + + PerfLogGeneralEvent1(DATALOGGER_FRAME); + + m_Application->UpdateAndRender(); + + if (m_startupTime < 0 && m_startupTimer) { + m_startupTime = m_startupTimer->elapsed(); + m_startupTimer->invalidate(); + } + + if (m_showOnScreenStats) { + ITegraRenderStateManager &manager + = GetTegraRenderEngine()->GetTegraRenderStateManager(); + manager.PushState(); + + QSize dim = m_WindowSystem.GetWindowDimensions(); + manager.SetScissorTestEnabled(false); + manager.SetViewport(0, 0, dim.width(), dim.height()); + + QPair fps + = m_RuntimeFactory->GetQt3DSRenderContext().GetFPS(); + const QVector times = m_RuntimeFactory->GetQt3DSRenderContext().GetFrameTimes(); + + QString text; + QTextStream stream(&text); + stream << QStringLiteral("Render Statistics: "); + stream << QString::number(fps.first, 'f', 2); + stream << " fps, frame count "; + stream << QString::number(fps.second); + stream << ", frame time "; + stream << QString::number(times[0], 'f', 2); + stream << " ms"; + if (m_startupTime) { + stream << ", Init time: "; + stream << QString::number(m_startupTime); + stream << " ms"; + } + + // bottom left coordinates + GetTegraRenderEngine()->RenderText2D( + dim.width() / 4, dim.height() - 25, qt3ds::QT3DSVec3(0.0, 1.0, 0.0), + text.toLatin1().constData()); + GetTegraRenderEngine()->RenderGpuProfilerStats( + 20.0, dim.height() - 80, qt3ds::QT3DSVec3(0.0, 1.0, 0.0)); + + manager.PopState(); + } +} + +bool CRuntimeView::WasLastFrameDirty() +{ + if (m_Application) + return m_Application->IsApplicationDirty(); + return false; +} + +//============================================================================== +/** + * nv_main APP-SPECIFIC message call + * HandleMessage + */ +bool CRuntimeView::HandleMessage(const QEvent *inEvent) +{ + if (m_Application.mPtr == nullptr || m_RenderEngine == nullptr) + return 0; + + bool ret = false; + switch (inEvent->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + { + const QMouseEvent *event = static_cast(inEvent); + m_InputEngine->SetPickInput(static_cast(event->x()), + static_cast(event->y()), true); + m_InputEngine->SetPickFlags(inEvent->type() == QEvent::MouseButtonPress + ? LMOUSE_DOWN : LMOUSE_UP); + ret = true; + } + break; + case QEvent::Resize: + { + if (m_Application->GetPrimaryPresentation()) + m_RenderEngine->CheckResize(true, *m_Application->GetPrimaryPresentation()); + ret = true; + } + break; + default: + break; + } + + m_InputEngine->HandleMessage(inEvent, *m_RenderEngine, m_Application->GetPrimaryPresentation()); + return ret ? 1 : 0; +} + +void CRuntimeView::Pause() +{ + m_TimeProvider.Pause(); +} + +void CRuntimeView::UnPause() +{ + m_TimeProvider.UnPause(); +} + +bool CRuntimeView::IsPaused() +{ + return m_TimeProvider.IsPaused(); +} + +INT32 CRuntimeView::GetFrameCount() +{ + return m_Application->GetFrameCount(); +} + +void CRuntimeView::showOnScreenStats(bool show) +{ + m_showOnScreenStats = show; + m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer().EnableLayerGpuProfiling(show); +} + +CInputEngine *CRuntimeView::GetInputEngine() +{ + return m_InputEngine; +} + +//============================================================================== +/** + * Generates an event in the presentation. + */ +void CRuntimeView::GoToSlideByName(const char *elementPath, const char *slideName) +{ + if (m_Application) { + if (!elementPath || !slideName) + return; + + CPresentation *thePresentation = m_Application->GetPrimaryPresentation(); + IScriptBridge *theBridge = thePresentation->GetScriptBridgeQml(); + + if (!theBridge) + return; + + theBridge->GotoSlide(elementPath, slideName, SScriptEngineGotoSlideArgs()); + } +} + +void CRuntimeView::GoToSlideByIndex(const char *elementPath, const int slideIndex) +{ + if (m_Application) { + if (!elementPath || slideIndex < 0) + return; + + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + theBridgeEngine.GotoSlideIndex(elementPath, slideIndex, SScriptEngineGotoSlideArgs()); + } +} + +void CRuntimeView::GoToSlideRelative(const char *elementPath, const bool next, const bool wrap) +{ + if (m_Application) { + if (!elementPath) + return; + + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + theBridgeEngine.GotoSlideRelative(elementPath, next, wrap, SScriptEngineGotoSlideArgs()); + } +} + +bool CRuntimeView::GetSlideInfo(const char *elementPath, int ¤tIndex, int &previousIndex, + QString ¤tName, QString &previousName) +{ + if (m_Application && elementPath) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + return theBridgeEngine.GetSlideInfo(elementPath, currentIndex, previousIndex, + currentName, previousName); + } + return false; +} + +void CRuntimeView::SetPresentationAttribute(const char *presId, const char *, const char *value) +{ + if (m_Application) { + if (!presId || !value) + return; + + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + theBridgeEngine.SetPresentationAttribute(presId, nullptr, value); + } +} + +bool CRuntimeView::RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + return theBridgeEngine.RegisterCallback(callbackType, func, inUserData); + } + + return false; +} + +void CRuntimeView::GoToTime(const char *elementPath, const float time) +{ + if (m_Application) { + if (!elementPath || time < 0.0) + return; + + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + theBridgeEngine.GotoTime(elementPath, time); + } +} + +void CRuntimeView::SetGlobalAnimationTime(qint64 inMilliSecs) +{ + if (m_Application) + m_Application->SetTimeMilliSecs(inMilliSecs); +} + +void CRuntimeView::SetDataInputValue( + const QString &name, const QVariant &value, + int property = 0) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + theBridgeEngine.SetDataInputValue(name, value, (qt3ds::runtime::DataInputValueRole)property); + } +} + +QList CRuntimeView::dataInputs() const +{ + if (m_Application) + return m_Application->dataInputs(); + + return {}; +} + +QList CRuntimeView::dataOutputs() const +{ + if (m_Application) + return m_Application->dataOutputs(); + + return {}; +} + +float CRuntimeView::dataInputMax(const QString &name) const +{ + if (m_Application) + return m_Application->dataInputMax(name); + + return 0; +} + +float CRuntimeView::dataInputMin(const QString &name) const +{ + if (m_Application) + return m_Application->dataInputMin(name); + + return 0; +} + +QHash CRuntimeView::dataInputMetadata(const QString &name) const +{ + if (m_Application) + return m_Application->dataInputMetadata(name); + + return {}; +} + +void CRuntimeView::createElements(const QString &parentElementPath, const QString &slideName, + const QVector> &properties) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + theBridgeEngine.createElements(parentElementPath, slideName, properties, + &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer()); + } +} + +void CRuntimeView::deleteElements(const QStringList &elementPaths) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + theBridgeEngine.deleteElements(elementPaths, + &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer()); + } +} + +void CRuntimeView::createMaterials(const QString &subPresId, + const QStringList &materialDefinitions) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + theBridgeEngine.createMaterials( + subPresId, materialDefinitions, + &m_RuntimeFactory->GetQt3DSRenderContext().GetCustomMaterialSystem(), + &m_RuntimeFactory->GetQt3DSRenderContext().GetDynamicObjectSystem(), + &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer()); + } +} + +void CRuntimeView::deleteMaterials(const QStringList &materialNames) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + theBridgeEngine.deleteMaterials(materialNames, + &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer()); + } +} + +void CRuntimeView::createMesh(const QString &name, qt3dsimp::Mesh *mesh) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + theBridgeEngine.createMesh( + name, mesh, &m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager()); + } +} + +void CRuntimeView::deleteMeshes(const QStringList &meshNames) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + theBridgeEngine.deleteMeshes( + meshNames, &m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager()); + } +} + +void CRuntimeView::SetAttribute(const char *elementPath, const char *attributeName, + const char *value) +{ + if (m_Application) { + if (!elementPath || !attributeName || !value) + return; + + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + theBridgeEngine.SetAttribute(elementPath, attributeName, value); + } +} + +bool CRuntimeView::GetAttribute(const char *elementPath, const char *attributeName, void *value) +{ + if (m_Application) { + if (!elementPath || !attributeName || !value) + return false; + + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + return theBridgeEngine.GetAttribute(elementPath, attributeName, (char *)value); + } + + return false; +} + +void CRuntimeView::FireEvent(const char *element, const char *evtName) +{ + if (m_Application) { + if (!element || !evtName) + return; + + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + theBridgeEngine.FireEvent(element, evtName); + } +} + +bool CRuntimeView::PeekCustomAction(char *&outElementPath, char *&outActionName) +{ + bool actionAvailable = true; + + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast(m_RuntimeFactoryCore->GetScriptEngineQml()); + + Q3DStudio::TElement *theElement = nullptr; + actionAvailable = theBridgeEngine.PeekSignal(theElement, outActionName); + if (actionAvailable && theElement) + outElementPath = (char *)theElement->m_Path.c_str(); + } + + return actionAvailable; +} + +void CRuntimeView::FireEvent(const TEventCommandHash inEventType, eastl::string inArgument) +{ + if (m_Application) { + CPresentation *thePresentation = m_Application->GetPrimaryPresentation(); + TElement *theScene = thePresentation->GetRoot(); + if (inArgument.empty()) { + thePresentation->FireEvent(inEventType, theScene, nullptr, nullptr, ATTRIBUTETYPE_NONE, + ATTRIBUTETYPE_NONE); + } else { + UVariant inArg; + inArg.m_StringHandle = thePresentation->GetStringTable().GetHandle(inArgument.c_str()); + thePresentation->FireEvent(inEventType, theScene, &inArg, nullptr, ATTRIBUTETYPE_STRING, + ATTRIBUTETYPE_NONE); + } + } +} + +void CRuntimeView::preloadSlide(const QString &slide) +{ + if (m_Application) + m_Application->preloadSlide(slide); +} + +void CRuntimeView::unloadSlide(const QString &slide) +{ + if (m_Application) + m_Application->unloadSlide(slide); +} + +void CRuntimeView::setDelayedLoading(bool enable) +{ + if (m_Application) + m_Application->setDelayedLoading(enable); +} + +qt3ds::foundation::Option CRuntimeView::GetPresentationSize() +{ + if (m_Application) { + CPresentation *thePresentation = m_Application->GetPrimaryPresentation(); + if (thePresentation) + return thePresentation->GetSize(); + } + return qt3ds::foundation::Empty(); +} + +//============================================================================== +/** + * Perform the initialization steps prior to loading any presentation. + */ +void CRuntimeView::BootupPreGraphicsInitObjects() +{ + qCInfo(TRACE_INFO) << "CNDDView::BootupPreGraphicsInitObjects: DoInitialize"; + // Create engines and runtime + const eastl::string &theAppDir = QCoreApplication::applicationDirPath().toLatin1().constData(); + + m_RuntimeFactoryCore = qt3ds::render::IQt3DSRenderFactoryCore::CreateRenderFactoryCore( + theAppDir.c_str(), m_WindowSystem, m_TimeProvider); + m_ApplicationCore = qt3ds::runtime::IApplication::CreateApplicationCore(*m_RuntimeFactoryCore, + theAppDir.c_str()); + + if (m_ApplicationCore && m_visitor) + m_ApplicationCore->setAssetVisitor(m_visitor); + + m_InputEngine = static_cast(CreateInputEngine()); + Q3DStudio_ASSERT(m_InputEngine != nullptr); + + qCInfo(TRACE_INFO) << "CNDDView::DoInitialize: Successfully initialized!"; +} + +void CRuntimeView::setAssetVisitor(qt3ds::Qt3DSAssetVisitor *v) +{ + m_visitor = v; + if (m_ApplicationCore) + m_ApplicationCore->setAssetVisitor(v); +} + +IRuntimeView &IRuntimeView::Create(ITimeProvider &inProvider, IWindowSystem &inWindowSystem, + IAudioPlayer *inAudioPlayer, QElapsedTimer *startupTimer) +{ + return *QT3DS_NEW(qt3ds::render::g_BaseAllocator, CRuntimeView)(inProvider, inWindowSystem, + inAudioPlayer, startupTimer); +} + +QRuntimeViewSignalProxy *IRuntimeView::signalProxy() +{ + return &m_SignalProxy; +} + +} // namespace Q3DStudio + diff --git a/src/engine/Qt3DSRuntimeView.h b/src/engine/Qt3DSRuntimeView.h new file mode 100644 index 0000000..22d8cba --- /dev/null +++ b/src/engine/Qt3DSRuntimeView.h @@ -0,0 +1,238 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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$ +** +****************************************************************************/ + +#ifndef QT3DS_RUNTIME_VIEW_H +#define QT3DS_RUNTIME_VIEW_H + +#include "EnginePrefix.h" +#include "Qt3DSIStateful.h" +#include "foundation/Qt3DSVec4.h" +#include "foundation/Qt3DSOption.h" +#include "render/Qt3DSRenderBaseTypes.h" +#include "EASTL/string.h" +#include "foundation/Qt3DSRefCounted.h" +#include "Qt3DSApplication.h" +#include "Qt3DSWindowSystem.h" +#include "Qt3DSTimer.h" +#include "Qt3DSPresentation.h" +#include "Qt3DSRenderRuntimeBinding.h" +#include +#include +#include +#include + +typedef void (*qml_Function)(void *inUserData); + +namespace qt3dsimp { + struct Mesh; +} + +class QRuntimeViewSignalProxy : public QObject +{ + Q_OBJECT +Q_SIGNALS: + void SigSlideEntered(const QString &elementPath, unsigned int index, const QString &name); + void SigSlideExited(const QString &elementPath, unsigned int index, const QString &name); + void SigCustomSignal(const QString &elementPath, const QString &name); + void SigPresentationReady(); + void SigElementsCreated(const QStringList &elementPaths, const QString &error); + void SigMaterialsCreated(const QStringList &materialNames, const QString &error); + void SigDataOutputValueUpdated(const QString &name, const QVariant &value); +}; + +namespace qt3ds { +class Qt3DSAssetVisitor; +} + +namespace qt3ds { +namespace render { +class NVRenderContext; +} +} + +namespace Q3DStudio { + +class CTegraInputEngine; +class CTegraRenderEngine; +class IScene; +class CInputEngine; +class IAudioPlayer; + +class ITegraRenderStateManager : public IStatefulStackBase +{ +protected: + virtual ~ITegraRenderStateManager() {} +public: + virtual void SetViewport(INT32 inX, INT32 inY, INT32 inWidth, INT32 inHeight) = 0; + virtual void SetScissorTestEnabled(bool inValue) = 0; + virtual void SaveAllState() = 0; + virtual void RestoreAllState() = 0; +}; + +struct TegraRenderScaleModes +{ + enum Enum { + ExactSize = 0, // Ensure the viewport is exactly same size as application + ScaleToFit = 1, // Resize viewport keeping aspect ratio + ScaleToFill = 2, // Resize viewport to entire window + }; +}; + +struct TegraRenderShadeModes +{ + enum Enum { + Shaded = 0, // Geometry is shaded only + ShadedWireframe = 1, // Wireframe is drawn on top shaded geometry + Wireframe = 2, // Wireframe only + }; +}; + +class ITegraApplicationRenderEngine +{ +protected: + virtual ~ITegraApplicationRenderEngine() {} + +public: + virtual void SetViewport(INT32 inX, INT32 inY, INT32 inWidth, INT32 inHeight) = 0; + virtual void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) = 0; + virtual void ensureRenderTarget() = 0; + virtual void CheckResize(bool inForce, IPresentation &inActivePresentation) = 0; + virtual BOOL LoadShaderCache(const CHAR *inFilePath) = 0; + virtual void AbandonLoadingImages(IScene &inScene) = 0; + virtual BOOL IsPickValid(FLOAT &outX, FLOAT &outY, + const IPresentation &inPresentation) const = 0; + virtual void SetScaleMode(TegraRenderScaleModes::Enum inScale) = 0; + virtual void SetShadeMode(TegraRenderShadeModes::Enum inShade) = 0; + virtual TegraRenderScaleModes::Enum GetScaleMode() const = 0; + + // TODO: To be removed, not used anywhere anymore + void CycleScaleMode() + { + int mode = (int)GetScaleMode(); + mode = (mode + 1) % 3; + SetScaleMode((TegraRenderScaleModes::Enum)mode); + } + + virtual ITegraRenderStateManager &GetTegraRenderStateManager() = 0; + virtual qt3ds::render::NVRenderContext &GetRenderContext() = 0; + virtual void SetMatteColor(qt3ds::foundation::Option inColor) = 0; + virtual void EnableRenderRotation(bool inEnable) = 0; + virtual void SetWriteOutShaderCache(bool inWriteOutShaderCache) = 0; + virtual void Release() = 0; + virtual void RenderText2D(FLOAT x, FLOAT y, qt3ds::foundation::Option inColor, + const char *text) = 0; + virtual void RenderGpuProfilerStats(FLOAT x, FLOAT y, + qt3ds::foundation::Option inColor) = 0; +}; + +class IRuntimeView : public qt3ds::foundation::NVRefCounted +{ +public: + virtual ~IRuntimeView(){} + +public: // loading + virtual bool BeginLoad(const QString &sourcePath, const QStringList &variantList) = 0; + virtual bool HasOfflineLoadingCompleted() = 0; + virtual bool InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading) = 0; + + virtual void Cleanup() = 0; + + virtual bool CanRender() = 0; + + virtual void Render() = 0; + + virtual bool WasLastFrameDirty() = 0; + + virtual bool HandleMessage(const QEvent *inEvent) = 0; + + virtual void Pause() = 0; + virtual void UnPause() = 0; + virtual bool IsPaused() = 0; + virtual INT32 GetFrameCount() = 0; + virtual void showOnScreenStats(bool) = 0; + + virtual void setPresentationId(const QString &id) = 0; + +public: // Input engine access + virtual CInputEngine *GetInputEngine() = 0; + // Only valid after InitializeGraphics + virtual ITegraApplicationRenderEngine *GetTegraRenderEngine() = 0; + +public: + virtual void GoToSlideByName(const char *elementPath, const char *slideName) = 0; + virtual void GoToSlideByIndex(const char *elementPath, const int slideIndex) = 0; + virtual void GoToSlideRelative(const char *elementPath, const bool next, const bool wrap) = 0; + virtual bool GetSlideInfo(const char *elementPath, int ¤tIndex, int &previousIndex, + QString ¤tName, QString &previousName) = 0; + virtual void SetPresentationAttribute(const char *presId, const char *, const char *value) = 0; + virtual void GoToTime(const char *elementPath, const float time) = 0; + virtual void SetGlobalAnimationTime(qint64 inMilliSecs) = 0; + virtual void SetDataInputValue(const QString &name, const QVariant &value, + int property) = 0; + virtual QList dataInputs() const = 0; + virtual QList dataOutputs() const = 0; + virtual float dataInputMax(const QString &name) const = 0; + virtual float dataInputMin(const QString &name) const = 0; + virtual QHash dataInputMetadata(const QString &name) const = 0; + virtual void createElements(const QString &parentElementPath, const QString &slideName, + const QVector> &properties) = 0; + virtual void deleteElements(const QStringList &elementPaths) = 0; + virtual void createMaterials(const QString &subPresId, + const QStringList &materialDefinitions) = 0; + virtual void deleteMaterials(const QStringList &materialNames) = 0; + virtual void createMesh(const QString &name, qt3dsimp::Mesh *mesh) = 0; + virtual void deleteMeshes(const QStringList &meshNames) = 0; + virtual void SetAttribute(const char *elementPath, const char *attributeName, + const char *value) = 0; + virtual bool GetAttribute(const char *elementPath, const char *attributeName, void *value) = 0; + virtual void FireEvent(const char *element, const char *evtName) = 0; + virtual bool PeekCustomAction(char *&outElementPath, char *&outActionName) = 0; + virtual bool RegisterScriptCallback(int callbackType, qml_Function func, void *inUserData) = 0; + virtual void FireEvent(const TEventCommandHash inEventType, eastl::string inArgument) = 0; + virtual qt3ds::foundation::Option GetPresentationSize() = 0; + virtual void setAssetVisitor(qt3ds::Qt3DSAssetVisitor *) = 0; + virtual void preloadSlide(const QString &slide) = 0; + virtual void unloadSlide(const QString &slide) = 0; + virtual void setDelayedLoading(bool enable) = 0; + +public: + static IRuntimeView &Create(ITimeProvider &inProvider, IWindowSystem &inWindowSystem, + IAudioPlayer *inAudioPlayer = nullptr, + QElapsedTimer *startupTimer = nullptr); + +public: + QRuntimeViewSignalProxy *signalProxy(); +private: + QRuntimeViewSignalProxy m_SignalProxy; +}; + +} // namespace Q3DStudio + +#endif // QT3DS_RUNTIME_VIEW_H diff --git a/src/engine/Qt3DSTegraInputEngine.cpp b/src/engine/Qt3DSTegraInputEngine.cpp new file mode 100644 index 0000000..bb9a7f9 --- /dev/null +++ b/src/engine/Qt3DSTegraInputEngine.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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 "EnginePrefix.h" +#include "Qt3DSTegraInputEngine.h" + +//============================================================================== +// Namespace +//============================================================================== +namespace Q3DStudio { + +//============================================================================== +/** + * XXX + */ +CTegraInputEngine::CTegraInputEngine() +{ +} + +//============================================================================== +/** + * XXX + */ +CTegraInputEngine::~CTegraInputEngine() +{ +} + +//============================================================================== +/** + * Returns the structure that contains the input information for the current frame. + */ +SInputFrame &CTegraInputEngine::GetInputFrame() +{ + return m_InputFrame; +} + +//============================================================================== +/** + * Handles the input message. + */ +void CTegraInputEngine::HandleMessage(const QEvent *inEvent, + ITegraApplicationRenderEngine &inRenderEngine, + CPresentation *inPresentation) +{ + static bool s_PointerWasDown = false; + + if (NULL == inPresentation) + return; + + switch (inEvent->type()) { + + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + { + const QMouseEvent *event = static_cast(inEvent); + + QPointF pos = event->localPos(); + FLOAT x = pos.x(); + FLOAT y = pos.y(); + + const bool pressed = inEvent->type() == QEvent::MouseButtonPress; + + if (inRenderEngine.IsPickValid(x, y, *inPresentation)) { + // printf( "INPUT x %ld y %ld\n", (int)x, (int)y ); + SetPickInput(x, y, (pressed || s_PointerWasDown) ? true : false); + + if (pressed) { + if (s_PointerWasDown) + SetPickFlags(LMOUSE_DOWN); + else + SetPickFlags(LMOUSE_PRESSED); + + s_PointerWasDown = true; + } else { + if (s_PointerWasDown) + SetPickFlags(LMOUSE_RELEASED); + else + SetPickFlags(LMOUSE_UP); + + s_PointerWasDown = false; + } + } else { + if (s_PointerWasDown) + SetPickFlags(LMOUSE_RELEASED); + else + SetPickFlags(LMOUSE_UP); + + s_PointerWasDown = false; + } + } + break; + default: + break; + } +} + +} // namespace Q3DStudio diff --git a/src/engine/Qt3DSTegraInputEngine.h b/src/engine/Qt3DSTegraInputEngine.h new file mode 100644 index 0000000..29f20f2 --- /dev/null +++ b/src/engine/Qt3DSTegraInputEngine.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 1993-2009 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$ +** +****************************************************************************/ + +#ifndef QT3DS_TEGRA_INPUT_ENGINE_H +#define QT3DS_TEGRA_INPUT_ENGINE_H + +//============================================================================== +// Includes +//============================================================================== +#include "Qt3DSInputEngine.h" +#include "Qt3DSRuntimeView.h" +#include "Qt3DSInputEventTypes.h" +#include "Qt3DSPresentation.h" + +//============================================================================== +// Namespace +//============================================================================== +namespace Q3DStudio { + +//============================================================================== +// Forwards +//============================================================================== +class CTegraRenderEngine; +class CPresentation; +class ITegraApplicationRenderEngine; + +//============================================================================== +/** +* @class CTegraInputEngine +* @brief +*/ +class CTegraInputEngine : public CInputEngine +{ + //============================================================================== + // Fields + //============================================================================== + + //============================================================================== + // Methods + //============================================================================== +public: // Construction + CTegraInputEngine(); + virtual ~CTegraInputEngine(); + +public: // Access + SInputFrame &GetInputFrame() override; + + void HandleMessage(const QEvent *inEvent, ITegraApplicationRenderEngine &inRenderEngine, + CPresentation *inPresentation); +}; + +} // namespace Q3DStudio + +#endif // QT3DS_TEGRA_INPUT_ENGINE_H diff --git a/src/engine/Qt3DSWindowSystem.h b/src/engine/Qt3DSWindowSystem.h new file mode 100644 index 0000000..173dd83 --- /dev/null +++ b/src/engine/Qt3DSWindowSystem.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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$ +** +****************************************************************************/ +#ifndef QT3DS_WINDOW_SYSTEM_H +#define QT3DS_WINDOW_SYSTEM_H + +#include + +namespace Q3DStudio { + +struct SEGLInfo; + +class IWindowSystem +{ +protected: + virtual ~IWindowSystem() {} +public: + virtual QSize GetWindowDimensions() = 0; + virtual void SetWindowDimensions(const QSize &inSize) = 0; + // For platforms that support it, we get the egl info for render plugins + // Feel free to return NULL. + virtual SEGLInfo *GetEGLInfo() = 0; + // on some systems we allow our default render target to be a offscreen buffer + // otherwise return 0; + virtual int GetDefaultRenderTargetID() = 0; + // returns the depth buffer bit count for the render window + virtual int GetDepthBitCount() = 0; +}; +} + +#endif -- cgit v1.2.3