├── CFrame and Vector3
├── .vs
│ └── CFrame and Vector3
│ │ └── v14
│ │ └── .suo
├── CFrame and Vector3.sln
└── CFrame and Vector3
│ ├── App.config
│ ├── CFrame and Vector3.csproj
│ ├── CFrame.cs
│ ├── Program.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── Vector3.cs
│ ├── bin
│ └── Debug
│ │ ├── CFrame and Vector3.exe
│ │ ├── CFrame and Vector3.exe.config
│ │ ├── CFrame and Vector3.pdb
│ │ ├── CFrame and Vector3.vshost.exe
│ │ ├── CFrame and Vector3.vshost.exe.config
│ │ └── CFrame and Vector3.vshost.exe.manifest
│ └── obj
│ └── Debug
│ ├── CFrame and Vector3.csproj.FileListAbsolute.txt
│ ├── CFrame and Vector3.csprojResolveAssemblyReference.cache
│ ├── CFrame and Vector3.exe
│ ├── CFrame and Vector3.pdb
│ ├── DesignTimeResolveAssemblyReferencesInput.cache
│ ├── TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
│ ├── TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
│ └── TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
├── LICENSE
├── Lua
├── CFrame.lua
└── Vector3.lua
└── README.md
/CFrame and Vector3/.vs/CFrame and Vector3/v14/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/.vs/CFrame and Vector3/v14/.suo
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CFrame and Vector3", "CFrame and Vector3\CFrame and Vector3.csproj", "{56D79B32-653F-4212-BE44-53163742CA7A}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {56D79B32-653F-4212-BE44-53163742CA7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {56D79B32-653F-4212-BE44-53163742CA7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {56D79B32-653F-4212-BE44-53163742CA7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {56D79B32-653F-4212-BE44-53163742CA7A}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/CFrame and Vector3.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {56D79B32-653F-4212-BE44-53163742CA7A}
8 | Exe
9 | Properties
10 | CFrame_and_Vector3
11 | CFrame and Vector3
12 | v4.6.1
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
62 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/CFrame.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace CFrame_and_Vector3
8 | {
9 | class CFrame
10 | {
11 | private float m11 = 1, m12 = 0, m13 = 0, m14 = 0;
12 | private float m21 = 0, m22 = 1, m23 = 0, m24 = 0;
13 | private float m31 = 0, m32 = 0, m33 = 1, m34 = 0;
14 | private const float m41 = 0, m42 = 0, m43 = 0, m44 = 1;
15 |
16 | public readonly float x = 0, y = 0, z = 0;
17 | public readonly Vector3 p = new Vector3(0, 0, 0);
18 | public readonly Vector3 lookVector = new Vector3(0, 0, -1);
19 | public readonly Vector3 rightVector = new Vector3(1, 0, 0);
20 | public readonly Vector3 upVector = new Vector3(0, 1, 0);
21 |
22 | private static Vector3 RIGHT = new Vector3(1, 0, 0);
23 | private static Vector3 UP = new Vector3(0, 1, 0);
24 | private static Vector3 BACK = new Vector3(0, 0, 1);
25 |
26 | // constructors
27 |
28 | public CFrame(Vector3 pos)
29 | {
30 | m14 = pos.x;
31 | m24 = pos.y;
32 | m34 = pos.z;
33 | x = m14; y = m24; z = m34;
34 | p = new Vector3(m14, m24, m34);
35 | lookVector = new Vector3(-m13, -m23, -m33);
36 | rightVector = new Vector3(m11, m21, m31);
37 | upVector = new Vector3(m12, m22, m32);
38 | }
39 |
40 | public CFrame(Vector3 eye, Vector3 look)
41 | {
42 | Vector3 zAxis = (eye - look).unit;
43 | Vector3 xAxis = Vector3.Cross(UP, zAxis);
44 | Vector3 yAxis = Vector3.Cross(zAxis, xAxis);
45 | if (xAxis.magnitude == 0)
46 | {
47 | if (zAxis.y < 0)
48 | {
49 | xAxis = new Vector3(0, 0, -1);
50 | yAxis = new Vector3(1, 0, 0);
51 | zAxis = new Vector3(0, -1, 0);
52 | }
53 | else
54 | {
55 | xAxis = new Vector3(0, 0, 1);
56 | yAxis = new Vector3(1, 0, 0);
57 | zAxis = new Vector3(0, 1, 0);
58 | }
59 | }
60 | m11 = xAxis.x; m12 = yAxis.x; m13 = zAxis.x; m14 = eye.x;
61 | m21 = xAxis.y; m22 = yAxis.y; m23 = zAxis.y; m24 = eye.y;
62 | m31 = xAxis.z; m32 = yAxis.z; m33 = zAxis.z; m34 = eye.z;
63 | x = m14; y = m24; z = m34;
64 | p = new Vector3(m14, m24, m34);
65 | lookVector = new Vector3(-m13, -m23, -m33);
66 | rightVector = new Vector3(m11, m21, m31);
67 | upVector = new Vector3(m12, m22, m32);
68 | }
69 |
70 | public CFrame(float nx = 0, float ny = 0, float nz = 0)
71 | {
72 | m14 = nx;
73 | m24 = ny;
74 | m34 = nz;
75 | x = m14; y = m24; z = m34;
76 | p = new Vector3(m14, m24, m34);
77 | lookVector = new Vector3(-m13, -m23, -m33);
78 | rightVector = new Vector3(m11, m21, m31);
79 | upVector = new Vector3(m12, m22, m32);
80 | }
81 |
82 | public CFrame(float nx, float ny, float nz, float i, float j, float k, float w)
83 | {
84 | m14 = nx;
85 | m24 = ny;
86 | m34 = nz;
87 | m11 = 1 - 2 * (float)Math.Pow(j, 2) - 2 * (float)Math.Pow(k, 2);
88 | m12 = 2 * (i * j - k * w);
89 | m13 = 2 * (i * k + j * w);
90 | m21 = 2 * (i * j + k * w);
91 | m22 = 1 - 2 * (float)Math.Pow(i, 2) - 2 * (float)Math.Pow(k, 2);
92 | m23 = 2 * (j * k - i * w);
93 | m31 = 2 * (i * k - j * w);
94 | m32 = 2 * (j * k + i * w);
95 | m33 = 1 - 2 * (float)Math.Pow(i, 2) - 2 * (float)Math.Pow(j, 2);
96 | x = m14; y = m24; z = m34;
97 | p = new Vector3(m14, m24, m34);
98 | lookVector = new Vector3(-m13, -m23, -m33);
99 | rightVector = new Vector3(m11, m21, m31);
100 | upVector = new Vector3(m12, m22, m32);
101 | }
102 |
103 | public CFrame(float n14, float n24, float n34, float n11, float n12, float n13, float n21, float n22, float n23, float n31, float n32, float n33)
104 | {
105 | m14 = n14; m24 = n24; m34 = n34;
106 | m11 = n11; m12 = n12; m13 = n13;
107 | m21 = n21; m22 = n22; m23 = n23;
108 | m31 = n31; m32 = n32; m33 = n33;
109 | x = m14; y = m24; z = m34;
110 | p = new Vector3(m14, m24, m34);
111 | lookVector = new Vector3(-m13, -m23, -m33);
112 | rightVector = new Vector3(m11, m21, m31);
113 | upVector = new Vector3(m12, m22, m32);
114 | }
115 |
116 | // opperator overloads
117 |
118 | public static CFrame operator +(CFrame a, Vector3 b)
119 | {
120 | float[] ac = a.components();
121 | float x = ac[0], y = ac[1], z = ac[2], m11 = ac[3], m12 = ac[4], m13 = ac[5], m21 = ac[6], m22 = ac[7], m23 = ac[8], m31 = ac[9], m32 = ac[10], m33 = ac[11];
122 | return new CFrame(x + b.x, y + b.y, z + b.z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
123 | }
124 |
125 | public static CFrame operator -(CFrame a, Vector3 b)
126 | {
127 | float[] ac = a.components();
128 | float x = ac[0], y = ac[1], z = ac[2], m11 = ac[3], m12 = ac[4], m13 = ac[5], m21 = ac[6], m22 = ac[7], m23 = ac[8], m31 = ac[9], m32 = ac[10], m33 = ac[11];
129 | return new CFrame(x - b.x, y - b.y, z - b.z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
130 | }
131 |
132 | public static Vector3 operator *(CFrame a, Vector3 b)
133 | {
134 | float[] ac = a.components();
135 | float x = ac[0], y = ac[1], z = ac[2], m11 = ac[3], m12 = ac[4], m13 = ac[5], m21 = ac[6], m22 = ac[7], m23 = ac[8], m31 = ac[9], m32 = ac[10], m33 = ac[11];
136 | Vector3 right = new Vector3(m11, m21, m31);
137 | Vector3 up = new Vector3(m12, m22, m32);
138 | Vector3 back = new Vector3(m13, m23, m33);
139 | return a.p + b.x * right + b.y * up + b.z * back;
140 | }
141 |
142 | public static CFrame operator *(CFrame a, CFrame b)
143 | {
144 | float[] ac = a.components();
145 | float[] bc = b.components();
146 | float a14 = ac[0], a24 = ac[1], a34 = ac[2], a11 = ac[3], a12 = ac[4], a13 = ac[5], a21 = ac[6], a22 = ac[7], a23 = ac[8], a31 = ac[9], a32 = ac[10], a33 = ac[11];
147 | float b14 = bc[0], b24 = bc[1], b34 = bc[2], b11 = bc[3], b12 = bc[4], b13 = bc[5], b21 = bc[6], b22 = bc[7], b23 = bc[8], b31 = bc[9], b32 = bc[10], b33 = bc[11];
148 | float n11 = a11 * b11 + a12 * b21 + a13 * b31 + a14 * m41;
149 | float n12 = a11 * b12 + a12 * b22 + a13 * b32 + a14 * m42;
150 | float n13 = a11 * b13 + a12 * b23 + a13 * b33 + a14 * m43;
151 | float n14 = a11 * b14 + a12 * b24 + a13 * b34 + a14 * m44;
152 | float n21 = a21 * b11 + a22 * b21 + a23 * b31 + a24 * m41;
153 | float n22 = a21 * b12 + a22 * b22 + a23 * b32 + a24 * m42;
154 | float n23 = a21 * b13 + a22 * b23 + a23 * b33 + a24 * m43;
155 | float n24 = a21 * b14 + a22 * b24 + a23 * b34 + a24 * m44;
156 | float n31 = a31 * b11 + a32 * b21 + a33 * b31 + a34 * m41;
157 | float n32 = a31 * b12 + a32 * b22 + a33 * b32 + a34 * m42;
158 | float n33 = a31 * b13 + a32 * b23 + a33 * b33 + a34 * m43;
159 | float n34 = a31 * b14 + a32 * b24 + a33 * b34 + a34 * m44;
160 | float n41 = m41 * b11 + m42 * b21 + m43 * b31 + m44 * m41;
161 | float n42 = m41 * b12 + m42 * b22 + m43 * b32 + m44 * m42;
162 | float n43 = m41 * b13 + m42 * b23 + m43 * b33 + m44 * m43;
163 | float n44 = m41 * b14 + m42 * b24 + m43 * b34 + m44 * m44;
164 | return new CFrame(n14, n24, n34, n11, n12, n13, n21, n22, n23, n31, n32, n33);
165 | }
166 |
167 | public override string ToString()
168 | {
169 | return String.Join(", ", components());
170 | }
171 |
172 | // private static functions
173 |
174 | private static Vector3 vectorAxisAngle(Vector3 n, Vector3 v, float t)
175 | {
176 | n = n.unit;
177 | return v * (float)Math.Cos(t) + Vector3.Dot(v, n) * n * (1 - (float)Math.Cos(t)) + Vector3.Cross(n, v) * (float)Math.Sin(t);
178 | }
179 |
180 | private static float getDeterminant(CFrame a)
181 | {
182 | float[] ac = a.components();
183 | float a14 = ac[0], a24 = ac[1], a34 = ac[2], a11 = ac[3], a12 = ac[4], a13 = ac[5], a21 = ac[6], a22 = ac[7], a23 = ac[8], a31 = ac[9], a32 = ac[10], a33 = ac[11];
184 | float det = (a11 * a22 * a33 * m44 + a11 * a23 * a34 * m42 + a11 * a24 * a32 * m43
185 | + a12 * a21 * a34 * m43 + a12 * a23 * a31 * m44 + a12 * a24 * a33 * m41
186 | + a13 * a21 * a32 * m44 + a13 * a22 * a34 * m41 + a13 * a24 * a31 * m42
187 | + a14 * a21 * a33 * m42 + a14 * a22 * a31 * m43 + a14 * a23 * a32 * m41
188 | - a11 * a22 * a34 * m43 - a11 * a23 * a32 * m44 - a11 * a24 * a33 * m42
189 | - a12 * a21 * a33 * m44 - a12 * a23 * a34 * m41 - a12 * a24 * a31 * m43
190 | - a13 * a21 * a34 * m42 - a13 * a22 * a31 * m44 - a13 * a24 * a32 * m41
191 | - a14 * a21 * a32 * m43 - a14 * a22 * a33 * m41 - a14 * a23 * a31 * m42);
192 | return det;
193 | }
194 |
195 | private static CFrame invert4x4(CFrame a)
196 | {
197 | float[] ac = a.components();
198 | float a14 = ac[0], a24 = ac[1], a34 = ac[2], a11 = ac[3], a12 = ac[4], a13 = ac[5], a21 = ac[6], a22 = ac[7], a23 = ac[8], a31 = ac[9], a32 = ac[10], a33 = ac[11];
199 | float det = getDeterminant(a);
200 | if (det == 0) { return a; }
201 | float b11 = (a22 * a33 * m44 + a23 * a34 * m42 + a24 * a32 * m43 - a22 * a34 * m43 - a23 * a32 * m44 - a24 * a33 * m42) / det;
202 | float b12 = (a12 * a34 * m43 + a13 * a32 * m44 + a14 * a33 * m42 - a12 * a33 * m44 - a13 * a34 * m42 - a14 * a32 * m43) / det;
203 | float b13 = (a12 * a23 * m44 + a13 * a24 * m42 + a14 * a22 * m43 - a12 * a24 * m43 - a13 * a22 * m44 - a14 * a23 * m42) / det;
204 | float b14 = (a12 * a24 * a33 + a13 * a22 * a34 + a14 * a23 * a32 - a12 * a23 * a34 - a13 * a24 * a32 - a14 * a22 * a33) / det;
205 | float b21 = (a21 * a34 * m43 + a23 * a31 * m44 + a24 * a33 * m41 - a21 * a33 * m44 - a23 * a34 * m41 - a24 * a31 * m43) / det;
206 | float b22 = (a11 * a33 * m44 + a13 * a34 * m41 + a14 * a31 * m43 - a11 * a34 * m43 - a13 * a31 * m44 - a14 * a33 * m41) / det;
207 | float b23 = (a11 * a24 * m43 + a13 * a21 * m44 + a14 * a23 * m41 - a11 * a23 * m44 - a13 * a24 * m41 - a14 * a21 * m43) / det;
208 | float b24 = (a11 * a23 * a34 + a13 * a24 * a31 + a14 * a21 * a33 - a11 * a24 * a33 - a13 * a21 * a34 - a14 * a23 * a31) / det;
209 | float b31 = (a21 * a32 * m44 + a22 * a34 * m41 + a24 * a31 * m42 - a21 * a34 * m42 - a22 * a31 * m44 - a24 * a32 * m41) / det;
210 | float b32 = (a11 * a34 * m42 + a12 * a31 * m44 + a14 * a32 * m41 - a11 * a32 * m44 - a12 * a34 * m41 - a14 * a31 * m42) / det;
211 | float b33 = (a11 * a22 * m44 + a12 * a24 * m41 + a14 * a21 * m42 - a11 * a24 * m42 - a12 * a21 * m44 - a14 * a22 * m41) / det;
212 | float b34 = (a11 * a24 * a32 + a12 * a21 * a34 + a14 * a22 * a31 - a11 * a22 * a34 - a12 * a24 * a31 - a14 * a21 * a32) / det;
213 | float b41 = (a21 * a33 * m42 + a22 * a31 * m43 + a23 * a32 * m41 - a21 * a32 * m43 - a22 * a33 * m41 - a23 * a31 * m42) / det;
214 | float b42 = (a11 * a32 * m43 + a12 * a33 * m41 + a13 * a31 * m42 - a11 * a33 * m42 - a12 * a31 * m43 - a13 * a32 * m41) / det;
215 | float b43 = (a11 * a23 * m42 + a12 * a21 * m43 + a13 * a22 * m41 - a11 * a22 * m43 - a12 * a23 * m41 - a13 * a21 * m42) / det;
216 | float b44 = (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 - a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31) / det;
217 | return new CFrame(b14, b24, b34, b11, b12, b13, b21, b22, b23, b31, b32, b33);
218 | }
219 |
220 | private static float[] quaternionFromCFrame(CFrame a)
221 | {
222 | float[] ac = a.components();
223 | float mx = ac[0], my = ac[1], mz = ac[2], m11 = ac[3], m12 = ac[4], m13 = ac[5], m21 = ac[6], m22 = ac[7], m23 = ac[8], m31 = ac[9], m32 = ac[10], m33 = ac[11];
224 | float trace = m11 + m22 + m33;
225 | float w = 1, i = 0, j = 0, k = 0;
226 | if (trace > 0)
227 | {
228 | float s = (float)Math.Sqrt(1 + trace);
229 | float r = 0.5f / s;
230 | w = s * 0.5f; i = (m32 - m23) * r; j = (m13 - m31) * r; k = (m21 - m12) * r;
231 | }
232 | else
233 | {
234 | float big = Math.Max(Math.Max(m11, m22), m33);
235 | if (big == m11)
236 | {
237 | float s = (float)Math.Sqrt(1 + m11 - m22 - m33);
238 | float r = 0.5f / s;
239 | w = (m32 - m23) * r; i = 0.5f * s; j = (m21 + m12) * r; k = (m13 + m31) * r;
240 | }
241 | else if (big == m22)
242 | {
243 | float s = (float)Math.Sqrt(1 - m11 + m22 - m33);
244 | float r = 0.5f / s;
245 | w = (m13 - m31) * r; i = (m21 + m12) * r; j = 0.5f * s; k = (m32 + m23) * r;
246 | }
247 | else if (big == m33)
248 | {
249 | float s = (float)Math.Sqrt(1 - m11 - m22 + m33);
250 | float r = 0.5f / s;
251 | w = (m21 - m12) * r; i = (m13 + m31) * r; j = (m32 + m23) * r; k = 0.5f * s;
252 | }
253 | }
254 | return new float[] { w, i, j, k };
255 | }
256 |
257 | private static CFrame lerpinternal(CFrame a, CFrame b, float t)
258 | {
259 | CFrame cf = a.inverse() * b;
260 | float[] q = quaternionFromCFrame(cf);
261 | float w = q[0], i = q[1], j = q[2], k = q[3];
262 | float theta = (float)Math.Acos(w) * 2;
263 | Vector3 v = new Vector3(i, j, k);
264 | Vector3 p = a.p.Lerp(b.p, t);
265 | if (theta != 0)
266 | {
267 | CFrame r = a * fromAxisAngle(v, theta * t);
268 | return (r - r.p) + p;
269 | }
270 | else
271 | {
272 | return (a - a.p) + p;
273 | }
274 | }
275 |
276 | // public static functions
277 |
278 | public static CFrame fromAxisAngle(Vector3 axis, float theta)
279 | {
280 | Vector3 r = vectorAxisAngle(axis, RIGHT, theta);
281 | Vector3 u = vectorAxisAngle(axis, UP, theta);
282 | Vector3 b = vectorAxisAngle(axis, BACK, theta);
283 | return new CFrame(0, 0, 0, r.x, u.x, b.x, r.y, u.y, b.y, r.z, u.z, b.z);
284 | }
285 |
286 | public static CFrame Angles(float x, float y, float z)
287 | {
288 | CFrame cfx = fromAxisAngle(RIGHT, x);
289 | CFrame cfy = fromAxisAngle(UP, y);
290 | CFrame cfz = fromAxisAngle(BACK, z);
291 | return cfx * cfy * cfz;
292 | }
293 |
294 | public static CFrame fromEulerAnglesXYZ(float x, float y, float z)
295 | {
296 | return Angles(x, y, z);
297 | }
298 |
299 | // methods
300 |
301 | public CFrame inverse()
302 | {
303 | return invert4x4(this);
304 | }
305 |
306 | public CFrame lerp(CFrame cf2, float t)
307 | {
308 | return lerpinternal(this, cf2, t);
309 | }
310 |
311 | public CFrame toWorldSpace(CFrame cf2)
312 | {
313 | return this * cf2;
314 | }
315 |
316 | public CFrame toObjectSpace(CFrame cf2)
317 | {
318 | return this.inverse() * cf2;
319 | }
320 |
321 | public Vector3 pointToWorldSpace(Vector3 v)
322 | {
323 | return this * v;
324 | }
325 |
326 | public Vector3 pointToObjectSpace(Vector3 v)
327 | {
328 | return this.inverse() * v;
329 | }
330 |
331 | public Vector3 vectorToWorldSpace(Vector3 v)
332 | {
333 | return (this - this.p) * v;
334 | }
335 |
336 | public Vector3 vectorToObjectSpace(Vector3 v)
337 | {
338 | return (this - this.p).inverse() * v;
339 | }
340 |
341 | public float[] components()
342 | {
343 | return new float[] { m14, m24, m34, m11, m12, m13, m21, m22, m23, m31, m32, m33 };
344 | }
345 |
346 | public float[] toEulerAnglesXYZ()
347 | {
348 | float x = (float)Math.Atan2(-m23, m33);
349 | float y = (float)Math.Asin(m13);
350 | float z = (float)Math.Atan2(-m12, m11);
351 | return new float[] { x, y, z };
352 | }
353 | }
354 | }
355 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace CFrame_and_Vector3
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | CFrame dcf = new CFrame();
14 | CFrame cf1 = new CFrame(1, 2, 3) * CFrame.Angles((float)Math.PI / 3, (float)Math.PI / 6, 0);
15 | CFrame cf2 = new CFrame(-4, 5, 7.2f) * CFrame.Angles(0, (float)Math.PI / 7, -(float)Math.PI / 3);
16 | CFrame cf = cf1 * cf2;
17 |
18 | Vector3 v = new Vector3(10, -5, 6);
19 | Vector3 v2 = new Vector3(12.6602535f, -0.669872522f, -1.2320509f);
20 |
21 | Console.WriteLine(cf * cf2.inverse());
22 | Console.WriteLine(cf1.pointToObjectSpace(v2));
23 | Console.ReadLine();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("CFrame and Vector3")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("CFrame and Vector3")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("56d79b32-653f-4212-be44-53163742ca7a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/Vector3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace CFrame_and_Vector3
8 | {
9 | class Vector3
10 | {
11 | public readonly float x, y, z;
12 | public readonly float magnitude;
13 | public Vector3 unit { get { return normalize(this); } }
14 |
15 | public Vector3(float x = 0, float y = 0, float z = 0)
16 | {
17 | this.x = x;
18 | this.y = y;
19 | this.z = z;
20 | magnitude = calcMagnitude(this);
21 | }
22 |
23 | // opperator overloads
24 |
25 | public static Vector3 operator -(Vector3 v)
26 | {
27 | return new Vector3(-v.x, -v.y, -v.z);
28 | }
29 |
30 | public static Vector3 operator *(float k, Vector3 a)
31 | {
32 | return new Vector3(a.x * k, a.y * k, a.z * k);
33 | }
34 |
35 | public static Vector3 operator *(Vector3 a, float k)
36 | {
37 | return new Vector3(a.x * k, a.y * k, a.z * k);
38 | }
39 |
40 | public static Vector3 operator +(Vector3 a, Vector3 b)
41 | {
42 | return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
43 | }
44 |
45 | public static Vector3 operator -(Vector3 a, Vector3 b)
46 | {
47 | return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
48 | }
49 |
50 | public static Vector3 operator *(Vector3 a, Vector3 b)
51 | {
52 | return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
53 | }
54 |
55 | public static Vector3 operator /(Vector3 a, Vector3 b)
56 | {
57 | return new Vector3(a.x / b.x, a.y / b.y, a.z / b.z);
58 | }
59 |
60 | public override string ToString()
61 | {
62 | return x + ", " + y + ", " + z;
63 | }
64 |
65 | // statics
66 |
67 | private static float calcMagnitude(Vector3 v)
68 | {
69 | return (float)Math.Sqrt(Dot(v, v));
70 | }
71 |
72 | private static Vector3 normalize(Vector3 v)
73 | {
74 | float m = calcMagnitude(v);
75 | float nx = v.x / m, ny = v.y / m, nz = v.z / m;
76 | return new Vector3(nx, ny, nz);
77 | }
78 |
79 | public static float Dot(Vector3 a, Vector3 b)
80 | {
81 | return a.x*b.x + a.y*b.y + a.z*b.z;
82 | }
83 |
84 | public static Vector3 Cross(Vector3 a, Vector3 b)
85 | {
86 | return new Vector3(
87 | a.y * b.z - b.y * a.z,
88 | a.z * b.x - b.z * a.x,
89 | a.x * b.y - b.x * a.y
90 | );
91 | }
92 |
93 | // methods
94 |
95 | public Vector3 Lerp(Vector3 b, float t)
96 | {
97 | return (1 - t) * this + t * b;
98 | }
99 |
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.exe
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.pdb
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.vshost.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.vshost.exe
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.vshost.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/bin/Debug/CFrame and Vector3.vshost.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/CFrame and Vector3.csproj.FileListAbsolute.txt:
--------------------------------------------------------------------------------
1 | C:\Users\Michael\Documents\Visual Studio 2015\Projects\C# Projects\ConsoleApplications\CFrame and Vector3\CFrame and Vector3\bin\Debug\CFrame and Vector3.exe.config
2 | C:\Users\Michael\Documents\Visual Studio 2015\Projects\C# Projects\ConsoleApplications\CFrame and Vector3\CFrame and Vector3\bin\Debug\CFrame and Vector3.exe
3 | C:\Users\Michael\Documents\Visual Studio 2015\Projects\C# Projects\ConsoleApplications\CFrame and Vector3\CFrame and Vector3\bin\Debug\CFrame and Vector3.pdb
4 | C:\Users\Michael\Documents\Visual Studio 2015\Projects\C# Projects\ConsoleApplications\CFrame and Vector3\CFrame and Vector3\obj\Debug\CFrame and Vector3.csprojResolveAssemblyReference.cache
5 | C:\Users\Michael\Documents\Visual Studio 2015\Projects\C# Projects\ConsoleApplications\CFrame and Vector3\CFrame and Vector3\obj\Debug\CFrame and Vector3.exe
6 | C:\Users\Michael\Documents\Visual Studio 2015\Projects\C# Projects\ConsoleApplications\CFrame and Vector3\CFrame and Vector3\obj\Debug\CFrame and Vector3.pdb
7 |
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/CFrame and Vector3.csprojResolveAssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/obj/Debug/CFrame and Vector3.csprojResolveAssemblyReference.cache
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/CFrame and Vector3.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/obj/Debug/CFrame and Vector3.exe
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/CFrame and Vector3.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/obj/Debug/CFrame and Vector3.pdb
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
--------------------------------------------------------------------------------
/CFrame and Vector3/CFrame and Vector3/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EgoMooseOldProjects/Vector3-and-CFrame/2a0716f773362afb5e16205e3f2d518b30af5099/CFrame and Vector3/CFrame and Vector3/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/Lua/CFrame.lua:
--------------------------------------------------------------------------------
1 | -- dependancies
2 |
3 | local Vector3 = require("vector3");
4 |
5 | -- CFrame class
6 |
7 | local cframe = {__type = "cframe"};
8 | local mt = {__index = cframe};
9 |
10 | local prettyPrint = false; -- mainly for debug (not a feature in real CFrames)
11 |
12 | -- built-in functions
13 |
14 | local pi = math.pi;
15 | local max = math.max;
16 | local cos = math.cos;
17 | local sin = math.sin;
18 | local acos = math.acos;
19 | local asin = math.asin;
20 | local sqrt = math.sqrt;
21 | local atan2 = math.atan2;
22 | local unpack = unpack;
23 | local concat = table.concat;
24 |
25 | -- some variables
26 |
27 | local identityMatrix = {
28 | m11 = 1, m12 = 0, m13 = 0,
29 | m21 = 0, m22 = 1, m23 = 0,
30 | m31 = 0, m32 = 0, m33 = 1
31 | };
32 | local m41, m42, m43, m44 = 0, 0, 0, 1;
33 | local identityCFrame = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
34 |
35 | local right = Vector3.new(1, 0, 0);
36 | local top = Vector3.new(0, 1, 0);
37 | local back = Vector3.new(0, 0, 1);
38 |
39 | -- private functions
40 |
41 | local function fromAxisAngle(axis, vector, theta)
42 | -- http://wiki.roblox.com/index.php?title=User:EgoMoose/Articles/Quaternions_and_slerping#Rodriguez_Rotation_formula:_Axis-angle_rotations
43 | local axis = axis.unit;
44 | return vector * cos(theta) + vector:Dot(axis) * axis * (1 - cos(theta)) + axis:Cross(vector) * sin(theta);
45 | end;
46 |
47 | local function cfTimesv3(cf, v3)
48 | local _, _, _, m11, m12, m13, m21, m22, m23, m31, m32, m33 = cf:components();
49 | local right = Vector3.new(m11, m21, m31);
50 | local top = Vector3.new(m12, m22, m32);
51 | local back = Vector3.new(m13, m23, m33);
52 | return cf.p + v3.x * right + v3.y * top + v3.z * back;
53 | end;
54 |
55 | local function fourByfour(a, b)
56 | local a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44 = unpack(a);
57 | local b11, b12, b13, b14, b21, b22, b23, b24, b31, b32, b33, b34, b41, b42, b43, b44 = unpack(b);
58 | -- 4x4 matrix multiplication
59 | local m11 = a11*b11 + a12*b21 + a13*b31 + a14*b41;
60 | local m12 = a11*b12 + a12*b22 + a13*b32 + a14*b42;
61 | local m13 = a11*b13 + a12*b23 + a13*b33 + a14*b43;
62 | local m14 = a11*b14 + a12*b24 + a13*b34 + a14*b44;
63 | local m21 = a21*b11 + a22*b21 + a23*b31 + a24*b41;
64 | local m22 = a21*b12 + a22*b22 + a23*b32 + a24*b42;
65 | local m23 = a21*b13 + a22*b23 + a23*b33 + a24*b43;
66 | local m24 = a21*b14 + a22*b24 + a23*b34 + a24*b44;
67 | local m31 = a31*b11 + a32*b21 + a33*b31 + a34*b41;
68 | local m32 = a31*b12 + a32*b22 + a33*b32 + a34*b42;
69 | local m33 = a31*b13 + a32*b23 + a33*b33 + a34*b43;
70 | local m34 = a31*b14 + a32*b24 + a33*b34 + a34*b44;
71 | local m41 = a41*b11 + a42*b21 + a43*b31 + a44*b41;
72 | local m42 = a41*b12 + a42*b22 + a43*b32 + a44*b42;
73 | local m43 = a41*b13 + a42*b23 + a43*b33 + a44*b43;
74 | local m44 = a41*b14 + a42*b24 + a43*b34 + a44*b44;
75 | -- return the components
76 | return m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44;
77 | end;
78 |
79 | local function cfTimescf(cf1, cf2)
80 | local a14, a24, a34, a11, a12, a13, a21, a22, a23, a31, a32, a33 = cf1:components();
81 | local b14, b24, b34, b11, b12, b13, b21, b22, b23, b31, b32, b33 = cf2:components();
82 | local m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 = fourByfour({
83 | a11, a12, a13, a14,
84 | a21, a22, a23, a24,
85 | a31, a32, a33, a34,
86 | m41, m42, m43, m44
87 | }, {
88 | b11, b12, b13, b14,
89 | b21, b22, b23, b24,
90 | b31, b32, b33, b34,
91 | m41, m42, m43, m44
92 | });
93 | -- return the final CFrame
94 | return cframe.new(m14, m24, m34, m11, m12, m13, m21, m22, m23, m31, m32, m33);
95 | end;
96 |
97 | local function getDeterminant(cf)
98 | local a14, a24, a34, a11, a12, a13, a21, a22, a23, a31, a32, a33 = cf:components();
99 | local m41, m42, m43, m44 = 0, 0, 0, 1;
100 | local det = a11*a22*a33*m44 + a11*a23*a34*m42 + a11*a24*a32*m43
101 | + a12*a21*a34*m43 + a12*a23*a31*m44 + a12*a24*a33*m41
102 | + a13*a21*a32*m44 + a13*a22*a34*m41 + a13*a24*a31*m42
103 | + a14*a21*a33*m42 + a14*a22*a31*m43 + a14*a23*a32*m41
104 | - a11*a22*a34*m43 - a11*a23*a32*m44 - a11*a24*a33*m42
105 | - a12*a21*a33*m44 - a12*a23*a34*m41 - a12*a24*a31*m43
106 | - a13*a21*a34*m42 - a13*a22*a31*m44 - a13*a24*a32*m41
107 | - a14*a21*a32*m43 - a14*a22*a33*m41 - a14*a23*a31*m42;
108 | return det;
109 | end;
110 |
111 | local function invert4x4(cf)
112 | -- this is linear algebra. We're inverting a 4x4 matrix
113 | -- see: http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/teche23.html
114 | -- it is very possible that the built-in CFrame class does not use this method as computers tend to use elimination methods
115 | -- regardless, both functions should return the same answer
116 | local a14, a24, a34, a11, a12, a13, a21, a22, a23, a31, a32, a33 = cf:components();
117 | local det = getDeterminant(cf);
118 | if (det == 0) then return cf; end;
119 | local b11 = (a22*a33*m44 + a23*a34*m42 + a24*a32*m43 - a22*a34*m43 - a23*a32*m44 - a24*a33*m42) / det;
120 | local b12 = (a12*a34*m43 + a13*a32*m44 + a14*a33*m42 - a12*a33*m44 - a13*a34*m42 - a14*a32*m43) / det;
121 | local b13 = (a12*a23*m44 + a13*a24*m42 + a14*a22*m43 - a12*a24*m43 - a13*a22*m44 - a14*a23*m42) / det;
122 | local b14 = (a12*a24*a33 + a13*a22*a34 + a14*a23*a32 - a12*a23*a34 - a13*a24*a32 - a14*a22*a33) / det;
123 | local b21 = (a21*a34*m43 + a23*a31*m44 + a24*a33*m41 - a21*a33*m44 - a23*a34*m41 - a24*a31*m43) / det;
124 | local b22 = (a11*a33*m44 + a13*a34*m41 + a14*a31*m43 - a11*a34*m43 - a13*a31*m44 - a14*a33*m41) / det;
125 | local b23 = (a11*a24*m43 + a13*a21*m44 + a14*a23*m41 - a11*a23*m44 - a13*a24*m41 - a14*a21*m43) / det;
126 | local b24 = (a11*a23*a34 + a13*a24*a31 + a14*a21*a33 - a11*a24*a33 - a13*a21*a34 - a14*a23*a31) / det;
127 | local b31 = (a21*a32*m44 + a22*a34*m41 + a24*a31*m42 - a21*a34*m42 - a22*a31*m44 - a24*a32*m41) / det;
128 | local b32 = (a11*a34*m42 + a12*a31*m44 + a14*a32*m41 - a11*a32*m44 - a12*a34*m41 - a14*a31*m42) / det;
129 | local b33 = (a11*a22*m44 + a12*a24*m41 + a14*a21*m42 - a11*a24*m42 - a12*a21*m44 - a14*a22*m41) / det;
130 | local b34 = (a11*a24*a32 + a12*a21*a34 + a14*a22*a31 - a11*a22*a34 - a12*a24*a31 - a14*a21*a32) / det;
131 | local b41 = (a21*a33*m42 + a22*a31*m43 + a23*a32*m41 - a21*a32*m43 - a22*a33*m41 - a23*a31*m42) / det;
132 | local b42 = (a11*a32*m43 + a12*a33*m41 + a13*a31*m42 - a11*a33*m42 - a12*a31*m43 - a13*a32*m41) / det;
133 | local b43 = (a11*a23*m42 + a12*a21*m43 + a13*a22*m41 - a11*a22*m43 - a12*a23*m41 - a13*a21*m42) / det;
134 | local b44 = (a11*a22*a33 + a12*a23*a31 + a13*a21*a32 - a11*a23*a32 - a12*a21*a33 - a13*a22*a31) / det;
135 | return cframe.new(b14, b24, b34, b11, b12, b13, b21, b22, b23, b31, b32, b33);
136 | end;
137 |
138 | local function quaternionToMatrix(i, j, k, w)
139 | local m11 = 1 - 2*j^2 - 2*k^2;
140 | local m12 = 2*(i*j - k*w);
141 | local m13 = 2*(i*k + j*w);
142 | local m21 = 2*(i*j + k*w);
143 | local m22 = 1 - 2*i^2 - 2*k^2;
144 | local m23 = 2*(j*k - i*w);
145 | local m31 = 2*(i*k - j*w);
146 | local m32 = 2*(j*k + i*w);
147 | local m33 = 1 - 2*i^2 - 2*j^2;
148 | return {0, 0, 0, m11, m12, m13, m21, m22, m23, m31, m32, m33};
149 | end;
150 |
151 | local function quaternionFromCFrame(cf)
152 | -- taken from: http://wiki.roblox.com/index.php?title=Quaternions_for_rotation#Quaternion_from_a_Rotation_Matrix
153 | local mx, my, mz, m11, m12, m13, m21, m22, m23, m31, m32, m33 = cf:components();
154 | local trace = m11 + m22 + m33;
155 | if (trace > 0) then
156 | local s = sqrt(1 + trace);
157 | local r = 0.5 / s;
158 | return s * 0.5, Vector3.new((m32 - m23) * r, (m13 - m31) * r, (m21 - m12) * r);
159 | else -- find the largest diagonal element
160 | local big = max(m11, m22, m33);
161 | if big == m11 then
162 | local s = sqrt(1 + m11 - m22 - m33);
163 | local r = 0.5 / s;
164 | return (m32 - m23) * r, Vector3.new(0.5 * s, (m21 + m12) * r, (m13 + m31) * r);
165 | elseif big == m22 then
166 | local s = sqrt(1 - m11 + m22 - m33);
167 | local r = 0.5 / s;
168 | return (m13 - m31) * r, Vector3.new((m21 + m12) * r, 0.5 * s, (m32 + m23) * r);
169 | elseif big == m33 then
170 | local s = sqrt(1 - m11 - m22 + m33);
171 | local r = 0.5 / s;
172 | return (m21 - m12) * r, Vector3.new((m13 + m31) * r, (m32 + m23) * r, 0.5 * s);
173 | end;
174 | end;
175 | end;
176 |
177 | local function lerp(a, b, t)
178 | -- I have no idea what the internal implemenation is
179 | -- get the difference in CFrames, convert to quaternion, convert to axis angle, slerp
180 | local cf = a:inverse() * b;
181 | local w, v = quaternionFromCFrame(cf);
182 | local theta = acos(w) * 2;
183 | local p = a.p:Lerp(b.p, t);
184 | if theta ~= 0 then
185 | local rot = a * cframe.fromAxisAngle(v, theta * t);
186 | local _, _, _, m11, m12, m13, m21, m22, m23, m31, m32, m33 = rot:components();
187 | return cframe.new(p.x, p.y, p.z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
188 | else
189 | local _, _, _, m11, m12, m13, m21, m22, m23, m31, m32, m33 = a:components();
190 | return cframe.new(p.x, p.y, p.z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
191 | end;
192 | end;
193 |
194 | -- meta-methods
195 |
196 | function mt.__index(cf, index)
197 | if (index == "x" or index == "y" or index == "z") then
198 | return rawget(cf, "proxy").p[index];
199 | elseif (index == "p" or index == "lookVector") then
200 | return rawget(cf, "proxy")[index];
201 | elseif cframe[index] then
202 | return cframe[index];
203 | else
204 | error(index .. " is not a valid member of CFrame");
205 | end;
206 | end;
207 |
208 | function mt.__newindex(v, index, value)
209 | error(index .. " cannot be assigned to");
210 | end;
211 |
212 | function mt.__add(a, b)
213 | local aIsCFrame = type(a) == "table" and a.__type and a.__type == "cframe";
214 | local bIsCFrame = type(b) == "table" and b.__type and b.__type == "cframe";
215 | local bIsVector = type(b) == "table" and b.__type and b.__type == "vector3";
216 | if (aIsCFrame and bIsVector) then
217 | local x, y, z, m11, m12, m13, m21, m22, m23, m31, m32, m33 = a:components();
218 | return cframe.new(x + b.x, y + b.y, z + b.z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
219 | elseif (bIsCFrame) then
220 | local t = type(a);
221 | local cust = t == "table" and a.__type or t;
222 | -- fun fact, you can't add two CFrames so I assume the error code is wrong on this internally ;)
223 | error("bad argument #2 to '?' (CFrame expected, got " .. cust .. ")");
224 | elseif (aIsCFrame) then
225 | local t = type(b);
226 | local cust = t == "table" and b.__type or t;
227 | error("bad argument #2 to '?' (Vector3 expected, got " .. cust .. ")");
228 | end;
229 | end;
230 |
231 | function mt.__sub(a, b)
232 | local aIsCFrame = type(a) == "table" and a.__type and a.__type == "cframe";
233 | local bIsCFrame = type(b) == "table" and b.__type and b.__type == "cframe";
234 | local bIsVector = type(b) == "table" and b.__type and b.__type == "vector3";
235 | if (aIsCFrame and bIsVector) then
236 | local x, y, z, m11, m12, m13, m21, m22, m23, m31, m32, m33 = a:components();
237 | return cframe.new(x - b.x, y - b.y, z - b.z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
238 | elseif (bIsCFrame) then
239 | local t = type(a);
240 | local cust = t == "table" and a.__type or t;
241 | -- fun fact, you can't add two CFrames so I assume the error code is wrong on this internally ;)
242 | error("bad argument #2 to '?' (CFrame expected, got " .. cust .. ")");
243 | elseif (aIsCFrame) then
244 | local t = type(b);
245 | local cust = t == "table" and b.__type or t;
246 | error("bad argument #2 to '?' (Vector3 expected, got " .. cust .. ")");
247 | end;
248 | end;
249 |
250 | function mt.__mul(a, b)
251 | local aIsCFrame = type(a) == "table" and a.__type and a.__type == "cframe";
252 | local bIsCFrame = type(b) == "table" and b.__type and b.__type == "cframe";
253 | local aIsVector = type(a) == "table" and a.__type and a.__type == "vector3";
254 | local bIsVector = type(b) == "table" and b.__type and b.__type == "vector3";
255 | if (aIsCFrame and bIsVector) then
256 | return cfTimesv3(a, b);
257 | elseif (aIsCFrame and bIsCFrame) then
258 | return cfTimescf(a, b);
259 | elseif (aIsCFrame) then
260 | local t = type(a);
261 | local cust = t == "table" and a.__type or t;
262 | error("bad argument #2 to '?' (Vector3 expected, got " .. cust .. " )");
263 | elseif (bIsCFrame) then
264 | local t = type(a);
265 | local cust = t == "table" and a.__type or t;
266 | error("bad argument #1 to '?' (CFrame expected, got " .. cust .. " )");
267 | end;
268 | end;
269 |
270 | function mt.__tostring(t)
271 | local components = {t:components()};
272 | if prettyPrint then
273 | local s = "";
274 | for i = 1, 12 do
275 | s = s .. ((i > 1 and i % 3 == 1 and "\n") or "") .. components[i] .. (i < 12 and ", " or "");
276 | end;
277 | return s;
278 | else
279 | return concat(components, ", ");
280 | end;
281 | end;
282 |
283 | mt.__metatable = false;
284 |
285 | -- public class
286 |
287 | function cframe.new(...)
288 | local self = {};
289 | self.proxy = {};
290 |
291 | self.proxy.p = Vector3.new(0, 0, 0);
292 | for k, v in next, identityMatrix do
293 | self.proxy[k] = v;
294 | end;
295 |
296 | -- most of this function is error handling from bad userinput
297 |
298 | local t = {...};
299 | local length = #t;
300 | if length > 12 then
301 | error("Invalid number of arguments: " .. length);
302 | elseif (length == 1) then -- single vector3 case
303 | local v = t[1];
304 | local isVector = type(v) == "table" and v.__type and v.__type == "vector3";
305 | if (not isVector) then
306 | local t = type(v);
307 | local cust = t == "table" and v.__type or t;
308 | error("bad argument #1 to 'new' (Vector3 expected, got" .. cust .. ")");
309 | end;
310 |
311 | -- make a copy to avoid user changing the original vector
312 | self.proxy.p = Vector3.new(v.x, v.y, v.z);
313 | elseif (length == 2) then -- two vector3 case, we much build a lookAt matrix
314 | local eye, look = t[1], t[2];
315 | local eyeIsVector = type(eye) == "table" and eye.__type and eye.__type == "vector3";
316 | local lookIsVector = type(look) == "table" and look.__type and look.__type == "vector3";
317 | if (not eyeIsVector and not lookIsVector) then
318 | local t = type(eye);
319 | local cust = t == "table" and eye.__type or t;
320 | error("bad argument #1 to 'new' (Vector3 expected, got" .. cust .. ")");
321 | end;
322 |
323 | local zaxis = (eye - look).unit;
324 | local xaxis = top:Cross(zaxis).unit;
325 | local yaxis = zaxis:Cross(xaxis).unit;
326 | if (xaxis.magnitude == 0) then -- edge cases
327 | if zaxis.y < 0 then
328 | xaxis = Vector3.new(0, 0, -1);
329 | yaxis = Vector3.new(1, 0, 0);
330 | zaxis = Vector3.new(0, -1, 0);
331 | else
332 | xaxis = Vector3.new(0, 0, 1);
333 | yaxis = Vector3.new(1, 0, 0);
334 | zaxis = Vector3.new(0, 1, 0);
335 | end;
336 | end;
337 | self.proxy.p = Vector3.new(eye.x, eye.y, eye.z);
338 | self.proxy.m11, self.proxy.m12, self.proxy.m13 = xaxis.x, yaxis.x, zaxis.x;
339 | self.proxy.m21, self.proxy.m22, self.proxy.m23 = xaxis.y, yaxis.y, zaxis.y;
340 | self.proxy.m31, self.proxy.m32, self.proxy.m33 = xaxis.z, yaxis.z, zaxis.z;
341 | elseif (length == 3) then -- x, y, z
342 | for i = 1, length do
343 | local t = type(t[i]);
344 | local cust = t == "table" and n.__type or t;
345 | if cust ~= "number" then error("bad argument #" .. i .. " to 'new' (Number expected, got " .. cust .. ")"); end;
346 | end;
347 |
348 | self.proxy.p = Vector3.new(t[1], t[2], t[3]);
349 | elseif (length == 7) then -- x, y, z, quaternion
350 | for i = 1, length do
351 | local t = type(t[i]);
352 | local cust = t == "table" and n.__type or t;
353 | if cust ~= "number" then error("bad argument #" .. i .. " to 'new' (Number expected, got " .. cust .. ")"); end;
354 | end;
355 |
356 | local m = quaternionToMatrix(t[4], t[5], t[6], t[7]);
357 | self.proxy.p = Vector3.new(t[1], t[2], t[3]);
358 | self.proxy.m11, self.proxy.m12, self.proxy.m13 = m[4], m[5], m[6];
359 | self.proxy.m21, self.proxy.m22, self.proxy.m23 = m[7], m[8], m[9];
360 | self.proxy.m31, self.proxy.m32, self.proxy.m33 = m[10], m[11], m[12];
361 | elseif (length == 12) then -- all components provided
362 | for i = 1, length do
363 | local t = type(t[i]);
364 | local cust = t == "table" and n.__type or t;
365 | if cust ~= "number" then error("bad argument #" .. i .. " to 'new' (Number expected, got " .. cust .. ")"); end;
366 | end;
367 |
368 | self.proxy.p = Vector3.new(t[1], t[2], t[3]);
369 | self.proxy.m11, self.proxy.m12, self.proxy.m13 = t[4], t[5], t[6];
370 | self.proxy.m21, self.proxy.m22, self.proxy.m23 = t[7], t[8], t[9];
371 | self.proxy.m31, self.proxy.m32, self.proxy.m33 = t[10], t[11], t[12];
372 | elseif length > 0 then -- more than zero components
373 | for i = 1, length do
374 | local t = type(t[i]);
375 | local cust = t == "table" and n.__type or t;
376 | if cust ~= "number" then error("bad argument #" .. i .. " to 'new' (Number expected, got " .. cust .. ")"); end;
377 | end;
378 | error("bad argument #" .. (length + 1) .. " to 'new' (Number expected, got nil)");
379 | end;
380 |
381 | self.proxy.lookVector = Vector3.new(-self.proxy.m13, -self.proxy.m23, -self.proxy.m33);
382 |
383 | return setmetatable(self, mt);
384 | end;
385 |
386 | function cframe.fromAxisAngle(axis, theta)
387 | local axis = axis.unit;
388 | local r = fromAxisAngle(axis, right, theta);
389 | local t = fromAxisAngle(axis, top, theta);
390 | local b = fromAxisAngle(axis, back, theta);
391 | return cframe.new(
392 | 0, 0, 0,
393 | r.x, t.x, b.x,
394 | r.y, t.y, b.y,
395 | r.z, t.z, b.z
396 | );
397 | end;
398 |
399 | function cframe.Angles(x, y, z)
400 | -- two implemenations possible. The commented one is what is what is used in the real CFrame constructor (to my knowledge)
401 | -- the uncommented implemenation is easier for me to keep track of and I think makes more sense, but you can use either
402 |
403 | -- the method (presumably) used in the real constructor
404 | -- How to find this matrix: http://i.imgur.com/IWDMw0m.png
405 | -- https://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions
406 | --[[
407 | local m11 = cos(y) * cos(z);
408 | local m12 = -cos(y) * sin(z);
409 | local m13 = sin(y);
410 | local m21 = cos(z) * sin(x) * sin(y) + cos(x) * sin(z);
411 | local m22 = cos(x) * cos(z) - sin(x) * sin(y) * sin(z);
412 | local m23 = -cos(y) * sin(x);
413 | local m31 = sin(x) * sin(z) - cos(x) * cos(z) * sin(y);
414 | local m32 = cos(z) * sin(x) + cos(x) * sin(y) * sin(z);
415 | local m33 = cos(x) * cos(y);
416 |
417 | return cframe.new(0, 0, 0, m11, m12, m13, m21, m22, m23, m31, m32, m33);
418 | --]]
419 |
420 | -- the method I prefer
421 | local cfx = cframe.fromAxisAngle(right, x);
422 | local cfy = cframe.fromAxisAngle(top, y);
423 | local cfz = cframe.fromAxisAngle(back, z);
424 |
425 | return cfx * cfy * cfz;
426 | end;
427 |
428 | function cframe.fromEulerAnglesXYZ(x, y, z)
429 | return cframe.Angles(x, y, z);
430 | end;
431 |
432 | function cframe:inverse()
433 | return invert4x4(self);
434 | end;
435 |
436 | function cframe:lerp(self2, t)
437 | return lerp(self, self2, t);
438 | end;
439 |
440 | function cframe:toWorldSpace(self2)
441 | return self * self2;
442 | end;
443 |
444 | function cframe:toWorldSpace(self2)
445 | return self * self2;
446 | end;
447 |
448 | function cframe:toObjectSpace(self2)
449 | return self:inverse() * self2;
450 | end;
451 |
452 | function cframe:pointToWorldSpace(v3)
453 | return self * v3;
454 | end;
455 |
456 | function cframe:pointToObjectSpace(v3)
457 | return self:inverse() * v3;
458 | end;
459 |
460 | function cframe:vectorToWorldSpace(v3)
461 | return (self - self.p) * v3;
462 | end;
463 |
464 | function cframe:vectorToObjectSpace(v3)
465 | return (self - self.p):inverse() * v3;
466 | end;
467 |
468 | function cframe:components()
469 | local m = rawget(self, "proxy");
470 | return m.p.x, m.p.y, m.p.z, m.m11, m.m12, m.m13, m.m21, m.m22, m.m23, m.m31, m.m32, m.m33;
471 | end;
472 |
473 | function cframe:toEulerAnglesXYZ()
474 | -- based off the method (presumably) used in the real constructor for cframe.Angles
475 | local _, _, _, m11, m12, m13, m21, m22, m23, m31, m32, m33 = self:components();
476 | local x = atan2(-m23, m33);
477 | local y = asin(m13);
478 | local z = atan2(-m12, m11);
479 | return x, y, z;
480 | end;
481 |
482 | return cframe;
--------------------------------------------------------------------------------
/Lua/Vector3.lua:
--------------------------------------------------------------------------------
1 | -- Vector3 class
2 |
3 | local vector3 = {__type = "vector3"};
4 | local mt = {__index = vector3};
5 |
6 | -- built-in functions
7 |
8 | local sqrt = math.sqrt;
9 | local acos = math.acos;
10 | local cos = math.cos;
11 | local sin = math.sin;
12 |
13 | -- private functions
14 |
15 | local function calcMagnitude(v)
16 | return sqrt(v.x^2 + v.y^2 + v.z^2);
17 | end;
18 |
19 | local function normalize(v)
20 | local magnitude = sqrt(v.x^2 + v.y^2 + v.z^2);
21 | if magnitude > 0 then
22 | return vector3.new(v.x / magnitude, v.y / magnitude, v.z / magnitude);
23 | else
24 | -- avoid 'nan' case
25 | return vector3.new(0, 0, 0);
26 | end;
27 | end;
28 |
29 | -- meta-methods
30 |
31 | function mt.__index(v, index)
32 | if (index == "unit") then
33 | return normalize(v);
34 | elseif (index == "magnitude") then
35 | return calcMagnitude(v);
36 | elseif vector3[index] then
37 | return vector3[index];
38 | elseif rawget(v, "proxy")[index] then
39 | return rawget(v, "proxy")[index];
40 | else
41 | error(index .. " is not a valid member of Vector3");
42 | end;
43 | end;
44 |
45 | function mt.__newindex(v, index, value)
46 | error(index .. " cannot be assigned to");
47 | end;
48 |
49 | function mt.__add(a, b)
50 | local aIsVector = type(a) == "table" and a.__type and a.__type == "vector3";
51 | local bIsVector = type(b) == "table" and b.__type and b.__type == "vector3";
52 | if (aIsVector and bIsVector) then
53 | return vector3.new(a.x + b.x, a.y + b.y, a.z + b.z);
54 | elseif (bIsVector) then
55 | -- check for custom type
56 | local t = type(a);
57 | local cust = t == "table" and a.__type or t;
58 | error("bad argument #1 to '?' (Vector3 expected, got " .. cust .. ")");
59 | elseif (aIsVector) then
60 | local t = type(b);
61 | local cust = t == "table" and b.__type or t;
62 | error("bad argument #2 to '?' (Vector3 expected, got " .. cust .. ")");
63 | end;
64 | end;
65 |
66 | function mt.__sub(a, b)
67 | local aIsVector = type(a) == "table" and a.__type and a.__type == "vector3";
68 | local bIsVector = type(b) == "table" and b.__type and b.__type == "vector3";
69 | if (aIsVector and bIsVector) then
70 | return vector3.new(a.x - b.x, a.y - b.y, a.z - b.z);
71 | elseif (bIsVector) then
72 | -- check for custom type
73 | local t = type(a);
74 | local cust = t == "table" and a.__type or t;
75 | error("bad argument #1 to '?' (Vector3 expected, got " .. cust .. ")");
76 | elseif (aIsVector) then
77 | local t = type(b);
78 | local cust = t == "table" and b.__type or t;
79 | error("bad argument #2 to '?' (Vector3 expected, got " .. cust .. ")");
80 | end;
81 | end;
82 |
83 | function mt.__mul(a, b)
84 | if (type(a) == "number") then
85 | return vector3.new(a * b.x, a * b.y, a * b.z);
86 | elseif (type(b) == "number") then
87 | return vector3.new(a.x * b, a.y * b, a.z * b);
88 | elseif (a.__type and a.__type == "vector3" and b.__type and b.__type == "vector3") then
89 | return vector3.new(a.x * b.x, a.y * b.y, a.z * b.z);
90 | else
91 | error("attempt to multiply a Vector3 with an incompatible value type or nil");
92 | end;
93 | end;
94 |
95 | function mt.__div(a, b)
96 | if (type(a) == "number") then
97 | return vector3.new(a / b.x, a / b.y, a / b.z);
98 | elseif (type(b) == "number") then
99 | return vector3.new(a.x / b, a.y / b, a.z / b);
100 | elseif (a.__type and a.__type == "vector3" and b.__type and b.__type == "vector3") then
101 | return vector3.new(a.x / b.x, a.y / b.y, a.z / b.z);
102 | else
103 | error("attempt to divide a Vector3 with an incompatible value type or nil");
104 | end;
105 | end;
106 |
107 | function mt.__unm(v)
108 | return vector3.new(-v.x, -v.y, -v.z);
109 | end;
110 |
111 | function mt.__tostring(v)
112 | return v.x .. ", " .. v.y .. ", " .. v.z;
113 | end;
114 |
115 | mt.__metatable = false;
116 |
117 | -- public class
118 |
119 | function vector3.new(x, y, z)
120 | local self = {};
121 | self.proxy = {};
122 | self.proxy.x = x or 0;
123 | self.proxy.y = y or 0;
124 | self.proxy.z = z or 0;
125 | return setmetatable(self, mt);
126 | end;
127 |
128 | function vector3.FromNormalId(id)
129 | pcall(function() id = id.Value or id end);
130 | if (id == 0) then -- right
131 | return vector3.new(1, 0, 0);
132 | elseif (id == 1) then -- top
133 | return vector3.new(0, 1, 0);
134 | elseif (id == 2) then -- back
135 | return vector3.new(0, 0, 1);
136 | elseif (id == 3) then -- left
137 | return vector3.new(-1, 0, 0);
138 | elseif (id == 4) then
139 | return vector3.new(0, -1, 0);
140 | elseif (id == 5) then
141 | return vector3.new(0, 0, -1);
142 | end;
143 | end;
144 |
145 | function vector3.FromAxis(id)
146 | pcall(function() id = id.Value or id end);
147 | if (id == 0) then -- right
148 | return vector3.new(1, 0, 0);
149 | elseif (id == 1) then -- top
150 | return vector3.new(0, 1, 0);
151 | elseif (id == 2) then -- back
152 | return vector3.new(0, 0, 1);
153 | end;
154 | end;
155 |
156 | function vector3:Lerp(v3, t)
157 | return self + (v3 - self) * t;
158 | end;
159 |
160 | function vector3:Dot(v3)
161 | local isVector = v3.__type and v3.__type == "vector3";
162 | if (isVector) then
163 | return self.x * v3.x + self.y * v3.y + self.z * v3.z;
164 | else
165 | error("bad argument #1 to 'Dot' (Vector3 expected, got number)");
166 | end;
167 | end;
168 |
169 | function vector3:Cross(v3)
170 | local isVector = v3.__type and v3.__type == "vector3";
171 | if (isVector) then
172 | return vector3.new(
173 | self.y * v3.z - self.z * v3.y,
174 | self.z * v3.x - self.x * v3.z,
175 | self.x * v3.y - self.y * v3.x
176 | );
177 | else
178 | error("bad argument #1 to 'Cross' (Vector3 expected, got number)");
179 | end;
180 | end;
181 |
182 | return vector3;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vector3-and-CFrame-pure-Lua
2 | Vector3 and CFrame classes in pure Lua (also C# now!)
3 |
4 | These are a few "classes" (I use the term lightly) that I wrote for use in pure Lua. They are useful for anything 3D in gamedev or potentially mathematical. The CFrame class is used to store 3D positional/rotational data while the Vector3 class can be used in a similar fasion or for general mathematical usage.
5 |
6 | The Vector3 class is independant and can run on its own in plain old Lua. The CFrame class needs the Vector3 class to run.
7 |
8 | I originally posted this on my wiki page, but I wanted to have a copy on github in case it ever got deleted or whatever.
9 | http://wiki.roblox.com/index.php?title=User:EgoMoose/Articles/Pure_Lua_Vector3_and_CFrame
10 |
--------------------------------------------------------------------------------