├── Exporter3dsmax ├── OpenGex-Max.def ├── OpenGex-Max.vcxproj.filters ├── OpenGex-Max.sln ├── OpenGex-Max.vcxproj ├── MorphR3.h └── OpenGex-Max.h ├── Importer ├── OpenGEX │ ├── OpenGEX.vcxproj.filters │ ├── OpenGEX.sln │ ├── Example.ogex │ └── OpenGEX.vcxproj └── OpenDDL │ ├── Code │ ├── TSRigid2D.cpp │ ├── TSRigid3D.cpp │ ├── TSTools.cpp │ ├── TSBivector3D.cpp │ ├── TSVector2D.cpp │ ├── TSHalf.h │ ├── TSHalf.cpp │ ├── TSVector3D.cpp │ ├── TSVector4D.cpp │ ├── TSBasic.h │ ├── TSMatrix2D.cpp │ ├── TSQuaternion.cpp │ ├── TSPlatform.h │ ├── TSList.cpp │ ├── TSMatrix2D.h │ ├── TSTree.cpp │ ├── TSBivector3D.h │ ├── TSAlgebra.cpp │ ├── TSMath.h │ ├── TSTools.h │ ├── TSMap.cpp │ ├── TSMatrix3D.cpp │ └── TSColor.cpp │ ├── OpenDDL.vcxproj.filters │ └── OpenDDL.vcxproj ├── ExporterMaya ├── OpenGex-Maya.vcxproj.filters ├── OpenGex-Maya.sln ├── OpenGex-Maya.vcxproj └── OpenGex-Maya.h ├── README.md └── LICENSE /Exporter3dsmax/OpenGex-Max.def: -------------------------------------------------------------------------------- 1 | LIBRARY OpenGex.dle 2 | EXPORTS 3 | LibDescription @1 4 | LibNumberClasses @2 5 | LibClassDesc @3 6 | LibVersion @4 7 | SECTIONS 8 | .data READ WRITE 9 | -------------------------------------------------------------------------------- /Importer/OpenGEX/OpenGEX.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ExporterMaya/OpenGex-Maya.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Exporter3dsmax/OpenGex-Max.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSRigid2D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSRigid2D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(16) const ConstFlatPoint2D FlatPoint2D::origin = {0.0F, 0.0F, 1.0F}; 17 | alignas(16) const ConstLine2D Line2D::zero = {0.0F, 0.0F, 0.0F}; 18 | alignas(16) const ConstLine2D Line2D::horizon = {0.0F, 0.0F, 1.0F}; 19 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSRigid3D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSRigid3D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(16) const ConstFlatPoint3D FlatPoint3D::origin = {0.0F, 0.0F, 0.0F, 1.0F}; 17 | alignas(32) const ConstLine3D Line3D::zero = {0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}; 18 | alignas(16) const ConstPlane3D Plane3D::zero = {0.0F, 0.0F, 0.0F, 0.0F}; 19 | alignas(16) const ConstPlane3D Plane3D::horizon = {0.0F, 0.0F, 0.0F, 1.0F}; 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Game Engine Exchange 2 | 3 | This repository contains reference code for the Open Game Engine Exchange (OpenGEX) file format. 4 | 5 | For more information about OpenGEX, see [opengex.org](http://opengex.org). 6 | 7 | ## Export Plugins 8 | 9 | To use the export plugin for 3ds Max, place the OpenGex.dle file in the Max `plugins` directory. 10 | 11 | To use the export plugin for Maya, place the OpenGex.mll file in the Maya `bin/plug-ins` directory. 12 | 13 | ## Import Template 14 | 15 | The reference importer contains a lot of code that reads an OpenGEX file, validates it, and creates all of the structures necessary to construct a scene. Application-specific processing must be added in the appropriate places to support your own software. 16 | -------------------------------------------------------------------------------- /Exporter3dsmax/OpenGex-Max.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenGex-Max", "OpenGex-Max.vcxproj", "{84451A04-2CCA-47D8-9EAB-371347648B42}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x64 = Debug|x64 9 | Release|x64 = Release|x64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Debug|x64.ActiveCfg = Debug|x64 13 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Debug|x64.Build.0 = Debug|x64 14 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Release|x64.ActiveCfg = Release|x64 15 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Release|x64.Build.0 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /ExporterMaya/OpenGex-Maya.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenGex-Maya", "OpenGex-Maya.vcxproj", "{84451A04-2CCA-47D8-9EAB-371347648B42}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x64 = Debug|x64 9 | Release|x64 = Release|x64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Debug|x64.ActiveCfg = Debug|x64 13 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Debug|x64.Build.0 = Debug|x64 14 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Release|x64.ActiveCfg = Release|x64 15 | {84451A04-2CCA-47D8-9EAB-371347648B42}.Release|x64.Build.0 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSTools.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Common Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSTools.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | #ifdef TERATHON_DEBUG 17 | 18 | #if defined(_MSC_VER) || defined(__ORBIS__) || defined(__PROSPERO__) 19 | 20 | void Terathon::Fatal(const char *message) 21 | { 22 | __debugbreak(); 23 | } 24 | 25 | #elif defined(__GNUC__) 26 | 27 | extern "C" 28 | { 29 | int raise(int); 30 | } 31 | 32 | void Terathon::Fatal(const char *message) 33 | { 34 | raise(5); // SIGTRAP 35 | } 36 | 37 | #endif 38 | 39 | void Terathon::Assert(bool condition, const char *message) 40 | { 41 | if (!condition) 42 | { 43 | Fatal(message); 44 | } 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSBivector3D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSBivector3D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(16) const ConstBivector3D Bivector3D::zero = {0.0F, 0.0F, 0.0F}; 17 | 18 | alignas(16) const ConstBivector3D Bivector3D::yz_unit = {1.0F, 0.0F, 0.0F}; 19 | alignas(16) const ConstBivector3D Bivector3D::zx_unit = {0.0F, 1.0F, 0.0F}; 20 | alignas(16) const ConstBivector3D Bivector3D::xy_unit = {0.0F, 0.0F, 1.0F}; 21 | 22 | alignas(16) const ConstBivector3D Bivector3D::minus_yz_unit = {-1.0F, 0.0F, 0.0F}; 23 | alignas(16) const ConstBivector3D Bivector3D::minus_zx_unit = {0.0F, -1.0F, 0.0F}; 24 | alignas(16) const ConstBivector3D Bivector3D::minus_xy_unit = {0.0F, 0.0F, -1.0F}; 25 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSVector2D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSVector2D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(8) const ConstVector2D Vector2D::zero = {0.0F, 0.0F}; 17 | alignas(8) const ConstPoint2D Origin2D::origin = {0.0F, 0.0F}; 18 | alignas(8) const Origin2D Point2D::origin = {}; 19 | 20 | alignas(8) const ConstVector2D Vector2D::x_unit = {1.0F, 0.0F}; 21 | alignas(8) const ConstVector2D Vector2D::y_unit = {0.0F, 1.0F}; 22 | 23 | alignas(8) const ConstVector2D Vector2D::minus_x_unit = {-1.0F, 0.0F}; 24 | alignas(8) const ConstVector2D Vector2D::minus_y_unit = {0.0F, -1.0F}; 25 | 26 | 27 | Vector2D& Vector2D::Rotate(float angle) 28 | { 29 | Vector2D t = CosSin(angle); 30 | float nx = t.x * x - t.y * y; 31 | float ny = t.y * x + t.x * y; 32 | 33 | x = nx; 34 | y = ny; 35 | return (*this); 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 1999-2022 Eric Lengyel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Importer/OpenGEX/OpenGEX.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.1267 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenDDL", "..\OpenDDL\OpenDDL.vcxproj", "{1A000EBE-832E-4085-8853-B9298F8DD3BF}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenGEX", "OpenGEX.vcxproj", "{8EF0F47D-3045-4C55-B736-5022167A4D3D}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {1A000EBE-832E-4085-8853-B9298F8DD3BF} = {1A000EBE-832E-4085-8853-B9298F8DD3BF} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {1A000EBE-832E-4085-8853-B9298F8DD3BF}.Debug|x64.ActiveCfg = Debug|x64 20 | {1A000EBE-832E-4085-8853-B9298F8DD3BF}.Debug|x64.Build.0 = Debug|x64 21 | {1A000EBE-832E-4085-8853-B9298F8DD3BF}.Release|x64.ActiveCfg = Release|x64 22 | {1A000EBE-832E-4085-8853-B9298F8DD3BF}.Release|x64.Build.0 = Release|x64 23 | {8EF0F47D-3045-4C55-B736-5022167A4D3D}.Debug|x64.ActiveCfg = Debug|x64 24 | {8EF0F47D-3045-4C55-B736-5022167A4D3D}.Debug|x64.Build.0 = Debug|x64 25 | {8EF0F47D-3045-4C55-B736-5022167A4D3D}.Release|x64.ActiveCfg = Release|x64 26 | {8EF0F47D-3045-4C55-B736-5022167A4D3D}.Release|x64.Build.0 = Release|x64 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {38C6975D-A986-4876-8090-C505AEC6BEA4} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSHalf.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Common Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #ifndef TSHalf_h 11 | #define TSHalf_h 12 | 13 | 14 | #include "TSPlatform.h" 15 | 16 | 17 | #define TERATHON_HALF 1 18 | 19 | 20 | namespace Terathon 21 | { 22 | class Half 23 | { 24 | private: 25 | 26 | uint16 value; 27 | 28 | Half(uint16 v) 29 | { 30 | value = v; 31 | } 32 | 33 | TERATHON_API float GetFloat(void) const; 34 | TERATHON_API void SetFloat(float v) volatile; 35 | 36 | public: 37 | 38 | inline Half() = default; 39 | 40 | Half(const Half& h) 41 | { 42 | value = h.value; 43 | } 44 | 45 | Half(float v) 46 | { 47 | SetFloat(v); 48 | } 49 | 50 | Half(double v) 51 | { 52 | SetFloat(float(v)); 53 | } 54 | 55 | operator float(void) const 56 | { 57 | return (GetFloat()); 58 | } 59 | 60 | inline Half& operator =(const Half& h) 61 | { 62 | value = h.value; 63 | return (*this); 64 | } 65 | 66 | Half& operator =(float v) 67 | { 68 | SetFloat(v); 69 | return (*this); 70 | } 71 | 72 | void operator =(float v) volatile 73 | { 74 | SetFloat(v); 75 | } 76 | 77 | Half& operator =(double v) 78 | { 79 | SetFloat(float(v)); 80 | return (*this); 81 | } 82 | 83 | void operator =(double v) volatile 84 | { 85 | SetFloat(float(v)); 86 | } 87 | 88 | friend Half operator -(const Half& h); 89 | }; 90 | 91 | 92 | inline Half operator -(const Half& h) 93 | { 94 | return (Half(uint16(h.value ^ 0x8000))); 95 | } 96 | 97 | 98 | inline const Half& ashalf(const int16& i) 99 | { 100 | return (reinterpret_cast(i)); 101 | } 102 | 103 | inline const Half& ashalf(const uint16& i) 104 | { 105 | return (reinterpret_cast(i)); 106 | } 107 | } 108 | 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSHalf.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Common Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSHalf.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | namespace 17 | { 18 | // Indexed by the high 6 bits of a 16-bit float, this table contains the sign and exponent 19 | // for the corresponding 32-bit float as well as a mantissa mask that flushes denorms to 20 | // zero and clears the mantissa bits for any infinities. 21 | 22 | alignas(64) const uint32 halfTable[64] = 23 | { 24 | 0x00000000, 0x38FFFFFF, 0x397FFFFF, 0x39FFFFFF, 0x3A7FFFFF, 0x3AFFFFFF, 0x3B7FFFFF, 0x3BFFFFFF, 0x3C7FFFFF, 0x3CFFFFFF, 0x3D7FFFFF, 0x3DFFFFFF, 0x3E7FFFFF, 0x3EFFFFFF, 0x3F7FFFFF, 0x3FFFFFFF, 25 | 0x407FFFFF, 0x40FFFFFF, 0x417FFFFF, 0x41FFFFFF, 0x427FFFFF, 0x42FFFFFF, 0x437FFFFF, 0x43FFFFFF, 0x447FFFFF, 0x44FFFFFF, 0x457FFFFF, 0x45FFFFFF, 0x467FFFFF, 0x46FFFFFF, 0x477FFFFF, 0x7F800000, 26 | 0x80000000, 0xB8FFFFFF, 0xB97FFFFF, 0xB9FFFFFF, 0xBA7FFFFF, 0xBAFFFFFF, 0xBB7FFFFF, 0xBBFFFFFF, 0xBC7FFFFF, 0xBCFFFFFF, 0xBD7FFFFF, 0xBDFFFFFF, 0xBE7FFFFF, 0xBEFFFFFF, 0xBF7FFFFF, 0xBFFFFFFF, 27 | 0xC07FFFFF, 0xC0FFFFFF, 0xC17FFFFF, 0xC1FFFFFF, 0xC27FFFFF, 0xC2FFFFFF, 0xC37FFFFF, 0xC3FFFFFF, 0xC47FFFFF, 0xC4FFFFFF, 0xC57FFFFF, 0xC5FFFFFF, 0xC67FFFFF, 0xC6FFFFFF, 0xC77FFFFF, 0xFF800000 28 | }; 29 | } 30 | 31 | 32 | float Half::GetFloat(void) const 33 | { 34 | uint32 h = value; 35 | uint32 i = halfTable[h >> 10]; 36 | uint32 f = ((h << 13) | 0xFF800000) & i; 37 | return (asfloat(f)); 38 | } 39 | 40 | void Half::SetFloat(float v) volatile 41 | { 42 | uint32 f = asuint(v); 43 | uint32 s = (f >> 16) & 0x8000; 44 | int32 e = int32((f >> 23) & 0xFF) - 127; 45 | 46 | if (e >= -14) 47 | { 48 | // Add one to the 11th bit in the mantissa to perform proper rounding. 49 | 50 | uint32 m = (((f >> 12) & 0x07FF) + 1) >> 1; 51 | e += m >> 10; 52 | 53 | if (e <= 15) 54 | { 55 | value = uint16(s | ((e + 15) << 10) | (m & 0x03FF)); 56 | } 57 | else 58 | { 59 | value = uint16(s | 0x7C00); 60 | } 61 | } 62 | else 63 | { 64 | value = uint16(s); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSVector3D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSBivector3D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(16) const ConstVector3D Vector3D::zero = {0.0F, 0.0F, 0.0F}; 17 | alignas(16) const ConstPoint3D Origin3D::origin = {0.0F, 0.0F, 0.0F}; 18 | alignas(16) const Origin3D Point3D::origin = {}; 19 | 20 | alignas(16) const ConstVector3D Vector3D::x_unit = {1.0F, 0.0F, 0.0F}; 21 | alignas(16) const ConstVector3D Vector3D::y_unit = {0.0F, 1.0F, 0.0F}; 22 | alignas(16) const ConstVector3D Vector3D::z_unit = {0.0F, 0.0F, 1.0F}; 23 | 24 | alignas(16) const ConstVector3D Vector3D::minus_x_unit = {-1.0F, 0.0F, 0.0F}; 25 | alignas(16) const ConstVector3D Vector3D::minus_y_unit = {0.0F, -1.0F, 0.0F}; 26 | alignas(16) const ConstVector3D Vector3D::minus_z_unit = {0.0F, 0.0F, -1.0F}; 27 | 28 | 29 | Vector3D& Vector3D::RotateAboutX(float angle) 30 | { 31 | Vector2D v = CosSin(angle); 32 | float ny = v.x * y - v.y * z; 33 | float nz = v.x * z + v.y * y; 34 | 35 | y = ny; 36 | z = nz; 37 | return (*this); 38 | } 39 | 40 | Vector3D& Vector3D::RotateAboutY(float angle) 41 | { 42 | Vector2D v = CosSin(angle); 43 | float nx = v.x * x + v.y * z; 44 | float nz = v.x * z - v.y * x; 45 | 46 | x = nx; 47 | z = nz; 48 | return (*this); 49 | } 50 | 51 | Vector3D& Vector3D::RotateAboutZ(float angle) 52 | { 53 | Vector2D v = CosSin(angle); 54 | float nx = v.x * x - v.y * y; 55 | float ny = v.x * y + v.y * x; 56 | 57 | x = nx; 58 | y = ny; 59 | return (*this); 60 | } 61 | 62 | Vector3D& Vector3D::RotateAboutAxis(float angle, const Bivector3D& axis) 63 | { 64 | Vector2D v = CosSin(angle); 65 | float u = 1.0F - v.x; 66 | 67 | float nx = x * (v.x + u * axis.x * axis.x) + y * (u * axis.x * axis.y - v.y * axis.z) + z * (u * axis.x * axis.z + v.y * axis.y); 68 | float ny = x * (u * axis.x * axis.y + v.y * axis.z) + y * (v.x + u * axis.y * axis.y) + z * (u * axis.y * axis.z - v.y * axis.x); 69 | float nz = x * (u * axis.x * axis.z - v.y * axis.y) + y * (u * axis.y * axis.z + v.y * axis.x) + z * (v.x + u * axis.z * axis.z); 70 | 71 | x = nx; 72 | y = ny; 73 | z = nz; 74 | return (*this); 75 | } 76 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSVector4D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSVector4D.h" 11 | #include "TSBivector3D.h" 12 | 13 | 14 | using namespace Terathon; 15 | 16 | 17 | alignas(16) const ConstVector4D Vector4D::zero = {0.0F, 0.0F, 0.0F, 0.0F}; 18 | 19 | alignas(16) const ConstVector4D Vector4D::x_unit = {1.0F, 0.0F, 0.0F, 0.0F}; 20 | alignas(16) const ConstVector4D Vector4D::y_unit = {0.0F, 1.0F, 0.0F, 0.0F}; 21 | alignas(16) const ConstVector4D Vector4D::z_unit = {0.0F, 0.0F, 1.0F, 0.0F}; 22 | alignas(16) const ConstVector4D Vector4D::w_unit = {0.0F, 0.0F, 0.0F, 1.0F}; 23 | 24 | alignas(16) const ConstVector4D Vector4D::minus_x_unit = {-1.0F, 0.0F, 0.0F, 0.0F}; 25 | alignas(16) const ConstVector4D Vector4D::minus_y_unit = {0.0F, -1.0F, 0.0F, 0.0F}; 26 | alignas(16) const ConstVector4D Vector4D::minus_z_unit = {0.0F, 0.0F, -1.0F, 0.0F}; 27 | alignas(16) const ConstVector4D Vector4D::minus_w_unit = {0.0F, 0.0F, 0.0F, -1.0F}; 28 | 29 | 30 | Vector4D& Vector4D::RotateAboutX(float angle) 31 | { 32 | Vector2D v = CosSin(angle); 33 | float ny = v.x * y - v.y * z; 34 | float nz = v.x * z + v.y * y; 35 | 36 | y = ny; 37 | z = nz; 38 | return (*this); 39 | } 40 | 41 | Vector4D& Vector4D::RotateAboutY(float angle) 42 | { 43 | Vector2D v = CosSin(angle); 44 | float nx = v.x * x + v.y * z; 45 | float nz = v.x * z - v.y * x; 46 | 47 | x = nx; 48 | z = nz; 49 | return (*this); 50 | } 51 | 52 | Vector4D& Vector4D::RotateAboutZ(float angle) 53 | { 54 | Vector2D v = CosSin(angle); 55 | float nx = v.x * x - v.y * y; 56 | float ny = v.x * y + v.y * x; 57 | 58 | x = nx; 59 | y = ny; 60 | return (*this); 61 | } 62 | 63 | Vector4D& Vector4D::RotateAboutAxis(float angle, const Bivector3D& axis) 64 | { 65 | Vector2D v = CosSin(angle); 66 | float u = 1.0F - v.x; 67 | 68 | float nx = x * (v.x + u * axis.x * axis.x) + y * (u * axis.x * axis.y - v.y * axis.z) + z * (u * axis.x * axis.z + v.y * axis.y); 69 | float ny = x * (u * axis.x * axis.y + v.y * axis.z) + y * (v.x + u * axis.y * axis.y) + z * (u * axis.y * axis.z - v.y * axis.x); 70 | float nz = x * (u * axis.x * axis.z - v.y * axis.y) + y * (u * axis.y * axis.z + v.y * axis.x) + z * (v.x + u * axis.z * axis.z); 71 | 72 | x = nx; 73 | y = ny; 74 | z = nz; 75 | return (*this); 76 | } 77 | -------------------------------------------------------------------------------- /Importer/OpenDDL/OpenDDL.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSBasic.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Common Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #ifndef TSBasic_h 11 | #define TSBasic_h 12 | 13 | 14 | #include "TSPlatform.h" 15 | 16 | 17 | #if defined(_MSC_VER) 18 | 19 | extern "C" 20 | { 21 | unsigned char _BitScanReverse(unsigned long *, unsigned long); 22 | #pragma intrinsic(_BitScanReverse) 23 | } 24 | 25 | #endif 26 | 27 | 28 | namespace Terathon 29 | { 30 | inline int32 Abs(int32 x) 31 | { 32 | int32 a = x >> 31; 33 | return ((x ^ a) - a); 34 | } 35 | 36 | inline int64 Abs64(int64 x) 37 | { 38 | int64 a = x >> 63; 39 | return ((x ^ a) - a); 40 | } 41 | 42 | 43 | inline int32 Sgn(int32 x) 44 | { 45 | return ((x >> 31) - (-x >> 31)); 46 | } 47 | 48 | inline int64 Sgn64(int64 x) 49 | { 50 | return ((x >> 63) - (-x >> 63)); 51 | } 52 | 53 | 54 | inline int32 Min(int32 x, int32 y) 55 | { 56 | return ((x < y) ? x : y); 57 | } 58 | 59 | inline int64 Min64(int64 x, int64 y) 60 | { 61 | return ((x < y) ? x : y); 62 | } 63 | 64 | inline int32 Max(int32 x, int32 y) 65 | { 66 | return ((x > y) ? x : y); 67 | } 68 | 69 | inline int64 Max64(int64 x, int64 y) 70 | { 71 | return ((x > y) ? x : y); 72 | } 73 | 74 | inline int32 MinZero(int32 x) 75 | { 76 | return (x & (x >> 31)); 77 | } 78 | 79 | inline int64 MinZero64(int64 x) 80 | { 81 | return (x & (x >> 63)); 82 | } 83 | 84 | inline int32 MaxZero(int32 x) 85 | { 86 | return (x & ~(x >> 31)); 87 | } 88 | 89 | inline int64 MaxZero64(int64 x) 90 | { 91 | return (x & ~(x >> 63)); 92 | } 93 | 94 | 95 | template 96 | inline int32 IncMod(int32 x) 97 | { 98 | int32 y = x + 1; 99 | return ((y < mod) ? y : 0); 100 | } 101 | 102 | template 103 | inline int32 DecMod(int32 x) 104 | { 105 | int32 y = x - 1; 106 | return ((y < 0) ? mod - 1 : y); 107 | } 108 | 109 | inline int32 OverflowZero(int32 x, int32 y) 110 | { 111 | return (x & ((x - y) >> 31)); 112 | } 113 | 114 | 115 | template 116 | inline void Exchange(type& x, type& y) 117 | { 118 | x ^= y; 119 | y ^= x; 120 | x ^= y; 121 | } 122 | 123 | template <> 124 | inline void Exchange(float& x, float& y) 125 | { 126 | float f = x; 127 | x = y; 128 | y = f; 129 | } 130 | 131 | 132 | inline int32 Cntlz(uint32 n) 133 | { 134 | #if defined(_MSC_VER) 135 | 136 | unsigned long x; 137 | 138 | if (_BitScanReverse(&x, n) == 0) 139 | { 140 | return (32); 141 | } 142 | 143 | return (31 - x); 144 | 145 | #else 146 | 147 | return ((n != 0) ? __builtin_clz(n) : 32); 148 | 149 | #endif 150 | } 151 | 152 | 153 | inline int32 IntLog2(uint32 n) 154 | { 155 | return (31 - Cntlz(n)); 156 | } 157 | 158 | inline uint32 Pow2Floor(uint32 n) 159 | { 160 | return (0x80000000U >> Cntlz(n)); 161 | } 162 | 163 | inline uint32 Pow2Ceil(uint32 n) 164 | { 165 | return (uint32(1 << (32 - Cntlz(n - 1)))); 166 | } 167 | } 168 | 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSMatrix2D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSMatrix2D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(16) const ConstMatrix2D Matrix2D::identity = {{{1.0F, 0.0F}, {0.0F, 1.0F}}}; 17 | 18 | 19 | Matrix2D::Matrix2D(float n00, float n01, float n10, float n11) : Mat2D(n00, n01, n10, n11) 20 | { 21 | } 22 | 23 | Matrix2D::Matrix2D(const Vector2D& a, const Vector2D& b) 24 | { 25 | col0 = a; 26 | col1 = b; 27 | } 28 | 29 | Matrix2D& Matrix2D::Set(float n00, float n01, float n10, float n11) 30 | { 31 | matrix.Set(n00, n01, n10, n11); 32 | return (*this); 33 | } 34 | 35 | Matrix2D& Matrix2D::Set(const Vector2D& a, const Vector2D& b) 36 | { 37 | col0 = a; 38 | col1 = b; 39 | return (*this); 40 | } 41 | 42 | Matrix2D& Matrix2D::operator *=(const Matrix2D& m) 43 | { 44 | float t = m00 * m(0,0) + m01 * m(1,0); 45 | m01 = m00 * m(0,1) + m01 * m(1,1); 46 | m00 = t; 47 | 48 | t = m10 * m(0,0) + m11 * m(1,0); 49 | m11 = m10 * m(0,1) + m11 * m(1,1); 50 | m10 = t; 51 | 52 | return (*this); 53 | } 54 | 55 | Matrix2D& Matrix2D::operator *=(float s) 56 | { 57 | matrix *= s; 58 | return (*this); 59 | } 60 | 61 | Matrix2D& Matrix2D::operator /=(float s) 62 | { 63 | matrix /= s; 64 | return (*this); 65 | } 66 | 67 | Matrix2D& Matrix2D::SetIdentity(void) 68 | { 69 | m00 = m11 = 1.0F; 70 | m01 = m10 = 0.0F; 71 | return (*this); 72 | } 73 | 74 | Matrix2D& Matrix2D::Orthogonalize(int32 column) 75 | { 76 | Vector2D& x = (*this)[column]; 77 | Vector2D& y = (*this)[column ^ 1]; 78 | 79 | x.Normalize(); 80 | y = Normalize(y - x * Dot(x, y)); 81 | 82 | return (*this); 83 | } 84 | 85 | Matrix2D Matrix2D::MakeRotation(float angle) 86 | { 87 | Vector2D v = CosSin(angle); 88 | return (Matrix2D(v.x, -v.y, v.y, v.x)); 89 | } 90 | 91 | Matrix2D Matrix2D::MakeScale(float scale) 92 | { 93 | return (Matrix2D(scale, 0.0F, 0.0F, scale)); 94 | } 95 | 96 | Matrix2D Matrix2D::MakeScale(float sx, float sy) 97 | { 98 | return (Matrix2D(sx, 0.0F, 0.0F, sy)); 99 | } 100 | 101 | Matrix2D Matrix2D::MakeScaleX(float sx) 102 | { 103 | return (Matrix2D(sx, 0.0F, 0.0F, 1.0F)); 104 | } 105 | 106 | Matrix2D Matrix2D::MakeScaleY(float sy) 107 | { 108 | return (Matrix2D(1.0F, 0.0F, 0.0F, sy)); 109 | } 110 | 111 | 112 | Matrix2D Terathon::operator *(const Matrix2D& m, float s) 113 | { 114 | return (Matrix2D(m(0,0) * s, m(0,1) * s, m(1,0) * s, m(1,1) * s)); 115 | } 116 | 117 | Matrix2D Terathon::operator /(const Matrix2D& m, float s) 118 | { 119 | s = 1.0F / s; 120 | return (Matrix2D(m(0,0) * s, m(0,1) * s, m(1,0) * s, m(1,1) * s)); 121 | } 122 | 123 | float Terathon::Determinant(const Matrix2D& m) 124 | { 125 | return (m(0,0) * m(1,1) - m(0,1) * m(1,0)); 126 | } 127 | 128 | Matrix2D Terathon::Inverse(const Matrix2D& m) 129 | { 130 | float invDet = 1.0F / (m(0,0) * m(1,1) - m(0,1) * m(1,0)); 131 | 132 | return (Matrix2D( m(1,1) * invDet, -m(0,1) * invDet, 133 | -m(1,0) * invDet, m(0,0) * invDet)); 134 | } 135 | 136 | Matrix2D Terathon::Adjugate(const Matrix2D& m) 137 | { 138 | return (Matrix2D(m(1,1), -m(0,1), -m(1,0), m(0,0))); 139 | } 140 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSQuaternion.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSQuaternion.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(16) const ConstQuaternion Quaternion::identity = {0.0F, 0.0F, 0.0F, 1.0F}; 17 | 18 | 19 | Quaternion& Quaternion::operator *=(const Quaternion& q) 20 | { 21 | float a = w * q.x + x * q.w + y * q.z - z * q.y; 22 | float b = w * q.y - x * q.z + y * q.w + z * q.x; 23 | float c = w * q.z + x * q.y - y * q.x + z * q.w; 24 | 25 | w = w * q.w - x * q.x - y * q.y - z * q.z; 26 | xyz.Set(a, b, c); 27 | 28 | return (*this); 29 | } 30 | 31 | Quaternion& Quaternion::operator *=(const Bivector3D& v) 32 | { 33 | float a = w * v.x + y * v.z - z * v.y; 34 | float b = w * v.y - x * v.z + z * v.x; 35 | float c = w * v.z + x * v.y - y * v.x; 36 | 37 | w = -x * v.x - y * v.y - z * v.z; 38 | xyz.Set(a, b, c); 39 | 40 | return (*this); 41 | } 42 | 43 | Matrix3D Quaternion::GetRotationMatrix(void) const 44 | { 45 | // See FGED1, Section 2.7. 46 | 47 | float x2 = x * x; 48 | float y2 = y * y; 49 | float z2 = z * z; 50 | float xy = x * y; 51 | float zx = z * x; 52 | float yz = y * z; 53 | float wx = w * x; 54 | float wy = w * y; 55 | float wz = w * z; 56 | 57 | return (Matrix3D(1.0F - 2.0F * (y2 + z2), 2.0F * (xy - wz), 2.0F * (zx + wy), 58 | 2.0F * (xy + wz), 1.0F - 2.0F * (x2 + z2), 2.0F * (yz - wx), 59 | 2.0F * (zx - wy), 2.0F * (yz + wx), 1.0F - 2.0F * (x2 + y2))); 60 | } 61 | 62 | template 63 | Quaternion& Quaternion::SetRotationMatrix(const matrix& M) 64 | { 65 | // See FGED1, Section 2.7. 66 | 67 | float m00 = M(0,0); 68 | float m11 = M(1,1); 69 | float m22 = M(2,2); 70 | float sum = m00 + m11 + m22; 71 | 72 | if (sum > 0.0F) 73 | { 74 | w = Sqrt(sum + 1.0F) * 0.5F; 75 | float f = 0.25F / w; 76 | 77 | x = (M(2,1) - M(1,2)) * f; 78 | y = (M(0,2) - M(2,0)) * f; 79 | z = (M(1,0) - M(0,1)) * f; 80 | } 81 | else if ((m00 > m11) && (m00 > m22)) 82 | { 83 | x = Sqrt(m00 - m11 - m22 + 1.0F) * 0.5F; 84 | float f = 0.25F / x; 85 | 86 | y = (M(1,0) + M(0,1)) * f; 87 | z = (M(0,2) + M(2,0)) * f; 88 | w = (M(2,1) - M(1,2)) * f; 89 | } 90 | else if (m11 > m22) 91 | { 92 | y = Sqrt(m11 - m22 - m00 + 1.0F) * 0.5F; 93 | float f = 0.25F / y; 94 | 95 | x = (M(1,0) + M(0,1)) * f; 96 | z = (M(2,1) + M(1,2)) * f; 97 | w = (M(0,2) - M(2,0)) * f; 98 | } 99 | else 100 | { 101 | z = Sqrt(m22 - m00 - m11 + 1.0F) * 0.5F; 102 | float f = 0.25F / z; 103 | 104 | x = (M(0,2) + M(2,0)) * f; 105 | y = (M(2,1) + M(1,2)) * f; 106 | w = (M(1,0) - M(0,1)) * f; 107 | } 108 | 109 | return (*this); 110 | } 111 | 112 | template TERATHON_API Quaternion& Quaternion::SetRotationMatrix(const Matrix3D& M); 113 | template TERATHON_API Quaternion& Quaternion::SetRotationMatrix(const Transform3D& M); 114 | 115 | 116 | Quaternion Terathon::operator *(const Quaternion& q1, const Quaternion& q2) 117 | { 118 | return (Quaternion(q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, 119 | q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x, 120 | q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w, 121 | q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z)); 122 | } 123 | 124 | Quaternion Terathon::operator *(const Quaternion& q, const Bivector3D& v) 125 | { 126 | return (Quaternion(q.w * v.x + q.y * v.z - q.z * v.y, 127 | q.w * v.y - q.x * v.z + q.z * v.x, 128 | q.w * v.z + q.x * v.y - q.y * v.x, 129 | -q.x * v.x - q.y * v.y - q.z * v.z)); 130 | } 131 | 132 | Quaternion Terathon::Sqrt(const Quaternion& q) 133 | { 134 | float f = InverseSqrt(q.w * 2.0F + 2.0F); 135 | return (Quaternion(q.x * f, q.y * f, q.z * f, q.w * f + f)); 136 | } 137 | 138 | Vector3D Terathon::Transform(const Vector3D& v, const Quaternion& q) 139 | { 140 | Bivector3D u = (!q.xyz ^ v) * 2.0F; 141 | return ((q.xyz ^ u) + !u * q.w + v); 142 | } 143 | -------------------------------------------------------------------------------- /Importer/OpenGEX/Example.ogex: -------------------------------------------------------------------------------- 1 | Metric (key = "distance") {float {1}} 2 | Metric (key = "angle") {float {1}} 3 | Metric (key = "time") {float {1}} 4 | Metric (key = "up") {string {"z"}} 5 | Metric (key = "forward") {string {"x"}} 6 | 7 | GeometryNode $node1 8 | { 9 | Name {string {"Box001"}} 10 | ObjectRef {ref {$geometry1}} 11 | MaterialRef {ref {$material1}} 12 | 13 | Transform 14 | { 15 | float[16] 16 | { 17 | {0x3F800000, 0x00000000, 0x00000000, 0x00000000, // {1, 0, 0, 0 18 | 0x00000000, 0x3F800000, 0x00000000, 0x00000000, // 0, 1, 0, 0 19 | 0x00000000, 0x00000000, 0x3F800000, 0x00000000, // 0, 0, 1, 0 20 | 0xBEF33B00, 0x411804DE, 0x00000000, 0x3F800000} // -0.47506, 9.50119, 0, 1} 21 | } 22 | } 23 | } 24 | 25 | GeometryNode $node2 26 | { 27 | Name {string {"Box002"}} 28 | ObjectRef {ref {$geometry1}} 29 | MaterialRef {ref {$material1}} 30 | 31 | Transform 32 | { 33 | float[16] 34 | { 35 | {0x3F800000, 0x00000000, 0x00000000, 0x00000000, // {1, 0, 0, 0 36 | 0x00000000, 0x3F800000, 0x00000000, 0x00000000, // 0, 1, 0, 0 37 | 0x00000000, 0x00000000, 0x3F800000, 0x00000000, // 0, 0, 1, 0 38 | 0x43041438, 0x411804DE, 0x00000000, 0x3F800000} // 132.079, 9.50119, 0, 1} 39 | } 40 | } 41 | } 42 | 43 | GeometryObject $geometry1 // Box001, Box002 44 | { 45 | Mesh (primitive = "triangles") 46 | { 47 | VertexArray (attrib = "position") 48 | { 49 | float[3] // 24 50 | { 51 | {0xC2501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0x424C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x42BA3928}, 52 | {0xC2501375, 0xC24C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x00000000}, {0x42501375, 0xC24C468A, 0x42BA3928}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x00000000}, {0x42501375, 0x424C468A, 0x42BA3928}, {0x42501375, 0xC24C468A, 0x42BA3928}, 53 | {0x42501375, 0x424C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x00000000}, {0xC2501375, 0x424C468A, 0x42BA3928}, {0x42501375, 0x424C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x00000000}, {0xC2501375, 0xC24C468A, 0x42BA3928}, {0xC2501375, 0x424C468A, 0x42BA3928} 54 | } 55 | } 56 | 57 | VertexArray (attrib = "normal") 58 | { 59 | float[3] // 24 60 | { 61 | {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0xBF800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000}, {0x00000000, 0x00000000, 0x3F800000}, 62 | {0x00000000, 0xBF800000, 0x00000000}, {0x00000000, 0xBF800000, 0x00000000}, {0x00000000, 0xBF800000, 0x00000000}, {0x80000000, 0xBF800000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, {0x3F800000, 0x00000000, 0x00000000}, 63 | {0x00000000, 0x3F800000, 0x00000000}, {0x00000000, 0x3F800000, 0x00000000}, {0x00000000, 0x3F800000, 0x00000000}, {0x80000000, 0x3F800000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000}, {0xBF800000, 0x00000000, 0x00000000} 64 | } 65 | } 66 | 67 | VertexArray (attrib = "texcoord") 68 | { 69 | float[2] // 24 70 | { 71 | {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, 72 | {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, 73 | {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000}, {0x00000000, 0x00000000}, {0x3F800000, 0x00000000}, {0x3F800000, 0x3F800000}, {0x00000000, 0x3F800000} 74 | } 75 | } 76 | 77 | IndexArray 78 | { 79 | uint32[3] // 12 80 | { 81 | {0, 1, 2}, {2, 3, 0}, {4, 5, 6}, {6, 7, 4}, {8, 9, 10}, {10, 11, 8}, {12, 13, 14}, {14, 15, 12}, {16, 17, 18}, {18, 19, 16}, {20, 21, 22}, {22, 23, 20} 82 | } 83 | } 84 | } 85 | } 86 | 87 | Material $material1 88 | { 89 | Name {string {"Default"}} 90 | 91 | Color (attrib = "diffuse") {float[3] {{0.588235, 0.588235, 0.588235}}} 92 | Texture (attrib = "diffuse") 93 | { 94 | string {"texture/Concrete.tga"} 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Importer/OpenGEX/OpenGEX.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {8EF0F47D-3045-4C55-B736-5022167A4D3D} 21 | OpenGEX 22 | 10.0 23 | 24 | 25 | 26 | Application 27 | true 28 | v143 29 | MultiByte 30 | 31 | 32 | Application 33 | false 34 | v143 35 | true 36 | MultiByte 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Level3 52 | Disabled 53 | MultiThreadedDebug 54 | ..\OpenDDL\Code 55 | true 56 | true 57 | false 58 | Default 59 | false 60 | false 61 | ProgramDatabase 62 | 63 | 64 | true 65 | OpenDDL.lib 66 | ..\OpenGEX\$(IntDir) 67 | Default 68 | LIBCMT 69 | 70 | 71 | 72 | 73 | Level3 74 | MaxSpeed 75 | true 76 | true 77 | true 78 | MultiThreaded 79 | ..\OpenDDL\Code 80 | false 81 | true 82 | false 83 | false 84 | 85 | 86 | true 87 | true 88 | true 89 | ..\OpenGEX\$(IntDir) 90 | OpenDDL.lib 91 | Default 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSPlatform.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Common Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #ifndef TSPlatform_h 11 | #define TSPlatform_h 12 | 13 | 14 | #if defined(TERATHON_EXPORT) 15 | 16 | #if defined(_MSC_VER) 17 | 18 | #define TERATHON_API __declspec(dllexport) 19 | 20 | #elif defined(__GNUC__) 21 | 22 | #define TERATHON_API __attribute__((visibility("default"))) 23 | 24 | #else 25 | 26 | #define TERATHON_API 27 | 28 | #endif 29 | 30 | #elif defined(TERATHON_IMPORT) 31 | 32 | #if defined(_MSC_VER) 33 | 34 | #define TERATHON_API __declspec(dllimport) 35 | 36 | #else 37 | 38 | #define TERATHON_API 39 | 40 | #endif 41 | 42 | #else 43 | 44 | #define TERATHON_API 45 | 46 | #endif 47 | 48 | 49 | #ifdef TERATHON_NO_SYSTEM 50 | 51 | void *__cdecl operator new(size_t); 52 | void *__cdecl operator new[](size_t); 53 | void __cdecl operator delete(void *); 54 | void __cdecl operator delete[](void *); 55 | 56 | inline void *__cdecl operator new(size_t, void *ptr) 57 | { 58 | return (ptr); 59 | } 60 | 61 | inline void *__cdecl operator new[](size_t, void *ptr) 62 | { 63 | return (ptr); 64 | } 65 | 66 | inline void __cdecl operator delete(void *, void *) 67 | { 68 | } 69 | 70 | inline void __cdecl operator delete[](void *, void *) 71 | { 72 | } 73 | 74 | extern "C" 75 | { 76 | void *__cdecl memcpy(void *, const void *, size_t); 77 | #pragma intrinsic(memcpy) 78 | 79 | void *__cdecl memset(void *, int, size_t); 80 | #pragma intrinsic(memset) 81 | } 82 | 83 | #else 84 | 85 | #if defined(_MSC_VER) 86 | 87 | #pragma warning(push) 88 | #pragma warning(disable: 4530) // C++ exception handler used, but unwind semantics are not enabled 89 | #pragma warning(disable: 4577) // 'noexcept' used with no exception handling mode specified 90 | 91 | #endif 92 | 93 | #include 94 | #include 95 | 96 | #if defined(_MSC_VER) 97 | 98 | #pragma warning(pop) 99 | 100 | #endif 101 | 102 | #endif 103 | 104 | 105 | namespace Terathon 106 | { 107 | #if defined(_MSC_VER) 108 | 109 | typedef signed char int8; 110 | typedef short int16; 111 | typedef int int32; 112 | typedef __int64 int64; 113 | typedef unsigned char uint8; 114 | typedef unsigned short uint16; 115 | typedef unsigned int uint32; 116 | typedef unsigned __int64 uint64; 117 | 118 | #if defined(_M_X64) || defined(_M_ARM64) 119 | 120 | typedef __int64 machine; 121 | typedef unsigned __int64 umachine; 122 | typedef unsigned __int64 machine_address; 123 | 124 | #else 125 | 126 | typedef int machine; 127 | typedef unsigned int umachine; 128 | typedef unsigned int machine_address; 129 | 130 | #endif 131 | 132 | #define restrict __restrict 133 | 134 | #pragma warning(disable: 4100) // unreferenced formal parameter 135 | #pragma warning(disable: 4244) // conversion, possible loss of data 136 | #pragma warning(disable: 4324) // structure was padded due to alignment specifier 137 | #pragma warning(disable: 4458) // declaration hides class member 138 | #pragma warning(disable: 4522) // multiple assignment operators specified 139 | 140 | #elif defined(__ORBIS__) || defined(__PROSPERO__) 141 | 142 | typedef signed char int8; 143 | typedef short int16; 144 | typedef int int32; 145 | typedef long int64; 146 | typedef unsigned char uint8; 147 | typedef unsigned short uint16; 148 | typedef unsigned int uint32; 149 | typedef unsigned long uint64; 150 | typedef long machine; 151 | typedef unsigned long umachine; 152 | typedef unsigned long machine_address; 153 | 154 | #elif defined(__GNUC__) 155 | 156 | typedef signed char int8; 157 | typedef short int16; 158 | typedef int int32; 159 | typedef long long int64; 160 | typedef unsigned char uint8; 161 | typedef unsigned short uint16; 162 | typedef unsigned int uint32; 163 | typedef unsigned long long uint64; 164 | 165 | #if defined(__LP64__) || defined(_WIN64) 166 | 167 | typedef long long machine; 168 | typedef unsigned long long umachine; 169 | typedef unsigned long long machine_address; 170 | 171 | #else 172 | 173 | typedef int machine; 174 | typedef unsigned int umachine; 175 | typedef unsigned int machine_address; 176 | 177 | #endif 178 | 179 | #if !defined(restrict) 180 | 181 | #define restrict __restrict__ 182 | 183 | #endif 184 | 185 | #endif 186 | 187 | 188 | inline machine_address GetPointerAddress(const volatile void *ptr) 189 | { 190 | return (reinterpret_cast(ptr)); 191 | } 192 | 193 | 194 | inline const float& asfloat(const int32& i) 195 | { 196 | return (reinterpret_cast(i)); 197 | } 198 | 199 | inline const float& asfloat(const uint32& i) 200 | { 201 | return (reinterpret_cast(i)); 202 | } 203 | 204 | inline const int32& asint(const float& f) 205 | { 206 | return (reinterpret_cast(f)); 207 | } 208 | 209 | inline const uint32& asuint(const float& f) 210 | { 211 | return (reinterpret_cast(f)); 212 | } 213 | 214 | 215 | #undef CopyMemory 216 | #undef FillMemory 217 | #undef ClearMemory 218 | 219 | 220 | inline void CopyMemory(const void *source, void *dest, uint32 size) 221 | { 222 | memcpy(dest, source, size); 223 | } 224 | 225 | inline void FillMemory(void *ptr, uint32 size, uint8 value) 226 | { 227 | memset(ptr, value, size); 228 | } 229 | 230 | inline void ClearMemory(void *ptr, uint32 size) 231 | { 232 | memset(ptr, 0, size); 233 | } 234 | } 235 | 236 | 237 | #endif 238 | -------------------------------------------------------------------------------- /ExporterMaya/OpenGex-Maya.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Win32Proj 21 | OpenGex-Maya 22 | OpenGex-Maya 23 | {84451A04-2CCA-47D8-9EAB-371347648B42} 24 | 10.0 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | v142 31 | Unicode 32 | 33 | 34 | DynamicLibrary 35 | false 36 | v142 37 | Unicode 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | false 51 | $(MAYA_LOCATION)\lib;$(LibraryPath) 52 | $(MAYA_LOCATION)\include;$(IncludePath) 53 | OpenGex 54 | .mll 55 | 56 | 57 | false 58 | $(MAYA_LOCATION)\lib;$(LibraryPath) 59 | $(MAYA_LOCATION)\include;$(IncludePath) 60 | OpenGex 61 | .mll 62 | 63 | 64 | 65 | Level3 66 | Disabled 67 | _UNICODE;UNICODE;_BOOL 68 | true 69 | OnlyExplicitInline 70 | true 71 | false 72 | false 73 | false 74 | true 75 | 76 | Default 77 | MultiThreaded 78 | ProgramDatabase 79 | 80 | 81 | Windows 82 | true 83 | Foundation.lib;OpenMaya.lib;OpenMayaAnim.lib;kernel32.lib;user32.lib;gdi32.lib 84 | 85 | 86 | 87 | 88 | Level3 89 | MaxSpeed 90 | true 91 | _UNICODE;UNICODE;_BOOL 92 | true 93 | AnySuitable 94 | Speed 95 | false 96 | false 97 | true 98 | 99 | MultiThreaded 100 | 101 | 102 | Windows 103 | false 104 | true 105 | true 106 | Foundation.lib;OpenMaya.lib;OpenMayaAnim.lib;kernel32.lib;user32.lib;gdi32.lib 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Exporter3dsmax/OpenGex-Max.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {84451A04-2CCA-47D8-9EAB-371347648B42} 24 | Win32Proj 25 | OpenGex-Max 26 | OpenGex-Max 27 | 10.0 28 | 29 | 30 | 31 | DynamicLibrary 32 | true 33 | v142 34 | Unicode 35 | 36 | 37 | DynamicLibrary 38 | false 39 | v142 40 | Unicode 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | false 54 | $(ADSK_3DSMAX_SDK_2021)\lib\x64\Release;$(LibraryPath) 55 | $(ADSK_3DSMAX_SDK_2021)\include;$(IncludePath) 56 | OpenGex 57 | .dle 58 | 59 | 60 | false 61 | $(ADSK_3DSMAX_SDK_2021)\lib\x64\Release;$(LibraryPath) 62 | OpenGex 63 | .dle 64 | $(ADSK_3DSMAX_SDK_2021)\include;$(IncludePath) 65 | 66 | 67 | 68 | Level3 69 | Disabled 70 | _UNICODE;UNICODE 71 | true 72 | OnlyExplicitInline 73 | true 74 | false 75 | Default 76 | false 77 | false 78 | false 79 | true 80 | 81 | MultiThreaded 82 | ProgramDatabase 83 | 84 | 85 | Windows 86 | true 87 | core.lib;maxutil.lib;geom.lib;mesh.lib;Paramblk2.lib;kernel32.lib;user32.lib;gdi32.lib 88 | OpenGex-Max.def 89 | 90 | 91 | 92 | 93 | Level3 94 | MaxSpeed 95 | false 96 | true 97 | _UNICODE;UNICODE 98 | true 99 | AnySuitable 100 | Speed 101 | false 102 | false 103 | true 104 | 105 | MultiThreaded 106 | 107 | 108 | Windows 109 | false 110 | true 111 | true 112 | core.lib;maxutil.lib;geom.lib;mesh.lib;Paramblk2.lib;kernel32.lib;user32.lib;gdi32.lib 113 | OpenGex-Max.def 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /Importer/OpenDDL/OpenDDL.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | {1A000EBE-832E-4085-8853-B9298F8DD3BF} 65 | Win32Proj 66 | OpenDDL 67 | 10.0 68 | 69 | 70 | 71 | StaticLibrary 72 | true 73 | v143 74 | Unicode 75 | 76 | 77 | StaticLibrary 78 | false 79 | v143 80 | true 81 | Unicode 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | true 95 | 96 | 97 | false 98 | 99 | 100 | 101 | NotUsing 102 | Level3 103 | Disabled 104 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 105 | true 106 | true 107 | true 108 | false 109 | Default 110 | MultiThreaded 111 | false 112 | false 113 | false 114 | ProgramDatabase 115 | 116 | 117 | Windows 118 | true 119 | 120 | 121 | false 122 | 123 | 124 | 125 | 126 | Level3 127 | NotUsing 128 | MaxSpeed 129 | false 130 | true 131 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 132 | true 133 | true 134 | MultiThreaded 135 | false 136 | false 137 | false 138 | 139 | 140 | Windows 141 | true 142 | true 143 | true 144 | 145 | 146 | false 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSList.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Container Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSList.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | ListElementBase::~ListElementBase() 17 | { 18 | if (owningList) 19 | { 20 | owningList->RemoveListElement(this); 21 | } 22 | } 23 | 24 | int32 ListElementBase::GetListIndex(void) const 25 | { 26 | machine index = 0; 27 | 28 | const ListElementBase *element = this; 29 | for (;;) 30 | { 31 | element = element->GetPreviousListElement(); 32 | if (!element) 33 | { 34 | break; 35 | } 36 | 37 | index++; 38 | } 39 | 40 | return (int32(index)); 41 | } 42 | 43 | void ListElementBase::Detach(void) 44 | { 45 | if (owningList) 46 | { 47 | owningList->RemoveListElement(this); 48 | } 49 | } 50 | 51 | 52 | ListBase::~ListBase() 53 | { 54 | PurgeList(); 55 | } 56 | 57 | ListElementBase *ListBase::operator [](machine index) const 58 | { 59 | machine i = 0; 60 | ListElementBase *element = firstListElement; 61 | while (element) 62 | { 63 | if (i == index) 64 | { 65 | return (element); 66 | } 67 | 68 | i++; 69 | element = element->nextListElement; 70 | } 71 | 72 | return (nullptr); 73 | } 74 | 75 | int32 ListBase::GetListElementCount(void) const 76 | { 77 | machine count = 0; 78 | const ListElementBase *element = firstListElement; 79 | while (element) 80 | { 81 | count++; 82 | element = element->nextListElement; 83 | } 84 | 85 | return (int32(count)); 86 | } 87 | 88 | void ListBase::PrependListElement(ListElementBase *element) 89 | { 90 | ListBase *list = element->owningList; 91 | if (list) 92 | { 93 | ListElementBase *prev = element->prevListElement; 94 | ListElementBase *next = element->nextListElement; 95 | 96 | if (prev) 97 | { 98 | prev->nextListElement = next; 99 | element->prevListElement = nullptr; 100 | } 101 | 102 | if (next) 103 | { 104 | next->prevListElement = prev; 105 | element->nextListElement = nullptr; 106 | } 107 | 108 | if (list->firstListElement == element) 109 | { 110 | list->firstListElement = next; 111 | } 112 | 113 | if (list->lastListElement == element) 114 | { 115 | list->lastListElement = prev; 116 | } 117 | } 118 | 119 | if (firstListElement) 120 | { 121 | firstListElement->prevListElement = element; 122 | element->nextListElement = firstListElement; 123 | firstListElement = element; 124 | } 125 | else 126 | { 127 | firstListElement = element; 128 | lastListElement = element; 129 | } 130 | 131 | element->owningList = this; 132 | } 133 | 134 | void ListBase::AppendListElement(ListElementBase *element) 135 | { 136 | ListBase *list = element->owningList; 137 | if (list) 138 | { 139 | ListElementBase *prev = element->prevListElement; 140 | ListElementBase *next = element->nextListElement; 141 | 142 | if (prev) 143 | { 144 | prev->nextListElement = next; 145 | element->prevListElement = nullptr; 146 | } 147 | 148 | if (next) 149 | { 150 | next->prevListElement = prev; 151 | element->nextListElement = nullptr; 152 | } 153 | 154 | if (list->firstListElement == element) 155 | { 156 | list->firstListElement = next; 157 | } 158 | 159 | if (list->lastListElement == element) 160 | { 161 | list->lastListElement = prev; 162 | } 163 | } 164 | 165 | element->owningList = this; 166 | 167 | if (lastListElement) 168 | { 169 | lastListElement->nextListElement = element; 170 | element->prevListElement = lastListElement; 171 | lastListElement = element; 172 | } 173 | else 174 | { 175 | firstListElement = element; 176 | lastListElement = element; 177 | } 178 | } 179 | 180 | void ListBase::InsertListElementBefore(ListElementBase *element, ListElementBase *before) 181 | { 182 | ListBase *list = element->owningList; 183 | if (list) 184 | { 185 | ListElementBase *prev = element->prevListElement; 186 | ListElementBase *next = element->nextListElement; 187 | 188 | if (prev) 189 | { 190 | prev->nextListElement = next; 191 | } 192 | 193 | if (next) 194 | { 195 | next->prevListElement = prev; 196 | } 197 | 198 | if (list->firstListElement == element) 199 | { 200 | list->firstListElement = next; 201 | } 202 | 203 | if (list->lastListElement == element) 204 | { 205 | list->lastListElement = prev; 206 | } 207 | } 208 | 209 | element->owningList = this; 210 | element->nextListElement = before; 211 | 212 | if (before) 213 | { 214 | ListElementBase *after = before->prevListElement; 215 | element->prevListElement = after; 216 | before->prevListElement = element; 217 | 218 | if (after) 219 | { 220 | after->nextListElement = element; 221 | } 222 | else 223 | { 224 | firstListElement = element; 225 | } 226 | } 227 | else 228 | { 229 | ListElementBase *after = lastListElement; 230 | element->prevListElement = after; 231 | 232 | if (after) 233 | { 234 | after->nextListElement = element; 235 | lastListElement = element; 236 | } 237 | else 238 | { 239 | firstListElement = element; 240 | lastListElement = element; 241 | } 242 | } 243 | } 244 | 245 | void ListBase::InsertListElementAfter(ListElementBase *element, ListElementBase *after) 246 | { 247 | ListBase *list = element->owningList; 248 | if (list) 249 | { 250 | ListElementBase *prev = element->prevListElement; 251 | ListElementBase *next = element->nextListElement; 252 | 253 | if (prev) 254 | { 255 | prev->nextListElement = next; 256 | } 257 | 258 | if (next) 259 | { 260 | next->prevListElement = prev; 261 | } 262 | 263 | if (list->firstListElement == element) 264 | { 265 | list->firstListElement = next; 266 | } 267 | 268 | if (list->lastListElement == element) 269 | { 270 | list->lastListElement = prev; 271 | } 272 | } 273 | 274 | element->owningList = this; 275 | element->prevListElement = after; 276 | 277 | if (after) 278 | { 279 | ListElementBase *before = after->nextListElement; 280 | element->nextListElement = before; 281 | after->nextListElement = element; 282 | 283 | if (before) 284 | { 285 | before->prevListElement = element; 286 | } 287 | else 288 | { 289 | lastListElement = element; 290 | } 291 | } 292 | else 293 | { 294 | ListElementBase *before = firstListElement; 295 | element->nextListElement = before; 296 | 297 | if (before) 298 | { 299 | before->prevListElement = element; 300 | firstListElement = element; 301 | } 302 | else 303 | { 304 | firstListElement = element; 305 | lastListElement = element; 306 | } 307 | } 308 | } 309 | 310 | void ListBase::RemoveListElement(ListElementBase *element) 311 | { 312 | ListElementBase *prev = element->prevListElement; 313 | ListElementBase *next = element->nextListElement; 314 | 315 | if (prev) 316 | { 317 | prev->nextListElement = next; 318 | } 319 | 320 | if (next) 321 | { 322 | next->prevListElement = prev; 323 | } 324 | 325 | if (firstListElement == element) 326 | { 327 | firstListElement = next; 328 | } 329 | 330 | if (lastListElement == element) 331 | { 332 | lastListElement = prev; 333 | } 334 | 335 | element->prevListElement = nullptr; 336 | element->nextListElement = nullptr; 337 | element->owningList = nullptr; 338 | } 339 | 340 | void ListBase::RemoveAllListElements(void) 341 | { 342 | ListElementBase *element = firstListElement; 343 | while (element) 344 | { 345 | ListElementBase *next = element->nextListElement; 346 | element->prevListElement = nullptr; 347 | element->nextListElement = nullptr; 348 | element->owningList = nullptr; 349 | element = next; 350 | } 351 | 352 | firstListElement = nullptr; 353 | lastListElement = nullptr; 354 | } 355 | 356 | void ListBase::PurgeList(void) 357 | { 358 | while (firstListElement) 359 | { 360 | delete firstListElement; 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /Exporter3dsmax/MorphR3.h: -------------------------------------------------------------------------------- 1 | // The morpher modifier is not part of the base Max SDK, and the header wm3.h 2 | // supplied in the maxsdk/samples/modifiers/morpher/ directory does not build, 3 | // so we include our own minimal header for it that lets us access what we need. 4 | 5 | 6 | #ifndef __MORPHR3__H 7 | #define __MORPHR3__H 8 | 9 | 10 | #include "max.h" 11 | 12 | 13 | #define MR3_CLASS_ID Class_ID(0x17BB6854, 0xA5CBA2A3) 14 | #define MorphExport __declspec(dllimport) 15 | 16 | 17 | class morphChannel; 18 | class MorphR3; 19 | class M3Mat; 20 | 21 | 22 | // The std::vector class used by Max has the following layout. 23 | // We use this class as a stand-in to maintain binary compatibility. 24 | 25 | template class StdVector 26 | { 27 | private: 28 | 29 | type *first; 30 | type *last; 31 | type *end; 32 | void *reserved; 33 | 34 | public: 35 | 36 | size_t size(void) const 37 | { 38 | return (last - first); 39 | } 40 | 41 | type& front(void) const 42 | { 43 | return (*first); 44 | } 45 | }; 46 | 47 | 48 | class TargetCache 49 | { 50 | public: 51 | 52 | long mNumPoints; 53 | INode *mTargetINode; 54 | StdVector mTargetPoints; 55 | float mTargetPercent; 56 | }; 57 | 58 | 59 | class morphChannel 60 | { 61 | public: 62 | 63 | ~morphChannel(); 64 | morphChannel(); 65 | morphChannel(const morphChannel& from); 66 | 67 | MorphR3 *mp; 68 | 69 | float mCurvature; 70 | int mNumPoints; 71 | 72 | int iTargetListSelection; 73 | 74 | StdVector mPoints; 75 | StdVector mDeltas; 76 | StdVector mWeights; 77 | 78 | StdVector mTargetCache; 79 | 80 | BitArray mSel; 81 | INode *mConnection; 82 | TSTR mName; 83 | int mNumProgressiveTargs; 84 | float mTargetPercent; 85 | 86 | BOOL mActive; 87 | BOOL mModded; 88 | BOOL mUseLimit; 89 | BOOL mUseSel; 90 | float mSpinmin, mSpinmax; 91 | 92 | BOOL mInvalid; 93 | BOOL mActiveOverride; 94 | 95 | IParamBlock *cblock; 96 | 97 | void InitTargetCache(const int& targnum, INode *nd); 98 | 99 | MorphExport void ResetMe(); 100 | MorphExport void AllocBuffers(int sizeA, int sizeB); 101 | MorphExport float getMemSize(); 102 | MorphExport void rebuildChannel(); 103 | MorphExport void buildFromNode(INode *node, BOOL resetTime = TRUE, TimeValue t = 0, BOOL picked = FALSE); 104 | 105 | MorphExport void operator =(const morphChannel& from); 106 | void operator =(const TargetCache& tcache); 107 | 108 | MorphExport IOResult Save(ISave *isave); 109 | MorphExport IOResult Load(ILoad *iload); 110 | 111 | void SetUpNewController(); 112 | int NumProgressiveTargets(void); 113 | void ResetRefs(MorphR3 *, const int&); 114 | float GetTargetPercent(const int& which); 115 | void ReNormalize(); 116 | void CopyTargetPercents(const morphChannel& chan); 117 | }; 118 | 119 | 120 | class morphCache 121 | { 122 | public: 123 | 124 | BOOL CacheValid; 125 | Point3 *oPoints; 126 | double *oWeights; 127 | BitArray sel; 128 | int Count; 129 | }; 130 | 131 | 132 | class MorphR3 : public Modifier, TimeChangeCallback 133 | { 134 | public: 135 | 136 | float mFileVersion; 137 | 138 | static IObjParam *ip; 139 | 140 | StdVector chanBank; 141 | M3Mat *morphmaterial; 142 | 143 | int chanSel; 144 | int chanNum; 145 | 146 | ISpinnerControl *chanSpins[10]; 147 | ISpinnerControl *glSpinmin, *glSpinmax; 148 | ISpinnerControl *cSpinmin, *cSpinmax, *cCurvature, *cTargetPercent; 149 | 150 | IParamBlock *pblock; 151 | 152 | HWND hwGlobalParams, hwChannelList, hwChannelParams, hwAdvanced, hwLegend; 153 | static HWND hMaxWnd; 154 | 155 | ICustEdit *newname; 156 | 157 | morphCache MC_Local; 158 | 159 | BOOL tccI; 160 | TCHAR trimD[50]; 161 | 162 | BOOL recordModifications; 163 | int recordTarget; 164 | 165 | Tab markerIndex; 166 | NameTab markerName; 167 | int markerSel; 168 | 169 | int cOp; 170 | int srcIdx; 171 | 172 | bool hackUI; 173 | 174 | MorphR3(); 175 | ~MorphR3(); 176 | 177 | void TimeChanged(TimeValue t); 178 | 179 | void DeleteThis(); 180 | void GetClassName(TSTR& s); 181 | virtual Class_ID ClassID(); 182 | RefTargetHandle Clone(RemapDir& remap); 183 | const TCHAR *GetObjectName(); 184 | 185 | SvGraphNodeReference SvTraverseAnimGraph(IGraphObjectManager *gom, Animatable *owner, int id, DWORD flags); 186 | TSTR SvGetRelTip(IGraphObjectManager *gom, IGraphNode *gNodeTarger, int id, IGraphNode *gNodeMaker); 187 | 188 | IOResult Load(ILoad *iload); 189 | IOResult Save(ISave *isave); 190 | 191 | ChannelMask ChannelsUsed(); 192 | ChannelMask ChannelsChanged(); 193 | 194 | void Bez3D(Point3& b, const Point3 *p, const float& u); 195 | void ModifyObject(TimeValue t, ModContext& mc, ObjectState *os, INode *node); 196 | Class_ID InputType(); 197 | 198 | Interval LocalValidity(TimeValue t); 199 | void NotifyInputChanged(Interval changeInt, PartID partID, RefMessage message, ModContext *mc); 200 | 201 | void DeleteChannel(const int&); 202 | 203 | BOOL ChangeTopology(); 204 | int GetParamBlockIndex(int id); 205 | 206 | int NumRefs(); 207 | RefTargetHandle GetReference(int i); 208 | 209 | private: 210 | 211 | virtual void SetReference(int i, RefTargetHandle rtarg); 212 | 213 | public: 214 | 215 | int NumSubs(); 216 | Animatable *SubAnim(int i); 217 | TSTR SubAnimName(int i); 218 | bool CheckMaterialDependency(void); 219 | bool CheckSubMaterialDependency(void); 220 | RefResult NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget, PartID& partID, RefMessage message); 221 | void TestMorphReferenceDependencies(const RefTargetHandle hTarget); 222 | 223 | CreateMouseCallBack *GetCreateMouseCallBack(); 224 | void BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev); 225 | void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next); 226 | 227 | Interval GetValidity(TimeValue t); 228 | ParamDimension *GetParameterDim(int pbIndex); 229 | TSTR GetParameterName(int pbIndex); 230 | 231 | MorphExport void VScroll(int code, short int cpos); 232 | MorphExport void Clamp_chanNum(); 233 | MorphExport void ChannelOp(int src, int targ, int flags); 234 | MorphExport void Update_globalParams(); 235 | MorphExport void Update_advancedParams(); 236 | MorphExport void Update_channelParams(); 237 | MorphExport float GetIncrements(); 238 | MorphExport void Update_SpinnerIncrements(); 239 | MorphExport void Update_colorIndicators(); 240 | MorphExport void Update_channelNames(); 241 | MorphExport void Update_channelValues(); 242 | MorphExport void Update_channelLimits(); 243 | MorphExport void Update_channelInfo(); 244 | MorphExport void Update_channelMarkers(); 245 | MorphExport void Update_channelFULL(); 246 | 247 | MorphExport float TrimDown(float value, int decimalpts); 248 | 249 | BOOL inRender; 250 | 251 | int RenderBegin(TimeValue t, ULONG flags); 252 | int RenderEnd(TimeValue t); 253 | 254 | int CurrentChannelIndex(void); 255 | morphChannel& CurrentChannel(void); 256 | 257 | float GetCurrentTargetPercent(void); 258 | void SetCurrentTargetPercent(const float& fval); 259 | 260 | void DeleteTarget(void); 261 | void Update_TargetListBoxNames(void); 262 | void SwapTargets(const int way); 263 | void SwapTargets(const int from, const int to, const bool isundo); 264 | 265 | int GetRefNumber(int chanNum, int targNum); 266 | void DisplayMemoryUsage(void); 267 | 268 | public: 269 | 270 | void RescaleWorldUnits(float f); 271 | }; 272 | 273 | 274 | #endif 275 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSMatrix2D.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #ifndef TSMatrix2D_h 11 | #define TSMatrix2D_h 12 | 13 | 14 | #include "TSVector2D.h" 15 | 16 | 17 | #define TERATHON_MATRIX2D 1 18 | 19 | 20 | namespace Terathon 21 | { 22 | class Matrix2D; 23 | struct ConstMatrix2D; 24 | 25 | 26 | // ============================================== 27 | // Matrix2D 28 | // ============================================== 29 | 30 | struct TypeMatrix2D 31 | { 32 | typedef float component_type; 33 | typedef Matrix2D matrix2D_type; 34 | typedef TypeVector2D column_type_struct; 35 | typedef TypeVector2D row_type_struct; 36 | }; 37 | 38 | 39 | /// \brief Encapsulates a 2 × 2 matrix. 40 | /// 41 | /// The $Matrix2D$ class is used to store a 2 × 2 matrix. The entries of the matrix 42 | /// are accessed using the () operator with two indexes specifying the row and column of an entry. 43 | /// 44 | /// \also Matrix3D 45 | /// \also Matrix4D 46 | /// \also Transform2D 47 | /// \also Transform3D 48 | 49 | class Matrix2D : public Mat2D 50 | { 51 | public: 52 | 53 | TERATHON_API static const ConstMatrix2D identity; 54 | 55 | /// \brief Default constructor that leaves the entries uninitialized. 56 | 57 | inline Matrix2D() = default; 58 | 59 | Matrix2D(const Matrix2D& m) 60 | { 61 | matrix = m.matrix; 62 | } 63 | 64 | /// \brief Constructor that sets entries explicitly. 65 | /// \param n00,n01,n10,n11 The entries of the matrix. 66 | 67 | TERATHON_API Matrix2D(float n00, float n01, float n10, float n11); 68 | 69 | /// \brief Constructor that sets columns explicitly. 70 | /// \param a,b The columns of the matrix. 71 | 72 | TERATHON_API Matrix2D(const Vector2D& a, const Vector2D& b); 73 | 74 | /// \brief Sets all four entries of a 2 × 2 matrix. 75 | /// \param n00,n01,n10,n11 The new entries of the matrix. 76 | 77 | TERATHON_API Matrix2D& Set(float n00, float n01, float n10, float n11); 78 | 79 | /// \brief Sets both columns of a 2 × 2 matrix. 80 | /// \param a,b The new columns of the matrix. 81 | 82 | TERATHON_API Matrix2D& Set(const Vector2D& a, const Vector2D& b); 83 | 84 | Matrix2D& operator =(const Matrix2D& m) 85 | { 86 | matrix = m.matrix; 87 | return (*this); 88 | } 89 | 90 | void operator =(const Matrix2D& m) volatile 91 | { 92 | matrix = m.matrix; 93 | } 94 | 95 | template 96 | Matrix2D& operator =(const Submat2D& m) 97 | { 98 | matrix = m; 99 | return (*this); 100 | } 101 | 102 | template 103 | void operator =(const Submat2D& m) volatile 104 | { 105 | matrix = m; 106 | } 107 | 108 | TERATHON_API Matrix2D& operator *=(const Matrix2D& m); 109 | TERATHON_API Matrix2D& operator *=(float s); 110 | TERATHON_API Matrix2D& operator /=(float s); 111 | 112 | /// \brief Sets a matrix to the 2 × 2 identity matrix. 113 | 114 | TERATHON_API Matrix2D& SetIdentity(void); 115 | 116 | /// \brief Orthogonalizes the columns of a 2 × 2 matrix. 117 | /// \param column The index of the column whose direction does not change. This must be 0 or 1. 118 | /// 119 | /// The $Orthogonalize()$ function uses Gram-Schmidt orthogonalization to orthogonalize the columns 120 | /// of a matrix. The column whose index is specified by the $column$ parameter is normalized to unit length. 121 | /// The remaining column is orthogonalized and made unit length. Only the column not specified by the 122 | /// $column$ parameter can change direction. 123 | 124 | TERATHON_API Matrix2D& Orthogonalize(int32 column); 125 | 126 | /// \brief Returns a 2 × 2 matrix that represents a rotation in the 2D plane. 127 | /// \param angle The angle through which to rotate, in radians. 128 | 129 | TERATHON_API static Matrix2D MakeRotation(float angle); 130 | 131 | /// \brief Returns a 2 × 2 matrix that represents a uniform scale. 132 | /// \param scale The scale along both axes. 133 | 134 | TERATHON_API static Matrix2D MakeScale(float scale); 135 | 136 | TERATHON_API static Matrix2D MakeScale(float sx, float sy); 137 | TERATHON_API static Matrix2D MakeScaleX(float sx); 138 | TERATHON_API static Matrix2D MakeScaleY(float sy); 139 | }; 140 | 141 | 142 | template 143 | inline typename type_struct::vector2D_type operator *(const Matrix2D& m, const Subvec2D& v) 144 | { 145 | return (m.matrix * v); 146 | } 147 | 148 | template 149 | inline typename type_struct::vector2D_type operator *(const Subvec2D& v, const Matrix2D& m) 150 | { 151 | return (v * m.matrix); 152 | } 153 | 154 | template 155 | inline Vector2D operator *(const Submat2D& m, const Vector2D& v) 156 | { 157 | return (m * v.xy); 158 | } 159 | 160 | template 161 | inline Vector2D operator *(const Vector2D& v, const Submat2D& m) 162 | { 163 | return (v.xy * m); 164 | } 165 | 166 | /// \brief Returns the product of the matrix $m$ and the column vector $v$. 167 | /// \related Matrix2D 168 | 169 | inline Vector2D operator *(const Matrix2D& m, const Vector2D& v) 170 | { 171 | return (m.matrix * v.xy); 172 | } 173 | 174 | /// \brief Returns the product of the matrix $m$ and the column vector $p$. 175 | /// \related Matrix2D 176 | 177 | inline Point2D operator *(const Matrix2D& m, const Point2D& p) 178 | { 179 | return (Point2D::origin + m.matrix * p.xy); 180 | } 181 | 182 | /// \brief Returns the product of the row vector $v$ and the matrix $m$. 183 | /// \related Matrix2D 184 | 185 | inline Vector2D operator *(const Vector2D& v, const Matrix2D& m) 186 | { 187 | return (v.xy * m.matrix); 188 | } 189 | 190 | /// \brief Returns the product of the matrices $m1$ and $m2$. 191 | /// \related Matrix2D 192 | 193 | inline Matrix2D operator *(const Matrix2D& m1, const Matrix2D& m2) 194 | { 195 | return (m1.matrix * m2.matrix); 196 | } 197 | 198 | template 199 | inline Matrix2D operator *(const Matrix2D& m1, const Submat2D& m2) 200 | { 201 | return (m1.matrix * m2); 202 | } 203 | 204 | template 205 | inline Matrix2D operator *(const Submat2D& m1, const Matrix2D& m2) 206 | { 207 | return (m1 * m2.matrix); 208 | } 209 | 210 | 211 | TERATHON_API Matrix2D operator *(const Matrix2D& m, float s); 212 | TERATHON_API Matrix2D operator /(const Matrix2D& m, float s); 213 | 214 | inline Matrix2D operator *(float s, const Matrix2D& m) 215 | { 216 | return (m * s); 217 | } 218 | 219 | 220 | /// \brief Returns the determinant of the matrix $m$. 221 | /// \related Matrix2D 222 | 223 | TERATHON_API float Determinant(const Matrix2D& m); 224 | 225 | /// \brief Returns the inverse of the matrix $m$. If $m$ is singular, then the result is undefined. 226 | /// \related Matrix2D 227 | 228 | TERATHON_API Matrix2D Inverse(const Matrix2D& m); 229 | 230 | /// \brief Returns the adjugate of the matrix $m$. 231 | /// \related Matrix2D 232 | 233 | TERATHON_API Matrix2D Adjugate(const Matrix2D& m); 234 | 235 | 236 | // ============================================== 237 | // POD Structures 238 | // ============================================== 239 | 240 | struct ConstMatrix2D 241 | { 242 | float n[2][2]; 243 | 244 | operator const Matrix2D&(void) const 245 | { 246 | return (reinterpret_cast(*this)); 247 | } 248 | 249 | const Matrix2D *operator &(void) const 250 | { 251 | return (reinterpret_cast(this)); 252 | } 253 | 254 | const Matrix2D *operator ->(void) const 255 | { 256 | return (reinterpret_cast(this)); 257 | } 258 | 259 | float operator ()(int32 i, int32 j) const 260 | { 261 | return (reinterpret_cast(*this)(i, j)); 262 | } 263 | 264 | const Vector2D& operator [](machine j) const 265 | { 266 | return (reinterpret_cast(*this)[j]); 267 | } 268 | }; 269 | } 270 | 271 | 272 | #endif 273 | -------------------------------------------------------------------------------- /Exporter3dsmax/OpenGex-Max.h: -------------------------------------------------------------------------------- 1 | // 2 | // OpenGEX exporter for 3ds Max 3 | // Version 3.0 4 | // 5 | // This file is part of the Open Game Engine Exchange library, by Eric Lengyel. 6 | // Copyright 2013-2022, Terathon Software LLC 7 | // 8 | // This software is distributed under the MIT License. 9 | // Separate proprietary licenses are available from Terathon Software. 10 | // 11 | 12 | 13 | #ifndef OpenGex_Max_h 14 | #define OpenGex_Max_h 15 | 16 | 17 | #include "maxapi.h" 18 | #include "units.h" 19 | #include "inode.h" 20 | #include "triobj.h" 21 | #include "iskin.h" 22 | #include "genlight.h" 23 | #include "control.h" 24 | #include "modstack.h" 25 | #include "stdmat.h" 26 | #include "euler.h" 27 | #include "istdplug.h" 28 | #include "iparamb2.h" 29 | #include "iiksys.h" 30 | #include "impexp.h" 31 | #include "CS/bipexp.h" 32 | #include "VertexNormal.h" 33 | #include "MorphR3.h" 34 | #include 35 | #include 36 | 37 | 38 | class OpenGexClassDesc : public ClassDesc2 39 | { 40 | public: 41 | 42 | OpenGexClassDesc(); 43 | ~OpenGexClassDesc(); 44 | 45 | int IsPublic(void) override; 46 | void *Create(BOOL loading) override; 47 | const MCHAR *ClassName(void) override; 48 | SClass_ID SuperClassID(void) override; 49 | Class_ID ClassID(void) override; 50 | const MCHAR *Category(void) override; 51 | }; 52 | 53 | 54 | namespace OpenGex 55 | { 56 | enum 57 | { 58 | kMaxTexcoordCount = 2 59 | }; 60 | 61 | 62 | enum 63 | { 64 | kNodeTypeNode, 65 | kNodeTypeBone, 66 | kNodeTypeGeometry, 67 | kNodeTypeLight, 68 | kNodeTypeCamera, 69 | kNodeTypeCount 70 | }; 71 | 72 | 73 | struct NodeReference 74 | { 75 | INode *node; 76 | int nodeType; 77 | std::string structName; 78 | 79 | NodeReference(INode *n, int type, const char *name) : node(n), nodeType(type), structName(name) {} 80 | NodeReference(const NodeReference& nodeReference) : node(nodeReference.node), nodeType(nodeReference.nodeType), structName(nodeReference.structName) {} 81 | }; 82 | 83 | 84 | struct ObjectReference 85 | { 86 | Object *object; 87 | std::string structName; 88 | std::vector nodeTable; 89 | 90 | ObjectReference(Object *obj, const char *name, INode *node) : object(obj), structName(name), nodeTable(1, node) {} 91 | ObjectReference(const ObjectReference& objectReference) : object(objectReference.object), structName(objectReference.structName), nodeTable(objectReference.nodeTable) {} 92 | }; 93 | 94 | 95 | struct MaterialReference 96 | { 97 | StdMat *material; 98 | std::string structName; 99 | 100 | MaterialReference(StdMat *mat, const char *name) : material(mat), structName(name) {} 101 | MaterialReference(const MaterialReference& materialReference) : material(materialReference.material), structName(materialReference.structName) {} 102 | }; 103 | 104 | 105 | struct ExportVertex 106 | { 107 | unsigned int hash; 108 | unsigned int index; 109 | 110 | Point3 position; 111 | Point3 normal; 112 | Point3 color; 113 | Point2 texcoord[kMaxTexcoordCount]; 114 | 115 | ExportVertex(); 116 | 117 | bool operator ==(const ExportVertex& v) const; 118 | 119 | void Hash(void); 120 | }; 121 | } 122 | 123 | 124 | class OpenGexExport : public SceneExport 125 | { 126 | private: 127 | 128 | HANDLE exportFile; 129 | int indentLevel; 130 | 131 | TimeValue startTime; 132 | TimeValue endTime; 133 | 134 | std::vector *nodeArray; 135 | std::vector *geometryArray; 136 | std::vector *lightArray; 137 | std::vector *cameraArray; 138 | std::vector *materialArray; 139 | 140 | void Write(const void *buffer, unsigned int size) const; 141 | void Write(const char *string) const; 142 | void Write(const wchar_t *string) const; 143 | void IndentWrite(const char *string, int extra = 0, bool newline = false) const; 144 | 145 | void WriteInt(int i) const; 146 | void WriteUnsignedInt(unsigned int i) const; 147 | void WriteFloat(float f) const; 148 | void WriteHexFloat(float f) const; 149 | void WriteMatrix(const Matrix3& matrix) const; 150 | void WriteMatrixFlat(const Matrix3& matrix) const; 151 | void WriteHexMatrixFlat(const Matrix3& matrix) const; 152 | void WritePoint3(const Point3& point) const; 153 | void WriteHexPoint3(const Point3& point) const; 154 | void WriteQuat(const Quat& quat) const; 155 | void WriteHexQuat(const Quat& quat) const; 156 | void WriteColor(const Color& color) const; 157 | void WriteFileName(const wchar_t *string) const; 158 | 159 | void WriteIntArray(int count, const int *value) const; 160 | void WriteFloatArray(int count, const float *value) const; 161 | 162 | void WriteVertex(const Point2& vertex) const; 163 | void WriteVertex(const Point3& vertex) const; 164 | template void WriteVertexArray(int count, const type *vertex, int stride) const; 165 | void WriteMorphVertexArray(int count, const OpenGex::ExportVertex *exportVertex, const Point3 *morphVertex) const; 166 | void WriteMorphNormalArray(int count, const Point3 *morphNormal) const; 167 | 168 | void WriteTriangle(int triangleIndex, const int *indexTable) const; 169 | void WriteTriangleArray(int count, const int *indexTable) const; 170 | 171 | void WriteNodeTable(const OpenGex::ObjectReference *objectRef) const; 172 | 173 | int GetNodeType(INode *node) const; 174 | static ISkin *GetSkinInterface(Object *object); 175 | static MorphR3 *GetMorphModifier(Object *object); 176 | static bool ActiveMorphChannel(const morphChannel *channel); 177 | 178 | OpenGex::NodeReference *FindNode(const INode *node) const; 179 | static OpenGex::ObjectReference *FindObject(std::vector *array, const Object *object); 180 | OpenGex::MaterialReference *FindMaterial(const StdMat *material); 181 | 182 | static OpenGex::ExportVertex *DeindexMesh(Mesh *mesh, Mesh *baseMesh, int *exportTriangleCount, int *exportColorCount, int *exportTexcoordCount); 183 | static int FindExportVertex(const std::vector& bucket, const OpenGex::ExportVertex *exportVertex, const OpenGex::ExportVertex& vertex); 184 | static int UnifyVertices(int vertexCount, const OpenGex::ExportVertex *exportVertex, OpenGex::ExportVertex *unifiedVertex, int *indexTable); 185 | static void CalculateMorphNormalArray(int vertexCount, int triangleCount, const int *indexTable, const OpenGex::ExportVertex *exportVertex, const Point3 *morphVertex, Point3 *morphNormal); 186 | 187 | void ProcessNode(INode *node, bool exportAllFlag); 188 | void ProcessSkinnedMeshes(void); 189 | 190 | template static bool AnimationKeysDifferent(IKeyControl *keyInterface); 191 | template static bool AnimationTangentsNonzero(IKeyControl *keyInterface); 192 | static bool AnimationPresent(Control *control); 193 | 194 | template void ExportKeyTimes(IKeyControl *keyInterface); 195 | template void ExportKeyTimeControlPoints(IKeyControl *keyInterface); 196 | void ExportFloatKeyTimeControlPoints(IKeyControl *keyInterface); 197 | template void ExportFloatKeyValues(IKeyControl *keyInterface, float scale = 1.0F); 198 | void ExportFloatKeyValueControlPoints(IKeyControl *keyInterface, float scale = 1.0F); 199 | template void ExportPoint3KeyValues(IKeyControl *keyInterface); 200 | template void ExportPoint3KeyValueControlPoints(IKeyControl *keyInterface); 201 | template void ExportQuatKeyValues(IKeyControl *keyInterface, bool relative = false); 202 | template void ExportInvQuatKeyValues(IKeyControl *keyInterface); 203 | template void ExportFloatKeyData(IKeyControl *keyInterface, const char *kind, const float keyType::*data, float scale = 1.0F); 204 | 205 | void ExportAnimationTrack(Control *control, const char *target, bool newline, float scale = 1.0F); 206 | void ExportSampledAnimation(INode *node); 207 | 208 | void ExportObjectTransform(INode *node); 209 | void ExportTransform(INode *node); 210 | 211 | void ExportMaterialRef(Mtl *material, int index = -1); 212 | void ExportMorphWeights(MorphR3 *morpher); 213 | void ExportNode(INode *node); 214 | 215 | void ExportSkin(ISkin *skin, INode *node, int vertexCount, const OpenGex::ExportVertex *exportVertex); 216 | void ExportGeometry(const OpenGex::ObjectReference *objectRef); 217 | void ExportLight(const OpenGex::ObjectReference *objectRef); 218 | void ExportCamera(const OpenGex::ObjectReference *objectRef); 219 | void ExportObjects(void); 220 | 221 | void ExportTexture(StdMat *material, int slot, const char *attrib); 222 | void ExportMaterials(void); 223 | 224 | void ExportMetrics(void); 225 | 226 | public: 227 | 228 | OpenGexExport(); 229 | ~OpenGexExport(); 230 | 231 | int ExtCount(void) override; 232 | const MCHAR *Ext(int n) override; 233 | 234 | const MCHAR *LongDesc(void) override; 235 | const MCHAR *ShortDesc(void) override; 236 | 237 | const MCHAR *AuthorName(void) override; 238 | const MCHAR *CopyrightMessage(void) override; 239 | const MCHAR *OtherMessage1(void) override; 240 | const MCHAR *OtherMessage2(void) override; 241 | 242 | unsigned int Version(void) override; 243 | void ShowAbout(HWND hWnd) override; 244 | 245 | int DoExport(const MCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts, DWORD options) override; 246 | BOOL SupportsOptions(int ext, DWORD options) override; 247 | }; 248 | 249 | 250 | #endif 251 | -------------------------------------------------------------------------------- /ExporterMaya/OpenGex-Maya.h: -------------------------------------------------------------------------------- 1 | // 2 | // OpenGEX exporter for Maya 3 | // Version 3.0 4 | // 5 | // This file is part of the Open Game Engine Exchange library, by Eric Lengyel. 6 | // Copyright 2013-2022, Terathon Software LLC 7 | // 8 | // This software is distributed under the MIT License. 9 | // Separate proprietary licenses are available from Terathon Software. 10 | // 11 | 12 | 13 | #ifndef OpenGex_Maya_h 14 | #define OpenGex_Maya_h 15 | 16 | 17 | #include 18 | #include 19 | #include 20 | #include "maya/MGlobal.h" 21 | #include "maya/MIOStream.h" 22 | #include "maya/MPxFileTranslator.h" 23 | #include "maya/MAnimControl.h" 24 | #include "maya/MSelectionList.h" 25 | #include "maya/MMatrix.h" 26 | #include "maya/MEulerRotation.h" 27 | #include "maya/MQuaternion.h" 28 | #include "maya/MFloatArray.h" 29 | #include "maya/MFloatVectorArray.h" 30 | #include "maya/MFloatPointArray.h" 31 | #include "maya/MPlugArray.h" 32 | #include "maya/MDagPathArray.h" 33 | #include "maya/MDagPath.h" 34 | #include "maya/MItDependencyGraph.h" 35 | #include "maya/MItDag.h" 36 | #include "maya/MFnSet.h" 37 | #include "maya/MFnDagNode.h" 38 | #include "maya/MFnTransform.h" 39 | #include "maya/MFnIkJoint.h" 40 | #include "maya/MFnMesh.h" 41 | #include "maya/MFnSkinCluster.h" 42 | #include "maya/MFnBlendShapeDeformer.h" 43 | #include "maya/MFnSpotLight.h" 44 | #include "maya/MFnCamera.h" 45 | #include "maya/MFnAttribute.h" 46 | #include "maya/MFnAnimCurve.h" 47 | #include "maya/MFnMatrixData.h" 48 | #include "maya/MFnPhongShader.h" 49 | #include "maya/MFnPlugin.h" 50 | 51 | 52 | namespace OpenGex 53 | { 54 | enum 55 | { 56 | kMaxVertexColorCount = 2, 57 | kMaxTexcoordCount = 2 58 | }; 59 | 60 | 61 | enum 62 | { 63 | kNodeTypeNone = -1, 64 | kNodeTypeNode, 65 | kNodeTypeBone, 66 | kNodeTypeGeometry, 67 | kNodeTypeLight, 68 | kNodeTypeCamera, 69 | kNodeTypeCount 70 | }; 71 | 72 | 73 | struct NodeReference 74 | { 75 | MObject node; 76 | int nodeType; 77 | int childIndex; 78 | std::string structName; 79 | 80 | NodeReference(const MObject& n, int type, int index, const char *name) : node(n), nodeType(type), childIndex(index), structName(name) {} 81 | NodeReference(const NodeReference& nodeReference) : node(nodeReference.node), nodeType(nodeReference.nodeType), childIndex(nodeReference.childIndex), structName(nodeReference.structName) {} 82 | }; 83 | 84 | 85 | struct ObjectReference 86 | { 87 | MObject object; 88 | std::string structName; 89 | std::vector nodeTable; 90 | 91 | ObjectReference(const MObject& obj, const char *name, const MObject& node) : object(obj), structName(name), nodeTable(1, node) {} 92 | ObjectReference(const ObjectReference& objectReference) : object(objectReference.object), structName(objectReference.structName), nodeTable(objectReference.nodeTable) {} 93 | }; 94 | 95 | 96 | struct MaterialReference 97 | { 98 | MObject material; 99 | std::string structName; 100 | 101 | MaterialReference(const MObject& mat, const char *name) : material(mat), structName(name) {} 102 | MaterialReference(const MaterialReference& materialReference) : material(materialReference.material), structName(materialReference.structName) {} 103 | }; 104 | 105 | 106 | struct TextureReference 107 | { 108 | MObject texture; 109 | int texcoord; 110 | 111 | TextureReference(const MObject& tex, int coord) : texture(tex), texcoord(coord) {} 112 | TextureReference(const TextureReference& textureReference) : texture(textureReference.texture), texcoord(textureReference.texcoord) {} 113 | }; 114 | 115 | 116 | struct ExportVertex 117 | { 118 | unsigned int hash; 119 | unsigned int vertexIndex; 120 | unsigned int normalIndex; 121 | 122 | MFloatVector position; 123 | MFloatVector normal; 124 | MColor color[kMaxVertexColorCount]; 125 | float texcoord[kMaxTexcoordCount][2]; 126 | 127 | ExportVertex(); 128 | 129 | bool operator ==(const ExportVertex& v) const; 130 | 131 | void Hash(void); 132 | }; 133 | } 134 | 135 | 136 | class OpenGexExport : public MPxFileTranslator 137 | { 138 | private: 139 | 140 | HANDLE exportFile; 141 | int indentLevel; 142 | 143 | std::vector *nodeArray; 144 | std::vector *geometryArray; 145 | std::vector *lightArray; 146 | std::vector *cameraArray; 147 | std::vector *materialArray; 148 | std::vector *textureArray; 149 | 150 | void Write(const void *buffer, unsigned int size) const; 151 | void Write(const char *string) const; 152 | void Write(const wchar_t *string) const; 153 | void IndentWrite(const char *string, int extra = 0, bool newline = false) const; 154 | 155 | void WriteInt(int i) const; 156 | void WriteUnsignedInt(unsigned int i) const; 157 | void WriteFloat(float f) const; 158 | void WriteHexFloat(float f) const; 159 | void WriteMatrix(const MMatrix& matrix) const; 160 | void WriteMatrixFlat(const MMatrix& matrix) const; 161 | void WriteHexMatrixFlat(const MMatrix& matrix) const; 162 | void WriteVector(const MVector& point) const; 163 | void WriteHexVector(const MVector& point) const; 164 | void WriteQuaternion(const MQuaternion& quat) const; 165 | void WriteHexQuaternion(const MQuaternion& quat) const; 166 | void WriteColor(const MColor& color) const; 167 | void WriteFileName(const char *string) const; 168 | 169 | void WriteIntArray(int count, const int *value) const; 170 | void WriteFloatArray(int count, const float *value) const; 171 | 172 | void WriteVertex(const float (& vertex)[2]) const; 173 | void WriteVertex(const MFloatVector& vertex) const; 174 | void WriteVertex(const MColor& vertex) const; 175 | template void WriteVertexArray(int count, const type *vertex, int stride) const; 176 | void WriteMorphVertexArray(int count, const OpenGex::ExportVertex *exportVertex, const MFloatPointArray& morphVertexArray); 177 | void WriteMorphNormalArray(int count, const OpenGex::ExportVertex *exportVertex, const MFloatVectorArray& morphNormalArray); 178 | 179 | void WriteTriangle(int triangleIndex, const int *indexTable) const; 180 | void WriteTriangleArray(int count, const int *indexTable) const; 181 | 182 | void WriteNodeTable(const OpenGex::ObjectReference *objectRef) const; 183 | 184 | int GetNodeType(const MObject& node, int *childIndex) const; 185 | static MFnSkinCluster *GetSkinCluster(const MObject& node); 186 | static bool FindSkinClusterInputGeometry(const MFnSkinCluster *skin, MObject *object); 187 | static MFnBlendShapeDeformer *GetBlendShapeDeformer(const MObject& node, unsigned int *geometryIndex = nullptr); 188 | static bool FindBlendShapeDeformerInputGeometry(const MFnBlendShapeDeformer *deformer, unsigned int geometryIndex, MObject *object); 189 | 190 | OpenGex::NodeReference *FindNode(const MObject& node) const; 191 | static OpenGex::ObjectReference *FindObject(std::vector *array, const MObject& object); 192 | OpenGex::MaterialReference *FindMaterial(const MObject& material); 193 | OpenGex::TextureReference *FindTexture(const MObject& texture); 194 | 195 | static int GetLocalIndex(int index, const MIntArray& globalIndexArray); 196 | OpenGex::ExportVertex *DeindexMesh(MFnMesh *mesh, const MFnMesh *baseMesh, int *exportTriangleCount, int *exportColorCount, int *exportTexcoordCount, int **polygonIndexArray); 197 | static int FindExportVertex(const std::vector& bucket, const OpenGex::ExportVertex *exportVertex, const OpenGex::ExportVertex& vertex); 198 | static int UnifyVertices(int vertexCount, const OpenGex::ExportVertex *exportVertex, OpenGex::ExportVertex *unifiedVertex, int *indexTable); 199 | 200 | void ProcessNode(const MDagPath& dagPath, const MSelectionList *exportList); 201 | void ProcessSkinnedMeshes(void); 202 | 203 | static bool AnimationPresent(const MFnAnimCurve& animCurve); 204 | 205 | void ExportKeyTimes(const MFnAnimCurve& animCurve); 206 | void ExportKeyTimeControlPoints(const MFnAnimCurve& animCurve); 207 | void ExportKeyValues(const MFnAnimCurve& animCurve, float scale = 1.0F); 208 | void ExportKeyValueControlPoints(const MFnAnimCurve& animCurve, float scale = 1.0F); 209 | void ExportAnimationTrack(const MFnAnimCurve& animCurve, const char *target, bool newline, float scale = 1.0F); 210 | 211 | void ExportTransform(const MObject& node, const MObject& parent); 212 | void ExportMaterialRef(const MObject& material, int index); 213 | void ExportMorphWeights(const MObject& node, const MFnBlendShapeDeformer *deformer); 214 | void ExportNode(const MDagPath& dagPath, const MObject& parent); 215 | 216 | void ExportSkin(const MFnSkinCluster& skin, const MObject& object, int vertexCount, const OpenGex::ExportVertex *exportVertex); 217 | void ExportGeometry(const OpenGex::ObjectReference *objectRef); 218 | void ExportLight(const OpenGex::ObjectReference *objectRef); 219 | void ExportCamera(const OpenGex::ObjectReference *objectRef); 220 | void ExportObjects(void); 221 | 222 | bool ExportTexture(const MFnDependencyNode& shader, const char *input, const char *attrib); 223 | void ExportMaterials(void); 224 | 225 | void ExportMetrics(void); 226 | 227 | public: 228 | 229 | OpenGexExport(); 230 | ~OpenGexExport(); 231 | 232 | static void *New(void); 233 | 234 | MStatus writer(const MFileObject& file, const MString& optionsString, FileAccessMode mode) override; 235 | bool haveWriteMethod(void) const override; 236 | MString defaultExtension(void) const override; 237 | MFileKind identifyFile(const MFileObject& file, const char *buffer, short size) const override; 238 | }; 239 | 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSTree.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Container Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSTree.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | TreeBase::~TreeBase() 17 | { 18 | PurgeSubtree(); 19 | 20 | if (superNode) 21 | { 22 | superNode->RemoveSubnode(this); 23 | } 24 | } 25 | 26 | TreeBase *TreeBase::GetRootNode(void) 27 | { 28 | TreeBase *root = this; 29 | for (;;) 30 | { 31 | TreeBase *node = root->superNode; 32 | if (!node) 33 | { 34 | break; 35 | } 36 | 37 | root = node; 38 | } 39 | 40 | return (root); 41 | } 42 | 43 | const TreeBase *TreeBase::GetRootNode(void) const 44 | { 45 | const TreeBase *root = this; 46 | for (;;) 47 | { 48 | const TreeBase *node = root->superNode; 49 | if (!node) 50 | { 51 | break; 52 | } 53 | 54 | root = node; 55 | } 56 | 57 | return (root); 58 | } 59 | 60 | bool TreeBase::Successor(const TreeBase *node) const 61 | { 62 | TreeBase *super = node->superNode; 63 | while (super) 64 | { 65 | if (super == this) 66 | { 67 | return (true); 68 | } 69 | 70 | super = super->superNode; 71 | } 72 | 73 | return (false); 74 | } 75 | 76 | TreeBase *TreeBase::GetLeftmostNode(void) 77 | { 78 | TreeBase *node = this; 79 | for (;;) 80 | { 81 | TreeBase *subnode = node->firstSubnode; 82 | if (!subnode) 83 | { 84 | break; 85 | } 86 | 87 | node = subnode; 88 | } 89 | 90 | return (node); 91 | } 92 | 93 | const TreeBase *TreeBase::GetLeftmostNode(void) const 94 | { 95 | const TreeBase *node = this; 96 | for (;;) 97 | { 98 | const TreeBase *subnode = node->firstSubnode; 99 | if (!subnode) 100 | { 101 | break; 102 | } 103 | 104 | node = subnode; 105 | } 106 | 107 | return (node); 108 | } 109 | 110 | TreeBase *TreeBase::GetRightmostNode(void) 111 | { 112 | TreeBase *node = this; 113 | for (;;) 114 | { 115 | TreeBase *subnode = node->lastSubnode; 116 | if (!subnode) 117 | { 118 | break; 119 | } 120 | 121 | node = subnode; 122 | } 123 | 124 | return (node); 125 | } 126 | 127 | const TreeBase *TreeBase::GetRightmostNode(void) const 128 | { 129 | const TreeBase *node = this; 130 | for (;;) 131 | { 132 | const TreeBase *subnode = node->lastSubnode; 133 | if (!subnode) 134 | { 135 | break; 136 | } 137 | 138 | node = subnode; 139 | } 140 | 141 | return (node); 142 | } 143 | 144 | TreeBase *TreeBase::GetNextTreeNode(const TreeBase *node) const 145 | { 146 | TreeBase *next = node->firstSubnode; 147 | if (!next) 148 | { 149 | for (;;) 150 | { 151 | if (node == this) 152 | { 153 | break; 154 | } 155 | 156 | next = node->nextNode; 157 | if (next) 158 | { 159 | break; 160 | } 161 | 162 | node = node->superNode; 163 | } 164 | } 165 | 166 | return (next); 167 | } 168 | 169 | TreeBase *TreeBase::GetPreviousTreeNode(const TreeBase *node) 170 | { 171 | if (node == this) 172 | { 173 | return (nullptr); 174 | } 175 | 176 | TreeBase *prev = node->prevNode; 177 | if (!prev) 178 | { 179 | return (node->superNode); 180 | } 181 | 182 | return (prev->GetRightmostNode()); 183 | } 184 | 185 | const TreeBase *TreeBase::GetPreviousTreeNode(const TreeBase *node) const 186 | { 187 | if (node == this) 188 | { 189 | return (nullptr); 190 | } 191 | 192 | const TreeBase *prev = node->prevNode; 193 | if (!prev) 194 | { 195 | return (node->superNode); 196 | } 197 | 198 | return (prev->GetRightmostNode()); 199 | } 200 | 201 | TreeBase *TreeBase::GetNextLevelNode(const TreeBase *node) const 202 | { 203 | TreeBase *next = nullptr; 204 | for (;;) 205 | { 206 | if (node == this) 207 | { 208 | break; 209 | } 210 | 211 | next = node->nextNode; 212 | if (next) 213 | { 214 | break; 215 | } 216 | 217 | node = node->superNode; 218 | } 219 | 220 | return (next); 221 | } 222 | 223 | TreeBase *TreeBase::GetPreviousLevelNode(const TreeBase *node) const 224 | { 225 | TreeBase *prev = nullptr; 226 | for (;;) 227 | { 228 | if (node == this) 229 | { 230 | break; 231 | } 232 | 233 | prev = node->prevNode; 234 | if (prev) 235 | { 236 | break; 237 | } 238 | 239 | node = node->superNode; 240 | } 241 | 242 | return (prev); 243 | } 244 | 245 | int32 TreeBase::GetSubnodeCount(void) const 246 | { 247 | machine count = 0; 248 | const TreeBase *subnode = firstSubnode; 249 | while (subnode) 250 | { 251 | count++; 252 | subnode = subnode->nextNode; 253 | } 254 | 255 | return (int32(count)); 256 | } 257 | 258 | int32 TreeBase::GetSubtreeNodeCount(void) const 259 | { 260 | machine count = 0; 261 | const TreeBase *subnode = firstSubnode; 262 | while (subnode) 263 | { 264 | count++; 265 | subnode = GetNextTreeNode(subnode); 266 | } 267 | 268 | return (int32(count)); 269 | } 270 | 271 | int32 TreeBase::GetNodeIndex(void) const 272 | { 273 | machine index = 0; 274 | const TreeBase *element = this; 275 | for (;;) 276 | { 277 | element = element->prevNode; 278 | if (!element) 279 | { 280 | break; 281 | } 282 | 283 | index++; 284 | } 285 | 286 | return (int32(index)); 287 | } 288 | 289 | int32 TreeBase::GetNodeDepth(void) const 290 | { 291 | machine depth = 0; 292 | const TreeBase *element = this; 293 | for (;;) 294 | { 295 | element = element->superNode; 296 | if (!element) 297 | { 298 | break; 299 | } 300 | 301 | depth++; 302 | } 303 | 304 | return (int32(depth)); 305 | } 306 | 307 | void TreeBase::MoveSubtree(TreeBase *super) 308 | { 309 | for (;;) 310 | { 311 | TreeBase *node = firstSubnode; 312 | if (!node) 313 | { 314 | break; 315 | } 316 | 317 | super->AppendSubnode(node); 318 | } 319 | } 320 | 321 | void TreeBase::RemoveSubtree(void) 322 | { 323 | TreeBase *subnode = firstSubnode; 324 | while (subnode) 325 | { 326 | TreeBase *next = subnode->nextNode; 327 | subnode->prevNode = nullptr; 328 | subnode->nextNode = nullptr; 329 | subnode->superNode = nullptr; 330 | subnode = next; 331 | } 332 | 333 | firstSubnode = nullptr; 334 | lastSubnode = nullptr; 335 | } 336 | 337 | void TreeBase::PurgeSubtree(void) 338 | { 339 | while (firstSubnode) 340 | { 341 | delete firstSubnode; 342 | } 343 | } 344 | 345 | void TreeBase::AppendSubnode(TreeBase *node) 346 | { 347 | TreeBase *tree = node->superNode; 348 | if (tree) 349 | { 350 | TreeBase *prev = node->prevNode; 351 | TreeBase *next = node->nextNode; 352 | 353 | if (prev) 354 | { 355 | prev->nextNode = next; 356 | node->prevNode = nullptr; 357 | } 358 | 359 | if (next) 360 | { 361 | next->prevNode = prev; 362 | node->nextNode = nullptr; 363 | } 364 | 365 | if (tree->firstSubnode == node) 366 | { 367 | tree->firstSubnode = next; 368 | } 369 | 370 | if (tree->lastSubnode == node) 371 | { 372 | tree->lastSubnode = prev; 373 | } 374 | } 375 | 376 | node->superNode = this; 377 | 378 | if (lastSubnode) 379 | { 380 | lastSubnode->nextNode = node; 381 | node->prevNode = lastSubnode; 382 | lastSubnode = node; 383 | } 384 | else 385 | { 386 | firstSubnode = node; 387 | lastSubnode = node; 388 | } 389 | } 390 | 391 | void TreeBase::PrependSubnode(TreeBase *node) 392 | { 393 | TreeBase *tree = node->superNode; 394 | if (tree) 395 | { 396 | TreeBase *prev = node->prevNode; 397 | TreeBase *next = node->nextNode; 398 | 399 | if (prev) 400 | { 401 | prev->nextNode = next; 402 | node->prevNode = nullptr; 403 | } 404 | 405 | if (next) 406 | { 407 | next->prevNode = prev; 408 | node->nextNode = nullptr; 409 | } 410 | 411 | if (tree->firstSubnode == node) 412 | { 413 | tree->firstSubnode = next; 414 | } 415 | 416 | if (tree->lastSubnode == node) 417 | { 418 | tree->lastSubnode = prev; 419 | } 420 | } 421 | 422 | node->superNode = this; 423 | 424 | if (firstSubnode) 425 | { 426 | firstSubnode->prevNode = node; 427 | node->nextNode = firstSubnode; 428 | firstSubnode = node; 429 | } 430 | else 431 | { 432 | firstSubnode = node; 433 | lastSubnode = node; 434 | } 435 | } 436 | 437 | void TreeBase::InsertSubnodeBefore(TreeBase *node, TreeBase *before) 438 | { 439 | TreeBase *tree = node->superNode; 440 | if (tree) 441 | { 442 | TreeBase *prev = node->prevNode; 443 | TreeBase *next = node->nextNode; 444 | 445 | if (prev) 446 | { 447 | prev->nextNode = next; 448 | } 449 | 450 | if (next) 451 | { 452 | next->prevNode = prev; 453 | } 454 | 455 | if (tree->firstSubnode == node) 456 | { 457 | tree->firstSubnode = next; 458 | } 459 | 460 | if (tree->lastSubnode == node) 461 | { 462 | tree->lastSubnode = prev; 463 | } 464 | } 465 | 466 | node->superNode = this; 467 | node->nextNode = before; 468 | 469 | if (before) 470 | { 471 | TreeBase *after = before->prevNode; 472 | node->prevNode = after; 473 | before->prevNode = node; 474 | 475 | if (after) 476 | { 477 | after->nextNode = node; 478 | } 479 | else 480 | { 481 | firstSubnode = node; 482 | } 483 | } 484 | else 485 | { 486 | TreeBase *after = lastSubnode; 487 | node->prevNode = after; 488 | 489 | if (after) 490 | { 491 | after->nextNode = node; 492 | lastSubnode = node; 493 | } 494 | else 495 | { 496 | firstSubnode = node; 497 | lastSubnode = node; 498 | } 499 | } 500 | } 501 | 502 | void TreeBase::InsertSubnodeAfter(TreeBase *node, TreeBase *after) 503 | { 504 | TreeBase *tree = node->superNode; 505 | if (tree) 506 | { 507 | TreeBase *prev = node->prevNode; 508 | TreeBase *next = node->nextNode; 509 | 510 | if (prev) 511 | { 512 | prev->nextNode = next; 513 | } 514 | 515 | if (next) 516 | { 517 | next->prevNode = prev; 518 | } 519 | 520 | if (tree->firstSubnode == node) 521 | { 522 | tree->firstSubnode = next; 523 | } 524 | 525 | if (tree->lastSubnode == node) 526 | { 527 | tree->lastSubnode = prev; 528 | } 529 | } 530 | 531 | node->superNode = this; 532 | node->prevNode = after; 533 | 534 | if (after) 535 | { 536 | TreeBase *before = after->nextNode; 537 | node->nextNode = before; 538 | after->nextNode = node; 539 | 540 | if (before) 541 | { 542 | before->prevNode = node; 543 | } 544 | else 545 | { 546 | lastSubnode = node; 547 | } 548 | } 549 | else 550 | { 551 | TreeBase *before = firstSubnode; 552 | node->nextNode = before; 553 | 554 | if (before) 555 | { 556 | before->prevNode = node; 557 | firstSubnode = node; 558 | } 559 | else 560 | { 561 | firstSubnode = node; 562 | lastSubnode = node; 563 | } 564 | } 565 | } 566 | 567 | void TreeBase::RemoveSubnode(TreeBase *node) 568 | { 569 | TreeBase *prev = node->prevNode; 570 | TreeBase *next = node->nextNode; 571 | 572 | if (prev) 573 | { 574 | prev->nextNode = next; 575 | } 576 | 577 | if (next) 578 | { 579 | next->prevNode = prev; 580 | } 581 | 582 | if (firstSubnode == node) 583 | { 584 | firstSubnode = next; 585 | } 586 | 587 | if (lastSubnode == node) 588 | { 589 | lastSubnode = prev; 590 | } 591 | 592 | node->prevNode = nullptr; 593 | node->nextNode = nullptr; 594 | node->superNode = nullptr; 595 | } 596 | 597 | void TreeBase::Detach(void) 598 | { 599 | if (superNode) 600 | { 601 | superNode->RemoveSubnode(this); 602 | } 603 | } 604 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSBivector3D.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #ifndef TSBivector3D_h 11 | #define TSBivector3D_h 12 | 13 | 14 | #include "TSVector3D.h" 15 | 16 | 17 | #define TERATHON_BIVECTOR3D 1 18 | 19 | 20 | namespace Terathon 21 | { 22 | class Bivector3D; 23 | struct ConstBivector3D; 24 | 25 | 26 | // ============================================== 27 | // Bivector3D 28 | // ============================================== 29 | 30 | struct TypeBivector3D 31 | { 32 | typedef float component_type; 33 | typedef Vector2D vector2D_type; 34 | typedef Bivector3D vector3D_type; 35 | }; 36 | 37 | 38 | /// \brief Encapsulates a 3D bivector. 39 | /// 40 | /// The $Bivector3D$ class is used to store a three-dimensional bivector having floating-point 41 | /// components x, y, and z. 42 | /// 43 | /// \also Vector3D 44 | 45 | class Bivector3D : public Antivec3D 46 | { 47 | public: 48 | 49 | TERATHON_API static const ConstBivector3D zero; 50 | 51 | TERATHON_API static const ConstBivector3D yz_unit; 52 | TERATHON_API static const ConstBivector3D zx_unit; 53 | TERATHON_API static const ConstBivector3D xy_unit; 54 | 55 | TERATHON_API static const ConstBivector3D minus_yz_unit; 56 | TERATHON_API static const ConstBivector3D minus_zx_unit; 57 | TERATHON_API static const ConstBivector3D minus_xy_unit; 58 | 59 | /// \brief Default constructor that leaves the components uninitialized. 60 | 61 | inline Bivector3D() = default; 62 | 63 | Bivector3D(const Bivector3D& v) 64 | { 65 | xyz = v.xyz; 66 | } 67 | 68 | /// \brief Constructor that sets components explicitly. 69 | /// \param a,b,c The components of the bivector. 70 | 71 | Bivector3D(float a, float b, float c) : Antivec3D(a, b, c) {} 72 | 73 | template 74 | explicit Bivector3D(const Antivec3D& v) : Antivec3D(float(v.x), float(v.y), float(v.z)) {} 75 | 76 | /// \brief Sets all three components of a 3D bivector. 77 | /// \param a,b,c The new components of the bivector. 78 | 79 | Bivector3D& Set(float a, float b, float c) 80 | { 81 | xyz.Set(a, b, c); 82 | return (*this); 83 | } 84 | 85 | void Set(float a, float b, float c) volatile 86 | { 87 | xyz.Set(a, b, c); 88 | } 89 | 90 | Bivector3D& operator =(const Bivector3D& v) 91 | { 92 | xyz = v.xyz; 93 | return (*this); 94 | } 95 | 96 | void operator =(const Bivector3D& v) volatile 97 | { 98 | xyz = v.xyz; 99 | } 100 | 101 | template 102 | Bivector3D& operator =(const Subvec3D& v) 103 | { 104 | xyz = v; 105 | return (*this); 106 | } 107 | 108 | template 109 | void operator =(const Subvec3D& v) volatile 110 | { 111 | xyz = v; 112 | } 113 | 114 | Bivector3D& operator +=(const Bivector3D& v) 115 | { 116 | xyz += v.xyz; 117 | return (*this); 118 | } 119 | 120 | template 121 | Bivector3D& operator +=(const Subvec3D& v) 122 | { 123 | xyz += v; 124 | return (*this); 125 | } 126 | 127 | Bivector3D& operator -=(const Bivector3D& v) 128 | { 129 | xyz += v.xyz; 130 | return (*this); 131 | } 132 | 133 | template 134 | Bivector3D& operator -=(const Subvec3D& v) 135 | { 136 | xyz -= v; 137 | return (*this); 138 | } 139 | 140 | Bivector3D& operator *=(float n) 141 | { 142 | xyz *= n; 143 | return (*this); 144 | } 145 | 146 | Bivector3D& operator /=(float n) 147 | { 148 | xyz /= n; 149 | return (*this); 150 | } 151 | 152 | Bivector3D& Normalize(void) 153 | { 154 | return (static_cast(xyz.Normalize())); 155 | } 156 | }; 157 | 158 | 159 | /// \brief Returns the negation of the 3D bivector $v$. 160 | /// \related Bivector3D 161 | 162 | inline Bivector3D operator -(const Bivector3D& v) 163 | { 164 | return (Bivector3D(-v.x, -v.y, -v.z)); 165 | } 166 | 167 | inline Bivector3D operator +(const Bivector3D& a, const Bivector3D& b) 168 | { 169 | return (Bivector3D(a.x + b.x, a.y + b.y, a.z + b.z)); 170 | } 171 | 172 | inline Bivector3D operator -(const Bivector3D& a, const Bivector3D& b) 173 | { 174 | return (Bivector3D(a.x - b.x, a.y - b.y, a.z - b.z)); 175 | } 176 | 177 | /// \brief Returns the product of the 3D bivector $v$ and the scalar $n$. 178 | /// \related Bivector3D 179 | 180 | inline Bivector3D operator *(const Bivector3D& v, float n) 181 | { 182 | return (Bivector3D(v.x * n, v.y * n, v.z * n)); 183 | } 184 | 185 | /// \brief Returns the product of the 3D bivector $v$ and the scalar $n$. 186 | /// \related Bivector3D 187 | 188 | inline Bivector3D operator *(float n, const Bivector3D& v) 189 | { 190 | return (Bivector3D(n * v.x, n * v.y, n * v.z)); 191 | } 192 | 193 | /// \brief Returns the product of the 3D bivector $v$ and the inverse of the scalar $n$. 194 | /// \related Bivector3D 195 | 196 | inline Bivector3D operator /(const Bivector3D& v, float n) 197 | { 198 | n = 1.0F / n; 199 | return (Bivector3D(v.x * n, v.y * n, v.z * n)); 200 | } 201 | 202 | /// \brief Returns the componentwise product of the 3D bivectors $a$ and $b$. 203 | /// \related Bivector3D 204 | 205 | inline Bivector3D operator *(const Bivector3D& a, const Bivector3D& b) 206 | { 207 | return (Bivector3D(a.x * b.x, a.y * b.y, a.z * b.z)); 208 | } 209 | 210 | // ============================================== 211 | // Magnitude 212 | // ============================================== 213 | 214 | /// \brief Returns the magnitude of the 3D bivector $v$. 215 | /// \related Bivector3D 216 | 217 | inline float Magnitude(const Bivector3D& v) 218 | { 219 | return (Sqrt(v.x * v.x + v.y * v.y + v.z * v.z)); 220 | } 221 | 222 | /// \brief Returns the inverse magnitude of the 3D bivector $v$. 223 | /// \related Bivector3D 224 | 225 | inline float InverseMag(const Bivector3D& v) 226 | { 227 | return (InverseSqrt(v.x * v.x + v.y * v.y + v.z * v.z)); 228 | } 229 | 230 | /// \brief Returns the squared magnitude of the 3D bivector $v$. 231 | /// \related Bivector3D 232 | 233 | inline float SquaredMag(const Bivector3D& v) 234 | { 235 | return (v.x * v.x + v.y * v.y + v.z * v.z); 236 | } 237 | 238 | /// \brief Calculates the normalized version of the 3D bivector $v$. 239 | /// 240 | /// Multiplies the 3D bivector $v$ by the inverse of its magnitude. The return value is a 241 | /// bivector having unit area with the same attitude as $v$. If the magnitude of $v$ is 242 | /// zero, then the result is undefined. 243 | /// 244 | /// \related Bivector3D 245 | 246 | inline Bivector3D Normalize(const Bivector3D& v) 247 | { 248 | return (v * InverseSqrt(v.x * v.x + v.y * v.y + v.z * v.z)); 249 | } 250 | 251 | // ============================================== 252 | // Dot 253 | // ============================================== 254 | 255 | /// \brief Calculates the dot product of the 3D bivectors $a$ and $b$. 256 | /// \related Bivector3D 257 | 258 | inline float Dot(const Bivector3D& a, const Bivector3D& b) 259 | { 260 | return (a.x * b.x + a.y * b.y + a.z * b.z); 261 | } 262 | 263 | // ============================================== 264 | // Complement 265 | // ============================================== 266 | 267 | /// \brief Returns the complement of the 3D vector $v$, which is a bivector, with respect to the volume element e123. 268 | /// \related Bivector3D 269 | 270 | inline const Bivector3D& Complement(const Vector3D& v) 271 | { 272 | return (reinterpret_cast(v)); 273 | } 274 | 275 | /// \brief Returns the complement of the 3D bivector $v$, which is a vector, with respect to the volume element e123. 276 | /// \related Bivector3D 277 | 278 | inline const Vector3D& Complement(const Bivector3D& v) 279 | { 280 | return (reinterpret_cast(v)); 281 | } 282 | 283 | inline const Bivector3D& operator !(const Vector3D& v) {return (Complement(v));} 284 | inline const Vector3D& operator !(const Bivector3D& v) {return (Complement(v));} 285 | 286 | // ============================================== 287 | // Wedge 288 | // ============================================== 289 | 290 | /// \brief Calculates the wedge product of the vectors $a$ and $b$ to produce a 3D bivector. 291 | /// \related Bivector3D 292 | 293 | inline Bivector3D Wedge(const Vector3D& a, const Vector3D& b) 294 | { 295 | return (Bivector3D(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x)); 296 | } 297 | 298 | /// \brief Calculates the antiwedge product of the bivectors $a$ and $b$ to produce a 3D vector. 299 | /// \related Bivector3D 300 | 301 | inline Vector3D Antiwedge(const Bivector3D& a, const Bivector3D& b) 302 | { 303 | return (Vector3D(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x)); 304 | } 305 | 306 | inline float Antiwedge(const Bivector3D& a, const Vector3D& b) 307 | { 308 | return (a.xyz ^ b.xyz); 309 | } 310 | 311 | inline float Antiwedge(const Vector3D& a, const Bivector3D& b) 312 | { 313 | return (a.xyz ^ b.xyz); 314 | } 315 | 316 | template 317 | inline float Antiwedge(const Bivector3D& a, const Subvec3D& b) 318 | { 319 | return (a.xyz ^ b); 320 | } 321 | 322 | inline Bivector3D operator ^(const Vector3D& a, const Vector3D& b) {return (Wedge(a, b));} 323 | inline Vector3D operator ^(const Bivector3D& a, const Bivector3D& b) {return (Antiwedge(a, b));} 324 | inline float operator ^(const Bivector3D& a, const Vector3D& b) {return (Antiwedge(a, b));} 325 | inline float operator ^(const Vector3D& a, const Bivector3D& b) {return (Antiwedge(a, b));} 326 | 327 | template 328 | inline float operator ^(const Bivector3D& a, const Subvec3D& b) {return (Antiwedge(a, b));} 329 | 330 | 331 | // ============================================== 332 | // POD Structures 333 | // ============================================== 334 | 335 | struct ConstBivector3D 336 | { 337 | float x, y, z; 338 | 339 | operator const Bivector3D&(void) const 340 | { 341 | return (reinterpret_cast(*this)); 342 | } 343 | 344 | const Bivector3D *operator &(void) const 345 | { 346 | return (reinterpret_cast(this)); 347 | } 348 | 349 | const Bivector3D *operator ->(void) const 350 | { 351 | return (reinterpret_cast(this)); 352 | } 353 | }; 354 | 355 | 356 | typedef Bivector3D Antivector3D; 357 | } 358 | 359 | 360 | #endif 361 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSAlgebra.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSMatrix4D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | template 18 | TERATHON_API typename A_type_struct::matrix2D_type Terathon::operator *(const Submat2D& A, 19 | const Submat2D& B) 20 | { 21 | return (typename A_type_struct::matrix2D_type(A.data[A_index_00] * B.data[B_index_00] + A.data[A_index_01] * B.data[B_index_10], 22 | A.data[A_index_00] * B.data[B_index_01] + A.data[A_index_01] * B.data[B_index_11], 23 | A.data[A_index_10] * B.data[B_index_00] + A.data[A_index_11] * B.data[B_index_10], 24 | A.data[A_index_10] * B.data[B_index_01] + A.data[A_index_11] * B.data[B_index_11])); 25 | } 26 | 27 | template TERATHON_API Matrix2D Terathon::operator *(const Submat2D&, const Submat2D&); 28 | template TERATHON_API Matrix2D Terathon::operator *(const Submat2D&, const Submat2D&); 29 | template TERATHON_API Matrix2D Terathon::operator *(const Submat2D&, const Submat2D&); 30 | template TERATHON_API Matrix2D Terathon::operator *(const Submat2D&, const Submat2D&); 31 | 32 | 33 | template 35 | TERATHON_API typename A_type_struct::matrix3D_type Terathon::operator *(const Submat3D& A, 36 | const Submat3D& B) 37 | { 38 | return (typename A_type_struct::matrix3D_type(A.data[A_index_00] * B.data[B_index_00] + A.data[A_index_01] * B.data[B_index_10] + A.data[A_index_02] * B.data[B_index_20], 39 | A.data[A_index_00] * B.data[B_index_01] + A.data[A_index_01] * B.data[B_index_11] + A.data[A_index_02] * B.data[B_index_21], 40 | A.data[A_index_00] * B.data[B_index_02] + A.data[A_index_01] * B.data[B_index_12] + A.data[A_index_02] * B.data[B_index_22], 41 | A.data[A_index_10] * B.data[B_index_00] + A.data[A_index_11] * B.data[B_index_10] + A.data[A_index_12] * B.data[B_index_20], 42 | A.data[A_index_10] * B.data[B_index_01] + A.data[A_index_11] * B.data[B_index_11] + A.data[A_index_12] * B.data[B_index_21], 43 | A.data[A_index_10] * B.data[B_index_02] + A.data[A_index_11] * B.data[B_index_12] + A.data[A_index_12] * B.data[B_index_22], 44 | A.data[A_index_20] * B.data[B_index_00] + A.data[A_index_21] * B.data[B_index_10] + A.data[A_index_22] * B.data[B_index_20], 45 | A.data[A_index_20] * B.data[B_index_01] + A.data[A_index_21] * B.data[B_index_11] + A.data[A_index_22] * B.data[B_index_21], 46 | A.data[A_index_20] * B.data[B_index_02] + A.data[A_index_21] * B.data[B_index_12] + A.data[A_index_22] * B.data[B_index_22])); 47 | } 48 | 49 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 50 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 51 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 52 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 53 | 54 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 55 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 56 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 57 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 58 | 59 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 60 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 61 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 62 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 63 | 64 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 65 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 66 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 67 | template TERATHON_API Matrix3D Terathon::operator *(const Submat3D&, const Submat3D&); 68 | 69 | 70 | template 72 | TERATHON_API typename A_type_struct::matrix4D_type Terathon::operator *(const Submat4D& A, 73 | const Submat4D& B) 74 | { 75 | return (typename A_type_struct::matrix4D_type(A.data[A_index_00] * B.data[B_index_00] + A.data[A_index_01] * B.data[B_index_10] + A.data[A_index_02] * B.data[B_index_20] + A.data[A_index_03] * B.data[B_index_30], 76 | A.data[A_index_00] * B.data[B_index_01] + A.data[A_index_01] * B.data[B_index_11] + A.data[A_index_02] * B.data[B_index_21] + A.data[A_index_03] * B.data[B_index_31], 77 | A.data[A_index_00] * B.data[B_index_02] + A.data[A_index_01] * B.data[B_index_12] + A.data[A_index_02] * B.data[B_index_22] + A.data[A_index_03] * B.data[B_index_32], 78 | A.data[A_index_00] * B.data[B_index_03] + A.data[A_index_01] * B.data[B_index_13] + A.data[A_index_02] * B.data[B_index_23] + A.data[A_index_03] * B.data[B_index_33], 79 | A.data[A_index_10] * B.data[B_index_00] + A.data[A_index_11] * B.data[B_index_10] + A.data[A_index_12] * B.data[B_index_20] + A.data[A_index_13] * B.data[B_index_30], 80 | A.data[A_index_10] * B.data[B_index_01] + A.data[A_index_11] * B.data[B_index_11] + A.data[A_index_12] * B.data[B_index_21] + A.data[A_index_13] * B.data[B_index_31], 81 | A.data[A_index_10] * B.data[B_index_02] + A.data[A_index_11] * B.data[B_index_12] + A.data[A_index_12] * B.data[B_index_22] + A.data[A_index_13] * B.data[B_index_32], 82 | A.data[A_index_10] * B.data[B_index_03] + A.data[A_index_11] * B.data[B_index_13] + A.data[A_index_12] * B.data[B_index_23] + A.data[A_index_13] * B.data[B_index_33], 83 | A.data[A_index_20] * B.data[B_index_00] + A.data[A_index_21] * B.data[B_index_10] + A.data[A_index_22] * B.data[B_index_20] + A.data[A_index_23] * B.data[B_index_30], 84 | A.data[A_index_20] * B.data[B_index_01] + A.data[A_index_21] * B.data[B_index_11] + A.data[A_index_22] * B.data[B_index_21] + A.data[A_index_23] * B.data[B_index_31], 85 | A.data[A_index_20] * B.data[B_index_02] + A.data[A_index_21] * B.data[B_index_12] + A.data[A_index_22] * B.data[B_index_22] + A.data[A_index_23] * B.data[B_index_32], 86 | A.data[A_index_20] * B.data[B_index_03] + A.data[A_index_21] * B.data[B_index_13] + A.data[A_index_22] * B.data[B_index_23] + A.data[A_index_23] * B.data[B_index_33], 87 | A.data[A_index_30] * B.data[B_index_00] + A.data[A_index_31] * B.data[B_index_10] + A.data[A_index_32] * B.data[B_index_20] + A.data[A_index_33] * B.data[B_index_30], 88 | A.data[A_index_30] * B.data[B_index_01] + A.data[A_index_31] * B.data[B_index_11] + A.data[A_index_32] * B.data[B_index_21] + A.data[A_index_33] * B.data[B_index_31], 89 | A.data[A_index_30] * B.data[B_index_02] + A.data[A_index_31] * B.data[B_index_12] + A.data[A_index_32] * B.data[B_index_22] + A.data[A_index_33] * B.data[B_index_32], 90 | A.data[A_index_30] * B.data[B_index_03] + A.data[A_index_31] * B.data[B_index_13] + A.data[A_index_32] * B.data[B_index_23] + A.data[A_index_33] * B.data[B_index_33])); 91 | } 92 | 93 | template TERATHON_API Matrix4D Terathon::operator *(const Submat4D&, const Submat4D&); 94 | template TERATHON_API Matrix4D Terathon::operator *(const Submat4D&, const Submat4D&); 95 | template TERATHON_API Matrix4D Terathon::operator *(const Submat4D&, const Submat4D&); 96 | template TERATHON_API Matrix4D Terathon::operator *(const Submat4D&, const Submat4D&); 97 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSMath.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #ifndef TSMath_h 11 | #define TSMath_h 12 | 13 | 14 | #ifndef TERATHON_NO_SIMD 15 | 16 | #include "TSSimd.h" 17 | 18 | #else 19 | 20 | #include "TSPlatform.h" 21 | 22 | #endif 23 | 24 | 25 | #define TERATHON_MATH 1 26 | 27 | 28 | /// \brief Terathon math and container namespace. 29 | 30 | namespace Terathon 31 | { 32 | inline float Fabs(const float& x) 33 | { 34 | #ifndef TERATHON_NO_SIMD 35 | 36 | float result; 37 | 38 | VecStoreX(VecAndc(VecLoadScalar(&x), VecFloatGetMinusZero()), &result); 39 | return (result); 40 | 41 | #else 42 | 43 | return ((x < 0.0F) ? -x : x); 44 | 45 | #endif 46 | } 47 | 48 | inline float Fnabs(const float& x) 49 | { 50 | #ifndef TERATHON_NO_SIMD 51 | 52 | float result; 53 | 54 | VecStoreX(VecLoadScalar(&x) | VecFloatGetMinusZero(), &result); 55 | return (result); 56 | 57 | #else 58 | 59 | return ((x > 0.0F) ? -x : x); 60 | 61 | #endif 62 | } 63 | 64 | inline float Fsgn(const float& x) 65 | { 66 | #ifndef TERATHON_NO_SIMD 67 | 68 | float result; 69 | 70 | VecStoreX(VecFsgn(VecLoadScalar(&x)), &result); 71 | return (result); 72 | 73 | #else 74 | 75 | return ((x < 0.0F) ? -1.0F : ((x > 0.0F) ? 1.0F : 0.0F)); 76 | 77 | #endif 78 | } 79 | 80 | inline float Fnsgn(const float& x) 81 | { 82 | #ifndef TERATHON_NO_SIMD 83 | 84 | float result; 85 | 86 | VecStoreX(VecFnsgn(VecLoadScalar(&x)), &result); 87 | return (result); 88 | 89 | #else 90 | 91 | return ((x < 0.0F) ? 1.0F : ((x > 0.0F) ? -1.0F : 0.0F)); 92 | 93 | #endif 94 | } 95 | 96 | inline float NonzeroFsgn(const float& x) 97 | { 98 | #ifndef TERATHON_NO_SIMD 99 | 100 | float result; 101 | 102 | VecStoreX(VecNonzeroFsgn(VecLoadScalar(&x)), &result); 103 | return (result); 104 | 105 | #else 106 | 107 | return ((x < 0.0F) ? -1.0F : 1.0F); 108 | 109 | #endif 110 | } 111 | 112 | inline float NonzeroFnsgn(const float& x) 113 | { 114 | #ifndef TERATHON_NO_SIMD 115 | 116 | float result; 117 | 118 | VecStoreX(VecNonzeroFnsgn(VecLoadScalar(&x)), &result); 119 | return (result); 120 | 121 | #else 122 | 123 | return ((x < 0.0F) ? 1.0F : -1.0F); 124 | 125 | #endif 126 | } 127 | 128 | inline float Fmin(const float& x, const float& y) 129 | { 130 | #ifndef TERATHON_NO_SIMD 131 | 132 | float result; 133 | 134 | VecStoreX(VecMinScalar(VecLoadScalar(&x), VecLoadScalar(&y)), &result); 135 | return (result); 136 | 137 | #else 138 | 139 | return ((x < y) ? x : y); 140 | 141 | #endif 142 | } 143 | 144 | inline float Fmin(const float& x, const float& y, const float& z) 145 | { 146 | #ifndef TERATHON_NO_SIMD 147 | 148 | float result; 149 | 150 | VecStoreX(VecMinScalar(VecMinScalar(VecLoadScalar(&x), VecLoadScalar(&y)), VecLoadScalar(&z)), &result); 151 | return (result); 152 | 153 | #else 154 | 155 | return (Fmin(Fmin(x, y), z)); 156 | 157 | #endif 158 | } 159 | 160 | inline float Fmin(const float& x, const float& y, const float& z, const float& w) 161 | { 162 | #ifndef TERATHON_NO_SIMD 163 | 164 | float result; 165 | 166 | VecStoreX(VecMinScalar(VecMinScalar(VecLoadScalar(&x), VecLoadScalar(&y)), VecMinScalar(VecLoadScalar(&z), VecLoadScalar(&w))), &result); 167 | return (result); 168 | 169 | #else 170 | 171 | return (Fmin(Fmin(x, y), Fmin(z, w))); 172 | 173 | #endif 174 | } 175 | 176 | inline float Fmax(const float& x, const float& y) 177 | { 178 | #ifndef TERATHON_NO_SIMD 179 | 180 | float result; 181 | 182 | VecStoreX(VecMaxScalar(VecLoadScalar(&x), VecLoadScalar(&y)), &result); 183 | return (result); 184 | 185 | #else 186 | 187 | return ((x < y) ? y : x); 188 | 189 | #endif 190 | } 191 | 192 | inline float Fmax(const float& x, const float& y, const float& z) 193 | { 194 | #ifndef TERATHON_NO_SIMD 195 | 196 | float result; 197 | 198 | VecStoreX(VecMaxScalar(VecMaxScalar(VecLoadScalar(&x), VecLoadScalar(&y)), VecLoadScalar(&z)), &result); 199 | return (result); 200 | 201 | #else 202 | 203 | return (Fmax(Fmax(x, y), z)); 204 | 205 | #endif 206 | } 207 | 208 | inline float Fmax(const float& x, const float& y, const float& z, const float& w) 209 | { 210 | #ifndef TERATHON_NO_SIMD 211 | 212 | float result; 213 | 214 | VecStoreX(VecMaxScalar(VecMaxScalar(VecLoadScalar(&x), VecLoadScalar(&y)), VecMaxScalar(VecLoadScalar(&z), VecLoadScalar(&w))), &result); 215 | return (result); 216 | 217 | #else 218 | 219 | return (Fmax(Fmax(x, y), Fmax(z, w))); 220 | 221 | #endif 222 | } 223 | 224 | inline float FminZero(const float& x) 225 | { 226 | #ifndef TERATHON_NO_SIMD 227 | 228 | float result; 229 | 230 | VecStoreX(VecMinScalar(VecLoadScalar(&x), VecFloatGetZero()), &result); 231 | return (result); 232 | 233 | #else 234 | 235 | return ((x < 0.0F) ? x : 0.0F); 236 | 237 | #endif 238 | } 239 | 240 | inline float FmaxZero(const float& x) 241 | { 242 | #ifndef TERATHON_NO_SIMD 243 | 244 | float result; 245 | 246 | VecStoreX(VecMaxScalar(VecLoadScalar(&x), VecFloatGetZero()), &result); 247 | return (result); 248 | 249 | #else 250 | 251 | return ((x < 0.0F) ? 0.0F : x); 252 | 253 | #endif 254 | } 255 | 256 | inline float Saturate(const float& x) 257 | { 258 | #ifndef TERATHON_NO_SIMD 259 | 260 | float result; 261 | 262 | VecStoreX(VecMinScalar(VecMaxScalar(VecLoadScalar(&x), VecFloatGetZero()), VecLoadVectorConstant<0x3F800000>()), &result); 263 | return (result); 264 | 265 | #else 266 | 267 | float f = (x < 0.0F) ? 0.0F : x; 268 | return ((f < 1.0F) ? f : 1.0F); 269 | 270 | #endif 271 | } 272 | 273 | inline float Clamp(const float& x, const float& y, const float& z) 274 | { 275 | #ifndef TERATHON_NO_SIMD 276 | 277 | float result; 278 | 279 | VecStoreX(VecMinScalar(VecMaxScalar(VecLoadScalar(&x), VecLoadScalar(&y)), VecLoadScalar(&z)), &result); 280 | return (result); 281 | 282 | #else 283 | 284 | float f = (x < y) ? y : x; 285 | return ((f < z) ? f : z); 286 | 287 | #endif 288 | } 289 | 290 | #ifndef TERATHON_NO_SIMD 291 | 292 | inline float Floor(const float& x) 293 | { 294 | float result; 295 | 296 | VecStoreX(VecFloorScalar(VecLoadScalar(&x)), &result); 297 | return (result); 298 | } 299 | 300 | inline float Ceil(const float& x) 301 | { 302 | float result; 303 | 304 | VecStoreX(VecCeilScalar(VecLoadScalar(&x)), &result); 305 | return (result); 306 | } 307 | 308 | #else 309 | 310 | TERATHON_API float Floor(const float& x); 311 | TERATHON_API float Ceil(const float& x); 312 | 313 | #endif 314 | 315 | inline float PositiveFloor(const float& x) 316 | { 317 | #ifndef TERATHON_NO_SIMD 318 | 319 | float result; 320 | 321 | VecStoreX(VecPositiveFloorScalar(VecLoadScalar(&x)), &result); 322 | return (result); 323 | 324 | #else 325 | 326 | return (Floor(x)); 327 | 328 | #endif 329 | } 330 | 331 | inline float NegativeFloor(const float& x) 332 | { 333 | #ifndef TERATHON_NO_SIMD 334 | 335 | float result; 336 | 337 | VecStoreX(VecNegativeFloorScalar(VecLoadScalar(&x)), &result); 338 | return (result); 339 | 340 | #else 341 | 342 | return (Floor(x)); 343 | 344 | #endif 345 | } 346 | 347 | inline float PositiveCeil(const float& x) 348 | { 349 | #ifndef TERATHON_NO_SIMD 350 | 351 | float result; 352 | 353 | VecStoreX(VecPositiveCeilScalar(VecLoadScalar(&x)), &result); 354 | return (result); 355 | 356 | #else 357 | 358 | return (Ceil(x)); 359 | 360 | #endif 361 | } 362 | 363 | inline float NegativeCeil(const float& x) 364 | { 365 | #ifndef TERATHON_NO_SIMD 366 | 367 | float result; 368 | 369 | VecStoreX(VecNegativeCeilScalar(VecLoadScalar(&x)), &result); 370 | return (result); 371 | 372 | #else 373 | 374 | return (Ceil(x)); 375 | 376 | #endif 377 | } 378 | 379 | inline void FloorCeil(const float& x, float *f, float *c) 380 | { 381 | #ifndef TERATHON_NO_SIMD 382 | 383 | vec_float vf, vc; 384 | 385 | VecFloorCeilScalar(VecLoadScalar(&x), &vf, &vc); 386 | VecStoreX(vf, f); 387 | VecStoreX(vc, c); 388 | 389 | #else 390 | 391 | *f = Floor(x); 392 | *c = Ceil(x); 393 | 394 | #endif 395 | } 396 | 397 | inline void PositiveFloorCeil(const float& x, float *f, float *c) 398 | { 399 | #ifndef TERATHON_NO_SIMD 400 | 401 | vec_float vf, vc; 402 | 403 | VecPositiveFloorCeilScalar(VecLoadScalar(&x), &vf, &vc); 404 | VecStoreX(vf, f); 405 | VecStoreX(vc, c); 406 | 407 | #else 408 | 409 | *f = Floor(x); 410 | *c = Ceil(x); 411 | 412 | #endif 413 | } 414 | 415 | inline void NegativeFloorCeil(const float& x, float *f, float *c) 416 | { 417 | #ifndef TERATHON_NO_SIMD 418 | 419 | vec_float vf, vc; 420 | 421 | VecNegativeFloorCeilScalar(VecLoadScalar(&x), &vf, &vc); 422 | VecStoreX(vf, f); 423 | VecStoreX(vc, c); 424 | 425 | #else 426 | 427 | *f = Floor(x); 428 | *c = Ceil(x); 429 | 430 | #endif 431 | } 432 | 433 | inline float Frac(const float& x) 434 | { 435 | return (x - Floor(x)); 436 | } 437 | 438 | inline float PositiveFrac(const float& x) 439 | { 440 | return (x - PositiveFloor(x)); 441 | } 442 | 443 | inline float NegativeFrac(const float& x) 444 | { 445 | return (x - NegativeFloor(x)); 446 | } 447 | 448 | 449 | TERATHON_API float Sqrt(float x); 450 | TERATHON_API float InverseSqrt(float x); 451 | 452 | TERATHON_API float Sin(float x); 453 | TERATHON_API float Cos(float x); 454 | TERATHON_API float Tan(float x); 455 | TERATHON_API void CosSin(float x, float *c, float *s); 456 | 457 | TERATHON_API float Arcsin(float y); 458 | TERATHON_API float Arccos(float x); 459 | TERATHON_API float Arctan(float x); 460 | TERATHON_API float Arctan(float y, float x); 461 | 462 | TERATHON_API float Exp(float x); 463 | TERATHON_API float Log(float x); 464 | 465 | inline float Pow(float base, float exponent) 466 | { 467 | return (Exp(Log(base) * exponent)); 468 | } 469 | 470 | 471 | namespace Math 472 | { 473 | TERATHON_API extern const float infinity; 474 | TERATHON_API extern const float minus_infinity; 475 | TERATHON_API extern const float min_float; 476 | TERATHON_API extern const float max_float; 477 | 478 | TERATHON_API extern const float tau; 479 | TERATHON_API extern const float two_tau; 480 | TERATHON_API extern const float three_tau_over_4; 481 | TERATHON_API extern const float three_tau_over_8; 482 | TERATHON_API extern const float tau_over_2; 483 | TERATHON_API extern const float tau_over_3; 484 | TERATHON_API extern const float two_tau_over_3; 485 | TERATHON_API extern const float tau_over_4; 486 | TERATHON_API extern const float tau_over_6; 487 | TERATHON_API extern const float tau_over_8; 488 | TERATHON_API extern const float tau_over_12; 489 | TERATHON_API extern const float tau_over_16; 490 | TERATHON_API extern const float tau_over_24; 491 | TERATHON_API extern const float tau_over_40; 492 | TERATHON_API extern const float one_over_tau; 493 | TERATHON_API extern const float two_over_tau; 494 | TERATHON_API extern const float four_over_tau; 495 | TERATHON_API extern const float one_over_two_tau; 496 | 497 | TERATHON_API extern const float pi; 498 | TERATHON_API extern const float two_pi; 499 | TERATHON_API extern const float four_pi; 500 | TERATHON_API extern const float three_pi_over_2; 501 | TERATHON_API extern const float three_pi_over_4; 502 | TERATHON_API extern const float two_pi_over_3; 503 | TERATHON_API extern const float four_pi_over_3; 504 | TERATHON_API extern const float pi_over_2; 505 | TERATHON_API extern const float pi_over_3; 506 | TERATHON_API extern const float pi_over_4; 507 | TERATHON_API extern const float pi_over_6; 508 | TERATHON_API extern const float pi_over_8; 509 | TERATHON_API extern const float pi_over_12; 510 | TERATHON_API extern const float pi_over_20; 511 | TERATHON_API extern const float one_over_pi; 512 | TERATHON_API extern const float one_over_two_pi; 513 | TERATHON_API extern const float one_over_four_pi; 514 | 515 | TERATHON_API extern const float sqrt_2; 516 | TERATHON_API extern const float sqrt_2_over_2; 517 | TERATHON_API extern const float sqrt_2_over_3; 518 | TERATHON_API extern const float sqrt_3; 519 | TERATHON_API extern const float sqrt_3_over_2; 520 | TERATHON_API extern const float sqrt_3_over_3; 521 | 522 | TERATHON_API extern const float ln_2; 523 | TERATHON_API extern const float one_over_ln_2; 524 | TERATHON_API extern const float ln_10; 525 | TERATHON_API extern const float one_over_ln_10; 526 | TERATHON_API extern const float ln_256; 527 | 528 | 529 | TERATHON_API extern const uint32 trigTable[256][2]; 530 | } 531 | } 532 | 533 | 534 | #endif 535 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSTools.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Common Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #ifndef TSTools_h 11 | #define TSTools_h 12 | 13 | 14 | /// \component Utility Library 15 | /// \prefix Utilities/ 16 | 17 | 18 | #include "TSPlatform.h" 19 | 20 | 21 | #define TERATHON_TOOLS 1 22 | 23 | 24 | namespace Terathon 25 | { 26 | #ifdef TERATHON_DEBUG 27 | 28 | TERATHON_API void Fatal(const char *c = ""); 29 | TERATHON_API void Assert(bool b, const char *c = ""); 30 | 31 | #else 32 | 33 | inline void Fatal(const char * = "") 34 | { 35 | } 36 | 37 | #if defined(_MSC_VER) 38 | 39 | #define Assert(b, c) __assume(b) 40 | 41 | #else 42 | 43 | inline void Assert(bool, const char *) {} 44 | 45 | #endif 46 | 47 | #endif 48 | 49 | 50 | /// \class Range Encapsulates a range of values. 51 | /// 52 | /// The $Range$ class template encapsulates a range of values. 53 | /// 54 | /// \def template struct Range 55 | /// 56 | /// \tparam type The type of value used to represent the beginning and end of a range. 57 | /// 58 | /// \data Range 59 | /// 60 | /// \ctor Range(); 61 | /// \ctor Range(const type& x, const type& y); 62 | /// 63 | /// \param x The beginning of the range. 64 | /// \param y The end of the range. 65 | /// 66 | /// \desc 67 | /// The $Range$ class template encapsulates a range of values of the type given by the 68 | /// $type$ class template. 69 | /// 70 | /// The default constructor leaves the beginning and end values of the range undefined. 71 | /// If the values $x$ and $y$ are supplied, then they are assigned to the beginning and 72 | /// end of the range, respectively. 73 | /// 74 | /// \operator type& operator [](machine index); 75 | /// Returns a reference to the minimum value if $index$ is 0, and returns a reference to the maximum value if $index$ is 1. 76 | /// The $index$ parameter must be 0 or 1. 77 | /// 78 | /// \operator const type& operator [](machine index) const; 79 | /// Returns a constant reference to the minimum value if $index$ is 0, and returns a constant reference to the maximum value if $index$ is 1. 80 | /// The $index$ parameter must be 0 or 1. 81 | /// 82 | /// \operator bool operator ==(const Range& range) const; 83 | /// Returns a boolean value indicating whether two ranges are equal. 84 | /// 85 | /// \operator bool operator !=(const Range& range) const; 86 | /// Returns a boolean value indicating whether two ranges are not equal. 87 | 88 | 89 | /// \function Range::Set Sets the beginning and end of a range. 90 | /// 91 | /// \proto Range& Set(const type& x, const type& y); 92 | /// 93 | /// \param x The new beginning of the range. 94 | /// \param y The new end of the range. 95 | /// 96 | /// \desc 97 | /// The $Set$ function sets the beginning and end of a range to the values given by the 98 | /// $x$ and $y$ parameters, respectively. 99 | 100 | 101 | /// \member Range 102 | 103 | template 104 | struct Range 105 | { 106 | type min; ///< The beginning of the range. 107 | type max; ///< The end of the range. 108 | 109 | inline Range() = default; 110 | 111 | Range(const Range& range) 112 | { 113 | min = range.min; 114 | max = range.max; 115 | } 116 | 117 | Range(const type& x, const type& y) 118 | { 119 | min = x; 120 | max = y; 121 | } 122 | 123 | type& operator [](machine index) 124 | { 125 | return ((&min)[index]); 126 | } 127 | 128 | const type& operator [](machine index) const 129 | { 130 | return ((&min)[index]); 131 | } 132 | 133 | Range& operator =(const Range& range) 134 | { 135 | min = range.min; 136 | max = range.max; 137 | return (*this); 138 | } 139 | 140 | Range& Set(const type& x, const type& y) 141 | { 142 | min = x; 143 | max = y; 144 | return (*this); 145 | } 146 | 147 | bool operator ==(const Range& range) const 148 | { 149 | return ((min == range.min) && (max == range.max)); 150 | } 151 | 152 | bool operator !=(const Range& range) const 153 | { 154 | return ((min != range.min) || (max != range.max)); 155 | } 156 | }; 157 | 158 | 159 | class Buffer 160 | { 161 | private: 162 | 163 | char *bufferStorage; 164 | uint64 bufferSize; 165 | 166 | Buffer(const Buffer& buffer) = delete; 167 | Buffer& operator =(const Buffer& s) = delete; 168 | Buffer& operator =(Buffer&& s) = delete; 169 | 170 | public: 171 | 172 | Buffer() 173 | { 174 | bufferSize = 0; 175 | bufferStorage = nullptr; 176 | } 177 | 178 | explicit Buffer(uint64 size) 179 | { 180 | bufferSize = size; 181 | bufferStorage = new char[size]; 182 | } 183 | 184 | Buffer(Buffer&& buffer) 185 | { 186 | bufferStorage = buffer.bufferStorage; 187 | bufferSize = buffer.bufferSize; 188 | buffer.bufferStorage = nullptr; 189 | buffer.bufferSize = 0; 190 | } 191 | 192 | ~Buffer() 193 | { 194 | delete[] bufferStorage; 195 | } 196 | 197 | operator void *(void) const 198 | { 199 | return (bufferStorage); 200 | } 201 | 202 | template 203 | type *GetPointer(void) const 204 | { 205 | return (reinterpret_cast(bufferStorage)); 206 | } 207 | 208 | uint64 GetBufferSize(void) const 209 | { 210 | return (bufferSize); 211 | } 212 | 213 | void AllocateBuffer(uint64 size) 214 | { 215 | if (size != bufferSize) 216 | { 217 | bufferSize = size; 218 | delete[] bufferStorage; 219 | bufferStorage = new char[size]; 220 | } 221 | } 222 | }; 223 | 224 | 225 | /// \class Holder A helper class the wraps a pointer to an object. 226 | /// 227 | /// \def template class Holder 228 | /// 229 | /// \tparam type The type of object to which the $Holder$ object refers. 230 | /// 231 | /// \ctor explicit Holder(type *ptr); 232 | /// 233 | /// \param ptr A pointer to the object that is wrapped by the $Holder$ object. 234 | /// 235 | /// \desc 236 | /// The $Holder$ class template is a helper class that wraps a pointer to an object. 237 | /// When a $Holder$ object is destroyed (usually by going out of scope), the object 238 | /// that was passed into the $ptr$ parameter when the $Holder$ object was constructed 239 | /// is automatically deleted with the $delete$ operator. 240 | /// 241 | /// A $Holder$ object behaves like a pointer to an object of the type given by the 242 | /// $type$ template parameter. A $Holder$ object can be passed as a function parameter 243 | /// wherever a pointer to $type$ is expected, and the $->$ operator can be used to access 244 | /// members of the object that the $Holder$ object wraps. 245 | /// 246 | /// \also $@AutoRelease@$ 247 | 248 | 249 | template 250 | class Holder 251 | { 252 | private: 253 | 254 | type *pointer; 255 | 256 | Holder(const Holder&) = delete; 257 | Holder& operator =(const Holder&) = delete; 258 | 259 | public: 260 | 261 | Holder() 262 | { 263 | pointer = nullptr; 264 | } 265 | 266 | Holder(type *ptr) 267 | { 268 | pointer = ptr; 269 | } 270 | 271 | Holder(Holder&& holder) 272 | { 273 | pointer = holder.pointer; 274 | holder.pointer = nullptr; 275 | } 276 | 277 | ~Holder() 278 | { 279 | delete pointer; 280 | } 281 | 282 | operator type *(void) const 283 | { 284 | return (pointer); 285 | } 286 | 287 | type *operator ->(void) const 288 | { 289 | return (pointer); 290 | } 291 | 292 | type& operator *(void) const 293 | { 294 | return (*pointer); 295 | } 296 | 297 | Holder& operator =(type *ptr) 298 | { 299 | pointer = ptr; 300 | return (*this); 301 | } 302 | }; 303 | 304 | 305 | template 306 | class Holder 307 | { 308 | private: 309 | 310 | type *pointer; 311 | 312 | Holder(const Holder&) = delete; 313 | Holder& operator =(const Holder&) = delete; 314 | 315 | public: 316 | 317 | Holder() 318 | { 319 | pointer = nullptr; 320 | } 321 | 322 | Holder(type *ptr) 323 | { 324 | pointer = ptr; 325 | } 326 | 327 | Holder(Holder&& holder) 328 | { 329 | pointer = holder.pointer; 330 | holder.pointer = nullptr; 331 | } 332 | 333 | ~Holder() 334 | { 335 | delete[] pointer; 336 | } 337 | 338 | operator type *(void) const 339 | { 340 | return (pointer); 341 | } 342 | 343 | type *operator ->(void) const 344 | { 345 | return (pointer); 346 | } 347 | 348 | type& operator *(void) const 349 | { 350 | return (*pointer); 351 | } 352 | 353 | Holder& operator =(type *ptr) 354 | { 355 | pointer = ptr; 356 | return (*this); 357 | } 358 | }; 359 | 360 | 361 | /// \class Shared The base class for reference-counted objects. 362 | /// 363 | /// Objects inherit from the $Shared$ class when they contain shared data and 364 | /// need to be reference counted. 365 | /// 366 | /// \def class Shared 367 | /// 368 | /// \ctor Shared(); 369 | /// 370 | /// \desc 371 | /// The $Shared$ class encapsulates a reference count for objects that can be shared. 372 | /// Upon construction, the object's reference count is initialized to 1. 373 | /// 374 | /// \important 375 | /// The destructor of the $Shared$ class does not have public access, and the destructors 376 | /// of any subclasses of the $Shared$ class should not have public access. Shared objects 377 | /// must be released by calling the $@Shared::Release@$ function. 378 | /// 379 | /// \also $@AutoRelease@$ 380 | 381 | 382 | /// \function Shared::GetReferenceCount Returns an object's current reference count. 383 | /// 384 | /// \proto int32 GetReferenceCount(void) const; 385 | /// 386 | /// \desc 387 | /// The $GetReferenceCount$ function returns the current reference count. 388 | /// When a shared object is constructed, its initial reference count is 1. 389 | /// 390 | /// \also $@Shared::Retain@$ 391 | /// \also $@Shared::Release@$ 392 | 393 | 394 | /// \function Shared::Retain Increments an object's reference count. 395 | /// 396 | /// \proto int32 Retain(void); 397 | /// 398 | /// \desc 399 | /// The $Retain$ function increments the reference count. For each call to $Retain$ 400 | /// made for a particular shared object, a balancing call to $@Shared::Release@$ 401 | /// decrements the reference count without destroying the object. The return value 402 | /// of the $Retain$ function is the new reference count. 403 | /// 404 | /// \also $@Shared::GetReferenceCount@$ 405 | /// \also $@Shared::Release@$ 406 | 407 | 408 | /// \function Shared::Release Decrements an object's reference count. 409 | /// 410 | /// \proto virtual int32 Release(void); 411 | /// 412 | /// \desc 413 | /// The $Release$ function decrements the reference count. If the reference count 414 | /// becomes zero, then the object is destroyed. The return value of the $Release$ 415 | /// function is the new reference count. 416 | /// 417 | /// \also $@Shared::GetReferenceCount@$ 418 | /// \also $@Shared::Retain@$ 419 | 420 | 421 | class Shared 422 | { 423 | private: 424 | 425 | int32 referenceCount = 1; 426 | 427 | Shared(const Shared&) = delete; 428 | Shared& operator =(const Shared&) = delete; 429 | 430 | protected: 431 | 432 | inline Shared() = default; 433 | virtual ~Shared() = default; 434 | 435 | public: 436 | 437 | int32 GetReferenceCount(void) const 438 | { 439 | return (referenceCount); 440 | } 441 | 442 | int32 Retain(void) 443 | { 444 | return (++referenceCount); 445 | } 446 | 447 | virtual int32 Release(void) 448 | { 449 | int32 count = --referenceCount; 450 | if (count == 0) 451 | { 452 | delete this; 453 | } 454 | 455 | return (count); 456 | } 457 | }; 458 | 459 | 460 | /// \class AutoRelease A helper class the wraps a pointer to a shared object. 461 | /// 462 | /// \def template class AutoRelease 463 | /// 464 | /// \tparam type The type of object to which the $AutoRelease$ object refers. 465 | /// 466 | /// \ctor explicit AutoRelease(type *ptr); 467 | /// 468 | /// \param ptr A pointer to the shared object that is wrapped by the $AutoRelease$ object. 469 | /// 470 | /// \desc 471 | /// The $AutoRelease$ class template is a helper class that wraps a pointer to a shared 472 | /// object. When an $AutoRelease$ object is destroyed (usually by going out of scope), 473 | /// the $Release$ function is automatically called for the object that was passed into 474 | /// the $ptr$ parameter when the $AutoRelease$ object was constructed. 475 | /// 476 | /// An $AutoRelease$ object behaves like a pointer to an object of the type given by the 477 | /// $type$ template parameter. An $AutoRelease$ object can be passed as a function parameter 478 | /// wherever a pointer to $type$ is expected, and the $->$ operator can be used to access 479 | /// members of the object that the $AutoRelease$ object wraps. 480 | /// 481 | /// \also $@Shared@$ 482 | /// \also $@Holder@$ 483 | 484 | 485 | template 486 | class AutoRelease 487 | { 488 | private: 489 | 490 | type *reference; 491 | 492 | public: 493 | 494 | explicit AutoRelease(type *ptr) 495 | { 496 | reference = ptr; 497 | } 498 | 499 | AutoRelease(const AutoRelease& ar) 500 | { 501 | reference = ar.reference; 502 | reference->Retain(); 503 | } 504 | 505 | ~AutoRelease() 506 | { 507 | reference->Release(); 508 | } 509 | 510 | operator type *(void) const 511 | { 512 | return (reference); 513 | } 514 | 515 | type *const *operator &(void) const 516 | { 517 | return (&reference); 518 | } 519 | 520 | type *operator ->(void) const 521 | { 522 | return (reference); 523 | } 524 | }; 525 | } 526 | 527 | 528 | #endif 529 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSMap.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Container Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSMap.h" 11 | #include "TSBasic.h" 12 | 13 | 14 | using namespace Terathon; 15 | 16 | 17 | MapElementBase::~MapElementBase() 18 | { 19 | if (owningMap) 20 | { 21 | owningMap->RemoveMapElement(this); 22 | } 23 | } 24 | 25 | void MapElementBase::Detach(void) 26 | { 27 | if (owningMap) 28 | { 29 | owningMap->RemoveMapElement(this); 30 | } 31 | } 32 | 33 | MapElementBase *MapElementBase::GetFirstMapElement(void) 34 | { 35 | MapElementBase *element = this; 36 | for (;;) 37 | { 38 | MapElementBase *left = element->leftSubnode; 39 | if (!left) 40 | { 41 | break; 42 | } 43 | 44 | element = left; 45 | } 46 | 47 | return (element); 48 | } 49 | 50 | MapElementBase *MapElementBase::GetLastMapElement(void) 51 | { 52 | MapElementBase *element = this; 53 | for (;;) 54 | { 55 | MapElementBase *right = element->rightSubnode; 56 | if (!right) 57 | { 58 | break; 59 | } 60 | 61 | element = right; 62 | } 63 | 64 | return (element); 65 | } 66 | 67 | MapElementBase *MapElementBase::GetPreviousMapElement(void) const 68 | { 69 | if (leftSubnode) 70 | { 71 | return (leftSubnode->GetLastMapElement()); 72 | } 73 | 74 | const MapElementBase *element = this; 75 | for (;;) 76 | { 77 | MapElementBase *super = element->superNode; 78 | if (!super) 79 | { 80 | break; 81 | } 82 | 83 | if (super->rightSubnode == element) 84 | { 85 | return (super); 86 | } 87 | 88 | element = super; 89 | } 90 | 91 | return (nullptr); 92 | } 93 | 94 | MapElementBase *MapElementBase::GetNextMapElement(void) const 95 | { 96 | if (rightSubnode) 97 | { 98 | return (rightSubnode->GetFirstMapElement()); 99 | } 100 | 101 | const MapElementBase *element = this; 102 | for (;;) 103 | { 104 | MapElementBase *super = element->superNode; 105 | if (!super) 106 | { 107 | break; 108 | } 109 | 110 | if (super->leftSubnode == element) 111 | { 112 | return (super); 113 | } 114 | 115 | element = super; 116 | } 117 | 118 | return (nullptr); 119 | } 120 | 121 | void MapElementBase::RemoveSubtree(void) 122 | { 123 | if (leftSubnode) 124 | { 125 | leftSubnode->RemoveSubtree(); 126 | } 127 | 128 | if (rightSubnode) 129 | { 130 | rightSubnode->RemoveSubtree(); 131 | } 132 | 133 | superNode = nullptr; 134 | leftSubnode = nullptr; 135 | rightSubnode = nullptr; 136 | owningMap = nullptr; 137 | } 138 | 139 | void MapElementBase::DeleteSubtree(void) 140 | { 141 | if (leftSubnode) 142 | { 143 | leftSubnode->DeleteSubtree(); 144 | } 145 | 146 | if (rightSubnode) 147 | { 148 | rightSubnode->DeleteSubtree(); 149 | } 150 | 151 | owningMap = nullptr; 152 | delete this; 153 | } 154 | 155 | 156 | MapBase::~MapBase() 157 | { 158 | PurgeMap(); 159 | } 160 | 161 | MapElementBase *MapBase::operator [](machine index) const 162 | { 163 | machine i = 0; 164 | MapElementBase *element = GetFirstMapElement(); 165 | while (element) 166 | { 167 | if (i == index) 168 | { 169 | return (element); 170 | } 171 | 172 | i++; 173 | element = element->GetNextMapElement(); 174 | } 175 | 176 | return (nullptr); 177 | } 178 | 179 | int32 MapBase::GetMapElementCount(void) const 180 | { 181 | machine count = 0; 182 | const MapElementBase *element = GetFirstMapElement(); 183 | while (element) 184 | { 185 | count++; 186 | element = element->GetNextMapElement(); 187 | } 188 | 189 | return (int32(count)); 190 | } 191 | 192 | MapElementBase *MapBase::RotateLeft(MapElementBase *node) 193 | { 194 | MapElementBase *right = node->rightSubnode; 195 | 196 | if (node != rootElement) 197 | { 198 | MapElementBase *super = node->superNode; 199 | 200 | if (super->leftSubnode == node) 201 | { 202 | super->leftSubnode = right; 203 | } 204 | else 205 | { 206 | super->rightSubnode = right; 207 | } 208 | 209 | right->superNode = super; 210 | } 211 | else 212 | { 213 | rootElement = right; 214 | right->superNode = nullptr; 215 | } 216 | 217 | MapElementBase *subnode = right->leftSubnode; 218 | if (subnode) 219 | { 220 | subnode->superNode = node; 221 | } 222 | 223 | node->rightSubnode = subnode; 224 | 225 | right->leftSubnode = node; 226 | node->superNode = right; 227 | node->balance = -(--right->balance); 228 | 229 | return (right); 230 | } 231 | 232 | MapElementBase *MapBase::RotateRight(MapElementBase *node) 233 | { 234 | MapElementBase *left = node->leftSubnode; 235 | 236 | if (node != rootElement) 237 | { 238 | MapElementBase *super = node->superNode; 239 | 240 | if (super->leftSubnode == node) 241 | { 242 | super->leftSubnode = left; 243 | } 244 | else 245 | { 246 | super->rightSubnode = left; 247 | } 248 | 249 | left->superNode = super; 250 | } 251 | else 252 | { 253 | rootElement = left; 254 | left->superNode = nullptr; 255 | } 256 | 257 | MapElementBase *subnode = left->rightSubnode; 258 | if (subnode) 259 | { 260 | subnode->superNode = node; 261 | } 262 | 263 | node->leftSubnode = subnode; 264 | 265 | left->rightSubnode = node; 266 | node->superNode = left; 267 | node->balance = -(++left->balance); 268 | 269 | return (left); 270 | } 271 | 272 | MapElementBase *MapBase::ZigZagLeft(MapElementBase *node) 273 | { 274 | MapElementBase *right = node->rightSubnode; 275 | MapElementBase *top = right->leftSubnode; 276 | 277 | if (node != rootElement) 278 | { 279 | MapElementBase *super = node->superNode; 280 | 281 | if (super->leftSubnode == node) 282 | { 283 | super->leftSubnode = top; 284 | } 285 | else 286 | { 287 | super->rightSubnode = top; 288 | } 289 | 290 | top->superNode = super; 291 | } 292 | else 293 | { 294 | rootElement = top; 295 | top->superNode = nullptr; 296 | } 297 | 298 | MapElementBase *subLeft = top->leftSubnode; 299 | if (subLeft) 300 | { 301 | subLeft->superNode = node; 302 | } 303 | 304 | node->rightSubnode = subLeft; 305 | 306 | MapElementBase *subRight = top->rightSubnode; 307 | if (subRight) 308 | { 309 | subRight->superNode = right; 310 | } 311 | 312 | right->leftSubnode = subRight; 313 | 314 | top->leftSubnode = node; 315 | top->rightSubnode = right; 316 | node->superNode = top; 317 | right->superNode = top; 318 | 319 | int32 b = top->balance; 320 | node->balance = -MaxZero(b); 321 | right->balance = -MinZero(b); 322 | top->balance = 0; 323 | 324 | return (top); 325 | } 326 | 327 | MapElementBase *MapBase::ZigZagRight(MapElementBase *node) 328 | { 329 | MapElementBase *left = node->leftSubnode; 330 | MapElementBase *top = left->rightSubnode; 331 | 332 | if (node != rootElement) 333 | { 334 | MapElementBase *super = node->superNode; 335 | 336 | if (super->leftSubnode == node) 337 | { 338 | super->leftSubnode = top; 339 | } 340 | else 341 | { 342 | super->rightSubnode = top; 343 | } 344 | 345 | top->superNode = super; 346 | } 347 | else 348 | { 349 | rootElement = top; 350 | top->superNode = nullptr; 351 | } 352 | 353 | MapElementBase *subLeft = top->leftSubnode; 354 | if (subLeft) 355 | { 356 | subLeft->superNode = left; 357 | } 358 | 359 | left->rightSubnode = subLeft; 360 | 361 | MapElementBase *subRight = top->rightSubnode; 362 | if (subRight) 363 | { 364 | subRight->superNode = node; 365 | } 366 | 367 | node->leftSubnode = subRight; 368 | 369 | top->leftSubnode = left; 370 | top->rightSubnode = node; 371 | node->superNode = top; 372 | left->superNode = top; 373 | 374 | int32 b = top->balance; 375 | node->balance = -MinZero(b); 376 | left->balance = -MaxZero(b); 377 | top->balance = 0; 378 | 379 | return (top); 380 | } 381 | 382 | void MapBase::SetRootElement(MapElementBase *node) 383 | { 384 | MapBase *map = node->owningMap; 385 | if (map) 386 | { 387 | map->RemoveMapElement(node); 388 | } 389 | 390 | node->owningMap = this; 391 | node->balance = 0; 392 | 393 | rootElement = node; 394 | } 395 | 396 | void MapBase::InsertLeftSubnode(MapElementBase *node, MapElementBase *subnode) 397 | { 398 | MapBase *map = subnode->owningMap; 399 | if (map) 400 | { 401 | map->RemoveMapElement(subnode); 402 | } 403 | 404 | node->leftSubnode = subnode; 405 | subnode->superNode = node; 406 | subnode->owningMap = this; 407 | subnode->balance = 0; 408 | 409 | int32 b = node->balance - 1; 410 | node->balance = b; 411 | if (b != 0) 412 | { 413 | int32 dir1 = -1; 414 | for (;;) 415 | { 416 | int32 dir2; 417 | 418 | MapElementBase *super = node->superNode; 419 | if (!super) 420 | { 421 | break; 422 | } 423 | 424 | b = super->balance; 425 | if (super->leftSubnode == node) 426 | { 427 | super->balance = --b; 428 | dir2 = -1; 429 | } 430 | else 431 | { 432 | super->balance = ++b; 433 | dir2 = 1; 434 | } 435 | 436 | if (b == 0) 437 | { 438 | break; 439 | } 440 | 441 | if (Abs(b) == 2) 442 | { 443 | if (dir2 == -1) 444 | { 445 | if (dir1 == -1) 446 | { 447 | RotateRight(super); 448 | } 449 | else 450 | { 451 | ZigZagRight(super); 452 | } 453 | } 454 | else 455 | { 456 | if (dir1 == 1) 457 | { 458 | RotateLeft(super); 459 | } 460 | else 461 | { 462 | ZigZagLeft(super); 463 | } 464 | } 465 | 466 | break; 467 | } 468 | 469 | dir1 = dir2; 470 | node = super; 471 | } 472 | } 473 | } 474 | 475 | void MapBase::InsertRightSubnode(MapElementBase *node, MapElementBase *subnode) 476 | { 477 | MapBase *map = subnode->owningMap; 478 | if (map) 479 | { 480 | map->RemoveMapElement(subnode); 481 | } 482 | 483 | node->rightSubnode = subnode; 484 | subnode->superNode = node; 485 | subnode->owningMap = this; 486 | subnode->balance = 0; 487 | 488 | int32 b = node->balance + 1; 489 | node->balance = b; 490 | if (b != 0) 491 | { 492 | int32 dir1 = 1; 493 | for (;;) 494 | { 495 | int32 dir2; 496 | 497 | MapElementBase *super = node->superNode; 498 | if (!super) 499 | { 500 | break; 501 | } 502 | 503 | b = super->balance; 504 | if (super->leftSubnode == node) 505 | { 506 | super->balance = --b; 507 | dir2 = -1; 508 | } 509 | else 510 | { 511 | super->balance = ++b; 512 | dir2 = 1; 513 | } 514 | 515 | if (b == 0) 516 | { 517 | break; 518 | } 519 | 520 | if (Abs(b) == 2) 521 | { 522 | if (dir2 == -1) 523 | { 524 | if (dir1 == -1) 525 | { 526 | RotateRight(super); 527 | } 528 | else 529 | { 530 | ZigZagRight(super); 531 | } 532 | } 533 | else 534 | { 535 | if (dir1 == 1) 536 | { 537 | RotateLeft(super); 538 | } 539 | else 540 | { 541 | ZigZagLeft(super); 542 | } 543 | } 544 | 545 | break; 546 | } 547 | 548 | dir1 = dir2; 549 | node = super; 550 | } 551 | } 552 | } 553 | 554 | void MapBase::ReplaceMapElement(MapElementBase *element, MapElementBase *replacement) 555 | { 556 | MapBase *map = replacement->owningMap; 557 | if (map) 558 | { 559 | map->RemoveMapElement(replacement); 560 | } 561 | 562 | MapElementBase *super = element->superNode; 563 | if (super) 564 | { 565 | if (super->leftSubnode == element) 566 | { 567 | super->leftSubnode = replacement; 568 | } 569 | else 570 | { 571 | super->rightSubnode = replacement; 572 | } 573 | } 574 | 575 | replacement->superNode = super; 576 | replacement->balance = element->balance; 577 | replacement->owningMap = this; 578 | 579 | MapElementBase *subnode = element->leftSubnode; 580 | replacement->leftSubnode = subnode; 581 | if (subnode) 582 | { 583 | subnode->superNode = replacement; 584 | } 585 | 586 | subnode = element->rightSubnode; 587 | replacement->rightSubnode = subnode; 588 | if (subnode) 589 | { 590 | subnode->superNode = replacement; 591 | } 592 | 593 | element->superNode = nullptr; 594 | element->leftSubnode = nullptr; 595 | element->rightSubnode = nullptr; 596 | element->owningMap = nullptr; 597 | } 598 | 599 | void MapBase::RemoveBranchNode(MapElementBase *node, MapElementBase *subnode) 600 | { 601 | MapElementBase *super = node->superNode; 602 | if (subnode) 603 | { 604 | subnode->superNode = super; 605 | } 606 | 607 | if (super) 608 | { 609 | int32 db; 610 | 611 | if (super->leftSubnode == node) 612 | { 613 | super->leftSubnode = subnode; 614 | db = 1; 615 | } 616 | else 617 | { 618 | super->rightSubnode = subnode; 619 | db = -1; 620 | } 621 | 622 | for (;;) 623 | { 624 | int32 b = (super->balance += db); 625 | if (Abs(b) == 1) 626 | { 627 | break; 628 | } 629 | 630 | node = super; 631 | super = super->superNode; 632 | 633 | if (b != 0) 634 | { 635 | if (b > 0) 636 | { 637 | int32 rb = node->rightSubnode->balance; 638 | if (rb >= 0) 639 | { 640 | node = RotateLeft(node); 641 | if (rb == 0) 642 | { 643 | break; 644 | } 645 | } 646 | else 647 | { 648 | node = ZigZagLeft(node); 649 | } 650 | } 651 | else 652 | { 653 | int32 lb = node->leftSubnode->balance; 654 | if (lb <= 0) 655 | { 656 | node = RotateRight(node); 657 | if (lb == 0) 658 | { 659 | break; 660 | } 661 | } 662 | else 663 | { 664 | node = ZigZagRight(node); 665 | } 666 | } 667 | } 668 | 669 | if (!super) 670 | { 671 | break; 672 | } 673 | 674 | db = (super->leftSubnode == node) ? 1 : -1; 675 | } 676 | } 677 | else 678 | { 679 | rootElement = subnode; 680 | } 681 | } 682 | 683 | void MapBase::RemoveMapElement(MapElementBase *element) 684 | { 685 | MapElementBase *left = element->leftSubnode; 686 | MapElementBase *right = element->rightSubnode; 687 | 688 | if ((left) && (right)) 689 | { 690 | MapElementBase *top = right->GetFirstMapElement(); 691 | RemoveBranchNode(top, top->rightSubnode); 692 | 693 | MapElementBase *super = element->superNode; 694 | top->superNode = super; 695 | if (super) 696 | { 697 | if (super->leftSubnode == element) 698 | { 699 | super->leftSubnode = top; 700 | } 701 | else 702 | { 703 | super->rightSubnode = top; 704 | } 705 | } 706 | else 707 | { 708 | rootElement = top; 709 | } 710 | 711 | left = element->leftSubnode; 712 | top->leftSubnode = left; 713 | if (left) 714 | { 715 | left->superNode = top; 716 | } 717 | 718 | right = element->rightSubnode; 719 | top->rightSubnode = right; 720 | if (right) 721 | { 722 | right->superNode = top; 723 | } 724 | 725 | top->balance = element->balance; 726 | } 727 | else 728 | { 729 | RemoveBranchNode(element, (left) ? left : right); 730 | } 731 | 732 | element->superNode = nullptr; 733 | element->leftSubnode = nullptr; 734 | element->rightSubnode = nullptr; 735 | element->owningMap = nullptr; 736 | } 737 | 738 | void MapBase::RemoveAllMapElements(void) 739 | { 740 | if (rootElement) 741 | { 742 | rootElement->RemoveSubtree(); 743 | rootElement = nullptr; 744 | } 745 | } 746 | 747 | void MapBase::PurgeMap(void) 748 | { 749 | if (rootElement) 750 | { 751 | rootElement->DeleteSubtree(); 752 | rootElement = nullptr; 753 | } 754 | } 755 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSMatrix3D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Math Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSMatrix3D.h" 11 | 12 | 13 | using namespace Terathon; 14 | 15 | 16 | alignas(64) const ConstMatrix3D Matrix3D::identity = {{{1.0F, 0.0F, 0.0F}, {0.0F, 1.0F, 0.0F}, {0.0F, 0.0F, 1.0F}}}; 17 | alignas(64) const ConstTransform2D Transform2D::identity = {{{1.0F, 0.0F, 0.0F}, {0.0F, 1.0F, 0.0F}, {0.0F, 0.0F, 1.0F}}}; 18 | 19 | 20 | Matrix3D::Matrix3D(float n00, float n01, float n02, float n10, float n11, float n12, float n20, float n21, float n22) : Mat3D(n00, n01, n02, n10, n11, n12, n20, n21, n22) 21 | { 22 | } 23 | 24 | Matrix3D::Matrix3D(const Vector3D& a, const Vector3D& b, const Vector3D& c) 25 | { 26 | col0 = a; 27 | col1 = b; 28 | col2 = c; 29 | } 30 | 31 | Matrix3D& Matrix3D::Set(float n00, float n01, float n02, float n10, float n11, float n12, float n20, float n21, float n22) 32 | { 33 | matrix.Set(n00, n01, n02, n10, n11, n12, n20, n21, n22); 34 | return (*this); 35 | } 36 | 37 | Matrix3D& Matrix3D::Set(const Vector3D& a, const Vector3D& b, const Vector3D& c) 38 | { 39 | col0 = a; 40 | col1 = b; 41 | col2 = c; 42 | return (*this); 43 | } 44 | 45 | Matrix3D& Matrix3D::operator *=(const Matrix3D& m) 46 | { 47 | float t = m00 * m(0,0) + m01 * m(1,0) + m02 * m(2,0); 48 | float u = m00 * m(0,1) + m01 * m(1,1) + m02 * m(2,1); 49 | m02 = m00 * m(0,2) + m01 * m(1,2) + m02 * m(2,2); 50 | m00 = t; 51 | m01 = u; 52 | 53 | t = m10 * m(0,0) + m11 * m(1,0) + m12 * m(2,0); 54 | u = m10 * m(0,1) + m11 * m(1,1) + m12 * m(2,1); 55 | m12 = m10 * m(0,2) + m11 * m(1,2) + m12 * m(2,2); 56 | m10 = t; 57 | m11 = u; 58 | 59 | t = m20 * m(0,0) + m21 * m(1,0) + m22 * m(2,0); 60 | u = m20 * m(0,1) + m21 * m(1,1) + m22 * m(2,1); 61 | m22 = m20 * m(0,2) + m21 * m(1,2) + m22 * m(2,2); 62 | m20 = t; 63 | m21 = u; 64 | 65 | return (*this); 66 | } 67 | 68 | Matrix3D& Matrix3D::operator *=(float s) 69 | { 70 | matrix *= s; 71 | return (*this); 72 | } 73 | 74 | Matrix3D& Matrix3D::operator /=(float s) 75 | { 76 | matrix /= s; 77 | return (*this); 78 | } 79 | 80 | Matrix3D& Matrix3D::SetIdentity(void) 81 | { 82 | m00 = m11 = m22 = 1.0F; 83 | m01 = m02 = m10 = m12 = m20 = m21 = 0.0F; 84 | return (*this); 85 | } 86 | 87 | Matrix3D& Matrix3D::Orthogonalize(int32 column) 88 | { 89 | Vector3D& x = (*this)[column]; 90 | Vector3D& y = (*this)[(column < 2) ? column + 1 : 0]; 91 | Vector3D& z = (*this)[(column > 0) ? column - 1 : 2]; 92 | 93 | x.Normalize(); 94 | y = Normalize(y - x * Dot(x, y)); 95 | z = Normalize(z - x * Dot(x, z) - y * Dot(y, z)); 96 | 97 | return (*this); 98 | } 99 | 100 | void Matrix3D::GetEulerAngles(float *x, float *y, float *z) const 101 | { 102 | float sy = m02; 103 | if (sy < 1.0F) 104 | { 105 | if (sy > -1.0F) 106 | { 107 | *x = -Arctan(m12, m22); 108 | *y = Arcsin(sy); 109 | *z = -Arctan(m01, m00); 110 | } 111 | else 112 | { 113 | *x = 0.0F; 114 | *y = -Math::tau_over_4; 115 | *z = Arctan(m10, m11); 116 | } 117 | } 118 | else 119 | { 120 | *x = 0.0F; 121 | *y = Math::tau_over_4; 122 | *z = Arctan(m10, m11); 123 | } 124 | } 125 | 126 | Matrix3D& Matrix3D::SetEulerAngles(float x, float y, float z) 127 | { 128 | Vector2D xrot = CosSin(x); 129 | Vector2D yrot = CosSin(y); 130 | Vector2D zrot = CosSin(z); 131 | 132 | m00 = yrot.x * zrot.x; 133 | m10 = xrot.x * zrot.y + xrot.y * yrot.y * zrot.x; 134 | m20 = xrot.y * zrot.y - xrot.x * yrot.y * zrot.x; 135 | m01 = -yrot.x * zrot.y; 136 | m11 = xrot.x * zrot.x - xrot.y * yrot.y * zrot.y; 137 | m21 = xrot.y * zrot.x + xrot.x * yrot.y * zrot.y; 138 | m02 = yrot.y; 139 | m12 = -xrot.y * yrot.x; 140 | m22 = xrot.x * yrot.x; 141 | 142 | return (*this); 143 | } 144 | 145 | Matrix3D Matrix3D::MakeRotationX(float angle) 146 | { 147 | Vector2D v = CosSin(angle); 148 | 149 | return (Matrix3D(1.0F, 0.0F, 0.0F, 150 | 0.0F, v.x, -v.y, 151 | 0.0F, v.y, v.x)); 152 | } 153 | 154 | Matrix3D Matrix3D::MakeRotationY(float angle) 155 | { 156 | Vector2D v = CosSin(angle); 157 | 158 | return (Matrix3D( v.x, 0.0F, v.y, 159 | 0.0F, 1.0F, 0.0F, 160 | -v.y, 0.0F, v.x)); 161 | } 162 | 163 | Matrix3D Matrix3D::MakeRotationZ(float angle) 164 | { 165 | Vector2D v = CosSin(angle); 166 | 167 | return (Matrix3D( v.x, -v.y, 0.0F, 168 | v.y, v.x, 0.0F, 169 | 0.0F, 0.0F, 1.0F)); 170 | } 171 | 172 | Matrix3D Matrix3D::MakeRotation(float angle, const Bivector3D& axis) 173 | { 174 | float c, s; 175 | 176 | CosSin(angle, &c, &s); 177 | float d = 1.0F - c; 178 | 179 | float x = axis.x * d; 180 | float y = axis.y * d; 181 | float z = axis.z * d; 182 | float axay = x * axis.y; 183 | float axaz = x * axis.z; 184 | float ayaz = y * axis.z; 185 | 186 | return (Matrix3D(c + x * axis.x, axay - s * axis.z, axaz + s * axis.y, 187 | axay + s * axis.z, c + y * axis.y, ayaz - s * axis.x, 188 | axaz - s * axis.y, ayaz + s * axis.x, c + z * axis.z)); 189 | } 190 | 191 | Matrix3D Matrix3D::MakeReflection(const Vector3D& a) 192 | { 193 | float x = a.x * -2.0F; 194 | float y = a.y * -2.0F; 195 | float z = a.z * -2.0F; 196 | float axay = x * a.y; 197 | float axaz = x * a.z; 198 | float ayaz = y * a.z; 199 | 200 | return (Matrix3D(x * a.x + 1.0F, axay, axaz, 201 | axay, y * a.y + 1.0F, ayaz, 202 | axaz, ayaz, z * a.z + 1.0F)); 203 | } 204 | 205 | Matrix3D Matrix3D::MakeInvolution(const Vector3D& a) 206 | { 207 | float x = a.x * 2.0F; 208 | float y = a.y * 2.0F; 209 | float z = a.z * 2.0F; 210 | float axay = x * a.y; 211 | float axaz = x * a.z; 212 | float ayaz = y * a.z; 213 | 214 | return (Matrix3D(x * a.x - 1.0F, axay, axaz, 215 | axay, y * a.y - 1.0F, ayaz, 216 | axaz, ayaz, z * a.z - 1.0F)); 217 | } 218 | 219 | Matrix3D Matrix3D::MakeScale(float scale) 220 | { 221 | return (Matrix3D(scale, 0.0F, 0.0F, 0.0F, scale, 0.0F, 0.0F, 0.0F, scale)); 222 | } 223 | 224 | Matrix3D Matrix3D::MakeScale(float sx, float sy, float sz) 225 | { 226 | return (Matrix3D(sx, 0.0F, 0.0F, 0.0F, sy, 0.0F, 0.0F, 0.0F, sz)); 227 | } 228 | 229 | Matrix3D Matrix3D::MakeScale(float scale, const Vector3D& a) 230 | { 231 | scale -= 1.0F; 232 | float x = a.x * scale; 233 | float y = a.y * scale; 234 | float z = a.z * scale; 235 | float axay = x * a.y; 236 | float axaz = x * a.z; 237 | float ayaz = y * a.z; 238 | 239 | return (Matrix3D(x * a.x + 1.0F, axay, axaz, 240 | axay, y * a.y + 1.0F, ayaz, 241 | axaz, ayaz, z * a.z + 1.0F)); 242 | } 243 | 244 | Matrix3D Matrix3D::MakeScaleX(float sx) 245 | { 246 | return (Matrix3D(sx, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F)); 247 | } 248 | 249 | Matrix3D Matrix3D::MakeScaleY(float sy) 250 | { 251 | return (Matrix3D(1.0F, 0.0F, 0.0F, 0.0F, sy, 0.0F, 0.0F, 0.0F, 1.0F)); 252 | } 253 | 254 | Matrix3D Matrix3D::MakeScaleZ(float sz) 255 | { 256 | return (Matrix3D(1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, sz)); 257 | } 258 | 259 | Matrix3D Matrix3D::MakeSkew(float angle, const Vector3D& a, const Vector3D& b) 260 | { 261 | float t = Tan(angle); 262 | float x = a.x * t; 263 | float y = a.y * t; 264 | float z = a.z * t; 265 | 266 | return (Matrix3D(x * b.x + 1.0F, x * b.y, x * b.z, 267 | y * b.x, y * b.y + 1.0F, y * b.z, 268 | z * b.x, z * b.y, z * b.z + 1.0F)); 269 | } 270 | 271 | 272 | Matrix3D Terathon::operator *(const Matrix3D& m, float s) 273 | { 274 | return (Matrix3D(m(0,0) * s, m(0,1) * s, m(0,2) * s, m(1,0) * s, m(1,1) * s, m(1,2) * s, m(2,0) * s, m(2,1) * s, m(2,2) * s)); 275 | } 276 | 277 | Matrix3D Terathon::operator /(const Matrix3D& m, float s) 278 | { 279 | s = 1.0F / s; 280 | return (Matrix3D(m(0,0) * s, m(0,1) * s, m(0,2) * s, m(1,0) * s, m(1,1) * s, m(1,2) * s, m(2,0) * s, m(2,1) * s, m(2,2) * s)); 281 | } 282 | 283 | float Terathon::Determinant(const Matrix3D& m) 284 | { 285 | return (m(0,0) * (m(1,1) * m(2,2) - m(1,2) * m(2,1)) - m(0,1) * (m(1,0) * m(2,2) - m(1,2) * m(2,0)) + m(0,2) * (m(1,0) * m(2,1) - m(1,1) * m(2,0))); 286 | } 287 | 288 | Matrix3D Terathon::Inverse(const Matrix3D& m) 289 | { 290 | const Vector3D& a = m[0]; 291 | const Vector3D& b = m[1]; 292 | const Vector3D& c = m[2]; 293 | 294 | Bivector3D g0 = b ^ c; 295 | Bivector3D g1 = c ^ a; 296 | Bivector3D g2 = a ^ b; 297 | 298 | float invDet = 1.0F / (g2 ^ c); 299 | 300 | return (Matrix3D(g0.x * invDet, g0.y * invDet, g0.z * invDet, 301 | g1.x * invDet, g1.y * invDet, g1.z * invDet, 302 | g2.x * invDet, g2.y * invDet, g2.z * invDet)); 303 | } 304 | 305 | Matrix3D Terathon::Adjugate(const Matrix3D& m) 306 | { 307 | const Vector3D& a = m[0]; 308 | const Vector3D& b = m[1]; 309 | const Vector3D& c = m[2]; 310 | 311 | Bivector3D g0 = b ^ c; 312 | Bivector3D g1 = c ^ a; 313 | Bivector3D g2 = a ^ b; 314 | 315 | return (Matrix3D(g0.x, g0.y, g0.z, g1.x, g1.y, g1.z, g2.x, g2.y, g2.z)); 316 | } 317 | 318 | 319 | Transform2D::Transform2D(float n00, float n01, float n02, float n10, float n11, float n12) 320 | { 321 | m00 = n00; 322 | m01 = n01; 323 | m02 = n02; 324 | m10 = n10; 325 | m11 = n11; 326 | m12 = n12; 327 | 328 | row2.Set(0.0F, 0.0F, 1.0F); 329 | } 330 | 331 | Transform2D::Transform2D(const Vector2D& a, const Vector2D& b, const Point2D& p) 332 | { 333 | m00 = a.x; 334 | m10 = a.y; 335 | m01 = b.x; 336 | m11 = b.y; 337 | m02 = p.x; 338 | m12 = p.y; 339 | 340 | row2.Set(0.0F, 0.0F, 1.0F); 341 | } 342 | 343 | Transform2D::Transform2D(const Vector2D& r0, float n02, const Vector2D& r1, float n12) 344 | { 345 | row0.Set(r0.x, r0.y, n02); 346 | row1.Set(r1.x, r1.y, n12); 347 | row2.Set(0.0F, 0.0F, 1.0F); 348 | } 349 | 350 | Transform2D::Transform2D(const Matrix2D& m) 351 | { 352 | m00 = m.m00; 353 | m10 = m.m10; 354 | m01 = m.m01; 355 | m11 = m.m11; 356 | 357 | m02 = m12 = 0.0F; 358 | row2.Set(0.0F, 0.0F, 1.0F); 359 | } 360 | 361 | Transform2D::Transform2D(const Matrix2D& m, const Vector2D& v) 362 | { 363 | m00 = m.m00; 364 | m10 = m.m10; 365 | m01 = m.m01; 366 | m11 = m.m11; 367 | m02 = v.x; 368 | m12 = v.y; 369 | 370 | row2.Set(0.0F, 0.0F, 1.0F); 371 | } 372 | 373 | Transform2D& Transform2D::Set(float n00, float n01, float n02, float n10, float n11, float n12) 374 | { 375 | m00 = n00; 376 | m01 = n01; 377 | m02 = n02; 378 | m10 = n10; 379 | m11 = n11; 380 | m12 = n12; 381 | 382 | row2.Set(0.0F, 0.0F, 1.0F); 383 | return (*this); 384 | } 385 | 386 | Transform2D& Transform2D::Set(const Vector2D& a, const Vector2D& b, const Point2D& p) 387 | { 388 | m00 = a.x; 389 | m10 = a.y; 390 | m01 = b.x; 391 | m11 = b.y; 392 | m02 = p.x; 393 | m12 = p.y; 394 | 395 | row2.Set(0.0F, 0.0F, 1.0F); 396 | return (*this); 397 | } 398 | 399 | Transform2D& Transform2D::Set(const Matrix2D& m, const Vector2D& v) 400 | { 401 | m00 = m.m00; 402 | m10 = m.m10; 403 | m01 = m.m01; 404 | m11 = m.m11; 405 | m02 = v.x; 406 | m12 = v.y; 407 | 408 | row2.Set(0.0F, 0.0F, 1.0F); 409 | return (*this); 410 | } 411 | 412 | Transform2D& Transform2D::operator *=(const Transform2D& m) 413 | { 414 | float x = m00; 415 | float y = m01; 416 | m00 = x * m.m00 + y * m.m10; 417 | m01 = x * m.m01 + y * m.m11; 418 | m02 = x * m.m02 + y * m.m12 + m02; 419 | 420 | x = m10; 421 | y = m11; 422 | m10 = x * m.m00 + y * m.m10; 423 | m11 = x * m.m01 + y * m.m11; 424 | m12 = x * m.m02 + y * m.m12 + m12; 425 | 426 | return (*this); 427 | } 428 | 429 | Transform2D& Transform2D::operator *=(const Matrix2D& m) 430 | { 431 | float x = m00; 432 | float y = m01; 433 | m00 = x * m.m00 + y * m.m10; 434 | m01 = x * m.m01 + y * m.m11; 435 | 436 | x = m10; 437 | y = m11; 438 | m10 = x * m.m00 + y * m.m10; 439 | m11 = x * m.m01 + y * m.m11; 440 | 441 | return (*this); 442 | } 443 | 444 | Transform2D& Transform2D::SetMatrix2D(const Vector2D& a, const Vector2D& b) 445 | { 446 | m00 = a.x; 447 | m10 = a.y; 448 | m01 = b.x; 449 | m11 = b.y; 450 | 451 | return (*this); 452 | } 453 | 454 | Transform2D& Transform2D::Orthogonalize(int32 column) 455 | { 456 | Vector2D& x = (*this)[column]; 457 | Vector2D& y = (*this)[1 - column]; 458 | 459 | x.Normalize(); 460 | y = Normalize(y - x * Dot(x, y)); 461 | 462 | return (*this); 463 | } 464 | 465 | Transform2D Transform2D::MakeRotation(float angle) 466 | { 467 | Vector2D v = CosSin(angle); 468 | 469 | return (Transform2D(v.x, -v.y, 0.0F, 470 | v.y, v.x, 0.0F)); 471 | } 472 | 473 | Transform2D Transform2D::MakeScale(float sx, float sy) 474 | { 475 | return (Transform2D(sx, 0.0F, 0.0F, 0.0F, sy, 0.0F)); 476 | } 477 | 478 | Transform2D Transform2D::MakeTranslation(const Vector2D& dv) 479 | { 480 | return (Transform2D(1.0F, 0.0F, dv.x, 0.0F, 1.0F, dv.y)); 481 | } 482 | 483 | 484 | Transform2D Terathon::operator *(const Transform2D& m1, const Transform2D& m2) 485 | { 486 | return (Transform2D(m1(0,0) * m2(0,0) + m1(0,1) * m2(1,0), 487 | m1(0,0) * m2(0,1) + m1(0,1) * m2(1,1), 488 | m1(0,0) * m2(0,2) + m1(0,1) * m2(1,2) + m1(0,2), 489 | m1(1,0) * m2(0,0) + m1(1,1) * m2(1,0), 490 | m1(1,0) * m2(0,1) + m1(1,1) * m2(1,1), 491 | m1(1,0) * m2(0,2) + m1(1,1) * m2(1,2) + m1(1,2))); 492 | } 493 | 494 | Matrix3D Terathon::operator *(const Matrix3D& m1, const Transform2D& m2) 495 | { 496 | return (Matrix3D(m1(0,0) * m2(0,0) + m1(0,1) * m2(1,0), 497 | m1(0,0) * m2(0,1) + m1(0,1) * m2(1,1), 498 | m1(0,0) * m2(0,2) + m1(0,1) * m2(1,2) + m1(0,2), 499 | m1(1,0) * m2(0,0) + m1(1,1) * m2(1,0), 500 | m1(1,0) * m2(0,1) + m1(1,1) * m2(1,1), 501 | m1(1,0) * m2(0,2) + m1(1,1) * m2(1,2) + m1(1,2), 502 | m1(2,0) * m2(0,0) + m1(2,1) * m2(1,0), 503 | m1(2,0) * m2(0,1) + m1(2,1) * m2(1,1), 504 | m1(2,0) * m2(0,2) + m1(2,1) * m2(1,2) + m1(2,2))); 505 | } 506 | 507 | Matrix3D Terathon::operator *(const Transform2D& m1, const Matrix3D& m2) 508 | { 509 | return (Matrix3D(m1(0,0) * m2(0,0) + m1(0,1) * m2(1,0) + m1(0,2) * m2(2,0), 510 | m1(0,0) * m2(0,1) + m1(0,1) * m2(1,1) + m1(0,2) * m2(2,1), 511 | m1(0,0) * m2(0,2) + m1(0,1) * m2(1,2) + m1(0,2) * m2(2,2), 512 | m1(1,0) * m2(0,0) + m1(1,1) * m2(1,0) + m1(1,2) * m2(2,0), 513 | m1(1,0) * m2(0,1) + m1(1,1) * m2(1,1) + m1(1,2) * m2(2,1), 514 | m1(1,0) * m2(0,2) + m1(1,1) * m2(1,2) + m1(1,2) * m2(2,2), 515 | m2(2,0), m2(2,1), m2(2,2))); 516 | } 517 | 518 | Vector2D Terathon::operator *(const Transform2D& m, const Vector2D& v) 519 | { 520 | return (m * v.xy); 521 | } 522 | 523 | Vector2D Terathon::operator *(const Vector2D& v, const Transform2D& m) 524 | { 525 | return (v.xy * m); 526 | } 527 | 528 | Point2D Terathon::operator *(const Transform2D& m, const Point2D& p) 529 | { 530 | return (Point2D(m(0,0) * p.x + m(0,1) * p.y + m(0,2), 531 | m(1,0) * p.x + m(1,1) * p.y + m(1,2))); 532 | } 533 | 534 | float Terathon::Determinant(const Transform2D& m) 535 | { 536 | return (m(0,0) * m(1,1) - m(0,1) * m(1,0)); 537 | } 538 | 539 | Transform2D Terathon::Inverse(const Transform2D& m) 540 | { 541 | float invDet = 1.0F / (m(0,0) * m(1,1) - m(0,1) * m(1,0)); 542 | 543 | return (Transform2D(m(1,1) * invDet, -m(0,1) * invDet, (m(0,1) * m(1,2) - m(0,2) * m(1,1)) * invDet, 544 | -m(1,0) * invDet, m(0,0) * invDet, (m(0,2) * m(1,0) - m(0,0) * m(1,2)) * invDet)); 545 | } 546 | 547 | Transform2D Terathon::InverseUnitDet(const Transform2D& m) 548 | { 549 | return (Transform2D(m(1,1), -m(0,1), m(0,1) * m(1,2) - m(0,2) * m(1,1), 550 | -m(1,0), m(0,0), m(0,2) * m(1,0) - m(0,0) * m(1,2))); 551 | } 552 | -------------------------------------------------------------------------------- /Importer/OpenDDL/Code/TSColor.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This file is part of the Terathon Common Library, by Eric Lengyel. 3 | // Copyright 1999-2025, Terathon Software LLC 4 | // 5 | // This software is distributed under the MIT License. 6 | // Separate proprietary licenses are available from Terathon Software. 7 | // 8 | 9 | 10 | #include "TSColor.h" 11 | #include "TSBasic.h" 12 | #include "TSMath.h" 13 | 14 | 15 | using namespace Terathon; 16 | 17 | 18 | namespace 19 | { 20 | alignas(16) const char hexDigit[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 21 | } 22 | 23 | 24 | alignas(64) const uint8 Color::srgbLinearizationTable[256] = 25 | { 26 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 27 | 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 28 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 29 | 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 30 | 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, 31 | 0x14, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1B, 0x1B, 0x1C, 0x1D, 0x1D, 32 | 0x1E, 0x1E, 0x1F, 0x20, 0x20, 0x21, 0x22, 0x23, 0x23, 0x24, 0x25, 0x25, 0x26, 0x27, 0x28, 0x29, 33 | 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x33, 0x34, 0x35, 0x36, 34 | 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 35 | 0x47, 0x48, 0x49, 0x4A, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 36 | 0x5A, 0x5B, 0x5C, 0x5D, 0x5F, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 37 | 0x6F, 0x70, 0x72, 0x73, 0x74, 0x76, 0x77, 0x79, 0x7A, 0x7C, 0x7D, 0x7F, 0x80, 0x82, 0x83, 0x85, 38 | 0x86, 0x88, 0x8A, 0x8B, 0x8D, 0x8E, 0x90, 0x92, 0x93, 0x95, 0x97, 0x98, 0x9A, 0x9C, 0x9D, 0x9F, 39 | 0xA1, 0xA3, 0xA4, 0xA6, 0xA8, 0xAA, 0xAB, 0xAD, 0xAF, 0xB1, 0xB3, 0xB5, 0xB7, 0xB8, 0xBA, 0xBC, 40 | 0xBE, 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 41 | 0xDE, 0xE0, 0xE2, 0xE5, 0xE7, 0xE9, 0xEB, 0xED, 0xEF, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFD, 0xFF 42 | }; 43 | 44 | alignas(64) const uint8 Color::srgbDelinearizationTable[256] = 45 | { 46 | 0x00, 0x0D, 0x16, 0x1C, 0x22, 0x26, 0x2A, 0x2E, 0x32, 0x35, 0x38, 0x3B, 0x3D, 0x40, 0x42, 0x45, 47 | 0x47, 0x49, 0x4B, 0x4D, 0x4F, 0x51, 0x53, 0x55, 0x56, 0x58, 0x5A, 0x5C, 0x5D, 0x5F, 0x60, 0x62, 48 | 0x63, 0x65, 0x66, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x70, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 49 | 0x78, 0x79, 0x7A, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 50 | 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0x96, 0x97, 51 | 0x98, 0x99, 0x9A, 0x9B, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA3, 0xA4, 52 | 0xA5, 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, 0xAF, 0xAF, 0xB0, 53 | 0xB1, 0xB2, 0xB2, 0xB3, 0xB4, 0xB4, 0xB5, 0xB6, 0xB6, 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBB, 54 | 0xBC, 0xBD, 0xBD, 0xBE, 0xBE, 0xBF, 0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC5, 55 | 0xC6, 0xC7, 0xC7, 0xC8, 0xC8, 0xC9, 0xCA, 0xCA, 0xCB, 0xCB, 0xCC, 0xCD, 0xCD, 0xCE, 0xCE, 0xCF, 56 | 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD2, 0xD3, 0xD4, 0xD4, 0xD5, 0xD5, 0xD6, 0xD6, 0xD7, 0xD7, 0xD8, 57 | 0xD8, 0xD9, 0xDA, 0xDA, 0xDB, 0xDB, 0xDC, 0xDC, 0xDD, 0xDD, 0xDE, 0xDE, 0xDF, 0xDF, 0xE0, 0xE0, 58 | 0xE1, 0xE2, 0xE2, 0xE3, 0xE3, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE8, 0xE9, 59 | 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 60 | 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, 0xF7, 0xF7, 0xF8, 61 | 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFF, 0xFF 62 | }; 63 | 64 | alignas(64) const float Color::srgbFloatLinearizationTable[256] = 65 | { 66 | 0.0F, 0.0003F, 0.0006F, 0.00091F, 0.001214F, 0.0015175F, 0.0018211F, 0.0021246F, 0.0024281F, 0.0027316F, 0.0030351F, 0.0033464F, 0.0036764F, 0.0040246F, 0.0043914F, 0.0047768F, 67 | 0.0051814F, 0.0056053F, 0.0060487F, 0.006512F, 0.0069953F, 0.0074989F, 0.0080231F, 0.008568F, 0.009134F, 0.0097211F, 0.0103297F, 0.01096F, 0.0116121F, 0.0122864F, 0.0129829F, 0.013702F, 68 | 0.0144437F, 0.0152084F, 0.0159962F, 0.0168073F, 0.0176419F, 0.0185002F, 0.0193823F, 0.0202884F, 0.0212188F, 0.0221738F, 0.0231533F, 0.0241575F, 0.0251867F, 0.0262411F, 0.0273208F, 0.0284259F, 69 | 0.0295567F, 0.0307134F, 0.0318959F, 0.0331046F, 0.0343397F, 0.0356012F, 0.0368894F, 0.0382043F, 0.0395461F, 0.0409151F, 0.0423113F, 0.0437349F, 0.0451861F, 0.046665F, 0.0481717F, 0.0497064F, 70 | 0.0512694F, 0.0528606F, 0.0544801F, 0.0561283F, 0.0578054F, 0.0595111F, 0.061246F, 0.06301F, 0.0648032F, 0.0666259F, 0.0684781F, 0.07036F, 0.0722718F, 0.0742135F, 0.0761853F, 0.0781873F, 71 | 0.0802197F, 0.0822826F, 0.084376F, 0.0865004F, 0.0886555F, 0.0908416F, 0.0930589F, 0.0953074F, 0.0975873F, 0.0998986F, 0.1022416F, 0.1046164F, 0.107023F, 0.1094616F, 0.1119323F, 0.1144353F, 72 | 0.1169705F, 0.1195383F, 0.1221387F, 0.1247717F, 0.1274377F, 0.1301363F, 0.1328682F, 0.1356333F, 0.1384315F, 0.1412632F, 0.1441284F, 0.1470272F, 0.1499596F, 0.152926F, 0.1559264F, 0.1589608F, 73 | 0.1620292F, 0.1651321F, 0.1682693F, 0.171441F, 0.1746473F, 0.1778882F, 0.1811641F, 0.1844749F, 0.1878206F, 0.1912016F, 0.1946177F, 0.1980692F, 0.2015562F, 0.2050786F, 0.2086367F, 0.2122306F, 74 | 0.2158604F, 0.2195261F, 0.2232278F, 0.2269659F, 0.23074F, 0.2345505F, 0.2383975F, 0.2422811F, 0.2462013F, 0.2501583F, 0.2541521F, 0.2581828F, 0.2622506F, 0.2663556F, 0.2704977F, 0.2746772F, 75 | 0.2788943F, 0.2831487F, 0.2874408F, 0.2917706F, 0.2961382F, 0.3005437F, 0.3049873F, 0.3094688F, 0.3139886F, 0.3185467F, 0.3231432F, 0.3277781F, 0.3324515F, 0.3371635F, 0.3419144F, 0.346704F, 76 | 0.3515325F, 0.3564001F, 0.3613067F, 0.3662526F, 0.3712377F, 0.3762621F, 0.381326F, 0.3864294F, 0.3915725F, 0.3967552F, 0.4019777F, 0.4072402F, 0.4125427F, 0.4178851F, 0.4232677F, 0.4286905F, 77 | 0.4341536F, 0.4396572F, 0.4452011F, 0.4507857F, 0.4564111F, 0.462077F, 0.4677838F, 0.4735316F, 0.4793202F, 0.48515F, 0.4910207F, 0.4969329F, 0.5028865F, 0.5088814F, 0.5149177F, 0.5209956F, 78 | 0.5271152F, 0.5332765F, 0.5394796F, 0.5457245F, 0.5520114F, 0.5583404F, 0.5647115F, 0.5711249F, 0.5775804F, 0.5840784F, 0.5906188F, 0.5972018F, 0.6038274F, 0.6104956F, 0.6172066F, 0.6239603F, 79 | 0.6307572F, 0.6375969F, 0.6444797F, 0.6514056F, 0.6583749F, 0.6653873F, 0.6724431F, 0.6795424F, 0.6866854F, 0.6938719F, 0.7011021F, 0.7083759F, 0.7156937F, 0.7230552F, 0.7304608F, 0.7379105F, 80 | 0.7454043F, 0.7529422F, 0.7605246F, 0.7681512F, 0.7758221F, 0.7835378F, 0.791298F, 0.7991029F, 0.8069523F, 0.8148466F, 0.8227857F, 0.83077F, 0.8387989F, 0.8468731F, 0.8549928F, 0.8631572F, 81 | 0.8713669F, 0.8796223F, 0.8879232F, 0.8962693F, 0.9046614F, 0.9130986F, 0.9215819F, 0.9301109F, 0.9386857F, 0.9473063F, 0.9559732F, 0.9646861F, 0.9734454F, 0.9822505F, 0.9911019F, 1.0F 82 | }; 83 | 84 | 85 | alignas(16) const ConstColorRGBA Color::black = {0.0F, 0.0F, 0.0F, 1.0F}; 86 | alignas(16) const ConstColorRGBA Color::white = {1.0F, 1.0F, 1.0F, 1.0F}; 87 | alignas(16) const ConstColorRGBA Color::transparent = {0.0F, 0.0F, 0.0F, 0.0F}; 88 | alignas(16) const ConstColorRGBA Color::red = {1.0F, 0.0F, 0.0F, 1.0F}; 89 | alignas(16) const ConstColorRGBA Color::green = {0.0F, 1.0F, 0.0F, 1.0F}; 90 | alignas(16) const ConstColorRGBA Color::blue = {0.0F, 0.0F, 1.0F, 1.0F}; 91 | alignas(16) const ConstColorRGBA Color::yellow = {1.0F, 1.0F, 0.0F, 1.0F}; 92 | alignas(16) const ConstColorRGBA Color::cyan = {0.0F, 1.0F, 1.0F, 1.0F}; 93 | alignas(16) const ConstColorRGBA Color::magenta = {1.0F, 0.0F, 1.0F, 1.0F}; 94 | 95 | 96 | void ColorRGB::GetHueSat(float *hue, float *sat) const 97 | { 98 | float M = Fmax(red, green, blue); 99 | if (M > Math::min_float) 100 | { 101 | M = 1.0F / M; 102 | float r = red * M; 103 | float g = green * M; 104 | float b = blue * M; 105 | 106 | float m = Fmin(r, g, b); 107 | float s = 1.0F - m; 108 | if (s > Math::min_float) 109 | { 110 | *sat = s; 111 | s = 1.0F / s; 112 | 113 | if ((r >= g) && (r >= b)) 114 | { 115 | float h = (g - b) * s; 116 | if (h < 0.0F) 117 | { 118 | h += 6.0F; 119 | } 120 | 121 | *hue = h; 122 | } 123 | else if (g >= b) 124 | { 125 | *hue = (b - r) * s + 2.0F; 126 | } 127 | else 128 | { 129 | *hue = (r - g) * s + 4.0F; 130 | } 131 | 132 | return; 133 | } 134 | } 135 | 136 | *hue = 0.0F; 137 | *sat = 0.0F; 138 | } 139 | 140 | void ColorRGB::SetHueSat(float hue, float sat) 141 | { 142 | float f = Frac(hue) * sat; 143 | float s = 1.0F - sat; 144 | 145 | switch (int32(hue)) 146 | { 147 | case 0: 148 | 149 | Set(1.0F, s + f, s); 150 | break; 151 | 152 | case 1: 153 | 154 | Set(s + sat - f, 1.0F, s); 155 | break; 156 | 157 | case 2: 158 | 159 | Set(s, 1.0F, s + f); 160 | break; 161 | 162 | case 3: 163 | 164 | Set(s, s + sat - f, 1.0F); 165 | break; 166 | 167 | case 4: 168 | 169 | Set(s + f, s, 1.0F); 170 | break; 171 | 172 | case 5: 173 | 174 | Set(1.0F, s, s + sat - f); 175 | break; 176 | } 177 | } 178 | 179 | ColorRGB ColorRGB::GetBrightestColor(void) const 180 | { 181 | float M = Fmax(red, green, blue); 182 | if (M > Math::min_float) 183 | { 184 | M = 1.0F / M; 185 | return (ColorRGB(red * M, green * M, blue * M)); 186 | } 187 | 188 | return (ColorRGB(1.0F, 1.0F, 1.0F)); 189 | } 190 | 191 | uint32 ColorRGB::GetPackedColorRGB9E5(void) const 192 | { 193 | alignas(64) static const uint32 dividerTable[32] = 194 | { 195 | 0x4B800000, 0x4B000000, 0x4A800000, 0x4A000000, 0x49800000, 0x49000000, 0x48800000, 0x48000000, 0x47800000, 0x47000000, 0x46800000, 0x46000000, 0x45800000, 0x45000000, 0x44800000, 0x44000000, 196 | 0x43800000, 0x43000000, 0x42800000, 0x42000000, 0x41800000, 0x41000000, 0x40800000, 0x40000000, 0x3F800000, 0x3F000000, 0x3E800000, 0x3E000000, 0x3D800000, 0x3D000000, 0x3C800000, 0x3C000000 197 | }; 198 | 199 | float r = Clamp(red, 0.0F, 511.0F * 128.0F); 200 | float g = Clamp(green, 0.0F, 511.0F * 128.0F); 201 | float b = Clamp(blue, 0.0F, 511.0F * 128.0F); 202 | float m = Fmax(r, g, b); 203 | 204 | uint32 e = MaxZero(int32(asuint(m) >> 23) - 111); 205 | e += uint32(m * asfloat(dividerTable[e]) + 0.5F) >> 9; 206 | 207 | float d = asfloat(dividerTable[e]); 208 | uint32 x = uint32(r * d + 0.5F); 209 | uint32 y = uint32(g * d + 0.5F); 210 | uint32 z = uint32(b * d + 0.5F); 211 | 212 | return (x | (y << 9) | (z << 18) | (e << 27)); 213 | } 214 | 215 | void ColorRGB::GetHexString(char *string) const 216 | { 217 | int32 r = int32(Color::Delinearize(red) * 255.0F + 0.5F); 218 | int32 g = int32(Color::Delinearize(green) * 255.0F + 0.5F); 219 | int32 b = int32(Color::Delinearize(blue) * 255.0F + 0.5F); 220 | 221 | string[0] = hexDigit[(r >> 4) & 15]; 222 | string[1] = hexDigit[r & 15]; 223 | string[2] = hexDigit[(g >> 4) & 15]; 224 | string[3] = hexDigit[g & 15]; 225 | string[4] = hexDigit[(b >> 4) & 15]; 226 | string[5] = hexDigit[b & 15]; 227 | string[6] = 0; 228 | } 229 | 230 | ColorRGB& ColorRGB::SetHexString(const char *string) 231 | { 232 | int32 rh = 15; 233 | int32 rl = 15; 234 | int32 gh = 15; 235 | int32 gl = 15; 236 | int32 bh = 15; 237 | int32 bl = 15; 238 | 239 | int32 k = string[0]; 240 | if (k != 0) 241 | { 242 | rh = k - '0'; 243 | if (rh > 9) 244 | { 245 | rh -= 7; 246 | } 247 | 248 | k = string[1]; 249 | if (k != 0) 250 | { 251 | rl = k - '0'; 252 | if (rl > 9) 253 | { 254 | rl -= 7; 255 | } 256 | 257 | k = string[2]; 258 | if (k != 0) 259 | { 260 | gh = k - '0'; 261 | if (gh > 9) 262 | { 263 | gh -= 7; 264 | } 265 | 266 | k = string[3]; 267 | if (k != 0) 268 | { 269 | gl = k - '0'; 270 | if (gl > 9) 271 | { 272 | gl -= 7; 273 | } 274 | 275 | k = string[4]; 276 | if (k != 0) 277 | { 278 | bh = k - '0'; 279 | if (bh > 9) 280 | { 281 | bh -= 7; 282 | } 283 | 284 | k = string[5]; 285 | if (k != 0) 286 | { 287 | bl = k - '0'; 288 | if (bl > 9) 289 | { 290 | bl -= 7; 291 | } 292 | } 293 | } 294 | } 295 | } 296 | } 297 | } 298 | 299 | red = (rh << 4) | rl; 300 | green = (gh << 4) | gl; 301 | blue = (bh << 4) | bl; 302 | 303 | return (*this); 304 | } 305 | 306 | 307 | void ColorRGBA::GetHexString(char *string) const 308 | { 309 | int32 r = int32(Color::Delinearize(red) * 255.0F + 0.5F); 310 | int32 g = int32(Color::Delinearize(green) * 255.0F + 0.5F); 311 | int32 b = int32(Color::Delinearize(blue) * 255.0F + 0.5F); 312 | int32 a = int32(alpha * 255.0F + 0.5F); 313 | 314 | string[0] = hexDigit[(r >> 4) & 15]; 315 | string[1] = hexDigit[r & 15]; 316 | string[2] = hexDigit[(g >> 4) & 15]; 317 | string[3] = hexDigit[g & 15]; 318 | string[4] = hexDigit[(b >> 4) & 15]; 319 | string[5] = hexDigit[b & 15]; 320 | string[6] = hexDigit[(a >> 4) & 15]; 321 | string[7] = hexDigit[a & 15]; 322 | string[8] = 0; 323 | } 324 | 325 | ColorRGBA& ColorRGBA::SetHexString(const char *string) 326 | { 327 | int32 rh = 15; 328 | int32 rl = 15; 329 | int32 gh = 15; 330 | int32 gl = 15; 331 | int32 bh = 15; 332 | int32 bl = 15; 333 | int32 ah = 15; 334 | int32 al = 15; 335 | 336 | int32 k = string[0]; 337 | if (k != 0) 338 | { 339 | rh = k - '0'; 340 | if (rh > 9) 341 | { 342 | rh -= 7; 343 | } 344 | 345 | k = string[1]; 346 | if (k != 0) 347 | { 348 | rl = k - '0'; 349 | if (rl > 9) 350 | { 351 | rl -= 7; 352 | } 353 | 354 | k = string[2]; 355 | if (k != 0) 356 | { 357 | gh = k - '0'; 358 | if (gh > 9) 359 | { 360 | gh -= 7; 361 | } 362 | 363 | k = string[3]; 364 | if (k != 0) 365 | { 366 | gl = k - '0'; 367 | if (gl > 9) 368 | { 369 | gl -= 7; 370 | } 371 | 372 | k = string[4]; 373 | if (k != 0) 374 | { 375 | bh = k - '0'; 376 | if (bh > 9) 377 | { 378 | bh -= 7; 379 | } 380 | 381 | k = string[5]; 382 | if (k != 0) 383 | { 384 | bl = k - '0'; 385 | if (bl > 9) 386 | { 387 | bl -= 7; 388 | } 389 | 390 | k = string[6]; 391 | if (k != 0) 392 | { 393 | ah = k - '0'; 394 | if (ah > 9) 395 | { 396 | ah -= 7; 397 | } 398 | 399 | k = string[7]; 400 | if (k != 0) 401 | { 402 | al = k - '0'; 403 | if (al > 9) 404 | { 405 | al -= 7; 406 | } 407 | } 408 | } 409 | } 410 | } 411 | } 412 | } 413 | } 414 | } 415 | 416 | red = (rh << 4) | rl; 417 | green = (gh << 4) | gl; 418 | blue = (bh << 4) | bl; 419 | alpha = (ah << 4) | al; 420 | 421 | return (*this); 422 | } 423 | 424 | 425 | float Color::Linearize(float color) 426 | { 427 | return ((color > 0.04045F) ? Pow((color + 0.055F) * (1.0F / 1.055F), 2.4F) : color * (1.0F / 12.92F)); 428 | } 429 | 430 | float Color::Delinearize(float color) 431 | { 432 | return ((color < 0.0031308F) ? color * 12.92F : Pow(color, 1.0F / 2.4F) * 1.055F - 0.055F); 433 | } 434 | 435 | ColorRGB Color::Linearize(const ColorRGB& color) 436 | { 437 | float r = Linearize(color.red); 438 | float g = Linearize(color.green); 439 | float b = Linearize(color.blue); 440 | return (ColorRGB(r, g, b)); 441 | } 442 | 443 | ColorRGB Color::Delinearize(const ColorRGB& color) 444 | { 445 | float r = Delinearize(color.red); 446 | float g = Delinearize(color.green); 447 | float b = Delinearize(color.blue); 448 | return (ColorRGB(r, g, b)); 449 | } 450 | 451 | ColorRGBA Color::Linearize(const ColorRGBA& color) 452 | { 453 | float r = Linearize(color.red); 454 | float g = Linearize(color.green); 455 | float b = Linearize(color.blue); 456 | return (ColorRGBA(r, g, b, color.alpha)); 457 | } 458 | 459 | ColorRGBA Color::Delinearize(const ColorRGBA& color) 460 | { 461 | float r = Delinearize(color.red); 462 | float g = Delinearize(color.green); 463 | float b = Delinearize(color.blue); 464 | return (ColorRGBA(r, g, b, color.alpha)); 465 | } 466 | --------------------------------------------------------------------------------