#include "ScriptSystem_Math.h" #include "Utilities/MersenneTwister.h" #include namespace BlueCore { static MTRand mtrand; //------------------------------------------------------------------------------ static SQInteger _sin(HSQUIRRELVM v) { SQFloat f; sq_getfloat (v, 2, &f ); sq_pushfloat (v, ( SQFloat ) sin (f ) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _cos(HSQUIRRELVM v) { SQFloat f; sq_getfloat (v, 2, &f ); sq_pushfloat (v, ( SQFloat ) cos (f ) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _tan(HSQUIRRELVM v) { SQFloat f; sq_getfloat (v, 2, &f ); sq_pushfloat (v, ( SQFloat ) tan (f ) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _sqrt(HSQUIRRELVM v) { SQFloat f; sq_getfloat (v, 2, &f ); sq_pushfloat (v, ( SQFloat ) sqrt (f ) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _trunc(HSQUIRRELVM v) { SQFloat f; sq_getfloat (v, 2, &f ); sq_pushfloat (v, ( SQFloat ) f - fmod(f, 1.0) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _floor(HSQUIRRELVM v) { SQFloat f; sq_getfloat (v, 2, &f ); sq_pushfloat (v, ( SQFloat ) floor (f ) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _ceil(HSQUIRRELVM v) { SQFloat f; sq_getfloat (v, 2, &f ); sq_pushfloat (v, ( SQFloat ) ceil (f ) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _rand(HSQUIRRELVM v) { sq_pushfloat (v, mtrand.rand() ); return 1; } //------------------------------------------------------------------------------ static SQInteger _seed_rand(HSQUIRRELVM v) { SQInteger seed; sq_getinteger(v, 2, &seed ); mtrand.seed(seed ); return 0; } //------------------------------------------------------------------------------ static void _setup_basic_math (HSQUIRRELVM vm) { sq_pushroottable (vm); sq_pushstring (vm, "sin", -1); sq_newclosure (vm, _sin, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); sq_pushstring (vm, "cos", -1); sq_newclosure (vm, _cos, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); sq_pushstring (vm, "tan", -1); sq_newclosure (vm, _tan, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); sq_pushstring (vm, "sqrt", -1); sq_newclosure (vm, _sqrt, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); sq_pushstring (vm, "trunc", -1); sq_newclosure (vm, _trunc, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); sq_pushstring (vm, "floor", -1); sq_newclosure (vm, _floor, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); sq_pushstring (vm, "ceil", -1); sq_newclosure (vm, _ceil, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); sq_pushstring (vm, "rand", -1); sq_newclosure (vm, _rand, 0); sq_setparamscheck (vm, 1, "."); sq_newslot (vm, -3, false); sq_pushstring (vm, "seed_rand", -1); sq_newclosure (vm, _seed_rand, 0); sq_setparamscheck (vm, 2, ".n"); sq_newslot (vm, -3, false); // pop the root table sq_pop (vm, 1); } //------------------------------------------------------------------------------ static SQInteger _vector__add ( HSQUIRRELVM v ) { SQFloat ax, ay, az; SQFloat bx = 0.0, by = 0.0, bz = 0.0; _getvectorvalues ( v, 1, ax, ay, az ); _getvectorvalues ( v, 2, bx, by, bz ); _pushvector ( v, ax + bx, ay + by, az + bz ); return 1; } //------------------------------------------------------------------------------ static SQInteger _vector__sub ( HSQUIRRELVM v ) { SQFloat ax, ay, az; SQFloat bx = 0.0, by = 0.0, bz = 0.0; _getvectorvalues ( v, 1, ax, ay, az ); _getvectorvalues ( v, 2, bx, by, bz ); _pushvector ( v, ax - bx, ay - by, az - bz ); return 1; } //------------------------------------------------------------------------------ static SQInteger _vector__mul ( HSQUIRRELVM v ) { SQFloat x, y, z, f; _getvectorvalues ( v, 1, x, y, z ); sq_getfloat ( v, 2, &f ); _pushvector ( v, x*f, y*f, z*f ); return 1; } //------------------------------------------------------------------------------ static SQInteger _vector__div ( HSQUIRRELVM v ) { SQFloat x, y, z, f; _getvectorvalues ( v, 1, x, y, z ); sq_getfloat ( v, 2, &f ); _pushvector ( v, x / f, y / f, y / f ); return 1; } //------------------------------------------------------------------------------ static SQInteger _vector_length ( HSQUIRRELVM v ) { SQFloat x, y, z; _getvectorvalues ( v, 1, x, y, z ); sq_pushfloat ( v, std::sqrt ( x*x + y*y + z*z ) ); return 1; } //------------------------------------------------------------------------------ static SQInteger _vector_normalize ( HSQUIRRELVM v ) { SQFloat x, y, z; _getvectorvalues ( v, 1, x, y, z ); SQFloat l = 1 / std::sqrt ( x * x + y * y + z * z ); _setvectorvalues ( v, 1, x*l, y*l, z*l ); return 0; } //------------------------------------------------------------------------------ static SQInteger _vector_constructor ( HSQUIRRELVM v ) { SQFloat x = 0.0; SQFloat y = 0.0; SQFloat z = 0.0; SQInteger argc = sq_gettop ( v ); if ( argc > 1 ) sq_getfloat ( v, 2, &x ); if ( argc > 2 ) sq_getfloat ( v, 3, &y ); if ( argc > 3 ) sq_getfloat ( v, 4, &z ); _setvectorvalues ( v, 1, x, y, z ); return 0; } //------------------------------------------------------------------------------ static void _register_vector_class( HSQUIRRELVM _vm ) { sq_pushroottable ( _vm ); // push class sq_pushstring ( _vm, "Vector", -1 ); if ( SQ_SUCCEEDED ( sq_newclass ( _vm, SQFalse ) ) ) { // register variables sq_pushstring ( _vm, "x", -1 ); sq_pushfloat ( _vm, 0.0 ); sq_newslot ( _vm, -3, false ); sq_pushstring ( _vm, "y", -1 ); sq_pushfloat ( _vm, 0.0 ); sq_newslot ( _vm, -3, false ); sq_pushstring ( _vm, "z", -1 ); sq_pushfloat ( _vm, 0.0 ); sq_newslot ( _vm, -3, false ); // register constructor sq_pushstring ( _vm, "constructor", -1 ); sq_newclosure ( _vm, _vector_constructor, 0 ); sq_newslot ( _vm, -3, false ); // register _add sq_pushstring ( _vm, "_add", -1 ); sq_newclosure ( _vm, _vector__add, 0 ); sq_newslot ( _vm, -3, false ); // register _sub sq_pushstring ( _vm, "_sub", -1 ); sq_newclosure ( _vm, _vector__sub, 0 ); sq_newslot ( _vm, -3, false ); // register _mul sq_pushstring ( _vm, "_mul", -1 ); sq_newclosure ( _vm, _vector__mul, 0 ); sq_newslot ( _vm, -3, false ); // register _div sq_pushstring ( _vm, "_div", -1 ); sq_newclosure ( _vm, _vector__div, 0 ); sq_newslot ( _vm, -3, false ); // register length sq_pushstring ( _vm, "length", -1 ); sq_newclosure ( _vm, _vector_length, 0 ); sq_newslot ( _vm, -3, false ); // register normalize sq_pushstring ( _vm, "normalize", -1 ); sq_newclosure ( _vm, _vector_normalize, 0 ); sq_newslot ( _vm, -3, false ); // create_vector class sq_newslot ( _vm, -3, false ); } sq_poptop ( _vm ); } //------------------------------------------------------------------------------ static SQInteger _quaternion_constructor ( HSQUIRRELVM v ) { SQFloat w = 0.0; SQFloat x = 0.0; SQFloat y = 0.0; SQFloat z = 0.0; SQInteger argc = sq_gettop ( v ); if ( argc > 1 ) sq_getfloat ( v, 2, &w ); if ( argc > 2 ) sq_getfloat ( v, 3, &x ); if ( argc > 3 ) sq_getfloat ( v, 4, &y ); if ( argc > 4 ) sq_getfloat ( v, 5, &z ); _setquaternionvalues ( v, 1, w, x, y, z ); return 0; } //------------------------------------------------------------------------------ static SQInteger _quaternion_apply ( HSQUIRRELVM vm ) { SQFloat qw, qx, qy, qz; SQFloat vx, vy, vz; _getquaternionvalues ( vm, 1, qw, qx, qy, qz ); _getvectorvalues ( vm, 2, vx, vy, vz ); SQFloat xx = qx*qx, xy = qx*qy, xz = qx*qz, xw = qx*qw, yy = qy*qy, yz = qy*qz, yw = qy*qw, zz = qz*qz, zw = qz*qw; SQFloat rx = 2.0 * (vx * (0.5 - yy - zz) + vy * (xy - zw) + vz * (xz + yw)); SQFloat ry = 2.0 * (vx * (xy + zw) + vy * (0.5 - xx - zz) + vz * (yz - xw)); SQFloat rz = 2.0 * (vx * (xz - yw) + vy * (yz + xw) + vz * (0.5 - xx - yy)); _pushvector ( vm, rx, ry, rz ); return 1; } //------------------------------------------------------------------------------ static SQInteger _quaternion_applyinversed ( HSQUIRRELVM vm ) { SQFloat qw, qx, qy, qz; SQFloat vx, vy, vz; _getquaternionvalues ( vm, 1, qw, qx, qy, qz ); _getvectorvalues ( vm, 2, vx, vy, vz ); SQFloat xx = qx*qx, xy = qx*qy, xz = qx*qz, xw = -qx*qw, yy = qy*qy, yz = qy*qz, yw = -qy*qw, zz = qz*qz, zw = -qz*qw; SQFloat rx = 2.0 * (vx * (0.5 - yy - zz) + vy * (xy - zw) + vz * (xz + yw)); SQFloat ry = 2.0 * (vx * (xy + zw) + vy * (0.5 - xx - zz) + vz * (yz - xw)); SQFloat rz = 2.0 * (vx * (xz - yw) + vy * (yz + xw) + vz * (0.5 - xx - yy)); _pushvector ( vm, rx, ry, rz ); return 1; } //------------------------------------------------------------------------------ static void _register_quaternion_class (HSQUIRRELVM vm) { sq_pushroottable ( vm ); // push class sq_pushstring ( vm, "Quaternion", -1 ); if ( SQ_SUCCEEDED ( sq_newclass ( vm, SQFalse ) ) ) { // register variables sq_pushstring ( vm, "w", -1 ); sq_pushfloat ( vm, 0.0 ); sq_newslot ( vm, -3, false ); sq_pushstring ( vm, "x", -1 ); sq_pushfloat ( vm, 0.0 ); sq_newslot ( vm, -3, false ); sq_pushstring ( vm, "y", -1 ); sq_pushfloat ( vm, 0.0 ); sq_newslot ( vm, -3, false ); sq_pushstring ( vm, "z", -1 ); sq_pushfloat ( vm, 0.0 ); sq_newslot ( vm, -3, false ); // register constructor sq_pushstring ( vm, "constructor", -1 ); sq_newclosure ( vm, _quaternion_constructor, 0 ); sq_newslot ( vm, -3, false ); sq_pushstring ( vm, "apply", -1 ); sq_newclosure ( vm, _quaternion_apply, 0 ); sq_newslot ( vm, -3, false ); sq_pushstring ( vm, "applyInversed", -1 ); sq_newclosure ( vm, _quaternion_applyinversed, 0 ); sq_newslot ( vm, -3, false ); // create_vector class sq_newslot ( vm, -3, false ); } sq_poptop ( vm ); } //------------------------------------------------------------------------------ void setupScriptSystem_Math (ScriptSystem* scriptsystem) { if (scriptsystem == 0) return; HSQUIRRELVM vm = scriptsystem->getVM(); if (vm) { _setup_basic_math (vm); _register_vector_class(vm); _register_quaternion_class(vm); } } } // namespace BlueCore