源战役客户端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

585 行
13 KiB

  1. local math = math
  2. local sin = math.sin
  3. local cos = math.cos
  4. local acos = math.acos
  5. local asin = math.asin
  6. local sqrt = math.sqrt
  7. local min = math.min
  8. local max = math.max
  9. local sign = math.sign
  10. local atan2 = math.atan2
  11. local clamp = Mathf.Clamp
  12. local abs = math.abs
  13. local setmetatable = setmetatable
  14. local getmetatable = getmetatable
  15. local rawget = rawget
  16. local rawset = rawset
  17. local Vector3 = Vector3
  18. local rad2Deg = Mathf.Rad2Deg
  19. local halfDegToRad = 0.5 * Mathf.Deg2Rad
  20. local _forward = Vector3.forward
  21. local _up = Vector3.up
  22. local _next = { 2, 3, 1 }
  23. local Quaternion = {}
  24. local get = tolua.initget(Quaternion)
  25. Quaternion.__index = function(t, k)
  26. local var = rawget(Quaternion, k)
  27. if var == nil then
  28. var = rawget(get, k)
  29. if var ~= nil then
  30. return var(t)
  31. end
  32. end
  33. return var
  34. end
  35. Quaternion.__newindex = function(t, name, k)
  36. if name == "eulerAngles" then
  37. t:SetEuler(k)
  38. else
  39. rawset(t, name, k)
  40. end
  41. end
  42. function Quaternion.New(x, y, z, w)
  43. local quat = {x = x or 0, y = y or 0, z = z or 0, w = w or 0}
  44. setmetatable(quat, Quaternion)
  45. return quat
  46. end
  47. local _new = Quaternion.New
  48. Quaternion.__call = function(t, x, y, z, w)
  49. return _new(x, y, z, w)
  50. end
  51. function Quaternion:Set(x,y,z,w)
  52. self.x = x or 0
  53. self.y = y or 0
  54. self.z = z or 0
  55. self.w = w or 0
  56. end
  57. function Quaternion:Clone()
  58. return _new(self.x, self.y, self.z, self.w)
  59. end
  60. function Quaternion:Get()
  61. return self.x, self.y, self.z, self.w
  62. end
  63. function Quaternion.Dot(a, b)
  64. return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w
  65. end
  66. function Quaternion.Angle(a, b)
  67. local dot = Quaternion.Dot(a, b)
  68. if dot < 0 then dot = -dot end
  69. return acos(min(dot, 1)) * 2 * 57.29578
  70. end
  71. function Quaternion.AngleAxis(angle, axis)
  72. local normAxis = axis:Normalize()
  73. angle = angle * halfDegToRad
  74. local s = sin(angle)
  75. local w = cos(angle)
  76. local x = normAxis.x * s
  77. local y = normAxis.y * s
  78. local z = normAxis.z * s
  79. return _new(x,y,z,w)
  80. end
  81. function Quaternion.Equals(a, b)
  82. return a.x == b.x and a.y == b.y and a.z == b.z and a.w == b.w
  83. end
  84. function Quaternion.Euler(x, y, z)
  85. local quat = _new()
  86. quat:SetEuler(x,y,z)
  87. return quat
  88. end
  89. function Quaternion:SetEuler(x, y, z)
  90. if y == nil and z == nil then
  91. y = x.y
  92. z = x.z
  93. x = x.x
  94. end
  95. x = x * halfDegToRad
  96. y = y * halfDegToRad
  97. z = z * halfDegToRad
  98. local sinX = sin(x)
  99. local cosX = cos(x)
  100. local sinY = sin(y)
  101. local cosY = cos(y)
  102. local sinZ = sin(z)
  103. local cosZ = cos(z)
  104. self.w = cosY * cosX * cosZ + sinY * sinX * sinZ
  105. self.x = cosY * sinX * cosZ + sinY * cosX * sinZ
  106. self.y = sinY * cosX * cosZ - cosY * sinX * sinZ
  107. self.z = cosY * cosX * sinZ - sinY * sinX * cosZ
  108. return self
  109. end
  110. function Quaternion:Normalize()
  111. local quat = self:Clone()
  112. quat:SetNormalize()
  113. return quat
  114. end
  115. function Quaternion:SetNormalize()
  116. local n = self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w
  117. if n ~= 1 and n > 0 then
  118. n = 1 / sqrt(n)
  119. self.x = self.x * n
  120. self.y = self.y * n
  121. self.z = self.z * n
  122. self.w = self.w * n
  123. end
  124. end
  125. --产生一个新的从from到to的四元数
  126. function Quaternion.FromToRotation(from, to)
  127. local quat = Quaternion.New()
  128. quat:SetFromToRotation(from, to)
  129. return quat
  130. end
  131. --设置当前四元数为 from 到 to的旋转, 注意from和to同 forward平行会同unity不一致
  132. function Quaternion:SetFromToRotation1(from, to)
  133. local v0 = from:Normalize()
  134. local v1 = to:Normalize()
  135. local d = Vector3.Dot(v0, v1)
  136. if d > -1 + 1e-6 then
  137. local s = sqrt((1+d) * 2)
  138. local invs = 1 / s
  139. local c = Vector3.Cross(v0, v1) * invs
  140. self:Set(c.x, c.y, c.z, s * 0.5)
  141. elseif d > 1 - 1e-6 then
  142. return _new(0, 0, 0, 1)
  143. else
  144. local axis = Vector3.Cross(Vector3.right, v0)
  145. if axis:SqrMagnitude() < 1e-6 then
  146. axis = Vector3.Cross(Vector3.forward, v0)
  147. end
  148. self:Set(axis.x, axis.y, axis.z, 0)
  149. return self
  150. end
  151. return self
  152. end
  153. local function MatrixToQuaternion(rot, quat)
  154. local trace = rot[1][1] + rot[2][2] + rot[3][3]
  155. if trace > 0 then
  156. local s = sqrt(trace + 1)
  157. quat.w = 0.5 * s
  158. s = 0.5 / s
  159. quat.x = (rot[3][2] - rot[2][3]) * s
  160. quat.y = (rot[1][3] - rot[3][1]) * s
  161. quat.z = (rot[2][1] - rot[1][2]) * s--]]
  162. quat:SetNormalize()
  163. else
  164. local i = 1
  165. local q = {0, 0, 0}
  166. if rot[2][2] > rot[1][1] then
  167. i = 2
  168. end
  169. if rot[3][3] > rot[i][i] then
  170. i = 3
  171. end
  172. local j = _next[i]
  173. local k = _next[j]
  174. local t = rot[i][i] - rot[j][j] - rot[k][k] + 1
  175. local s = 0.5 / sqrt(t)
  176. q[i] = s * t
  177. local w = (rot[k][j] - rot[j][k]) * s
  178. q[j] = (rot[j][i] + rot[i][j]) * s
  179. q[k] = (rot[k][i] + rot[i][k]) * s
  180. quat:Set(q[1], q[2], q[3], w)
  181. quat:SetNormalize()
  182. end
  183. end
  184. function Quaternion:SetFromToRotation(from, to)
  185. from = from:Normalize()
  186. to = to:Normalize()
  187. local e = Vector3.Dot(from, to)
  188. if e > 1 - 1e-6 then
  189. self:Set(0, 0, 0, 1)
  190. elseif e < -1 + 1e-6 then
  191. local left = {0, from.z, from.y}
  192. local mag = left[2] * left[2] + left[3] * left[3] --+ left[1] * left[1] = 0
  193. if mag < 1e-6 then
  194. left[1] = -from.z
  195. left[2] = 0
  196. left[3] = from.x
  197. mag = left[1] * left[1] + left[3] * left[3]
  198. end
  199. local invlen = 1/sqrt(mag)
  200. left[1] = left[1] * invlen
  201. left[2] = left[2] * invlen
  202. left[3] = left[3] * invlen
  203. local up = {0, 0, 0}
  204. up[1] = left[2] * from.z - left[3] * from.y
  205. up[2] = left[3] * from.x - left[1] * from.z
  206. up[3] = left[1] * from.y - left[2] * from.x
  207. local fxx = -from.x * from.x
  208. local fyy = -from.y * from.y
  209. local fzz = -from.z * from.z
  210. local fxy = -from.x * from.y
  211. local fxz = -from.x * from.z
  212. local fyz = -from.y * from.z
  213. local uxx = up[1] * up[1]
  214. local uyy = up[2] * up[2]
  215. local uzz = up[3] * up[3]
  216. local uxy = up[1] * up[2]
  217. local uxz = up[1] * up[3]
  218. local uyz = up[2] * up[3]
  219. local lxx = -left[1] * left[1]
  220. local lyy = -left[2] * left[2]
  221. local lzz = -left[3] * left[3]
  222. local lxy = -left[1] * left[2]
  223. local lxz = -left[1] * left[3]
  224. local lyz = -left[2] * left[3]
  225. local rot =
  226. {
  227. {fxx + uxx + lxx, fxy + uxy + lxy, fxz + uxz + lxz},
  228. {fxy + uxy + lxy, fyy + uyy + lyy, fyz + uyz + lyz},
  229. {fxz + uxz + lxz, fyz + uyz + lyz, fzz + uzz + lzz},
  230. }
  231. MatrixToQuaternion(rot, self)
  232. else
  233. local v = Vector3.Cross(from, to)
  234. local h = (1 - e) / Vector3.Dot(v, v)
  235. local hx = h * v.x
  236. local hz = h * v.z
  237. local hxy = hx * v.y
  238. local hxz = hx * v.z
  239. local hyz = hz * v.y
  240. local rot =
  241. {
  242. {e + hx*v.x, hxy - v.z, hxz + v.y},
  243. {hxy + v.z, e + h*v.y*v.y, hyz-v.x},
  244. {hxz - v.y, hyz + v.x, e + hz*v.z},
  245. }
  246. MatrixToQuaternion(rot, self)
  247. end
  248. end
  249. function Quaternion:Inverse()
  250. local quat = Quaternion.New()
  251. quat.x = -self.x
  252. quat.y = -self.y
  253. quat.z = -self.z
  254. quat.w = self.w
  255. return quat
  256. end
  257. function Quaternion.Lerp(q1, q2, t)
  258. t = clamp(t, 0, 1)
  259. local q = _new()
  260. if Quaternion.Dot(q1, q2) < 0 then
  261. q.x = q1.x + t * (-q2.x -q1.x)
  262. q.y = q1.y + t * (-q2.y -q1.y)
  263. q.z = q1.z + t * (-q2.z -q1.z)
  264. q.w = q1.w + t * (-q2.w -q1.w)
  265. else
  266. q.x = q1.x + (q2.x - q1.x) * t
  267. q.y = q1.y + (q2.y - q1.y) * t
  268. q.z = q1.z + (q2.z - q1.z) * t
  269. q.w = q1.w + (q2.w - q1.w) * t
  270. end
  271. q:SetNormalize()
  272. return q
  273. end
  274. function Quaternion.LookRotation(forward, up)
  275. local mag = forward:Magnitude()
  276. if mag < 1e-6 then
  277. LogError("error input forward to Quaternion.LookRotation" + tostring(forward))
  278. return nil
  279. end
  280. forward = forward / mag
  281. up = up or _up
  282. local right = Vector3.Cross(up, forward)
  283. right:SetNormalize()
  284. up = Vector3.Cross(forward, right)
  285. right = Vector3.Cross(up, forward)
  286. --[[ local quat = _new(0,0,0,1)
  287. local rot =
  288. {
  289. {right.x, up.x, forward.x},
  290. {right.y, up.y, forward.y},
  291. {right.z, up.z, forward.z},
  292. }
  293. MatrixToQuaternion(rot, quat)
  294. return quat--]]
  295. local t = right.x + up.y + forward.z
  296. if t > 0 then
  297. local x, y, z, w
  298. t = t + 1
  299. local s = 0.5 / sqrt(t)
  300. w = s * t
  301. x = (up.z - forward.y) * s
  302. y = (forward.x - right.z) * s
  303. z = (right.y - up.x) * s
  304. local ret = _new(x, y, z, w)
  305. ret:SetNormalize()
  306. return ret
  307. else
  308. local rot =
  309. {
  310. {right.x, up.x, forward.x},
  311. {right.y, up.y, forward.y},
  312. {right.z, up.z, forward.z},
  313. }
  314. local q = {0, 0, 0}
  315. local i = 1
  316. if up.y > right.x then
  317. i = 2
  318. end
  319. if forward.z > rot[i][i] then
  320. i = 3
  321. end
  322. local j = _next[i]
  323. local k = _next[j]
  324. local t = rot[i][i] - rot[j][j] - rot[k][k] + 1
  325. local s = 0.5 / sqrt(t)
  326. q[i] = s * t
  327. local w = (rot[k][j] - rot[j][k]) * s
  328. q[j] = (rot[j][i] + rot[i][j]) * s
  329. q[k] = (rot[k][i] + rot[i][k]) * s
  330. local ret = _new(q[1], q[2], q[3], w)
  331. ret:SetNormalize()
  332. return ret
  333. end
  334. end
  335. function Quaternion:SetIdentity()
  336. self.x = 0
  337. self.y = 0
  338. self.z = 0
  339. self.w = 1
  340. end
  341. local function UnclampedSlerp(from, to, t)
  342. local cosAngle = Quaternion.Dot(from, to)
  343. if cosAngle < 0 then
  344. cosAngle = -cosAngle
  345. to = Quaternion.New(-to.x, -to.y, -to.z, -to.w)
  346. end
  347. local t1, t2
  348. if cosAngle < 0.95 then
  349. local angle = acos(cosAngle)
  350. local sinAngle = sin(angle)
  351. local invSinAngle = 1 / sinAngle
  352. t1 = sin((1 - t) * angle) * invSinAngle
  353. t2 = sin(t * angle) * invSinAngle
  354. local quat = _new(from.x * t1 + to.x * t2, from.y * t1 + to.y * t2, from.z * t1 + to.z * t2, from.w * t1 + to.w * t2)
  355. return quat
  356. else
  357. return Quaternion.Lerp(from, to, t)
  358. end
  359. end
  360. function Quaternion.Slerp(from, to, t)
  361. t = clamp(t, 0, 1)
  362. return UnclampedSlerp(from, to, t)
  363. end
  364. function Quaternion.RotateTowards(from, to, maxDegreesDelta)
  365. local angle = Quaternion.Angle(from, to)
  366. if angle == 0 then
  367. return to
  368. end
  369. local t = min(1, maxDegreesDelta / angle)
  370. return UnclampedSlerp(from, to, t)
  371. end
  372. local function Approximately(f0, f1)
  373. return abs(f0 - f1) < 1e-6
  374. end
  375. function Quaternion:ToAngleAxis()
  376. local angle = 2 * acos(self.w)
  377. if Approximately(angle, 0) then
  378. return angle * 57.29578, Vector3.New(1, 0, 0)
  379. end
  380. local div = 1 / sqrt(1 - sqrt(self.w))
  381. return angle * 57.29578, Vector3.New(self.x * div, self.y * div, self.z * div)
  382. end
  383. local pi = Mathf.PI
  384. local half_pi = pi * 0.5
  385. local two_pi = 2 * pi
  386. local negativeFlip = -0.0001
  387. local positiveFlip = two_pi - 0.0001
  388. local function SanitizeEuler(euler)
  389. if euler.x < negativeFlip then
  390. euler.x = euler.x + two_pi
  391. elseif euler.x > positiveFlip then
  392. euler.x = euler.x - two_pi
  393. end
  394. if euler.y < negativeFlip then
  395. euler.y = euler.y + two_pi
  396. elseif euler.y > positiveFlip then
  397. euler.y = euler.y - two_pi
  398. end
  399. if euler.z < negativeFlip then
  400. euler.z = euler.z + two_pi
  401. elseif euler.z > positiveFlip then
  402. euler.z = euler.z + two_pi
  403. end
  404. end
  405. --from http://www.geometrictools.com/Documentation/EulerAngles.pdf
  406. --Order of rotations: YXZ
  407. function Quaternion:ToEulerAngles()
  408. local x = self.x
  409. local y = self.y
  410. local z = self.z
  411. local w = self.w
  412. local check = 2 * (y * z - w * x)
  413. if check < 0.999 then
  414. if check > -0.999 then
  415. local v = Vector3.New( -asin(check),
  416. atan2(2 * (x * z + w * y), 1 - 2 * (x * x + y * y)),
  417. atan2(2 * (x * y + w * z), 1 - 2 * (x * x + z * z)))
  418. SanitizeEuler(v)
  419. v:Mul(rad2Deg)
  420. return v
  421. else
  422. local v = Vector3.New(half_pi, atan2(2 * (x * y - w * z), 1 - 2 * (y * y + z * z)), 0)
  423. SanitizeEuler(v)
  424. v:Mul(rad2Deg)
  425. return v
  426. end
  427. else
  428. local v = Vector3.New(-half_pi, atan2(-2 * (x * y - w * z), 1 - 2 * (y * y + z * z)), 0)
  429. SanitizeEuler(v)
  430. v:Mul(rad2Deg)
  431. return v
  432. end
  433. end
  434. function Quaternion:Forward()
  435. return self:MulVec3(_forward)
  436. end
  437. function Quaternion.MulVec3(self, point)
  438. local vec = Vector3.New()
  439. local num = self.x * 2
  440. local num2 = self.y * 2
  441. local num3 = self.z * 2
  442. local num4 = self.x * num
  443. local num5 = self.y * num2
  444. local num6 = self.z * num3
  445. local num7 = self.x * num2
  446. local num8 = self.x * num3
  447. local num9 = self.y * num3
  448. local num10 = self.w * num
  449. local num11 = self.w * num2
  450. local num12 = self.w * num3
  451. vec.x = (((1 - (num5 + num6)) * point.x) + ((num7 - num12) * point.y)) + ((num8 + num11) * point.z)
  452. vec.y = (((num7 + num12) * point.x) + ((1 - (num4 + num6)) * point.y)) + ((num9 - num10) * point.z)
  453. vec.z = (((num8 - num11) * point.x) + ((num9 + num10) * point.y)) + ((1 - (num4 + num5)) * point.z)
  454. return vec
  455. end
  456. Quaternion.__mul = function(lhs, rhs)
  457. if Quaternion == getmetatable(rhs) then
  458. return Quaternion.New((((lhs.w * rhs.x) + (lhs.x * rhs.w)) + (lhs.y * rhs.z)) - (lhs.z * rhs.y), (((lhs.w * rhs.y) + (lhs.y * rhs.w)) + (lhs.z * rhs.x)) - (lhs.x * rhs.z), (((lhs.w * rhs.z) + (lhs.z * rhs.w)) + (lhs.x * rhs.y)) - (lhs.y * rhs.x), (((lhs.w * rhs.w) - (lhs.x * rhs.x)) - (lhs.y * rhs.y)) - (lhs.z * rhs.z))
  459. elseif Vector3 == getmetatable(rhs) then
  460. return lhs:MulVec3(rhs)
  461. end
  462. end
  463. Quaternion.__unm = function(q)
  464. return Quaternion.New(-q.x, -q.y, -q.z, -q.w)
  465. end
  466. Quaternion.__eq = function(lhs,rhs)
  467. return Quaternion.Dot(lhs, rhs) > 0.999999
  468. end
  469. Quaternion.__tostring = function(self)
  470. return "["..self.x..","..self.y..","..self.z..","..self.w.."]"
  471. end
  472. get.identity = function() return _new(0, 0, 0, 1) end
  473. get.eulerAngles = Quaternion.ToEulerAngles
  474. UnityEngine.Quaternion = Quaternion
  475. setmetatable(Quaternion, Quaternion)
  476. return Quaternion