Skip to content

Instantly share code, notes, and snippets.

@SabinT
Created March 25, 2024 06:29
Show Gist options
  • Save SabinT/3b8e643e1b4b245a119f03130e507805 to your computer and use it in GitHub Desktop.
Save SabinT/3b8e643e1b4b245a119f03130e507805 to your computer and use it in GitHub Desktop.
Square to Quad homography (credits: hecomi)
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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment