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

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