#include <fakemeta>
#include <xs>
Matrix4x4_CreateModelview( Float:out[4][4] )
{
out[0][0] = out[1][1] = out[2][2] = 0.0;
out[3][0] = out[0][3] = 0.0;
out[3][1] = out[1][3] = 0.0;
out[3][2] = out[2][3] = 0.0;
out[3][3] = 1.0;
out[1][0] = out[0][2] = out[2][1] = 0.0;
out[2][0] = out[0][1] = -1.0;
out[1][2] = 1.0;
}
Matrix4x4_Copy(Float:out[4][4], Float:in[4][4])
{
for(new i = 0;i < 4;i++)
for(new j = 0 ; j < 4; j++)
out[i][j] = in[i][j];
}
Matrix4x4_CreateRotate( Float:out[4][4], Float: angle, Float: x, Float: y, Float: z )
{
new Float: len, Float:c, Float:s;
len = x * x + y * y + z * z;
if( len != 0.0 ) len = 1.0 / floatsqroot( len );
x *= len;
y *= len;
z *= len;
angle *= (-M_PI / 180.0);
s = floatsin(angle);
c = floatcos(angle);
out[0][0]=x * x + c * (1 - x * x);
out[0][1]=x * y * (1 - c) + z * s;
out[0][2]=z * x * (1 - c) - y * s;
out[0][3]=0.0;
out[1][0]=x * y * (1 - c) - z * s;
out[1][1]=y * y + c * (1 - y * y);
out[1][2]=y * z * (1 - c) + x * s;
out[1][3]=0.0;
out[2][0]=z * x * (1 - c) + y * s;
out[2][1]=y * z * (1 - c) - x * s;
out[2][2]=z * z + c * (1 - z * z);
out[2][3]=0.0;
out[3][0]=0.0;
out[3][1]=0.0;
out[3][2]=0.0;
out[3][3]=1.0;
}
Matrix4x4_Concat( Float:out[4][4], const Float:in1[4][4], const Float:in2[4][4] )
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0] + in1[0][3] * in2[3][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1] + in1[0][3] * in2[3][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2] + in1[0][3] * in2[3][2];
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3] * in2[3][3];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0] + in1[1][3] * in2[3][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1] + in1[1][3] * in2[3][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2] + in1[1][3] * in2[3][2];
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3] * in2[3][3];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0] + in1[2][3] * in2[3][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1] + in1[2][3] * in2[3][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2] + in1[2][3] * in2[3][2];
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3] * in2[3][3];
out[3][0] = in1[3][0] * in2[0][0] + in1[3][1] * in2[1][0] + in1[3][2] * in2[2][0] + in1[3][3] * in2[3][0];
out[3][1] = in1[3][0] * in2[0][1] + in1[3][1] * in2[1][1] + in1[3][2] * in2[2][1] + in1[3][3] * in2[3][1];
out[3][2] = in1[3][0] * in2[0][2] + in1[3][1] * in2[1][2] + in1[3][2] * in2[2][2] + in1[3][3] * in2[3][2];
out[3][3] = in1[3][0] * in2[0][3] + in1[3][1] * in2[1][3] + in1[3][2] * in2[2][3] + in1[3][3] * in2[3][3];
}
Matrix4x4_ConcatRotate( Float:out[4][4], Float:angle,Float: x, Float: y, Float: z )
{
new Float:base[4][4], Float:temp[4][4];
Matrix4x4_Copy( base, out );
Matrix4x4_CreateRotate( temp, angle, x, y, z );
Matrix4x4_Concat( out, base, temp );
}
Matrix4x4_CreateTranslate( Float:out[4][4], Float:x, Float:y, Float: z )
{
out[0][0] = 1.0;
out[0][1] = 0.0;
out[0][2] = 0.0;
out[0][3] = x;
out[1][0] = 0.0;
out[1][1] = 1.0;
out[1][2] = 0.0;
out[1][3] = y;
out[2][0] = 0.0;
out[2][1] = 0.0;
out[2][2] = 1.0;
out[2][3] = z;
out[3][0] = 0.0;
out[3][1] = 0.0;
out[3][2] = 0.0;
out[3][3] = 1.0;
}
Matrix4x4_ConcatTranslate( Float:out[4][4], Float:x, Float:y, Float:z )
{
new Float: base[4][4], Float: temp[4][4];
Matrix4x4_Copy( base, out );
Matrix4x4_CreateTranslate( temp, x, y, z );
Matrix4x4_Concat( out, base, temp );
}
Matrix4x4_CreateProjection( Float:out[4][4], Float:xMax, Float: xMin, Float: yMax, Float: yMin, Float: zNear, Float:zFar )
{
out[0][0] = ( 2.0 * zNear ) / ( xMax - xMin );
out[1][1] = ( 2.0 * zNear ) / ( yMax - yMin );
out[2][2] = -( zFar + zNear ) / ( zFar - zNear );
out[3][3] = out[0][1] = out[1][0] = out[3][0] = out[0][3] = out[3][1] = out[1][3] = 0.0;
out[2][0] = 0.0;
out[2][1] = 0.0;
out[0][2] = ( xMax + xMin ) / ( xMax - xMin );
out[1][2] = ( yMax + yMin ) / ( yMax - yMin );
out[3][2] = -1.0;
out[2][3] = -( 2.0 * zFar * zNear ) / ( zFar - zNear );
}
R_SetupProjectionMatrix( Float:m[4][4] )
{
new Float:xMin, Float:xMax, Float:yMin, Float:yMax, Float:zNear, Float:zFar;
zNear = 4.0
zFar = floatmax( 256.0, 8192.0 );
yMax = zNear * floattan( 74.0 * M_PI / 360.0 );
yMin = -yMax;
xMax = zNear * floattan( 90.0 * M_PI / 360.0 );
xMin = -xMax;
Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar );
}
R_SetupModelviewMatrix( Float: m[4][4], Float:viewangles[3], Float:vieworg[3])
{
Matrix4x4_CreateModelview( m );
Matrix4x4_ConcatRotate( m, -viewangles[2], 1.0, 0.0, 0.0 );
Matrix4x4_ConcatRotate( m, -viewangles[0], 0.0, 1.0, 0.0 );
Matrix4x4_ConcatRotate( m, -viewangles[1], 0.0, 0.0, 1.0 );
Matrix4x4_ConcatTranslate( m, -vieworg[0], -vieworg[1], -vieworg[2] );
}
stock bool:WorldToScreen( id, Float:point[3], Float:screen[2] )
{
new bool:behind;
new Float:w;
new Float:worldToScreen[4][4];
new Float:worldviewMatrix[4][4];
new Float:projectionMatrix[4][4];
new Float:viewangles[3];
new Float:viewofs[3];
new Float:vieworigin[3];
pev(id, pev_origin, vieworigin);
pev(id, pev_v_angle, viewangles);
pev(id, pev_view_ofs, viewofs);
xs_vec_add(vieworigin, viewofs, vieworigin);
R_SetupModelviewMatrix(worldviewMatrix, viewangles, vieworigin);
R_SetupProjectionMatrix( projectionMatrix );
Matrix4x4_Concat( worldToScreen, projectionMatrix, worldviewMatrix );
screen[0] = worldToScreen[0][0] * point[0] + worldToScreen[0][1] * point[1] + worldToScreen[0][2] * point[2] + worldToScreen[0][3];
screen[1] = worldToScreen[1][0] * point[0] + worldToScreen[1][1] * point[1] + worldToScreen[1][2] * point[2] + worldToScreen[1][3];
w = worldToScreen[3][0] * point[0] + worldToScreen[3][1] * point[1] + worldToScreen[3][2] * point[2] + worldToScreen[3][3];
if( w < 0.001 )
{
screen[0] *= 100000;
screen[1] *= 100000;
behind = true;
}
else
{
new Float:invw = 1.0 / w;
screen[0] *= invw;
screen[1] *= invw;
behind = false;
}
screen[0] = 0.5 * screen[0] * 1.0;
screen[1] = -0.5 * screen[1] * 1.0;
screen[0] += 0.5 * 1.0;
screen[1] += 0.5 * 1.0;
return behind;
}