Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- pos - observer position
- -- vec - observer vector
- -- target - target position
- function angle (pos, vec, target)
- -- Imagine that the observer is wearing spherical helmet of raduis 1.
- -- He looks on the target, and his line of sight crosses the helmet.
- -- We'll calculate this crossing point by normalizing his looking
- -- vector.
- -- Normalization means making length of vector equal to 1, but
- -- still pointing to the same direction.
- local vec_look = vector.normalize(vec)
- -- We also calculate another vector, that is the difference
- -- between observer and target (= position relative to target).
- local vec_diff = vector.subtract(target, pos)
- -- Well, this requires normalization too.
- vec_diff = vector.normalize(vec_diff)
- -- Now both are starting from center and pointing to some point
- -- of surface of helmet. We will calculate the distance of
- -- Calculate the length between two vectors.
- local chord = vector.length(vector.subtract(vec_look, vec_diff))
- -- What we have calculated is a chord on some circle of sphere.
- -- Having this we can calculate the angle.
- -- https://en.wikipedia.org/wiki/Chord_%28geometry%29
- -- c = 2*r*sin(phi / 2)
- -- because r = 1, it degenerates to:
- -- c = 2 * sin(phi / 2)
- -- c/2 = sin(phi / 2)
- -- asin(c/2) = phi / 2
- -- 2 * asin(c/2) = phi
- local angle = 2 * math.asin(chord / 2)
- -- note the result is in radians. Convert it to degrees.
- return angle * 180 / math.pi
- end
- function yaw2vec(yaw, pitch)
- return {
- x = -math.sin(yaw) * math.cos(pitch),
- y = math.sin(pitch),
- z = math.cos(yaw) * math.cos(pitch)}
- end
- minetest.register_entity("test:human", {
- hp_max = 1,
- physical = true,
- weight = 5,
- collisionbox = {-0.3, -1.0, -0.3, 0.3, 0.8, 0.3},
- visual = "mesh",
- visual_size = {x=1, y=1},
- mesh = "character.x",
- textures = {"character.png"},
- is_visible = true,
- makes_footstep_sound = false,
- automatic_rotate = true,
- -- When that guy is right-clicked, it will say the angle.
- on_rightclick = function(self, clicker)
- local o = self.object;
- local pos = o:getpos()
- local vec = yaw2vec(o:getyaw(), 0)
- local target = minetest.get_player_by_name('singleplayer'):getpos()
- minetest.chat_send_player(clicker:get_player_name(), angle(pos, vec, target))
- end,
- })
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement