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

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