source: trunk/src/lua/lua_glm.cc @ 177

Last change on this file since 177 was 177, checked in by epyon, 12 years ago
  • common - added narrow_cast (to be expanded)
  • lua/glm - added random coord constructor and UNIT/ZERO constants for each vector class
File size: 11.6 KB
RevLine 
[53]1// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6
7#include "nv/lua/lua_glm.hh"
[85]8
9#include "nv/lua/lua_raw.hh"
[53]10#include "nv/string.hh"
[177]11#include "nv/random.hh"
[53]12
13static size_t nlua_swizzel_lookup[256];
14
[121]15inline bool nlua_is_swizzel( const unsigned char* str, size_t max )
[53]16{
17        while (*str)
18        {
19                if (nlua_swizzel_lookup[*str] > max) return false;
20                str++;
21        }
22        return true;
23}
24
25template < typename T, size_t k >
26struct nlua_vec_constructor {
[177]27        static inline T unit() { return T(); }
[121]28        static inline T construct( lua_State*, int ) {
[53]29                return T();
30        }
31};
32
33template < typename T > struct nlua_vec_constructor< T, 1 > {
[177]34        static inline T unit() { return T( 1 ); }
[53]35        static inline T construct( lua_State* L, int index ) {
36                return T( lua_tonumber( L, index ) );
37        }
38};
39
40template < typename T > struct nlua_vec_constructor< T, 2 > {
[177]41        static inline T unit() { return T( 1, 1 ); }
[53]42        static inline T construct( lua_State* L, int index ) {
43                if ( lua_type( L, index ) == LUA_TUSERDATA )
44                        return nlua_to_vec<T>( L, index );
45                else
46                        return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ) );
47        }
48};
49
50template < typename T > struct nlua_vec_constructor< T, 3 > {
[177]51        static inline T unit() { return T( 1, 1, 1 ); }
[53]52        static inline T construct( lua_State* L, int index ) {
[113]53                typedef glm::detail::tvec2<typename T::value_type> vec2;
[53]54                if ( lua_type( L, index ) == LUA_TUSERDATA )
55                {
56                        if ( nlua_is_vec<T>( L, index ) )
57                                return nlua_to_vec<T>( L, index );
58                        else
59                                return T( nlua_to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ) );
60                }
61                else
62                {
63                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
64                                return T( lua_tonumber( L, index ), nlua_to_vec<vec2>( L, index+1 ) );
65                        else
66                                return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
67                }
68        }
69};
70
71template < typename T > struct nlua_vec_constructor< T, 4 > {
[177]72        static inline T unit() { return T( 1, 1, 1, 1 ); }
[53]73        static inline T construct( lua_State* L, int index ) {
[113]74                typedef glm::detail::tvec2<typename T::value_type> vec2;
75                typedef glm::detail::tvec3<typename T::value_type> vec3;
[53]76                if ( lua_type( L, index ) == LUA_TUSERDATA )
77                {
78                        if ( nlua_is_vec<T>( L, index ) )
79                                return nlua_to_vec<T>( L, index );
80                        else
81                        {
82                                if ( nlua_is_vec<vec3>( L, index ) )
83                                        return T( nlua_to_vec<vec3>( L, index ), lua_tonumber( L, index + 1 ) );
84                                else
85                                {
86                                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
87                                                return T( nlua_to_vec<vec2>( L, index ), nlua_to_vec<vec2>( L, index + 1 ) );
88                                        else
89                                                return T( nlua_to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
90                                }
91                        }
92                }
93                else
94                {
95                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
96                        {
97                                if ( nlua_is_vec<vec3>( L, index+1 ) )
98                                        return T( lua_tonumber( L, index ), nlua_to_vec<vec3>( L, index+1 ) );
99                                else
100                                        return T( lua_tonumber( L, index ), nlua_to_vec<vec2>( L, index+1 ), lua_tonumber( L, index + 2 ) );
101                        }
102                        else
103                        {
104                                if ( lua_type( L, index+2 ) == LUA_TUSERDATA )
105                                        return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), nlua_to_vec<vec2>( L, index+2 ) );
106                                else
107                                        return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ), lua_tonumber( L, index + 3 ) );
108                        }
109                }
110        }
111};
112
113template< typename T >
114int nlua_vec_new( lua_State* L )
115{
[174]116        nlua_push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 1 ) );
[53]117        return 1;
118}
119
120template< typename T >
[177]121int nlua_vec_random( lua_State* L )
122{
123        nlua_push_vec<T>( L, nv::random::get().range( nlua_to_vec<T>( L, 1 ), nlua_to_vec<T>( L, 2 ) ) );
124        return 1;
125}
126
127template< typename T >
[174]128int nlua_vec_clone( lua_State* L )
129{
130        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) );
131        return 1;
132}
133
134template< typename T >
[53]135int nlua_vec_call( lua_State* L )
136{
[174]137        nlua_push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 2 ) );
[53]138        return 1;
139}
140
141template< typename T >
142static int nlua_vec_unm( lua_State* L )
143{
144        nlua_push_vec<T>( L, -nlua_to_vec<T>( L, 1 ) );
145        return 1;
146}
147
148template< typename T >
149int nlua_vec_add( lua_State* L )
150{
151        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[113]152                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) + nlua_to_vec<T>( L, 2 ) );
[53]153        else
154                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[113]155                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + (typename T::value_type)(lua_tonumber( L, 2 )) );
[53]156                else
157                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + nlua_to_vec<T>( L, 2 ) );
158        return 1;
159}
160
161template< typename T >
162int nlua_vec_sub( lua_State* L )
163{
164        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[113]165                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) - nlua_to_vec<T>( L, 2 ) );
[53]166        else
167                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[113]168                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - (typename T::value_type)(lua_tonumber( L, 2 )) );
[53]169                else
170                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - nlua_to_vec<T>( L, 2 ) );
171        return 1;
172}
173
174template< typename T >
175int nlua_vec_mul( lua_State* L )
176{
177        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[113]178                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) * nlua_to_vec<T>( L, 2 ) );
[53]179        else
180                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[113]181                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * (typename T::value_type)(lua_tonumber( L, 2 )) );
[53]182                else
183                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * nlua_to_vec<T>( L, 2 ) );
184        return 1;
185}
186
187template< typename T >
188int nlua_vec_div( lua_State* L )
189{
190        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[113]191                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) / nlua_to_vec<T>( L, 2 ) );
[53]192        else
193                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[113]194                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / (typename T::value_type)(lua_tonumber( L, 2 )) );
[53]195                else
196                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / nlua_to_vec<T>( L, 2 ) );
197        return 1;
198}
199
200template< typename T >
201int nlua_vec_eq( lua_State* L )
202{
203        lua_pushboolean( L, nlua_to_vec<T>( L, 1 ) == nlua_to_vec<T>( L, 2 ) );
204        return 1;
205}
206
207template< typename T >
208int nlua_vec_get( lua_State* L )
209{
210        T v = nlua_to_vec<T>( L, 1 );
211        for ( size_t i = 0; i < v.length(); ++i )
212        {
213                lua_pushnumber( L, v[i] );
214        }
215        return v.length();
216}
217
218template< typename T >
219int nlua_vec_index( lua_State* L )
220{
221        T* v = nlua_to_pvec<T>( L, 1 );
222        size_t len  = 0;
223        size_t vlen = v->length();
[121]224        const unsigned char * key = (const unsigned char *)( lua_tolstring( L, 2, &len ) );
[53]225        size_t idx = 255;
226
[85]227        if ( len == 1 )
[53]228        {
229                idx = nlua_swizzel_lookup[ key[ 0 ] ];
230                if ( idx < vlen )
231                {
232                        lua_pushnumber( L, (*v)[idx] );
233                        return 1;
234                }
235        }
236        else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
237        {
238                switch (len) {
[113]239                case 2 : nlua_push_vec( L, glm::detail::tvec2<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]] ) ); return 1;
240                case 3 : nlua_push_vec( L, glm::detail::tvec3<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]] ) ); return 1;
241                case 4 : nlua_push_vec( L, glm::detail::tvec4<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]], (*v)[nlua_swizzel_lookup[key[3]]] ) ); return 1;
[53]242                default: break;
243                }
244        }
245
[174]246        luaL_getmetafield( L, 1, "__functions" );
[75]247        lua_pushvalue( L, 2 );
[53]248        lua_rawget( L, -2 );
249        return 1;
250}
251
252template< typename T >
253int nlua_vec_newindex( lua_State* L )
254{
[113]255        typedef glm::detail::tvec2<typename T::value_type> vec2;
256        typedef glm::detail::tvec3<typename T::value_type> vec3;
257        typedef glm::detail::tvec4<typename T::value_type> vec4;
[53]258
259        T* v = nlua_to_pvec<T>( L, 1 );
260        size_t len  = 0;
261        size_t vlen = v->length();
[121]262        const unsigned char * key = (const unsigned char *)( lua_tolstring( L, 2, &len ) );
[53]263        size_t idx = 255;
264        if( len == 1 )
265        {
266                idx = nlua_swizzel_lookup[ key[ 0 ] ];
267                if ( idx < vlen )
268                {
[113]269                        (*v)[idx] = (typename T::value_type)luaL_checknumber( L, 3 );
[53]270                        return 0;
271                }
272        }
273        else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
274        {
275                switch (len) {
276                case 2 : { vec2 v2 = nlua_to_vec<vec2>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v2[i]; } return 0;
277                case 3 : { vec3 v3 = nlua_to_vec<vec3>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v3[i]; } return 0;
278                case 4 : { vec4 v4 = nlua_to_vec<vec4>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v4[i]; } return 0;
279                default: break;
280                }
281        }
282        return 0;
283}
284
285template< typename T >
286static int nlua_vec_tostring( lua_State* L )
287{
288        T v = nlua_to_vec<T>( L, 1 );
289        std::string s = "(";
290        for ( size_t i = 0; i < v.length(); ++i )
291        {
292                if (i > 0) s += ",";
293                s += nv::to_string(v[i]);
294        }
295        s+=")";
296        lua_pushstring( L, s.c_str() );
297        return 1;
298}
299
300template< typename T >
301int luaopen_vec( lua_State * L )
302{
[174]303        static const struct luaL_Reg nlua_vec_sf [] = {
304                { "new",            nlua_vec_new<T> },
[177]305                { "random",         nlua_vec_random<T> },
[174]306                {NULL, NULL}
307        };
308
[53]309        static const struct luaL_Reg nlua_vec_f [] = {
[174]310                { "clone",          nlua_vec_clone<T> },
[53]311                { "get",            nlua_vec_get<T> },
[177]312                { "tostring",       nlua_vec_tostring<T> },
[53]313                {NULL, NULL}
314        };
315
[174]316        static const struct luaL_Reg nlua_vec_sm [] = {
[53]317                { "__call",         nlua_vec_call<T> },
318                {NULL, NULL}
319        };
320
321        static const struct luaL_Reg nlua_vec_m [] = {
322                { "__add",      nlua_vec_add<T> },
323                { "__sub",      nlua_vec_sub<T> },
324                { "__unm",      nlua_vec_unm<T> },
325                { "__mul",      nlua_vec_mul<T> },
326                { "__div",      nlua_vec_div<T> },
327                { "__eq",       nlua_vec_eq<T> },
328                { "__index",    nlua_vec_index<T> },
329                { "__newindex", nlua_vec_newindex<T> },
330                { "__tostring", nlua_vec_tostring<T> },
331                {NULL, NULL}
332        };
333
[75]334        luaL_newmetatable( L, nlua_metatable_name<T>() );
[85]335        nlua_register( L, nlua_vec_m, -1 );
336        lua_createtable( L, 0, 0 );
337        nlua_register( L, nlua_vec_f, -1 );
[174]338        lua_setfield(L, -2, "__functions" );
339        lua_pop( L, 1 );
340
[85]341        lua_createtable( L, 0, 0 );
[174]342        nlua_register( L, nlua_vec_sf, -1 );
343        lua_createtable( L, 0, 0 );
344        nlua_register( L, nlua_vec_sm, -1 );
[53]345        lua_setmetatable( L, -2 );
[177]346
347        nlua_push_vec( L, T() );
348        lua_setfield( L, -2, "ZERO" );
349        nlua_push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::unit() );
350        lua_setfield( L, -2, "UNIT" );
[53]351        return 1;
352}
353
354void nlua_register_glm( lua_State* L )
355{
356        for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
[121]357        using nv::char8;
358        nlua_swizzel_lookup[char8( 'x' )] = 0;
359        nlua_swizzel_lookup[char8( 'r' )] = 0;
360        nlua_swizzel_lookup[char8( 's' )] = 0;
361        nlua_swizzel_lookup[char8( '0' )] = 0;
362        nlua_swizzel_lookup[char8( 'y' )] = 1;
363        nlua_swizzel_lookup[char8( 'g' )] = 1;
364        nlua_swizzel_lookup[char8( 't' )] = 0;
365        nlua_swizzel_lookup[char8( '1' )] = 1;
366        nlua_swizzel_lookup[char8( 'z' )] = 2;
367        nlua_swizzel_lookup[char8( 'b' )] = 2;
368        nlua_swizzel_lookup[char8( 'u' )] = 0;
369        nlua_swizzel_lookup[char8( '2' )] = 2;
370        nlua_swizzel_lookup[char8( 'w' )] = 3;
371        nlua_swizzel_lookup[char8( 'a' )] = 3;
372        nlua_swizzel_lookup[char8( 'v' )] = 0;
373        nlua_swizzel_lookup[char8( '3' )] = 3;
[74]374        int stack = lua_gettop( L );
[75]375
[172]376        luaL_requiref(L, "coord", luaopen_vec<nv::ivec2>, 1);
[121]377        luaL_requiref(L, "ivec2", luaopen_vec<nv::ivec2>, 1);
378        luaL_requiref(L, "ivec3", luaopen_vec<nv::ivec3>, 1);
379        luaL_requiref(L, "ivec4", luaopen_vec<nv::ivec4>, 1);
380        luaL_requiref(L, "vec2", luaopen_vec<nv::vec2>, 1);
381        luaL_requiref(L, "vec3", luaopen_vec<nv::vec3>, 1);
382        luaL_requiref(L, "vec4", luaopen_vec<nv::vec4>, 1);
[74]383        lua_settop( L, stack );
[53]384}
385
Note: See TracBrowser for help on using the repository browser.