Skip to content

Instantly share code, notes, and snippets.

@SabinT
Created March 25, 2024 06:29
Show Gist options
  • Select an option

  • Save SabinT/3b8e643e1b4b245a119f03130e507805 to your computer and use it in GitHub Desktop.

Select an option

Save SabinT/3b8e643e1b4b245a119f03130e507805 to your computer and use it in GitHub Desktop.

Revisions

  1. SabinT created this gist Mar 25, 2024.
    75 changes: 75 additions & 0 deletions Homography.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,75 @@

    using UnityEngine;

    /// <summary>
    /// Utility to map points inside a unit square (0,0)-(1,1) to a quad defined by 4 points.
    /// Uses math from:
    /// https://github.com/hecomi/uHomography/blob/master/Assets/uHomography/Runtime/Scripts/Homography.cs
    /// Instructions to use for projection mapping:
    /// * Gather screen coordinates of four corner points, and call UpdateMatrix with them.
    /// * The Transform method now will map a point inside a unit square to an appropriate point on the screen quad.
    /// * Create a subdivided quad with both coordinates and uvs from (0,0)-(1,1)
    /// * Use the Transform method to get new coordinates, but keep the UVs the same.
    /// Hecomi's github contains a shader based implementation (no need to subdivide) if you want to investigate that further.
    /// </summary>
    public class Homography
    {
    private readonly float[] _matrix = new float[9];

    public Vector2 Transform(Vector2 pos)
    {
    if (_matrix == null)
    {
    return pos;
    }

    float s = _matrix[6] * pos.x + _matrix[7] * pos.y + _matrix[8];
    float x = (_matrix[0] * pos.x + _matrix[1] * pos.y + _matrix[2]) / s;
    float y = (_matrix[3] * pos.x + _matrix[4] * pos.y + _matrix[5]) / s;
    return new Vector2(x, y);
    }

    public void UpdateMatrix(Vector2 topLeft, Vector2 topRight, Vector2 bottomLeft, Vector2 bottomRight)
    {
    Vector2 p00 = bottomLeft;
    Vector2 p01 = bottomRight;
    Vector2 p10 = topLeft;
    Vector2 p11 = topRight;

    var x00 = p00.x;
    var y00 = p00.y;
    var x01 = p01.x;
    var y01 = p01.y;
    var x10 = p10.x;
    var y10 = p10.y;
    var x11 = p11.x;
    var y11 = p11.y;

    var a = x10 - x11;
    var b = x01 - x11;
    var c = x00 - x01 - x10 + x11;
    var d = y10 - y11;
    var e = y01 - y11;
    var f = y00 - y01 - y10 + y11;

    var h13 = x00;
    var h23 = y00;
    var h32 = (c * d - a * f) / (b * d - a * e);
    var h31 = (c * e - b * f) / (a * e - b * d);
    var h11 = x10 - x00 + h31 * x10;
    var h12 = x01 - x00 + h32 * x01;
    var h21 = y10 - y00 + h31 * y10;
    var h22 = y01 - y00 + h32 * y01;

    // Update existing array
    _matrix[0] = h11;
    _matrix[1] = h12;
    _matrix[2] = h13;
    _matrix[3] = h21;
    _matrix[4] = h22;
    _matrix[5] = h23;
    _matrix[6] = h31;
    _matrix[7] = h32;
    _matrix[8] = 1f;
    }
    }