@quenty/qframe 10.10.0 → 10.10.1-canary.542.7609692.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/package.json +6 -6
- package/src/Shared/QFrame.lua +70 -66
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [10.10.1-canary.542.7609692.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/qframe@10.10.0...@quenty/qframe@10.10.1-canary.542.7609692.0) (2025-03-13)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @quenty/qframe
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
# [10.10.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/qframe@10.9.0...@quenty/qframe@10.10.0) (2025-02-18)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @quenty/qframe
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/qframe",
|
|
3
|
-
"version": "10.10.0",
|
|
3
|
+
"version": "10.10.1-canary.542.7609692.0",
|
|
4
4
|
"description": "CFrame representation as a quaternion for Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"AxisAngles"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@quenty/loader": "
|
|
30
|
+
"@quenty/loader": "10.8.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@quenty/camerastoryutils": "
|
|
34
|
-
"@quenty/cubicspline": "
|
|
35
|
-
"@quenty/maid": "
|
|
33
|
+
"@quenty/camerastoryutils": "10.10.1-canary.542.7609692.0",
|
|
34
|
+
"@quenty/cubicspline": "10.8.0",
|
|
35
|
+
"@quenty/maid": "3.4.0"
|
|
36
36
|
},
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "76096921c6c965e5c4f9c796f97642d16d628c6b"
|
|
41
41
|
}
|
package/src/Shared/QFrame.lua
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
CFrame representation as a quaternion. Alternative representation of a [CFrame].
|
|
3
4
|
@class QFrame
|
|
@@ -6,19 +7,24 @@
|
|
|
6
7
|
local QFrame = {}
|
|
7
8
|
QFrame.__index = QFrame
|
|
8
9
|
|
|
10
|
+
export type QFrame = typeof(setmetatable(
|
|
11
|
+
{} :: {
|
|
12
|
+
x: number,
|
|
13
|
+
y: number,
|
|
14
|
+
z: number,
|
|
15
|
+
W: number,
|
|
16
|
+
X: number,
|
|
17
|
+
Y: number,
|
|
18
|
+
Z: number,
|
|
19
|
+
},
|
|
20
|
+
QFrame
|
|
21
|
+
))
|
|
22
|
+
|
|
9
23
|
--[=[
|
|
10
24
|
Constructs a new QFrame
|
|
11
|
-
|
|
12
|
-
@param x number?
|
|
13
|
-
@param y number?
|
|
14
|
-
@param z number?
|
|
15
|
-
@param W number?
|
|
16
|
-
@param X number?
|
|
17
|
-
@param Y number?
|
|
18
|
-
@param Z number?
|
|
19
25
|
@return QFrame
|
|
20
26
|
]=]
|
|
21
|
-
function QFrame.new(x
|
|
27
|
+
function QFrame.new(x: number?, y: number?, z: number?, W: number?, X: number?, Y: number?, Z: number?): QFrame
|
|
22
28
|
local self = setmetatable({}, QFrame)
|
|
23
29
|
self.x = x or 0
|
|
24
30
|
self.y = y or 0
|
|
@@ -36,7 +42,7 @@ end
|
|
|
36
42
|
@param value any
|
|
37
43
|
@return boolean
|
|
38
44
|
]=]
|
|
39
|
-
function QFrame.isQFrame(value)
|
|
45
|
+
function QFrame.isQFrame(value: any): boolean
|
|
40
46
|
return getmetatable(value) == QFrame
|
|
41
47
|
end
|
|
42
48
|
|
|
@@ -46,23 +52,23 @@ end
|
|
|
46
52
|
@param closestTo QFrame
|
|
47
53
|
@return QFrame
|
|
48
54
|
]=]
|
|
49
|
-
function QFrame.fromCFrameClosestTo(cframe, closestTo)
|
|
55
|
+
function QFrame.fromCFrameClosestTo(cframe: CFrame, closestTo: QFrame)
|
|
50
56
|
assert(typeof(cframe) == "CFrame", "Bad cframe")
|
|
51
57
|
assert(QFrame.isQFrame(closestTo), "Bad closestTo")
|
|
52
58
|
|
|
53
|
-
local axis, angle = cframe:
|
|
54
|
-
local W = math.cos(angle/2)
|
|
55
|
-
local X = math.sin(angle/2)*axis.
|
|
56
|
-
local Y = math.sin(angle/2)*axis.
|
|
57
|
-
local Z = math.sin(angle/2)*axis.
|
|
59
|
+
local axis, angle = cframe:ToAxisAngle()
|
|
60
|
+
local W = math.cos(angle / 2)
|
|
61
|
+
local X = math.sin(angle / 2) * axis.X
|
|
62
|
+
local Y = math.sin(angle / 2) * axis.Y
|
|
63
|
+
local Z = math.sin(angle / 2) * axis.Z
|
|
58
64
|
|
|
59
|
-
local dot = W*closestTo.W + X*closestTo.X + Y*closestTo.Y + Z*closestTo.Z
|
|
65
|
+
local dot = W * closestTo.W + X * closestTo.X + Y * closestTo.Y + Z * closestTo.Z
|
|
60
66
|
|
|
61
67
|
if dot < 0 then
|
|
62
|
-
return QFrame.new(cframe.
|
|
68
|
+
return QFrame.new(cframe.X, cframe.Y, cframe.Z, -W, -X, -Y, -Z)
|
|
63
69
|
end
|
|
64
70
|
|
|
65
|
-
return QFrame.new(cframe.
|
|
71
|
+
return QFrame.new(cframe.X, cframe.Y, cframe.Z, W, X, Y, Z)
|
|
66
72
|
end
|
|
67
73
|
|
|
68
74
|
--[=[
|
|
@@ -71,19 +77,20 @@ end
|
|
|
71
77
|
@param qFrame QFrame
|
|
72
78
|
@return QFrame
|
|
73
79
|
]=]
|
|
74
|
-
function QFrame.fromVector3(vector, qFrame)
|
|
80
|
+
function QFrame.fromVector3(vector: Vector3, qFrame: QFrame): QFrame
|
|
75
81
|
assert(typeof(vector) == "Vector3", "Bad vector")
|
|
76
|
-
assert(QFrame.isQFrame(qFrame))
|
|
82
|
+
assert(QFrame.isQFrame(qFrame), "Bad qFrame")
|
|
77
83
|
|
|
78
|
-
return QFrame.new(vector.
|
|
84
|
+
return QFrame.new(vector.X, vector.Y, vector.Z, qFrame.W, qFrame.X, qFrame.Y, qFrame.Z)
|
|
79
85
|
end
|
|
80
86
|
|
|
81
87
|
--[=[
|
|
82
88
|
Converts the QFrame to a [CFrame]
|
|
89
|
+
|
|
83
90
|
@param self QFrame
|
|
84
|
-
@return CFrame
|
|
91
|
+
@return CFrame?
|
|
85
92
|
]=]
|
|
86
|
-
function QFrame.toCFrame(self)
|
|
93
|
+
function QFrame.toCFrame(self): CFrame?
|
|
87
94
|
local cframe = CFrame.new(self.x, self.y, self.z, self.X, self.Y, self.Z, self.W)
|
|
88
95
|
if cframe == cframe then
|
|
89
96
|
return cframe
|
|
@@ -97,7 +104,7 @@ end
|
|
|
97
104
|
@param self QFrame
|
|
98
105
|
@return Vector3
|
|
99
106
|
]=]
|
|
100
|
-
function QFrame.toPosition(self)
|
|
107
|
+
function QFrame.toPosition(self: QFrame): Vector3
|
|
101
108
|
return Vector3.new(self.x, self.y, self.z)
|
|
102
109
|
end
|
|
103
110
|
|
|
@@ -106,9 +113,8 @@ end
|
|
|
106
113
|
@param a QFrame
|
|
107
114
|
@return boolean
|
|
108
115
|
]=]
|
|
109
|
-
function QFrame.isNAN(a)
|
|
110
|
-
return a.x ~= a.x or a.y ~= a.y or a.z ~= a.z
|
|
111
|
-
or a.W ~= a.W or a.X ~= a.X or a.Y ~= a.Y or a.Z ~= a.Z
|
|
116
|
+
function QFrame.isNAN(a: QFrame): boolean
|
|
117
|
+
return a.x ~= a.x or a.y ~= a.y or a.z ~= a.z or a.W ~= a.W or a.X ~= a.X or a.Y ~= a.Y or a.Z ~= a.Z
|
|
112
118
|
end
|
|
113
119
|
|
|
114
120
|
--[=[
|
|
@@ -116,7 +122,7 @@ end
|
|
|
116
122
|
@param a QFrame
|
|
117
123
|
@return QFrame
|
|
118
124
|
]=]
|
|
119
|
-
function QFrame.__unm(a)
|
|
125
|
+
function QFrame.__unm(a: QFrame): QFrame
|
|
120
126
|
return QFrame.new(-a.x, -a.y, -a.z, -a.W, -a.X, -a.Y, -a.Z)
|
|
121
127
|
end
|
|
122
128
|
|
|
@@ -126,9 +132,8 @@ end
|
|
|
126
132
|
@param b QFrame
|
|
127
133
|
@return QFrame
|
|
128
134
|
]=]
|
|
129
|
-
function QFrame.__add(a, b)
|
|
130
|
-
assert(QFrame.isQFrame(a) and QFrame.isQFrame(b),
|
|
131
|
-
"QFrame + non-QFrame attempted")
|
|
135
|
+
function QFrame.__add(a: QFrame, b: QFrame): QFrame
|
|
136
|
+
assert(QFrame.isQFrame(a) and QFrame.isQFrame(b), "QFrame + non-QFrame attempted")
|
|
132
137
|
|
|
133
138
|
return QFrame.new(a.x + b.x, a.y + b.y, a.z + b.z, a.W + b.W, a.X + b.X, a.Y + b.Y, a.Z + b.Z)
|
|
134
139
|
end
|
|
@@ -139,9 +144,8 @@ end
|
|
|
139
144
|
@param b QFrame
|
|
140
145
|
@return QFrame
|
|
141
146
|
]=]
|
|
142
|
-
function QFrame.__sub(a, b)
|
|
143
|
-
assert(QFrame.isQFrame(a) and QFrame.isQFrame(b),
|
|
144
|
-
"QFrame - non-QFrame attempted")
|
|
147
|
+
function QFrame.__sub(a: QFrame, b: QFrame): QFrame
|
|
148
|
+
assert(QFrame.isQFrame(a) and QFrame.isQFrame(b), "QFrame - non-QFrame attempted")
|
|
145
149
|
|
|
146
150
|
return QFrame.new(a.x - b.x, a.y - b.y, a.z - b.z, a.W - b.W, a.X - b.X, a.Y - b.Y, a.Z - b.Z)
|
|
147
151
|
end
|
|
@@ -152,7 +156,7 @@ end
|
|
|
152
156
|
@param b number
|
|
153
157
|
@return QFrame
|
|
154
158
|
]=]
|
|
155
|
-
function QFrame.__pow(a, b)
|
|
159
|
+
function QFrame.__pow(a: QFrame, b: QFrame): QF
|
|
156
160
|
assert(QFrame.isQFrame(a) and type(b) == "number", "Bad a or b")
|
|
157
161
|
|
|
158
162
|
-- Center of mass agnostic power formula
|
|
@@ -163,38 +167,38 @@ function QFrame.__pow(a, b)
|
|
|
163
167
|
local aW, aX, aY, aZ = a.W, a.X, a.Y, a.Z
|
|
164
168
|
|
|
165
169
|
-- first let's power the quaternion
|
|
166
|
-
local aMag = math.sqrt(aW*aW + aX*aX + aY*aY + aZ*aZ)
|
|
167
|
-
local aIm = math.sqrt(aX*aX + aY*aY + aZ*aZ)
|
|
168
|
-
local cMag = aMag^b
|
|
170
|
+
local aMag = math.sqrt(aW * aW + aX * aX + aY * aY + aZ * aZ)
|
|
171
|
+
local aIm = math.sqrt(aX * aX + aY * aY + aZ * aZ)
|
|
172
|
+
local cMag = aMag ^ b
|
|
169
173
|
|
|
170
|
-
if aIm <= 1e-8*aMag then
|
|
171
|
-
return QFrame.new(b*ax, b*ay, b*az, cMag, 0, 0, 0)
|
|
174
|
+
if aIm <= 1e-8 * aMag then
|
|
175
|
+
return QFrame.new(b * ax, b * ay, b * az, cMag, 0, 0, 0)
|
|
172
176
|
end
|
|
173
177
|
|
|
174
|
-
local rx = aX/aIm
|
|
175
|
-
local ry = aY/aIm
|
|
176
|
-
local rz = aZ/aIm
|
|
178
|
+
local rx = aX / aIm
|
|
179
|
+
local ry = aY / aIm
|
|
180
|
+
local rz = aZ / aIm
|
|
177
181
|
|
|
178
|
-
local cAng = b*math.atan2(aIm, aW)
|
|
182
|
+
local cAng = b * math.atan2(aIm, aW)
|
|
179
183
|
local cCos = math.cos(cAng)
|
|
180
184
|
local cSin = math.sin(cAng)
|
|
181
185
|
|
|
182
|
-
local cW = cMag*cCos
|
|
183
|
-
local cX = cMag*cSin*rx
|
|
184
|
-
local cY = cMag*cSin*ry
|
|
185
|
-
local cZ = cMag*cSin*rz
|
|
186
|
+
local cW = cMag * cCos
|
|
187
|
+
local cX = cMag * cSin * rx
|
|
188
|
+
local cY = cMag * cSin * ry
|
|
189
|
+
local cZ = cMag * cSin * rz
|
|
186
190
|
|
|
187
191
|
-- now we power the position
|
|
188
|
-
local k = ax*rx + ay*ry + az*rz
|
|
189
|
-
local wx, wy, wz = k*rx, k*ry, k*rz
|
|
192
|
+
local k = ax * rx + ay * ry + az * rz
|
|
193
|
+
local wx, wy, wz = k * rx, k * ry, k * rz
|
|
190
194
|
local ux, uy, uz = ax - wx, ay - wy, az - wz
|
|
191
|
-
local vx, vy, vz = ry*az - rz*ay, rz*ax - rx*az, rx*ay - ry*ax
|
|
192
|
-
local re = cSin*(aW/aIm*cCos + cSin)
|
|
193
|
-
local im = cSin*(aW/aIm*cSin - cCos)
|
|
195
|
+
local vx, vy, vz = ry * az - rz * ay, rz * ax - rx * az, rx * ay - ry * ax
|
|
196
|
+
local re = cSin * (aW / aIm * cCos + cSin)
|
|
197
|
+
local im = cSin * (aW / aIm * cSin - cCos)
|
|
194
198
|
|
|
195
|
-
local cx = re*ux + im*vx + b*wx
|
|
196
|
-
local cy = re*uy + im*vy + b*wy
|
|
197
|
-
local cz = re*uz + im*vz + b*wz
|
|
199
|
+
local cx = re * ux + im * vx + b * wx
|
|
200
|
+
local cy = re * uy + im * vy + b * wy
|
|
201
|
+
local cz = re * uz + im * vz + b * wz
|
|
198
202
|
|
|
199
203
|
return QFrame.new(cx, cy, cz, cW, cX, cY, cZ)
|
|
200
204
|
end
|
|
@@ -207,12 +211,13 @@ end
|
|
|
207
211
|
]=]
|
|
208
212
|
function QFrame.__mul(a, b)
|
|
209
213
|
if type(a) == "number" and QFrame.isQFrame(b) then
|
|
210
|
-
return QFrame.new(a*b.x, a*b.y, a*b.z, a*b.W, a*b.X, a*b.Y, a*b.Z)
|
|
214
|
+
return QFrame.new(a * b.x, a * b.y, a * b.z, a * b.W, a * b.X, a * b.Y, a * b.Z)
|
|
211
215
|
elseif QFrame.isQFrame(a) and type(b) == "number" then
|
|
212
|
-
return QFrame.new(a.x*b, a.y*b, a.z*b, a.W*b, a.X*b, a.Y*b, a.Z*b)
|
|
216
|
+
return QFrame.new(a.x * b, a.y * b, a.z * b, a.W * b, a.X * b, a.Y * b, a.Z * b)
|
|
213
217
|
elseif QFrame.isQFrame(a) and QFrame.isQFrame(b) then
|
|
214
|
-
local A2 = a.W*a.W + a.X*a.X + a.Y*a.Y + a.Z*a.Z
|
|
218
|
+
local A2 = a.W * a.W + a.X * a.X + a.Y * a.Y + a.Z * a.Z
|
|
215
219
|
|
|
220
|
+
-- stylua: ignore
|
|
216
221
|
return QFrame.new(
|
|
217
222
|
a.x + ((a.W*a.W + a.X*a.X - a.Y*a.Y - a.Z*a.Z)*b.x + 2*(a.X*a.Y - a.W*a.Z)*b.y + 2*(a.W*a.Y + a.X*a.Z)*b.z)
|
|
218
223
|
/A2,
|
|
@@ -235,9 +240,9 @@ end
|
|
|
235
240
|
@param b number
|
|
236
241
|
@return QFrame
|
|
237
242
|
]=]
|
|
238
|
-
function QFrame.__div(a, b)
|
|
243
|
+
function QFrame.__div(a: QFrame, b: number): QFrame
|
|
239
244
|
if type(b) == "number" then
|
|
240
|
-
return QFrame.new(a.x/b, a.y/b, a.z/b, a.W/b, a.X/b, a.Y/b, a.Z/b)
|
|
245
|
+
return QFrame.new(a.x / b, a.y / b, a.z / b, a.W / b, a.X / b, a.Y / b, a.Z / b)
|
|
241
246
|
else
|
|
242
247
|
error("QFrame / non-QFrame attempted")
|
|
243
248
|
end
|
|
@@ -249,9 +254,8 @@ end
|
|
|
249
254
|
@param b QFrame
|
|
250
255
|
@return boolean
|
|
251
256
|
]=]
|
|
252
|
-
function QFrame.__eq(a, b)
|
|
253
|
-
return a.x == b.x and a.y == b.y and a.z == b.z
|
|
254
|
-
and a.W == b.W and a.X == b.X and a.Y == b.Y and a.Z == b.Z
|
|
257
|
+
function QFrame.__eq(a: QFrame, b: QFrame)
|
|
258
|
+
return a.x == b.x and a.y == b.y and a.z == b.z and a.W == b.W and a.X == b.X and a.Y == b.Y and a.Z == b.Z
|
|
255
259
|
end
|
|
256
260
|
|
|
257
|
-
return QFrame
|
|
261
|
+
return QFrame
|