diff --git a/builtin/common/vector.lua b/builtin/common/vector.lua index e2008a9d7..be82401c3 100644 --- a/builtin/common/vector.lua +++ b/builtin/common/vector.lua @@ -375,6 +375,18 @@ function vector.in_area(pos, min, max) (pos.z >= min.z) and (pos.z <= max.z) end +function vector.random_direction() + -- Generate a random direction of unit length, via rejection sampling + local x, y, z, l2 + repeat -- expected less than two attempts on average (volume sphere vs. cube) + x, y, z = math.random() * 2 - 1, math.random() * 2 - 1, math.random() * 2 - 1 + l2 = x*x + y*y + z*z + until l2 <= 1 and l2 >= 1e-6 + -- normalize + local l = math.sqrt(l2) + return fast_new(x/l, y/l, z/l) +end + if rawget(_G, "core") and core.set_read_vector and core.set_push_vector then local function read_vector(v) return v.x, v.y, v.z diff --git a/doc/lua_api.md b/doc/lua_api.md index f892e0a5c..34e9c190a 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -3820,6 +3820,8 @@ vectors are written like this: `(x, y, z)`: `vector.new(v)` does the same as `vector.copy(v)` * `vector.zero()`: * Returns a new vector `(0, 0, 0)`. +* `vector.random_direction()`: + * Returns a new vector of length 1, pointing into a direction chosen uniformly at random. * `vector.copy(v)`: * Returns a copy of the vector `v`. * `vector.from_string(s[, init])`: