summaryrefslogtreecommitdiffstats
path: root/src/engine
diff options
context:
space:
mode:
authorPasi Keränen <pasi.keranen@qt.io>2019-06-06 16:22:02 +0300
committerPasi Keränen <pasi.keranen@qt.io>2019-06-07 13:52:44 +0300
commitb4954701093739e7a4e54a0669f306922d0d4605 (patch)
tree73d71319a921234f6b507c9098fdc842f7fe06dc /src/engine
parent8548a5f5579e3eee7e5ae6b1f6901dcc8bfee19e (diff)
Long live the slayer!
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 <pasi.keranen@qt.io>
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/EnginePrefix.h143
-rw-r--r--src/engine/NVImageScaler.h311
-rw-r--r--src/engine/OpenKodeInclude.h49
-rw-r--r--src/engine/Qt3DSEGLInfo.h60
-rw-r--r--src/engine/Qt3DSEGLWindowSystem.h81
-rw-r--r--src/engine/Qt3DSPluginDLL.h128
-rw-r--r--src/engine/Qt3DSRenderRuntimeBinding.cpp1858
-rw-r--r--src/engine/Qt3DSRenderRuntimeBinding.h82
-rw-r--r--src/engine/Qt3DSRenderRuntimeBindingImpl.h218
-rw-r--r--src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp224
-rw-r--r--src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp1841
-rw-r--r--src/engine/Qt3DSRuntimeView.cpp862
-rw-r--r--src/engine/Qt3DSRuntimeView.h238
-rw-r--r--src/engine/Qt3DSTegraInputEngine.cpp124
-rw-r--r--src/engine/Qt3DSTegraInputEngine.h81
-rw-r--r--src/engine/Qt3DSWindowSystem.h57
16 files changed, 6357 insertions, 0 deletions
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 <stdio.h>
+#include <iostream>
+
+#if defined(_PCPLATFORM) || defined(_TEGRAPLATFORM)
+#include <tchar.h>
+#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 <INT32 TNumChannels>
+ inline void BilinearReduceRows(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ CHAR *outDstBuffer, INT32 inDstHeight)
+ {
+ INT32 theDDAConst = static_cast<INT32>(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 <INT32 TNumChannels>
+ inline void BilinearReduceCols(const CHAR *inSrcBuffer, INT32 inSrcWidth, INT32 inSrcHeight,
+ CHAR *outDstBuffer, INT32 inDstWidth)
+ {
+ INT32 theDDAConst = static_cast<INT32>(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 <INT32 TNumChannels>
+ 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<INT32>(1024.f * inSrcWidth / inDstWidth);
+ // How many rows do we skip, in fixed point arithmetic, when we bump lines
+ INT32 theYIncrement = static_cast<INT32>(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 <INT32 TNumChannels>
+ 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<INT32>(1024.f * inSrcWidth / inDstWidth);
+ // How many rows do we skip, in fixed point arithmetic, when we bump lines
+ INT32 theYIncrement = static_cast<INT32>(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 <kd/kd.h> 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 <KD/kd.h>
+#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 <EGL/egl.h>
+
+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 <QtGlobal>
+
+#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<ILoadedBuffer> m_Data;
+ SPresentation *m_Presentation;
+ NVDataRef<QT3DSU8> m_TranslatorData;
+ NVDataRef<QT3DSU8> m_SceneGraphData;
+ eastl::vector<Qt3DSTranslator *> 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<IQt3DSRenderContext> m_Context;
+ NVScopedRefCounted<SSceneLoadData> 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<SGraphObject *> 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<SLayer *>(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<Qt3DSTranslator *>(theElement.GetAssociation());
+ if (!theTranslator && theElement.GetType() == m_PathSubPathType) {
+ Q3DStudio::TElement *theParent = theElement.GetParent();
+ if (theParent) {
+ theTranslator = reinterpret_cast<Qt3DSTranslator *>(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<SModel *>(const_cast<SGraphObject *>(thePickResult.m_HitObject));
+ return &Qt3DSTranslator::GetTranslatorFromGraphNode(*theHitModel)->Element();
+ }
+ return nullptr;
+ }
+
+ virtual Option<QT3DSVec2> FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY,
+ NVDataRef<Q3DStudio::TElement *> inMapperElements,
+ Q3DStudio::FacePositionPlanes::Enum inPlane)
+ {
+ if (inElement.GetBelongedPresentation() != this->m_RuntimePresentation
+ && inMapperElements.size() == 0) {
+ return Empty();
+ }
+ Qt3DSTranslator *theTranslator =
+ reinterpret_cast<Qt3DSTranslator *>(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<SNode &>(*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<SGraphObject *> theMapperObjects(inMapperElements.size());
+ for (QT3DSU32 idx = 0, end = inMapperElements.size(); idx < end; ++idx) {
+ Qt3DSTranslator *theMapperTranslator =
+ reinterpret_cast<Qt3DSTranslator *>(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<SGraphObject *>(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<SModel *>(
+ const_cast<SGraphObject *>(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<Qt3DSTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ Update();
+ TransferDirtyProperties();
+ SNode *theNode = static_cast<SNode *>(&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<Qt3DSTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ SNode *theNode = static_cast<SNode *>(&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<Qt3DSTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ Update();
+ TransferDirtyProperties();
+ SNode *theNode = static_cast<SNode *>(&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<Qt3DSTranslator *>(inElement->GetAssociation());
+ if (theTranslator && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ SNode *theNode = static_cast<SNode *>(&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<Qt3DSTranslator *>(inElem.GetAssociation());
+ if (theTranslator && theTranslator->m_RenderObject) {
+ Option<qt3ds::render::SCuboidRect> 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<Qt3DSTranslator *>(inElement.GetAssociation());
+ if (theTranslator && theTranslator->m_RenderObject) {
+ SNode *theNode = reinterpret_cast<SNode *>(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<Qt3DSTranslator *>(inElement.GetAssociation());
+ if (theTranslator && theTranslator->m_RenderObject) {
+ SNode *theNode = reinterpret_cast<SNode *>(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<Qt3DSTranslator *>(inElement->GetAssociation());
+ if (theTranslator && theTranslator->GetUIPType() == GraphObjectTypes::Image) {
+ SImage *theImage = static_cast<SImage *>(&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>((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<Qt3DSTranslator *>(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<SText *>(&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<Q3DStudio::INT32>(m_Presentation->m_PresentationDimensions.x),
+ static_cast<Q3DStudio::INT32>(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 <typename T, typename C>
+ void forAllObjects(nvvector<SGraphObject *> &vec, GraphObjectTypes::Enum type, C callable)
+ {
+ nvvector<SGraphObject *>::iterator it = vec.begin();
+ nvvector<SGraphObject *>::iterator end = vec.end();
+ while (it != end) {
+ if ((*it)->m_Type == type)
+ callable(static_cast<T*>(*it));
+ ++it;
+ }
+ }
+
+ void PostLoadStep()
+ {
+ IBufferManager &mgr = m_Context->GetBufferManager();
+ forAllObjects<SImage>(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<CRegisteredString, bool> TStrBoolMap;
+
+ NVScopedRefCounted<SBindingCore> m_Context;
+ nvvector<pair<Q3DStudio::IPresentation *, Qt3DSRenderScene *>> m_Scenes;
+ nvvector<pair<qt3ds::foundation::CRegisteredString, long>> m_RenderPlugins;
+ Q3DStudio::INT32 m_ViewWidth;
+ Q3DStudio::INT32 m_ViewHeight;
+ Q3DStudio::SPickFrame m_PickFrame;
+ NVDataRef<QT3DSU8> m_StrTableData;
+ // The boolean is to mark transparent images and ibl images
+ nvvector<eastl::pair<CRegisteredString, eastl::pair<bool, bool>>> m_SourcePaths;
+ eastl::hash_set<CRegisteredString> m_SourcePathSet;
+
+ Qt3DSRenderScene *m_LastRenderedScene;
+ Q3DStudio::IWindowSystem &m_WindowSystem;
+ Mutex m_LoadingScenesMutex;
+ eastl::vector<NVScopedRefCounted<SSceneLoadData>> 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<const QT3DSU32 *>(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<SRenderPlugin &>(*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<SSceneLoadData> 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<eastl::string> theSourcePathData(inParser->GetSourcePaths());
+ const QVector<QString> slideSourcePaths = inParser->GetSlideSourcePaths();
+ IBufferManager &theManager(m_Context->m_Context->GetBufferManager());
+ // List of image paths to be loaded in parallel at the end.
+ eastl::vector<CRegisteredString> theSourcePathList;
+ eastl::vector<CRegisteredString> 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<TImageBatchId>(imageBatchId));
+ m_Context->m_Context->GetImageBatchLoader().BlockUntilLoaded(
+ static_cast<TImageBatchId>(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<QT3DSU8> theLoadedData(inData.Data());
+ SDataReader theReader(theLoadedData.begin(), theLoadedData.end());
+
+ QT3DSU32 theFileSig = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theBinaryVersion = theReader.LoadRef<QT3DSU32>();
+ 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<QT3DSU32>();
+
+ NVDataRef<QT3DSU8> theSGData = NVDataRef<QT3DSU8>(theReader.m_CurrentPtr, theTranslatorOffset);
+ NVDataRef<QT3DSU8> theTranslatorData = NVDataRef<QT3DSU8>(
+ 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<QT3DSU32>();
+ 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<CRegisteredString> imagePathList(m_Context->GetAllocator(),
+ "imagePathList");
+ nvvector<CRegisteredString> 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<PROC_Initialize>(theDLLManager.GetProc("Initialize", theHandle));
+ Q3DStudio_ASSERT(theInitializeProc);
+#if !defined (Q_OS_MACOS)
+ PROC_SetEGLInfo theSetEGLInfoProc =
+ reinterpret_cast<PROC_SetEGLInfo>(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<Qt3DSRenderScene &>(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<QT3DSU32 *>(theWriteBuffer.begin() + theTranslatorCountAddress);
+ *theTranslatorCountPtr = theTranslatorCount;
+ QT3DSU32 *theTranslatorOffsetPtr =
+ reinterpret_cast<QT3DSU32 *>(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<pair<CRegisteredString, eastl::pair<bool, bool>>>::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<QT3DSU32 *>(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<qt3ds::QT3DSU8> 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>();
+ QT3DSU32 theMaterialSystemOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theBinaryPathOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 thePluginManagerOffset = theReader.LoadRef<QT3DSU32>();
+ QT3DSU32 theStringTableOffset = theReader.LoadRef<QT3DSU32>();
+ 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<QT3DSU32>();
+ 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<CRegisteredString>();
+ QT3DSU32 theFlags = theReader.LoadRef<QT3DSU32>();
+ 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<QT3DSU8> 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<QT3DSU8> 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<QT3DSU8> 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<QT3DSU8> 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<Q3DStudio::INT32>(theDisplayViewport.m_Width),
+ static_cast<Q3DStudio::INT32>(theDisplayViewport.m_Height));
+ }
+ return Q3DStudio::STextSizes(static_cast<Q3DStudio::INT32>(0),
+ static_cast<Q3DStudio::INT32>(0));
+ }
+
+ Q3DStudio::TElement *UserPick(float mouseX, float mouseY) override
+ {
+ if (m_LastRenderedScene) {
+ return m_LastRenderedScene->UserPick(mouseX, mouseY);
+ }
+ return nullptr;
+ }
+
+ Option<QT3DSVec2> FacePosition(Q3DStudio::TElement &inElement, float mouseX, float mouseY,
+ NVDataRef<Q3DStudio::TElement *> 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<PROC_Uninitialize>(
+ 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<SBindingCore> theContext(m_Context);
+ NVDelete(m_Context->GetAllocator(), this);
+ }
+};
+
+struct SRenderFactory;
+
+struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFactory
+{
+ NVScopedRefCounted<SBindingCore> m_Context;
+
+ NVScopedRefCounted<Q3DStudio::CQmlEngine> m_ScriptBridgeQml;
+ NVScopedRefCounted<Qt3DSRenderSceneManager> m_SceneManager;
+ NVScopedRefCounted<qt3ds::evt::IEventSystem> 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<SBindingCore> 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<SBindingCore *>(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 <QSurfaceFormat>
+
+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<NVFoundation> m_Foundation;
+ NVScopedRefCounted<IStringTable> m_StringTable;
+ NVScopedRefCounted<IQt3DSRenderContextCore> m_CoreContext;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ NVScopedRefCounted<IQt3DSRenderContext> 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<QT3DSU8> 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<Qt3DSTranslator, STranslatorGetOp, STranslatorSetOp> 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<SBindingCore> m_BindingCore;
+ NVScopedRefCounted<IQt3DSRenderContext> m_Context;
+ NVRenderRect m_Viewport;
+ nvvector<NVRenderRect> 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<Q3DStudio::FLOAT>(m_BindingCore->m_WindowDimensions.width());
+ theY = theY / static_cast<Q3DStudio::FLOAT>(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<ScaleModes::Enum>(inScale));
+ }
+ Q3DStudio::TegraRenderScaleModes::Enum GetScaleMode() const override
+ {
+ if (m_BindingCore && m_BindingCore->m_Context)
+ return static_cast<Q3DStudio::TegraRenderScaleModes::Enum>(
+ const_cast<SRenderer &>(*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<SBindingCore> 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<QT3DSVec4> 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<qt3ds::QT3DSVec3> inColor, const char *text) override
+ {
+ m_Context->RenderText2D(x, y, inColor, text);
+ }
+
+ void RenderGpuProfilerStats(Q3DStudio::FLOAT x, Q3DStudio::FLOAT y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> 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<Qt3DSTranslator>
+ {
+ static QT3DSU32 GetTag() { return g_TranslatorTag; }
+ };
+ template <>
+ struct SPointerTag<Q3DStudio::IPresentation>
+ {
+ static QT3DSU32 GetTag() { return g_PresentationTag; }
+ };
+}
+}
+
+namespace {
+
+template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+struct SDirtySetter
+{
+};
+
+template <>
+struct SDirtySetter<Qt3DSRenderDirtyFlags::Dirty>
+{
+ static void Set(bool &dirty, bool & /*transformDirty*/, bool & /*textDirty*/) { dirty = true; }
+};
+template <>
+struct SDirtySetter<Qt3DSRenderDirtyFlags::TransformDirty>
+{
+ static void Set(bool &dirty, bool &transformDirty, bool & /*textDirty*/)
+ {
+ dirty = true;
+ transformDirty = true;
+ }
+};
+template <>
+struct SDirtySetter<Qt3DSRenderDirtyFlags::TextDirty>
+{
+ static void Set(bool &dirty, bool & /*transformDirty*/, bool &textDirty)
+ {
+ dirty = true;
+ textDirty = true;
+ }
+};
+template <>
+struct SDirtySetter<Qt3DSRenderDirtyFlags::Unknown>
+{
+ 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 <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ void SetDirty()
+ {
+ SDirtySetter<TDirtyType>::Set(m_Dirty, m_TransformDirty, m_TextDirty);
+ }
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(QT3DSF32 &outValue)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT) {
+ QT3DSF32 newValue = m_Value.m_FLOAT;
+ if (outValue != newValue) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ };
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseProperty(QT3DSU32 &outValue)
+ {
+ if (m_Type == Q3DStudio::ATTRIBUTETYPE_INT32) {
+ QT3DSU32 newValue = (QT3DSU32)m_Value.m_INT32;
+ if (outValue != newValue) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ };
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<Qt3DSTranslator *>(theElem->GetAssociation());
+ if (theTranslator)
+ newValue = theTranslator->m_RenderObject;
+ }
+ if (outValue != newValue) {
+ outValue = newValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ };
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseRadianProperty(QT3DSF32 &outValue)
+ {
+ if (ParseProperty<TDirtyType>(outValue)) {
+ TORAD(outValue);
+ return true;
+ }
+ return false;
+ }
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseOpacityProperty(QT3DSF32 &outValue)
+ {
+ if (ParseProperty<TDirtyType>(outValue)) {
+ outValue *= 1.0f / 100.0f;
+ return true;
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseInverseBoolean(bool &ioCurrent)
+ {
+ bool temp = !ioCurrent;
+ if (ParseProperty<TDirtyType>(temp)) {
+ ioCurrent = temp;
+ return true;
+ }
+ return false;
+ }
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<TDirtyType>();
+ return true;
+ }
+ } else {
+ QT3DS_ASSERT(false);
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseRotationOrder(QT3DSU32 &outValue)
+ {
+ CRegisteredString theString;
+ ParseProperty<Qt3DSRenderDirtyFlags::Unknown>(theString);
+ if (theString.IsValid()) {
+ QT3DSU32 newRotationOrder = MapRotationOrder(theString);
+ if (newRotationOrder != outValue) {
+ outValue = newRotationOrder;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseOrientation(NodeFlags &outValue)
+ {
+ bool temp = false;
+ ParseOrientationProperty<TDirtyType>(temp);
+ bool wasLeftHanded = outValue.IsLeftHanded();
+ if (wasLeftHanded != temp) {
+ outValue.SetLeftHanded(temp);
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ }
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseNodeFlagsProperty(NodeFlags &outValue, NodeFlagValues::Enum inFlag)
+ {
+ bool temp = false;
+ ParseProperty<Qt3DSRenderDirtyFlags::Unknown>(temp);
+ bool wasSet = outValue & inFlag;
+ if (temp != wasSet) {
+ outValue.ClearOrSet(temp, inFlag);
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseNodeFlagsInverseProperty(NodeFlags &outValue, NodeFlagValues::Enum inFlag)
+ {
+ bool temp = false;
+ ParseProperty<Qt3DSRenderDirtyFlags::Unknown>(temp);
+ temp = !temp;
+ bool wasSet = outValue & inFlag;
+ if (temp != wasSet) {
+ outValue.ClearOrSet(temp, inFlag);
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType, typename TEnumType>
+ bool ParseEnumProperty(TEnumType &outValue)
+ {
+ CRegisteredString theString;
+ ParseProperty<Qt3DSRenderDirtyFlags::Unknown>(theString);
+ if (theString.IsValid()) {
+ SEnumNameMap *theMap = SEnumParseMap<TEnumType>::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<TEnumType>(theItem->m_Enum);
+ if (outValue != theNewValue) {
+ outValue = theNewValue;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ bool ParseAndResolveSourcePath(CRegisteredString &outValue)
+ {
+ CRegisteredString theTemp;
+ ParseProperty<Qt3DSRenderDirtyFlags::Unknown>(theTemp);
+ CRegisteredString theNewStr = theTemp;
+ if (outValue.c_str() != theNewStr.c_str()) {
+ SetDirty<TDirtyType>();
+ outValue = theNewStr;
+ return true;
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<Qt3DSTranslator *>(theElem->GetAssociation());
+ if (theTranslator != NULL && theTranslator->GetUIPType() == GraphObjectTypes::Image) {
+ SImage *theImage = static_cast<SImage *>(theTranslator->m_RenderObject);
+ if (ioImagePtr != theImage) {
+ ioImagePtr = theImage;
+ SetDirty<TDirtyType>();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ template <Qt3DSRenderDirtyFlags::Enum TDirtyType>
+ 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<Qt3DSTranslator *>(theElem->GetAssociation());
+ if (theTranslator != NULL
+ && GraphObjectTypes::IsNodeType(theTranslator->GetUIPType())) {
+ theNode = static_cast<SNode *>(theTranslator->m_RenderObject);
+ }
+ }
+ if (ioNodePtr != theNode) {
+ ioNodePtr = theNode;
+ SetDirty<TDirtyType>();
+ 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<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_VEC3_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_X: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break; \
+ case Q3DStudio::type##_##name##_Z: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.z); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_REAL_VEC2_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_X: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_COLOR_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_R: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_G: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break; \
+ case Q3DStudio::type##_##name##_B: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.z); \
+ break; \
+ case Q3DStudio::type##_##name##_A: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.w); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_COLOR_VEC3_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_TRANSFORM_VEC3_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_RADIAN_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseRadianProperty<Qt3DSRenderDirtyFlags::dirty>(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<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.y); \
+ break; \
+ case Q3DStudio::type##_##name##_Z: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.z); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_OPACITY_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseOpacityProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_ROTATION_ORDER_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseRotationOrder<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_NODE_ORIENTATION_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseOrientation<Qt3DSRenderDirtyFlags::dirty>(theItem.m_Flags); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_DEPTH_TEST_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseInverseBoolean<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_NODE_FLAGS_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseNodeFlagsProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_Flags, \
+ NodeFlagValues::name); \
+ break;
+
+#define HANDLE_QT3DS_NODE_FLAGS_INVERSE_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseNodeFlagsInverseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_Flags, \
+ NodeFlagValues::name); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_ENUM_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseEnumProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_SOURCEPATH_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name: \
+ inParser.ParseAndResolveSourcePath<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_ARRAY_PROPERTY(type, name, index, dirty) \
+ case Q3DStudio::type##_##name##_##index: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name[index]); \
+ break;
+
+#define HANDLE_QT3DS_RENDER_VEC2_PROPERTY(type, name, dirty) \
+ case Q3DStudio::type##_##name##_X: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(theItem.m_##name.x); \
+ break; \
+ case Q3DStudio::type##_##name##_Y: \
+ inParser.ParseProperty<Qt3DSRenderDirtyFlags::dirty>(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<SScene *>(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<SNode *>(m_RenderObject);
+ theItem.m_Flags.SetLocallyPickable(false);
+ }
+ void SetActive(bool inElementActive)
+ {
+ SNode &theItem = *static_cast<SNode *>(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<SNode *>(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<SNode *>(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<SLayer *>(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<SLight *>(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<SCamera *>(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<SModel *>(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<SPath *>(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<SPathSubPath *>(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<SPathSubPath *>(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<qt3ds::render::SPathAnchorPoint> 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<SDefaultMaterial *>(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<SDefaultMaterial *>(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<SImage *>(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<SImage *>(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<TNodeType *>(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<TNodeType *>(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<SText *>(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<Q3DStudio::INT32, SEffectPropertyEntry> 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<qt3ds::render::dynamic::SPropertyDefinition> 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<qt3ds::render::dynamic::SPropertyDefinition> 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<SEffect *>(m_RenderObject);
+ static_cast<SDynamicObjectTranslatorContext *>(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<SCustomMaterial *>(m_RenderObject);
+ static_cast<SDynamicObjectTranslatorContext *>(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<int, CRegisteredString> m_AttribHashIndexMap;
+ nvvector<SRenderPropertyValueUpdate> 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<SRenderPlugin *>(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<SRenderPluginTranslatorContext &>(*m_TranslatorContext);
+ if (theTransContext.m_AttribHashIndexMap.empty()) {
+ NVConstDataRef<SRenderPluginPropertyDeclaration> 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<int, CRegisteredString>::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<void *>(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<Qt3DSTranslator *>(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<size_t *>(&theNewTranslator->m_RenderObject);
+ *graphObjPtr = inGraphObjectOffset;
+}
+
+Qt3DSTranslator *Qt3DSTranslator::GetTranslatorFromGraphNode(SGraphObject &inObject)
+{
+ return inObject.m_UserData.DynamicCast<Qt3DSTranslator>();
+}
+
+namespace {
+struct SPresentationTranslator;
+struct SEffectTranslator;
+template <typename TTranslatorType>
+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<sizeof(TTranslatorType) == sizeof(Qt3DSTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, TTranslatorType)(inElement, static_cast<TNodeType &>(inObject));
+ }
+ static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &)
+ {
+ typedef typename TTranslatorType::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator) TTranslatorType(inTranslator.Element(),
+ static_cast<TNodeType &>(inTranslator.RenderObject()));
+ }
+
+ static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation,
+ IQt3DSRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ TTranslatorType &theTranslator(static_cast<TTranslatorType &>(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<SPresentationTranslator>
+{
+ 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<SEffectTranslator>
+{
+ 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<sizeof(SEffectTranslator) == sizeof(Qt3DSTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, SEffectTranslator)(inElement, static_cast<TNodeType &>(inObject),
+ inAllocator);
+ }
+
+ static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &inAllocator)
+ {
+ typedef SEffectTranslator::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator)
+ SEffectTranslator(inTranslator.Element(),
+ static_cast<TNodeType &>(inTranslator.RenderObject()), inAllocator);
+ }
+ static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation,
+ IQt3DSRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ static_cast<SEffectTranslator &>(inTranslator)
+ .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation);
+ }
+};
+
+template <>
+struct STranslatorCreator<SCustomMaterialTranslator>
+{
+ 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<sizeof(SCustomMaterialTranslator)
+ == sizeof(Qt3DSTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, SCustomMaterialTranslator)(
+ inElement, static_cast<TNodeType &>(inObject), inAllocator);
+ }
+
+ static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &inAllocator)
+ {
+ typedef SCustomMaterialTranslator::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator) SCustomMaterialTranslator(
+ inTranslator.Element(), static_cast<TNodeType &>(inTranslator.RenderObject()),
+ inAllocator);
+ }
+
+ static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation,
+ IQt3DSRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ static_cast<SCustomMaterialTranslator &>(inTranslator)
+ .OnElementChanged(inPresentation, inRenderContext, inStudioPresentation);
+ }
+};
+
+template <>
+struct STranslatorCreator<SRenderPluginTranslator>
+{
+ 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<sizeof(SRenderPluginTranslator) == sizeof(Qt3DSTranslator)>::valid_expression();
+ return QT3DS_NEW(inAllocator, SRenderPluginTranslator)(
+ inElement, static_cast<TNodeType &>(inObject), inAllocator);
+ }
+
+ static void InitializeTranslator(Qt3DSTranslator &inTranslator, NVAllocatorCallback &inAllocator)
+ {
+ typedef SRenderPluginTranslator::TNodeType TNodeType;
+ // Initialize the vtable.
+ new (&inTranslator) SRenderPluginTranslator(
+ inTranslator.Element(), static_cast<TNodeType &>(inTranslator.RenderObject()),
+ inAllocator);
+ }
+ static void OnElementChanged(Qt3DSTranslator &inTranslator, SPresentation &inPresentation,
+ IQt3DSRenderContext &inRenderContext,
+ Q3DStudio::IPresentation &inStudioPresentation)
+ {
+ static_cast<SRenderPluginTranslator &>(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<S##type##Translator>::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<S##type##Translator>::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<QT3DSU8> 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<Qt3DSTranslator>();
+ if (theTranslator) {
+ size_t *elemPtr = reinterpret_cast<size_t *>(&theTranslator->m_Element);
+ *elemPtr += inElemOffset;
+ size_t *graphObjPtr = reinterpret_cast<size_t *>(&theTranslator->m_RenderObject);
+ size_t sgSectionStart = reinterpret_cast<size_t>(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<S##type##Translator>::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<Q3DStudio::IPresentation>();
+}
+
+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 <time.h>
+#include "Qt3DSArray.h"
+// For perf log timestamp
+#include <time.h>
+
+#ifdef _LINUXPLATFORM
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#ifdef ANDROID
+#include <android/log.h>
+#endif
+
+#include <QCoreApplication>
+#include <QSurfaceFormat>
+
+//==============================================================================
+// 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<qt3ds::render::IQt3DSRenderFactoryCore> m_RuntimeFactoryCore;
+ ///< Base application before graphics
+ NVScopedRefCounted<qt3ds::runtime::IApplication> m_ApplicationCore;
+
+ // Post graphics init objects
+ NVScopedRefCounted<qt3ds::render::IQt3DSRenderFactory> m_RuntimeFactory;
+ NVScopedRefCounted<qt3ds::runtime::IApplication> 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 &currentIndex, int &previousIndex,
+ QString &currentName, 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<QString> dataInputs() const override;
+ QList<QString> dataOutputs() const override;
+ float dataInputMax(const QString &name) const override;
+ float dataInputMin(const QString &name) const override;
+ QHash<QString, QString> dataInputMetadata(const QString &name) const override;
+
+ void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &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<SPresentationSize> 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<QT3DSF32, QT3DSF32> fps
+ = m_RuntimeFactory->GetQt3DSRenderContext().GetFPS();
+ const QVector<QT3DSF32> 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<const QMouseEvent *>(inEvent);
+ m_InputEngine->SetPickInput(static_cast<FLOAT>(event->x()),
+ static_cast<FLOAT>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+
+ theBridgeEngine.GotoSlideRelative(elementPath, next, wrap, SScriptEngineGotoSlideArgs());
+ }
+}
+
+bool CRuntimeView::GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
+ QString &currentName, QString &previousName)
+{
+ if (m_Application && elementPath) {
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+ theBridgeEngine.SetDataInputValue(name, value, (qt3ds::runtime::DataInputValueRole)property);
+ }
+}
+
+QList<QString> CRuntimeView::dataInputs() const
+{
+ if (m_Application)
+ return m_Application->dataInputs();
+
+ return {};
+}
+
+QList<QString> 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<QString, QString> 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<QHash<QString, QVariant>> &properties)
+{
+ if (m_Application) {
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<Q3DStudio::CQmlEngine &>(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<SPresentationSize> 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<CTegraInputEngine *>(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 <QtCore/qobject.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qstringlist.h>
+#include <QtGui/qsurfaceformat.h>
+
+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<qt3ds::QT3DSVec4> 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<qt3ds::QT3DSVec3> inColor,
+ const char *text) = 0;
+ virtual void RenderGpuProfilerStats(FLOAT x, FLOAT y,
+ qt3ds::foundation::Option<qt3ds::QT3DSVec3> 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 &currentIndex, int &previousIndex,
+ QString &currentName, 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<QString> dataInputs() const = 0;
+ virtual QList<QString> dataOutputs() const = 0;
+ virtual float dataInputMax(const QString &name) const = 0;
+ virtual float dataInputMin(const QString &name) const = 0;
+ virtual QHash<QString, QString> dataInputMetadata(const QString &name) const = 0;
+ virtual void createElements(const QString &parentElementPath, const QString &slideName,
+ const QVector<QHash<QString, QVariant>> &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<SPresentationSize> 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<const QMouseEvent *>(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 <QtCore/qsize.h>
+
+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