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

Last change on this file since 198 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
Line 
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"
8
9#include "nv/lua/lua_raw.hh"
10#include "nv/string.hh"
11#include "nv/random.hh"
12
13static size_t nlua_swizzel_lookup[256];
14
15inline bool nlua_is_swizzel( const unsigned char* str, size_t max )
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 {
27        static inline T unit() { return T(); }
28        static inline T construct( lua_State*, int ) {
29                return T();
30        }
31};
32
33template < typename T > struct nlua_vec_constructor< T, 1 > {
34        static inline T unit() { return T( 1 ); }
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 > {
41        static inline T unit() { return T( 1, 1 ); }
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 > {
51        static inline T unit() { return T( 1, 1, 1 ); }
52        static inline T construct( lua_State* L, int index ) {
53                typedef glm::detail::tvec2<typename T::value_type> vec2;
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 > {
72        static inline T unit() { return T( 1, 1, 1, 1 ); }
73        static inline T construct( lua_State* L, int index ) {
74                typedef glm::detail::tvec2<typename T::value_type> vec2;
75                typedef glm::detail::tvec3<typename T::value_type> vec3;
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{
116        nlua_push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 1 ) );
117        return 1;
118}
119
120template< typename T >
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 >
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 >
135int nlua_vec_call( lua_State* L )
136{
137        nlua_push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 2 ) );
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 )
152                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) + nlua_to_vec<T>( L, 2 ) );
153        else
154                if ( lua_type( L, 2 ) == LUA_TNUMBER )
155                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + (typename T::value_type)(lua_tonumber( L, 2 )) );
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 )
165                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) - nlua_to_vec<T>( L, 2 ) );
166        else
167                if ( lua_type( L, 2 ) == LUA_TNUMBER )
168                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - (typename T::value_type)(lua_tonumber( L, 2 )) );
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 )
178                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) * nlua_to_vec<T>( L, 2 ) );
179        else
180                if ( lua_type( L, 2 ) == LUA_TNUMBER )
181                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * (typename T::value_type)(lua_tonumber( L, 2 )) );
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 )
191                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) / nlua_to_vec<T>( L, 2 ) );
192        else
193                if ( lua_type( L, 2 ) == LUA_TNUMBER )
194                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / (typename T::value_type)(lua_tonumber( L, 2 )) );
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();
224        const unsigned char * key = (const unsigned char *)( lua_tolstring( L, 2, &len ) );
225        size_t idx = 255;
226
227        if ( len == 1 )
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) {
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;
242                default: break;
243                }
244        }
245
246        luaL_getmetafield( L, 1, "__functions" );
247        lua_pushvalue( L, 2 );
248        lua_rawget( L, -2 );
249        return 1;
250}
251
252template< typename T >
253int nlua_vec_newindex( lua_State* L )
254{
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;
258
259        T* v = nlua_to_pvec<T>( L, 1 );
260        size_t len  = 0;
261        size_t vlen = v->length();
262        const unsigned char * key = (const unsigned char *)( lua_tolstring( L, 2, &len ) );
263        size_t idx = 255;
264        if( len == 1 )
265        {
266                idx = nlua_swizzel_lookup[ key[ 0 ] ];
267                if ( idx < vlen )
268                {
269                        (*v)[idx] = (typename T::value_type)luaL_checknumber( L, 3 );
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{
303        static const struct luaL_Reg nlua_vec_sf [] = {
304                { "new",            nlua_vec_new<T> },
305                { "random",         nlua_vec_random<T> },
306                {NULL, NULL}
307        };
308
309        static const struct luaL_Reg nlua_vec_f [] = {
310                { "clone",          nlua_vec_clone<T> },
311                { "get",            nlua_vec_get<T> },
312                { "tostring",       nlua_vec_tostring<T> },
313                {NULL, NULL}
314        };
315
316        static const struct luaL_Reg nlua_vec_sm [] = {
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
334        luaL_newmetatable( L, nlua_metatable_name<T>() );
335        nlua_register( L, nlua_vec_m, -1 );
336        lua_createtable( L, 0, 0 );
337        nlua_register( L, nlua_vec_f, -1 );
338        lua_setfield(L, -2, "__functions" );
339        lua_pop( L, 1 );
340
341        lua_createtable( L, 0, 0 );
342        nlua_register( L, nlua_vec_sf, -1 );
343        lua_createtable( L, 0, 0 );
344        nlua_register( L, nlua_vec_sm, -1 );
345        lua_setmetatable( L, -2 );
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" );
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;
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;
374        int stack = lua_gettop( L );
375
376        luaL_requiref(L, "coord", luaopen_vec<nv::ivec2>, 1);
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);
383        lua_settop( L, stack );
384}
385
Note: See TracBrowser for help on using the repository browser.