├── 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 |
--------------------------------------------------------------------------------