/* kd: In open-gl, your screen rotates nicely and you can do mostly what you know to be sane. It's all about making a rotation of your view and using what you know about right triangles. */ class dtLe_GlScreen : dtLe_ProjScreen { protected vector3 forw_unit; protected vector3 right_unit; protected vector3 down_unit; override void Reorient (vector3 world_view_pos, vector3 world_ang) { // kd: Pitch is a weird gzd joke. It's probably to compensate looking // speed and all. After that, you see what makes this fast. world_ang.y = VectorAngle( cos(world_ang.y), sin(world_ang.y) * pixel_stretch); super.Reorient(world_view_pos, world_ang); let cosang = cos(world_ang.x); let cosvang = cos(world_ang.y); let cosrang = cos(world_ang.z); let sinang = sin(world_ang.x); let sinvang = sin(world_ang.y); let sinrang = sin(world_ang.z); let right_no_roll = ( sinang, - cosang, 0); let down_no_roll = ( - sinvang * cosang, - sinvang * sinang, - cosvang); forw_unit = ( cosvang * cosang, cosvang * sinang, - sinvang); down_unit = cosrang * down_no_roll - sinrang * right_no_roll; right_unit = cosrang * right_no_roll + sinrang * down_no_roll; } // kd: Projection handling. These get called to make stuff a little faster, // since you may wanna project many many times. protected vector3 forw_in; protected vector3 right_in; protected vector3 down_in; override void BeginProjection () { forw_in = forw_unit; right_in = right_unit / tan_fov_2.x; down_in = down_unit / tan_fov_2.y; forw_in.z *= pixel_stretch; right_in.z *= pixel_stretch; down_in.z *= pixel_stretch; } override void ProjectWorldPos (vector3 world_pos) { diff = levellocals.vec3diff(view_pos, world_pos); proj_pos = (diff dot right_in, diff dot down_in); depth = diff dot forw_in; } override void ProjectActorPos (Actor mo, vector3 offset, double t) { let inter_pos = mo.prev + t * (mo.pos - mo.prev); diff = levellocals.vec3diff(view_pos, inter_pos + offset); proj_pos = (diff dot right_in, diff dot down_in); depth = diff dot forw_in; } override void ProjectActorPosPortal (Actor mo, vector3 offset, double t) { let inter_pos = mo.prev + t * levellocals.vec3diff(mo.prev, mo.pos); diff = levellocals.vec3diff(view_pos, inter_pos + offset); proj_pos = (diff dot right_in, diff dot down_in); depth = diff dot forw_in; } override vector2 ProjectToNormal () const { return proj_pos / depth; } override vector2 ProjectToScreen () const { let normal_pos = proj_pos / depth + (1, 1); return 0.5 * ( normal_pos.x * resolution.x, normal_pos.y * resolution.y); } override vector2 ProjectToCustom ( vector2 origin, vector2 resolution) const { let normal_pos = proj_pos / depth + (1, 1); return origin + 0.5 * ( normal_pos.x * resolution.x, normal_pos.y * resolution.y); } // kd: Same deal but backwards-ish. protected vector3 forw_out; protected vector3 right_out; protected vector3 down_out; override void BeginDeprojection () { // kd: Same deal as above, but reversed. This time, we're compensating // for what we rightfully assume is a projected position. forw_out = forw_unit; right_out = right_unit * tan_fov_2.x; down_out = down_unit * tan_fov_2.y; forw_out.z /= pixel_stretch; right_out.z /= pixel_stretch; down_out.z /= pixel_stretch; } override vector3 DeprojectNormalToDiff ( vector2 normal_pos, double depth) const { return depth * ( forw_out + normal_pos.x * right_out + normal_pos.y * down_out); } override vector3 DeprojectScreenToDiff ( vector2 screen_pos, double depth) const { // kd: Same thing... let normal_pos = 2 * ( screen_pos.x / resolution.x, screen_pos.y / resolution.y) - (1, 1); return depth * ( forw_out + normal_pos.x * right_out + normal_pos.y * down_out); } }