I=(S=Uno.Camera = function(){
}).prototype;

I.Reset = function()
{
    this.Position(Uno.Float3.$1(100.0, 100.0, 100.0));
    this.Target(Uno.Float3.$1(0.0, 0.0, 0.0));
    this.Up(Uno.Float3.$1(0.0, 0.0, 1.0));
    this.FovRadians(0.7853982);
    this.Aspect(1.777778);
    this.ZNear(1.0);
    this.ZFar(1000.0);
};

I.Intersects = function(s)
{
    var zAxis = Uno.Vector.Normalize(Uno.Float3.operator_Sub(this.target, this.position));
    var xAxis = Uno.Vector.Normalize(Uno.Vector.Cross(this.up, zAxis));
    var yAxis = Uno.Vector.Normalize(Uno.Vector.Cross(zAxis, xAxis));
    var yScale = Math.tan(this.fovRadians * 0.5);
    var xScale = yScale * this.aspect;
    var halfWidthNear = this.zNear * xScale;
    var halfHeightNear = this.zNear * yScale;
    var halfWidthFar = this.zFar * xScale;
    var halfHeightFar = this.zFar * yScale;
    var v = Uno.Float3.operator_Sub(s.Center, this.position);
    var p = Uno.Vector.Dot(v, zAxis);

    if ((p < (this.zNear - s.Radius)) || (p > (this.zFar + s.Radius)))
    {
        return false;
    }

    var fsf = p = (p - this.zNear) / this.zFar;
    var halfHeight = (halfHeightNear * (1.0 - fsf)) + (halfHeightFar * fsf);
    p = Uno.Vector.Dot(v, yAxis);
    var r = s.Radius / Math.cos(this.fovRadians * 0.5);

    if ((p < ((-halfHeight) - r)) || (p > (halfHeight + r)))
    {
        return false;
    }

    var halfWidth = (halfWidthNear * (1.0 - fsf)) + (halfWidthFar * fsf);
    p = Uno.Vector.Dot(v, xAxis);
    r = s.Radius / (Math.cos(this.fovRadians * 0.5) / this.aspect);

    if ((p < ((-halfWidth) - r)) || (p > (halfWidth + r)))
    {
        return false;
    }

    return true;
};

I.GetWorldRay = function(p)
{
    var viewProjInv = this.InverseViewProj();
    var r0 = Uno.Vector.TransformCoordinate(Uno.Float3.$2(p, -1.0), viewProjInv);
    var r1 = Uno.Vector.TransformCoordinate(Uno.Float3.$2(p, 1.0), viewProjInv);
    return Uno.Ray.$0(r0, Uno.Vector.Normalize(Uno.Float3.operator_Sub(r1, r0)));
};

I.PixelToWorldRay = function(pos, viewportSize)
{
    var p = Uno.Float2.$1(((pos.X / viewportSize.X) * 2.0) - 1.0, ((pos.Y / viewportSize.Y) * -2.0) + 1.0);
    return this.GetWorldRay(p);
};

I.PixelToWorldRay_1 = function(pos)
{
    var viewportSize = Uno.Application.WindowSize();
    var p = Uno.Float2.$1(((pos.X / viewportSize.X) * 2.0) - 1.0, ((pos.Y / viewportSize.Y) * -2.0) + 1.0);
    return this.GetWorldRay(p);
};

I.GetFrustum = function(rect)
{
    var zAxis = Uno.Vector.Normalize(Uno.Float3.operator_Sub(this.target, this.position));
    var xAxis = Uno.Vector.Normalize(Uno.Vector.Cross(this.up, zAxis));
    var yAxis = Uno.Vector.Normalize(Uno.Vector.Cross(zAxis, xAxis));
    var yScale = Math.tan(this.fovRadians * 0.5);
    var xScale = yScale * this.aspect;
    var halfWidthNear = this.zNear * xScale;
    var halfHeightNear = this.zNear * yScale;
    var halfWidthFar = this.zFar * xScale;
    var halfHeightFar = this.zFar * yScale;
    var fc = Uno.Float3.operator_Add(this.position, Uno.Float3.operator_Mul_1(zAxis, this.zFar));
    var nc = Uno.Float3.operator_Add(this.position, Uno.Float3.operator_Mul_1(zAxis, this.zNear));
    var result = new Uno.Frustum;
    result.Near = Uno.Plane.$2(nc, Uno.Float3.operator_Negate_2(zAxis, zAxis));
    result.Far = Uno.Plane.$2(fc, zAxis);
    result.Left = Uno.Plane.$2(this.position, Uno.Vector.Cross(yAxis, Uno.Vector.Normalize(Uno.Float3.operator_Sub(Uno.Float3.operator_Sub(nc, Uno.Float3.operator_Mul_1(xAxis, (halfWidthNear * rect.Left))), this.position))));
    result.Right = Uno.Plane.$2(this.position, Uno.Vector.Cross(Uno.Vector.Normalize(Uno.Float3.operator_Sub(Uno.Float3.operator_Sub(nc, Uno.Float3.operator_Mul_1(xAxis, (halfWidthNear * rect.Right))), this.position)), yAxis));
    result.Top = Uno.Plane.$2(this.position, Uno.Vector.Cross(Uno.Vector.Normalize(Uno.Float3.operator_Sub(Uno.Float3.operator_Add(nc, Uno.Float3.operator_Mul_1(yAxis, (halfHeightNear * rect.Top))), this.position)), xAxis));
    result.Bottom = Uno.Plane.$2(this.position, Uno.Vector.Cross(xAxis, Uno.Vector.Normalize(Uno.Float3.operator_Sub(Uno.Float3.operator_Add(nc, Uno.Float3.operator_Mul_1(yAxis, (halfHeightNear * rect.Bottom))), this.position))));
    return result;
};

I.Position = function(value)
{
    if (value !== undefined)
    {
        this.position = value;
        this.dirty = this.dirty | 45;
    }

    else
    {
        return this.position;
    }
};

I.Target = function(value)
{
    if (value !== undefined)
    {
        this.target = value;
        this.dirty = this.dirty | 45;
    }

    else
    {
        return this.target;
    }
};

I.Direction = function(value)
{
    if (value !== undefined)
    {
        this.Target(Uno.Float3.operator_Add(this.position, value));
    }

    else
    {
        return Uno.Float3.operator_Sub(this.target, this.position);
    }
};

I.Up = function(value)
{
    if (value !== undefined)
    {
        this.up = value;
        this.dirty = this.dirty | 45;
    }

    else
    {
        return this.up;
    }
};

I.FovRadians = function(value)
{
    if (value !== undefined)
    {
        this.fovRadians = value;
        this.dirty = this.dirty | 45;
    }

    else
    {
        return this.fovRadians;
    }
};

I.FovDegrees = function(value)
{
    if (value !== undefined)
    {
        this.FovRadians((value / 180.0) * 3.141593);
    }

    else
    {
        return (this.FovRadians() / 3.141593) * 180.0;
    }
};

I.Aspect = function(value)
{
    if (value !== undefined)
    {
        if (value != this.aspect)
        {
            this.aspect = value;
            this.dirty = this.dirty | 54;
        }
    }

    else
    {
        return this.aspect;
    }
};

I.ZNear = function(value)
{
    if (value !== undefined)
    {
        this.zNear = value;
        this.dirty = this.dirty | 54;
    }

    else
    {
        return this.zNear;
    }
};

I.ZFar = function(value)
{
    if (value !== undefined)
    {
        this.zFar = value;
        this.dirty = this.dirty | 54;
    }

    else
    {
        return this.zFar;
    }
};

S.Default = function()
{
    return Uno.Camera.$0(Uno.Float3.$1(100.0, 100.0, 100.0), Uno.Float3.$1(0.0, 0.0, 0.0), Uno.Float3.$1(0.0, 0.0, 1.0), 0.7853982, 1.777778, 1.0, 1000.0);
};

I.View = function()
{
    if ((this.dirty & 1) == 1)
    {
        this.view = Uno.Matrix.LookAtRH(this.position, this.target, this.up);
        this.dirty = this.dirty & (~1);
    }

    return this.view;
};

I.Proj = function()
{
    if ((this.dirty & 2) == 2)
    {
        this.proj = Uno.Matrix.PerspectiveRH(this.fovRadians, this.aspect, this.zNear, this.zFar);
        this.dirty = this.dirty & (~2);
    }

    return this.proj;
};

I.ViewProj = function()
{
    if ((this.dirty & 4) == 4)
    {
        this.viewProj = Uno.Matrix.Mul(this.View(), this.Proj());
        this.dirty = this.dirty & (~4);
    }

    return this.viewProj;
};

I.InverseView = function()
{
    if ((this.dirty & 8) == 8)
    {
        this.viewInv = Uno.Matrix.Invert_1(this.View());
        this.dirty = this.dirty & (~8);
    }

    return this.viewInv;
};

I.InverseProj = function()
{
    if ((this.dirty & 16) == 16)
    {
        this.projInv = Uno.Matrix.Invert_1(this.Proj());
        this.dirty = this.dirty & (~16);
    }

    return this.projInv;
};

I.InverseViewProj = function()
{
    if ((this.dirty & 32) == 32)
    {
        this.viewProjInv = Uno.Matrix.Invert_1(this.ViewProj());
        this.dirty = this.dirty & (~32);
    }

    return this.viewProjInv;
};

I.Frustum = function()
{
    return this.GetFrustum(Uno.Rect.$0(-1.0, 1.0, 1.0, -1.0));
};

S.$0 = function(pos, target, up, fovRadians, aspect, znear, zfar, $this) {
    if (!$this) $this = new Uno.Camera;
    $this.dirty = 63;
    $this.Position(pos);
    $this.Target(target);
    $this.Up(up);
    $this.FovRadians(fovRadians);
    $this.Aspect(aspect);
    $this.ZNear(znear);
    $this.ZFar(zfar);
    return $this;
};
