Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Types: color vs. vec4 vs vec3 vs vec2

edited January 2013 in Questions Posts: 666

I am eying to write a generic load/save routine for arbitrary type data. I have in the same class a color, a vec4, a vec3 and a vec2 variable. I am Abe to persist them with JSON.

When I reconstruct these objects, I need to determine the type the variable came from. I've already thought about hacking the persistence with tags to reconstruct, but I still need to figure out what my class definition type is that I came from.

How can I programmatically get color vs vec4, for example? They are all classified as userdata. Another example question: Does userdata have a property to determine what is a vec4 vs a vec3?

Tagged:

Comments

  • Posts: 666

    Whoa, interesting!

    So...if you stick ANYTHING into a color, it will downgrade into the appropriate vec type!

  • edited January 2013 Posts: 196

    Hi @aciolino, You mean color(gray), color(gray, a), color(r, g, b) and color(r, g, b, a) ?

  • Posts: 666

    Different - if you have a value at (255,128,64,255), what is that? It's a vec4 or it's a color object.

    What I find is that if you assign this to a vec2, you'll get (255,128) so a userdata can be used for a color or a point.

  • Jmv38Jmv38 Mod
    Posts: 3,297

    Hello @aciolino. Some time ago i posted a big mesh saving utility. There is a convert() class in it, and in the convert class i have this function that returns the type of userdata. You can see the trick i have used below:

    -- type(v):"nil", "number", "string", "boolean", "table", "function", "thread", "userdata".
    function Convert:type(x)
        local txt = type(x)
        function typeCompare(x,ref)
        -- nb: returns an error if x or ref have no metatable!
        local i = getmetatable(x).__index
        local j = getmetatable(ref).__index
        return (i==j)
        end
        if txt == "userdata" then
            if     typeCompare(x,vec2())     then txt ="vec2" 
            elseif typeCompare(x,vec3())     then txt ="vec3" 
            elseif typeCompare(x,color())    then txt ="color" 
            elseif typeCompare(x,image(1,1)) then txt ="image" 
            elseif typeCompare(x,matrix())   then txt ="matrix" 
            elseif typeCompare(x,mesh())     then txt ="mesh" 
            end
        end
        if txt == "table" then
            txt = "{"..self:type(x[1]).."}"
        end
        return txt
    end
    
  • Posts: 2,161

    .@Jmv38 Quick style question for you. Why are you defining typeCompare every time the function Convert:type is called? Wouldn't it make more sense to define it once outside this function and then call it from within? In fact, wouldn't the following be a little more compact:

    function Convert:type(x)
        local txt = type(x)
        local i = getmetatable(x).__index
        local j = getmetatable(ref).__index
        return (i==j)
        end
        if txt == "userdata" then
            local mt = getmetatable(x).__index
            if       mt == getmetatable(vec2()).__index    then txt ="vec2" 
            elseif mt == getmetatable(vec3()).__index    then txt ="vec3" 
            elseif mt == getmetatable(color()).__index     then txt ="color" 
            elseif mt == getmetatable(image()).__index    then txt ="image" 
            elseif mt == getmetatable(matrix()).__index   then txt ="matrix" 
            elseif mt == getmetatable(mesh()).__index     then txt ="mesh" 
            end
        elseif txt == "table" then
            txt = "{"..self:type(x[1]).."}"
        end
        return txt
    end
    
  • edited February 2013 Posts: 503

    But isn't this more compact ;) (and ref is undefined?)


    local typeTable = { [getmetatable(vec2()).__index ] = "vec2", [getmetatable(vec3()).__index ] = "vec3", [getmetatable(color()).__index ] = "color", [getmetatable(image(1,1)).__index ] = "image", [getmetatable(matrix()).__index] = "matrix", [getmetatable(mesh()).__index ] = "mesh" } function convertType(x) local txt = type(x) if txt == "userdata" then return typeTable[getmetatable(x).__index] elseif txt == "table" then return "{"..convertType(x[1]).."}" end return txt end
  • Posts: 196

    @Andrew_Stacey I think you forgot to remove the following

        local i = getmetatable(x).__index
        local j = getmetatable(ref).__index
        return (i==j)
        end
    

    Also, image seems to be a function and requires two arguments?

  • Posts: 2,161

    .@Xavier Whoops! Yes, I just edited it without testing it.

    .@tnlogy Looks better, yes.

  • Posts: 666

    It's certainly better form than me 'forcing' it the way I am. That said, it's working either way, which was quite a surprise to me. I do like the code by @tnlogy.

    Thanks all for the quick repsonse!

  • Jmv38Jmv38 Mod
    edited February 2013 Posts: 3,297

    Hello @andrew_Stacey and @tnlogy.
    Function in function: it is just a way to hide the local function from the rest, there Are already too many visible function in my code.
    If i look at both your code: metatable and __index appear at many locations. i am not familiar with these keywords, so they scared me. Then i used them only once, in an encapsulated location: this might not be the fastest code (but i dont need speed here) nor the most compact (but i favor debuggability against compactness). And it did the job for me, when i needed to... I always favor readability (according to my -low- level of programming skills) against optimization, except when speed is a key factor... Voilà.

Sign In or Register to comment.