 # Untitled

a guest
Jun 24th, 2015
272
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. -- pos - observer position
2. -- vec - observer vector
3. -- target - target position
4.
5. function angle (pos, vec, target)
6.
7. -- Imagine that the observer is wearing spherical helmet of raduis 1.
8. -- He looks on the target, and his line of sight crosses the helmet.
9. -- We'll calculate this crossing point by normalizing his looking
10. -- vector.
11.
12. -- Normalization means making length of vector equal to 1, but
13. -- still pointing to the same direction.
14.
15. local vec_look = vector.normalize(vec)
16.
17. -- We also calculate another vector, that is the difference
18. -- between observer and target (= position relative to target).
19.
20. local vec_diff = vector.subtract(target, pos)
21.
22. -- Well, this requires normalization too.
23.
24. vec_diff = vector.normalize(vec_diff)
25.
26. -- Now both are starting from center and pointing to some point
27. -- of surface of helmet. We will calculate the distance of
28.
29. -- Calculate the length between two vectors.
30.
31. local chord = vector.length(vector.subtract(vec_look, vec_diff))
32.
33. -- What we have calculated is a chord on some circle of sphere.
34. -- Having this we can calculate the angle.
35. -- https://en.wikipedia.org/wiki/Chord_%28geometry%29
36.
37. -- c = 2*r*sin(phi / 2)
38.
39. -- because r = 1, it degenerates to:
40.
41. -- c = 2 * sin(phi / 2)
42.
43. -- c/2 = sin(phi / 2)
44.
45. -- asin(c/2) = phi / 2
46.
47. -- 2 * asin(c/2) = phi
48.
49. local angle = 2 * math.asin(chord / 2)
50.
51. -- note the result is in radians. Convert it to degrees.
52.
53. return angle * 180 / math.pi
54. end
55.
56. function yaw2vec(yaw, pitch)
57. return {
58. x = -math.sin(yaw) * math.cos(pitch),
59. y = math.sin(pitch),
60. z = math.cos(yaw) * math.cos(pitch)}
61. end
62.
63. minetest.register_entity("test:human", {
64. hp_max = 1,
65. physical = true,
66. weight = 5,
67. collisionbox = {-0.3, -1.0, -0.3, 0.3, 0.8, 0.3},
68. visual = "mesh",
69. visual_size = {x=1, y=1},
70. mesh = "character.x",
71. textures = {"character.png"},
72. is_visible = true,
73. makes_footstep_sound = false,
74. automatic_rotate = true,
75.
76. -- When that guy is right-clicked, it will say the angle.
77. on_rightclick = function(self, clicker)
78. local o = self.object;
79. local pos = o:getpos()
80. local vec = yaw2vec(o:getyaw(), 0)
81. local target = minetest.get_player_by_name('singleplayer'):getpos()
82.
83. minetest.chat_send_player(clicker:get_player_name(), angle(pos, vec, target))
84. end,
85. })