lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> One problem I'm trying to figure out at the moment is how to have fast
> access to vector_xyz/vector_xyzw types - if these are implemented as a
> table
> they'll be *slow*, if they are implemented as simply x, y and z float
> types
> they are equally slow and *very* cumbersome to use.  So I think I need
to
> add a new integral type to Lua?  What do you reckon Nick?  I was
thinking
> maybe I could create a userdata with a metatable but because the
> userdata's
> aren't typed, I would have to associate the metatable numerous times
which
> might be an overhead considering how often you use these types.  Also
I'd
> like to allow elemental access which I think would be difficult with
> userdata - ie. I still want to do things like myvec1.x = myvec2.y + 10


You could store the vector on either side, C or Lua. Chances are C side
is more useful generally as you'll be using these vectors in C
functions. If you were to keep them on the Lua side a table per vector
can be expensive at runtime because you may have to create and collect
vectors that are created and deleted. 

To store them on the C side there are two userdata types for doing this.
"Light" data is like a C pointer and us basically a pointer wrapper so
you can get an easy handle to an object to pass back and forth from Lua
to C. The other ("heavy"?) userdata type is like a C++ class instance.
Here you have the overhead of the metatable (a bit like a virtual
function table pointer), but you have a powerful mechanism for
overloading the behaviour of the wrapped data type.

If you use light userdata you could use a purely functional interface to
manipulate vectors, e.g.

	v1 = vec_new()
	vec_set(v1, 1,2,3)
	vec_setx(v1, vec_gety(v2)+10)

If you use heavy userdata you could set up an OO style of manipulation.
E.g.

	v1 = Vector:new()
	v1:set(1,2,3)
	v1.x = v2.y + 10

You could write the above using a metatable which could just wrap the
functional interface. If you have lots vectors you may not want the
overhead of all the meta-mechanism stuff (I'm not sure what the overhead
is TBH). 

You could have a hybrid where you where a heavy userdata type which is a
pointer to a vector and you feed it a light userdata vector. The wrapper
gives it OO features but the data is light. You could reuse the wrapper
for each vector operation, rather

	v1 = vec_new()    	-- light
	hv1 = Vector:new()	-- vector wrapper
	hv1:setPointer(v1)	-- set light ptr in wrapper
	hv1:set(1,2,3)
	hv1:normalize()
	v2 = vec_new()		-- new light
	hv1:setPointer(v2)  	-- reuse wrapper
	hv1:set(8,7,6)
	hv1:dot(v1)

Using this optimisation is a useful general way of saving object
creations and deletions if you are passing wrapped data type parameters
back into C a lot, e.g. colour, position, object state. You create an
object (e.g. instance of bound colour class) which you set the values in
and pass a reference to C, rather than (what you might do in C++) use a
constructor to format the data and pass by reference - then the object
is deleted (read wasteful). You just keep the colour "utility/parameter
passing instance" around indefinitely.

Another way to add vectors would be to hack the Lua VM and add a new
data type. This seems a little pointless as Lua is so geared to
customisation. 

It's probably easiest to set up your system as much as you can in Lua
script and then when you're happy code elements using the C API as
certain actions should be quicker. The other thing to consider is that
you could run the development version of the game with all the scripts
in sandboxes which raise errors if something improper is done, which you
could turn off in the release build - which may give you a significant
speedup. I think when we turned off (tolua generated binding code using
lauxlib) typechecking in our Lua powered GUI we got something like a 30%
speedup.

Nick