/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include #include "script_squirrel/cobject/vector_decl.h" #include "script_squirrel/cobject/matrix_decl.h" #include "math/matrix4.h" #include "math/matrix3.h" #include "math/vector.h" #include "log/log.h" using namespace GS; #ifndef _T #define _T #endif _IMPL_NATIVE_CONSTRUCTION(Vector, Vector4); //------------------------------------------------------------------------------ _MEMBER_FUNCTION_IMPL(Vector, constructor) Vector4 temp; int nparams = sa.GetParamCount(); switch (nparams) { case 1: temp.Set(); break; case 2: if (sa.GetType(2) == OT_INSTANCE) { _GetTypedParam(vec, 2, Vector4, Vector); if (vec) temp = *vec; else return sa.ThrowError("Vector() invalid instance type"); } else temp.Set(sa.GetFloat(2)); break; case 3: temp.Set(sa.GetFloat(2), sa.GetFloat(3)); break; case 4: temp.Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4)); break; case 5: temp.Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5)); break; default: return sa.ThrowError("Vector wrong parameters"); } return construct_Vector(v, new Vector4(temp)); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, _cloned) _GetTypedParam(vec, 2, Vector4, Vector); return construct_Vector(v, new Vector4(*vec)); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, _set) _GetSelf(Vector4, Vector); const SQChar *s = sa.GetString(2); int index = s ? s[0] : sa.GetInt(2); switch (index) { case 0: case 'x': case 'r': return sa.Return(self->x = sa.GetFloat(3)); case 1: case 'y': case 'g': return sa.Return(self->y = sa.GetFloat(3)); case 2: case 'z': case 'b': return sa.Return(self->z = sa.GetFloat(3)); case 3: case 'w': case 'a': return sa.Return(self->w = sa.GetFloat(3)); } return SQ_ERROR; _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, _get) _GetSelf(Vector4, Vector); const SQChar *s = sa.GetString(2); if (s && (s[1] != 0)) return SQ_ERROR; int index = s && (s[1] == 0) ? s[0] : sa.GetInt(2); switch (index) { case 0: case 'x': case 'r': return sa.Return(self->x); case 1: case 'y': case 'g': return sa.Return(self->y); case 2: case 'z': case 'b': return sa.Return(self->z); case 3: case 'w': case 'a': return sa.Return(self->w); } return SQ_ERROR; _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, _add) _GetSelf(Vector4, Vector); switch (sa.GetType(2)) { case OT_INSTANCE: { _GetTypedParam(vec, 2, Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self + *vec)) } case OT_FLOAT: _SA_RETURN_OBJECT(new_Vector(v, *self + sa.GetFloat(2))); } return sa.ThrowError("Vector + operator: Invalid argument type.\n"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, _sub) _GetSelf(Vector4, Vector); switch (sa.GetType(2)) { case OT_INSTANCE: { _GetTypedParam(vec, 2, Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self - *vec)); } case OT_FLOAT: _SA_RETURN_OBJECT(new_Vector(v, *self - sa.GetFloat(2))); } return sa.ThrowError("Vector - operator: Invalid argument type.\n"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, _mul) _GetSelf(Vector4, Vector); switch (sa.GetType(2)) { case OT_INSTANCE: { // Vector * Vector. _CHECK_INST_PARAM_RAW(vec, 2, Vector4, Vector); if (vec) _SA_RETURN_OBJECT(new_Vector(v, *self * *vec)); // Vector * Matrix3. _CHECK_INST_PARAM_RAW(m3, 2, Matrix3, Matrix3); if (m3) _SA_RETURN_OBJECT(new_Vector(v, *self * *m3)); // Vector * Matrix4. _CHECK_INST_PARAM_RAW(m4, 2, Matrix4, Matrix4); if (m4) _SA_RETURN_OBJECT(new_Vector(v, *self * *m4)); } break; case OT_INTEGER: _SA_RETURN_OBJECT(new_Vector(v, *self * (float)sa.GetInt(2))); case OT_FLOAT: _SA_RETURN_OBJECT(new_Vector(v, *self * sa.GetFloat(2))); } return sa.ThrowError("Vector * operator: Invalid argument type.\n"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector,_div) _GetSelf(Vector4, Vector); switch (sa.GetType(2)) { case OT_INSTANCE: { _GetTypedParam(vec, 2, Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self / *vec)); } case OT_FLOAT: _SA_RETURN_OBJECT(new_Vector(v, *self / sa.GetFloat(2))); } return sa.ThrowError("Vector / operator: Invalid argument type.\n"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Set) _GetSelf(Vector4, Vector); switch (sa.GetParamCount()) { case 1: self->Set(); break; case 2: self->Set(sa.GetFloat(2)); break; case 3: self->Set(sa.GetFloat(2), sa.GetFloat(3)); break; case 4: self->Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4)); break; case 5: self->Set(sa.GetFloat(2), sa.GetFloat(3), sa.GetFloat(4), sa.GetFloat(5)); break; default: return sa.ThrowError("Vector Set() wrong parameters"); } return 0; _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Dot) _GetSelf(Vector4, Vector); _GetTypedParam(vec, 2, Vector4, Vector); return sa.Return(self->Dot(*vec)); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Cross) _GetSelf(Vector4, Vector); _GetTypedParam(vec, 2, Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, self->Cross(*vec))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, AngleWithVector) _GetSelf(Vector4, Vector); _GetTypedParam(vec, 2, Vector4, Vector); return sa.Return(acosf(Types::Clamp(self->Dot(*vec), -1.f, 1.f))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Reverse) _GetSelf(Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, self->Reversed())); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Dist) _GetSelf(Vector4, Vector); _GetTypedParam(vec, 2, Vector4, Vector); return sa.Return(Vector4::Dist(*self, *vec)); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Dist2) _GetSelf(Vector4, Vector); _GetTypedParam(vec, 2, Vector4, Vector); return sa.Return(Vector4::Dist2(*self, *vec)); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Len) _GetSelf(Vector4, Vector); return sa.Return(self->Len()); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Len2) _GetSelf(Vector4, Vector); return sa.Return(self->Len2()); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, ClampMagnitude) _GetSelf(Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, self->ClampedMagnitude(0, sa.GetFloat(2)))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, clamp) _GetSelf(Vector4, Vector); Vector4 mn, mx; if (sa.GetType(2) == OT_INSTANCE) { _GetTypedParam(_mn, 2, Vector4, Vector); mn = *_mn; } else mn.Set(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2)); if (sa.GetType(3) == OT_INSTANCE) { _GetTypedParam(_mx, 3, Vector4, Vector); mx = *_mx; } else mx.Set(sa.GetFloat(3), sa.GetFloat(3), sa.GetFloat(3)); _SA_RETURN_OBJECT(new_Vector(v, self->Clamped(mn, mx))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, ApplyMatrix) _GetSelf(Vector4, Vector); _CHECK_INST_PARAM_RAW(m3, 2, Matrix3, Matrix3); if (m3) _SA_RETURN_OBJECT(new_Vector(v, *self * *m3)); _CHECK_INST_PARAM_RAW(m4, 2, Matrix4, Matrix4); if (m4) _SA_RETURN_OBJECT(new_Vector(v, *self * *m4)); return sa.ThrowError("Vector::ApplyMatrix(): Invalid parameter"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, ApplyRotationMatrix) _GetSelf(Vector4, Vector); _CHECK_INST_PARAM_RAW(m3, 2, Matrix3, Matrix3); if (m3) _SA_RETURN_OBJECT(new_Vector(v, *self * *m3)); _CHECK_INST_PARAM_RAW(m4, 2, Matrix4, Matrix4); if (m4) _SA_RETURN_OBJECT(new_Vector(v, *self * Matrix3::FromMatrix4(*m4))); return sa.ThrowError("Vector::ApplyRotationMatrix(): Invalid parameter"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Randomize) if (sa.GetParamCount() == 2) _SA_RETURN_OBJECT(new_Vector(v, Vector4::Random(0, sa.GetFloat(2)))); _SA_RETURN_OBJECT(new_Vector(v, Vector4::Random(sa.GetFloat(2), sa.GetFloat(3)))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Normalize) _GetSelf(Vector4, Vector); if (sa.GetParamCount() == 1) _SA_RETURN_OBJECT(new_Vector(v, self->Normalized())) else _SA_RETURN_OBJECT(new_Vector(v, self->Normalized() * sa.GetFloat(2))) _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Lerp) _GetSelf(Vector4, Vector); float k = sa.GetFloat(2), ik = 1.f - k; _GetTypedParam(vec, 3, Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self * k + *vec * ik)); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, _cmp) _GetSelf(Vector4, Vector); _GetTypedParam(vec, 2, Vector4, Vector); return sa.Return((*self) == (*vec) ? true : false); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, IsEqual) _GetSelf(Vector4, Vector); _GetTypedParam(vec, 2, Vector4, Vector); float d2 = 0.0001f; switch (sa.GetParamCount()) { case 2: break; case 3: d2 = sa.GetFloat(3); break; default: return sa.ThrowError("Vector::IsEqual() wrong parameter count"); } d2 *= d2; return sa.Return(Vector4::Dist2(*self, *vec) < d2 ? true : false); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Min) _GetSelf(Vector4, Vector); if ((sa.GetParamCount() == 2) || (sa.GetParamCount() == 4)) switch (sa.GetType(2)) { case OT_INSTANCE: { _GetTypedParam(vec, 2, Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x < vec->x ? self->x : vec->x, self->y < vec->y ? self->y : vec->y, self->z < vec->z ? self->z : vec->z))); } case OT_FLOAT: { float x = sa.GetFloat(2), y = sa.GetFloat(3), z = sa.GetFloat(4); _SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x < x ? self->x : x, self->y < y ? self->y : y, self->z < z ? self->z : z))); } } return sa.ThrowError("Vector Min(): Invalid parameter list.\n"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Max) _GetSelf(Vector4, Vector); if ((sa.GetParamCount() == 2) || (sa.GetParamCount() == 4)) switch (sa.GetType(2)) { case OT_INSTANCE: { _GetTypedParam(vec, 2, Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x > vec->x ? self->x : vec->x, self->y > vec->y ? self->y : vec->y, self->z > vec->z ? self->z : vec->z))); } case OT_FLOAT: { float x = sa.GetFloat(2), y = sa.GetFloat(3), z = sa.GetFloat(4); _SA_RETURN_OBJECT(new_Vector(v, Vector4(self->x > x ? self->x : x, self->y > y ? self->y : y, self->z > z ? self->z : z))); } } return sa.ThrowError("Vector Max(): Invalid parameter list.\n"); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Scale) _GetSelf(Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self * sa.GetFloat(2))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, AddReal) _GetSelf(Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self + Vector4(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2)))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, MulReal) _GetSelf(Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self * Vector4(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2)))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, SubReal) _GetSelf(Vector4, Vector); _SA_RETURN_OBJECT(new_Vector(v, *self - Vector4(sa.GetFloat(2), sa.GetFloat(2), sa.GetFloat(2)))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, DivReal) _GetSelf(Vector4, Vector); const float ik = 1.f / sa.GetFloat(2); _SA_RETURN_OBJECT(new_Vector(v, *self * Vector4(ik, ik, ik))); _END_IMPL _MEMBER_FUNCTION_IMPL(Vector, Print) _GetSelf(Vector4, Vector); const char *label = "Vector"; if (sa.GetParamCount() == 2) label = sa.GetString(2); __LOG__ << label << ": { " << self->x << ", " << self->y << ", " << self->z << ", " << self->w << "}\n"; return 0; _END_IMPL /*# Topic: Vector Type: Vector #*/ /*# Section: VectorGeneric Desc: Generic #*/ _BEGIN_CLASS(Vector) /*# Func: Vector Proto: Vector:float x = 0,float y = 0,float z = 0,float w = 1 Desc: Create a new vector. Example: local v = Vector(1, 0, 0) #*/ _MEMBER_FUNCTION(Vector, constructor, -1, _T(".n|xnnn")) _MEMBER_FUNCTION(Vector, _cloned, 2, _T(".x")) _MEMBER_FUNCTION(Vector, _set, 3, _T("xs|n")) _MEMBER_FUNCTION(Vector, _get, 2, _T("xs|n")) _MEMBER_FUNCTION(Vector, _add, 2, _T("xx|n")) _MEMBER_FUNCTION(Vector, _sub, 2, _T("xx|n")) _MEMBER_FUNCTION(Vector, _mul, 2, _T("xx|n")) _MEMBER_FUNCTION(Vector, _div, 2, _T("xx|n")) _MEMBER_FUNCTION(Vector, _cmp, 2, _T("xx")) /*# Func: Set Proto: void:float x = 0,float y = 0,float z = 0,float w = 1 Desc: Set vector values. #*/ _MEMBER_FUNCTION(Vector, Set, -1, _T("xnnnn")) /*# Func: ApplyMatrix Proto: Vector:[Matrix4|Matrix3] matrix Desc: Transform vector by a given matrix. #*/ _MEMBER_FUNCTION(Vector, ApplyMatrix, 2, _T("xx")) /*# Func: ApplyRotationMatrix Proto: Vector:[Matrix4|Matrix3] matrix Desc: Transform vector by the rotation part of a given matrix. #*/ _MEMBER_FUNCTION(Vector, ApplyRotationMatrix, 2, _T("xx")) _MEMBER_FUNCTION(Vector, AddReal, 2, _T("xn")) _MEMBER_FUNCTION(Vector, MulReal, 2, _T("xn")) _MEMBER_FUNCTION(Vector, SubReal, 2, _T("xn")) _MEMBER_FUNCTION(Vector, DivReal, 2, _T("xn")) _MEMBER_FUNCTION(Vector, Scale, 2, _T("xn")) /*# Func: Clamp Proto: Vector:(Vector|float) min,(Vector|float) max Desc: Individually clamp vector components to a given range. #*/ _MEMBER_FUNCTION(Vector, clamp, 3, _T("x x|n x|n")) /*# Func: ClampMagnitude Proto: Vector:float len Desc: Clamp vector magnitude to a specific length. #*/ _MEMBER_FUNCTION(Vector, ClampMagnitude, 2, _T("xn")) /*# Func: Reverse Proto: Vector: Desc: Return the reverse vector. #*/ _MEMBER_FUNCTION(Vector, Reverse, 1, _T("x")) /*# Func: Min Proto: Vector:[Vector|float x,float y, float z] min Desc: Return the smallest value of the vector component or parameter for all the vector components. #*/ _MEMBER_FUNCTION(Vector, Min, -2, _T("xn|xnn")) /*# Func: Max Proto: Vector:[Vector|float x,float y, float z] max Desc: Return the largest value of the vector component or parameter for all the vector components. #*/ _MEMBER_FUNCTION(Vector, Max, -2, _T("xn|xnn")) /*# Func: Dot Proto: float:Vector v Desc: Return the dot product between two vectors. #*/ _MEMBER_FUNCTION(Vector, Dot, 2, _T("xx")) /*# Func: Cross Proto: Vector:Vector v Desc: Return the cross product between two vectors. #*/ _MEMBER_FUNCTION(Vector, Cross, 2, _T("xx")) /*# Func: Len Proto: float:Vector v Desc: Return the length of this vector. #*/ _MEMBER_FUNCTION(Vector, Len, 1, _T("x")) /*# Func: Len2 Proto: float:Vector v Desc: Return the squared length of this vector. #*/ _MEMBER_FUNCTION(Vector, Len2, 1, _T("x")) /*# Func: AngleWithVector Proto: float:Vector v Desc: Return the angle between two vectors. #*/ _MEMBER_FUNCTION(Vector, AngleWithVector, 2, _T("xx")) /*# Func: Normalize Proto: Vector:float length = 1 Desc: Return a normalized version of this vector scaled to a constant. #*/ _MEMBER_FUNCTION(Vector, Normalize, -1, _T("xn")) /*# Func: Dist Proto: float:Vector v Desc: Return the distance between two vectors. #*/ _MEMBER_FUNCTION(Vector, Dist, 2, _T("xx")) /*# Func: Dist2 Proto: float:Vector v Desc: Return the squared distance between two vectors. #*/ _MEMBER_FUNCTION(Vector, Dist2, 2, _T("xx")) /*# Func: Lerp Proto: float:Vector v,float t Desc: Return a linearly interpolated vector between two vectors. #*/ _MEMBER_FUNCTION(Vector, Lerp, 3, _T("xnx")) /*# Func: Randomize Proto: Vector:Vector v,float min,float max Desc: Return a random vector in a given range. #*/ _MEMBER_FUNCTION(Vector, Randomize, -2, _T(".nn")) /*# Func: IsEqual Proto: bool:Vector v,float epsilon = 0.0001 Desc: Test vectors for equality with a given espilon tolerance. #*/ _MEMBER_FUNCTION(Vector, IsEqual, -2, _T("xxn")) /*# Func: Print Proto: void: Desc: Dump this vector components to the engine log. #*/ _MEMBER_FUNCTION(Vector, Print, -1, _T("x")) _END_CLASS(Vector) //----------------------------------------------- void UCBind_RegisterVector(HSQUIRRELVM vm) //----------------------------------------------- { _INIT_CLASS(vm, Vector); }