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

Last change on this file since 546 was 534, checked in by epyon, 8 years ago

CONTINUED:

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