static int luaB_cross (lua_State *L) { float x1, y1, z1; float x2, y2, z2; float ax, ay, az; if (lua_gettop(L) != 2) luaL_error(L, "Invalid params, try cross(v,v)"); lua_checkvector3(L, 1, &x1, &y1, &z1); lua_checkvector3(L, 2, &x2, &y2, &z2); cross(x1,y1,z1, x2,y2,z2, &ax, &ay, &az); lua_pushvector3(L,ax,ay,az); return 1; }
static int luaB_unpack (lua_State *L) { if (lua_gettop(L)==1 && lua_isvector3(L,1)) { float x, y, z; lua_checkvector3(L, 1, &x, &y, &z); lua_pushnumber(L,x); lua_pushnumber(L,y); lua_pushnumber(L,z); return 3; } else if (lua_gettop(L)==1 && lua_isquat(L,1)) { float w, x, y, z; lua_checkquat(L, 1, &w, &x, &y, &z); lua_pushnumber(L,w); lua_pushnumber(L,x); lua_pushnumber(L,y); lua_pushnumber(L,z); return 4; } else { int i, e, n; luaL_checktype(L, 1, LUA_TTABLE); i = luaL_optint(L, 2, 1); e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); if (i > e) return 0; /* empty range */ n = e - i + 1; /* number of elements */ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ return luaL_error(L, "too many results to unpack"); lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ while (i++ < e) /* push arg[i + 1...e] */ lua_rawgeti(L, 1, i); return n; } }
static int math_abs (lua_State *L) { lua_Number v; float x, y, z, w; switch (lua_type(L,1)) { case LUA_TNUMBER: if (lua_isinteger(L, 1)) { lua_Integer n = lua_tointeger(L, 1); if (n < 0) n = (lua_Integer)(0u - n); lua_pushinteger(L, n); } else { v = lua_tonumber(L,1); lua_pushnumber(L,l_mathop(fabs)(v)); } return 1; case LUA_TVECTOR2: lua_checkvector2(L,1,&x,&y); lua_pushvector2(L,fabsf(x),fabsf(y)); return 1; case LUA_TVECTOR3: lua_checkvector3(L,1,&x,&y,&z); lua_pushvector3(L,fabsf(x),fabsf(y),fabsf(z)); return 1; case LUA_TVECTOR4: lua_checkvector4(L,1,&x,&y,&z,&w); lua_pushvector4(L,fabsf(x),fabsf(y),fabsf(z),fabsf(w)); return 1; } luaL_error(L, "abs takes a number, integer, vector2, vector3, or vector4."); return 1; }
static int math_ceil (lua_State *L) { lua_Number v; float x, y, z, w; switch (lua_type(L,1)) { case LUA_TNUMBER: if (lua_isinteger(L, 1)) { lua_settop(L, 1); /* integer is its own ceil */ } else { v = lua_tonumber(L,1); pushnumint(L,ceil(v)); } return 1; case LUA_TVECTOR2: lua_checkvector2(L,1,&x,&y); lua_pushvector2(L,ceilf(x),ceilf(y)); return 1; case LUA_TVECTOR3: lua_checkvector3(L,1,&x,&y,&z); lua_pushvector3(L,ceilf(x),ceilf(y),ceilf(z)); return 1; case LUA_TVECTOR4: lua_checkvector4(L,1,&x,&y,&z,&w); lua_pushvector4(L,ceilf(x),ceilf(y),ceilf(z),ceilf(w)); return 1; } luaL_error(L, "ceil takes a number, integer, vector2, vector3, or vector4."); return 1; }
static int luaB_dot (lua_State *L) { float x1, y1, z1, w1; float x2, y2, z2, w2; if (lua_gettop(L) != 2) luaL_error(L, "Invalid params, try dot(v,v)"); if (lua_isvector4(L,1)) { lua_checkvector4(L, 1, &x1, &y1, &z1, &w1); lua_checkvector4(L, 2, &x2, &y2, &z2, &w2); lua_pushnumber(L,dot4(x1,y1,z1,w1, x2,y2,z2,w2)); } else if (lua_isvector3(L,1)) { lua_checkvector3(L, 1, &x1, &y1, &z1); lua_checkvector3(L, 2, &x2, &y2, &z2); lua_pushnumber(L,dot3(x1,y1,z1, x2,y2,z2)); } else if (lua_isvector2(L,1)) { lua_checkvector2(L, 1, &x1, &y1); lua_checkvector2(L, 2, &x2, &y2); lua_pushnumber(L,dot2(x1,y1, x2,y2)); } return 1; }
static int math_clamp (lua_State *L) { if (lua_gettop(L)!=3) return luaL_error(L, "wrong number of arguments"); switch (lua_type(L,1)) { case LUA_TNUMBER: { lua_Number a, b, c; a = luaL_checknumber(L,1); b = luaL_checknumber(L,2); c = luaL_checknumber(L,3); if (a<b) a = b; if (a>c) a = c; lua_pushnumber(L, a); } break; case LUA_TVECTOR2: { float xa, ya; float xb, yb; float xc, yc; lua_checkvector2(L, 1, &xa, &ya); lua_checkvector2(L, 2, &xb, &yb); lua_checkvector2(L, 3, &xc, &yc); lua_pushvector2(L, do_clamp(xa,xb,xc), do_clamp(ya,yb,yc)); } break; case LUA_TVECTOR3: { float xa, ya, za; float xb, yb, zb; float xc, yc, zc; lua_checkvector3(L, 1, &xa, &ya, &za); lua_checkvector3(L, 2, &xb, &yb, &zb); lua_checkvector3(L, 3, &xc, &yc, &zc); lua_pushvector3(L, do_clamp(xa,xb,xc), do_clamp(ya,yb,yc), do_clamp(za,zb,zc)); } break; case LUA_TVECTOR4: { float xa, ya, za, wa; float xb, yb, zb, wb; float xc, yc, zc, wc; lua_checkvector4(L, 1, &xa, &ya, &za, &wa); lua_checkvector4(L, 2, &xb, &yb, &zb, &wb); lua_checkvector4(L, 3, &xc, &yc, &zc, &wc); lua_pushvector4(L, do_clamp(xa,xb,xc), do_clamp(ya,yb,yc), do_clamp(za,zb,zc), do_clamp(wa,wb,wc)); } break; default: return luaL_error(L, "clamp only works on number, vector2, vector3, vector4"); } return 1; }
static int luaB_vectorn (lua_State *L, int sz, float *input) { int counter = 0; int i; for (i=1; i<=lua_gettop(L) ; ++i) { switch (lua_type(L, i)) { case LUA_TVECTOR4: if (counter+4 <= sz) { float *x = &input[counter++]; float *y = &input[counter++]; float *z = &input[counter++]; float *w = &input[counter++]; lua_checkvector4(L, i, x,y,z,w); } else { return 0; } break; case LUA_TVECTOR3: if (counter+3 <= sz) { float *x = &input[counter++]; float *y = &input[counter++]; float *z = &input[counter++]; lua_checkvector3(L, i, x,y,z); } else { return 0; } break; case LUA_TVECTOR2: if (counter+2 <= sz) { float *x = &input[counter++]; float *y = &input[counter++]; lua_checkvector2(L, i, x,y); } else { return 0; } break; case LUA_TNUMBER: if (counter+1 <= sz) { input[counter++] = lua_tonumber(L, i); } else { return 0; } break; default: { char msg[1024]; sprintf(msg, "vector%d(...) argument %d had type %s", sz, i, lua_typename(L, lua_type(L,i))); luaL_error(L, msg); } } } return counter == sz; }
static int luaB_norm (lua_State *L) { if (lua_gettop(L)==1 && lua_isvector3(L,1)) { float x, y, z; float len; lua_checkvector3(L, 1, &x, &y, &z); len = sqrtf(x*x + y*y + z*z); lua_pushvector3(L,x/len,y/len,z/len); return 1; } else if (lua_gettop(L)==1 && lua_isquat(L,1)) { float w, x, y, z; float qlen; lua_checkquat(L, 1, &w, &x, &y, &z); qlen = sqrtf(w*w + x*x + y*y + z*z); lua_pushquat(L,w/qlen,x/qlen,y/qlen,z/qlen); return 1; } else { luaL_error(L, "Invalid params, try norm(v) norm(q)"); return 0; } }
static int luaB_norm (lua_State *L) { if (lua_gettop(L)==1 && lua_isvector2(L,1)) { float x, y; float len; lua_checkvector2(L, 1, &x, &y); len = sqrtf(x*x + y*y); if (len == 0) luaL_error(L, "Cannot normalise vector2(0,0)"); lua_pushvector2(L,x/len,y/len); return 1; } else if (lua_gettop(L)==1 && lua_isvector3(L,1)) { float x, y, z; float len; lua_checkvector3(L, 1, &x, &y, &z); len = sqrtf(x*x + y*y + z*z); if (len == 0) luaL_error(L, "Cannot normalise vector3(0,0,0)"); lua_pushvector3(L,x/len,y/len,z/len); return 1; } else if (lua_gettop(L)==1 && lua_isvector4(L,1)) { float x, y, z, w; float len; lua_checkvector4(L, 1, &x, &y, &z, &w); len = sqrtf(x*x + y*y + z*z + w*w); if (len == 0) luaL_error(L, "Cannot normalise vector4(0,0,0,0)"); lua_pushvector4(L,x/len,y/len,z/len,w/len); return 1; } else if (lua_gettop(L)==1 && lua_isquat(L,1)) { float w, x, y, z; float qlen; lua_checkquat(L, 1, &w, &x, &y, &z); qlen = sqrtf(w*w + x*x + y*y + z*z); if (qlen == 0) luaL_error(L, "Cannot normalise quat(0,0,0,0)"); lua_pushquat(L,w/qlen,x/qlen,y/qlen,z/qlen); return 1; } else { return luaL_error(L, "Invalid arguments, try norm(v) or norm(q)."); } }
static int luaB_quat (lua_State *L) { if (lua_gettop(L)==4 && lua_isnumber(L,1) && lua_isnumber(L,2) && lua_isnumber(L,3) && lua_isnumber(L,4)) { float w,x,y,z; w = (float)lua_tonumber(L, 1); x = (float)lua_tonumber(L, 2); y = (float)lua_tonumber(L, 3); z = (float)lua_tonumber(L, 4); lua_pushquat(L, w,x,y,z); return 1; } else if (lua_gettop(L)==2 && lua_isnumber(L,1) && lua_isvector3(L,2)) { float angle,x,y,z,ha,s; angle = (float)lua_tonumber(L, 1); lua_checkvector3(L, 2, &x, &y, &z); ha = angle*(0.5f*PI/180.0f); s = sinf(ha); lua_pushquat(L, cosf(ha),s*x,s*y,s*z); return 1; } else if (lua_gettop(L)==2 && lua_isvector3(L,1) && lua_isvector3(L,2)) { float x1, y1, z1; float x2, y2, z2; float l1,l2,d; lua_checkvector3(L, 1, &x1, &y1, &z1); lua_checkvector3(L, 2, &x2, &y2, &z2); /* Based on Stan Melax's article in Game Programming Gems */ l1 = sqrtf(x1*x1 + y1*y1 + z1*z1); l2 = sqrtf(x2*x2 + y2*y2 + z2*z2); x1/=l1; y1/=l1; z1/=l1; x2/=l2; y2/=l2; z2/=l2; d = dot3(x1,y1,z1, x2,y2,z2); /* If dot == 1, vectors are the same */ if (d >= 1.0f) { lua_pushquat(L, 1,0,0,0); return 1; } if (d < (1e-6f - 1.0f)) { float ax, ay, az; float len2, len; cross3(1,0,0, x1,y1,z1, &ax, &ay, &az); len2 = ax*ax + ay*ay + az*az; if (len2 == 0) { cross3(0,1,0, x1,y1,z1, &ax, &ay, &az); len2 = ax*ax + ay*ay + az*az; } len = sqrtf(len2); ax/=len; ay/=len; az/=len; lua_pushquat(L, 0,ax,ay,az); return 1; } else { float s = sqrtf((1+d)*2); float ax, ay, az; float qw, qlen; cross3(x1,y1,z1, x2,y2,z2, &ax, &ay, &az); ax/=s; ay/=s; az/=s; qw = s*0.5f; qlen = sqrtf(qw*qw + ax*ax + ay*ay + az*az); lua_pushquat(L, qw/qlen,ax/qlen,ay/qlen,az/qlen); return 1; } } else { luaL_error(L, "Invalid params, try quat(n,n,n,n) quat(n,v3) quat(v3,v3)"); return 0; } }