bluecore/engine/ScriptSystem_Math.cpp

441 line
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