-- ProjectFix
-- Fix for the project function to work with multiple active camera
--
-- @author:  	Stefan Geiger
-- @date:		22/12/11
-- @version:	v1.0
-- @history:	v1.0 - initial implementation

local oldProject = project;
local fixApplied = false;

EventListener = {};
function EventListener:loadMap(name)

    if not fixApplied then
        fixApplied = true;

        local env = getfenv(0);
        env["project"] = function(x,y,z)
            local cam0 = getCamera(0);
            local cam1 = getCamera(1);
            if cam0 ~= 0 and cam1 ~= 0 then

                local width, height = getScreenModeInfo(getScreenMode());
                local fovy = getFovy(cam0);
                local nearPlane = getNearClip(cam0);
                local farPlane = getFarClip(cam0);

                local aspect = width/height;

                local h = 1 / math.tan(math.rad(fovy *0.5));
                local w = h / aspect;

                local deltaZ = farPlane - nearPlane;
                local q = -(farPlane + nearPlane) / deltaZ;
                local qn = -2 * (farPlane * nearPlane) / deltaZ;

                -- Proj =
                -- [ w  0  0  0 ]
                -- [ 0  h  0  0 ]
                -- [ 0  0  q  qn]
                -- [ 0  0  -1 0 ]

                local x,y,z = worldToLocal(cam0, x,y,z);

                -- calculate Proj * (x,y,z,1) / (Proj * (x,y,z,1)).w
                local oneOverPw = -1/z;
                local px = w * x * oneOverPw;
                local py = h * y * oneOverPw;
                local pz = (q * z + qn) * oneOverPw;

                return px * 0.5 + 0.5, py * 0.5 + 0.5, pz * 0.5 + 0.5;
            end;
            return oldProject(x,y,z);
        end;
    end;
end;

function EventListener:deleteMap()
end;

function EventListener:mouseEvent(posX, posY, isDown, isUp, button)
end;

function EventListener:keyEvent(unicode, sym, modifier, isDown)
end;

function EventListener:update(dt)
end;

function EventListener:draw()
end;

addModEventListener(EventListener);