summaryrefslogtreecommitdiffstats
path: root/src/system
diff options
context:
space:
mode:
Diffstat (limited to 'src/system')
-rw-r--r--src/system/Qt3DSArray.h135
-rw-r--r--src/system/Qt3DSArray.inl287
-rw-r--r--src/system/Qt3DSAssert.cpp93
-rw-r--r--src/system/Qt3DSAssert.h78
-rw-r--r--src/system/Qt3DSAudioPlayer.h42
-rw-r--r--src/system/Qt3DSBasicPluginDLL.h67
-rw-r--r--src/system/Qt3DSBezierEval.h182
-rw-r--r--src/system/Qt3DSBoundingBox.cpp150
-rw-r--r--src/system/Qt3DSBoundingBox.h85
-rw-r--r--src/system/Qt3DSCircularArray.h102
-rw-r--r--src/system/Qt3DSCircularArray.inl225
-rw-r--r--src/system/Qt3DSColor.cpp95
-rw-r--r--src/system/Qt3DSColor.h85
-rw-r--r--src/system/Qt3DSConfig.h49
-rw-r--r--src/system/Qt3DSCubicRoots.cpp38
-rw-r--r--src/system/Qt3DSCubicRoots.h78
-rw-r--r--src/system/Qt3DSCubicRootsImpl.h177
-rw-r--r--src/system/Qt3DSDLLManager.cpp220
-rw-r--r--src/system/Qt3DSDLLManager.h96
-rw-r--r--src/system/Qt3DSDataLogger.cpp151
-rw-r--r--src/system/Qt3DSDataLogger.h226
-rw-r--r--src/system/Qt3DSDataLogger.hpp96
-rw-r--r--src/system/Qt3DSDataLoggerEnums.h117
-rw-r--r--src/system/Qt3DSDataLoggerViewer.h71
-rw-r--r--src/system/Qt3DSEGLTimer.h70
-rw-r--r--src/system/Qt3DSEndian.h38
-rw-r--r--src/system/Qt3DSEulerAngles.cpp390
-rw-r--r--src/system/Qt3DSEulerAngles.h141
-rw-r--r--src/system/Qt3DSFNDTimer.h44
-rw-r--r--src/system/Qt3DSFile.cpp77
-rw-r--r--src/system/Qt3DSFile.h94
-rw-r--r--src/system/Qt3DSFileStream.cpp237
-rw-r--r--src/system/Qt3DSFileStream.h93
-rw-r--r--src/system/Qt3DSFixedArray.h87
-rw-r--r--src/system/Qt3DSFixedArray.inl150
-rw-r--r--src/system/Qt3DSFunctionWrappers.cpp65
-rw-r--r--src/system/Qt3DSFunctionWrappers.h416
-rw-r--r--src/system/Qt3DSHash.h105
-rw-r--r--src/system/Qt3DSIFileStream.h56
-rw-r--r--src/system/Qt3DSIStream.h162
-rw-r--r--src/system/Qt3DSITimer.h61
-rw-r--r--src/system/Qt3DSMacros.h189
-rw-r--r--src/system/Qt3DSMatrix.cpp897
-rw-r--r--src/system/Qt3DSMatrix.h146
-rw-r--r--src/system/Qt3DSMemory.cpp137
-rw-r--r--src/system/Qt3DSMemory.h183
-rw-r--r--src/system/Qt3DSMemoryFilter.cpp126
-rw-r--r--src/system/Qt3DSMemoryFilter.h69
-rw-r--r--src/system/Qt3DSMemoryHeap.cpp236
-rw-r--r--src/system/Qt3DSMemoryHeap.h133
-rw-r--r--src/system/Qt3DSMemoryManager.cpp453
-rw-r--r--src/system/Qt3DSMemoryManager.h133
-rw-r--r--src/system/Qt3DSMemoryPool.cpp298
-rw-r--r--src/system/Qt3DSMemoryPool.h104
-rw-r--r--src/system/Qt3DSMemoryProbe.cpp149
-rw-r--r--src/system/Qt3DSMemoryProbe.h144
-rw-r--r--src/system/Qt3DSMemorySettings.h131
-rw-r--r--src/system/Qt3DSMemoryStatistics.cpp647
-rw-r--r--src/system/Qt3DSMemoryStatistics.h137
-rw-r--r--src/system/Qt3DSMemoryTracker.cpp164
-rw-r--r--src/system/Qt3DSMemoryTracker.h104
-rw-r--r--src/system/Qt3DSPlatformSpecific.h207
-rw-r--r--src/system/Qt3DSTimer.cpp116
-rw-r--r--src/system/Qt3DSTimer.h142
-rw-r--r--src/system/Qt3DSTypes.cpp54
-rw-r--r--src/system/Qt3DSTypes.h121
-rw-r--r--src/system/Qt3DSVector3.cpp466
-rw-r--r--src/system/Qt3DSVector3.h117
-rw-r--r--src/system/SystemPrefix.h92
69 files changed, 11126 insertions, 0 deletions
diff --git a/src/system/Qt3DSArray.h b/src/system/Qt3DSArray.h
new file mode 100644
index 0000000..805b8b0
--- /dev/null
+++ b/src/system/Qt3DSArray.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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 "Qt3DSMemorySettings.h"
+#include "Qt3DSMemory.h"
+#include "Qt3DSPlatformSpecific.h"
+
+#ifdef WIN32
+#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
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+#define NVARRAY_NOTFOUND -1
+
+//==============================================================================
+/**
+ * Ordered Collection also knows as a vector.
+ *
+ * Use Reserve or the constructor parameter if you know how many slots
+ * will be needed to prevent frequent reallocations during growth.
+ *
+ * The array grows by DEFAULT_GROWFACTOR aka 20% whenever it overflows. By
+ * setting the factor to 0 it will still clamp to 1 and instead grow the
+ * array by one slot at a time. This is not ideal but given a pooled memory
+ * manager you will not thrash memory too much since you will grow inside
+ * each pool chunk and only reallocate when switching pools.
+ *
+ * Naming of CArray instances are used to enable memory tracking of arrays
+ * that have gone berzerk or less frequently used instances that could be
+ * released after usage.
+ *
+ * The FOR_ARRAY macro is the preferred way to process all array slots.
+ */
+template <class T>
+class CArray
+{
+//==============================================================================
+// Constants
+//==============================================================================
+#define DEFAULT_GROWFACTOR 1.2f
+
+ //==============================================================================
+ // Types
+ //==============================================================================
+public:
+ typedef T TType; ///< Easy access to template type
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ CHAR m_Name[32]; ///< Allows easy ID using memory reporting
+ T *m_Data; ///< Allocated memory containing array data
+ INT32 m_Capacity; ///< Max number of slots possible
+ INT32 m_Count; ///< Current number of slots in array
+ FLOAT m_GrowFactor; ///< Factor by which array grows when out of space
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CArray(const INT32 inCapacity = 0, const FLOAT inGrowFactor = DEFAULT_GROWFACTOR,
+ const CHAR *inName = NULL);
+ inline CArray(const CArray<T> &);
+ inline ~CArray();
+
+public: // Management
+ inline void SetName(const CHAR *inName = NULL);
+ inline INT32 GetCount() const;
+ inline INT32 GetCapacity() const;
+ inline void Clear(const BOOL inRelease = true);
+ inline void Reserve(const INT32 inCapacity, const BOOL inExpand = false);
+
+public: // Stack access
+ void Push(const T &inValue);
+ inline const T &Pop();
+ inline const T &Top() const;
+
+public: // Random access
+ inline INT32 GetIndex(const T &inValue) const;
+ inline T &operator[](const INT32 inIndex) const;
+ inline void Remove(const INT32 inIndex);
+
+public: // FOR_ARRAY iteration
+ inline T *Begin() const;
+ inline T *End() const;
+
+private: // Disabled Copy Construction
+ inline CArray<T> &operator=(const CArray<T> &);
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Template code
+//==============================================================================
+#include "Qt3DSArray.inl"
diff --git a/src/system/Qt3DSArray.inl b/src/system/Qt3DSArray.inl
new file mode 100644
index 0000000..a9667fd
--- /dev/null
+++ b/src/system/Qt3DSArray.inl
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2007 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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ *
+ * @param inCapacity preallocated number of slots to avoid growth reallocation
+ * @param inGrowFactor factor by which the array grows when out of space
+ * @param inName 32 byte unique identifier for memory tracking
+ */
+template <typename T> inline
+CArray<T>::CArray( const INT32 inCapacity, const FLOAT inGrowFactor, const CHAR* inName ) :
+ m_Data( NULL ),
+ m_Capacity( 0 ),
+ m_Count( 0 ),
+ m_GrowFactor( inGrowFactor )
+{
+ // Disallow negative growth
+ if ( m_GrowFactor < 1.0f )
+ m_GrowFactor = DEFAULT_GROWFACTOR;
+
+ SetName( inName );
+ Reserve( inCapacity );
+}
+
+//==============================================================================
+/**
+ * Berger's Copy Constructor.
+ */
+template <typename T> inline
+CArray<T>::CArray( const CArray<T>& inOther ) :
+ m_Data( NULL ),
+ m_Capacity( 0 ),
+ m_Count( 0 ),
+ m_GrowFactor( inOther.m_GrowFactor )
+{
+ // Disallow negative growth
+ if ( m_GrowFactor < 1.0f )
+ m_GrowFactor = DEFAULT_GROWFACTOR;
+
+ SetName( inOther.m_Name );
+ Reserve( inOther.m_Capacity );
+ FOR_ARRAY( T, theTemp, inOther )
+ {
+ Push( *theTemp );
+ }
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+template <class T> inline
+CArray<T>::~CArray( )
+{
+ Clear( true );
+}
+
+//==============================================================================
+/**
+ * Name an array instance to easily identify it during memory reporting.
+ * @param inName 32 byte unique identifier
+ */
+template <class T> inline
+void CArray<T>::SetName( const CHAR* inName /*= NULL*/ )
+{
+ Q3DStudio_sprintf( m_Name, sizeof( m_Name ), "%s", inName ? inName : "CArray<T>" );
+}
+
+//==============================================================================
+/**
+ * Count is the number of elements in the array.
+ * @return current count of the array
+ */
+template <class T> inline
+INT32 CArray<T>::GetCount( ) const
+{
+ return m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the capacity of the array
+ * Capacity reflects the max count before reallocation happens.
+ * @return capacity of the array
+ */
+template <class T> inline
+INT32 CArray<T>::GetCapacity( ) const
+{
+ return m_Capacity;
+}
+
+//==============================================================================
+/**
+ * Clear the array by reducing the number of elements to zero.
+ *
+ * Using the release flag keeps the memory load low but could be
+ * suboptimal in situations where you are always using roughly the same
+ * number of elements. In that scenario, the array would have to build up
+ * and reallocate up to the same number of elements every time causing
+ * stress on the system. Clearing but keeping the buffer by setting
+ * release to false is optimal in that case.
+ *
+ * @param inRelease true to release memory, false keeps old buffer
+ */
+template <class T> inline
+void CArray<T>::Clear( const BOOL inRelease )
+{
+ m_Count = 0;
+
+ if ( inRelease )
+ {
+ Q3DStudio_free( m_Data, T, m_Capacity );
+ m_Capacity = 0;
+ m_Data = NULL;
+ }
+ else
+ Q3DStudio_memset( m_Data, 0 , sizeof( T ) * m_Capacity );
+}
+
+//==============================================================================
+/**
+ * Allocate enough memory to store T.
+ *
+ * If current memory is not sufficient, new block of memory is allocated and
+ * data in current memory is copied to the new block of memory. Data pointer will
+ * point to the new block of memory and current memory is released.
+ *
+ * @param inCapacity indicate the amount of memory required.
+ * @param inExpand true to not only allocate but also extend array
+ */
+template <class T> inline
+void CArray<T>::Reserve( const INT32 inCapacity, const BOOL inExpand )
+{
+ if ( inCapacity > m_Capacity )
+ {
+ T* theData = Q3DStudio_allocate_desc( T, inCapacity, m_Name );
+ Q3DStudio_memset( theData, 0 , sizeof( T ) * inCapacity );
+ if ( m_Data != NULL )
+ {
+ Q3DStudio_memcpy( theData, m_Data, sizeof( T ) * m_Count );
+ Q3DStudio_free( m_Data, T, m_Capacity );
+ }
+ m_Data = theData;
+ m_Capacity = inCapacity;
+ }
+
+ if ( inExpand )
+ m_Count = inCapacity;
+}
+
+//==============================================================================
+/**
+ * Insert T to the end of the array
+ * @param inValue value of datatype T
+ */
+template <class T> inline
+void CArray<T>::Push( const T& inValue )
+{
+ if ( m_Count == m_Capacity )
+ Reserve( static_cast<INT32>( m_GrowFactor * m_Capacity ) + 1 );
+
+ m_Data[m_Count++] = inValue;
+}
+
+//==============================================================================
+/**
+ * Remove and retrieve T which is at the end of the array
+ * @return value of datatype T
+ */
+template <class T> inline
+const T& CArray<T>::Pop( )
+{
+ return m_Data[--m_Count];
+}
+
+//==============================================================================
+/**
+ * Get T which is at the end of the array
+ * @return reference of value of datatype T
+ */
+template <class T> inline
+const T& CArray<T>::Top( ) const
+{
+ return m_Data[m_Count - 1];
+}
+
+//==============================================================================
+/**
+ * Get index of first element that matches inValue
+ * @return index of element matching T or INDEX_NOTFOUND
+ */
+template <class T> inline
+INT32 CArray<T>::GetIndex( const T& inValue ) const
+{
+ for ( INT32 theIndex = 0; theIndex < m_Count; ++theIndex )
+ if ( inValue == m_Data[theIndex] )
+ return theIndex;
+ return NVARRAY_NOTFOUND;
+}
+
+//==============================================================================
+/**
+ * Get the element at a particular index position of the array.
+ * @note Range checking is only done is debug builds.
+ * @param inIndex the index of the array
+ * @return reference of value of datatype T
+ */
+template <class T> inline
+T& CArray<T>::operator[]( const INT32 inIndex ) const
+{
+ Q3DStudio_ASSERT( inIndex >= 0 && inIndex < m_Capacity );
+ return m_Data[inIndex];
+}
+
+//==============================================================================
+/**
+ * Remove T that resides at a particular index position of the array.
+ * Other T data with higher index value is shifted to occupy the empty slot
+ * created in the removal process.
+ * @param inIndex the index of the array
+ */
+template <class T> inline
+void CArray<T>::Remove( const INT32 inIndex )
+{
+ Q3DStudio_memmove( m_Data + inIndex, m_Data + inIndex + 1, sizeof( T ) * ( m_Count - inIndex - 1 ) );
+ --m_Count;
+}
+
+//==============================================================================
+/**
+ * Get T at the first index of the array.
+ * Mainly used for FOR_ARRAY macro implementation
+ * @return pointer to first value in array
+ */
+template <class T> inline
+T* CArray<T>::Begin( ) const
+{
+ return m_Data;
+}
+
+//==============================================================================
+/**
+ * Get T at the last index of the array.
+ * Mainly used for FOR_ARRAY macro implementation
+ * @return pointer to one beyond last value in array
+ */
+template <class T> inline
+T* CArray<T>::End( ) const
+{
+ return m_Data + m_Count;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSAssert.cpp b/src/system/Qt3DSAssert.cpp
new file mode 100644
index 0000000..63d3876
--- /dev/null
+++ b/src/system/Qt3DSAssert.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSAssert.h"
+#include "foundation/Qt3DSLogging.h"
+//==============================================================================
+// Platform Specific Includes
+//==============================================================================
+#if defined(_PCPLATFORM)
+#pragma warning(push, 3)
+#include <Windows.h>
+#include <crtdbg.h>
+#pragma warning(pop)
+#endif // #if defined (_PCPLATFORM)
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Global Variables
+//==============================================================================
+CAssert::TFunction CAssert::s_AssertFunction = CAssert::Default; ///< Default assert function
+
+//==============================================================================
+/**
+ * Default method for asserts
+ */
+void CAssert::Default(const CHAR *inAssert, const CHAR *inFile, INT32 inLine,
+ const CHAR *inFunction)
+{
+ // Use logger to report the string first
+ qCCritical (qt3ds::INTERNAL_ERROR) << "Assertion failed: " << inFile << " " << inLine
+ << " " << inAssert << " " << inFunction;
+
+#if defined(_DEBUG) && defined(_PCPLATFORM) && defined(QT3DS_VC)
+ if (_CrtDbgReport(_CRT_ASSERT, inFile, inLine, inFunction, "Assertion Failed") == 1)
+ ::DebugBreak();
+#endif // _DEBUG & _PCPLATFORM
+}
+
+//==============================================================================
+/**
+ * Method for setting the assert function
+ */
+void CAssert::SetFunction(TFunction inAssert)
+{
+ s_AssertFunction = inAssert;
+}
+
+//==============================================================================
+/**
+ * Method for getting the assert function
+ */
+CAssert::TFunction CAssert::GetFunction()
+{
+ return s_AssertFunction;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSAssert.h b/src/system/Qt3DSAssert.h
new file mode 100644
index 0000000..a64ca7f
--- /dev/null
+++ b/src/system/Qt3DSAssert.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 "Qt3DSTypes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Static gateway for all asserts.
+ *
+ * By setting your own assert function you can redirect all Runtime asserts.
+ * By default it uses the internal Default method that uses CLog for output
+ * and displays a dialog on Windows PCs.
+ */
+class CAssert
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef void (*TFunction)(const Q3DStudio::CHAR *inAssert, const Q3DStudio::CHAR *inFile,
+ Q3DStudio::INT32 inLine, const Q3DStudio::CHAR *inFunction);
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static TFunction s_AssertFunction; ///< Function pointer to active assert function
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+private: // Hidden Constructor
+ CAssert();
+
+public: // Static Usage
+ static void Default(const Q3DStudio::CHAR *inAssert, const Q3DStudio::CHAR *inFile,
+ Q3DStudio::INT32 inLine, const Q3DStudio::CHAR *inFunction);
+
+public: // Static Configuration
+ static void SetFunction(TFunction inAssert);
+ static TFunction GetFunction();
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSAudioPlayer.h b/src/system/Qt3DSAudioPlayer.h
new file mode 100644
index 0000000..3b6f3ef
--- /dev/null
+++ b/src/system/Qt3DSAudioPlayer.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+namespace Q3DStudio {
+
+class IAudioPlayer
+{
+public:
+ virtual ~IAudioPlayer() {}
+ virtual bool PlaySoundFile(const char *inFilePath) = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSBasicPluginDLL.h b/src/system/Qt3DSBasicPluginDLL.h
new file mode 100644
index 0000000..63a2d1f
--- /dev/null
+++ b/src/system/Qt3DSBasicPluginDLL.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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 <QtGlobal>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+// Enums
+//==============================================================================
+typedef enum _EDLLSTATUS { EDLLSTATUS_FAIL = 0, EDLLSTATUS_OK } EDLLSTATUS;
+
+// GetPluginType should return this
+typedef enum _EDLLTYPE {
+ EDLLTYPE_UNKNOWN = 0,
+ EDLLTYPE_RENDERABLE_PLUGIN,
+ EDLLTYPE_CUSTOM_OBJECT,
+} EDLLTYPE;
+
+//==============================================================================
+// Function declarations
+//==============================================================================
+
+//==============================================================================
+/**
+ * Return the plugin type.
+ * @return plugin type
+ */
+typedef long (*PROC_GetPluginType)();
+Q_DECL_EXPORT long GetPluginType();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/system/Qt3DSBezierEval.h b/src/system/Qt3DSBezierEval.h
new file mode 100644
index 0000000..c4d733a
--- /dev/null
+++ b/src/system/Qt3DSBezierEval.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Generic Bezier parametric curve evaluation at a given parametric value.
+ * @param inP0 control point P0
+ * @param inP1 control point P1
+ * @param inP2 control point P2
+ * @param inP3 control point P3
+ * @param inS the variable
+ * @return the evaluated value on the bezier curve
+ */
+inline FLOAT EvaluateBezierCurve(FLOAT inP0, FLOAT inP1, FLOAT inP2, FLOAT inP3, const FLOAT inS)
+{
+ // Using:
+ // Q(s) = Sum i=0 to 3 ( Pi * Bi,3(s))
+ // where:
+ // Pi is a control point and
+ // Bi,3 is a basis function such that:
+ //
+ // B0,3(s) = (1 - s)^3
+ // B1,3(s) = (3 * s) * (1 - s)^2
+ // B2,3(s) = (3 * s^2) * (1 - s)
+ // B3,3(s) = s^3
+
+ /* FLOAT theSSquared = inS * inS; //
+ t^2
+ FLOAT theSCubed = theSSquared * inS; //
+ t^3
+
+ FLOAT theSDifference = 1 - inS; // (1 -
+ t)
+ FLOAT theSDifferenceSquared = theSDifference * theSDifference; // (1 -
+ t)^2
+ FLOAT theSDifferenceCubed = theSDifferenceSquared * theSDifference; // (1 - t)^3
+
+ FLOAT theFirstTerm = theSDifferenceCubed; // (1 -
+ t)^3
+ FLOAT theSecondTerm = ( 3 * inS ) * theSDifferenceSquared; // (3 * t) * (1
+ - t)^2
+ FLOAT theThirdTerm = ( 3 * theSSquared ) * theSDifference; // (3 * t^2) *
+ (1 - t)
+ FLOAT theFourthTerm = theSCubed; //
+ t^3
+
+ // Q(t) = ( p0 * (1 - t)^3 ) + ( p1 * (3 * t) * (1 - t)^2 ) + ( p2 * (3 * t^2) * (1 - t)
+ ) + ( p3 * t^3 )
+ return ( inP0 * theFirstTerm ) + ( inP1 * theSecondTerm ) + ( inP2 * theThirdTerm ) + (
+ inP3 * theFourthTerm );*/
+
+ FLOAT theFactor = inS * inS;
+ inP1 *= 3 * inS;
+ inP2 *= 3 * theFactor;
+ theFactor *= inS;
+ inP3 *= theFactor;
+
+ theFactor = 1 - inS;
+ inP2 *= theFactor;
+ theFactor *= 1 - inS;
+ inP1 *= theFactor;
+ theFactor *= 1 - inS;
+ inP0 *= theFactor;
+
+ return inP0 + inP1 + inP2 + inP3;
+}
+
+//==============================================================================
+/**
+ * Inverse Bezier parametric curve evaluation to get parametric value for a given output.
+ * This is equal to finding the root(s) of the Bezier cubic equation.
+ * @param inP0 control point P0
+ * @param inP1 control point P1
+ * @param inP2 control point P2
+ * @param inP3 control point P3
+ * @param inX the variable
+ * @return the evaluated value
+ */
+inline FLOAT EvaluateInverseBezierCurve(const FLOAT inP0, const FLOAT inP1, const FLOAT inP2,
+ const FLOAT inP3, const FLOAT inX)
+{
+ FLOAT theResult = 0;
+
+ // Using:
+ // Q(s) = Sum i=0 to 3 ( Pi * Bi,3(s))
+ // where:
+ // Pi is a control point and
+ // Bi,3 is a basis function such that:
+ //
+ // B0,3(s) = (1 - s)^3
+ // B1,3(s) = (3 * s) * (1 - s)^2
+ // B2,3(s) = (3 * s^2) * (1 - s)
+ // B3,3(s) = s^3
+
+ // The Bezier cubic equation:
+ // inX = inP0*(1-s)^3 + inP1*(3*s)*(1-s)^2 + inP2*(3*s^2)*(1-s) + inP3*s^3
+ // = s^3*( -inP0 + 3*inP1 - 3*inP2 +inP3 ) + s^2*( 3*inP0 - 6*inP1 + 3*inP2 ) + s*( -3*inP0
+ // + 3*inP1 ) + inP0
+ // For cubic eqn of the form: c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 = 0
+ FLOAT theConstants[4];
+ theConstants[0] = static_cast<FLOAT>(inP0 - inX);
+ theConstants[1] = static_cast<FLOAT>(-3 * inP0 + 3 * inP1);
+ theConstants[2] = static_cast<FLOAT>(3 * inP0 - 6 * inP1 + 3 * inP2);
+ theConstants[3] = static_cast<FLOAT>(-inP0 + 3 * inP1 - 3 * inP2 + inP3);
+
+ FLOAT theSolution[3] = { 0 };
+
+ if (theConstants[3] == 0) {
+ if (theConstants[2] == 0) {
+ if (theConstants[1] == 0)
+ theResult = 0;
+ else
+ theResult = -theConstants[0] / theConstants[1]; // linear
+ } else {
+ // quadratic
+ INT32 theNumRoots = CCubicRoots::SolveQuadric(theConstants, theSolution);
+ theResult = static_cast<FLOAT>(theSolution[theNumRoots / 2]);
+ }
+ } else {
+ INT32 theNumRoots = CCubicRoots::SolveCubic(theConstants, theSolution);
+ theResult = static_cast<FLOAT>(theSolution[theNumRoots / 3]);
+ }
+
+ return theResult;
+}
+
+inline FLOAT EvaluateBezierKeyframe(FLOAT inTime, FLOAT inTime1, FLOAT inValue1, FLOAT inC1Time,
+ FLOAT inC1Value, FLOAT inC2Time, FLOAT inC2Value, FLOAT inTime2,
+ FLOAT inValue2)
+{
+
+ // The special case of C1Time=0 and C2Time=0 is used to indicate Studio-native animation.
+ // Studio uses a simplified version of the bezier animation where the time control points
+ // are equally spaced between the starting and ending times. This avoids calling the expensive
+ // InverseBezierCurve function to find the right 's' given 't'.
+ FLOAT theParameter;
+ if (inC1Time == 0 && inC2Time == 0) {
+ // Special case signaling that it's ok to treat time as "s"
+ // This is done by assuming that Key1Val,Key1C1,Key1C2,Key2Val (aka P0,P1,P2,P3)
+ // are evenly distributed over time.
+ theParameter = (inTime - inTime1) / (inTime2 - inTime1);
+ } else {
+ // Compute the "s" parameter on the Bezier given the time
+ theParameter = EvaluateInverseBezierCurve(inTime1, inC1Time, inC2Time, inTime2, inTime);
+ if (theParameter <= 0.0f)
+ return inValue1;
+ if (theParameter >= 1.0f)
+ return inValue2;
+ }
+
+ return EvaluateBezierCurve(inValue1, inC1Value, inC2Value, inValue2, theParameter);
+}
+}
diff --git a/src/system/Qt3DSBoundingBox.cpp b/src/system/Qt3DSBoundingBox.cpp
new file mode 100644
index 0000000..2a9331d
--- /dev/null
+++ b/src/system/Qt3DSBoundingBox.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSBoundingBox.h"
+#include "Qt3DSMatrix.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor - creates an empty BoundingBox
+ */
+CBoundingBox::CBoundingBox()
+ : m_Min(1.0f, 1.0f, 1.0f)
+ , m_Max(-1.0f, -1.0f, -1.0f)
+{
+}
+
+//==============================================================================
+/**
+ * Make BoundingBox invalid
+ */
+void CBoundingBox::SetEmpty()
+{
+ m_Min.Set(1.0f, 1.0f, 1.0f);
+ m_Max.Set(-1.0f, -1.0f, -1.0f);
+}
+
+//==============================================================================
+/**
+ * Is the BoundingBox empty?
+ * @return true if bounding box is empty, false otherwise
+ */
+BOOL CBoundingBox::IsEmpty() const
+{
+ return (m_Min.m_X > m_Max.m_X);
+}
+
+//==============================================================================
+/**
+ * Add a point to the BoundingBox
+ * @param inPoint a 3D point
+ */
+void CBoundingBox::Add(const RuntimeVector3 &inPoint)
+{
+ if (IsEmpty()) {
+ m_Min = inPoint;
+ m_Max = inPoint;
+ } else {
+ m_Min.Minimize(inPoint);
+ m_Max.Maximize(inPoint);
+ }
+}
+
+//==============================================================================
+/**
+ * Add another BoundingBox to this BoundingBox
+ * @param inBox a 3D BoundingBox
+ */
+void CBoundingBox::Add(const CBoundingBox &inBox)
+{
+ if (!inBox.IsEmpty()) {
+ Add(inBox.GetMin());
+ Add(inBox.GetMax());
+ }
+}
+
+//==============================================================================
+/**
+ * Get the bounding box's smallest position
+ * @return the smallest position of the bounding box
+ */
+const RuntimeVector3 &CBoundingBox::GetMin() const
+{
+ return m_Min;
+}
+
+//==============================================================================
+/**
+ * Get the bounding box's largest position
+ * @return the largest position of the bounding box
+ */
+const RuntimeVector3 &CBoundingBox::GetMax() const
+{
+ return m_Max;
+}
+
+//==============================================================================
+/**
+ * Apply a transform to the BoundingBox
+ * @param inMatrix a 4x4 trasnform matrix
+ */
+void CBoundingBox::Transform(const RuntimeMatrix &inMatrix)
+{
+ // Apply transform to the 8 corners of the BoundingBox and renormalize to majox axes
+ CBoundingBox theTransformedBox;
+ RuntimeVector3 theCorners[8];
+
+ theCorners[0].Set(m_Min.m_X, m_Min.m_Y, m_Min.m_Z);
+ theCorners[1].Set(m_Min.m_X, m_Min.m_Y, m_Max.m_Z);
+ theCorners[2].Set(m_Min.m_X, m_Max.m_Y, m_Min.m_Z);
+ theCorners[3].Set(m_Min.m_X, m_Max.m_Y, m_Max.m_Z);
+ theCorners[4].Set(m_Max.m_X, m_Min.m_Y, m_Min.m_Z);
+ theCorners[5].Set(m_Max.m_X, m_Min.m_Y, m_Max.m_Z);
+ theCorners[6].Set(m_Max.m_X, m_Max.m_Y, m_Min.m_Z);
+ theCorners[7].Set(m_Max.m_X, m_Max.m_Y, m_Max.m_Z);
+
+ for (INT32 theIndex = 0; theIndex < 8; ++theIndex) {
+ theCorners[theIndex].Transform(inMatrix);
+ theTransformedBox.Add(theCorners[theIndex]);
+ }
+ *this = theTransformedBox;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSBoundingBox.h b/src/system/Qt3DSBoundingBox.h
new file mode 100644
index 0000000..988a9ba
--- /dev/null
+++ b/src/system/Qt3DSBoundingBox.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSVector3.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeMatrix;
+
+//==============================================================================
+/**
+ * Axis aligned 3D bounding box construction and manipulation.
+ *
+ * Initial construction creates an inverted box signifying an Empty box instead
+ * of an infinitely small box at 0,0,0. Keep this in mind when asking for
+ * Min or max on a box that has had no points added to it.
+ *
+ * Transforming a box simply transforms all eight corners to span a new
+ * axis aligned bounding box. Successive transformations can thus create a
+ * non-optimal box, much larger than needed.
+ */
+class CBoundingBox
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ RuntimeVector3 m_Min; ///< box minimum corner point
+ RuntimeVector3 m_Max; ///< box maximum corner point
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CBoundingBox();
+
+public: // Functions
+ BOOL IsEmpty() const;
+ void SetEmpty();
+ void Add(const RuntimeVector3 &inPoint);
+ void Add(const CBoundingBox &inBox);
+ const RuntimeVector3 &GetMin() const;
+ const RuntimeVector3 &GetMax() const;
+ void Transform(const RuntimeMatrix &inMatrix);
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSCircularArray.h b/src/system/Qt3DSCircularArray.h
new file mode 100644
index 0000000..be92167
--- /dev/null
+++ b/src/system/Qt3DSCircularArray.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Circular array. Not growable for now.
+ * The "streamlined" interface acts like a resource pool where construction of
+ * item T is minimized.
+ */
+template <class T>
+class CCircularArray
+{
+ //==============================================================================
+ // Types
+ //==============================================================================
+public:
+ typedef T TType; ///< Easy access to template type
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ CHAR m_Name[32]; ///< Allows easy ID if it grows too much
+ T *m_Data; ///< Allocated memory containing array data
+ INT32 m_Capacity; ///< Max number of elements possible
+ INT32 m_Count; ///< Current number of elements in array
+
+ INT32 m_Begin; ///< circular list indices
+ INT32 m_End; ///< circular list indices
+
+ // For 32-bit alignment
+ BOOL m_Full; ///< flag to indicate circular list is full
+ BOOL m_Paddings[3]; ///< Padding
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CCircularArray(const INT32 inCapacity = 0, const CHAR *inName = NULL);
+ inline ~CCircularArray();
+
+public: // Management
+ inline INT32 GetCount() const;
+ inline INT32 GetCapacity() const;
+ inline void Clear(const BOOL inRelease = false);
+ inline void Reserve(const INT32 inCapacity);
+
+public: // Stack access
+ inline T &NewEntry();
+ inline void Pop();
+ inline T &Top();
+
+public: // Status
+ BOOL IsEmpty() const;
+ BOOL IsFull() const;
+
+protected: // Internal methods
+ void Increment(INT32 &outIndex);
+ void Decrement(INT32 &outIndex);
+ void UpdateFullStatus();
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Template code
+//==============================================================================
+#include "Qt3DSCircularArray.inl"
diff --git a/src/system/Qt3DSCircularArray.inl b/src/system/Qt3DSCircularArray.inl
new file mode 100644
index 0000000..0d7f081
--- /dev/null
+++ b/src/system/Qt3DSCircularArray.inl
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2007 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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+template <typename T> inline
+CCircularArray<T>::CCircularArray( const INT32 inCapacity, const CHAR* inName ) :
+ m_Data( NULL ),
+ m_Capacity( 0 ),
+ m_Count( 0 ),
+ m_Begin( 0 ),
+ m_End( 0 ),
+ m_Full( false )
+{
+ Q3DStudio_sprintf( m_Name, sizeof( m_Name ), "%s", inName ? inName : "CircularArray" );
+ Reserve( inCapacity );
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+template <class T> inline
+CCircularArray<T>::~CCircularArray( )
+{
+ Clear( true );
+}
+
+//==============================================================================
+/**
+ * Get the number of items in the array
+ * @return the number of items in the array
+ */
+template <class T> inline
+INT32 CCircularArray<T>::GetCount( ) const
+{
+ return m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the capacity of the array
+ * @return the capacity of the array
+ */
+template <class T> inline
+INT32 CCircularArray<T>::GetCapacity( ) const
+{
+ return m_Capacity;
+}
+
+//==============================================================================
+/**
+ * Remove all items from the array
+ * @param inRelease if true, release the allocated memory, if false, reset
+ * parameters back to zero.
+ */
+template <class T> inline
+void CCircularArray<T>::Clear( const BOOL inRelease )
+{
+ m_Count = 0;
+ m_Begin = 0;
+ m_End = 0;
+ m_Full = false;
+
+ if ( inRelease )
+ {
+ Q3DStudio_free( m_Data, T, m_Capacity );
+ m_Capacity = 0;
+ m_Data = NULL;
+ }
+}
+
+//==============================================================================
+/**
+ * Change capacity of the array
+ * Assume no expansion for circular array
+ * @param inCapacity the new capacity to set
+ */
+template <class T> inline
+void CCircularArray<T>::Reserve( const INT32 inCapacity )
+{
+ Q3DStudio_ASSERT( !m_Data );
+ T* theData = Q3DStudio_allocate_desc( T, inCapacity, m_Name );
+ m_Data = theData;
+ m_Capacity = inCapacity;
+}
+
+//==============================================================================
+/**
+ * Create a new uninitialized item at the end of the array.
+ * The returned reference is used to initialize the item.
+ * @return a reference to the item
+ */
+template <class T> inline
+T& CCircularArray<T>::NewEntry( )
+{
+ Q3DStudio_ASSERT( !IsFull( ) );
+ T& theResult = m_Data[m_End];
+ Increment( m_End );
+ UpdateFullStatus( );
+ ++m_Count;
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Remove the top entry from the array
+ */
+template <class T> inline
+void CCircularArray<T>::Pop( )
+{
+ Q3DStudio_ASSERT( !IsEmpty( ) );
+ Increment( m_Begin );
+ m_Full = false;
+ --m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the top item from the
+ * @return a reference to the item
+ */
+template <class T> inline
+T& CCircularArray<T>::Top( )
+{
+ Q3DStudio_ASSERT( !IsEmpty( ) );
+ return m_Data[m_Begin];
+}
+
+//==============================================================================
+/**
+ * Check if the array is empty
+ * @return true if empty, false otherwise.
+ */
+template <class T> inline
+BOOL CCircularArray<T>::IsEmpty( ) const
+{
+ return ( m_Begin == m_End ) && !m_Full;
+}
+
+//==============================================================================
+/**
+ * Check if the array is full
+ * @return true if full, false otherwise.
+ */
+template <class T> inline
+BOOL CCircularArray<T>::IsFull( ) const
+{
+ return m_Full;
+}
+
+//==============================================================================
+/**
+ * Increment index of the array
+ * @param outIndex the index to increment
+ */
+template <class T> inline
+void CCircularArray<T>::Increment( INT32& outIndex )
+{
+ ++outIndex;
+ // circular list wrap-around
+ if ( outIndex >= m_Capacity )
+ outIndex = 0;
+}
+
+//==============================================================================
+/**
+ * Decrement index of the array
+ * @param outIndex the index to decrement
+ */
+template <class T> inline
+void CCircularArray<T>::Decrement( INT32& outIndex )
+{
+ --outIndex;
+ // circular list wrap-around
+ if ( outIndex < 0 )
+ outIndex = m_Capacity - 1;
+}
+
+//==============================================================================
+/**
+ * Update the status of the m_Full flag.
+ * This is an internal method for use ONLY AFTER a item has been added to the array.
+ */
+template <class T> inline
+void CCircularArray<T>::UpdateFullStatus( )
+{
+ m_Full = ( m_End == m_Begin );
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSColor.cpp b/src/system/Qt3DSColor.cpp
new file mode 100644
index 0000000..a44d488
--- /dev/null
+++ b/src/system/Qt3DSColor.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSColor.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inColor 32 bit represenation of the color
+ */
+CColor::CColor(const Q3DStudio::UINT32 inColor)
+ : m_Color(inColor)
+{
+}
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inRed 8 bit represenation of the red component
+ * @param inGreen 8 bit representation of the green component
+ * @param inBlue 8 bit representation of the blue component
+ * @param inAlpha 8 bit representation of the transparency component
+ */
+CColor::CColor(const UINT8 inRed, const UINT8 inGreen, const UINT8 inBlue, const UINT8 inAlpha)
+ : m_Red(inRed)
+ , m_Green(inGreen)
+ , m_Blue(inBlue)
+ , m_Alpha(inAlpha)
+{
+}
+
+//==============================================================================
+/**
+ * Set the color to a blend between the two given colors.
+ * @param inColor1 Color representing factor 0
+ * @param inColor2 Color representing factor 1.0
+ * @param inFactor Blend factor where 0.5 is an even mix of the two colors
+ */
+void CColor::Interpolate(const CColor &inColor1, const CColor &inColor2, const FLOAT inFactor)
+{
+ // m_Red = static_cast<UINT8>( rand() % 256 );//( 1.0f - inFactor ) * inColor1.m_Red +
+ //inFactor * inColor2.m_Red );
+ // m_Green = static_cast<UINT8>( rand() % 256 );//( 1.0f - inFactor ) * inColor1.m_Green +
+ //inFactor * inColor2.m_Green );
+ // m_Blue = static_cast<UINT8>( rand() % 256 );//( 1.0f - inFactor ) * inColor1.m_Blue +
+ //inFactor * inColor2.m_Blue );
+ // m_Alpha = 255;//static_cast<UINT8>( ( 1.0f - inFactor ) * inColor1.m_Alpha + inFactor *
+ //inColor2.m_Alpha );
+
+ m_Red = static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Red + inFactor * inColor2.m_Red);
+ m_Green =
+ static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Green + inFactor * inColor2.m_Green);
+ m_Blue = static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Blue + inFactor * inColor2.m_Blue);
+ m_Alpha =
+ static_cast<UINT8>((1.0f - inFactor) * inColor1.m_Alpha + inFactor * inColor2.m_Alpha);
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSColor.h b/src/system/Qt3DSColor.h
new file mode 100644
index 0000000..b917f46
--- /dev/null
+++ b/src/system/Qt3DSColor.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Express a color and transparency using 32 bits.
+ */
+class CColor
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ union {
+ UINT32 m_Color; ///< 32bit representation of the color
+ struct
+ {
+ UINT8 m_Red; ///< Red component 0-255
+ UINT8 m_Green; ///< Green component 0-255
+ UINT8 m_Blue; ///< Blue component 0-255
+ UINT8 m_Alpha; ///< Transparency component 0-255
+ };
+ };
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CColor(const UINT32 inColor);
+ CColor(const UINT8 inRed = 255, const UINT8 inGreen = 255, const UINT8 inBlue = 255,
+ const UINT8 inAlpha = 255);
+
+public: // Setters
+ void SetColor(const UINT32 inColor) { m_Color = inColor; }
+ void SetRed(const UINT8 inRed) { m_Red = inRed; }
+ void SetGreen(const UINT8 inGreen) { m_Green = inGreen; }
+ void SetBlue(const UINT8 inBlue) { m_Blue = inBlue; }
+ void SetAlpha(const UINT8 inAlpha) { m_Alpha = inAlpha; }
+
+public: // Getters
+ UINT32 GetColor() const { return m_Color; }
+ UINT8 GetRed() const { return m_Red; }
+ UINT8 GetGreen() const { return m_Green; }
+ UINT8 GetBlue() const { return m_Blue; }
+ UINT8 GetAlpha() const { return m_Alpha; }
+
+public: // Utilities
+ void Interpolate(const CColor &inColor1, const CColor &inColor2, const FLOAT inFactor);
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSConfig.h b/src/system/Qt3DSConfig.h
new file mode 100644
index 0000000..49c644d
--- /dev/null
+++ b/src/system/Qt3DSConfig.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// This file should only contain macros that configure the build environment
+// and build options.
+//==============================================================================
+#include "Qt3DSMemorySettings.h"
+
+/// Number of chars to evaluate when generating a hash from a string.
+/// Verify that hash strings are unique after changing this value.
+#ifndef HASH_LIMIT
+#define HASH_LIMIT 100
+#endif // HASH_LIMIT
+
+/// Define this macro use use sync primitives(mutex/critical sections) when accessing
+/// shared data structures
+#ifndef Q3DStudio_USE_SYNC_PRIMITIVES
+#define Q3DStudio_USE_SYNC_PRIMITIVES 1
+#endif // Q3DStudio_USE_SYNC_PRIMITIVES
diff --git a/src/system/Qt3DSCubicRoots.cpp b/src/system/Qt3DSCubicRoots.cpp
new file mode 100644
index 0000000..ebcc54b
--- /dev/null
+++ b/src/system/Qt3DSCubicRoots.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSCubicRoots.h"
+#include "Qt3DSDataLogger.h"
+#include "Qt3DSCubicRootsImpl.h"
diff --git a/src/system/Qt3DSCubicRoots.h b/src/system/Qt3DSCubicRoots.h
new file mode 100644
index 0000000..b5ac053
--- /dev/null
+++ b/src/system/Qt3DSCubicRoots.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Wrapper class to functions that solve cubic equations.
+ *
+ * The function suite is taken from Graphics Gems:
+ * Roots3And4.c
+ *
+ * Utility functions to find cubic and quartic roots,
+ * coefficients are passed like this:
+ *
+ * c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0
+ *
+ * The functions return the number of non-complex roots and
+ * put the values into the s array.
+ *
+ * Author: Jochen Schwarze (schwarze@isa.de)
+ *
+ * Jan 26, 1990 Version for Graphics Gems
+ * Oct 11, 1990 Fixed sign problem for negative q's in SolveQuartic
+ * (reported by Mark Podlipec),
+ * Old-style function definitions,
+ * IsZero() as a macro
+ * Nov 23, 1990 Some systems do not declare acos() and cbrt() in
+ * <math.h>, though the functions exist in the library.
+ * If large coefficients are used, EQN_EPS should be
+ * reduced considerably (e.g. to 1E-30), results will be
+ * correct but multiple roots might be reported more
+ * than once.
+ */
+class CCubicRoots
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public:
+ static INT32 SolveQuadric(FLOAT inConstants[3], FLOAT outSolutions[2]);
+ static INT32 SolveCubic(FLOAT inConstants[4], FLOAT outSolutions[3]);
+ // static int SolveQuartic( FLOAT c[5], FLOAT s[4] );
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSCubicRootsImpl.h b/src/system/Qt3DSCubicRootsImpl.h
new file mode 100644
index 0000000..8cca59f
--- /dev/null
+++ b/src/system/Qt3DSCubicRootsImpl.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants used by the functions
+//==============================================================================
+const FLOAT M_PHI = 3.14159265358979323846f;
+
+/* epsilon surrounding for near zero values */
+const FLOAT EQN_EPS = 1e-9f;
+
+#define ISZERO(x) ((x) > -EQN_EPS && (x) < EQN_EPS)
+
+// cube-root
+#ifndef CUBEROOT
+#define CUBEROOT(x) \
+ ((x) > 0.0 ? static_cast<FLOAT>(pow((x), 1.0f / 3.0f)) \
+ : ((x) < 0.0 ? -static_cast<FLOAT>(pow(-(x), 1.0f / 3.0f)) : 0.0f))
+#endif
+
+//==============================================================================
+/**
+ * Find the root/s to a quadratic equation.
+ *
+ * The equation is of the form: c[2]*x^2 + c[1]*x + c[0] = 0
+ * Note that this will fail if c[2] is zero, or this is a linear equation.
+ *
+ * @param inConstants The array of constants to the equation; see form above
+ * @param outSolutions The array of solutions to the equation
+ * @return the number of solutions for the equation
+ */
+INT32 CCubicRoots::SolveQuadric(FLOAT inConstants[3], FLOAT outSolutions[2])
+{
+#ifdef _PERF_LOG
+ PerfLogMathEvent1 thePerfLog(DATALOGGER_CUBICROOT);
+#endif
+ FLOAT theP, theQ, theD;
+ INT32 theResult = 0;
+
+ /* normal form: x^2 + px + theQ = 0 */
+
+ theP = inConstants[1] / (2 * inConstants[2]);
+ theQ = inConstants[0] / inConstants[2];
+
+ theD = theP * theP - theQ;
+
+ if (ISZERO(theD)) {
+ outSolutions[0] = -theP;
+ theResult = 1;
+ } else if (theD < 0.0f) {
+ theResult = 0;
+ } else if (theD > 0.0f) {
+ FLOAT theSquareRootD = sqrtf(theD);
+
+ outSolutions[0] = theSquareRootD - theP;
+ outSolutions[1] = -theSquareRootD - theP;
+ theResult = 2;
+ }
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Find the root/s to a cubic equation.
+ *
+ * The equation is of the form: c[3]*x^3 + c[2]*x^2 + c[1]*x + c[0] = 0
+ * Note that this will fail if c[3] is zero, or this is a quadratic equation.
+ *
+ * @param inConstants The array of constants to the equation; see form above
+ * @param outSolutions The array of solutions to the equation
+ * @return the number of solutions for the equation
+ */
+INT32 CCubicRoots::SolveCubic(FLOAT inConstants[4], FLOAT outSolutions[3])
+{
+#ifdef _PERF_LOG
+ PerfLogMathEvent1 thePerfLog(DATALOGGER_CUBICROOT);
+#endif
+
+ INT32 theResult;
+ FLOAT theSubstitute;
+ FLOAT theVariableA, theVariableB, theVariableC;
+ FLOAT theASquared, theVariableP, theVariableQ;
+ FLOAT thePCubed, theVariableD;
+
+ /* normal form: x^3 + Ax^2 + Bx + C = 0 */
+
+ theVariableA = inConstants[2] / inConstants[3];
+ theVariableB = inConstants[1] / inConstants[3];
+ theVariableC = inConstants[0] / inConstants[3];
+
+ /* substitute x = y - A/3 to eliminate quadric term:
+ x^3 +px + q = 0 */
+
+ theASquared = theVariableA * theVariableA;
+ theVariableP = 1.0f / 3.0f * (-1.0f / 3.0f * theASquared + theVariableB);
+ theVariableQ = 1.0f / 2.0f * (2.0f / 27.0f * theVariableA * theASquared
+ - 1.0f / 3.0f * theVariableA * theVariableB + theVariableC);
+
+ /* use Cardano's formula */
+
+ thePCubed = theVariableP * theVariableP * theVariableP;
+ theVariableD = theVariableQ * theVariableQ + thePCubed;
+
+ if (ISZERO(theVariableD)) {
+ if (ISZERO(theVariableQ)) /* one triple solution */
+ {
+ outSolutions[0] = 0;
+ theResult = 1;
+ } else /* one single and one double solution */
+ {
+ FLOAT theVariableU = CUBEROOT(-theVariableQ);
+ outSolutions[0] = 2.0f * theVariableU;
+ outSolutions[1] = -theVariableU;
+ theResult = 2;
+ }
+ } else if (theVariableD < 0.0f) /* Casus irreducibilis: three real solutions */
+ {
+ FLOAT thePhi = 1.0f / 3.0f * static_cast<FLOAT>(acos(-theVariableQ / sqrtf(-thePCubed)));
+ FLOAT theVariableT = 2.0f * sqrtf(-theVariableP);
+
+ outSolutions[0] = theVariableT * static_cast<FLOAT>(cos(thePhi));
+ outSolutions[1] = -theVariableT * static_cast<FLOAT>(cos(thePhi + M_PHI / 3.0f));
+ outSolutions[2] = -theVariableT * static_cast<FLOAT>(cos(thePhi - M_PHI / 3.0f));
+ theResult = 3;
+ } else /* one real solution */
+ {
+ FLOAT theSquareRootD = sqrtf(theVariableD);
+ FLOAT theVariableU = CUBEROOT(theSquareRootD - theVariableQ);
+ FLOAT theVariableV = -CUBEROOT(theSquareRootD + theVariableQ);
+
+ outSolutions[0] = theVariableU + theVariableV;
+ theResult = 1;
+ }
+
+ /* resubstitute */
+ theSubstitute = 1.0f / 3.0f * theVariableA;
+
+ for (INT32 theIndex = 0; theIndex < theResult; ++theIndex)
+ outSolutions[theIndex] -= theSubstitute;
+
+ return theResult;
+}
+
+}; // namespace Q3DStudio
diff --git a/src/system/Qt3DSDLLManager.cpp b/src/system/Qt3DSDLLManager.cpp
new file mode 100644
index 0000000..c6f6d80
--- /dev/null
+++ b/src/system/Qt3DSDLLManager.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+#include "Qt3DSDLLManager.h"
+#include "Qt3DSBasicPluginDLL.h"
+#include <QDebug>
+#ifdef _LINUXPLATFORM
+#include <dlfcn.h>
+#endif
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+ * Comparator for DLL instances.
+ * Compares by plugin type and handle
+ */
+namespace Q3DStudio {
+bool operator==(const _SDLLInfo &inInfo1, const _SDLLInfo &inInfo2)
+{
+ return (inInfo1.m_Type == inInfo2.m_Type) && (inInfo1.m_Handle == inInfo2.m_Handle);
+}
+}
+
+//==============================================================================
+/**
+ * Singleton getter
+ */
+CDLLManager &CDLLManager::GetDLLManager()
+{
+ static CDLLManager theDLLManager = CDLLManager();
+ return theDLLManager;
+}
+
+//==============================================================================
+/**
+ * CTOR
+ */
+CDLLManager::CDLLManager()
+{
+}
+
+//==============================================================================
+/**
+ * DTOR
+ */
+CDLLManager::~CDLLManager()
+{
+}
+
+//==============================================================================
+/**
+ * Cleanup
+ */
+void CDLLManager::Cleanup()
+{
+ m_LoadedLibraries.Clear(true);
+}
+
+//==============================================================================
+/**
+ * Loads a DLL/shared library given a path to the library plugin and the plugin
+ * type to expect.
+ */
+long CDLLManager::LoadLibrary(const char *inLibraryPath, long inPluginType)
+{
+ long theEmptyIndex = NVARRAY_NOTFOUND;
+#ifdef _PCPLATFORM
+ DLLHANDLE theHandle = ::LoadLibraryA(inLibraryPath);
+#endif
+
+#ifdef _LINUXPLATFORM
+ DLLHANDLE theHandle = ::dlopen(inLibraryPath, RTLD_NOW);
+
+ if (!theHandle) {
+ const char *error = ::dlerror();
+ qWarning() << "Failed to load shared library, error:" << QStringLiteral("%1, full path: %2").arg(error).arg(inLibraryPath);
+ }
+
+#endif
+
+#ifdef _INTEGRITYPLATFORM
+ DLLHANDLE theHandle = 0;
+ qWarning() << "CDLLManager::LoadLibrary handle is zero!";
+#endif
+
+ Q3DStudio_ASSERT(theHandle);
+
+ if (theHandle != NULL) {
+ SDLLInfo theInfo;
+ PROC_GetPluginType theProc =
+ reinterpret_cast<PROC_GetPluginType>(GetProc("GetPluginType", theHandle));
+ Q3DStudio_ASSERT(theProc);
+
+ if (theProc) {
+ theInfo.m_Type = theProc();
+
+ if (theInfo.m_Type == inPluginType) {
+ theEmptyIndex = m_LoadedLibraries.GetIndex(theInfo);
+ theInfo.m_Handle = theHandle;
+
+ if (theEmptyIndex == NVARRAY_NOTFOUND) {
+ m_LoadedLibraries.Push(theInfo);
+ theEmptyIndex = m_LoadedLibraries.GetCount() - 1;
+ } else
+ m_LoadedLibraries[theEmptyIndex] = theInfo;
+ }
+ }
+
+ if (theEmptyIndex == NVARRAY_NOTFOUND) {
+#ifdef _PCPLATFORM
+ ::FreeLibrary(theHandle);
+#endif
+
+#ifdef _LINUXPLATFORM
+ ::dlclose(theHandle);
+#endif
+ }
+ }
+
+ return theEmptyIndex;
+}
+
+//==============================================================================
+/**
+ * Unloads a DLL given a handle
+ */
+void CDLLManager::UnloadLibrary(const long inHandle)
+{
+ if (inHandle >= 0 && inHandle < m_LoadedLibraries.GetCount()) {
+#ifdef _PCPLATFORM
+ ::FreeLibrary(m_LoadedLibraries[inHandle].m_Handle);
+#endif
+
+#ifdef _LINUXPLATFORM
+ ::dlclose(m_LoadedLibraries[inHandle].m_Handle);
+#endif
+
+ m_LoadedLibraries[inHandle] = SDLLInfo();
+ }
+}
+
+//==============================================================================
+/**
+ * Retrieves a DLL proc given the proc name
+ */
+void *CDLLManager::GetProc(const char *inProcName, long inHandle)
+{
+ if (inHandle >= 0 && inHandle < m_LoadedLibraries.GetCount())
+ return GetProc(inProcName, m_LoadedLibraries[inHandle].m_Handle);
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+ * Retrieves a DLL proc fiven the proc name
+ */
+void *CDLLManager::GetProc(const char *inProcName, const DLLHANDLE inHandle)
+{
+#ifdef _PCPLATFORM
+#ifdef QT3DS_VC
+ return ::GetProcAddress(inHandle, inProcName);
+#else
+ return (void *)(::GetProcAddress(inHandle, inProcName));
+#endif
+#endif
+
+#ifdef _LINUXPLATFORM
+ return ::dlsym(inHandle, inProcName);
+#endif
+
+#ifdef _INTEGRITYPLATFORM
+ qWarning() << "CDLLManager::GetProc returns NULL!";
+ return NULL;
+#endif
+}
+
+//==============================================================================
+/**
+ * Retrieves the plugin type for the DLL
+ */
+template <typename EEnumType>
+EEnumType CDLLManager::GetPluginType(long inHandle)
+{
+ if (inHandle >= 0 && inHandle < m_LoadedLibraries.GetCount())
+ return static_cast<EEnumType>(m_LoadedLibraries[inHandle].m_Type);
+
+ return 0;
+}
diff --git a/src/system/Qt3DSDLLManager.h b/src/system/Qt3DSDLLManager.h
new file mode 100644
index 0000000..d670af2
--- /dev/null
+++ b/src/system/Qt3DSDLLManager.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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
+
+#ifdef _PCPLATFORM
+#pragma warning(push, 3)
+#include <windows.h>
+#pragma warning(pop)
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+#ifdef _PCPLATFORM
+typedef HMODULE DLLHANDLE;
+#endif
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+typedef void *DLLHANDLE;
+#endif
+
+typedef struct _SDLLInfo
+{
+ long m_Type; ///< Plugin type
+ DLLHANDLE m_Handle; ///< DLL handle
+
+ _SDLLInfo()
+ : m_Type(0)
+ , m_Handle(NULL)
+
+ {
+ }
+
+} SDLLInfo;
+
+//==============================================================================
+/**
+ * Loads DLLs and queries for DLL functions
+ */
+class CDLLManager
+{
+public:
+ static CDLLManager &GetDLLManager();
+
+protected:
+ CDLLManager();
+ virtual ~CDLLManager();
+
+public:
+ long LoadLibrary(const char *inLibraryPath, long inPluginType);
+ void UnloadLibrary(const long inHandle);
+ void *GetProc(const char *inProcName, long inHandle);
+ template <typename EEnumType>
+ EEnumType GetPluginType(long inHandle);
+ void Cleanup();
+
+protected:
+ void *GetProc(const char *inProcName, const DLLHANDLE inHandle);
+
+protected:
+ CArray<Q3DStudio::SDLLInfo> m_LoadedLibraries;
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSDataLogger.cpp b/src/system/Qt3DSDataLogger.cpp
new file mode 100644
index 0000000..2f45f01
--- /dev/null
+++ b/src/system/Qt3DSDataLogger.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSDataLogger.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+CDataLogger::SExternalFunctors CDataLogger::m_Functors;
+CDataLogger::EDataLoggerLevel CDataLogger::m_LogLevel = CDataLogger::LOG_LEVEL_INVALID;
+BOOL CDataLogger::m_Enabled = false;
+
+// Developers - change out the = NULL to = class::LogEntry to log specific stuff.
+template <>
+TPerfLogGeneralEvent1::TLogEntryInternal TPerfLogGeneralEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogGeneralEvent2::TLogEntryInternal TPerfLogGeneralEvent2::m_InternalLogFunc = NULL;
+
+template <>
+TPerfLogRenderEvent1::TLogEntryInternal TPerfLogRenderEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogSceneEvent1::TLogEntryInternal TPerfLogSceneEvent1::m_InternalLogFunc = NULL;
+
+template <>
+TPerfLogMathEvent1::TLogEntryInternal TPerfLogMathEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogPresentationEvent1::TLogEntryInternal TPerfLogPresentationEvent1::m_InternalLogFunc = NULL;
+template <>
+TPerfLogRenderEvent2::TLogEntryInternal TPerfLogRenderEvent2::m_InternalLogFunc = NULL;
+
+//==============================================================================
+/**
+ * Set the application supplied functors to use for getting time and handling
+ * the writing out of data
+ */
+void CDataLogger::SetFunctors(SExternalFunctors inFunctors)
+{
+ m_Functors = inFunctors;
+}
+
+//==============================================================================
+/**
+* Call into the specified functors to make stuff happen
+*/
+void CDataLogger::LogEntry(UINT32 inEntryEnum, BOOL inStartFlag)
+{
+ if (m_Enabled && m_Functors.m_GetTimeFunc && m_Functors.m_WriteFunc && m_Functors.m_UserData) {
+ // Initialize to the correct values
+ SPerfLogEntry theEntry(inEntryEnum, inStartFlag,
+ m_Functors.m_GetTimeFunc(m_Functors.m_UserData));
+ m_Functors.m_WriteFunc(m_Functors.m_UserData, theEntry);
+ }
+}
+
+//==============================================================================
+/**
+* Enable logging
+*/
+void CDataLogger::Enable()
+{
+ SetLogLevel(m_LogLevel);
+ m_Enabled = true;
+}
+
+//==============================================================================
+/**
+* Disable logging
+*/
+void CDataLogger::Disable()
+{
+ m_Enabled = false;
+}
+
+//==============================================================================
+/**
+ * XXX
+ */
+void CDataLogger::SetLogLevel(EDataLoggerLevel inLogLevel)
+{
+ switch (inLogLevel) {
+ // No logging
+ case LOG_LEVEL_NONE:
+ TPerfLogGeneralEvent1::Disable();
+ TPerfLogGeneralEvent2::Disable();
+
+ TPerfLogRenderEvent1::Disable();
+ TPerfLogSceneEvent1::Disable();
+
+ TPerfLogMathEvent1::Disable();
+ TPerfLogPresentationEvent1::Disable();
+ TPerfLogRenderEvent2::Disable();
+ break;
+
+ case LOG_LEVEL_3:
+ TPerfLogMathEvent1::Enable();
+ TPerfLogPresentationEvent1::Enable();
+ TPerfLogRenderEvent2::Enable();
+
+ case LOG_LEVEL_2:
+ TPerfLogRenderEvent1::Enable();
+ TPerfLogSceneEvent1::Enable();
+
+ case LOG_LEVEL_1:
+ TPerfLogGeneralEvent1::Enable();
+ TPerfLogGeneralEvent2::Enable();
+ break;
+
+ case LOG_LEVEL_INVALID:
+ default:
+ m_LogLevel = LOG_LEVEL_INVALID;
+ return;
+ break;
+ }
+ m_LogLevel = inLogLevel;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSDataLogger.h b/src/system/Qt3DSDataLogger.h
new file mode 100644
index 0000000..b834eda
--- /dev/null
+++ b/src/system/Qt3DSDataLogger.h
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** 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 _DATA_LOGGER_H_
+#define _DATA_LOGGER_H_
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSTypes.h"
+#include "Qt3DSDataLoggerEnums.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+typedef TTimeUnit TDataLoggerTimeUnit;
+
+//==============================================================================
+/**
+* The structure that holds all the info we collect
+*/
+struct SPerfLogEntry
+{
+ UINT32 m_EntryEnum : 31;
+ UINT32 m_StartBool : 1;
+
+ TDataLoggerTimeUnit m_Time;
+
+ SPerfLogEntry(UINT32 inEntryEnum, BOOL inStartFlag, TDataLoggerTimeUnit inTime)
+ : m_EntryEnum(inEntryEnum)
+ , m_StartBool(inStartFlag ? 1U : 0U)
+ , m_Time(inTime)
+ {
+ // Make sure our enums never use the high bit
+ Q3DStudio_ASSERT(false == (inEntryEnum & (1 << 31)));
+ }
+};
+
+//==============================================================================
+/**
+* The stack based helper class that wraps the actually logging of start and end messages
+* for use with start/end time logging.
+*/
+template <typename T>
+class CPerfLogPairedEventWrapper
+{
+public:
+ typedef void (*TLogEntryInternal)(UINT32 inEntryEnum, BOOL inStartFlag);
+
+private:
+ UINT32 m_EntryEnum;
+ static TLogEntryInternal m_InternalLogFunc;
+
+private:
+ static void LogEntry(UINT32 inEntryEnum, BOOL inStartFlag);
+
+public:
+ CPerfLogPairedEventWrapper(UINT32 inEntryEnum);
+ ~CPerfLogPairedEventWrapper();
+
+ static void Enable();
+ static void Disable();
+};
+
+//==============================================================================
+/**
+*/
+class CPerfLogPairedEventWrapperDummy
+{
+public:
+ CPerfLogPairedEventWrapperDummy(UINT32 /*inEntryEnum*/) {}
+ ~CPerfLogPairedEventWrapperDummy() {}
+};
+
+// Dummy structs, so we get one 'type' of class per log event
+// so we can turn things on and off
+struct SPerfLogGeneralEvent1
+{
+};
+struct SPerfLogGeneralEvent2
+{
+};
+
+struct SPerfLogRenderEvent1
+{
+};
+struct SPerfLogSceneEvent1
+{
+};
+
+struct SPerfLogMathEvent1
+{
+};
+struct SPerfLogPresentationEvent1
+{
+};
+struct SPerfLogRenderEvent2
+{
+};
+
+// level 0
+// no profiling at all...
+
+// level 1
+typedef CPerfLogPairedEventWrapper<SPerfLogGeneralEvent1>
+ TPerfLogGeneralEvent1; // Frame, update presentations, update scene, render scene
+typedef CPerfLogPairedEventWrapper<SPerfLogGeneralEvent2>
+ TPerfLogGeneralEvent2; // Event processing and manager updates,
+// call frame and slide callbacks,
+// opaque, transparent, layer render, finalize drawlist and pick
+// level 2
+typedef CPerfLogPairedEventWrapper<SPerfLogRenderEvent1>
+ TPerfLogRenderEvent1; // More detailed rendering
+typedef CPerfLogPairedEventWrapper<SPerfLogSceneEvent1>
+ TPerfLogSceneEvent1; // More detailed scene update
+
+// level 3
+typedef CPerfLogPairedEventWrapper<SPerfLogMathEvent1> TPerfLogMathEvent1; // vector and matrix math
+typedef CPerfLogPairedEventWrapper<SPerfLogPresentationEvent1>
+ TPerfLogPresentationEvent1; // More detailed scene update
+typedef CPerfLogPairedEventWrapper<SPerfLogRenderEvent2> TPerfLogRenderEvent2; //
+
+// Defines
+#ifdef _PERF_LOG
+#define PerfLogGeneralEvent1(inEventID) TPerfLogGeneralEvent1 thePerfLog(inEventID);
+#define PerfLogGeneralEvent2(inEventID) TPerfLogGeneralEvent2 thePerfLog(inEventID);
+
+#define PerfLogRenderEvent1(inEventID) TPerfLogRenderEvent1 thePerfLog(inEventID);
+#define PerfLogSceneEvent1(inEventID) TPerfLogSceneEvent1 thePerfLog(inEventID);
+
+#define PerfLogMathEvent1(inEventID) TPerfLogMathEvent1 thePerfLog(inEventID);
+#define PerfLogPresentationEvent1(inEventID) TPerfLogPresentationEvent1 thePerfLog(inEventID);
+#define PerfLogRenderEvent2(inEventID) TPerfLogRenderEvent2 thePerfLog(inEventID);
+#else
+#define PerfLogGeneralEvent1(inEventID)
+#define PerfLogGeneralEvent2(inEventID)
+
+#define PerfLogRenderEvent1(inEventID)
+#define PerfLogSceneEvent1(inEventID)
+
+#define PerfLogMathEvent1(inEventID)
+#define PerfLogPresentationEvent1(inEventID)
+#define PerfLogRenderEvent2(inEventID)
+#endif
+
+//==============================================================================
+/**
+*/
+class CDataLogger
+{
+private:
+ // App level function to write this out to a stream/file... set externally
+ typedef void (*TDataLoggerWriteFunc)(void *inUserData, SPerfLogEntry inEntry);
+ typedef TDataLoggerTimeUnit (*TGetTimeFunc)(void *inUserData);
+
+public:
+ struct SExternalFunctors
+ {
+ void *m_UserData;
+ TDataLoggerWriteFunc m_WriteFunc;
+ TGetTimeFunc m_GetTimeFunc;
+
+ SExternalFunctors()
+ : m_UserData(NULL)
+ , m_WriteFunc(NULL)
+ , m_GetTimeFunc(NULL)
+ {
+ }
+ };
+
+ enum EDataLoggerLevel {
+ LOG_LEVEL_NONE,
+ LOG_LEVEL_1,
+ LOG_LEVEL_2,
+ LOG_LEVEL_3,
+ LOG_LEVEL_INVALID, // use this if you want to selectively enable or disable loggers
+ };
+
+private:
+ static SExternalFunctors m_Functors;
+ static EDataLoggerLevel m_LogLevel;
+ static BOOL m_Enabled;
+
+public:
+ static void SetFunctors(SExternalFunctors inFunctors);
+ static void LogEntry(UINT32 inEntryEnum, BOOL inStartFlag);
+ static void Enable();
+ static void Disable();
+
+ static void SetLogLevel(EDataLoggerLevel inLogLevel);
+};
+
+} // namespace Q3DStudio
+
+#include "Qt3DSDataLogger.hpp"
+
+#endif // _DATA_LOGGER_H_
diff --git a/src/system/Qt3DSDataLogger.hpp b/src/system/Qt3DSDataLogger.hpp
new file mode 100644
index 0000000..0900c4a
--- /dev/null
+++ b/src/system/Qt3DSDataLogger.hpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSDataLogger.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* Constructor
+*/
+template <typename T>
+CPerfLogPairedEventWrapper<T>::CPerfLogPairedEventWrapper(UINT32 inEntryEnum)
+ : m_EntryEnum(inEntryEnum)
+{
+ if (m_InternalLogFunc)
+ m_InternalLogFunc(m_EntryEnum, true);
+}
+
+//==============================================================================
+/**
+* Destructor
+*/
+template <typename T>
+CPerfLogPairedEventWrapper<T>::~CPerfLogPairedEventWrapper()
+{
+ if (m_InternalLogFunc)
+ m_InternalLogFunc(m_EntryEnum, false);
+}
+
+//==============================================================================
+/**
+* Logger functions
+*/
+template <typename T>
+void CPerfLogPairedEventWrapper<T>::LogEntry(UINT32 inEntryEnum, BOOL inStartFlag)
+{
+ CDataLogger::LogEntry(inEntryEnum, inStartFlag);
+}
+
+//==============================================================================
+/**
+ * Enable logging
+ */
+template <typename T>
+void CPerfLogPairedEventWrapper<T>::Enable()
+{
+ m_InternalLogFunc = LogEntry;
+}
+
+//==============================================================================
+/**
+* Disable logging
+*/
+template <typename T>
+void CPerfLogPairedEventWrapper<T>::Disable()
+{
+ m_InternalLogFunc = NULL;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSDataLoggerEnums.h b/src/system/Qt3DSDataLoggerEnums.h
new file mode 100644
index 0000000..27320e1
--- /dev/null
+++ b/src/system/Qt3DSDataLoggerEnums.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** 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 _DATA_LOGGER_ENUMS_H_
+#define _DATA_LOGGER_ENUMS_H_
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+// TODO ah - for now, these are all specific to paired events. Later we will
+// extend this to support single events which may or may not have timestamps
+// for example, every matrix multiple would log a single event with no time
+enum EDataLoggerEvents {
+ //
+ DATALOGGER_FRAME, /// Time spent in a application frame ( UpdatePresentations, UpdateScenes, and
+ /// Render )
+
+ // DATALOGGER_FRAME
+ // CRuntime
+ DATALOGGER_UPDATEPRESENTATIONS, /// Time spent updating all presentations
+ DATALOGGER_UPDATESCENES, /// Time spent updating all scenes
+ DATALOGGER_RENDERSCENES, /// Time spent rendering all scenes
+
+ // DATALOGGER_UPDATEPRESENTATIONS
+ // CPresentation::Update
+ DATALOGGER_PROCESSEVENTS, /// Time spent in ProcessEventCommandQueue
+ DATALOGGER_ELEMENTMANAGERUPDATE, /// Time spent in CElementManager::Update doing activate and
+ /// deactivate scans
+ DATALOGGER_ANIMATIONMANAGERUPDATE, /// Time spent in CAnimationManager::Update
+
+ // More detailed presentation update
+ DATALOGGER_PROCESSCOMMAND, /// xxx
+ DATALOGGER_PROCESSEVENT, /// xxx
+ DATALOGGER_PROCESSEVENTBUBBLING, /// xxx
+
+ // DATALOGGER_UPDATESCENES
+ // CScene::Update
+ DATALOGGER_PROCESSDIRTYLIST, /// Time spent in CScene::ProcessDirtyList
+ DATALOGGER_CALCULATETRANSFORM, /// Time spent in CScene::CalculateGlobalTransform
+ DATALOGGER_SCENEUPDATE, /// Time spent in CScene::Update recursion
+
+ // More detailed scene update
+ DATALOGGER_SCANNODEATTRIBUTES, /// Time
+ DATALOGGER_PUSHNODE, /// Time
+
+ // DATALOGGER_RENDERSCENES
+ // CRenderEngine
+ DATALOGGER_RENDERLAYER, /// Time spent rendering the contents of a layer
+ DATALOGGER_RENDEROPAQUE, /// Time spent rendering all opaque items
+ DATALOGGER_RENDERTRANSPARENT, /// Time spent rendering all transparent items
+ DATALOGGER_FINALIZEDRAWLIST, /// Time spent finalizing the draw list
+ DATALOGGER_PICK, /// Time spent in pick code
+
+ // More detailed rendering
+ DATALOGGER_RENDER_SORTDISTANCE, /// asdf
+ DATALOGGER_RENDER_SETOPACITY, /// asdf
+ DATALOGGER_RENDER_DRAWMODEL, /// asdf
+ DATALOGGER_RENDER_DRAWTEXT, /// asdf
+ DATALOGGER_RENDER_CLEARBUFFER, /// asdf
+ DATALOGGER_RENDER_ZWRITEENABLE, /// asdf
+ DATALOGGER_RENDER_CHECKRESIZE, /// asdf
+ DATALOGGER_RENDER_SETATTRIBUTES, /// asdf
+ DATALOGGER_RENDER_TEXTUPDATE, /// asdf
+ DATALOGGER_RENDER_CAMERAUPDATE, /// asdf
+
+ // super specific low level gl calls
+ DATALOGGER_TEXTURESTATE_APPLY, /// asdf
+ DATALOGGER_GEOMETRY_DRAW, /// asdf
+ DATALOGGER_MATERIAL_APPLY, /// asdf
+ DATALOGGER_SETSHADER, /// asdf
+
+ // vector math
+ DATALOGGER_VECTOR, /// asdf
+ DATALOGGER_MATRIX, /// asdf
+ DATALOGGER_CUBICROOT, /// asdf
+
+ //
+ DATALOGGER_COUNTERTEST, /// Time spent in counter test code
+ DATALOGGER_COUNTERTESTX, /// Time spent in counter test code
+
+ DATALOGGEREVENTCOUNT /// Event count
+};
+
+// CPerfLogPairedEventWrapperx thePerfLog( xxx );
+
+} // namespace Q3DStudio
+
+#endif // _DATA_LOGGER_ENUMS_H_
diff --git a/src/system/Qt3DSDataLoggerViewer.h b/src/system/Qt3DSDataLoggerViewer.h
new file mode 100644
index 0000000..0eaf9f6
--- /dev/null
+++ b/src/system/Qt3DSDataLoggerViewer.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 AKDATALOGGERVIEWER_H_INCLUDED
+#define AKDATALOGGERVIEWER_H_INCLUDED
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSTypes.h"
+#include "Qt3DSDataLogger.h"
+#include "Qt3DSDataLoggerEnums.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+// Helps interpret and analyse data logger entries
+class CDataLoggerViewer
+{
+public:
+ typedef CArray<SPerfLogEntry> TPerfLogEntryList;
+
+public:
+ CDataLoggerViewer(TPerfLogEntryList *inPerfLogEntryList);
+ CDataLoggerViewer(const char *inFilename);
+ virtual ~CDataLoggerViewer();
+
+public:
+ float GetAverageTimeInMsForEntry(enum EDataLoggerEvents inEventType);
+ void ResetPerfLogEntry(enum EDataLoggerEvents inEventType);
+ void ResetAllEntries();
+
+public:
+ static bool ProcessKeyEvent(char inKey, TPerfLogEntryList *inList);
+
+protected:
+ TPerfLogEntryList *m_PerfLogEntryList;
+ bool m_Dispose;
+};
+
+} // namespace NVUI
+
+#endif // AKDATALOGGERVIEWER_H_INCLUDED
diff --git a/src/system/Qt3DSEGLTimer.h b/src/system/Qt3DSEGLTimer.h
new file mode 100644
index 0000000..4c9f4ce
--- /dev/null
+++ b/src/system/Qt3DSEGLTimer.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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 "Qt3DSTimer.h"
+#include "Qt3DSTypes.h"
+
+// You have to include egl before including this file.
+
+typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)(void);
+typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void);
+extern EGLuint64NV eglSystemTimeFrequency;
+extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNVProc;
+extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNVProc;
+
+namespace Q3DStudio {
+
+struct SEGLTimeProvider : public Q3DStudio::ITimeProvider
+{
+public:
+ Q3DStudio::INT64 m_TimeFrequency;
+ SEGLTimeProvider()
+ : m_TimeFrequency(0)
+ {
+ }
+ virtual Q3DStudio::INT64 GetCurrentTimeMicroSeconds()
+ {
+ // This can be called before EGL is initialized.
+ if (eglGetSystemTimeFrequencyNVProc == NULL || eglGetSystemTimeNVProc == NULL)
+ return 0;
+
+ if (!m_TimeFrequency) {
+ // Time frequency converts to seconds.
+ m_TimeFrequency = eglGetSystemTimeFrequencyNVProc();
+ // We need it to conver to microseconds
+ m_TimeFrequency = m_TimeFrequency / 1000000ULL;
+ }
+ Q3DStudio::INT64 currentTime = eglGetSystemTimeNVProc();
+ currentTime = currentTime / m_TimeFrequency;
+ return currentTime;
+ }
+};
+} \ No newline at end of file
diff --git a/src/system/Qt3DSEndian.h b/src/system/Qt3DSEndian.h
new file mode 100644
index 0000000..f8913a7
--- /dev/null
+++ b/src/system/Qt3DSEndian.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2010 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
+
+//==============================================================================
+// Constants
+//==============================================================================
+
+#define QT3DS_LITTLE_ENDIAN false
+#define QT3DS_BIG_ENDIAN true
diff --git a/src/system/Qt3DSEulerAngles.cpp b/src/system/Qt3DSEulerAngles.cpp
new file mode 100644
index 0000000..7c4364f
--- /dev/null
+++ b/src/system/Qt3DSEulerAngles.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include "Qt3DSEulerAngles.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4365) // warnings on conversion from unsigned int to int
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CEulerAngleConverter::CEulerAngleConverter()
+{
+ m_OrderInfoBuffer[0] = '\0';
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CEulerAngleConverter::~CEulerAngleConverter()
+{
+}
+
+//==============================================================================
+/**
+ * Constructs a Euler angle & holds it in a EulerAngles struct
+ * @param theI x rotation ( radians )
+ * @param theJ y rotation ( radians )
+ * @param theH z rotation ( radians )
+ * @param theOrder the order this angle is in namely XYZ( static ), etc.
+ * use the EulOrd**** macros to generate values
+ * 0 to 23 is valid
+ * @return the euler angle
+ */
+EulerAngles CEulerAngleConverter::Eul_(float theI, float theJ, float theH, int theOrder)
+{
+ EulerAngles theEulerAngle;
+ theEulerAngle.x = theI;
+ theEulerAngle.y = theJ;
+ theEulerAngle.z = theH;
+ theEulerAngle.w = (float)theOrder;
+ return theEulerAngle;
+}
+
+//==============================================================================
+/**
+ * Construct quaternion from Euler angles (in radians).
+ * @param theEulerAngle incoming angle( radians )
+ * @return the Quaternion
+ */
+Quat CEulerAngleConverter::Eul_ToQuat(EulerAngles theEulerAngle)
+{
+ Quat theQuaternion;
+ double a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+
+ EulGetOrd((unsigned int)theEulerAngle.w, i, j, k, h, n, s, f);
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+
+ if (n == EulParOdd)
+ theEulerAngle.y = -theEulerAngle.y;
+
+ ti = theEulerAngle.x * 0.5;
+ tj = theEulerAngle.y * 0.5;
+ th = theEulerAngle.z * 0.5;
+
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+
+ if (s == EulRepYes) {
+ a[i] = cj * (cs + sc); /* Could speed up with */
+ a[j] = sj * (cc + ss); /* trig identities. */
+ a[k] = sj * (cs - sc);
+ theQuaternion.w = (float)(cj * (cc - ss));
+ } else {
+ a[i] = cj * sc - sj * cs;
+ a[j] = cj * ss + sj * cc;
+ a[k] = cj * cs - sj * sc;
+ theQuaternion.w = (float)(cj * cc + sj * ss);
+ }
+ if (n == EulParOdd)
+ a[j] = -a[j];
+
+ theQuaternion.x = (float)a[X];
+ theQuaternion.y = (float)a[Y];
+ theQuaternion.z = (float)a[Z];
+ return theQuaternion;
+}
+
+//==============================================================================
+/**
+ * Construct matrix from Euler angles (in radians).
+ * @param theEulerAngle incoming angle
+ * @param theMatrix outgoing matrix
+ */
+void CEulerAngleConverter::Eul_ToHMatrix(EulerAngles theEulerAngle, HMatrix theMatrix)
+{
+ double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
+ int i, j, k, h, n, s, f;
+ EulGetOrd((unsigned int)theEulerAngle.w, i, j, k, h, n, s, f);
+
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+
+ if (n == EulParOdd) {
+ theEulerAngle.x = -theEulerAngle.x;
+ theEulerAngle.y = -theEulerAngle.y;
+ theEulerAngle.z = -theEulerAngle.z;
+ }
+
+ ti = theEulerAngle.x;
+ tj = theEulerAngle.y;
+ th = theEulerAngle.z;
+
+ ci = cos(ti);
+ cj = cos(tj);
+ ch = cos(th);
+
+ si = sin(ti);
+ sj = sin(tj);
+ sh = sin(th);
+
+ cc = ci * ch;
+ cs = ci * sh;
+ sc = si * ch;
+ ss = si * sh;
+
+ if (s == EulRepYes) {
+ theMatrix[i][i] = (float)cj;
+ theMatrix[i][j] = (float)(sj * si);
+ theMatrix[i][k] = (float)(sj * ci);
+ theMatrix[j][i] = (float)(sj * sh);
+ theMatrix[j][j] = (float)(-cj * ss + cc);
+ theMatrix[j][k] = (float)(-cj * cs - sc);
+ theMatrix[k][i] = (float)(-sj * ch);
+ theMatrix[k][j] = (float)(cj * sc + cs);
+ theMatrix[k][k] = (float)(cj * cc - ss);
+ } else {
+ theMatrix[i][i] = (float)(cj * ch);
+ theMatrix[i][j] = (float)(sj * sc - cs);
+ theMatrix[i][k] = (float)(sj * cc + ss);
+ theMatrix[j][i] = (float)(cj * sh);
+ theMatrix[j][j] = (float)(sj * ss + cc);
+ theMatrix[j][k] = (float)(sj * cs - sc);
+ theMatrix[k][i] = (float)(-sj);
+ theMatrix[k][j] = (float)(cj * si);
+ theMatrix[k][k] = (float)(cj * ci);
+ }
+
+ theMatrix[W][X] = 0.0;
+ theMatrix[W][Y] = 0.0;
+ theMatrix[W][Z] = 0.0;
+ theMatrix[X][W] = 0.0;
+ theMatrix[Y][W] = 0.0;
+ theMatrix[Z][W] = 0.0;
+ theMatrix[W][W] = 1.0;
+}
+
+//==============================================================================
+/**
+ * Convert matrix to Euler angles (in radians).
+ * @param theMatrix incoming matrix
+ * @param theOrder 0-23, use EulOrd**** to generate this value
+ * @return a set of angles in radians!!!!
+ */
+EulerAngles CEulerAngleConverter::Eul_FromHMatrix(HMatrix theMatrix, int theOrder)
+{
+ EulerAngles theEulerAngle;
+ int i, j, k, h, n, s, f;
+
+ EulGetOrd(theOrder, i, j, k, h, n, s, f);
+ if (s == EulRepYes) {
+ double sy = sqrt(theMatrix[i][j] * theMatrix[i][j] + theMatrix[i][k] * theMatrix[i][k]);
+ if (sy > 16 * FLT_EPSILON) {
+ theEulerAngle.x = (float)(atan2((double)theMatrix[i][j], (double)theMatrix[i][k]));
+ theEulerAngle.y = (float)(atan2((double)sy, (double)theMatrix[i][i]));
+ theEulerAngle.z = (float)(atan2((double)theMatrix[j][i], -(double)theMatrix[k][i]));
+ } else {
+ theEulerAngle.x = (float)(atan2(-(double)theMatrix[j][k], (double)theMatrix[j][j]));
+ theEulerAngle.y = (float)(atan2((double)sy, (double)theMatrix[i][i]));
+ theEulerAngle.z = 0;
+ }
+ } else {
+ double cy = sqrt(theMatrix[i][i] * theMatrix[i][i] + theMatrix[j][i] * theMatrix[j][i]);
+ if (cy > 16 * FLT_EPSILON) {
+ theEulerAngle.x = (float)(atan2((double)theMatrix[k][j], (double)theMatrix[k][k]));
+ theEulerAngle.y = (float)(atan2(-(double)theMatrix[k][i], (double)cy));
+ theEulerAngle.z = (float)(atan2((double)theMatrix[j][i], (double)theMatrix[i][i]));
+ } else {
+ theEulerAngle.x = (float)(atan2(-(double)theMatrix[j][k], (double)theMatrix[j][j]));
+ theEulerAngle.y = (float)(atan2(-(double)theMatrix[k][i], (double)cy));
+ theEulerAngle.z = 0;
+ }
+ }
+
+ if (n == EulParOdd) {
+ theEulerAngle.x = -theEulerAngle.x;
+ theEulerAngle.y = -theEulerAngle.y;
+ theEulerAngle.z = -theEulerAngle.z;
+ }
+
+ if (f == EulFrmR) {
+ float t = theEulerAngle.x;
+ theEulerAngle.x = theEulerAngle.z;
+ theEulerAngle.z = t;
+ }
+ theEulerAngle.w = (float)theOrder;
+ return theEulerAngle;
+}
+
+//==============================================================================
+/**
+ * Convert quaternion to Euler angles (in radians).
+ * @param theQuaternion incoming quaternion
+ * @param theOrder 0-23, use EulOrd**** to generate this value
+ * @return the generated angles ( radians )
+ */
+EulerAngles CEulerAngleConverter::Eul_FromQuat(Quat theQuaternion, int theOrder)
+{
+ HMatrix theMatrix;
+ double Nq = theQuaternion.x * theQuaternion.x + theQuaternion.y * theQuaternion.y
+ + theQuaternion.z * theQuaternion.z + theQuaternion.w * theQuaternion.w;
+ double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
+ double xs = theQuaternion.x * s;
+ double ys = theQuaternion.y * s;
+ double zs = theQuaternion.z * s;
+ double wx = theQuaternion.w * xs;
+ double wy = theQuaternion.w * ys;
+ double wz = theQuaternion.w * zs;
+ double xx = theQuaternion.x * xs;
+ double xy = theQuaternion.x * ys;
+ double xz = theQuaternion.x * zs;
+ double yy = theQuaternion.y * ys;
+ double yz = theQuaternion.y * zs;
+ double zz = theQuaternion.z * zs;
+
+ theMatrix[X][X] = (float)(1.0 - (yy + zz));
+ theMatrix[X][Y] = (float)(xy - wz);
+ theMatrix[X][Z] = (float)(xz + wy);
+ theMatrix[Y][X] = (float)(xy + wz);
+ theMatrix[Y][Y] = (float)(1.0 - (xx + zz));
+ theMatrix[Y][Z] = (float)(yz - wx);
+ theMatrix[Z][X] = (float)(xz - wy);
+ theMatrix[Z][Y] = (float)(yz + wx);
+ theMatrix[Z][Z] = (float)(1.0 - (xx + yy));
+ theMatrix[W][X] = 0.0;
+ theMatrix[W][Y] = 0.0;
+ theMatrix[W][Z] = 0.0;
+ theMatrix[X][W] = 0.0;
+ theMatrix[Y][W] = 0.0;
+ theMatrix[Z][W] = 0.0;
+ theMatrix[W][W] = 1.0;
+
+ return Eul_FromHMatrix(theMatrix, theOrder);
+}
+
+//==============================================================================
+/**
+ * Dump the Order information
+ */
+const char *CEulerAngleConverter::DumpOrderInfo()
+{
+ long theCount = 0;
+ long theOrder[24];
+ char theOrderStr[24][16];
+
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZs");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZXr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYZYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXYr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdYXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZXZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdXYZr");
+ ::strcpy(theOrderStr[theCount++], "EulOrdZYZr");
+
+ theCount = 0;
+ theOrder[theCount++] = EulOrdXYZs;
+ theOrder[theCount++] = EulOrdXYXs;
+ theOrder[theCount++] = EulOrdXZYs;
+ theOrder[theCount++] = EulOrdXZXs;
+ theOrder[theCount++] = EulOrdYZXs;
+ theOrder[theCount++] = EulOrdYZYs;
+ theOrder[theCount++] = EulOrdYXZs;
+ theOrder[theCount++] = EulOrdYXYs;
+ theOrder[theCount++] = EulOrdZXYs;
+ theOrder[theCount++] = EulOrdZXZs;
+ theOrder[theCount++] = EulOrdZYXs;
+ theOrder[theCount++] = EulOrdZYZs;
+
+ theOrder[theCount++] = EulOrdZYXr;
+ theOrder[theCount++] = EulOrdXYXr;
+ theOrder[theCount++] = EulOrdYZXr;
+ theOrder[theCount++] = EulOrdXZXr;
+ theOrder[theCount++] = EulOrdXZYr;
+ theOrder[theCount++] = EulOrdYZYr;
+ theOrder[theCount++] = EulOrdZXYr;
+ theOrder[theCount++] = EulOrdYXYr;
+ theOrder[theCount++] = EulOrdYXZr;
+ theOrder[theCount++] = EulOrdZXZr;
+ theOrder[theCount++] = EulOrdXYZr;
+ theOrder[theCount++] = EulOrdZYZr;
+
+ char theSubBuf[256];
+ m_OrderInfoBuffer[0] = '\0';
+ for (long theIndex = 0; theIndex < 24; ++theIndex) {
+ ::sprintf(theSubBuf, " %16s - %ld\n ", theOrderStr[theIndex], theOrder[theIndex]);
+ ::strcat(m_OrderInfoBuffer, theSubBuf);
+ }
+
+ return m_OrderInfoBuffer;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSEulerAngles.h b/src/system/Qt3DSEulerAngles.h
new file mode 100644
index 0000000..d0f53c5
--- /dev/null
+++ b/src/system/Qt3DSEulerAngles.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** 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 <qmath.h>
+
+namespace Q3DStudio {
+//==============================================================================
+// Description
+//==============================================================================
+// QuatTypes.h - Basic type declarations
+// by Ken Shoemake, shoemake@graphics.cis.upenn.edu
+// in "Graphics Gems IV", Academic Press, 1994
+typedef struct
+{
+ float x, y, z, w;
+} Quat; /* Quaternion */
+typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
+enum QuatPart { X, Y, Z, W };
+typedef Quat EulerAngles; /* (x,y,z)=ang 1,2,3, w=order code */
+
+#define EulFrmS 0
+#define EulFrmR 1
+#define EulFrm(ord) ((unsigned)(ord)&1)
+#define EulRepNo 0
+#define EulRepYes 1
+#define EulRep(ord) (((unsigned)(ord) >> 1) & 1)
+#define EulParEven 0
+#define EulParOdd 1
+#define EulPar(ord) (((unsigned)(ord) >> 2) & 1)
+#define EulSafe "\000\001\002\000"
+#define EulNext "\001\002\000\001"
+#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord) >> 3) & 3)]))
+#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) == EulParOdd)]))
+#define EulAxK(ord) ((int)(EulNext[EulAxI(ord) + (EulPar(ord) != EulParOdd)]))
+#define EulAxH(ord) ((EulRep(ord) == EulRepNo) ? EulAxK(ord) : EulAxI(ord))
+
+// EulGetOrd unpacks all useful information about order simultaneously.
+#define EulGetOrd(ord, i, j, k, h, n, s, f) \
+ { \
+ unsigned o = ord; \
+ f = o & 1; \
+ o = o >> 1; \
+ s = o & 1; \
+ o = o >> 1; \
+ n = o & 1; \
+ o = o >> 1; \
+ i = EulSafe[o & 3]; \
+ j = EulNext[i + n]; \
+ k = EulNext[i + 1 - n]; \
+ h = s ? k : i; \
+ }
+
+// EulOrd creates an order value between 0 and 23 from 4-tuple choices.
+#define EulOrd(i, p, r, f) (((((((i) << 1) + (p)) << 1) + (r)) << 1) + (f))
+
+// Static axes
+// X = 0, Y = 1, Z = 2 ref QuatPart
+#define EulOrdXYZs EulOrd(0, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdXYXs EulOrd(0, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdXZYs EulOrd(0, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdXZXs EulOrd(0, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdYZXs EulOrd(1, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdYZYs EulOrd(1, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdYXZs EulOrd(1, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdYXYs EulOrd(1, EulParOdd, EulRepYes, EulFrmS)
+#define EulOrdZXYs EulOrd(2, EulParEven, EulRepNo, EulFrmS)
+#define EulOrdZXZs EulOrd(2, EulParEven, EulRepYes, EulFrmS)
+#define EulOrdZYXs EulOrd(2, EulParOdd, EulRepNo, EulFrmS)
+#define EulOrdZYZs EulOrd(2, EulParOdd, EulRepYes, EulFrmS)
+
+// Rotating axes
+#define EulOrdZYXr EulOrd(0, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdXYXr EulOrd(0, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdYZXr EulOrd(0, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdXZXr EulOrd(0, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdXZYr EulOrd(1, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdYZYr EulOrd(1, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdZXYr EulOrd(1, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdYXYr EulOrd(1, EulParOdd, EulRepYes, EulFrmR)
+#define EulOrdYXZr EulOrd(2, EulParEven, EulRepNo, EulFrmR)
+#define EulOrdZXZr EulOrd(2, EulParEven, EulRepYes, EulFrmR)
+#define EulOrdXYZr EulOrd(2, EulParOdd, EulRepNo, EulFrmR)
+#define EulOrdZYZr EulOrd(2, EulParOdd, EulRepYes, EulFrmR)
+
+#ifndef M_PI
+#define M_PI 3.1415926535898
+#endif
+
+#define TODEG(x) x = (float)(x * 180 / M_PI);
+#define TORAD(x) x = (float)(x / 180 * M_PI);
+
+class CEulerAngleConverter
+{
+private:
+ char m_OrderInfoBuffer[1024];
+
+public:
+ CEulerAngleConverter();
+ virtual ~CEulerAngleConverter();
+
+public:
+ EulerAngles Eul_(float ai, float aj, float ah, int order);
+ Quat Eul_ToQuat(EulerAngles ea);
+ void Eul_ToHMatrix(EulerAngles ea, HMatrix M);
+ EulerAngles Eul_FromHMatrix(HMatrix M, int order);
+ EulerAngles Eul_FromQuat(Quat q, int order);
+
+ // Debug Stuff
+ const char *DumpOrderInfo();
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSFNDTimer.h b/src/system/Qt3DSFNDTimer.h
new file mode 100644
index 0000000..8241e2e
--- /dev/null
+++ b/src/system/Qt3DSFNDTimer.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** 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 "Qt3DSTimer.h"
+#include "Qt3DSTypes.h"
+#include "foundation/Qt3DSTime.h"
+
+namespace Q3DStudio {
+class Qt3DSFNDTimer : public ITimeProvider
+{
+ Q3DStudio::INT64 GetCurrentTimeMicroSeconds() override
+ {
+ return qt3ds::foundation::Time::getCurrentTimeInTensOfNanoSeconds() / 100;
+ }
+};
+}
diff --git a/src/system/Qt3DSFile.cpp b/src/system/Qt3DSFile.cpp
new file mode 100644
index 0000000..a26b735
--- /dev/null
+++ b/src/system/Qt3DSFile.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSFile.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// OS level memory routines
+//==============================================================================
+#if defined(_XENONPLATFORM) || defined(_PCPLATFORM) || defined(_PS3PLATFORM) \
+ || defined(_TEGRAPLATFORM) || defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+CFile::TOpen CFile::s_Open = &fopen;
+CFile::TClose CFile::s_Close = &fclose;
+CFile::TRead CFile::s_Read = &fread;
+CFile::TWrite CFile::s_Write = &fwrite;
+CFile::TTell CFile::s_Tell = &ftell;
+CFile::TSeek CFile::s_Seek = &fseek;
+#else
+#error "A platform must be defined"
+#endif
+
+//==============================================================================
+/**
+ * Overrides basic memory allocation/deallocation routines
+ * @param inOpen fopen replacement method
+ * @param inClose fclose replacement method
+ * @param inRead fread replacement method
+ * @param inWrite fwrite replacement method
+ */
+void CFile::SetFileFunctions(const TOpen inOpen, const TClose inClose, const TRead inRead,
+ const TWrite inWrite, const TTell inTell, const TSeek inSeek)
+{
+ s_Open = inOpen;
+ s_Close = inClose;
+ s_Read = inRead;
+ s_Write = inWrite;
+ s_Tell = inTell;
+ s_Seek = inSeek;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSFile.h b/src/system/Qt3DSFile.h
new file mode 100644
index 0000000..e970cd2
--- /dev/null
+++ b/src/system/Qt3DSFile.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSTypes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Single overridable exit point for all low level file calls.
+ */
+class CFile
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef enum _E_SEEK {
+ E_SEEK_SET = SEEK_SET,
+ E_SEEK_CUR = SEEK_CUR,
+ E_SEEK_END = SEEK_END
+ } E_SEEK;
+
+ typedef TFile *(*TOpen)(const char *inFileName, const char *inMode);
+ typedef int (*TClose)(TFile *inFile);
+ typedef TFileSize (*TRead)(void *inBuffer, TFileSize inSize, TFileSize inCount, TFile *inFile);
+ typedef TFileSize (*TWrite)(const void *inBuffer, TFileSize inSize, TFileSize inCount,
+ TFile *inFile);
+ typedef long (*TTell)(TFile *inFile);
+ typedef int (*TSeek)(TFile *inFile, long inOffset, int inOrigin);
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static TOpen s_Open; ///< function pointer to fopen operation
+ static TClose s_Close; ///< function pointer to fclose operation
+ static TRead s_Read; ///< function pointer to fread operation
+ static TWrite s_Write; ///< function pointer to fwrite operation
+ static TTell s_Tell; ///< function pointer to ftell operation
+ static TSeek s_Seek; ///< function pointer to fseek operation
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Memory override
+ static void SetFileFunctions(const TOpen inOpen, const TClose inClose, const TRead inRead,
+ const TWrite inWrite, const TTell inTell, const TSeek inSeek);
+
+public: // Function access
+ static TOpen Open() { return s_Open; }
+ static TClose Close() { return s_Close; }
+ static TRead Read() { return s_Read; }
+ static TWrite Write() { return s_Write; }
+ static TTell Tell() { return s_Tell; }
+ static TSeek Seek() { return s_Seek; }
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSFileStream.cpp b/src/system/Qt3DSFileStream.cpp
new file mode 100644
index 0000000..202e4ae
--- /dev/null
+++ b/src/system/Qt3DSFileStream.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+#include "Qt3DSFile.h"
+#include "Qt3DSFileStream.h"
+#include "foundation/Qt3DSLogging.h"
+
+#include <QtCore/qthread.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ * @param inFilename the file to open
+ * @param inMode the file mode to use
+ */
+CFileStream::CFileStream(const CHAR *inFilePath, const CHAR *inMode, BOOL inKeepTrying)
+ : m_FileStream(NULL)
+ , m_Endian(QT3DS_LITTLE_ENDIAN)
+ , m_KeepTrying(inKeepTrying)
+{
+ m_TempBuffer.Reserve(sizeof(MATRIX16)); // Preallocated some space
+ if (inFilePath)
+ Open(inFilePath, inMode);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CFileStream::~CFileStream()
+{
+ Close();
+}
+
+//==============================================================================
+/**
+ * Open file.
+ * @param inFilename the file to open
+ * @param inMode the file mode ( read/write ) to use
+ */
+void CFileStream::Open(const CHAR *inFilePath, const CHAR *inMode)
+{
+ Close();
+ m_FileStream = CFile::Open()(inFilePath, inMode);
+ while (m_KeepTrying && !m_FileStream) {
+ QThread::msleep(10);
+ m_FileStream = CFile::Open()(inFilePath, inMode);
+ }
+
+ if (m_FileStream)
+ m_FilePath = inFilePath;
+}
+
+//==============================================================================
+/**
+ * Close file.
+ */
+void CFileStream::Close()
+{
+ if (m_FileStream) {
+ CFile::Close()(m_FileStream);
+ m_FileStream = NULL;
+ }
+}
+
+//==============================================================================
+/**
+ * Check if there is an opened file.
+ * @return TRUE if opened, FALSE otherwise.
+ */
+BOOL CFileStream::IsOpen() const
+{
+ return m_FileStream != NULL;
+}
+
+//==============================================================================
+/**
+ * Access the source path of a file stream.
+ * @return an empty string if the stream is not open
+ */
+const CHAR *CFileStream::GetFilePath() const
+{
+ return m_FilePath.toLatin1().constData();
+}
+
+//==============================================================================
+/**
+ * Read from stream into memory.
+ * @param outMemory the destination of the read
+ * @param inByteCount the amount to read
+ * @return the number of bytes actually read
+ */
+INT32 CFileStream::ReadRawCopy(void *inDestination, const UINT32 inByteCount)
+{
+ INT32 lastRead = 0;
+ INT32 totalRead = 0;
+ do {
+ if (totalRead) {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Failed to read expected amount, retrying, expected "
+ << inByteCount << " bytes, got "<< totalRead <<" bytes";
+ }
+ lastRead = static_cast<INT32>(CFile::Read()(((char *)inDestination) + totalRead, 1,
+ inByteCount - totalRead, m_FileStream));
+ totalRead += lastRead;
+ } while (lastRead && totalRead < (INT32)inByteCount);
+
+ if (totalRead != (INT32)inByteCount) {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Failed to read expected amount, retrying, expected "
+ << inByteCount << " bytes, got "<< totalRead <<" bytes";
+
+ // Zero out remaining destination buffer.
+ // This can, in some cases, avoid a crash and allow the system to survive a partial
+ // read.
+ INT32 amountLeft = inByteCount - totalRead;
+ memset(((char *)inDestination) + totalRead, 0, amountLeft);
+ }
+ return totalRead;
+}
+
+//==============================================================================
+/**
+ * Reads data into internal buffer and return the data pointer for it.
+ * @param outMemory pointer to internal data buffer
+ * @param inByteCount the amount to read
+ * @return the number of bytes actually read
+ */
+INT32 CFileStream::ReadRaw(const void *&inPtr, const UINT32 inByteCount)
+{
+ m_TempBuffer.Reserve(static_cast<INT32>(inByteCount));
+ INT32 theReadSize = ReadRawCopy(m_TempBuffer.Begin(), inByteCount);
+ if (theReadSize != (INT32)inByteCount) {
+ qCWarning(qt3ds::INVALID_OPERATION)
+ << "Failed to read expected amount, retrying, expected "<< inByteCount
+ << " bytes, got "<< theReadSize <<" bytes";
+ }
+ inPtr = m_TempBuffer.Begin();
+ return theReadSize;
+}
+
+//==============================================================================
+/**
+ * Write from memory to stream.
+ * @param inMemory the buffer to write from
+ * @param inByteCount the amount to write
+ * @return the number of bytes actually written
+ */
+INT32 CFileStream::WriteRaw(const void *inSource, const UINT32 inByteCount)
+{
+ return static_cast<INT32>(CFile::Write()(inSource, 1, inByteCount, m_FileStream));
+}
+
+//==============================================================================
+/**
+ * Offsets the file position by the specified number of bytes
+ */
+void CFileStream::Offset(const INT32 inByteCount)
+{
+ CFile::Seek()(m_FileStream, inByteCount, CFile::E_SEEK_CUR);
+}
+
+//==============================================================================
+/**
+ * Returns the current position of the file stream
+ */
+IStream::TStreamPosition CFileStream::Current()
+{
+ return static_cast<INT32>(CFile::Tell()(m_FileStream));
+}
+
+//==============================================================================
+/**
+ * Sets the stream to the specified position within the file
+ */
+void CFileStream::Set(const TStreamPosition &inPosition)
+{
+ CFile::Seek()(m_FileStream, inPosition, CFile::E_SEEK_SET);
+}
+
+//==============================================================================
+/**
+ * Set the endianess of the file.
+ * @warning endian support not implemented
+ */
+void CFileStream::SetEndian(const BOOL inEndian)
+{
+ m_Endian = inEndian;
+}
+
+//==============================================================================
+/**
+ * Get the endianess of the file.
+ * @warning endian support not implemented
+ */
+BOOL CFileStream::GetEndian()
+{
+ return m_Endian;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSFileStream.h b/src/system/Qt3DSFileStream.h
new file mode 100644
index 0000000..49e272f
--- /dev/null
+++ b/src/system/Qt3DSFileStream.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSIFileStream.h"
+#include "Qt3DSArray.h"
+#include "Qt3DSEndian.h"
+
+#include <QtCore/QString>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * File stream base class.
+ */
+class CFileStream : public IFileStream
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CFileStream(const CHAR *inFilePath = NULL, const CHAR *inMode = "rb",
+ BOOL inKeepTrying = false);
+ virtual ~CFileStream();
+
+public: // Serializing
+ INT32 ReadRawCopy(void *inDestination, const UINT32 inByteCount) override;
+ INT32 ReadRaw(const void *&inPtr, const UINT32 inByteCount) override;
+ INT32 WriteRaw(const void *inSource, const UINT32 inByteCount) override;
+
+ // Seeking
+ void Offset(const INT32 inOffset) override;
+ TStreamPosition Current() override;
+ void Set(const TStreamPosition &inPosition) override;
+
+public: // File Operation
+ void Open(const CHAR *inFilePath, const CHAR *inMode) override;
+ void Close() override;
+ BOOL IsOpen() const override;
+ const CHAR *GetFilePath() const override;
+
+public: // Endianess
+ void SetEndian(const BOOL inEndian);
+ BOOL GetEndian();
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ TFile *m_FileStream;
+ QString m_FilePath;
+ CArray<UINT8> m_TempBuffer;
+ BOOL m_Endian;
+ BOOL m_KeepTrying;
+ CHAR m_Unused[2]; ///< (padding)
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSFixedArray.h b/src/system/Qt3DSFixedArray.h
new file mode 100644
index 0000000..9f971d8
--- /dev/null
+++ b/src/system/Qt3DSFixedArray.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 <QtCore/QDebug>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Fixed size Ordered Collection that doesn't support growing.
+ */
+template <class T, int Size>
+class CFixedArray
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef T TType; ///< Easy access to template type
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ T m_Data[Size]; ///< Allocated memory containing array data
+ INT32 m_Capacity; ///< Max number of elements possible
+ INT32 m_Count; ///< Current number of elements in array
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ inline CFixedArray();
+ inline ~CFixedArray();
+
+public: // Management
+ inline void Clear();
+ inline INT32 GetCount() const;
+ inline INT32 GetCapacity() const;
+
+public: // Stack access
+ inline void Push(const T &inValue);
+ inline const T &Pop();
+
+public: // Array access
+ inline T &operator[](const INT32 inIndex);
+ inline void Remove(const INT32 inIndex);
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Template code
+//==============================================================================
+#include "Qt3DSFixedArray.inl"
diff --git a/src/system/Qt3DSFixedArray.inl b/src/system/Qt3DSFixedArray.inl
new file mode 100644
index 0000000..5524224
--- /dev/null
+++ b/src/system/Qt3DSFixedArray.inl
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 1999-2007 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$
+**
+****************************************************************************/
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+template <class T, int Size>
+inline CFixedArray<T, Size>::CFixedArray()
+ : m_Capacity(Size)
+ , m_Count(0)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+template <class T, int Size>
+inline CFixedArray<T, Size>::~CFixedArray()
+{
+}
+
+//==============================================================================
+/**
+ * Remove all elements in the array
+ */
+template <class T, int Size>
+inline void CFixedArray<T, Size>::Clear()
+{
+ m_Count = 0;
+}
+
+//==============================================================================
+/**
+ * Get current count of T in the array
+ * @return current count of the array
+ */
+template <class T, int Size>
+inline INT32 CFixedArray<T, Size>::GetCount() const
+{
+ return m_Count;
+}
+
+//==============================================================================
+/**
+ * Get the capacity of the array
+ * Capacity reflects the allocated memory size
+ * @return capacity of the array
+ */
+template <class T, int Size>
+inline INT32 CFixedArray<T, Size>::GetCapacity() const
+{
+ return m_Capacity;
+}
+
+//==============================================================================
+/**
+ * Insert T to the end of the array
+ * @param inValue value of datatype T
+ */
+template <class T, int Size>
+inline void CFixedArray<T, Size>::Push(const T &inValue)
+{
+ if (m_Count == m_Capacity) {
+ qWarning("Trying to push to many objects onto a CFixedArray", "Capacity=%d", m_Capacity);
+ return;
+ }
+
+ m_Data[m_Count] = inValue;
+ ++m_Count;
+}
+
+//==============================================================================
+/**
+ * Remove and retrieve T which is at the end of the array
+ * @return value of datatype T
+ */
+template <class T, int Size>
+inline const T &CFixedArray<T, Size>::Pop()
+{
+ if (m_Count == 0)
+ return {};
+
+ --m_Count;
+ return m_Data[m_Count];
+}
+
+//==============================================================================
+/**
+ * Get T at a particular index position of the array.
+ * Need to ensure only valid index is allowed
+ * Clear( ) will set the m_counter = 0
+ * @param inIndex the index of the array
+ * @return reference of value of datatype T
+ */
+template <class T, int Size>
+inline T &CFixedArray<T, Size>::operator[](const INT32 inIndex)
+{
+ Q3DStudio_ASSERT(inIndex < m_Capacity);
+
+ return m_Data[inIndex];
+}
+
+//==============================================================================
+/**
+ * Removes a specific entry from the array.
+ * Moves all entries below it up, expensive.
+ * @param inIndex the index of the entry
+ */
+template <class T, int Size>
+inline void CFixedArray<T, Size>::Remove(const INT32 inIndex)
+{
+ Q3DStudio_memmove(m_Data + inIndex, m_Data + inIndex + 1, sizeof(T) * (m_Count - inIndex - 1));
+ --m_Count;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSFunctionWrappers.cpp b/src/system/Qt3DSFunctionWrappers.cpp
new file mode 100644
index 0000000..e96c3ce
--- /dev/null
+++ b/src/system/Qt3DSFunctionWrappers.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2010 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 "SystemPrefix.h"
+#include "Qt3DSFunctionWrappers.h"
+
+using namespace Q3DStudio;
+
+//==============================================================================
+/**
+* CTOR
+*/
+IFunctionWrapper::IFunctionWrapper()
+ : m_Cost(0)
+{
+}
+
+//==============================================================================
+/**
+* Retrieve the cost associated with this function.
+* Should be zero or greater
+*/
+INT32 IFunctionWrapper::GetCost()
+{
+ return m_Cost;
+}
+
+//==============================================================================
+/**
+* Sets the cost associated with this function.
+*/
+void IFunctionWrapper::SetCost(const INT32 inCost)
+{
+ m_Cost = inCost;
+} \ No newline at end of file
diff --git a/src/system/Qt3DSFunctionWrappers.h b/src/system/Qt3DSFunctionWrappers.h
new file mode 100644
index 0000000..8fff62d
--- /dev/null
+++ b/src/system/Qt3DSFunctionWrappers.h
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2010 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+* Interface for a function wrapper with an associated cost.
+*/
+class IFunctionWrapper
+{
+public:
+ IFunctionWrapper();
+ virtual ~IFunctionWrapper(){}
+
+public:
+ virtual void Execute() = 0;
+ INT32 GetCost();
+ void SetCost(const INT32 inCost);
+
+protected:
+ INT32 m_Cost;
+};
+
+//==============================================================================
+/**
+* 2 arguments function wrapper
+*/
+template <typename TArg1, typename TArg2>
+class CFunctionWrapper2Args : public IFunctionWrapper
+{
+public:
+ typedef void (*TFunction)(TArg1 inArg1, TArg2 inArg2);
+
+public:
+ CFunctionWrapper2Args(TFunction, TArg1 inArg1, TArg2 inArg2);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+};
+
+// Unused
+/*
+template <typename TArg1, typename TArg2, typename TArg3>
+class CFunctionWrapper3Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3 );
+
+ public:
+ CFunctionWrapper3Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+};
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4>
+class CFunctionWrapper4Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4
+);
+
+ public:
+ CFunctionWrapper4Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3, TArg4 inArg4 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+};
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8>
+class CFunctionWrapper8Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4,
+TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8 );
+
+ public:
+ CFunctionWrapper8Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3, TArg4 inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+ TArg5 m_Arg5;
+ TArg6 m_Arg6;
+ TArg7 m_Arg7;
+ TArg8 m_Arg8;
+};
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8, typename TArg9>
+class CFunctionWrapper9Args : public IFunctionWrapper
+{
+ public:
+ typedef void ( *TFunction )( TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4,
+TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8, TArg9 inArg9 );
+
+ public:
+ CFunctionWrapper9Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3
+inArg3, TArg4 inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8, TArg9 inArg9 );
+
+ public:
+ virtual void Execute( );
+
+ protected:
+ TFunction m_Function;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+ TArg5 m_Arg5;
+ TArg6 m_Arg6;
+ TArg7 m_Arg7;
+ TArg8 m_Arg8;
+ TArg9 m_Arg9;
+};
+*/
+
+//==============================================================================
+/**
+* 1 argument member function wrapper
+*/
+template <typename TObject, typename TReturn, typename TArg1>
+class CMemberFunctionWrapper1Args : public IFunctionWrapper
+{
+public:
+ typedef TReturn (TObject::*TFunction)(TArg1 inArg1);
+
+public:
+ CMemberFunctionWrapper1Args(TObject *inObject, TFunction inFunction, TArg1 inArg1);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TObject *m_Object;
+ TArg1 m_Arg1;
+};
+
+//==============================================================================
+/**
+* 2 argument member function wrapper
+*/
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2>
+class CMemberFunctionWrapper2Args : public IFunctionWrapper
+{
+public:
+ typedef TReturn (TObject::*TFunction)(TArg1 inArg1, TArg2 inArg2);
+
+public:
+ CMemberFunctionWrapper2Args(TObject *inObject, TFunction inFunction, TArg1 inArg1,
+ TArg2 inArg2);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TObject *m_Object;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+};
+
+//==============================================================================
+/**
+* 6 argument member function wrapper
+*/
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2, typename TArg3,
+ typename TArg4, typename TArg5, typename TArg6>
+class CMemberFunctionWrapper6Args : public IFunctionWrapper
+{
+public:
+ typedef TReturn (TObject::*TFunction)(TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4,
+ TArg5 inArg5, TArg6 inArg6);
+
+public:
+ CMemberFunctionWrapper6Args(TObject *inObject, TFunction inFunction, TArg1 inArg1, TArg2 inArg2,
+ TArg3 inArg3, TArg4 inArg4, TArg5 inArg5, TArg6 inArg6);
+
+public:
+ virtual void Execute();
+
+protected:
+ TFunction m_Function;
+ TObject *m_Object;
+ TArg1 m_Arg1;
+ TArg2 m_Arg2;
+ TArg3 m_Arg3;
+ TArg4 m_Arg4;
+ TArg5 m_Arg5;
+ TArg6 m_Arg6;
+};
+
+// Implementation
+template <typename TArg1, typename TArg2>
+CFunctionWrapper2Args<TArg1, TArg2>::CFunctionWrapper2Args(TFunction inFunction, TArg1 inArg1,
+ TArg2 inArg2)
+ : m_Function(inFunction)
+ , m_Arg1(inArg1)
+ , m_Arg2(inArg2)
+{
+}
+
+template <typename TArg1, typename TArg2>
+void CFunctionWrapper2Args<TArg1, TArg2>::Execute()
+{
+ m_Function(m_Arg1, m_Arg2);
+}
+
+// Unused
+/*
+template <typename TArg1, typename TArg2, typename TArg3>
+CFunctionWrapper3Args<TArg1, TArg2, TArg3>::CFunctionWrapper3Args( TFunction inFunction, TArg1
+inArg1, TArg2 inArg2, TArg3 inArg3 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 )
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3>
+void CFunctionWrapper3Args<TArg1, TArg2, TArg3>::Execute( )
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3 );
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4>
+CFunctionWrapper4Args<TArg1, TArg2, TArg3, TArg4>::CFunctionWrapper4Args( TFunction inFunction,
+TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4 inArg4 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 ),
+ m_Arg4( inArg4 )
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4>
+void CFunctionWrapper4Args<TArg1, TArg2, TArg3, TArg4>::Execute( )
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3, m_Arg4 );
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8>
+CFunctionWrapper8Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7,
+TArg8>::CFunctionWrapper8Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4
+inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 ),
+ m_Arg4( inArg4 ),
+ m_Arg5( inArg5 ),
+ m_Arg6( inArg6 ),
+ m_Arg7( inArg7 ),
+ m_Arg8( inArg8 )
+
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8>
+void CFunctionWrapper8Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8>::Execute( )
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7, m_Arg8 );
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8, typename TArg9>
+CFunctionWrapper9Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8,
+TArg9>::CFunctionWrapper9Args( TFunction inFunction, TArg1 inArg1, TArg2 inArg2, TArg3 inArg3, TArg4
+inArg4, TArg5 inArg5, TArg6 inArg6, TArg7 inArg7, TArg8 inArg8, TArg9 inArg9 )
+: m_Function( inFunction ),
+ m_Arg1( inArg1 ),
+ m_Arg2( inArg2 ),
+ m_Arg3( inArg3 ),
+ m_Arg4( inArg4 ),
+ m_Arg5( inArg5 ),
+ m_Arg6( inArg6 ),
+ m_Arg7( inArg7 ),
+ m_Arg8( inArg8 ),
+ m_Arg9( inArg9 )
+{
+}
+
+template <typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename
+TArg6, typename TArg7, typename TArg8, typename TArg9>
+void CFunctionWrapper9Args<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9>::Execute(
+)
+{
+ m_Function( m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7, m_Arg8, m_Arg9 );
+}
+*/
+
+template <typename TObject, typename TReturn, typename TArg1>
+CMemberFunctionWrapper1Args<TObject, TReturn, TArg1>::CMemberFunctionWrapper1Args(
+ TObject *inObject, TFunction inFunction, TArg1 inArg1)
+ : m_Function(inFunction)
+ , m_Object(inObject)
+ , m_Arg1(inArg1)
+{
+}
+
+template <typename TObject, typename TReturn, typename TArg1>
+void CMemberFunctionWrapper1Args<TObject, TReturn, TArg1>::Execute()
+{
+ (m_Object->*m_Function)(m_Arg1);
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2>
+CMemberFunctionWrapper2Args<TObject, TReturn, TArg1, TArg2>::CMemberFunctionWrapper2Args(
+ TObject *inObject, TFunction inFunction, TArg1 inArg1, TArg2 inArg2)
+ : m_Function(inFunction)
+ , m_Object(inObject)
+ , m_Arg1(inArg1)
+ , m_Arg2(inArg2)
+{
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2>
+void CMemberFunctionWrapper2Args<TObject, TReturn, TArg1, TArg2>::Execute()
+{
+ (m_Object->*m_Function)(m_Arg1, m_Arg2);
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2, typename TArg3,
+ typename TArg4, typename TArg5, typename TArg6>
+CMemberFunctionWrapper6Args<TObject, TReturn, TArg1, TArg2, TArg3, TArg4, TArg5,
+ TArg6>::CMemberFunctionWrapper6Args(TObject *inObject,
+ TFunction inFunction, TArg1 inArg1,
+ TArg2 inArg2, TArg3 inArg3,
+ TArg4 inArg4, TArg5 inArg5,
+ TArg6 inArg6)
+ : m_Function(inFunction)
+ , m_Object(inObject)
+ , m_Arg1(inArg1)
+ , m_Arg2(inArg2)
+ , m_Arg3(inArg3)
+ , m_Arg4(inArg4)
+ , m_Arg5(inArg5)
+ , m_Arg6(inArg6)
+{
+}
+
+template <typename TObject, typename TReturn, typename TArg1, typename TArg2, typename TArg3,
+ typename TArg4, typename TArg5, typename TArg6>
+void CMemberFunctionWrapper6Args<TObject, TReturn, TArg1, TArg2, TArg3, TArg4, TArg5,
+ TArg6>::Execute()
+{
+ (m_Object->*m_Function)(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6);
+}
+}
diff --git a/src/system/Qt3DSHash.h b/src/system/Qt3DSHash.h
new file mode 100644
index 0000000..8baa2db
--- /dev/null
+++ b/src/system/Qt3DSHash.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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 "Qt3DSConfig.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Utility class transforming a string into a hash value.
+ */
+class CHash
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Static utility
+ //==============================================================================
+ /**
+ * We use the hashing algorithm called "sdbm".
+ *
+ * This algorithm was created from sdbm (a public-domain reimplementation
+ * of ndbm) database library. It was found to do well in scrambling bits,
+ * causing better distribution of the keys and fewer splits. it also happens
+ * to be a good general hashing function with good distribution. the actual
+ * function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
+ * is the faster version used in gawk. [there is even a faster, duff-device
+ * version] the magic constant 65599 was picked out of thin air while
+ * experimenting with different constants, and turns out to be a prime. this
+ * is one of the algorithms used in berkeley db (see sleepycat) and elsewhere.
+ *
+ * @param inString the string to hash
+ * @return the hash value
+ */
+ static TStringHash HashString(const CHAR *inString)
+ {
+ TStringHash theHash = 0;
+ INT32 theChar = *inString;
+ INT32 theCount = 0;
+ while (theChar && (theCount < HASH_LIMIT)) {
+ theChar = *inString++;
+ theHash = theChar + (theHash << 6) + (theHash << 16) - theHash;
+ ++theCount;
+ }
+
+ return theHash;
+ }
+
+ //==============================================================================
+ /**
+ * 31-bit hash with MSB set to 0
+ *
+ * @param inString the string to hash
+ * @return the 31-bit hash value
+ */
+ static TEventCommandHash HashEventCommand(const CHAR *inString)
+ {
+ return HashString(inString) & 0x7fffffff;
+ }
+
+ //==============================================================================
+ /**
+ * 26-bit hash with MSBs all set to 0
+ *
+ * @param inString the string to hash
+ * @return the 26-bit hash value
+ */
+ static TAttributeHash HashAttribute(const CHAR *inString)
+ {
+ return HashString(inString) & 0x03ffffff;
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSIFileStream.h b/src/system/Qt3DSIFileStream.h
new file mode 100644
index 0000000..0b43260
--- /dev/null
+++ b/src/system/Qt3DSIFileStream.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSIStream.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * File stream interface
+ */
+class IFileStream : public IStream
+{
+public:
+ virtual void Open(const CHAR *inFilePath, const CHAR *inMode) = 0;
+ virtual void Close() = 0;
+ virtual BOOL IsOpen() const = 0;
+ virtual const CHAR *GetFilePath() const = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSIStream.h b/src/system/Qt3DSIStream.h
new file mode 100644
index 0000000..a4c1195
--- /dev/null
+++ b/src/system/Qt3DSIStream.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Pure virtual interface providing the stream for class serialization.
+ */
+class IStream
+{
+ //==============================================================================
+ // Typedef
+ //==============================================================================
+public:
+ typedef INT32 TStreamPosition;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~IStream(){}
+
+public: // Serializing
+ virtual INT32 ReadRawCopy(void *inDestination, const UINT32 inByteCount) = 0;
+ virtual INT32 ReadRaw(const void *&inPtr, const UINT32 inByteCount) = 0;
+ virtual INT32 WriteRaw(const void *inSource, const UINT32 inByteCount) = 0;
+
+ // Seeking
+ virtual void Offset(const INT32 inOffset) = 0;
+ virtual TStreamPosition Current() = 0;
+ virtual void Set(const TStreamPosition &inPosition) = 0;
+
+public: // Template Readers that make a copy
+ template <typename T>
+ INT32 ReadCopy(T &outValue);
+ template <typename T>
+ INT32 ReadArrayCopy(T *outValue, const UINT32 inCount);
+
+public: // Template Readers that access value directly
+ template <typename T>
+ INT32 Read(const T *&inPtr);
+ template <typename T>
+ INT32 ReadArray(const T *&inPtr, UINT32 inCount);
+
+public: // Template Writers
+ template <typename T>
+ INT32 Write(const T &inValue);
+ template <typename T>
+ INT32 WriteArray(const T *inValue, const UINT32 inCount);
+};
+
+/** Notes concerning usage of Read or ReadCopy (and ReadArray and ReadArrayCopy)**/
+/**
+If the value being read fits into 4 bytes (i.e float, int/long), either Read/ReadCopy can be used.
+However, if the read value is going to be accessed frequently (in loops etc), ReadCopy is
+recommended so a copy is available instead of dereferencing.
+
+ReadCopy should be used if the data read is an array or is significantly larger than 4 bytes (like
+vectors or matrixes).
+
+For cases where the value is to be stored in a persistant data structures, ReadCopy should be used.
+
+One important thing about Read/ReadArray, is that the pointer returned is only valid before the next
+Read/ReadyArray is called.
+There is no guarantee that the pointer data will remain unchanged during subsequent calls to
+Read/ReadArray.
+**/
+
+//==============================================================================
+/**
+ * Read and assign a value by copying.
+ */
+template <typename T>
+INT32 IStream::ReadCopy(T &outValue)
+{
+ return ReadRawCopy(&outValue, sizeof(T));
+}
+
+//==============================================================================
+/**
+ * Read and copy data to a preallocated array.
+ */
+template <typename T>
+INT32 IStream::ReadArrayCopy(T *outValue, const UINT32 inCount)
+{
+ return ReadRawCopy(outValue, sizeof(T) * inCount);
+}
+
+//==============================================================================
+/**
+ * Obtain a pointer directly to the data.
+ */
+template <typename T>
+INT32 IStream::Read(const T *&inPtr)
+{
+ return ReadRaw(reinterpret_cast<const void *&>(inPtr), sizeof(T));
+}
+
+//==============================================================================
+/**
+ * Obtain a pointer directly to the array data.
+ */
+template <typename T>
+INT32 IStream::ReadArray(const T *&inPtr, const UINT32 inCount)
+{
+ return ReadRaw(reinterpret_cast<const void *&>(inPtr), sizeof(T) * inCount);
+}
+
+//==============================================================================
+/**
+ * Write a value.
+ */
+template <typename T>
+INT32 IStream::Write(const T &inValue)
+{
+ return WriteRaw(&inValue, sizeof(T));
+}
+
+//==============================================================================
+/**
+ * Write an array of values.
+ */
+template <typename T>
+INT32 IStream::WriteArray(const T *inValue, const UINT32 inCount)
+{
+ return WriteRaw(inValue, sizeof(T) * inCount);
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSITimer.h b/src/system/Qt3DSITimer.h
new file mode 100644
index 0000000..e73fbb9
--- /dev/null
+++ b/src/system/Qt3DSITimer.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * @interface ITimer
+ * The base functionality of the timer used by the Kernel
+ *
+ * Implement this interface per-platform to obtain the required functionality
+ */
+class ITimer
+{
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ virtual ~ITimer() {}
+
+public: // Operation
+ virtual void Start() = 0;
+ virtual void Stop() = 0;
+ virtual void Reset() = 0;
+ virtual TTimeUnit GetTimeMilliSecs() = 0;
+ virtual TMicroSeconds GetTimeMicroSecs() = 0;
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMacros.h b/src/system/Qt3DSMacros.h
new file mode 100644
index 0000000..fbc40b4
--- /dev/null
+++ b/src/system/Qt3DSMacros.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSAssert.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Easy iterations over arrays.
+ * @param array_type element type
+ * @param array_element element variable name getting each entry
+ * @param array_container element array we are traversing
+ */
+#define FOR_ARRAY(array_type, array_element, array_container) \
+ for (array_type *array_element = (array_container).Begin(); \
+ array_element != (array_container).End(); ++array_element)
+
+#define FOR_ARRAY_REVERSE(array_type, array_element, array_container) \
+ for (array_type *array_element = (array_container).End() - 1; \
+ array_element != (array_container).Begin() - 1; --array_element)
+
+//==============================================================================
+/**
+ * Return the smallest of two numbers/objects.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @return a reference, not a copy, to the smallest of the two values
+ */
+template <class T>
+inline const T Q3DStudio_abs(const T &inVal)
+{
+ return inVal >= 0 ? inVal : -inVal;
+}
+
+//==============================================================================
+/**
+ * Return the smallest of two numbers/objects.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @return a reference, not a copy, to the smallest of the two values
+ */
+template <typename T>
+inline const T &Q3DStudio_min(const T &inA, const T &inB)
+{
+ return inA < inB ? inA : inB;
+}
+
+//==============================================================================
+/**
+ * Return the largest of two numbers/objects.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @return a reference, not a copy, to the largest of the two values
+ */
+template <class T>
+inline const T &Q3DStudio_max(const T &inA, const T &inB)
+{
+ return inA > inB ? inA : inB;
+}
+
+//==============================================================================
+/**
+ * Return the smallest of three values.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @param inC a third value to compare
+ * @return a reference, not a copy, to the smallest of the three values
+ */
+template <class T>
+inline const T &Q3DStudio_min3(const T &inA, const T &inB, const T &inC)
+{
+ return inA < inB ? Q3DStudio_min(inA, inC) : Q3DStudio_min(inB, inC);
+}
+
+//==============================================================================
+/**
+ * Return the largest of three values.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @param inC a third value to compare
+ * @return a reference, not a copy, to the largest of the three values
+ */
+template <class T>
+inline const T &Q3DStudio_max3(const T &inA, const T &inB, const T &inC)
+{
+ return inA > inB ? Q3DStudio_max(inA, inC) : Q3DStudio_max(inB, inC);
+}
+
+//==============================================================================
+/**
+ * Make sure a value is in-bounds between two other values.
+ * @param inVal the value to clamp
+ * @param inMin the lowest inclusive value
+ * @param inMax the highest inclusive value
+ * @return a reference to inVal if the value is in bounds,
+ inMin if lower than the minimum value, or
+ inMax if higher than maximum value.
+ */
+template <class T>
+inline const T &Q3DStudio_clamp(const T &inVal, const T &inMin, const T &inMax)
+{
+ if (inVal <= inMin)
+ return inMin;
+ else if (inVal >= inMax)
+ return inMax;
+
+ return inVal;
+}
+
+//==============================================================================
+/**
+ * Return the identified lower and higher values.
+ * @param inA one value to compare
+ * @param inB another value to compare
+ * @param outMin is assigned to the lower of the two compared values
+ * @param outMax is assigned to the higher of the two compared values
+ */
+template <class T>
+inline void Q3DStudio_minmax(const T &inA, const T &inB, T &outMin, T &outMax)
+{
+ if (inA < inB) {
+ outMin = inA;
+ outMax = inB;
+ } else {
+ outMin = inB;
+ outMax = inA;
+ }
+}
+
+//==============================================================================
+/**
+ * Identify needed parameters that are not currently referenced.
+ */
+#define Q3DStudio_UNREFERENCED_PARAMETER(P) \
+ { \
+ (void)P; \
+ }
+
+//==============================================================================
+/**
+ * Assert
+ */
+#if defined(_DEBUG) || defined(_PROFILE)
+#define Q3DStudio_ASSERT(inExpression) \
+ { \
+ if (!(inExpression)) \
+ Q3DStudio::CAssert::GetFunction()(#inExpression, __FILE__, __LINE__, __FUNCTION__); \
+ }
+#else
+#define Q3DStudio_ASSERT(inExpression) ((void)0)
+#endif // _DEBUG or _PROFILE
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMatrix.cpp b/src/system/Qt3DSMatrix.cpp
new file mode 100644
index 0000000..b5310d0
--- /dev/null
+++ b/src/system/Qt3DSMatrix.cpp
@@ -0,0 +1,897 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMatrix.h"
+#include "Qt3DSVector3.h"
+#include "Qt3DSEulerAngles.h"
+#include "Qt3DSDataLogger.h"
+#include <math.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+FLOAT g_IdentityInit[4][4] = { { 1.0f, 0.0f, 0.0f, 0.0f },
+ { 0.0f, 1.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 1.0f, 0.0f },
+ { 0.0f, 0.0f, 0.0f, 1.0f } };
+
+const RuntimeMatrix RuntimeMatrix::IDENTITY = RuntimeMatrix(g_IdentityInit);
+extern const FLOAT RUNTIME_EPSILON;
+
+//==============================================================================
+/**
+ * Empty constructor.
+ * Initializes this matrix to the identity matrix.
+ */
+RuntimeMatrix::RuntimeMatrix(const BOOL inInitializeIdentity /*= true*/)
+{
+ if (inInitializeIdentity)
+ Q3DStudio_memcpy(&m_Data, &IDENTITY, sizeof(m_Data));
+}
+
+//==============================================================================
+/**
+ * Copy constructor.
+ * @param inMatrix the source matrix to copy
+ */
+RuntimeMatrix::RuntimeMatrix(const RuntimeMatrix &inMatrix)
+{
+ Q3DStudio_memcpy(&m_Data, &inMatrix.m_Data, sizeof(m_Data));
+}
+
+//==============================================================================
+/**
+ * Assignment constructor.
+ * Initializes the matrix from an array.
+ * @param inComponents an array of 16 values
+ */
+RuntimeMatrix::RuntimeMatrix(const FLOAT inComponents[4][4])
+{
+ if (inComponents)
+ Q3DStudio_memcpy(&m_Data, inComponents, sizeof(m_Data));
+}
+
+//==============================================================================
+/**
+ * Sets this matrix to a NULL matrix with all values at zero.
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Zero()
+{
+ Q3DStudio_memset(&m_Data, 0, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the matrix to the identity matrix.
+ * @return reference to this matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Identity()
+{
+ Q3DStudio_memcpy(&m_Data, &IDENTITY, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Copies the elements from another matrix.
+ * @param inMatrix the source matrix
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Set(const RuntimeMatrix &inMatrix)
+{
+ Q3DStudio_memcpy(&m_Data, &inMatrix.m_Data, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Copies the given components to this matrix.
+ * @param inComponents an array of 16 components
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Set(const FLOAT inComponents[4][4])
+{
+ if (inComponents)
+ Q3DStudio_memcpy(&m_Data, inComponents, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Heavily optimized assignment method. This has the same result as creating
+ * four full 4x4 matrices and multiplying them together.
+ * @todo Look into optimized code.
+ * @param inTranslation translation coordinates
+ * @param inRotation Euler angle rotations
+ * @param inScale scaling dimensions
+ * @param inPivot pivot offset vector
+ * @param inRotationOrder rotation order
+ * @param inCoordinateSystem the coordindate system
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Set(const RuntimeVector3 &inTranslation, const RuntimeVector3 &inRotation,
+ const RuntimeVector3 &inScale, const RuntimeVector3 &inPivot, const UINT8 inRotationOrder,
+ const UINT8 inCoordinateSystem)
+{
+ // *this = m_ScaleMatrix * m_PivotMatrix * m_RotMatrix * m_TransMatrix; // Distributed
+ //original - plain speak
+
+ RuntimeVector3 theScaledPivot;
+ theScaledPivot.m_X = -inPivot.m_X * inScale.m_X;
+ theScaledPivot.m_Y = -inPivot.m_Y * inScale.m_Y;
+ theScaledPivot.m_Z = -inPivot.m_Z * inScale.m_Z;
+
+ // This would take care of rotation in the right order
+ RuntimeMatrix theRotation;
+ theRotation.SetRotate(inRotation, inRotationOrder, inCoordinateSystem);
+
+ Q3DStudio_memcpy(&m_Data, &IDENTITY, sizeof(m_Data));
+ m_Data[0][0] = inScale.m_X;
+ m_Data[1][1] = inScale.m_Y;
+ m_Data[2][2] = inScale.m_Z;
+
+ m_Data[3][0] = theScaledPivot.m_X;
+ m_Data[3][1] = theScaledPivot.m_Y;
+
+ if (inCoordinateSystem == ORIENTATION_LEFT_HANDED)
+ m_Data[3][2] = theScaledPivot.m_Z;
+ else
+ m_Data[3][2] = -theScaledPivot.m_Z;
+
+ MultiplyAffine(theRotation); // This could be optimized to only 9 multiplications instead of 16
+ // if you do them by hand
+
+ m_Data[3][0] += inTranslation.m_X;
+ m_Data[3][1] += inTranslation.m_Y;
+
+ if (inCoordinateSystem == ORIENTATION_LEFT_HANDED)
+ m_Data[3][2] += inTranslation.m_Z;
+ else
+ m_Data[3][2] += -inTranslation.m_Z;
+
+ if (inCoordinateSystem == ORIENTATION_LEFT_HANDED)
+ return FlipCoordinateSystem();
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the translation portion of the matrix without affecting the rest.
+ *
+ * If you want a pure translation matrix you must make sure to start with
+ * the identity matrix.
+ * @param inTranslate a translation vector
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::SetTranslate(const RuntimeVector3 &inTranslate)
+{
+ m_Data[3][0] = inTranslate.m_X;
+ m_Data[3][1] = inTranslate.m_Y;
+ m_Data[3][2] = inTranslate.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the rotation portion of the matrix without affecting the rest.
+ *
+ * FYI: The rotate and scale portions overlap. If you want a pure scale matrix
+ * you must make sure to start with the identity matrix.
+ * @param inRotation a quaternion describing the rotation
+ * @return reference to this modified matrix
+ */
+// CMatrix& CMatrix::SetRotate( const CQuaternion& inRotation )
+//{
+// inRotation.ToMatrix( *this );
+// return *this;
+//}
+
+//==============================================================================
+/**
+ * Sets the rotation portion of the matrix without affecting the rest.
+ *
+ * FYI: The rotate and scale portions overlap. If you want a pure rotation matrix
+ * you must make sure to start with the identity matrix.
+ * @param inRotation Euler angle rotation
+ * @param inRotationOrder rotation order
+ * @param inCoordinateSystem the coordindate system
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::SetRotate(const RuntimeVector3 &inRotation, const UINT8 inRotationOrder,
+ const UINT8 inCoordinateSystem)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+ Q3DStudio_UNREFERENCED_PARAMETER(inCoordinateSystem);
+
+ EulerAngles theEulerAngles;
+ switch (inRotationOrder) {
+ case ROTATIONORDER_XYZ:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdXYZs;
+ break;
+ case ROTATIONORDER_XYZR:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdXYZr;
+ break;
+ case ROTATIONORDER_YZX:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdYZXs;
+ break;
+ case ROTATIONORDER_YZXR:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdYZXr;
+ break;
+ case ROTATIONORDER_ZXY:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdZXYs;
+ break;
+ case ROTATIONORDER_ZXYR:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdZXYr;
+ break;
+ case ROTATIONORDER_XZY:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdXZYs;
+ break;
+ case ROTATIONORDER_XZYR:
+ theEulerAngles.x = inRotation.m_X;
+ theEulerAngles.y = inRotation.m_Z;
+ theEulerAngles.z = inRotation.m_Y;
+ theEulerAngles.w = EulOrdXZYr;
+ break;
+ case ROTATIONORDER_YXZ:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdYXZs;
+ break;
+ case ROTATIONORDER_YXZR:
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdYXZr;
+ break;
+ case ROTATIONORDER_ZYX:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdZYXs;
+ break;
+ case ROTATIONORDER_ZYXR:
+ theEulerAngles.x = inRotation.m_Z;
+ theEulerAngles.y = inRotation.m_Y;
+ theEulerAngles.z = inRotation.m_X;
+ theEulerAngles.w = EulOrdZYXr;
+ break;
+ default: // defaults to Studio's rotation type
+ theEulerAngles.x = inRotation.m_Y;
+ theEulerAngles.y = inRotation.m_X;
+ theEulerAngles.z = inRotation.m_Z;
+ theEulerAngles.w = EulOrdYXZs;
+ break;
+ }
+
+ theEulerAngles.x *= -1;
+ theEulerAngles.y *= -1;
+ theEulerAngles.z *= -1;
+
+ CEulerAngleConverter theConverter;
+ theConverter.Eul_ToHMatrix(theEulerAngles, m_Data);
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Sets the scale portion of the matrix without affecting the rest.
+ *
+ * FYI: The rotate and scale portions overlap. If you want a pure scale matrix
+ * you must make sure to start with the identity matrix.
+ * @param inScale scale vector
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::SetScale(const RuntimeVector3 &inScale)
+{
+ m_Data[0][0] = inScale.m_X;
+ m_Data[1][1] = inScale.m_Y;
+ m_Data[2][2] = inScale.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Check this matrix against the identity matrix.
+ * @return true if this matrix is equivalent to the identity matrix
+ */
+BOOL RuntimeMatrix::IsIdentity() const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ return *this == IDENTITY;
+}
+
+//==============================================================================
+/**
+ * Checks to see if this matrix is affine.
+ * An affine matrix has the last row being [ 0 0 0 1 ]
+ * @return true if the matrix is affine
+ */
+BOOL RuntimeMatrix::IsAffine() const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ return m_Data[0][3] == 0 && m_Data[1][3] == 0 && m_Data[2][3] == 0 && m_Data[3][3] == 1.0f;
+}
+
+//==============================================================================
+/**
+ * Appends the matrix to include a translation. Equivalent to post-multiplying
+ * this matrix with a transformation matrix derived from the given vector.
+ * @param inTranslation transformation vector applied
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Translate(const RuntimeVector3 &inTranslation)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ m_Data[3][0] += inTranslation.m_X;
+ m_Data[3][1] += inTranslation.m_Y;
+ m_Data[3][2] += inTranslation.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Appends the matrix to include a rotation. Equivalent to post-multiplying
+ * this matrix with a rotation matrix derived from the given quaternion.
+ * @param inRotation the rotation quaternion applied
+ * @return reference to this modified matrix
+ */
+// CMatrix& CMatrix::Rotate( const CQuaternion& inRotation )
+//{
+// CMatrix theRotation;
+// return MultiplyAffine( inRotation.ToMatrix( theRotation ) );
+//}
+
+//==============================================================================
+/**
+ * Appends the matrix to include scaling. Equivalent to post-multiplying
+ * this matrix with a scale matrix derived from the given vector.
+ * @param inScale the scale vector applied
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Scale(const RuntimeVector3 &inScale)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ m_Data[0][0] *= inScale.m_X;
+ m_Data[0][1] *= inScale.m_X;
+ m_Data[0][2] *= inScale.m_X;
+
+ m_Data[1][0] *= inScale.m_Y;
+ m_Data[1][1] *= inScale.m_Y;
+ m_Data[1][2] *= inScale.m_Y;
+
+ m_Data[2][0] *= inScale.m_Z;
+ m_Data[2][1] *= inScale.m_Z;
+ m_Data[2][2] *= inScale.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Flips the matrix elements around the identity diagonal.
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::Transpose()
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theSwap = m_Data[1][0];
+ m_Data[1][0] = m_Data[0][1];
+ m_Data[0][1] = theSwap;
+
+ theSwap = m_Data[2][0];
+ m_Data[2][0] = m_Data[0][2];
+ m_Data[0][2] = theSwap;
+
+ theSwap = m_Data[3][0];
+ m_Data[3][0] = m_Data[0][3];
+ m_Data[0][3] = theSwap;
+
+ theSwap = m_Data[2][1];
+ m_Data[2][1] = m_Data[1][2];
+ m_Data[1][2] = theSwap;
+
+ theSwap = m_Data[3][1];
+ m_Data[3][1] = m_Data[1][3];
+ m_Data[1][3] = theSwap;
+
+ theSwap = m_Data[3][2];
+ m_Data[3][2] = m_Data[2][3];
+ m_Data[2][3] = theSwap;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compute the inverse of a 3D affine matrix; i.e. a matrix with a
+ * dimensionality of 4 where the bottom row has the entries (0, 0, 0, 1).
+ *
+ * This procedure treats the 4 by 4 matrix as a block matrix and
+ * calculates the inverse of one submatrix for a significant performance
+ * improvement over a general procedure that can invert any non-singular matrix:
+@code
+ | | -1 | -1 -1 |
+ | A C | | A -C A |
+ -1 | | | |
+ M = | | = | |
+ | 0 1 | | 0 1 |
+ | | | |
+@endcode
+ * where M is a 4 by 4 matrix,
+ * A is the 3 by 3 upper left submatrix of M,
+ * C is the 3 by 1 upper right submatrix of M.
+ *
+ * @return the determinant of matrix
+ */
+FLOAT RuntimeMatrix::Invert()
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ const FLOAT PRECISIONLIMIT = 1.0e-07f;
+ FLOAT thePositiveDet = 0.0f;
+ FLOAT theNegativeDet = 0.0f;
+ FLOAT theTempDet;
+
+ // Calculate the determinant of submatrix A and determine if the
+ // the matrix is singular as limited by the float precision.
+ theTempDet = m_Data[0][0] * m_Data[1][1] * m_Data[2][2];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m_Data[0][1] * m_Data[1][2] * m_Data[2][0];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = m_Data[0][2] * m_Data[1][0] * m_Data[2][1];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m_Data[0][2] * m_Data[1][1] * m_Data[2][0];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m_Data[0][1] * m_Data[1][0] * m_Data[2][2];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ theTempDet = -m_Data[0][0] * m_Data[1][2] * m_Data[2][1];
+ if (theTempDet >= 0.0f)
+ thePositiveDet += theTempDet;
+ else
+ theNegativeDet += theTempDet;
+
+ // Is the submatrix A nonsingular? (i.e. there is an inverse?)
+ FLOAT theDeterminant = thePositiveDet + theNegativeDet;
+ if (theDeterminant != 0
+ || ::fabs(theDeterminant / (thePositiveDet - theNegativeDet)) >= PRECISIONLIMIT) {
+ RuntimeMatrix theInverse;
+ FLOAT theInvDeterminant = 1.0f / theDeterminant;
+
+ // Calculate inverse(A) = adj(A) / det(A)
+ theInverse.m_Data[0][0] =
+ (m_Data[1][1] * m_Data[2][2] - m_Data[1][2] * m_Data[2][1]) * theInvDeterminant;
+ theInverse.m_Data[1][0] =
+ -(m_Data[1][0] * m_Data[2][2] - m_Data[1][2] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[2][0] =
+ (m_Data[1][0] * m_Data[2][1] - m_Data[1][1] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[0][1] =
+ -(m_Data[0][1] * m_Data[2][2] - m_Data[0][2] * m_Data[2][1]) * theInvDeterminant;
+ theInverse.m_Data[1][1] =
+ (m_Data[0][0] * m_Data[2][2] - m_Data[0][2] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[2][1] =
+ -(m_Data[0][0] * m_Data[2][1] - m_Data[0][1] * m_Data[2][0]) * theInvDeterminant;
+ theInverse.m_Data[0][2] =
+ (m_Data[0][1] * m_Data[1][2] - m_Data[0][2] * m_Data[1][1]) * theInvDeterminant;
+ theInverse.m_Data[1][2] =
+ -(m_Data[0][0] * m_Data[1][2] - m_Data[0][2] * m_Data[1][0]) * theInvDeterminant;
+ theInverse.m_Data[2][2] =
+ (m_Data[0][0] * m_Data[1][1] - m_Data[0][1] * m_Data[1][0]) * theInvDeterminant;
+
+ // Calculate -C * inverse(A)
+ theInverse.m_Data[3][0] =
+ -(m_Data[3][0] * theInverse.m_Data[0][0] + m_Data[3][1] * theInverse.m_Data[1][0]
+ + m_Data[3][2] * theInverse.m_Data[2][0]);
+ theInverse.m_Data[3][1] =
+ -(m_Data[3][0] * theInverse.m_Data[0][1] + m_Data[3][1] * theInverse.m_Data[1][1]
+ + m_Data[3][2] * theInverse.m_Data[2][1]);
+ theInverse.m_Data[3][2] =
+ -(m_Data[3][0] * theInverse.m_Data[0][2] + m_Data[3][1] * theInverse.m_Data[1][2]
+ + m_Data[3][2] * theInverse.m_Data[2][2]);
+
+ // assign ourselves to the inverse
+ *this = theInverse;
+ }
+
+ return theDeterminant;
+}
+
+//==============================================================================
+/**
+ * Fast multiplication of two affine 4x4 matrices. No affine pre-check.
+ * @todo MF - Convert to SSE Assembly Code
+ * @param inMatrix the source matrix
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::MultiplyAffine(const RuntimeMatrix &inMatrix)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theMult[4][4];
+
+ theMult[0][0] = m_Data[0][0] * inMatrix.m_Data[0][0] + m_Data[0][1] * inMatrix.m_Data[1][0]
+ + m_Data[0][2] * inMatrix.m_Data[2][0];
+ theMult[0][1] = m_Data[0][0] * inMatrix.m_Data[0][1] + m_Data[0][1] * inMatrix.m_Data[1][1]
+ + m_Data[0][2] * inMatrix.m_Data[2][1];
+ theMult[0][2] = m_Data[0][0] * inMatrix.m_Data[0][2] + m_Data[0][1] * inMatrix.m_Data[1][2]
+ + m_Data[0][2] * inMatrix.m_Data[2][2];
+ theMult[0][3] = 0;
+
+ theMult[1][0] = m_Data[1][0] * inMatrix.m_Data[0][0] + m_Data[1][1] * inMatrix.m_Data[1][0]
+ + m_Data[1][2] * inMatrix.m_Data[2][0];
+ theMult[1][1] = m_Data[1][0] * inMatrix.m_Data[0][1] + m_Data[1][1] * inMatrix.m_Data[1][1]
+ + m_Data[1][2] * inMatrix.m_Data[2][1];
+ theMult[1][2] = m_Data[1][0] * inMatrix.m_Data[0][2] + m_Data[1][1] * inMatrix.m_Data[1][2]
+ + m_Data[1][2] * inMatrix.m_Data[2][2];
+ theMult[1][3] = 0;
+
+ theMult[2][0] = m_Data[2][0] * inMatrix.m_Data[0][0] + m_Data[2][1] * inMatrix.m_Data[1][0]
+ + m_Data[2][2] * inMatrix.m_Data[2][0];
+ theMult[2][1] = m_Data[2][0] * inMatrix.m_Data[0][1] + m_Data[2][1] * inMatrix.m_Data[1][1]
+ + m_Data[2][2] * inMatrix.m_Data[2][1];
+ theMult[2][2] = m_Data[2][0] * inMatrix.m_Data[0][2] + m_Data[2][1] * inMatrix.m_Data[1][2]
+ + m_Data[2][2] * inMatrix.m_Data[2][2];
+ theMult[2][3] = 0;
+
+ theMult[3][0] = m_Data[3][0] * inMatrix.m_Data[0][0] + m_Data[3][1] * inMatrix.m_Data[1][0]
+ + m_Data[3][2] * inMatrix.m_Data[2][0] + inMatrix.m_Data[3][0];
+ theMult[3][1] = m_Data[3][0] * inMatrix.m_Data[0][1] + m_Data[3][1] * inMatrix.m_Data[1][1]
+ + m_Data[3][2] * inMatrix.m_Data[2][1] + inMatrix.m_Data[3][1];
+ theMult[3][2] = m_Data[3][0] * inMatrix.m_Data[0][2] + m_Data[3][1] * inMatrix.m_Data[1][2]
+ + m_Data[3][2] * inMatrix.m_Data[2][2] + inMatrix.m_Data[3][2];
+ theMult[3][3] = 1.0f;
+
+ return Set(theMult);
+}
+
+//==============================================================================
+/**
+ * Standard matrix multiplication
+ * @todo MF - Convert to SSE Assembly Code
+ * @param inMatrix matrix to multiply with
+ */
+RuntimeMatrix &RuntimeMatrix::Multiply(const RuntimeMatrix &inMatrix)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theMult[4][4];
+
+ theMult[0][0] = m_Data[0][0] * inMatrix.m_Data[0][0] + m_Data[1][0] * inMatrix.m_Data[0][1]
+ + m_Data[2][0] * inMatrix.m_Data[0][2] + m_Data[3][0] * inMatrix.m_Data[0][3];
+ theMult[0][1] = m_Data[0][1] * inMatrix.m_Data[0][0] + m_Data[1][1] * inMatrix.m_Data[0][1]
+ + m_Data[2][1] * inMatrix.m_Data[0][2] + m_Data[3][1] * inMatrix.m_Data[0][3];
+ theMult[0][2] = m_Data[0][2] * inMatrix.m_Data[0][0] + m_Data[1][2] * inMatrix.m_Data[0][1]
+ + m_Data[2][2] * inMatrix.m_Data[0][2] + m_Data[3][2] * inMatrix.m_Data[0][3];
+ theMult[0][3] = m_Data[0][3] * inMatrix.m_Data[0][0] + m_Data[1][3] * inMatrix.m_Data[0][1]
+ + m_Data[2][3] * inMatrix.m_Data[0][2] + m_Data[3][3] * inMatrix.m_Data[0][3];
+ theMult[1][0] = m_Data[0][0] * inMatrix.m_Data[1][0] + m_Data[1][0] * inMatrix.m_Data[1][1]
+ + m_Data[2][0] * inMatrix.m_Data[1][2] + m_Data[3][0] * inMatrix.m_Data[1][3];
+ theMult[1][1] = m_Data[0][1] * inMatrix.m_Data[1][0] + m_Data[1][1] * inMatrix.m_Data[1][1]
+ + m_Data[2][1] * inMatrix.m_Data[1][2] + m_Data[3][1] * inMatrix.m_Data[1][3];
+ theMult[1][2] = m_Data[0][2] * inMatrix.m_Data[1][0] + m_Data[1][2] * inMatrix.m_Data[1][1]
+ + m_Data[2][2] * inMatrix.m_Data[1][2] + m_Data[3][2] * inMatrix.m_Data[1][3];
+ theMult[1][3] = m_Data[0][3] * inMatrix.m_Data[1][0] + m_Data[1][3] * inMatrix.m_Data[1][1]
+ + m_Data[2][3] * inMatrix.m_Data[1][2] + m_Data[3][3] * inMatrix.m_Data[1][3];
+ theMult[2][0] = m_Data[0][0] * inMatrix.m_Data[2][0] + m_Data[1][0] * inMatrix.m_Data[2][1]
+ + m_Data[2][0] * inMatrix.m_Data[2][2] + m_Data[3][0] * inMatrix.m_Data[2][3];
+ theMult[2][1] = m_Data[0][1] * inMatrix.m_Data[2][0] + m_Data[1][1] * inMatrix.m_Data[2][1]
+ + m_Data[2][1] * inMatrix.m_Data[2][2] + m_Data[3][1] * inMatrix.m_Data[2][3];
+ theMult[2][2] = m_Data[0][2] * inMatrix.m_Data[2][0] + m_Data[1][2] * inMatrix.m_Data[2][1]
+ + m_Data[2][2] * inMatrix.m_Data[2][2] + m_Data[3][2] * inMatrix.m_Data[2][3];
+ theMult[2][3] = m_Data[0][3] * inMatrix.m_Data[2][0] + m_Data[1][3] * inMatrix.m_Data[2][1]
+ + m_Data[2][3] * inMatrix.m_Data[2][2] + m_Data[3][3] * inMatrix.m_Data[2][3];
+
+ theMult[3][0] = m_Data[0][0] * inMatrix.m_Data[3][0] + m_Data[1][0] * inMatrix.m_Data[3][1]
+ + m_Data[2][0] * inMatrix.m_Data[3][2] + m_Data[3][0] * inMatrix.m_Data[3][3];
+ theMult[3][1] = m_Data[0][1] * inMatrix.m_Data[3][0] + m_Data[1][1] * inMatrix.m_Data[3][1]
+ + m_Data[2][1] * inMatrix.m_Data[3][2] + m_Data[3][1] * inMatrix.m_Data[3][3];
+ theMult[3][2] = m_Data[0][2] * inMatrix.m_Data[3][0] + m_Data[1][2] * inMatrix.m_Data[3][1]
+ + m_Data[2][2] * inMatrix.m_Data[3][2] + m_Data[3][2] * inMatrix.m_Data[3][3];
+ theMult[3][3] = m_Data[0][3] * inMatrix.m_Data[3][0] + m_Data[1][3] * inMatrix.m_Data[3][1]
+ + m_Data[2][3] * inMatrix.m_Data[3][2] + m_Data[3][3] * inMatrix.m_Data[3][3];
+
+ return Set(theMult);
+}
+
+//==============================================================================
+/**
+ * Toggle between left-hand and right-hand coordinate system
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::FlipCoordinateSystem()
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ // rotation conversion
+ m_Data[0][2] *= -1;
+ m_Data[1][2] *= -1;
+ m_Data[2][0] *= -1;
+ m_Data[2][1] *= -1;
+
+ // translation conversion
+ m_Data[3][2] *= -1;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Rotate this matrix to align with the rotation of the specified matrix.
+ *
+ * @param inMatrix the maxtrix we are cloning.
+ * @param inMirrorFlag flag indicating that we should flip the z and face the opposite
+ *direction.
+ * @return This matrix after the rotation.
+ */
+RuntimeMatrix &RuntimeMatrix::CloneRotation(const RuntimeMatrix &inMatrix, BOOL inMirrorFlag /*= false*/)
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ // Create the axes
+ RuntimeVector3 theZ(inMatrix.Get(2, 0), inMatrix.Get(2, 1), inMatrix.Get(2, 2));
+ if (inMirrorFlag)
+ theZ *= -1;
+ RuntimeVector3 theY(inMatrix.Get(1, 0), inMatrix.Get(1, 1), inMatrix.Get(1, 2));
+ RuntimeVector3 theX(theY);
+ theX.CrossProduct(theZ);
+
+ // Normalize
+ theX.Normalize();
+ theY.Normalize();
+ theZ.Normalize();
+
+ // Copy it into the matrix
+ m_Data[0][0] = theX.m_X;
+ m_Data[0][1] = theX.m_Y;
+ m_Data[0][2] = theX.m_Z;
+
+ m_Data[1][0] = theY.m_X;
+ m_Data[1][1] = theY.m_Y;
+ m_Data[1][2] = theY.m_Z;
+
+ m_Data[2][0] = theZ.m_X;
+ m_Data[2][1] = theZ.m_Y;
+ m_Data[2][2] = theZ.m_Z;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compute the square distance between the position vectors of two transforms.
+ * @param inMatrix the other transform, signifying a global object position for example
+ * @return the square of the "distance" between the two transforms
+ */
+FLOAT RuntimeMatrix::SquareDistance(const RuntimeMatrix &inMatrix) const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ FLOAT theResult = 0;
+ FLOAT theFactor;
+
+ theFactor = m_Data[3][0] - inMatrix.m_Data[3][0];
+ theFactor *= theFactor;
+ theResult += theFactor;
+
+ theFactor = m_Data[3][1] - inMatrix.m_Data[3][1];
+ theFactor *= theFactor;
+ theResult += theFactor;
+
+ theFactor = m_Data[3][2] - inMatrix.m_Data[3][2];
+ theFactor *= theFactor;
+ theResult += theFactor;
+
+ return theResult;
+}
+
+//==============================================================================
+/**
+ * Simple assignment operator.
+ * @param inMatrix new matrix being assigned
+ * @return reference to this modified matrix
+ */
+RuntimeMatrix &RuntimeMatrix::operator=(const RuntimeMatrix &inMatrix)
+{
+ Q3DStudio_memcpy(&m_Data, &inMatrix.m_Data, sizeof(m_Data));
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compares this matrix's elements with another matrix's and returns true
+ * if the matrices are equivalent.
+ * @param inMatrix the matrix we are comparing against
+ * @return true if all elements are within EPSILON of each other.
+ */
+BOOL RuntimeMatrix::operator==(const RuntimeMatrix &inMatrix) const
+{
+ PerfLogMathEvent1(DATALOGGER_MATRIX);
+
+ for (INT32 iRow = 0; iRow < 4; ++iRow) {
+ for (INT32 iCol = 0; iCol < 4; ++iCol) {
+ if (::fabs(m_Data[iRow][iCol] - inMatrix.m_Data[iRow][iCol]) > RUNTIME_EPSILON)
+ return false;
+ }
+ }
+ return true;
+}
+
+//==============================================================================
+/**
+ * Compares this matrix's elements with another matrix's and returns true
+ * if the matrices are not equivalent.
+ * @param inMatrix the matrix we are comparing against
+ * @return true if one or more elements are more than EPSILON from each other
+ */
+BOOL RuntimeMatrix::operator!=(const RuntimeMatrix &inMatrix) const
+{
+ // Reuse same code path..
+ return !(*this == inMatrix);
+}
+
+//==============================================================================
+/**
+ * Standardized conversion to string.
+ * @param outString string becoming a representation for the matrix
+ */
+// void CMatrix::ToString( AK_STRING& outString ) const
+//{
+// INT8 theBuffer[ 256 ];
+//
+// Q3DStudio_sprintf
+// (
+// theBuffer, 255,
+// "%.2f %.2f %.2f %.2f "
+// "%.2f %.2f %.2f %.2f "
+// "%.2f %.2f %.2f %.2f "
+// "%.2f %.2f %.2f %.2f",
+//
+// m_Data.m[ 0 ][ 0 ],
+// m_Data.m[ 0 ][ 1 ],
+// m_Data.m[ 0 ][ 2 ],
+// m_Data.m[ 0 ][ 3 ],
+//
+// m_Data.m[ 1 ][ 0 ],
+// m_Data.m[ 1 ][ 1 ],
+// m_Data.m[ 1 ][ 2 ],
+// m_Data.m[ 1 ][ 3 ],
+//
+// m_Data.m[ 2 ][ 0 ],
+// m_Data.m[ 2 ][ 1 ],
+// m_Data.m[ 2 ][ 2 ],
+// m_Data.m[ 2 ][ 3 ],
+//
+// m_Data.m[ 3 ][ 0 ],
+// m_Data.m[ 3 ][ 1 ],
+// m_Data.m[ 3 ][ 2 ],
+// m_Data.m[ 3 ][ 3 ]
+// );
+//
+// outString = theBuffer;
+//}
+//
+////==============================================================================
+///**
+// * Standardized conversion from string.
+// * @param inString string being a representation for the matrix
+// */
+// void CMatrix::FromString( const AK_STRING& inString )
+//{
+// std::sscanf
+// (
+// inString.c_str( ),
+//
+// "%f %f %f %f "
+// "%f %f %f %f "
+// "%f %f %f %f "
+// "%f %f %f %f",
+//
+// &m_Data.m[ 0 ][ 0 ],
+// &m_Data.m[ 0 ][ 1 ],
+// &m_Data.m[ 0 ][ 2 ],
+// &m_Data.m[ 0 ][ 3 ],
+//
+// &m_Data.m[ 1 ][ 0 ],
+// &m_Data.m[ 1 ][ 1 ],
+// &m_Data.m[ 1 ][ 2 ],
+// &m_Data.m[ 1 ][ 3 ],
+//
+// &m_Data.m[ 2 ][ 0 ],
+// &m_Data.m[ 2 ][ 1 ],
+// &m_Data.m[ 2 ][ 2 ],
+// &m_Data.m[ 2 ][ 3 ],
+//
+// &m_Data.m[ 3 ][ 0 ],
+// &m_Data.m[ 3 ][ 1 ],
+// &m_Data.m[ 3 ][ 2 ],
+// &m_Data.m[ 3 ][ 3 ]
+// );
+//}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMatrix.h b/src/system/Qt3DSMatrix.h
new file mode 100644
index 0000000..4ef7442
--- /dev/null
+++ b/src/system/Qt3DSMatrix.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeVector3;
+
+//==============================================================================
+/**
+ * A row major matrix for 3D transformation.
+ *
+ * Matrix[row][column]
+@code
+ | 0 1 2 3 | or | 00 01 02 03 | or | Xx Xy Xz w |
+ | 4 5 6 7 | | 10 11 12 13 | | Yx Yy Yz w |
+ | 8 9 A B | | 20 21 22 23 | | Zx Zy Zz w |
+ | C D E F | | 30 31 32 33 | | Tx Ty Tz w |
+@endcode
+ * Rotations are concatenated in the the following order: YXZ
+ * All rotations are clockwise when viewed down the positive axis
+ * towards the origin.
+ */
+class RuntimeMatrix
+{
+ //==============================================================================
+ // Enumerations
+ //==============================================================================
+public:
+ enum ERotationOrder {
+ ROTATIONORDER_XYZ = 0,
+ ROTATIONORDER_YZX,
+ ROTATIONORDER_ZXY,
+ ROTATIONORDER_XZY,
+ ROTATIONORDER_YXZ,
+ ROTATIONORDER_ZYX,
+
+ ROTATIONORDER_XYZR,
+ ROTATIONORDER_YZXR,
+ ROTATIONORDER_ZXYR,
+ ROTATIONORDER_XZYR,
+ ROTATIONORDER_YXZR,
+ ROTATIONORDER_ZYXR
+ };
+
+ enum EOrientation { ORIENTATION_LEFT_HANDED = 0, ORIENTATION_RIGHT_HANDED };
+
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ static const RuntimeMatrix IDENTITY; ///< Enabling fast initialization from static identity matrix
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ FLOAT m_Data[4][4]; ///< 16 elements in a 4 x 4
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ RuntimeMatrix(const BOOL inInitializeIdentity = true);
+ RuntimeMatrix(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix(const FLOAT inComponents[4][4]);
+
+public: // Initialization
+ RuntimeMatrix &Zero();
+ RuntimeMatrix &Identity();
+
+ RuntimeMatrix &Set(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix &Set(const FLOAT inComponents[4][4]);
+ RuntimeMatrix &Set(const RuntimeVector3 &inTranslation, const RuntimeVector3 &inRotation, const RuntimeVector3 &inScale,
+ const RuntimeVector3 &inPivot, const UINT8 inRotationOrder,
+ const UINT8 inCoordinateSystem);
+
+ RuntimeMatrix &SetTranslate(const RuntimeVector3 &inTranslate);
+ RuntimeMatrix &SetRotate(const RuntimeVector3 &inRotation, const UINT8 inRotationOrder = ROTATIONORDER_XYZ,
+ const UINT8 inCoordinateSystem = ORIENTATION_LEFT_HANDED);
+ RuntimeMatrix &SetScale(const RuntimeVector3 &inScale);
+
+public: // Functions
+ BOOL IsIdentity() const;
+ BOOL IsAffine() const;
+ RuntimeMatrix &Translate(const RuntimeVector3 &inTranslate);
+ RuntimeMatrix &Scale(const RuntimeVector3 &inScale);
+ RuntimeMatrix &Transpose();
+ FLOAT Invert();
+ RuntimeMatrix &MultiplyAffine(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix &Multiply(const RuntimeMatrix &inMatrix);
+ RuntimeMatrix &FlipCoordinateSystem();
+ RuntimeMatrix &CloneRotation(const RuntimeMatrix &inMatrix, BOOL inMirrorFlag = false);
+ FLOAT SquareDistance(const RuntimeMatrix &inMatrix) const;
+
+public: // Operators
+ RuntimeMatrix &operator=(const RuntimeMatrix &inMatrix);
+ BOOL operator==(const RuntimeMatrix &inMatrix) const;
+ BOOL operator!=(const RuntimeMatrix &inMatrix) const;
+
+public: // Script based accessors
+ inline FLOAT Get(const INT32 inRow, const INT32 inColumn) const
+ {
+ return m_Data[inRow][inColumn];
+ }
+ inline void Set(const INT32 inRow, const INT32 inColumn, const FLOAT inValue)
+ {
+ m_Data[inRow][inColumn] = inValue;
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemory.cpp b/src/system/Qt3DSMemory.cpp
new file mode 100644
index 0000000..17fa5c8
--- /dev/null
+++ b/src/system/Qt3DSMemory.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemory.h"
+
+//==============================================================================
+// OS level memory routines
+//==============================================================================
+Q3DStudio::CMemory::TMalloc Q3DStudio::CMemory::s_Malloc = NULL;
+Q3DStudio::CMemory::TRealloc Q3DStudio::CMemory::s_Realloc = NULL;
+Q3DStudio::CMemory::TFree Q3DStudio::CMemory::s_Free = NULL;
+
+//==============================================================================
+/**
+ * Overrides basic memory allocation/deallocation routines
+ * @param inMalloc memory allocation routine
+ * @param inFree memory deallocation routine
+ * @param inRealloc memory reallocation routine
+ */
+void Q3DStudio::CMemory::SetMemoryFunctions(const TMalloc inMalloc, const TFree inFree,
+ const TRealloc inRealloc)
+{
+ s_Malloc = inMalloc;
+ s_Realloc = inRealloc;
+ s_Free = inFree;
+}
+
+static Q3DStudio::CMemoryManager *s_globalManager = nullptr;
+static Q3DStudio::CMemoryHeap *s_globalHeap = nullptr;
+
+//==============================================================================
+/**
+ * Boot up the pooled memory manager and return it.
+ * @note The manager has to be initialized before use:
+ * GetMemoryManager( ).Initialize( "GlobalManager", g_ChunkSize, g_ChunkCount );
+ * @return Q3DStudio::CMemoryManager reference to the global object
+ */
+Q3DStudio::CMemoryManager &GetMemoryManager()
+{
+ if (!s_globalManager)
+ s_globalManager = new Q3DStudio::CMemoryManager;
+ return *s_globalManager;
+}
+
+//==============================================================================
+/**
+ * Return a reference to the global heap object.
+ * @return Q3DStudio::CMemoryHeap reference to the global object
+ */
+Q3DStudio::CMemoryHeap &GetMemoryHeap()
+{
+ if (!s_globalHeap)
+ s_globalHeap = new Q3DStudio::CMemoryHeap;
+ return *s_globalHeap;
+}
+
+//==============================================================================
+// Q3DStudio_new operator prototypes (5 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, size_t inOfficialSize, const char *inType,
+ const char *inFile, int inLine)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inReportedSize);
+ Q3DStudio_ASSERT(inReportedSize == inOfficialSize);
+
+ return Q3DStudio_HANDLER_NEW.Allocate(static_cast<const Q3DStudio::INT32>(inOfficialSize),
+ inType, inFile, inLine);
+}
+
+//==============================================================================
+/**
+ * Override 'operator delete' in order to track memory usage.
+ *
+ * So what's the use of the overloaded delete with special arguments? There is
+ * actually one case in which it will be called--when an exception is thrown
+ * during object construction. As you might recall, there is a contract implicit
+ * in the language that if an exception happens during the construction of an object,
+ * the memory for this object will be automatically deallocated. It so happens
+ * that during object's construction the compiler is still aware of which version
+ * of operator new was called to allocate memory. It is therefore able to generate
+ * a call to the corresponding version of delete, in case an exception is thrown.
+ * After the successful completion of construction, this information is no longer
+ * available and the compiler has no means to guess which version of global delete
+ * is appropriate for a given object.
+ */
+void operator delete(void *inReportedAddress, size_t inOfficialSize, const char *, const char *,
+ int)
+{
+ Q3DStudio_HANDLER_NEW.Free(inReportedAddress,
+ static_cast<const Q3DStudio::INT32>(inOfficialSize));
+}
+
+//==============================================================================
+// Q3DStudio_virtual_new operators (4 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, const char *inType, const char *inFile, int inLine)
+{
+ return Q3DStudio::CMemoryFilter::Allocate(static_cast<Q3DStudio::INT32>(inReportedSize), inType,
+ inFile, inLine, false);
+}
+
+void operator delete(void *inReportedAddress, const char *, const char *, int)
+{
+ Q3DStudio::CMemoryFilter::Free(inReportedAddress);
+}
diff --git a/src/system/Qt3DSMemory.h b/src/system/Qt3DSMemory.h
new file mode 100644
index 0000000..cc04bf7
--- /dev/null
+++ b/src/system/Qt3DSMemory.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#ifndef _INTEGRITYPLATFORM
+#include <memory.h>
+#endif
+#include "Qt3DSMemoryHeap.h"
+#include "Qt3DSMemoryManager.h"
+#include "Qt3DSMemoryFilter.h"
+#include "Qt3DSMemoryStatistics.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Single overridable exit point for all low level memory calls.
+ */
+class CMemory
+{
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef void *(*TMalloc)(size_t inSize);
+ typedef void (*TFree)(void *inPtr);
+ typedef void *(*TRealloc)(void *inPtr, size_t inSize);
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static TMalloc s_Malloc; ///< function pointer to malloc operation
+ static TFree s_Free; ///< function pointer to free operation
+ static TRealloc s_Realloc; ///< function pointer to realloc operation
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Memory override
+ static void SetMemoryFunctions(const TMalloc inMalloc, const TFree inFree,
+ const TRealloc inRealloc);
+
+public: // Function access
+ static TMalloc Malloc() { return s_Malloc; }
+ static TFree Free() { return s_Free; }
+ static TRealloc Realloc() { return s_Realloc; }
+};
+
+} // namespace Q3DStudio
+
+//==============================================================================
+// Globals
+//==============================================================================
+Q3DStudio::CMemoryManager &GetMemoryManager();
+Q3DStudio::CMemoryHeap &GetMemoryHeap();
+
+//==============================================================================
+// Handlers
+//==============================================================================
+#ifndef Q3DStudio_HANDLER_NEW
+#define Q3DStudio_HANDLER_NEW GetMemoryManager()
+#endif // Q3DStudio_HANDLER_NEW
+
+#ifndef Q3DStudio_HANDLER_ALLOC
+#define Q3DStudio_HANDLER_ALLOC GetMemoryManager()
+#endif // Q3DStudio_HANDLER_ALLOC
+
+#ifndef Q3DStudio_HANDLER_FILTER
+#define Q3DStudio_HANDLER_FILTER GetMemoryManager()
+#endif // Q3DStudio_HANDLER_FILTER
+
+//==============================================================================
+// Q3DStudio new defines
+//==============================================================================
+#undef new
+#undef delete
+
+#ifndef Q3DStudio_new
+#define Q3DStudio_new(type) new (sizeof(type), "class " #type, __FILE__, __LINE__)
+#endif // Q3DStudio_new
+
+#ifndef Q3DStudio_delete
+#define Q3DStudio_delete(ptr, type) \
+ if (ptr) { \
+ reinterpret_cast<type *>(ptr)->~type(); \
+ Q3DStudio_HANDLER_NEW.Free(ptr, sizeof(type)); \
+ }
+#endif // Q3DStudio_delete
+
+#ifndef Q3DStudio_virtual_new
+#define Q3DStudio_virtual_new(type) new ("class " #type, __FILE__, __LINE__)
+#endif // Q3DStudio_virtual_new
+
+#ifndef Q3DStudio_virtual_delete
+#define Q3DStudio_virtual_delete(ptr, type) \
+ if (ptr) { \
+ static_cast<type *>(ptr)->~type(); \
+ Q3DStudio::CMemoryFilter::Free(ptr); \
+ }
+#endif // Q3DStudio_virtual_delete
+
+//==============================================================================
+// Q3DStudio alloc defines
+//==============================================================================
+#ifndef Q3DStudio_allocate
+#define Q3DStudio_allocate(type, count) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Allocate( \
+ static_cast<Q3DStudio::INT32>(sizeof(type) * (count)), #type "[]", __FILE__, __LINE__))
+#endif // Q3DStudio_allocate
+
+#ifndef Q3DStudio_allocate_desc
+#define Q3DStudio_allocate_desc(type, count, desc) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Allocate( \
+ static_cast<Q3DStudio::INT32>(sizeof(type) * (count)), desc, __FILE__, __LINE__))
+#endif // Q3DStudio_allocate_desc
+
+#ifndef Q3DStudio_reallocate
+#define Q3DStudio_reallocate(ptr, type, oldcount, newcount) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Reallocate( \
+ ptr, static_cast<Q3DStudio::INT32>(sizeof(type) * (oldcount)), \
+ static_cast<INT32>(sizeof(type) * (newcount)), #type "[]", __FILE__, __LINE__))
+#endif // Q3DStudio_reallocate
+
+#ifndef Q3DStudio_reallocate_desc
+#define Q3DStudio_reallocate_desc(ptr, type, oldcount, newcount, desc) \
+ reinterpret_cast<type *>(Q3DStudio_HANDLER_ALLOC.Reallocate( \
+ ptr, static_cast<Q3DStudio::INT32>(sizeof(type) * (oldcount)), \
+ static_cast<INT32>(sizeof(type) * (newcount)), desc, __FILE__, __LINE__))
+#endif // Q3DStudio_reallocate_desc
+
+#ifndef Q3DStudio_free
+#define Q3DStudio_free(ptr, type, count) \
+ Q3DStudio_HANDLER_ALLOC.Free(ptr, static_cast<Q3DStudio::INT32>(sizeof(type) * (count)))
+#endif // Q3DStudio_free
+
+//==============================================================================
+// Q3DStudio_new - operator prototypes (5 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, size_t inOfficialSize, const char *inType,
+ const char *inFile, int inLine);
+void operator delete(void *inReportedAddress, size_t inOfficialSize, const char *, const char *,
+ int);
+
+//==============================================================================
+// Q3DStudio_virtual_new and new - operator prototypes (4 args)
+//==============================================================================
+void *operator new(size_t inReportedSize, const char *inType, const char *inFile, int inLine);
+void operator delete(void *inReportedAddress, const char *, const char *, int);
diff --git a/src/system/Qt3DSMemoryFilter.cpp b/src/system/Qt3DSMemoryFilter.cpp
new file mode 100644
index 0000000..f6d6591
--- /dev/null
+++ b/src/system/Qt3DSMemoryFilter.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryFilter.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Allocate a chunk of memory and add a header to track it.
+ * @param inSize size of requested memory block, in bytes
+ * @param inType allocation description
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @param inClear true to clear allocated memory to zero
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryFilter::Allocate(const INT32 inSize, const CHAR *inType, const CHAR *inFile,
+ const INT32 inLine, const BOOL inClear)
+{
+ const INT32 theTotalSize = inSize + Q3DStudio_MEMORY_ALIGNMENT;
+
+ INT32 *theMemory = reinterpret_cast<INT32 *>(
+ Q3DStudio_HANDLER_FILTER.Allocate(theTotalSize, inType, inFile, inLine));
+
+ theMemory[0] = FILTER_DOGTAG;
+ theMemory[1] = theTotalSize;
+
+ if (inClear)
+ Q3DStudio_memset(reinterpret_cast<INT8 *>(theMemory) + Q3DStudio_MEMORY_ALIGNMENT, 0,
+ inSize);
+
+ return reinterpret_cast<INT8 *>(theMemory) + Q3DStudio_MEMORY_ALIGNMENT;
+}
+
+//==============================================================================
+/**
+ * Free a block of memory that was allocated and tagged here.
+ * @param inPointer pointer given in a previous filter allocation
+ */
+void CMemoryFilter::Free(void *inPointer)
+{
+ if (!inPointer)
+ return;
+
+ INT32 *theMemory =
+ reinterpret_cast<INT32 *>(reinterpret_cast<INT8 *>(inPointer) - Q3DStudio_MEMORY_ALIGNMENT);
+
+ // Sanity check: Did we allocate this memory in the first place?
+ // If this throws we may be calling Q3DStudio_virtual_delete on memory that was getten from
+ // Q3DStudio_new
+ Q3DStudio_ASSERT(FILTER_DOGTAG == theMemory[0]);
+ Q3DStudio_HANDLER_FILTER.Free(theMemory, theMemory[1]);
+}
+
+//==============================================================================
+/**
+ * Re-allocate an existing chunk of memory and track it.
+ * @param inPointer pointer given in a previous allocation
+ * @param inNewSize size of requested memory block, in bytes
+ * @param inNewType new allocation description
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryFilter::Reallocate(void *inPointer, const INT32 inNewSize, const CHAR *inNewType,
+ const CHAR *inFile, const INT32 inLine)
+{
+ INT32 *theNewMemory = NULL;
+ const INT32 theTotalSize = inNewSize + Q3DStudio_MEMORY_ALIGNMENT;
+
+ // Dogtag is not valid if the old pointer is NULL
+ if (inPointer) {
+ INT32 *theOldMemory = reinterpret_cast<INT32 *>(reinterpret_cast<INT8 *>(inPointer)
+ - Q3DStudio_MEMORY_ALIGNMENT);
+ Q3DStudio_ASSERT(FILTER_DOGTAG == theOldMemory[0]);
+ theNewMemory = reinterpret_cast<INT32 *>(Q3DStudio_HANDLER_FILTER.Reallocate(
+ theOldMemory, theOldMemory[1], theTotalSize, inNewType, inFile, inLine));
+ } else {
+ theNewMemory = reinterpret_cast<INT32 *>(
+ Q3DStudio_HANDLER_FILTER.Reallocate(NULL, 0, theTotalSize, inNewType, inFile, inLine));
+ }
+
+ theNewMemory[0] = FILTER_DOGTAG;
+ theNewMemory[1] = theTotalSize;
+ return reinterpret_cast<INT8 *>(theNewMemory) + Q3DStudio_MEMORY_ALIGNMENT;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryFilter.h b/src/system/Qt3DSMemoryFilter.h
new file mode 100644
index 0000000..df9367d
--- /dev/null
+++ b/src/system/Qt3DSMemoryFilter.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Aggregation interface for legacy calls that don't remember allocation size.
+ *
+ * CMemoryManager and its pools require that the size must be sent along with
+ * any call, including the Free call. Normal memory calls do not require this
+ * information and this filter class is used to intercept these calls and
+ * add a header to each call before forwarded to the manager. This thin class
+ * allows old school calls such as malloc and free to still use the advantages
+ * of a pooled memory system without impacting the cleanliness and memory
+ * footprint of the modern system.
+ */
+class CMemoryFilter
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+protected:
+ const static INT32 FILTER_DOGTAG = 0x1337f1d0;
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Allocation Deallocation
+ static void *Allocate(const INT32 inSize, const CHAR *inType, const CHAR *inFile,
+ const INT32 inLine, const BOOL inClear);
+ static void Free(void *inPointer);
+ static void *Reallocate(void *inPointer, const INT32 inNewSize, const CHAR *inNewType,
+ const CHAR *inFile, const INT32 inLine);
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryHeap.cpp b/src/system/Qt3DSMemoryHeap.cpp
new file mode 100644
index 0000000..4ab3617
--- /dev/null
+++ b/src/system/Qt3DSMemoryHeap.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemory.h"
+#include "Qt3DSMemoryHeap.h"
+#include "Qt3DSMemoryStatistics.h"
+#include "Qt3DSIStream.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Static Initialzation
+//==============================================================================
+CMemoryProbe CMemoryHeap::s_Probe;
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+CMemoryHeap::TMemoryReport CMemoryHeap::s_MemoryReport;
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+//==============================================================================
+/**
+ * Allocate a chunk of memory and potentially track it.
+ * @param inSize size of requested memory block, in bytes
+ * @param inDescription allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryHeap::Allocate(const INT32 inSize, const CHAR *inDescription, const CHAR *inFile,
+ const INT32 inLine)
+{
+ // Always track stats and trigger snapshot if this is a new record
+ s_Probe.Allocate(inSize);
+
+ // Check if we are exceeding the max memory limit
+ if (Q3DStudio_MEMORY_LIMIT > 0
+ && s_Probe.GetBytes(Q3DStudio::MEMSCOPE_GLOBAL, Q3DStudio::MEMVALUE_CURRENT)
+ > Q3DStudio_MEMORY_LIMIT) {
+ qCCritical (qt3ds::OUT_OF_MEMORY)
+ << "Q3DStudio_MEMORY_UNIT exceeded " << Q3DStudio_MEMORY_LIMIT;
+ Q3DStudio_ASSERT(false);
+ }
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ void *theAllocatedPtr = CMemory::Malloc()(static_cast<const size_t>(inSize));
+ if (s_MemoryReport.GetCount() < s_MemoryReport.GetCapacity()) {
+ SReportEntry theEntry = { theAllocatedPtr, inSize, inDescription, inFile, inLine };
+ s_MemoryReport.Push(theEntry);
+ } else {
+ static BOOL s_FullWarning = false;
+ if (!s_FullWarning) {
+ qCWarning (qt3ds::TRACE_INFO) << "HeapTracker full. "
+ << "Please increase Q3DStudio_MEMORY_HEAPTRACKINGSIZE("
+ << Q3DStudio_MEMORY_HEAPTRACKINGSIZE << ") "
+ << "to track all allocation and tune your pools to avoid "
+ << "hitting the heap.";
+ s_FullWarning = true;
+ }
+ }
+ return theAllocatedPtr;
+#else
+ Q3DStudio_UNREFERENCED_PARAMETER(inLine);
+ Q3DStudio_UNREFERENCED_PARAMETER(inFile);
+ Q3DStudio_UNREFERENCED_PARAMETER(inDescription);
+
+ return CMemory::Malloc()(static_cast<const size_t>(inSize));
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+//==============================================================================
+/**
+ * Free a block of memory allocated using CMemoryHeap::Allocate
+ * @param inPointer pointer given in a previous allocation
+ * @param inSize size of given memory block, in bytes
+ */
+void CMemoryHeap::Free(void *inPointer, INT32 inSize)
+{
+ // No-Op on NULL
+ if (!inPointer)
+ return;
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ RemoveReport(inPointer);
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ s_Probe.Free(inSize);
+ return CMemory::Free()(inPointer);
+}
+
+//==============================================================================
+/**
+ * Re-allocate an existing chunk of memory and potentially track it.
+ * @param inPointer pointer given in a previous allocation
+ * @param inOldSize size of current memory block, in bytes
+ * @param inNewSize size of requested memory block, in bytes
+ * @param inNewDescription allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryHeap::Reallocate(void *inPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewDescription, const CHAR *inFile, const INT32 inLine)
+{
+ // Make sure this isn't a new malloc
+ if (!inPointer)
+ return Allocate(inNewSize, inNewDescription, inFile, inLine);
+
+ // Always track stats and record new high if it's a record
+ s_Probe.Allocate(inNewSize);
+ s_Probe.Free(inOldSize);
+
+ // Check if we are exceeding the max memory limit
+ Q3DStudio_ASSERT(Q3DStudio_MEMORY_LIMIT == 0
+ ? true
+ : s_Probe.GetBytes(Q3DStudio::MEMSCOPE_GLOBAL, Q3DStudio::MEMVALUE_CURRENT)
+ < Q3DStudio_MEMORY_LIMIT);
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ RemoveReport(inPointer);
+
+ void *theReallocatedPtr = CMemory::Realloc()(inPointer, static_cast<const size_t>(inNewSize));
+
+ SReportEntry theEntry = { theReallocatedPtr, inNewSize, inNewDescription, inFile, inLine };
+ s_MemoryReport.Push(theEntry);
+
+ return theReallocatedPtr;
+#else
+ return CMemory::Realloc()(inPointer, static_cast<const size_t>(inNewSize));
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieves memory info about a particular allocation
+ * @param inPointer allocated memory
+ * @return SMemoryHeapReportEntry* memory report
+ */
+CMemoryHeap::SReportEntry *CMemoryHeap::FindReport(void *inPointer)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inPointer);
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ INT32 theEnd = s_MemoryReport.GetCount();
+ for (INT32 theIndex = 0; theIndex < theEnd; ++theIndex)
+ if (s_MemoryReport[theIndex].m_AllocatedPointer == inPointer)
+ return &s_MemoryReport[theIndex];
+
+ Q3DStudio_ASSERT(false);
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ return NULL;
+}
+
+//==============================================================================
+/**
+ * Removes memory info due to a deallocation.
+ * @param inPointer allocated memory
+ */
+void CMemoryHeap::RemoveReport(void *inPointer)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inPointer);
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ INT32 theEnd = s_MemoryReport.GetCount();
+ for (INT32 theIndex = 0; theIndex < theEnd; ++theIndex) {
+ if (s_MemoryReport[theIndex].m_AllocatedPointer == inPointer) {
+ s_MemoryReport.Remove(theIndex);
+ return;
+ }
+ }
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+//==============================================================================
+/**
+ * The memory probe records basic heap activity
+ * @return reference to probe
+ */
+CMemoryProbe &CMemoryHeap::GetProbe()
+{
+ return s_Probe;
+}
+
+//==============================================================================
+/**
+ * The report records all heap activity
+ * @return pointer to report if tracking is on, or NULL
+ */
+CMemoryHeap::TMemoryReport *CMemoryHeap::GetReport()
+{
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ return &s_MemoryReport;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryHeap.h b/src/system/Qt3DSMemoryHeap.h
new file mode 100644
index 0000000..ba7c130
--- /dev/null
+++ b/src/system/Qt3DSMemoryHeap.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryProbe.h"
+#include "Qt3DSFixedArray.h"
+#include "Qt3DSMemorySettings.h"
+
+//==============================================================================
+/**
+ * Low level entry points to the heap.
+ *
+ * Do not call these directly. Use Q3DStudio_new or Q3DStudio_allocate instead since
+ * those use the pools.
+ * @see CMemoryHeap
+ */
+#define Q3DStudio_heap_allocate(size, desc) \
+ Q3DStudio::CMemoryHeap::Allocate(size, desc, __FILE__, __LINE__)
+#define Q3DStudio_heap_reallocate(ptr, oldsize, newsize, newdesc) \
+ Q3DStudio::CMemoryHeap::Reallocate(ptr, oldsize, newsize, newdesc, __FILE__, _LINE__)
+#define Q3DStudio_heap_free(ptr, size) Q3DStudio::CMemoryHeap::Free(ptr, size)
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class IStream;
+
+//==============================================================================
+/**
+ * Last memory interface before calls to memory callbacks or OS malloc.
+ *
+ * First of all, don't call this class directy. Use the macros
+ * Q3DStudio_heap_allocate and Q3DStudio_heap_free instead since they fill out file,
+ * line and function parameters for the tracking system.
+ *
+ * This is the single exit point for all heap memory allocations. Change this
+ * code to redirect memory to your own subsystems or add more tracking code to
+ * measure memory usage. Note however that most memory requests during runtime
+ * will never reach this point since memory pools will handle those requests.
+ * Large memory requests and emergency scenarios will still end up here.
+ *
+ * @note This class contains the only three real memory calls in Runtime.
+ */
+class CMemoryHeap
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// Simple memory log entry
+ struct SReportEntry
+ {
+ const void *m_AllocatedPointer; ///< allocated pointer
+ INT32 m_Size; ///< size in bytes
+ const CHAR *m_Description; ///< simple description
+ const CHAR *m_File; ///< filename
+ INT32 m_Line; ///< line number
+ };
+
+ //==============================================================================
+ // Typedefs
+ //==============================================================================
+public:
+ typedef CFixedArray<SReportEntry, Q3DStudio_MEMORY_HEAPTRACKINGSIZE> TMemoryReport;
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static CMemoryProbe s_Probe; ///< Light overall allocation statistics
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ static TMemoryReport s_MemoryReport; ///< Storage for memory logs
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Allocation/Deallocation
+ static void *Allocate(const INT32 inSize, const CHAR *inDescription, const CHAR *inFile,
+ const INT32 inLine);
+ static void Free(void *inPointer, INT32 inSize);
+ static void *Reallocate(void *inPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewDescription, const CHAR *inFile, const INT32 inLine);
+
+public: // Statistics
+ static CMemoryProbe &GetProbe();
+ static TMemoryReport *GetReport();
+
+protected: // Low level memory overview
+ static SReportEntry *FindReport(void *inPointer);
+ static void RemoveReport(void *inPointer);
+
+public: // Report request
+ static void Report(IStream *inStream = NULL);
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryManager.cpp b/src/system/Qt3DSMemoryManager.cpp
new file mode 100644
index 0000000..a1ace59
--- /dev/null
+++ b/src/system/Qt3DSMemoryManager.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemory.h"
+#include "Qt3DSMemoryManager.h"
+#include "Qt3DSMemoryHeap.h"
+#include "Qt3DSMemoryProbe.h"
+#include "Qt3DSMemoryTracker.h"
+#include "Qt3DSMemoryStatistics.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Create a new empty memory pool manager.
+ *
+ * The manager must be initialized before use or it will forward all requests
+ * to the heap.
+ */
+CMemoryManager::CMemoryManager()
+{
+ // Set default allocations functions if they are not already set
+ if (NULL == CMemory::Malloc())
+ CMemory::SetMemoryFunctions(&malloc, &free, &realloc);
+
+ CMemoryStatistics::AddManager(this);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Q3DStudio_memset(m_Histogram, 0, sizeof(m_Histogram));
+ CMemoryStatistics::Overhead() += sizeof(m_Histogram);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Create a new initialized memory pool manager.
+ *
+ * @param inName short description of manager used in tracker
+ * @param inChunkSize array of values describing the chunk size of each pool
+ * @param inChunkCount array of values describing the number of chunks in each pool
+ */
+CMemoryManager::CMemoryManager(const CHAR *inName,
+ const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT])
+{
+ // Set default allocations functions if they are not already set
+ if (NULL == CMemory::Malloc())
+ CMemory::SetMemoryFunctions(&malloc, &free, &realloc);
+
+ CMemoryStatistics::AddManager(this);
+ Initialize(inName, inChunkSize, inChunkCount);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Q3DStudio_memset(m_Histogram, 0, sizeof(m_Histogram));
+ CMemoryStatistics::Overhead() -= sizeof(m_Histogram);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Release the memory manager and all owned pools.
+ *
+ * Nobody better point to memory in these pool because the it will be
+ * invalid after this.
+ */
+CMemoryManager::~CMemoryManager()
+{
+ CMemoryStatistics::RemoveManager(this);
+ Release();
+}
+
+//==============================================================================
+/**
+ * Configure the pool manager into separate pools of different chunk sizes.
+ *
+ * The chunk size array has to be increasing values such as:
+ * inChunkSize = { 8, 16, 32, 64, 96, 128, 256, 512, 1024 }
+ * but count doesn't:
+ * inChunkCount = { 500, 200, 1000, 200, 200, 100, 250, 50, 20 }
+ *
+ * The global memory manager settings are initialized in AKMemory.h
+ *
+ * @param inName short description of manager used in tracker
+ * @param inChunkSize array of Q3DStudio_MEMORY_POOLCOUNT values describing the chunk size
+ *of each pool
+ * @param inChunkCount array of Q3DStudio_MEMORY_POOLCOUNT values describing the number of
+ *chunks in each pool
+ */
+void CMemoryManager::Initialize(const CHAR *inName,
+ const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT])
+{
+ // Don't initialize more than once
+ Q3DStudio_ASSERT(m_Pool[0].GetChunkCount() == 0);
+ Q3DStudio_sprintf(m_Name, sizeof(m_Name), "%s", inName);
+
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ // Make sure pool are aligned to Q3DStudio_MEMORY_ALIGNMENT or smaller than
+ // Q3DStudio_MEMORY_ALIGNMENT
+ Q3DStudio_ASSERT(inChunkSize[thePoolIndex] < Q3DStudio_MEMORY_ALIGNMENT
+ || (inChunkSize[thePoolIndex] % Q3DStudio_MEMORY_ALIGNMENT) == 0);
+ m_Pool[thePoolIndex].Initialize(inName, inChunkSize[thePoolIndex],
+ inChunkCount[thePoolIndex]);
+ }
+}
+
+//==============================================================================
+/**
+ * Release all the memory allocated in Initialize - essentially "uninitialize".
+ */
+void CMemoryManager::Release()
+{
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ m_Pool[thePoolIndex].Release();
+}
+
+//==============================================================================
+// ALLOCATION AND DEALLOCATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Fetch a new chunk of memory from the smallest pool possible
+ * @param inSize size of requested memory block, in bytes
+ * @param inType allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryManager::Allocate(INT32 inSize, const CHAR *inType, const CHAR *inFile,
+ const INT32 inLine)
+{
+ Q3DStudio_ASSERT(inSize >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Histogram[Q3DStudio_min<INT32>(inSize, 511)].Add(1);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ inSize += sizeof(CMemoryTracker::SMemoryInfo); // make room for SMemoryInfo
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ // Find the smallest pool that fits
+ void *thePointer = NULL;
+ INT32 thePoolIndex = 0;
+ while (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ // Does this pool fit?
+ if (inSize <= m_Pool[thePoolIndex].GetChunkSize()) {
+ thePointer = m_Pool[thePoolIndex].Allocate();
+ break;
+ }
+ ++thePoolIndex;
+ }
+
+ // // Record the amount of wasted bytes in this chunk
+ if (thePointer) {
+ // Basic tracking
+ m_ManagerData.m_Aligned.Allocate(inSize);
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_PoolData[thePoolIndex].m_Aligned.Allocate(inSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+ // If not, we go to the heap for now.
+ else {
+ // REFACTOR: Use the next pool size up instead?
+ thePointer = CMemoryHeap::Allocate(inSize, inType, inFile, inLine);
+ m_ManagerData.m_Overflow.Allocate(inSize);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ if (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT)
+ m_PoolData[thePoolIndex].m_Overflow.Allocate(
+ inSize); // Heap allocation due to full memory pool
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ CMemoryTracker::SMemoryInfo *theMemoryInfo =
+ reinterpret_cast<CMemoryTracker::SMemoryInfo *>(thePointer);
+
+ theMemoryInfo->m_DogTag = CMemoryTracker::TRACKER_DOGTAG;
+ theMemoryInfo->m_Line = static_cast<INT16>(inLine);
+ theMemoryInfo->m_Size = static_cast<INT16>(inSize - sizeof(CMemoryTracker::SMemoryInfo));
+ theMemoryInfo->m_File = inFile;
+ theMemoryInfo->m_Type = inType;
+
+ m_LineTracker.Remember(theMemoryInfo);
+ thePointer = reinterpret_cast<CMemoryTracker::SMemoryInfo *>(thePointer) + 1;
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ return thePointer;
+}
+
+//==============================================================================
+/**
+ * Release a chunk of memory.
+ * @param inPointer pointer to memory to be reused
+ * @param inSize size of the memory we are releasing, in bytes
+ */
+void CMemoryManager::Free(void *inPointer, INT32 inSize)
+{
+ if (!inPointer)
+ return;
+
+ Q3DStudio_ASSERT(inSize >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Histogram[Q3DStudio_min<INT32>(inSize, 511)].Delete(1);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ inPointer = reinterpret_cast<CMemoryTracker::SMemoryInfo *>(inPointer) - 1;
+ m_LineTracker.Forget(reinterpret_cast<CMemoryTracker::SMemoryInfo *>(inPointer));
+ inSize += sizeof(CMemoryTracker::SMemoryInfo);
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ // Did we get a valid pool?
+ INT32 thePoolIndex = FetchPoolIndex(inPointer);
+ if (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ m_Pool[thePoolIndex].Free(inPointer);
+ m_ManagerData.m_Aligned.Free(inSize);
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_PoolData[thePoolIndex].m_Aligned.Free(inSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ } else {
+ CMemoryHeap::Free(inPointer, inSize);
+ m_ManagerData.m_Overflow.Free(inSize);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ if (inSize <= m_Pool[Q3DStudio_MEMORY_POOLCOUNT - 1].GetChunkSize())
+ for (thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ if (inSize <= m_Pool[thePoolIndex].GetChunkSize()) {
+ m_PoolData[thePoolIndex].m_Overflow.Free(inSize);
+ // This is driving me crazy -CN.
+ // Q3DStudio_ASSERT( m_PoolData[thePoolIndex].m_Overflow.GetCalls(
+ // MEMSCOPE_GLOBAL, MEMVALUE_CURRENT ) >= 0 );
+ break;
+ }
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ }
+}
+
+//==============================================================================
+/**
+ * Grow the existing memory allocated
+ *
+ * @param inOldPointer pointer given in a previous allocation
+ * @param inOldSize size of current memory block, in bytes
+ * @param inNewSize size of requested memory block, in bytes
+ * @param inNewType allocation description such as class name or pool name
+ * @param inFile file name
+ * @param inFunction method name
+ * @param inLine line number
+ * @return void* a pointer to a memory block large enough to hold inSize bytes
+ */
+void *CMemoryManager::Reallocate(void *inOldPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewType, const CHAR *inFile, const INT32 inLine)
+{
+ Q3DStudio_ASSERT(inOldSize >= 0 && inNewSize >= 0);
+
+ // It's legal to pass NULL as old pointer to realloc
+ if (!inOldPointer)
+ return Allocate(inNewSize, inNewType, inFile, inLine);
+
+ if (inNewSize == 0) {
+ Free(inOldPointer, inOldSize);
+ return NULL;
+ }
+
+ // Get a new bigger chunk and transfer old data to it
+ void *thePointer = Allocate(inNewSize, inNewType, inFile, inLine);
+ Q3DStudio_memcpy(thePointer, inOldPointer, Q3DStudio_min(inOldSize, inNewSize));
+
+ // Release old data
+ Free(inOldPointer, inOldSize);
+ return thePointer;
+}
+
+//==============================================================================
+// IMPLEMENTATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Find the pool that owns the given pointer.
+ * @param inPointer pointer to memory to be found
+ * @return INT32 index of pool or Q3DStudio_MEMORY_POOLCOUNT if the chunk can't be found
+ */
+INT32 CMemoryManager::FetchPoolIndex(const void *inPointer)
+{
+ // Find pool that owns the pointer
+ INT32 thePoolIndex = 0;
+ while (thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT) {
+ if (m_Pool[thePoolIndex].OwnsChunk(inPointer))
+ return thePoolIndex;
+ ++thePoolIndex;
+ }
+
+ return Q3DStudio_MEMORY_POOLCOUNT;
+}
+
+//==============================================================================
+// STATISTICS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Return the text identifier of the manager
+ * @return the name, max 32 bytes long
+ */
+const CHAR *CMemoryManager::GetName()
+{
+ return m_Name;
+}
+
+//==============================================================================
+/**
+ * Reset all probe statistics
+ */
+void CMemoryManager::Reset()
+{
+ m_ManagerData.m_Aligned.Reset();
+ m_ManagerData.m_Overflow.Reset();
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ m_Pool[thePoolIndex].GetProbe().Reset();
+ m_PoolData[thePoolIndex].m_Aligned.Reset();
+ m_PoolData[thePoolIndex].m_Overflow.Reset();
+ }
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieve a particular memory pool
+ * @param inPoolIndex index of the pool
+ * @return SPoolData& is a reference to the indicated pool data
+ */
+CMemoryPool &CMemoryManager::GetPool(const INT32 inPoolIndex)
+{
+ Q3DStudio_ASSERT(inPoolIndex < Q3DStudio_MEMORY_POOLCOUNT && inPoolIndex >= 0);
+ return m_Pool[inPoolIndex];
+}
+
+//==============================================================================
+/**
+ * Retrieve a particular memory pool
+ * @param inPoolIndex index of the pool
+ * @return SPoolData& is a reference to the indicated pool data
+ */
+CMemoryManager::SPoolData *CMemoryManager::GetPoolData(const INT32 inPoolIndex)
+{
+ Q3DStudio_UNREFERENCED_PARAMETER(inPoolIndex);
+ Q3DStudio_ASSERT(inPoolIndex < Q3DStudio_MEMORY_POOLCOUNT && inPoolIndex >= 0);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ return m_PoolData + inPoolIndex;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+//==============================================================================
+/**
+ * Retrieve the number of bytes that were allocated on the heap
+ * @return CMemoryProbe as the heap statistics
+ */
+CMemoryManager::SPoolData &CMemoryManager::GetManagerData()
+{
+ return m_ManagerData;
+}
+
+//==============================================================================
+/**
+ * Sum the high level statistics of all the pools.
+ * @return CMemoryProbe as the statistics, calculated on the spot
+ */
+CMemoryProbe CMemoryManager::GetProbe()
+{
+ CMemoryProbe theProbe;
+#if Q3DStudio_MEMORY_POOLTRACKING
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex)
+ theProbe.Combine(m_Pool[thePoolIndex].GetProbe());
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ return theProbe;
+}
+
+//==============================================================================
+/**
+ * Fetch the tracker if enabled by setting Q3DStudio_MEMORY_LINETRACKING
+ * @return CMemoryTracker pointer or NULL
+ */
+CMemoryTracker *CMemoryManager::GetLineTracker()
+{
+#if Q3DStudio_MEMORY_LINETRACKING
+ return &m_LineTracker;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_LINETRACKING
+}
+
+//==============================================================================
+/**
+ * Fetch the histogram if enabled by setting Q3DStudio_MEMORY_HISTOGRAM.
+ * The histogram counts all requested allocations of the specific size.
+ * @return UINT16 array of 512 values, or NULL
+ */
+const CMemoryProbe::SValue *CMemoryManager::GetHistogram()
+{
+#if Q3DStudio_MEMORY_POOLTRACKING
+ return m_Histogram;
+#else
+ return NULL;
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryManager.h b/src/system/Qt3DSMemoryManager.h
new file mode 100644
index 0000000..fa54fce
--- /dev/null
+++ b/src/system/Qt3DSMemoryManager.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryPool.h"
+#include "Qt3DSMemoryProbe.h"
+#include "Qt3DSMemoryTracker.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class CMemoryTracker;
+
+//==============================================================================
+/**
+ * Allocation switch-board forwarding requests to pools.
+ *
+ * This is a memory pool hub acting as a complete heap replacement. The number
+ * of pools is hardcoded in Q3DStudio_MEMORY_POOLCOUNT but can be changed with a
+ * recompile. The main manager is created in AKMemory and is preconfigured to
+ * be generous with memory. Tune these values to match your title since
+ * unused chunks are wasteful.
+ *
+ * @note A pool manager survives fine even when not initialized. In this state
+ * it simply forwards each request to the CMemoryHeap. This setup is intentional
+ * to enable the default manager to survive long enough to allow future runtime
+ * initialization based on complexity of the level or presentation being loaded.
+ */
+class CMemoryManager
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// External pool usage information
+ struct SPoolData
+ {
+ CMemoryProbe
+ m_Aligned; ///< Exact sum of memory use (28byte struct in 32byte pool is still 28 here)
+ CMemoryProbe m_Overflow; ///< Failed memory allocation because the pool was full
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ CHAR m_Name[32]; ///< Manager identifier for statistics
+ CMemoryPool m_Pool[Q3DStudio_MEMORY_POOLCOUNT]; ///< Actual pool memory objects
+ SPoolData m_ManagerData; ///< Track allocations forwarded to heap because they were too large
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ SPoolData
+ m_PoolData[Q3DStudio_MEMORY_POOLCOUNT]; ///< Trace pools of different sizes with their usage
+ CMemoryProbe::SValue
+ m_Histogram[512]; ///< Allocation histogram if active using Q3DStudio_MEMORY_HEAPTRACKING
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+#if Q3DStudio_MEMORY_LINETRACKING
+ CMemoryTracker
+ m_LineTracker; ///< Line allocation tracker if active using Q3DStudio_MEMORY_LINETRACKING
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CMemoryManager();
+ CMemoryManager(const CHAR *inName, const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT]);
+ ~CMemoryManager();
+
+public: // Initialization
+ void Initialize(const CHAR *inName, const INT32 inChunkSize[Q3DStudio_MEMORY_POOLCOUNT],
+ const INT32 inChunkCount[Q3DStudio_MEMORY_POOLCOUNT]);
+ void Release();
+
+public: // Allocation and Deallocation
+ void *Allocate(INT32 inSize, const CHAR *inType, const CHAR *inFile, const INT32 inLine);
+ void Free(void *inOldPointer, INT32 inSize);
+ void *Reallocate(void *inOldPointer, const INT32 inOldSize, const INT32 inNewSize,
+ const CHAR *inNewType, const CHAR *inFile, const INT32 inLine);
+
+protected: // Implementation
+ INT32 FetchPoolIndex(const void *inPointer);
+
+public: // Statistics
+ void Reset();
+ const CHAR *GetName();
+ CMemoryPool &GetPool(const INT32 inPoolIndex);
+ SPoolData *GetPoolData(const INT32 inPoolIndex);
+ SPoolData &GetManagerData();
+ CMemoryProbe GetProbe();
+ CMemoryTracker *GetLineTracker();
+ const CMemoryProbe::SValue *GetHistogram();
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryPool.cpp b/src/system/Qt3DSMemoryPool.cpp
new file mode 100644
index 0000000..44545d4
--- /dev/null
+++ b/src/system/Qt3DSMemoryPool.cpp
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryPool.h"
+#include "Qt3DSMemoryHeap.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Create a new memory pool.
+ *
+ */
+CMemoryPool::CMemoryPool()
+ : m_ChunkSize(0)
+ , m_ChunkCount(0)
+ , m_Ceiling(NULL)
+ , m_Memory(NULL)
+ , m_Top(NULL)
+ , m_Hole(NULL)
+{
+ m_Description[0] = '\0';
+}
+
+//==============================================================================
+/**
+ * Release the memory pool.
+ *
+ * Nobody better point to this pool because it's illegal after this.
+ * We could blast the memory in debug mode to trigger bugs early but most
+ * compilers already do this.
+ */
+CMemoryPool::~CMemoryPool()
+{
+ Release();
+}
+
+//==============================================================================
+/**
+ * Configure the memory pool.
+ *
+ * The pool will allocate inChunkSize * inChunkCount bytes of memory from
+ * the heap using Q3DStudio_new, aligned on 4 byte boundaries.
+ *
+ * @param inName short description of pool - used in tracker
+ * @param inChunkSize size in bytes of each memory block, aka chunk
+ * @param inChunkCount number of chunks the pool holds
+ */
+void CMemoryPool::Initialize(const CHAR *inName, const INT32 inChunkSize, const INT32 inChunkCount)
+{
+ Q3DStudio_ASSERT(!m_Memory);
+
+ // Round up chunk size to the next even pointer size
+ // It needs to be at least pointer size to store the hole linked list
+ INT32 theRoundedChunkSize =
+ static_cast<INT32>(((inChunkSize + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *));
+
+ // Create pool description
+ Q3DStudio_sprintf(m_Description, sizeof(m_Description), "POOL: %s(%dx%d)", inName,
+ theRoundedChunkSize, inChunkCount);
+
+ // Reserve memory pool
+ m_ChunkSize = theRoundedChunkSize;
+ m_ChunkCount = inChunkCount;
+ m_Memory = reinterpret_cast<INT8 *>(
+ Q3DStudio_heap_allocate(m_ChunkSize * m_ChunkCount, m_Description));
+ m_Top = m_Memory;
+ m_Ceiling = m_Memory + m_ChunkSize * m_ChunkCount;
+}
+
+//==============================================================================
+/**
+ * Release all the memory allocated in Initialize - essentially "uninitialize".
+ */
+void CMemoryPool::Release()
+{
+ Q3DStudio_heap_free(m_Memory, m_ChunkSize * m_ChunkCount);
+
+ m_ChunkSize = 0, m_ChunkCount = 0;
+ m_Ceiling = NULL;
+ m_Memory = NULL;
+ m_Top = NULL;
+ m_Hole = NULL;
+}
+
+//==============================================================================
+// ALLOCATION AND DEALLOCATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Fetch a new chunk of memory.
+ *
+ * If there is a pool hole we use that, otherwise feed of the head.
+ * Every alloction is tracked in m_Statistics.
+ * @return a pointer to inChunkSize bytes of usable memory
+ */
+void *CMemoryPool::Allocate()
+{
+ if (m_Hole)
+ return PopHole();
+ else
+ return UseTop();
+}
+
+//==============================================================================
+/**
+ * Release a chunk of memory and track changes in statistics
+ * @param inChunk a pointer to memory to be reused
+ */
+void CMemoryPool::Free(void *inChunk)
+{
+ Q3DStudio_ASSERT(OwnsChunk(inChunk));
+ PushHole(inChunk);
+}
+
+//==============================================================================
+/**
+ * Verify that a pointer is owned by a specific pool
+ * @param inChunk a pointer to be checked
+ * @return BOOL true if the chunk is owned by this pool
+ */
+BOOL CMemoryPool::OwnsChunk(const void *inChunk) const
+{
+#ifdef _DEBUG
+ // Scan all holes to prevent double releasing memory
+ if (!(inChunk >= m_Ceiling || inChunk < m_Memory)) {
+ // No freeing anything above the top?
+ Q3DStudio_ASSERT(inChunk < m_Top);
+
+ // Not freeing any holes?
+ void *theHoleChunk = m_Hole;
+ while (theHoleChunk) {
+ Q3DStudio_ASSERT(inChunk != theHoleChunk);
+ theHoleChunk = reinterpret_cast<void *>(*reinterpret_cast<size_t *>(theHoleChunk));
+ }
+ }
+#endif // DEBUG
+
+ return !(inChunk >= m_Ceiling || inChunk < m_Memory);
+}
+
+//==============================================================================
+/**
+ * Quick check to see if there are chunks available
+ * @return BOOL true if the pool has available chunks
+ */
+BOOL CMemoryPool::IsFull() const
+{
+ return m_Hole == NULL && GetFreeTops() == 0;
+}
+
+//==============================================================================
+/**
+ * Get the total number of free chunks in this pool.
+ * @return INT32 is the nunber of free chunks
+ */
+INT32 CMemoryPool::GetFreeChunks() const
+{
+ return GetFreeTops() + GetFreeHoles();
+}
+
+//==============================================================================
+/**
+ * Get the number of holes in this pool.
+ * @return INT32 is the nunber of holes
+ */
+INT32 CMemoryPool::GetFreeHoles() const
+{
+ INT32 theHoleCounter = 0;
+ void *theHoleChunk = m_Hole;
+
+ // Walk the hole list until there are no more holes
+ while (theHoleChunk) {
+ theHoleChunk = reinterpret_cast<void *>(*reinterpret_cast<size_t *>(theHoleChunk));
+ ++theHoleCounter;
+ }
+
+ return theHoleCounter;
+}
+
+//==============================================================================
+/**
+ * Get the number of chunks left at the top.
+ * @return INT32 is the nunber of continous chunks at the top
+ */
+INT32 CMemoryPool::GetFreeTops() const
+{
+ return static_cast<INT32>((m_Ceiling - m_Top)) / m_ChunkSize;
+}
+
+//==============================================================================
+// IMPLEMENTATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Return a chunch from the top.
+ *
+ * The top is only used if no pool holes are available.
+ * @return a pointer to the chunk at the top
+ */
+void *CMemoryPool::UseTop()
+{
+ // Out of memory?
+ // This is not assert since it may happen during normal runtime.
+ if (m_Top >= m_Ceiling)
+ return NULL;
+
+ void *theChunk = m_Top;
+ m_Top += m_ChunkSize;
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Probe.Allocate(m_ChunkSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ return theChunk;
+}
+
+//==============================================================================
+/**
+ * Add a new hole to the pool list.
+ *
+ * The holes are used in a stack-like fashion so the chunk we push in most
+ * recently is the first one to be returned next New call.
+ * The holes are linked by using the first four bytes to point to the next
+ * chunk. We are hijacking them to create a linked list of free chunks.
+ * @param inChunk is the just deleted chunk
+ */
+void CMemoryPool::PushHole(void *inChunk)
+{
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Probe.Free(m_ChunkSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+ // Set the pushed chunk to be the new top hole after we
+ // link the content of the new chunk to the last top.
+ *reinterpret_cast<size_t *>(inChunk) = reinterpret_cast<size_t>(m_Hole);
+ m_Hole = inChunk;
+}
+
+//==============================================================================
+/**
+ * Get the topmost hole as our chunk.
+ *
+ * Return the latest hole and relink the list of holes to the top.
+ * @return void* is the most recently deleted chunk
+ */
+void *CMemoryPool::PopHole()
+{
+ Q3DStudio_ASSERT(m_Hole);
+
+ // Return the old hole as our new chunk after we
+ // set the hole to the second hole in the list.
+ void *theChunk = m_Hole;
+ m_Hole = reinterpret_cast<void *>(*reinterpret_cast<size_t *>(m_Hole));
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ m_Probe.Allocate(m_ChunkSize);
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+ return theChunk;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryPool.h b/src/system/Qt3DSMemoryPool.h
new file mode 100644
index 0000000..01b2e41
--- /dev/null
+++ b/src/system/Qt3DSMemoryPool.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryProbe.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Managed memory allocation using fixed-size chunks.
+ *
+ * The pool class implements a generic algorithm that favors reusing recently
+ * used memory chunks instead of returning memory continously. Yet, a fresh
+ * pool will always return chunks positioned side by side.
+ *
+ * If a chunk is freed it will be the first to be returned next time a fresh
+ * chunk is new'ed. This makes the cache lines happier. Deleted chunks are
+ * maintained by linking to each other instead of being stored in a separate
+ * memory consuming array.
+ */
+class CMemoryPool
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ INT32 m_ChunkSize; ///< size in bytes of each chunk
+ INT32 m_ChunkCount; ///< number of chunks in pool
+
+ INT8 *m_Ceiling; ///< ceiling memory pointer
+ INT8 *m_Memory; ///< base memory pointer, INT8 for easy pointer arithemtic
+ INT8 *m_Top; ///< edge of free continous memory
+ void *m_Hole; ///< first dis-continous memory chunk if any
+
+ CMemoryProbe m_Probe; ///< call and byte data on pool usage
+ CHAR m_Description[32]; ///< short description of this pool
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CMemoryPool();
+ ~CMemoryPool();
+
+public: // Initialization
+ void Initialize(const CHAR *inName, const INT32 inChunkSize, const INT32 inChunkCount);
+ void Release();
+
+public: // Allocation and Deallocation
+ void *Allocate();
+ void Free(void *inChunk);
+ BOOL IsFull() const;
+ BOOL OwnsChunk(const void *inChunk) const;
+
+protected: // Implementation
+ void *UseTop();
+ void PushHole(void *inChunk);
+ void *PopHole();
+
+public: // Statistics and reports
+ INT32 GetFreeHoles() const;
+ INT32 GetFreeTops() const;
+ INT32 GetFreeChunks() const;
+ INT32 GetChunkSize() const { return m_ChunkSize; }
+ INT32 GetChunkCount() const { return m_ChunkCount; }
+ CMemoryProbe &GetProbe() { return m_Probe; }
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryProbe.cpp b/src/system/Qt3DSMemoryProbe.cpp
new file mode 100644
index 0000000..4e977ee
--- /dev/null
+++ b/src/system/Qt3DSMemoryProbe.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryProbe.h"
+#include "Qt3DSMemoryStatistics.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor - records its size with the statistics class
+ */
+CMemoryProbe::CMemoryProbe()
+{
+ CMemoryStatistics::Overhead() += sizeof(CMemoryProbe);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CMemoryProbe::~CMemoryProbe()
+{
+ CMemoryStatistics::Overhead() -= sizeof(CMemoryProbe);
+}
+
+//==============================================================================
+/**
+ * Track the number related to incrementing memory.
+ * @param inByteAmount amount of bytes being allocated
+ */
+void CMemoryProbe::Allocate(const INT32 inByteAmount)
+{
+ if (inByteAmount > 0) {
+ m_Calls[MEMSCOPE_RESET].Add(1);
+ m_Bytes[MEMSCOPE_RESET].Add(inByteAmount);
+
+ m_Calls[MEMSCOPE_GLOBAL].Add(1);
+ m_Bytes[MEMSCOPE_GLOBAL].Add(inByteAmount);
+ }
+}
+
+//==============================================================================
+/**
+ * Track the number related to incrementing memory.
+ * @param inByteAmount amount of bytes being deallocted
+ */
+void CMemoryProbe::Free(const INT32 inByteAmount)
+{
+ Q3DStudio_ASSERT(inByteAmount >= 0);
+ if (inByteAmount > 0) {
+ m_Calls[MEMSCOPE_RESET].Delete(1);
+ m_Bytes[MEMSCOPE_RESET].Delete(inByteAmount);
+
+ m_Calls[MEMSCOPE_GLOBAL].Delete(1);
+ m_Bytes[MEMSCOPE_GLOBAL].Delete(inByteAmount);
+ }
+}
+
+//==============================================================================
+/**
+ * Reset all local statistics. Global values are not reset.
+ */
+void CMemoryProbe::Reset()
+{
+ m_Calls[MEMSCOPE_RESET].Reset();
+ m_Bytes[MEMSCOPE_RESET].Reset();
+}
+
+//==============================================================================
+/**
+ * Helper method for adding statistics used by manager to add pool usage.
+ * @param inProbe is the stats being added
+ */
+void CMemoryProbe::Combine(const CMemoryProbe &inProbe)
+{
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS];
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES];
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK];
+ m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Calls[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT];
+
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_ADDS];
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_DELETES];
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_PEAK];
+ m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Bytes[MEMSCOPE_GLOBAL].m_Value[MEMVALUE_CURRENT];
+
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS];
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES];
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK];
+ m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Calls[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT];
+
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_ADDS];
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_DELETES];
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_PEAK];
+ m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT] +=
+ inProbe.m_Bytes[MEMSCOPE_RESET].m_Value[MEMVALUE_CURRENT];
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryProbe.h b/src/system/Qt3DSMemoryProbe.h
new file mode 100644
index 0000000..5f0844e
--- /dev/null
+++ b/src/system/Qt3DSMemoryProbe.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** 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 "Qt3DSMacros.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Memory Tracking Enums
+//==============================================================================
+
+/// Track a value - remembering peak and add/del count
+enum EMemoryValue {
+ MEMVALUE_ADDS = 0, ///< For example: allocation call count or bytes allocated
+ MEMVALUE_DELETES, ///< For example: free call count or bytes deallocated
+ MEMVALUE_PEAK, ///< Peak of the current value since the last reset
+ MEMVALUE_CURRENT, ///< Current count
+ MEMVALUECOUNT
+};
+
+/// Differentiate between full session (global) or since last reset (local)
+enum EMemoryScope {
+ MEMSCOPE_RESET = 0, ///< Since last reset
+ MEMSCOPE_GLOBAL, ///< Since process start
+ MEMSCOPECOUNT
+};
+
+//==============================================================================
+/**
+ * Memory allocation counter tracking bytes or calls.
+ *
+ * A probe instance can be placed to track either number of allocations
+ * or the bytes of each allocation. CMemoryManager and CMemoryHeap both
+ * record statistics using this class. 64 bytes.
+ */
+class CMemoryProbe
+{
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ //==============================================================================
+ /**
+ * Intelligent number that tracks current, peak, incr. and decr.
+ *
+ * This value remembers how the amount added, the amount deleted, the highest
+ * value, while keeping a current value. These are used by CMemoryProbe when
+ * tracking memory allocations.
+ */
+ struct SValue
+ {
+ // Fields
+ INT32 m_Value[MEMVALUECOUNT]; ///< Four aspects (add,del,current,peak) we are tracking
+
+ // Methods
+ SValue() { Reset(); }
+ void Reset()
+ {
+ m_Value[MEMVALUE_ADDS] = 0;
+ m_Value[MEMVALUE_DELETES] = 0;
+ m_Value[MEMVALUE_PEAK] = 0;
+ m_Value[MEMVALUE_CURRENT] = 0;
+ }
+
+ void Delete(INT32 inAmount)
+ {
+ Q3DStudio_ASSERT(inAmount >= 0);
+ m_Value[MEMVALUE_DELETES] += inAmount;
+ m_Value[MEMVALUE_CURRENT] -= inAmount;
+ }
+
+ void Add(INT32 inAmount)
+ {
+ Q3DStudio_ASSERT(inAmount >= 0);
+ m_Value[MEMVALUE_ADDS] += inAmount;
+ m_Value[MEMVALUE_CURRENT] += inAmount;
+ m_Value[MEMVALUE_PEAK] =
+ Q3DStudio_max(m_Value[MEMVALUE_PEAK], m_Value[MEMVALUE_CURRENT]);
+ }
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ SValue m_Calls[MEMSCOPECOUNT]; ///< Memory call count
+ SValue m_Bytes[MEMSCOPECOUNT]; ///< Memory allocation amount
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Constructor
+ CMemoryProbe();
+ ~CMemoryProbe();
+
+public: // Operations
+ void Reset();
+ void Allocate(const INT32 inByteAmount);
+ void Free(const INT32 inByteAmount);
+ void Combine(const CMemoryProbe &inProbe);
+
+public: // Accessors
+ INT32 GetCalls(const EMemoryScope inScope, const EMemoryValue inValue) const
+ {
+ return m_Calls[inScope].m_Value[inValue];
+ }
+ INT32 GetBytes(const EMemoryScope inScope, const EMemoryValue inValue) const
+ {
+ return m_Bytes[inScope].m_Value[inValue];
+ }
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemorySettings.h b/src/system/Qt3DSMemorySettings.h
new file mode 100644
index 0000000..5400242
--- /dev/null
+++ b/src/system/Qt3DSMemorySettings.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSTypes.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * GlobalMemoryManager constants
+ * NOTE THAT THESE NUMBERS BELOW SHOULD BE ADJUSTED TO FIT YOUR APPLICATION.
+ *
+ * See the Memory Management section in the documentation for guidelines
+ * on memory diagnostics that enable you to optimize these values:
+ */
+
+//==============================================================================
+// Memory Pool Configuration
+//==============================================================================
+
+#ifndef Q3DStudio_MEMORY_POOLCOUNT
+#define Q3DStudio_MEMORY_POOLCOUNT 12
+#endif // Q3DStudio_MEMORY_POOLCOUNT
+
+/// A memory pool has a chunk size that defines he size in bytes of each slot
+/// and a chunk count defining how many slots there are of that size.
+/// The pools below thus has 128 slots of 4 bytes, 256 slots of 8 bytes etc:
+const INT32 g_ChunkSize[Q3DStudio_MEMORY_POOLCOUNT] = { 4, 8, 16, 32, 48, 64,
+ 96, 128, 160, 256, 384, 640 };
+const INT32 g_ChunkCount[Q3DStudio_MEMORY_POOLCOUNT] = { 128, 256, 256, 1536, 128, 128,
+ 256, 64, 32, 32, 32, 32 };
+
+//==============================================================================
+// Memory Settings
+//==============================================================================
+
+/// Define the upper memory limit used by Runtime.
+/// 0 = unlimited
+#ifndef Q3DStudio_MEMORY_LIMIT
+#define Q3DStudio_MEMORY_LIMIT 0
+#endif // Q3DStudio_MEMORY_LIMIT
+
+// Pool sizes and diagnostics are aligned to the required boundary.
+#ifndef Q3DStudio_MEMORY_ALIGNMENT
+#define Q3DStudio_MEMORY_ALIGNMENT 8
+#endif // Q3DStudio_MEMORY_ALIGNMENT
+
+//==============================================================================
+// Memory Diagnostics
+//==============================================================================
+
+/// Note that the simple report is always on. (F1 in Quarterback)
+
+/// CMemoryHeap usage report. (F2 in Quarterback)
+/// Tracks large allocations such as pool buffers, managers and overflows.
+/// Not much overhead since most allocations should be intercepted by pools.
+#ifndef Q3DStudio_MEMORY_HEAPTRACKING
+#define Q3DStudio_MEMORY_HEAPTRACKING 0
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+/// Max number of 20 byte SReportEntry heap entries
+/// Increase this number if you get a log warning but you should really tune
+/// your memory pools to avoid hitting the heap.
+#ifndef Q3DStudio_MEMORY_HEAPTRACKINGSIZE
+#define Q3DStudio_MEMORY_HEAPTRACKINGSIZE 4000
+#endif // Q3DStudio_MEMORY_HEAPTRACKINGSIZE
+
+/// Invasive allocation tracker. (F3 in Quarterback)
+/// Track detailed memory usage per allocation through CMemoryManager by tracking
+/// every Runtime allocation, line by line using __FILE__ and __LINE__.
+/// Note that this adds a 16byte SMemoryInfo to each allocation and thus
+/// changes pool usage.
+/// === Do not tune pools with line tracking enabled! ===
+#ifndef Q3DStudio_MEMORY_LINETRACKING
+#define Q3DStudio_MEMORY_LINETRACKING 0
+#endif // Q3DStudio_MEMORY_LINETRACKING
+
+// Hashbin size of entries pointing to SMemoryInfo allocation headers
+#ifndef Q3DStudio_MEMORY_LINETRACKINGSIZE
+#define Q3DStudio_MEMORY_LINETRACKINGSIZE (128 * 1024)
+#endif // Q3DStudio_MEMORY_LINETRACKINGSIZE
+
+/// CMemoryManager pooled memory usage report. (F5-F8 in Quarterback)
+/// Track most used allocation sizes to tune pool sizes and count.
+/// Enabled by default since it allows tracking precise presentation
+/// memory usage without much of an overhead.
+/// It also includes a histogram when showing Reset data (F5,F6)
+#ifndef Q3DStudio_MEMORY_POOLTRACKING
+#ifdef _DEBUG
+#define Q3DStudio_MEMORY_POOLTRACKING 1
+#else
+#define Q3DStudio_MEMORY_POOLTRACKING 0
+#endif
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryStatistics.cpp b/src/system/Qt3DSMemoryStatistics.cpp
new file mode 100644
index 0000000..2f5eba0
--- /dev/null
+++ b/src/system/Qt3DSMemoryStatistics.cpp
@@ -0,0 +1,647 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSIStream.h"
+#include "Qt3DSMemoryStatistics.h"
+#include "Qt3DSMemoryTracker.h"
+#include "Qt3DSMemoryHeap.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Static Fields
+//==============================================================================
+INT32 CMemoryStatistics::s_Overhead = 0;
+CMemoryManager *CMemoryStatistics::s_PoolManagers[MANAGERCOUNT] = { NULL };
+
+//==============================================================================
+// REGISTRATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Add the manager from the static list done automatically on manager construction.
+ * @param inManager the manager we are beginning to track
+ */
+void CMemoryStatistics::AddManager(CMemoryManager *inManager)
+{
+ INT32 theIndex = 0;
+ while (s_PoolManagers[theIndex] && theIndex < MANAGERCOUNT - 1)
+ ++theIndex;
+
+ if (!s_PoolManagers[theIndex]) {
+ s_PoolManagers[theIndex] = inManager;
+ } else {
+ qCWarning(qt3ds::TRACE_INFO)
+ << "Could not add memory manager tracker. Limit: " << MANAGERCOUNT;
+ }
+}
+
+//==============================================================================
+/**
+ * Remove the manager from the static list done automatically on manager deletion.
+ * @param inManager the manager we are ceasing to track
+ */
+void CMemoryStatistics::RemoveManager(CMemoryManager *inManager)
+{
+ INT32 theIndex = 0;
+ while (inManager != s_PoolManagers[theIndex] && theIndex < MANAGERCOUNT - 1)
+ ++theIndex;
+
+ if (inManager == s_PoolManagers[theIndex])
+ s_PoolManagers[theIndex] = NULL;
+}
+
+//==============================================================================
+/**
+ * Read/write access to the static tracking field that keeps tab on how
+ * much memory we are spending _tracking_ memory.
+ * @return reference to the field tracking the overhead in bytes
+ */
+INT32 &CMemoryStatistics::Overhead()
+{
+ return s_Overhead;
+}
+
+//==============================================================================
+// OPERATION
+//==============================================================================
+
+//==============================================================================
+/**
+ * Reset all memory probes
+ */
+void CMemoryStatistics::Reset()
+{
+ qCInfo(qt3ds::TRACE_INFO) << "Resetting Memory Statistics";
+ CMemoryHeap::GetProbe().Reset();
+
+ for (INT32 theIndex = 0; theIndex < MANAGERCOUNT; ++theIndex)
+ if (s_PoolManagers[theIndex])
+ s_PoolManagers[theIndex]->Reset();
+}
+
+//==============================================================================
+// ACCESS
+//==============================================================================
+
+//==============================================================================
+/**
+ * Quick access to memory usage of the first memory manager.
+ * @param inPeak is true if you want the peak, false if you want the current state
+ * @return the current explict usage in bytes
+ */
+INT32 CMemoryStatistics::GetRequestedBytes(BOOL inPeak /*=false*/)
+{
+ Q3DStudio_ASSERT(s_PoolManagers[0]);
+
+ EMemoryValue theValue = inPeak ? MEMVALUE_PEAK : MEMVALUE_CURRENT;
+ CMemoryManager::SPoolData &theUsageData = s_PoolManagers[0]->GetManagerData();
+
+ return theUsageData.m_Aligned.GetBytes(MEMSCOPE_RESET, theValue)
+ + theUsageData.m_Overflow.GetBytes(MEMSCOPE_RESET, theValue);
+}
+
+//==============================================================================
+/**
+ * Quick access to heap usage.
+ * @param inPeak is true if you want the peak, false if you want the current state
+ * @return the current heap usage in bytes
+ */
+INT32 CMemoryStatistics::GetHeapBytes(BOOL inPeak /*=false*/)
+{
+ return Q3DStudio::CMemoryHeap::GetProbe().GetBytes(MEMSCOPE_RESET,
+ inPeak ? MEMVALUE_PEAK : MEMVALUE_CURRENT);
+}
+
+//==============================================================================
+/**
+ * Fill out a SFactSheet with memory statistics.
+ * @param outFacts is filled out with factoids showing the system state
+ * @param inPeak is true if you want the peak, false if you want the current state
+ * @param inGlobal is true if you want values since process start, false since last reset
+ */
+void CMemoryStatistics::GetFacts(SFactSheet &outFacts, BOOL inPeak /*= true*/,
+ BOOL inGlobal /*= true*/)
+{
+ INT32 thePresentationBytes = 0;
+ Q3DStudio_UNREFERENCED_PARAMETER(thePresentationBytes);
+ Q3DStudio_memset(&outFacts, 0, sizeof(SFactSheet));
+
+ // Translate flags to enumerations
+ EMemoryScope theScope = inGlobal ? MEMSCOPE_GLOBAL : MEMSCOPE_RESET;
+ EMemoryValue theValue = inPeak ? MEMVALUE_PEAK : MEMVALUE_CURRENT;
+
+ // Capture heap state
+ outFacts.m_HeapState.m_Bytes = CMemoryHeap::GetProbe().GetBytes(theScope, theValue);
+ outFacts.m_HeapState.m_Calls = CMemoryHeap::GetProbe().GetCalls(theScope, theValue);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ INT32 theTotalChunks = 0;
+ INT32 theTotalBytes = 0;
+
+ // Scan all registered pool managers
+ Q3DStudio_sprintf(outFacts.m_ManagerState.m_Name, 32, "All Managers");
+ for (INT32 theManagerIndex = 0; theManagerIndex < MANAGERCOUNT; ++theManagerIndex) {
+ CMemoryManager *theManager = s_PoolManagers[theManagerIndex];
+ SFactoid &theManagerFact = outFacts.m_Manager[theManagerIndex];
+ INT32 theManagerChunks = 0;
+ INT32 theManagerBytes = 0;
+
+ // Ignore empty managers
+ if (!theManager)
+ break;
+
+ // Scan each pool in the manager
+ Q3DStudio_sprintf(theManagerFact.m_Name, 32, " %s", theManager->GetName());
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT; ++thePoolIndex) {
+ CMemoryPool &thePool = theManager->GetPool(thePoolIndex);
+ CMemoryManager::SPoolData *thePoolData = theManager->GetPoolData(thePoolIndex);
+ Q3DStudio_ASSERT(thePoolData);
+
+ SFactoid &thePoolFact = outFacts.m_Pool[theManagerIndex][thePoolIndex];
+ INT32 theUsed = thePool.GetProbe().GetCalls(theScope, theValue);
+ INT32 theAlign = thePoolData->m_Aligned.GetBytes(theScope, theValue);
+
+ // Ignore empty pools
+ if (thePool.GetChunkCount() == 0)
+ break;
+
+ // Extract all the factoids
+ Q3DStudio_sprintf(thePoolFact.m_Name, 32, " %d: %4db x %4d", thePoolIndex,
+ thePool.GetChunkSize(), thePool.GetChunkCount());
+ thePoolFact.m_Bytes = thePool.GetChunkSize() * thePool.GetChunkCount();
+ thePoolFact.m_Calls = thePool.GetProbe().GetCalls(theScope, theValue);
+ thePoolFact.m_Used = 100 * theUsed / thePool.GetChunkCount();
+
+ thePoolFact.m_Align = 100;
+ if (theUsed > 0)
+ thePoolFact.m_Align = 100 * theAlign / (theUsed * thePool.GetChunkSize());
+ thePoolFact.m_Miss = thePoolData->m_Overflow.GetCalls(theScope, theValue);
+
+ thePresentationBytes += theAlign + thePoolData->m_Overflow.GetBytes(theScope, theValue);
+
+ theManagerFact.m_Bytes += thePoolFact.m_Bytes;
+ theManagerFact.m_Calls += thePoolFact.m_Calls;
+ theManagerFact.m_Used += theUsed;
+ theManagerFact.m_Align += theAlign;
+ theManagerFact.m_Miss += thePoolFact.m_Miss;
+
+ outFacts.m_ManagerState.m_Bytes += thePoolFact.m_Bytes;
+ outFacts.m_ManagerState.m_Calls += thePoolFact.m_Calls;
+ outFacts.m_ManagerState.m_Used += theUsed;
+ outFacts.m_ManagerState.m_Align += theAlign;
+ outFacts.m_ManagerState.m_Miss += thePoolFact.m_Miss;
+
+ theManagerChunks += thePool.GetChunkCount();
+ theManagerBytes += theUsed * thePool.GetChunkSize();
+ }
+
+ thePresentationBytes +=
+ theManager->GetManagerData().m_Overflow.GetBytes(theScope, theValue);
+
+ // Both the manager sub-total and grand-total need to track bytes separately
+ // since the percentages can't just be added or averaged. Those totals
+ // are instead weighted and this is the tracking math that does it.
+ theTotalChunks += theManagerChunks;
+ theTotalBytes += theManagerBytes;
+
+ theManagerFact.m_Used = 0;
+ if (theManagerChunks > 0)
+ theManagerFact.m_Used = 100 * theManagerFact.m_Used / theManagerChunks;
+
+ theManagerFact.m_Align = 100;
+ if (theManagerBytes > 0)
+ theManagerFact.m_Align = 100 * theManagerFact.m_Align / theManagerBytes;
+
+ CullHistogram(theManager->GetHistogram(), theValue, outFacts.m_Histogram[theManagerIndex]);
+ }
+
+ // Again this is the grand-total separate percentage computation that has
+ // to be done in the end when all sums have been added.
+ outFacts.m_ManagerState.m_Used = 0;
+ if (theTotalChunks > 0)
+ outFacts.m_ManagerState.m_Used = 100 * outFacts.m_ManagerState.m_Used / theTotalChunks;
+
+ outFacts.m_ManagerState.m_Align = 100;
+ if (theTotalBytes > 0)
+ outFacts.m_ManagerState.m_Align = 100 * outFacts.m_ManagerState.m_Align / theTotalBytes;
+
+#endif // Q3DStudio_MEMORY_POOLTRACKING
+
+ // return thePresentationBytes;
+}
+
+//==============================================================================
+/**
+ * Find the HISTOGRAMLIMIT highest performers in the histogram.
+ * @param inHistogram array of CMemoryManager::HISTOGRAMCOUNT values
+ * each showing the number of allocation of that bytesize
+ * @param outResults collects the highest points of the histogram
+ */
+void CMemoryStatistics::CullHistogram(const CMemoryProbe::SValue *inHistogram,
+ const EMemoryValue inValue,
+ SHistogramScore outResults[HISTOGRAMCOUNT])
+{
+ // Always clear even if there is no data
+ Q3DStudio_memset(outResults, 0, sizeof(SHistogramScore));
+
+ // Return quickly when no data
+ if (!inHistogram)
+ return;
+
+ // Scan full histogram
+ INT32 theLowestIndex = 0;
+ for (UINT16 theSize = 0; theSize < 512; ++theSize) {
+ // Is this count higher than the lowest recorded count?
+ if (inHistogram[theSize].m_Value[inValue] > outResults[theLowestIndex].m_Count) {
+ outResults[theLowestIndex].m_Count = inHistogram[theSize].m_Value[inValue];
+ outResults[theLowestIndex].m_Size = theSize;
+
+ // Find new low in high score
+ theLowestIndex = 0;
+ for (UINT16 theResult = 1; theResult < HISTOGRAMCOUNT; ++theResult)
+ if (outResults[theResult].m_Count < outResults[theLowestIndex].m_Count)
+ theLowestIndex = theResult;
+ }
+ }
+
+ // Sort histogram - brute force for now so don't call this all the time
+ ::qsort(outResults, 10, sizeof(SHistogramScore), CompareHistogram);
+}
+
+//==============================================================================
+/**
+ * Helper comparison function for CullHistogram
+ */
+int CMemoryStatistics::CompareHistogram(const void *arg1, const void *arg2)
+{
+ return reinterpret_cast<const SHistogramScore *>(arg2)->m_Count
+ - reinterpret_cast<const SHistogramScore *>(arg1)->m_Count;
+}
+
+//==============================================================================
+/**
+ * Helper comparison function for CMemoryStatistics::HeapReport
+ */
+int CMemoryStatistics::CompareHeap(const void *inEntry1, const void *inEntry2)
+{
+ return reinterpret_cast<const CMemoryHeap::SReportEntry *>(inEntry1)->m_Size
+ - reinterpret_cast<const CMemoryHeap::SReportEntry *>(inEntry2)->m_Size;
+}
+
+//==============================================================================
+// REPORTING
+//==============================================================================
+
+//==============================================================================
+/**
+ * Simple memory usage report covering both bytes allocated and call count.
+ * @param inStream the stream we are sending the report or NULL to use logger
+ */
+void CMemoryStatistics::SimpleReport(IStream *inStream /*=NULL*/)
+{
+ CHAR theReportBuffer[REPORTSIZE];
+ CMemoryProbe theProbe;
+
+ // Basic info is always available
+ Report(inStream, "\n --- RUNTIME SIMPLE MEMORY REPORT ---\n");
+
+ // Only the first manager is reported for now
+ Q3DStudio_ASSERT(s_PoolManagers[0]);
+ theProbe = s_PoolManagers[0]->GetManagerData().m_Aligned;
+ theProbe.Combine(s_PoolManagers[0]->GetManagerData().m_Overflow);
+ Report(inStream, "PRESENTATION: Current Peak Alloc Free\n");
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Global:%12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Reset: %12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+
+ // Overflow is memory not serviced by memory pools - removed to make the simple report...
+ // simpler
+ /* theProbe = s_PoolManagers[0]->GetManagerData( ).m_Overflow;
+ Report( inStream, "OVERFLOW:\n" );
+ Q3DStudio_sprintf( theReportBuffer, sizeof( theReportBuffer ),
+ "Global:%12ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)\n",
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_PEAK )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_PEAK ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_ADDS )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_ADDS ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_DELETES )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_DELETES ) );
+ Report( inStream, theReportBuffer );
+ Q3DStudio_sprintf( theReportBuffer, sizeof( theReportBuffer ), "Reset:
+ %12ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)%8ldk(%4ld)\n",
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_CURRENT ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_PEAK )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_PEAK ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_ADDS )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_ADDS ),
+ theProbe.GetBytes( MEMSCOPE_GLOBAL, MEMVALUE_DELETES )/1024,
+ theProbe.GetCalls( MEMSCOPE_GLOBAL, MEMVALUE_DELETES ) );
+ Report( inStream, theReportBuffer );*/
+
+ // All managers share the same heap
+ theProbe = CMemoryHeap::GetProbe();
+ Report(inStream, "HEAP:\n");
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Global:%12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_GLOBAL, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_GLOBAL, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "Reset: %12dk(%4d)%8dk(%4d)%8dk(%4d)%8dk(%4d)\n",
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_CURRENT) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_CURRENT),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_PEAK) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_PEAK),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_ADDS) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_ADDS),
+ theProbe.GetBytes(MEMSCOPE_RESET, MEMVALUE_DELETES) / 1024,
+ theProbe.GetCalls(MEMSCOPE_RESET, MEMVALUE_DELETES));
+ Report(inStream, theReportBuffer);
+
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer), "Tracking overhead: %dk\n",
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ (s_Overhead + sizeof(CMemoryHeap::TMemoryReport)) / 1024);
+#else
+ s_Overhead / 1024);
+#endif // Q3DStudio_MEMORY_HEAPTRACKING
+
+ Report(inStream, theReportBuffer);
+}
+
+//==============================================================================
+/**
+ * Output the memory report log.
+ *
+ * The is always watched by a CMemoryProbe that records all activity. Most
+ * individual allocations will not be recorded though since they are handled
+ * by memory pools.
+ *
+ * A probe records three axis of information (value, scope and call/bytes).
+ *
+ * # Value (current,peak,add,del) tracks the current value along with its
+ * peak value, and also separately tracks adds(allocations) and deletes(frees)
+ * such that current = add - del.
+ * # Scope (local,global) tracks values since last reset or dawn of heap.
+ * # Call/Bytes tracks separately bytes and calls so you can distinguish between
+ * many small allocations and a few large.
+ *
+ * @param inStream the stream we are sending the report or NULL to use logger
+ */
+void CMemoryStatistics::HeapReport(IStream *inStream /*=NULL*/)
+{
+ Report(inStream, "\n --- RUNTIME HEAP MEMORY REPORT ---\n");
+
+#if Q3DStudio_MEMORY_HEAPTRACKING
+ // Detailed info needs Q3DStudio_MEMORY_HEAPTRACKING defined
+ INT32 theCount = CMemoryHeap::GetReport()->GetCount();
+ ::qsort(&CMemoryHeap::GetReport()[0], static_cast<size_t>(theCount),
+ sizeof(CMemoryHeap::SReportEntry), CompareHeap);
+
+ CHAR theReportBuffer[REPORTSIZE];
+ for (INT32 theIndex = 0; theIndex < theCount; ++theIndex) {
+ CMemoryHeap::SReportEntry &theEntry = CMemoryHeap::GetReport()->operator[](theIndex);
+ Q3DStudio_sprintf(theReportBuffer, sizeof(theReportBuffer),
+ "%3d. %8d bytes - \"%s\" - %s (%d)\n", theIndex, theEntry.m_Size,
+ theEntry.m_Description, theEntry.m_File, theEntry.m_Line);
+ Report(inStream, theReportBuffer);
+ }
+#else
+ Report(inStream, " Unavailable: Q3DStudio_MEMORY_HEAPTRACKING not defined in this build\n");
+#endif
+}
+
+/* Example output of CMemoryStatistics::Report
+
+=POOL= HEAP CALLS USED ALIGN MISSES
+---------------------------------------------------------------
+All Managers 722k 38 72% 19%
+
+ Global 482k
+ 0: 16b x 1024 16k 2182 3% 13%
+ 1: 32b x 2048 64k 4123 96% 9% 38
+ 2: 48b x 512 24k 212 72% 21%
+ 3: 64b x 512 32k 454 11% 3%
+ .
+ 8: 512b x 128 64k 68 64% 22%
+*/
+
+//==============================================================================
+/**
+ * Return a text buffer describing the state of the memory system.
+ */
+void CMemoryStatistics::PoolReport(BOOL inPeak /*= true*/, BOOL inGlobal /*= true*/,
+ IStream *inStream /*=NULL*/)
+{
+ CHAR theLine[256] = { 0 };
+ SFactSheet theFacts;
+
+ GetFacts(theFacts, inPeak, inGlobal);
+
+ Report(inStream, "\n --- RUNTIME POOL MEMORY REPORT ---\n");
+ Q3DStudio_sprintf(theLine, 256,
+ "Mode: %s %s\nTotal Heap: %7dk(%d)\nPresentation: %7dk\n",
+ inGlobal ? "GLOBAL" : "RESET", inPeak ? "PEAK" : "CURRENT",
+ theFacts.m_HeapState.m_Bytes / 1024, theFacts.m_HeapState.m_Calls,
+ GetRequestedBytes(inPeak) / 1024);
+ Report(inStream, theLine);
+
+#if Q3DStudio_MEMORY_POOLTRACKING
+ Report(inStream, "=POOLS= HEAP HITS USED ALIGN MISS"
+ "\n");
+ Report(inStream, "-----------------------------------------------------------------"
+ "\n");
+ Q3DStudio_sprintf(theLine, 256, "All Managers %7dk %8d %5d%% %5d%% %6d"
+ "\n\n",
+ theFacts.m_ManagerState.m_Bytes / 1024, theFacts.m_ManagerState.m_Calls,
+ theFacts.m_ManagerState.m_Used, theFacts.m_ManagerState.m_Align,
+ theFacts.m_ManagerState.m_Miss);
+ Report(inStream, theLine);
+
+ for (INT32 theManagerIndex = 0; theManagerIndex < MANAGERCOUNT; ++theManagerIndex) {
+ SFactoid &theManagerFact = theFacts.m_Manager[theManagerIndex];
+ if (theManagerFact.m_Bytes > 0) {
+ Q3DStudio_sprintf(theLine, 256, "%-20s %7dk %8d %5d%% %5d%% %6d\n",
+ theManagerFact.m_Name, theManagerFact.m_Bytes / 1024,
+ theManagerFact.m_Calls, theManagerFact.m_Used, theManagerFact.m_Align,
+ theManagerFact.m_Miss);
+ Report(inStream, theLine);
+
+ for (INT32 thePoolIndex = 0; thePoolIndex < Q3DStudio_MEMORY_POOLCOUNT;
+ ++thePoolIndex) {
+ SFactoid &thePoolFact = theFacts.m_Pool[theManagerIndex][thePoolIndex];
+ if (theManagerFact.m_Bytes > 0) {
+ Q3DStudio_sprintf(theLine, 256, "%-20s %7dk %8d %5d%% %5d%% %6d\n",
+ thePoolFact.m_Name, thePoolFact.m_Bytes / 1024,
+ thePoolFact.m_Calls, thePoolFact.m_Used, thePoolFact.m_Align,
+ thePoolFact.m_Miss);
+ Report(inStream, theLine);
+ }
+ }
+
+ // Histogram only valid for Current-Reset
+ if (inGlobal) {
+ Report(inStream, " Histogram: Only available in RESET mode\n");
+ } else {
+ Q3DStudio_sprintf(
+ theLine, 256,
+ " Histogram: 1:%3db(%3d) 2:%3db(%3d) 3:%3db(%3d) 4:%3db(%3d) 5:%3db(%3d)\n",
+ theFacts.m_Histogram[theManagerIndex][0].m_Size,
+ theFacts.m_Histogram[theManagerIndex][0].m_Count,
+ theFacts.m_Histogram[theManagerIndex][1].m_Size,
+ theFacts.m_Histogram[theManagerIndex][1].m_Count,
+ theFacts.m_Histogram[theManagerIndex][2].m_Size,
+ theFacts.m_Histogram[theManagerIndex][2].m_Count,
+ theFacts.m_Histogram[theManagerIndex][3].m_Size,
+ theFacts.m_Histogram[theManagerIndex][3].m_Count,
+ theFacts.m_Histogram[theManagerIndex][4].m_Size,
+ theFacts.m_Histogram[theManagerIndex][4].m_Count);
+ Report(inStream, theLine);
+ Q3DStudio_sprintf(
+ theLine, 256,
+ " 6:%3db(%3d) 7:%3db(%3d) 8:%3db(%3d) 9:%3db(%3d) 10:%3db(%3d)\n",
+ theFacts.m_Histogram[theManagerIndex][5].m_Size,
+ theFacts.m_Histogram[theManagerIndex][5].m_Count,
+ theFacts.m_Histogram[theManagerIndex][6].m_Size,
+ theFacts.m_Histogram[theManagerIndex][6].m_Count,
+ theFacts.m_Histogram[theManagerIndex][7].m_Size,
+ theFacts.m_Histogram[theManagerIndex][7].m_Count,
+ theFacts.m_Histogram[theManagerIndex][8].m_Size,
+ theFacts.m_Histogram[theManagerIndex][8].m_Count,
+ theFacts.m_Histogram[theManagerIndex][9].m_Size,
+ theFacts.m_Histogram[theManagerIndex][9].m_Count);
+ Report(inStream, theLine);
+ }
+ }
+ }
+#else
+ Report(inStream, " Unavailable: Q3DStudio_MEMORY_POOLTRACKING not defined in this build\n");
+#endif
+}
+
+//==============================================================================
+/**
+ * Dump the low-level memory list stored in each manager's hash bin.
+ *
+ * @note Q3DStudio_MEMORY_LINETRACKING has to be set to 1 in AKMemorySettings.h or
+ * the compiler for this method to save out any data.
+ *
+ * @param inStream the stream we are sending the report or NULL to use logger
+ */
+void CMemoryStatistics::LineReport(IStream *inStream /*=NULL*/)
+{
+ Report(inStream, "\n--- RUNTIME LINE MEMORY REPORT ---\n");
+#if Q3DStudio_MEMORY_LINETRACKING
+ Report(inStream, "ADDR, SIZE, TYPE, LINE, FILE, \n");
+
+ INT32 theTotalBytes = 0;
+ for (INT32 theManagerIndex = 0; theManagerIndex < MANAGERCOUNT; ++theManagerIndex)
+ if (s_PoolManagers[theManagerIndex] && s_PoolManagers[theManagerIndex]->GetLineTracker())
+ theTotalBytes += s_PoolManagers[theManagerIndex]->GetLineTracker()->Report(inStream);
+
+ CHAR theTotal[64];
+ theTotal[0] = '\0';
+
+ Q3DStudio_sprintf(theTotal, sizeof(theTotal), "TOTAL: , %8d\n", theTotalBytes);
+ Report(inStream, theTotal);
+#else
+ Report(inStream, " Unavailable: Q3DStudio_MEMORY_LINETRACKING not defined in this build\n");
+#endif // Q3DStudio_MEMORY_LINETRACKING
+}
+
+//==============================================================================
+/**
+ * Output to log or stream if available.
+ * @param inMessage string to be reported
+ * @param inStream stream to be used or output to log if NULL
+ */
+void CMemoryStatistics::Report(IStream *inStream, const CHAR *inMessage)
+{
+ if (inStream)
+ inStream->WriteRaw(inMessage, (INT32)::strlen(inMessage));
+ else
+ qCInfo(qt3ds::TRACE_INFO) << inMessage;
+}
+
+//==============================================================================
+/**
+ * Output full memory report to log or stream if available.
+ * @param inStream stream to be used or output to log if NULL
+ */
+void CMemoryStatistics::FullReport(IStream *inStream /*=NULL*/)
+{
+ SimpleReport(inStream);
+ HeapReport(inStream);
+ LineReport(inStream);
+ PoolReport(false, false, inStream);
+ PoolReport(true, false, inStream);
+ PoolReport(false, true, inStream);
+ PoolReport(true, true, inStream);
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryStatistics.h b/src/system/Qt3DSMemoryStatistics.h
new file mode 100644
index 0000000..81e3043
--- /dev/null
+++ b/src/system/Qt3DSMemoryStatistics.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryManager.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Static facade to memory statistics and allocation tracking data.
+ *
+ * Use this class to examine the memory state of the system at any point.
+ * Heap, managers and pools are are connected to this point by registering
+ * themselves on creation. Initiate the extraction of the collected data
+ * using this interface.
+ */
+class CMemoryStatistics
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ const static INT32 REPORTSIZE = 256; ///< Max size of single report string
+ const static INT32 MANAGERCOUNT = 5; ///< Fixed number of managers tracked
+ const static INT32 HISTOGRAMCOUNT = 10; ///< Fixed number of managers tracked
+
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// One row of statistics on allocation
+ struct SFactoid
+ {
+ CHAR m_Name[32]; ///< Ascii identifier - manager name or pool description
+ INT32 m_Bytes; ///< Bytes used - full pool size for example - zero if factoid unused
+ INT32 m_Calls; ///< Function calls, i.e number of allocations
+ INT32 m_Used; ///< Discrete chunk usage in percent - 10 used of 200 gives a value 5
+ INT32 m_Align; ///< Packed efficiency in percent - all 24byte structs in 32byte pool give a
+ ///value 75
+ INT32 m_Miss; ///< Allocation misses - due to full pools for example
+ };
+
+ /// Tuple describing one data point in a histogram
+ struct SHistogramScore
+ {
+ INT32 m_Size; ///< Allocation request in bytes
+ INT32 m_Count; ///< Number of allocation requests
+ };
+
+ /// Set of factoids describing a system memory state
+ struct SFactSheet
+ {
+ SFactoid m_HeapState; ///< Heap facts
+ SFactoid m_ManagerState; ///< Combined manager facts
+ SFactoid m_Manager[MANAGERCOUNT]; ///< Individual manager facts
+ SHistogramScore m_Histogram[MANAGERCOUNT][HISTOGRAMCOUNT]; ///< Top allocation requests
+ ///sorted by bytes, global and
+ ///never reset
+ SFactoid m_Pool[MANAGERCOUNT][Q3DStudio_MEMORY_POOLCOUNT]; ///< Individual pool facts
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ static INT32 s_Overhead; ///< Memory tracking structures report in here
+ static CMemoryManager
+ *s_PoolManagers[MANAGERCOUNT]; ///< Pointers to all created memory pool managers
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Registration
+ static void AddManager(CMemoryManager *inManager);
+ static void RemoveManager(CMemoryManager *inManager);
+ static INT32 &Overhead();
+
+public: // Access
+ static void Reset();
+ static void GetFacts(SFactSheet &outFacts, const BOOL inPeak = false,
+ const BOOL inGlobal = false);
+ static INT32 GetRequestedBytes(const BOOL inPeak = false);
+ static INT32 GetHeapBytes(const BOOL inPeak = false);
+
+public: // Reporting
+ static void SimpleReport(IStream *inStream = NULL);
+ static void HeapReport(IStream *inStream = NULL);
+ static void PoolReport(const BOOL inPeak = false, const BOOL inGlobal = false,
+ IStream *inStream = NULL);
+ static void LineReport(IStream *inStream = NULL);
+
+ static void FullReport(IStream *inStream = NULL);
+ static void Report(IStream *inStream, const CHAR *inString);
+
+protected: // Utility
+ static void CullHistogram(const CMemoryProbe::SValue *inHistogram, const EMemoryValue inValue,
+ SHistogramScore outResults[HISTOGRAMCOUNT]);
+ static int CompareHeap(const void *arg1, const void *arg2);
+ static int CompareHistogram(const void *arg1, const void *arg2);
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryTracker.cpp b/src/system/Qt3DSMemoryTracker.cpp
new file mode 100644
index 0000000..8aef951
--- /dev/null
+++ b/src/system/Qt3DSMemoryTracker.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSMemoryTracker.h"
+#include "foundation/Qt3DSLogging.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Construct and reset the tracker.
+ */
+CMemoryTracker::CMemoryTracker()
+ : m_TrackingOverhead(0)
+{
+ Q3DStudio_memset(&m_TrackingHashBin, 0, sizeof(m_TrackingHashBin));
+ CMemoryStatistics::Overhead() += sizeof(m_TrackingHashBin);
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CMemoryTracker::~CMemoryTracker()
+{
+ CMemoryStatistics::Overhead() -= sizeof(m_TrackingHashBin);
+}
+
+//==============================================================================
+/**
+ * Add information about allocation
+ * @param inPtr contains info about a new allocation
+ */
+void CMemoryTracker::Remember(SMemoryInfo *inPointer)
+{
+ if (inPointer) {
+ // Update global tracking
+ m_TrackingOverhead += sizeof(SMemoryInfo);
+
+ // Locate a suitable hashbin
+ size_t theHashBin =
+ (reinterpret_cast<size_t>(inPointer) >> 2) % Q3DStudio_MEMORY_LINETRACKINGSIZE;
+ size_t theStartHashBin = theHashBin;
+
+ while (m_TrackingHashBin[theHashBin]) {
+ ++theHashBin;
+ if (theHashBin >= Q3DStudio_MEMORY_LINETRACKINGSIZE)
+ theHashBin = 0;
+
+ if (theHashBin == theStartHashBin) {
+ // We've run out of room in the hashbin.
+ // Abort and increase the bin size.
+ qCCritical(qt3ds::OUT_OF_MEMORY)
+ << "Memory Tracker Error: Ran out of room in tracker hashbin "
+ << Q3DStudio_MEMORY_LINETRACKINGSIZE;
+ // exit( -1 );
+ }
+ }
+
+ // Set WatchGuard and store the pointer in the hash bin
+ inPointer->m_DogTag = TRACKER_DOGTAG;
+ m_TrackingHashBin[theHashBin] = inPointer;
+ }
+}
+
+//==============================================================================
+/**
+ * Remove information on an allocation
+ * @param inPtr contains info about the allocation we are releasing
+ */
+void CMemoryTracker::Forget(SMemoryInfo *inPointer)
+{
+ if (inPointer) {
+ // Update global tracking
+ m_TrackingOverhead -= sizeof(SMemoryInfo);
+
+ // Locate the pointer in the hash bin
+ size_t theHashBin = Q3DStudio_max<size_t>(0, (reinterpret_cast<size_t>(inPointer) >> 2)
+ % Q3DStudio_MEMORY_LINETRACKINGSIZE);
+ size_t theStartHashBin = theHashBin;
+
+ while (m_TrackingHashBin[theHashBin] != inPointer) {
+ ++theHashBin;
+ if (theHashBin >= Q3DStudio_MEMORY_LINETRACKINGSIZE)
+ theHashBin = 0;
+
+ if (theHashBin == theStartHashBin) {
+ // We were unable to locate the pointer in the hash bin.
+ // This is really bad, but not catastrophic
+ qCWarning(qt3ds::OUT_OF_MEMORY)
+ << "Memory Tracker Warning. Can't find pointer in tracker hashbin";
+ return;
+ }
+ }
+
+ // Verify watch guard. Something is trashing memory if this call fails.
+ Q3DStudio_ASSERT(m_TrackingHashBin[theHashBin]->m_DogTag == TRACKER_DOGTAG);
+
+ // Clear the pointer from the hash bin
+ m_TrackingHashBin[theHashBin] = NULL;
+ }
+}
+
+//==============================================================================
+/**
+ * Dump the memory list stored in the hash bin.
+ * @param inFileName the report filename or NULL to dump to the logger
+ */
+INT32 CMemoryTracker::Report(IStream *inStream /*=NULL*/)
+{
+ INT32 theTotalBytes = 0;
+ CHAR theLine[256];
+
+ for (INT32 theBinIndex = 0; theBinIndex < Q3DStudio_MEMORY_LINETRACKINGSIZE; ++theBinIndex) {
+ if (m_TrackingHashBin[theBinIndex]) {
+ CMemoryTracker::SMemoryInfo *theInfo = m_TrackingHashBin[theBinIndex];
+
+ Q3DStudio_sprintf(theLine, sizeof(theLine), "0x%p, %8d, %s, %s(%hd)\n", theInfo,
+ theInfo->m_Size, theInfo->m_Type, theInfo->m_File, theInfo->m_Line);
+
+ CMemoryStatistics::Report(inStream, theLine);
+ theTotalBytes += theInfo->m_Size;
+ }
+ }
+
+ return theTotalBytes;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSMemoryTracker.h b/src/system/Qt3DSMemoryTracker.h
new file mode 100644
index 0000000..ee6ce69
--- /dev/null
+++ b/src/system/Qt3DSMemoryTracker.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Low level memory statistics tracking each individual allocation.
+ *
+ * This class is instantiated in each CMemoryManager if tracking is enabled
+ * by setting ENABLE_MEMORY_LINETRACKING to 1 in AKConfig.h for the build
+ * configuration you want.
+ *
+ * Tracking is much more invasive than simple statistics since it records each
+ * individual allocation and deallocation. The overhead can be seen mostly in
+ * the memory load since we store a tracking hashbin of all memory allocation
+ * and a 16 byte SMemoryInfo structure is prepended to each allocation no matter
+ * how small. This mode should be used when debugging memory to track down
+ * individual allocations. It's turned off by default and should stay off
+ * most of the time.
+ *
+ * The tracking information is usually dumped to a comma delimited .csv file
+ * for easy viewing as a spreadsheet of data. This action is initiated by
+ * pressing CTRL-F1 in Quarterback on the PC but can be added to any viewer
+ * by calling CMemoryStatistics::TrackingDump.
+ */
+class CMemoryTracker
+{
+ //==============================================================================
+ // Constants
+ //==============================================================================
+public:
+ const static UINT16 TRACKER_DOGTAG = 0xbead; ///< Watch guard value in SMemoryTrackInfo
+
+ //==============================================================================
+ // Structs
+ //==============================================================================
+public:
+ /// 16 bytes of details on each allocation when tracking is enabled
+ struct SMemoryInfo
+ {
+ UINT16 m_DogTag; ///< 0xbead - asserting this to track overwrites
+ INT16 m_Line; ///< line from which the allocation occurred
+ INT32 m_Size; ///< allocation size in bytes
+ const CHAR *m_File; ///< file from which the allocation occurred
+ const CHAR *m_Type; ///< type of allocation, usually class name
+ };
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ INT32 m_TrackingOverhead; ///< memory used to track allocations in bytes
+ SMemoryInfo *m_TrackingHashBin[Q3DStudio_MEMORY_LINETRACKINGSIZE]; ///< hash table of all
+ ///tracked allocations
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CMemoryTracker();
+ ~CMemoryTracker();
+
+public: // Tracking
+ void Remember(SMemoryInfo *inData);
+ void Forget(SMemoryInfo *inData);
+
+public: // Reporting
+ INT32 Report(IStream *inStream = NULL);
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSPlatformSpecific.h b/src/system/Qt3DSPlatformSpecific.h
new file mode 100644
index 0000000..3fc3401
--- /dev/null
+++ b/src/system/Qt3DSPlatformSpecific.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** 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
+
+#if defined(_PCPLATFORM)
+
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf _snprintf
+#define Q3DStudio_stricmp(inStr1, inStr2) _stricmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) _strnicmp(inStr1, inStr2, inCount)
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy_s(inDest, inSize, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat_s(inDest, inSize, inSource)
+#define Q3DStudio_fopen fopen_s
+#define Q3DStudio_sleepmillisec(inMillisec) Sleep(inMillisec)
+#define Q3DStudio_getpid GetCurrentProcessId
+
+#elif defined(_TEGRAPLATFORM)
+
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf _snprintf
+#define Q3DStudio_stricmp(inStr1, inStr2) _stricmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) _strnicmp(inStr1, inStr2, inCount)
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy_s(inDest, inSize, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat_s(inDest, inSize, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) fopen_s(inFilePtr, inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) Sleep(inMillisec)
+#define Q3DStudio_getpid GetCurrentProcessId
+
+#elif defined(_XENONPLATFORM)
+
+#include <xtl.h>
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+//#define Q3DStudio_memcpy( inDest, inSource, inCount ) XMemCpy( inDest, inSource,
+//static_cast<SIZE_T>( inCount ) )
+//#define Q3DStudio_memset( inDest, inChar, inCount ) XMemSet( inDest, inChar,
+//static_cast<SIZE_T>( inCount ) )
+#define Q3DStudio_sprintf _snprintf
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress) __dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy_s(inDest, inSize, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat_s(inDest, inSize, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) fopen_s(inFilePtr, inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) Sleep(inMillisec)
+#define Q3DStudio_getpid GetCurrentProcessId
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) _strnicmp(inStr1, inStr2, inCount)
+#define Q3DStudio_stricmp(inStr1, inStr2) _stricmp(inStr1, inStr2)
+
+#elif defined(_PS3PLATFORM)
+
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf snprintf
+#define Q3DStudio_tolower std::tolower
+#define Q3DStudio_restrict
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy(inDest, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat(inDest, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) *(inFilePtr) = fopen(inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) \
+ { \
+ struct timespec theSleepTime = { inMillisec / 1000, (inMillisec % 1000) * 1000000 }; \
+ ::nanosleep(&theSleepTime, NULL); \
+ }
+#define Q3DStudio_getpid getpid
+#define Q3DStudio_stricmp(inStr1, inStr2) strcasecmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) strncasecmp(inStr1, inStr2, inCount)
+
+#elif defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#include <time.h>
+#define Q3DStudio_memcpy(inDest, inSource, inCount) \
+ memcpy(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memmove(inDest, inSource, inCount) \
+ memmove(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_memset(inDest, inChar, inCount) \
+ memset(inDest, inChar, static_cast<size_t>(inCount))
+#define Q3DStudio_memcmp(inDest, inSource, inCount) \
+ memcmp(inDest, inSource, static_cast<size_t>(inCount))
+#define Q3DStudio_sprintf snprintf
+#define Q3DStudio_stricmp(inStr1, inStr2) strcasecmp(inStr1, inStr2)
+#define Q3DStudio_strnicmp(inStr1, inStr2, inCount) strncasecmp(inStr1, inStr2, inCount)
+#define Q3DStudio_tolower tolower
+#define Q3DStudio_restrict /*__restrict*/
+#define Q3DStudio_dcbt(inOffset, inAddress)
+#define Q3DStudio_strcpy(inDest, inSize, inSource) strcpy(inDest, inSource)
+#define Q3DStudio_strcat(inDest, inSize, inSource) strcat(inDest, inSource)
+#define Q3DStudio_fopen(inFilePtr, inFilename, inMode) *(inFilePtr) = fopen(inFilename, inMode)
+#define Q3DStudio_sleepmillisec(inMillisec) \
+ { \
+ struct timespec theSleepTime = { inMillisec / 1000, (inMillisec % 1000) * 1000000 }; \
+ ::nanosleep(&theSleepTime, NULL); \
+ }
+#define Q3DStudio_getpid getpid
+
+#else
+#error "A platform must be defined"
+#endif
+
+//==============================================================================
+/** @def Q3DStudio_dcbt( inOffset, inAddress )
+ * @brief Data Cache Block Touch - Loads the block of memory containing
+ * the specified address into the data cache.
+ *
+ * A program uses the dcbt instruction to request a cache block fetch before
+ * it is actually needed by the program. This prevents stalls in the pipeline.
+ */
+
+//==============================================================================
+/** @def Q3DStudio_restrict
+ * @brief Cross platform macro for pointer aliasing.
+ *
+ * Performance Implications of Pointer Aliasing
+ *
+ * Doug Cook
+ * Silicon Graphics, Inc.
+ * August, 1997
+ *
+ * Pointer aliasing can have a severe impact on program performance.
+ * Understanding its implications is critical to writing high-performance code.
+ * This document provides a brief introduction to the problem, and suggests
+ * several approaches to solving it through source-code restructuring, compiler
+ * options, and C or C++ language extensions.
+ *
+ * *Aliasing*
+ *
+ * Here's a brief overview of aliasing. Consider the following function:
+ *
+ * void process_data(float *in, float *out, float gain, int nsamps)
+ * {
+ * int i;
+ * for (i = 0; i < nsamps; i++) {
+ * out[i] = in[i] * gain;
+ * }
+ * }
+ *
+ * In C or C++, it is legal for the parameters in and out to point to
+ * overlapping regions in memory. When this happens, in and out are said to be
+ * aliases. When the compiler optimizes the function, it does not in general
+ * know whether in and out are aliases. It must therefore assume that any
+ * store through out can affect the memory pointed to by in, which severely
+ * limits its ability to reorder or parallelize the code (For some simple
+ * cases, the compiler could analyze the entire program to determine that two
+ * pointers cannot be aliases. But in general, it is impossible for the
+ * compiler to determine whether or not two pointers are aliases, so to be
+ * safe, it must assume that they are).
+ */
diff --git a/src/system/Qt3DSTimer.cpp b/src/system/Qt3DSTimer.cpp
new file mode 100644
index 0000000..d9e82eb
--- /dev/null
+++ b/src/system/Qt3DSTimer.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSTimer.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CTimer::CTimer(ITimeProvider &inProvider)
+ : m_TimeProvider(inProvider)
+ , m_IsRunning(false)
+{
+ Start();
+}
+
+//==============================================================================
+/**
+ * Start the timer
+ */
+void CTimer::Start()
+{
+ if (!m_IsRunning)
+ m_StartTime = m_TimeProvider.GetCurrentTimeMicroSeconds();
+ m_IsRunning = true;
+}
+
+//==============================================================================
+/**
+ * Stop the timer
+ */
+void CTimer::Stop()
+{
+ if (m_IsRunning)
+ m_StartTime = m_TimeProvider.GetCurrentTimeMicroSeconds() - m_StartTime;
+
+ m_IsRunning = false;
+}
+
+//==============================================================================
+/**
+ * Reset the timer
+ */
+void CTimer::Reset()
+{
+ if (m_IsRunning)
+ m_StartTime = m_TimeProvider.GetCurrentTimeMicroSeconds();
+ else
+ m_StartTime = 0;
+}
+
+//==============================================================================
+/**
+ * Gets the current time in milliseconds.
+ * @return the current time since timer was started(in miliseconds),
+ * or time when it was stopped
+ */
+TTimeUnit CTimer::GetTimeMilliSecs()
+{
+ return GetTimeMicroSecs() / 1000;
+}
+
+//=============================================================================
+/**
+ * Get the number of usecs elapsed since start was called.
+ * If the timer is running then this will return the time from when start was
+ * called. If the timer is stopped then this will return the amount of time
+ * between the start and last stop.
+ * @return returns the elasped micro second.
+ */
+TMicroSeconds CTimer::GetTimeMicroSecs()
+{
+ if (m_IsRunning)
+ return m_TimeProvider.GetCurrentTimeMicroSeconds() - m_StartTime;
+ else
+ return m_StartTime;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSTimer.h b/src/system/Qt3DSTimer.h
new file mode 100644
index 0000000..278bd4b
--- /dev/null
+++ b/src/system/Qt3DSTimer.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** 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
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSITimer.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+
+//==============================================================================
+/**
+ * Time provider interface abstracting time from the usage of time.
+ */
+class ITimeProvider
+{
+protected:
+ virtual ~ITimeProvider() {}
+public:
+ virtual INT64 GetCurrentTimeMicroSeconds() = 0;
+};
+
+// Pause in a way that is completely transparent to the underlying system.
+class CPausingTimeProvider : public ITimeProvider
+{
+ ITimeProvider &m_Provider;
+ INT64 m_PauseOffset;
+ INT64 m_Offset;
+ bool m_Paused;
+
+public:
+ CPausingTimeProvider(ITimeProvider &inProvider)
+ : m_Provider(inProvider)
+ , m_PauseOffset(0)
+ , m_Offset(0)
+ , m_Paused(false)
+ {
+ }
+
+ INT64 GetCurrentTimeMicroSeconds() override
+ {
+ INT64 currentTime = 0;
+ if (m_Paused)
+ currentTime = m_PauseOffset;
+ else
+ currentTime = m_Provider.GetCurrentTimeMicroSeconds();
+
+ return currentTime - m_Offset;
+ }
+
+ void Pause()
+ {
+ if (!m_Paused) {
+ m_Paused = true;
+ m_PauseOffset = m_Provider.GetCurrentTimeMicroSeconds();
+ }
+ }
+
+ void UnPause()
+ {
+ if (m_Paused) {
+ m_Paused = false;
+ INT64 timePaused = m_Provider.GetCurrentTimeMicroSeconds() - m_PauseOffset;
+ m_Offset += timePaused;
+ }
+ }
+
+ bool IsPaused() { return m_Paused; }
+
+ void Reset() { m_PauseOffset = m_Offset = 0; }
+};
+
+//==============================================================================
+/**
+ * @class CTimer
+ * @brief A very simple platform optimized utility class to return lapsed time
+ *
+ * Gets current time based on the time lapsed from the point where timer is started.
+ */
+
+class CTimer : public ITimer
+{
+
+ //==============================================================================
+ // Fields
+ //==============================================================================
+protected:
+ ITimeProvider &m_TimeProvider;
+ INT64 m_StartTime;
+ BOOL m_IsRunning; // Whether this timer is running or stopped
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ CTimer(ITimeProvider &inProvider);
+
+public: // Operation
+ void Start() override;
+ void Stop() override;
+ void Reset() override;
+ TTimeUnit GetTimeMilliSecs() override;
+ TMicroSeconds GetTimeMicroSecs() override;
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSTypes.cpp b/src/system/Qt3DSTypes.cpp
new file mode 100644
index 0000000..25d41c8
--- /dev/null
+++ b/src/system/Qt3DSTypes.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Return 2^inBitCount - 1.
+ * @param inBitCount number of bits available
+ * @param inUnsigned true if all bits are available
+ * @return the higest number the bits can represent
+ */
+INT32 Q3DStudio_maxbits(const INT32 inBitCount, const BOOL inUnsigned)
+{
+ Q3DStudio_ASSERT(inBitCount < 32);
+ if (inUnsigned)
+ return (1 << inBitCount) - 1;
+ else
+ return (1 << (inBitCount - 1)) - 1;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSTypes.h b/src/system/Qt3DSTypes.h
new file mode 100644
index 0000000..65d57da
--- /dev/null
+++ b/src/system/Qt3DSTypes.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 <QtCore/qglobal.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Typedefs
+//==============================================================================
+typedef bool BOOL; ///< true or false, usually 8 bits
+typedef qint8 INT8; ///< A signed 8-bit integer, not a character
+typedef quint8 UINT8; ///< An unsigned 8-bit integer 0-255, not a character
+typedef qint16 INT16; ///< A signed 16-bit integer
+typedef quint16 UINT16; ///< An unsigned 16-bit integer
+typedef qint32 INT32; ///< A signed 32-bit integer
+typedef quint32 UINT32; ///< An unsigned 32-bit integer
+typedef float FLOAT; ///< A 32-bit floating point number
+typedef char CHAR; ///< String character, not a number
+typedef qint64 INT64;
+typedef quint64 UINT64;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+//==============================================================================
+// Max constants and computation
+//==============================================================================
+INT32 Q3DStudio_maxbits(const INT32 inBitCount, const BOOL inUnsigned);
+
+#define AKMAX_INT8 static_cast<INT8>(0x7F)
+#define AKMAX_UINT8 static_cast<UINT8>(0xFF)
+#define AKMAX_INT16 static_cast<INT16>(0x7FFF)
+#define AKMAX_UINT16 static_cast<UINT16>(0xFFFF)
+#define AKMAX_INT32 0x7FFFFFFFL
+#define AKMAX_UINT32 0xFFFFFFFFUL
+
+#define Q3DStudio_INT64_C(x) x
+#define Q3DStudio_UINT64_C(x) x
+
+typedef FILE TFile;
+typedef size_t TFileSize;
+
+struct VECTOR4
+{
+ union {
+ FLOAT v[4];
+ UINT32 u[4];
+ };
+
+ FLOAT &x() { return v[0]; }
+ FLOAT &y() { return v[1]; }
+ FLOAT &z() { return v[2]; }
+ FLOAT &w() { return v[3]; }
+};
+
+struct MATRIX16
+{
+ union {
+ VECTOR4 v[4];
+ FLOAT m[4][4];
+ FLOAT f[16];
+ };
+
+ FLOAT &_11() { return f[0]; }
+ FLOAT &_12() { return f[1]; }
+ FLOAT &_13() { return f[2]; }
+ FLOAT &_14() { return f[3]; }
+ FLOAT &_21() { return f[4]; }
+ FLOAT &_22() { return f[5]; }
+ FLOAT &_23() { return f[6]; }
+ FLOAT &_24() { return f[7]; }
+ FLOAT &_31() { return f[8]; }
+ FLOAT &_32() { return f[9]; }
+ FLOAT &_33() { return f[10]; }
+ FLOAT &_34() { return f[11]; }
+ FLOAT &_41() { return f[12]; }
+ FLOAT &_42() { return f[13]; }
+ FLOAT &_43() { return f[14]; }
+ FLOAT &_44() { return f[15]; }
+};
+
+typedef INT64 TMicroSeconds; ///< Time in microseconds
+typedef INT64 TTimeUnit; ///< Time in milliseconds
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSVector3.cpp b/src/system/Qt3DSVector3.cpp
new file mode 100644
index 0000000..2d790f9
--- /dev/null
+++ b/src/system/Qt3DSVector3.cpp
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** 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 "SystemPrefix.h"
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSVector3.h"
+#include "Qt3DSMatrix.h"
+#include "Qt3DSDataLogger.h"
+#include <math.h>
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Constants
+//==============================================================================
+extern const float RUNTIME_EPSILON = 0.0001f;
+const float RUNTIME_SQUARE_EPSILON = 0.000001f;
+
+//==============================================================================
+/**
+ * Simple constructor - creates a NULL vector.
+ */
+RuntimeVector3::RuntimeVector3()
+ : m_X(0.0f)
+ , m_Y(0.0f)
+ , m_Z(0.0f)
+{
+}
+
+//==============================================================================
+/**
+ * Construction from three array value.
+ * @param inVector the source array
+ */
+RuntimeVector3::RuntimeVector3(const float inVector[3])
+ : m_X(inVector[0])
+ , m_Y(inVector[1])
+ , m_Z(inVector[2])
+{
+}
+
+//==============================================================================
+/**
+ * Construction from three coordinates.
+ * @param inX the m_X coordinate
+ * @param inY the m_Y coordinate
+ * @param inZ the m_Z coordinate
+ */
+RuntimeVector3::RuntimeVector3(const float inX, const float inY, const float inZ)
+ : m_X(inX)
+ , m_Y(inY)
+ , m_Z(inZ)
+{
+}
+
+//==============================================================================
+/**
+ * Copy constructor
+ * @param inVector the source vector
+ */
+RuntimeVector3::RuntimeVector3(const RuntimeVector3 &inVector)
+ : m_X(inVector.m_X)
+ , m_Y(inVector.m_Y)
+ , m_Z(inVector.m_Z)
+{
+}
+
+//==============================================================================
+/**
+ * Assignment of coordinates.
+ * @param inX the m_X coordinate
+ * @param inY the m_Y coordinate
+ * @param inZ the m_Z coordinate
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::Set(const float inX, const float inY, const float inZ)
+{
+ m_X = inX;
+ m_Y = inY;
+ m_Z = inZ;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Assignment of coordinates using another vector.
+ * @param inVector the vector to be copied.
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::Set(const RuntimeVector3 &inVector)
+{
+ m_X = inVector.m_X;
+ m_Y = inVector.m_Y;
+ m_Z = inVector.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Compare this vector with another. Exact match is not needed but instead
+ * an error of EPSILON is allowed.
+ * @param inVector the vector we are compared with
+ * @return true if the vectors are close to identical
+ * @see EPSILON
+ */
+bool RuntimeVector3::operator==(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+
+ return (::fabsf(m_X - inVector.m_X) < RUNTIME_EPSILON) && (::fabsf(m_Y - inVector.m_Y) < RUNTIME_EPSILON)
+ && (::fabsf(m_Z - inVector.m_Z) < RUNTIME_EPSILON);
+}
+
+//==============================================================================
+/**
+ * Compare this vector with another. Exact match is not needed but instead
+ * an error of EPSILON is allowed.
+ * @param inVector the vector we are compared with
+ * @return true if the vectors are not even close to identical
+ * @see EPSILON
+ */
+bool RuntimeVector3::operator!=(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+
+ return (::fabsf(m_X - inVector.m_X) > RUNTIME_EPSILON) || (::fabsf(m_Y - inVector.m_Y) > RUNTIME_EPSILON)
+ || (::fabsf(m_Z - inVector.m_Z) > RUNTIME_EPSILON);
+}
+
+//==============================================================================
+/**
+ * Add this vector with another but do not modify this vector.
+ * @param inVector the second vector being added
+ * @return a new vector
+ */
+RuntimeVector3 RuntimeVector3::operator+(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+
+ return RuntimeVector3(m_X + inVector.m_X, m_Y + inVector.m_Y, m_Z + inVector.m_Z);
+}
+
+//==============================================================================
+/**
+ * Add two vectors but do not modify this vector.
+ * @param inVector vector being subtracted
+ * @return a new vector
+ */
+RuntimeVector3 RuntimeVector3::operator-(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return RuntimeVector3(m_X - inVector.m_X, m_Y - inVector.m_Y, m_Z - inVector.m_Z);
+}
+
+//==============================================================================
+/**
+ * Get a scaled copy of this vector.
+ * @param inFactor the factor that scales each coordinate
+ * @return a new scaled vector
+ */
+RuntimeVector3 RuntimeVector3::operator*(float inFactor) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return RuntimeVector3(m_X * inFactor, m_Y * inFactor, m_Z * inFactor);
+}
+
+//==============================================================================
+/**
+ * Invert the vector.
+ * @return the inverted copy of this vector
+ */
+RuntimeVector3 RuntimeVector3::operator-() const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return RuntimeVector3(-m_X, -m_Y, -m_Z);
+}
+
+//==============================================================================
+/**
+ * Simple assignment.
+ * @param inVector the new vector
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator=(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ if (&inVector != this) {
+ m_X = inVector.m_X;
+ m_Y = inVector.m_Y;
+ m_Z = inVector.m_Z;
+ }
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Increment this vector.
+ * @param inVector has the coordinates by which this vector will be incremented
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator+=(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X += inVector.m_X;
+ m_Y += inVector.m_Y;
+ m_Z += inVector.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Decrement this vector.
+ * @param inVector has the coordinates by which this vector will be decremented
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator-=(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X -= inVector.m_X;
+ m_Y -= inVector.m_Y;
+ m_Z -= inVector.m_Z;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Scale this vector by a factor.
+ * @param inFactor the scale factor
+ * @return a reference to this modified vector
+ */
+RuntimeVector3 &RuntimeVector3::operator*=(float inFactor)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X *= inFactor;
+ m_Y *= inFactor;
+ m_Z *= inFactor;
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Calculates the squared distance between this vector and another.
+ * This is often used in sorting situations where the real distance isn't needed.
+ * @param inVector vector to which the distance is being calculated
+ * @return the squared distance between vectors
+ */
+float RuntimeVector3::DistanceSquared(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return (m_X - inVector.m_X) * (m_X - inVector.m_X) + (m_Y - inVector.m_Y) * (m_Y - inVector.m_Y)
+ + (m_Z - inVector.m_Z) * (m_Z - inVector.m_Z);
+}
+
+//==============================================================================
+/**
+ * Calculates the distance between this vector and another.
+ * @param inVector vector to which the distance is being calculated
+ * @return the distance between vectors
+ */
+float RuntimeVector3::Distance(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return ::sqrtf((m_X - inVector.m_X) * (m_X - inVector.m_X)
+ + (m_Y - inVector.m_Y) * (m_Y - inVector.m_Y)
+ + (m_Z - inVector.m_Z) * (m_Z - inVector.m_Z));
+}
+
+//==============================================================================
+/**
+ * Calculates the squared length (squared magnitude) of the current vector.
+ * @return the squared length of this vector
+ */
+float RuntimeVector3::LengthSquared() const
+{
+ return m_X * m_X + m_Y * m_Y + m_Z * m_Z;
+}
+
+//==============================================================================
+/**
+ * Calculates the length (magnitude) of the current vector.
+ * @return the length of this vector
+ */
+float RuntimeVector3::Length() const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return ::sqrtf(m_X * m_X + m_Y * m_Y + m_Z * m_Z);
+}
+
+//==============================================================================
+/**
+ * Calculates the dot product of this vector and another.
+ * @param inVector vector measuring with
+ * @return the dot product
+ * @see operator*
+ */
+float RuntimeVector3::DotProduct(const RuntimeVector3 &inVector) const
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ return m_X * inVector.m_X + m_Y * inVector.m_Y + m_Z * inVector.m_Z;
+}
+
+//==============================================================================
+/**
+ * Calculates the cross product of this vector and another and modifies this vector
+ * @param inVector other vector
+ * @return this cross product vector
+ * @see operator%
+ * @see operator%=
+ */
+RuntimeVector3 &RuntimeVector3::CrossProduct(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ float theX = m_Y * inVector.m_Z - m_Z * inVector.m_Y;
+ float theY = m_Z * inVector.m_X - m_X * inVector.m_Z;
+ float theZ = m_X * inVector.m_Y - m_Y * inVector.m_X;
+
+ m_X = theX;
+ m_Y = theY;
+ m_Z = theZ;
+
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Normalizes the current vector making it a unit vector.
+ * The normalized vector is defined to be: V_norm = V / Magnitude(V).
+ * @return this normalized vector
+*/
+RuntimeVector3 &RuntimeVector3::Normalize()
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ float theLengthSquared = LengthSquared();
+ if ((theLengthSquared > RUNTIME_SQUARE_EPSILON) && ::fabsf(theLengthSquared - 1.0f) > RUNTIME_SQUARE_EPSILON) {
+ float theInvLength = 1.0f / ::sqrtf(theLengthSquared);
+ m_X *= theInvLength;
+ m_Y *= theInvLength;
+ m_Z *= theInvLength;
+ }
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the minimum between
+ * this vector and another.
+ * @param inVector vector that whose elements are tested against the
+ * current vector to build the minimum.
+ * @return this minimized vector
+*/
+RuntimeVector3 &RuntimeVector3::Minimize(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X = Q3DStudio_min<float>(m_X, inVector.m_X);
+ m_Y = Q3DStudio_min<float>(m_Y, inVector.m_Y);
+ m_Z = Q3DStudio_min<float>(m_Z, inVector.m_Z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector to contain elements that are the maximum between
+ * this vector and another.
+ * @param inVector vector that whose elements are tested against the
+ * current vector to build the maximum.
+ * @return this maximized vector
+*/
+RuntimeVector3 &RuntimeVector3::Maximize(const RuntimeVector3 &inVector)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X = Q3DStudio_max<float>(m_X, inVector.m_X);
+ m_Y = Q3DStudio_max<float>(m_Y, inVector.m_Y);
+ m_Z = Q3DStudio_max<float>(m_Z, inVector.m_Z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Modifies the current vector by performing a linear interpolation
+ * between the current vector and the given vector.
+ *
+ * If inFactor is 0.0 then this vector remains unchanged. If inFactor is
+ * 1.0 then this vector becomes inDestVector. If inFactor is between 0.0-1.0
+ * then this vector becomes a vector between this old vector and inDestVector
+ * proportionally interpolated based in inFactor. If inFactor is less than 0
+ * or more than 1 then this vector is extrapolated.
+ *
+ * @param inDestVector Second vector for the interpolation
+ * @param inFactor Weight for the interpolation
+ * @return this interpolated vector
+ */
+RuntimeVector3 &RuntimeVector3::InterpolateLinear(const RuntimeVector3 &inDestVector, float inFactor)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ m_X += inFactor * (inDestVector.m_X - m_X);
+ m_Y += inFactor * (inDestVector.m_Y - m_Y);
+ m_Z += inFactor * (inDestVector.m_Z - m_Z);
+ return *this;
+}
+
+//==============================================================================
+/**
+ * Transforms this vector by the given matrix.
+ *
+ * The matrix is row column of the form Matrix[row][column]:
+@code
+ | m0 m1 m2 w |
+ | m4 m5 m6 w |
+ | m8 m9 m10 w |
+ | tX tY tZ w |
+@endcode
+ * @param inMatrix transform matrix
+ * @return this transformed vector
+ */
+RuntimeVector3 &RuntimeVector3::Transform(const RuntimeMatrix &inMatrix)
+{
+ PerfLogMathEvent1(DATALOGGER_VECTOR);
+ float theX = m_X;
+ float theY = m_Y;
+ float theZ = m_Z;
+
+ m_X = theX * inMatrix.Get(0, 0) + theY * inMatrix.Get(1, 0) + theZ * inMatrix.Get(2, 0);
+ m_Y = theX * inMatrix.Get(0, 1) + theY * inMatrix.Get(1, 1) + theZ * inMatrix.Get(2, 1);
+ m_Z = theX * inMatrix.Get(0, 2) + theY * inMatrix.Get(1, 2) + theZ * inMatrix.Get(2, 2);
+
+ m_X += inMatrix.Get(3, 0);
+ m_Y += inMatrix.Get(3, 1);
+ m_Z += inMatrix.Get(3, 2);
+
+ return *this;
+}
+
+} // namespace Q3DStudio
diff --git a/src/system/Qt3DSVector3.h b/src/system/Qt3DSVector3.h
new file mode 100644
index 0000000..08df028
--- /dev/null
+++ b/src/system/Qt3DSVector3.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** 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
+
+#ifdef WIN32
+#pragma warning(disable : 4201)
+#endif
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+// Forwards
+//==============================================================================
+class RuntimeMatrix;
+
+//==============================================================================
+/**
+ * 3D vector with automatic notification on change.
+ *
+ * This implementation of a 3D vector along with all the sibling and helper
+ * classes in the geometry section, try to strike a balance between clean code,
+ * ease-of-use and speed. Fields are public and most methods are designed to
+ * give the impression of a very intelligent and capable structure. Heavier
+ * code such as intersections is encouraged to be added externally instead
+ * of here.
+ *
+ * The vector is a member of the geometry classes next to CMatrix and CRotation
+ * @see CMatrix
+ * @see CRotation
+ */
+class RuntimeVector3
+{
+ //==============================================================================
+ // Fields
+ //==============================================================================
+public:
+ union {
+ float m[3];
+ struct
+ {
+ float m_X;
+ float m_Y;
+ float m_Z;
+ };
+ };
+
+ //==============================================================================
+ // Methods
+ //==============================================================================
+public: // Construction
+ RuntimeVector3();
+ RuntimeVector3(const float inVector[3]);
+ RuntimeVector3(const float inX, const float inY, const float inZ);
+ RuntimeVector3(const RuntimeVector3 &inVector);
+
+public: // Initialization
+ RuntimeVector3 &Set(const float inX, const float inY, const float inZ);
+ RuntimeVector3 &Set(const RuntimeVector3 &inVector);
+
+public: // Functions
+ float DistanceSquared(const RuntimeVector3 &inVector) const;
+ float Distance(const RuntimeVector3 &inVector) const;
+ float LengthSquared() const;
+ float Length() const;
+ float DotProduct(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 &CrossProduct(const RuntimeVector3 &inVector);
+ RuntimeVector3 &Normalize();
+ RuntimeVector3 &Minimize(const RuntimeVector3 &inVector);
+ RuntimeVector3 &Maximize(const RuntimeVector3 &inVector);
+ RuntimeVector3 &InterpolateLinear(const RuntimeVector3 &inDestVector, float inFactor);
+ RuntimeVector3 &Transform(const RuntimeMatrix &inMatrix);
+
+public: // Operators
+ bool operator==(const RuntimeVector3 &inVector) const;
+ bool operator!=(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 operator+(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 operator-(const RuntimeVector3 &inVector) const;
+ RuntimeVector3 operator*(float inFactor) const;
+ RuntimeVector3 &operator=(const RuntimeVector3 &inVector);
+ RuntimeVector3 &operator+=(const RuntimeVector3 &inVector);
+ RuntimeVector3 &operator-=(const RuntimeVector3 &inVector);
+ RuntimeVector3 &operator*=(float inFactor);
+ RuntimeVector3 operator-() const;
+};
+
+} // namespace Q3DStudio
diff --git a/src/system/SystemPrefix.h b/src/system/SystemPrefix.h
new file mode 100644
index 0000000..aa1ba18
--- /dev/null
+++ b/src/system/SystemPrefix.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** 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
+
+#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 : 4201) // nonstandard extension used : nameless struct/union
+#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 : 4826) // Conversion from 'const void *' to 'void *' is sign-extended
+#pragma warning(disable : 4996) // _snprintf' was declared deprecated
+#pragma warning(disable : 4711) // function selected for automatic inline expansion
+#pragma warning(disable : 4710) // function not inlined
+#pragma warning(disable : 4355) // 'this' : used in base member initializer list
+
+#pragma warning(disable : 4640) // construction of local static object is not thread-safe
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning( \
+ disable : 4738) // storing 32-bit float result in memory, possible loss of performance
+#endif //_WIN32
+
+//==============================================================================
+// STD INCLUDES - Standard includes MUST come first
+#include <stdlib.h> // Standard functions
+#include <stdio.h> // File and IO
+#ifndef _INTEGRITYPLATFORM
+#include <memory.h> // memset, memcpy
+#endif
+#include <string.h> // strlen
+#include <math.h> // Bezier math - pow, acos, cos, sqrt
+#include <ctype.h> // _tolower
+
+#if defined(_LINUXPLATFORM) || defined(_INTEGRITYPLATFORM)
+#include <stdint.h>
+#endif
+
+//==============================================================================
+// OUR INCLUDES
+#include "Qt3DSTypes.h"
+#include "Qt3DSPlatformSpecific.h"
+#include "Qt3DSAssert.h"
+#include "Qt3DSMacros.h"
+#include "Qt3DSConfig.h"
+#include "Qt3DSMemorySettings.h"
+#include "Qt3DSMemory.h"
+#include "Qt3DSArray.h"