Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Lua) Doing mathematical operations with non-number values

Tags:

lua

I want to make some sort of a Vector3 library for Lua which could let you make simple 3D position operations with simple syntax. I'll mention that I'm using Luaj for running Lua code for Java manipulation.

Here's my beginning code:

Vector3 = {
new = function (x1, y1, z1)
  return {x = x1, y = y1, z = z1}
end
}



Position1 = Vector3.new(1, 5, 8)
Position2 = Vector3.new(4, 7, 2)

And here's what I want to be able to happen:

Subtraction = Position1 - Position2
print(Subtraction.x, Subtraction.y, Subtraction.z) -- prints "-3, -2, 6"

Any idea on making EXACT code to work?

like image 462
Laimonas Mileška Avatar asked Dec 01 '25 12:12

Laimonas Mileška


2 Answers

This is what metatables and metamethods are for. You should have a read in the documentation.

Basically, they let you redefine what operators (and some other things) do on your values. What you want right now is to define the __sub metamethod, which defines how to handle the - operator. I guess in the future you'll want to redefine the other metamethods as well.

First, define a subtraction function in your Vector3 "class" that takes two vectors:

function Vector3.subtract(u,v)
    return Vector3.new(u.x - v.x, u.y - v.y, u.z - v.z)
end

Then create let Vector3 know the metatable it should give all vectors:

Vector3.mt = {__sub = Vector3.subtract}

And when you create a new vector:

new = function (x1, y1, z1)
    local vec = {x = x1, y = y1, z = z1}
    setmetatable(vec, Vector3.mt)
    return vec
end

You could also make the metatable (mt) a local variable inside your new function - that would prevent external code from messing with the metatable (as it would be only accessible by your new function). However, having it inside Vector3 allows you to check against usages like v - "string":

function Vector3.subtract(u,v)
    if getmetatable(u) ~= Vector3.mt or
       getmetatable(v) ~= Vector3.mt then
        error("Only vectors can be subtracted from vectors", 2)
    end
    return Vector3.new(u.x - v.x, u.y - v.y, u.z - v.z)
end
like image 162
Martin Ender Avatar answered Dec 04 '25 20:12

Martin Ender


You could do something like this:

Vector3 = {}

mt = {}

function Vector3:new(_x, _y, _z)
  return setmetatable({
    x = _x or 0, 
    y = _y or 0,
    z = _z or 0
  }, mt)
end

mt.__sub = function(v1, v2) return Vector3:new(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z) end
mt.__tostring = function(v) return "Vector3=(" .. v.x .. "," .. v.y .. "," .. v.z .. ")" end
mt.__index = Vector3 -- redirect queries to the Vector3 table

-- test Vector3
Position1 = Vector3:new(1, 5, 8)
Position2 = Vector3:new(4, 7, 2)
Sub = Position1 - Position2
print(Sub)

which would print:

Vector3=(-3,-2,6)

More on Lua & OO, see: http://lua-users.org/wiki/ObjectOrientationTutorial

like image 40
Bart Kiers Avatar answered Dec 04 '25 19:12

Bart Kiers