441 lines
10 KiB
C++
441 lines
10 KiB
C++
|
#include "ScriptSystem_Math.h"
|
||
|
|
||
|
#include "Utilities/MersenneTwister.h"
|
||
|
|
||
|
#include <cmath>
|
||
|
|
||
|
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
|