source: trunk/src/lua/lua_math.cc @ 531

Last change on this file since 531 was 529, checked in by epyon, 8 years ago
  • mass update
File size: 13.5 KB
RevLine 
[395]1// Copyright (C) 2012-2015 ChaosForge Ltd
[53]2// http://chaosforge.org/
3//
[395]4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
[53]6
[452]7#include "nv/lua/lua_math.hh"
[85]8
9#include "nv/lua/lua_raw.hh"
[520]10#include "nv/lua/lua_aux.hh"
[385]11#include "nv/stl/type_traits/common.hh"
[53]12
[487]13static size_t nlua_swizzel_lookup[256];
[53]14
[207]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
[487]20inline bool nlua_is_swizzel( const unsigned char* str, size_t max )
[53]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 {
[177]32        static inline T unit() { return T(); }
[121]33        static inline T construct( lua_State*, int ) {
[53]34                return T();
35        }
36};
37
38template < typename T > struct nlua_vec_constructor< T, 1 > {
[177]39        static inline T unit() { return T( 1 ); }
[53]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 > {
[177]46        static inline T unit() { return T( 1, 1 ); }
[53]47        static inline T construct( lua_State* L, int index ) {
48                if ( lua_type( L, index ) == LUA_TUSERDATA )
[207]49                        return to_vec<T>( L, index );
[53]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 > {
[177]56        static inline T unit() { return T( 1, 1, 1 ); }
[53]57        static inline T construct( lua_State* L, int index ) {
[451]58                typedef nv::math::tvec2<typename T::value_type> vec2;
[53]59                if ( lua_type( L, index ) == LUA_TUSERDATA )
60                {
[207]61                        if ( is_vec<T>( L, index ) )
62                                return to_vec<T>( L, index );
[53]63                        else
[207]64                                return T( to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ) );
[53]65                }
66                else
67                {
68                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
[207]69                                return T( lua_tonumber( L, index ), to_vec<vec2>( L, index+1 ) );
[53]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 > {
[177]77        static inline T unit() { return T( 1, 1, 1, 1 ); }
[53]78        static inline T construct( lua_State* L, int index ) {
[451]79                typedef nv::math::tvec2<typename T::value_type> vec2;
80                typedef nv::math::tvec3<typename T::value_type> vec3;
[53]81                if ( lua_type( L, index ) == LUA_TUSERDATA )
82                {
[207]83                        if ( is_vec<T>( L, index ) )
84                                return to_vec<T>( L, index );
[53]85                        else
86                        {
[207]87                                if ( is_vec<vec3>( L, index ) )
88                                        return T( to_vec<vec3>( L, index ), lua_tonumber( L, index + 1 ) );
[53]89                                else
90                                {
91                                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
[207]92                                                return T( to_vec<vec2>( L, index ), to_vec<vec2>( L, index + 1 ) );
[53]93                                        else
[207]94                                                return T( to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
[53]95                                }
96                        }
97                }
98                else
99                {
100                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
101                        {
[207]102                                if ( is_vec<vec3>( L, index+1 ) )
103                                        return T( lua_tonumber( L, index ), to_vec<vec3>( L, index+1 ) );
[53]104                                else
[207]105                                        return T( lua_tonumber( L, index ), to_vec<vec2>( L, index+1 ), lua_tonumber( L, index + 2 ) );
[53]106                        }
107                        else
108                        {
109                                if ( lua_type( L, index+2 ) == LUA_TUSERDATA )
[207]110                                        return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), to_vec<vec2>( L, index+2 ) );
[53]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{
[207]121        push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 1 ) );
[53]122        return 1;
123}
124
125template< typename T >
[177]126int nlua_vec_random( lua_State* L )
127{
[520]128        push_vec<T>( L, nv::lua::rng().range( to_vec<T>( L, 1 ), to_vec<T>( L, 2 ) ) );
[177]129        return 1;
130}
131
132template< typename T >
[174]133int nlua_vec_clone( lua_State* L )
134{
[207]135        push_vec<T>( L, to_vec<T>( L, 1 ) );
[174]136        return 1;
137}
138
139template< typename T >
[529]140int nlua_vec_sign( lua_State* L )
141{
142        push_vec<T>( L, nv::math::sign( to_vec<T>( L, 1 ) ) );
143        return 1;
144}
145
146template< typename T >
[53]147int nlua_vec_call( lua_State* L )
148{
[207]149        push_vec<T>( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 2 ) );
[53]150        return 1;
151}
152
153template< typename T >
154static int nlua_vec_unm( lua_State* L )
155{
[207]156        push_vec<T>( L, -to_vec<T>( L, 1 ) );
[53]157        return 1;
158}
159
160template< typename T >
161int nlua_vec_add( lua_State* L )
162{
[512]163        T v;
[53]164        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[512]165                v = static_cast<typename T::value_type>(lua_tonumber( L, 1 )) + to_vec<T>( L, 2 );
[53]166        else
167                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[512]168                        v = to_vec<T>( L, 1 ) + static_cast<typename T::value_type>( lua_tonumber( L, 2 ) );
[53]169                else
[512]170                        v = to_vec<T>( L, 1 ) + to_vec<T>( L, 2 );
171        push_vec<T>( L, v );
[53]172        return 1;
173}
174
175template< typename T >
176int nlua_vec_sub( lua_State* L )
177{
[512]178        T v;
[53]179        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[512]180                v = static_cast<typename T::value_type>(lua_tonumber( L, 1 )) - to_vec<T>( L, 2 );
[53]181        else
182                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[512]183                        v = to_vec<T>( L, 1 ) - static_cast<typename T::value_type>(lua_tonumber( L, 2 ) );
[53]184                else
[512]185                        v = to_vec<T>( L, 1 ) - to_vec<T>( L, 2 );
186        push_vec<T>( L, v );
[53]187        return 1;
188}
189
190template< typename T >
191int nlua_vec_mul( lua_State* L )
192{
[512]193        T v;
[53]194        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[512]195                v = static_cast<typename T::value_type>(lua_tonumber( L, 1 )) * to_vec<T>( L, 2 );
[53]196        else
197                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[512]198                        v = to_vec<T>( L, 1 ) * static_cast<typename T::value_type>(lua_tonumber( L, 2 ));
[53]199                else
[512]200                        v = to_vec<T>( L, 1 ) * to_vec<T>( L, 2 );
201        push_vec<T>( L, v );
[53]202        return 1;
203}
204
205template< typename T >
206int nlua_vec_div( lua_State* L )
207{
[512]208        T v;
[53]209        if ( lua_type( L, 1 ) == LUA_TNUMBER )
[512]210                v = static_cast<typename T::value_type>(lua_tonumber( L, 1 )) / to_vec<T>( L, 2 );
[53]211        else
212                if ( lua_type( L, 2 ) == LUA_TNUMBER )
[512]213                        v = to_vec<T>( L, 1 ) / static_cast<typename T::value_type>(lua_tonumber( L, 2 ));
[53]214                else
[512]215                        v = to_vec<T>( L, 1 ) / to_vec<T>( L, 2 );
216        push_vec<T>( L, v );
[53]217        return 1;
218}
219
220template< typename T >
221int nlua_vec_eq( lua_State* L )
222{
[207]223        lua_pushboolean( L, to_vec<T>( L, 1 ) == to_vec<T>( L, 2 ) );
[53]224        return 1;
225}
226
227template< typename T >
228int nlua_vec_get( lua_State* L )
229{
[207]230        T v = to_vec<T>( L, 1 );
[471]231        for ( size_t i = 0; i < v.size(); ++i )
[53]232        {
233                lua_pushnumber( L, v[i] );
234        }
[471]235        return v.size();
[53]236}
237
238template< typename T >
239int nlua_vec_index( lua_State* L )
240{
[207]241        T* v = to_pvec<T>( L, 1 );
[53]242        size_t len  = 0;
[471]243        size_t vlen = v->size();
[406]244        const unsigned char * key = reinterpret_cast<const unsigned char *>( lua_tolstring( L, 2, &len ) );
[471]245        size_t idx = 255;
[53]246
[85]247        if ( len == 1 )
[53]248        {
249                idx = nlua_swizzel_lookup[ key[ 0 ] ];
250                if ( idx < vlen )
251                {
252                        lua_pushnumber( L, (*v)[idx] );
253                        return 1;
254                }
255        }
256        else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
257        {
258                switch (len) {
[451]259                case 2 : push_vec( L, nv::math::tvec2<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]] ) ); return 1;
260                case 3 : push_vec( L, nv::math::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;
261                case 4 : push_vec( L, nv::math::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]262                default: break;
263                }
264        }
265
[174]266        luaL_getmetafield( L, 1, "__functions" );
[75]267        lua_pushvalue( L, 2 );
[53]268        lua_rawget( L, -2 );
269        return 1;
270}
271
272template< typename T >
273int nlua_vec_newindex( lua_State* L )
274{
[451]275        typedef nv::math::tvec2<typename T::value_type> vec2;
276        typedef nv::math::tvec3<typename T::value_type> vec3;
277        typedef nv::math::tvec4<typename T::value_type> vec4;
[53]278
[207]279        T* v = to_pvec<T>( L, 1 );
[53]280        size_t len  = 0;
[471]281        size_t vlen = v->size();
[406]282        const unsigned char * key = reinterpret_cast<const unsigned char *>( lua_tolstring( L, 2, &len ) );
[471]283        size_t idx = 255;
[53]284        if( len == 1 )
285        {
286                idx = nlua_swizzel_lookup[ key[ 0 ] ];
287                if ( idx < vlen )
288                {
[406]289                        (*v)[idx] = static_cast<typename T::value_type>( luaL_checknumber( L, 3 ) );
[53]290                        return 0;
291                }
292        }
293        else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
294        {
295                switch (len) {
[487]296                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;
297                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;
298                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;
[53]299                default: break;
300                }
301        }
302        return 0;
303}
304
305template< typename T >
306static int nlua_vec_tostring( lua_State* L )
307{
[207]308        T v = to_vec<T>( L, 1 );
[378]309        bool fl = nv::is_floating_point<typename T::value_type>::value;
[471]310        switch ( v.size() )
[53]311        {
[380]312        case 1: lua_pushfstring( L, ( fl ? "(%f)"          : "(%d)" ),          v[0] ); break;
313        case 2: lua_pushfstring( L, ( fl ? "(%f,%f)"       : "(%d,%d)" ),       v[0], v[1] ); break;
314        case 3: lua_pushfstring( L, ( fl ? "(%f,%f,%f)"    : "(%d,%d,%d)" ),    v[0], v[1], v[2] ); break;
315        case 4: lua_pushfstring( L, ( fl ? "(%f,%f,%f,%f)" : "(%d,%d,%d,%d)" ), v[0], v[1], v[2], v[3] ); break;
[385]316        default:
[378]317                lua_pushliteral( L, "(vector?)" ); break;
[53]318        }
319        return 1;
320}
321
322template< typename T >
323int luaopen_vec( lua_State * L )
324{
[174]325        static const struct luaL_Reg nlua_vec_sf [] = {
326                { "new",            nlua_vec_new<T> },
[177]327                { "random",         nlua_vec_random<T> },
[174]328                {NULL, NULL}
329        };
330
[53]331        static const struct luaL_Reg nlua_vec_f [] = {
[174]332                { "clone",          nlua_vec_clone<T> },
[529]333                { "sign",           nlua_vec_sign<T> },
[53]334                { "get",            nlua_vec_get<T> },
[177]335                { "tostring",       nlua_vec_tostring<T> },
[53]336                {NULL, NULL}
337        };
338
[174]339        static const struct luaL_Reg nlua_vec_sm [] = {
[53]340                { "__call",         nlua_vec_call<T> },
341                {NULL, NULL}
342        };
343
344        static const struct luaL_Reg nlua_vec_m [] = {
345                { "__add",      nlua_vec_add<T> },
346                { "__sub",      nlua_vec_sub<T> },
347                { "__unm",      nlua_vec_unm<T> },
348                { "__mul",      nlua_vec_mul<T> },
349                { "__div",      nlua_vec_div<T> },
350                { "__eq",       nlua_vec_eq<T> },
351                { "__index",    nlua_vec_index<T> },
352                { "__newindex", nlua_vec_newindex<T> },
353                { "__tostring", nlua_vec_tostring<T> },
354                {NULL, NULL}
355        };
356
[449]357        luaL_newmetatable( L, nv::lua::pass_traits<T>::metatable() );
[85]358        nlua_register( L, nlua_vec_m, -1 );
359        lua_createtable( L, 0, 0 );
360        nlua_register( L, nlua_vec_f, -1 );
[174]361        lua_setfield(L, -2, "__functions" );
362        lua_pop( L, 1 );
363
[85]364        lua_createtable( L, 0, 0 );
[174]365        nlua_register( L, nlua_vec_sf, -1 );
366        lua_createtable( L, 0, 0 );
367        nlua_register( L, nlua_vec_sm, -1 );
[53]368        lua_setmetatable( L, -2 );
[177]369
[207]370        nv::lua::detail::push_vec( L, T() );
[177]371        lua_setfield( L, -2, "ZERO" );
[207]372        nv::lua::detail::push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::unit() );
[177]373        lua_setfield( L, -2, "UNIT" );
[53]374        return 1;
375}
376
[503]377template < typename T >
378void nlua_rtti_vec_push( nv::lua::state* state, const nv::type_entry*, void* object )
379{
380        T* value = reinterpret_cast<T*>( object );
381        push_vec<T>( state->get_raw(), *value );
382}
383
384template < typename T >
385bool nlua_rtti_vec_read( nv::lua::state* state, const nv::type_entry*, void* object, int index )
386{
387        T* value = reinterpret_cast<T*>( object );
388        int type = lua_type( state->get_raw(), index );
389        if ( type == LUA_TUSERDATA )
390        {
391                T* from = to_pvec<T>( state->get_raw(), index );
392                if ( !from ) return false;
393                *value = *from;
394        }
395//      else if ( type == LUA_TTABLE )
396//      {
397//
398//      }
399        else
400                return false;
401        int todo; int table_constructor;
402        return true;
403}
404
405void nv::lua::register_math( lua::state* state )
[53]406{
407        for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
[369]408        using nv::uchar8;
409        nlua_swizzel_lookup[uchar8( 'x' )] = 0;
410        nlua_swizzel_lookup[uchar8( 'r' )] = 0;
411        nlua_swizzel_lookup[uchar8( 's' )] = 0;
412        nlua_swizzel_lookup[uchar8( '0' )] = 0;
413        nlua_swizzel_lookup[uchar8( 'y' )] = 1;
414        nlua_swizzel_lookup[uchar8( 'g' )] = 1;
415        nlua_swizzel_lookup[uchar8( 't' )] = 0;
416        nlua_swizzel_lookup[uchar8( '1' )] = 1;
417        nlua_swizzel_lookup[uchar8( 'z' )] = 2;
418        nlua_swizzel_lookup[uchar8( 'b' )] = 2;
419        nlua_swizzel_lookup[uchar8( 'u' )] = 0;
420        nlua_swizzel_lookup[uchar8( '2' )] = 2;
421        nlua_swizzel_lookup[uchar8( 'w' )] = 3;
422        nlua_swizzel_lookup[uchar8( 'a' )] = 3;
423        nlua_swizzel_lookup[uchar8( 'v' )] = 0;
424        nlua_swizzel_lookup[uchar8( '3' )] = 3;
[503]425
426        lua_State* L = state->get_raw();
[74]427        int stack = lua_gettop( L );
[75]428
[490]429        nlua_requiref(L, "coord", luaopen_vec<nv::ivec2>, 1);
430        nlua_requiref(L, "ivec2", luaopen_vec<nv::ivec2>, 1);
431        nlua_requiref(L, "ivec3", luaopen_vec<nv::ivec3>, 1);
432        nlua_requiref(L, "ivec4", luaopen_vec<nv::ivec4>, 1);
433        nlua_requiref(L, "vec2", luaopen_vec<nv::vec2>, 1);
434        nlua_requiref(L, "vec3", luaopen_vec<nv::vec3>, 1);
435        nlua_requiref(L, "vec4", luaopen_vec<nv::vec4>, 1);
[74]436        lua_settop( L, stack );
[503]437
438        state->register_rtti_type< nv::ivec2 >( nlua_rtti_vec_push<nv::ivec2>, nlua_rtti_vec_read<nv::ivec2> );
439        state->register_rtti_type< nv::ivec3 >( nlua_rtti_vec_push<nv::ivec3>, nlua_rtti_vec_read<nv::ivec3> );
440        state->register_rtti_type< nv::ivec4 >( nlua_rtti_vec_push<nv::ivec4>, nlua_rtti_vec_read<nv::ivec4> );
441        state->register_rtti_type< nv::vec2 > ( nlua_rtti_vec_push<nv::vec2>,  nlua_rtti_vec_read<nv::vec2> );
442        state->register_rtti_type< nv::vec3 > ( nlua_rtti_vec_push<nv::vec3>,  nlua_rtti_vec_read<nv::vec3> );
443        state->register_rtti_type< nv::vec4 > ( nlua_rtti_vec_push<nv::vec4>,  nlua_rtti_vec_read<nv::vec4> );
[53]444}
445
Note: See TracBrowser for help on using the repository browser.