You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
14 KiB
401 lines
14 KiB
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace UC
|
|
{
|
|
public class DoHomography : MonoBehaviour
|
|
{
|
|
[AutoUI(AutoUIAttribute.BindingFlag.NonSerialized)]
|
|
public static bool show = false;
|
|
[AutoUI(AutoUIAttribute.BindingFlag.NonSerialized)]
|
|
public bool reset = false;
|
|
[AutoUI]
|
|
public Vector2 resolution;
|
|
|
|
private Vector4 textureSize;
|
|
public Texture cornerTexture;
|
|
|
|
[AutoUI]
|
|
public Vector2 destination1;
|
|
[AutoUI]
|
|
public Vector2 destination2;
|
|
[AutoUI]
|
|
public Vector2 destination3;
|
|
[AutoUI]
|
|
public Vector2 destination4;
|
|
|
|
[AutoUI]
|
|
public float cornerSize = 30;
|
|
|
|
private Vector2[] source = new Vector2[4];
|
|
private Vector2[] destination = new Vector2[4];
|
|
|
|
//public Camera targetCamera;
|
|
private List<UIDragableObj> corners = null;
|
|
public GameObject cornerCanvas;
|
|
|
|
public Material mat;
|
|
|
|
private static Matrix4x4 homo = new Matrix4x4();
|
|
public static Matrix4x4 gethomo { get { return homo; } }
|
|
|
|
public RectTransform homoImagerect;
|
|
|
|
public RenderTexture homoTexture;
|
|
|
|
UIDragableObj GenerateCorner(string name)
|
|
{
|
|
//var obj = Instantiate(new GameObject(), transform);
|
|
var obj = new GameObject();
|
|
obj.layer = LayerMask.NameToLayer("NoneSpout");
|
|
obj.transform.parent = transform;
|
|
obj.transform.localPosition = Vector3.zero;
|
|
obj.name = name;
|
|
var raw_image = obj.AddComponent<RawImage>();
|
|
raw_image.color = new Color(189.0f / 255.0f, 73.0f / 255.0f, 50.0f / 255.0f,0);
|
|
raw_image.texture = cornerTexture;
|
|
var rt = obj.GetComponent<RectTransform>();
|
|
rt.sizeDelta = new Vector2(cornerSize, cornerSize);
|
|
var corner = obj.AddComponent<UIDragableObj>();
|
|
return corner;
|
|
}
|
|
|
|
void ResetCorners()
|
|
{
|
|
if (corners == null)
|
|
{
|
|
corners = new List<UIDragableObj>();
|
|
corners.Add(GenerateCorner("TopLeft"));
|
|
corners.Add(GenerateCorner("TopRight"));
|
|
corners.Add(GenerateCorner("BottomRight"));
|
|
corners.Add(GenerateCorner("BottomLeft"));
|
|
}
|
|
|
|
destination[0] = corners[0].position = new Vector2(-resolution.x, resolution.y)/2;
|
|
destination[1] = corners[1].position = new Vector2(resolution.x, resolution.y)/2;
|
|
destination[2] = corners[2].position = new Vector2(resolution.x, -resolution.y)/2;
|
|
destination[3] = corners[3].position = new Vector2(-resolution.x, -resolution.y)/2;
|
|
|
|
source[0] = new Vector2((-resolution.x )/ (float)Screen.width , (resolution.y ) / (float)Screen.height );
|
|
source[1] = new Vector2((resolution.x ) / (float)Screen.width , (resolution.y) / (float)Screen.height );
|
|
source[2] = new Vector2((resolution.x ) / (float)Screen.width , (-resolution.y ) / (float)Screen.height );
|
|
source[3] = new Vector2((-resolution.x ) / (float)Screen.width , (-resolution.y ) / (float)Screen.height );
|
|
foreach (Vector2 vec in source)
|
|
print(vec);
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
ResetCorners();
|
|
//homoImagerect.sizeDelta = resolution;
|
|
homoImagerect.GetComponent<RawImage>().texture = homoTexture;
|
|
Vector2 des_scale = new Vector2( (float)Screen.width / 2.0f, (float)Screen.height / 2.0f);
|
|
corners[0].position = Vector2.Scale(destination1, des_scale);
|
|
corners[1].position = Vector2.Scale(destination2, des_scale);
|
|
corners[2].position = Vector2.Scale(destination3, des_scale);
|
|
corners[3].position = Vector2.Scale(destination4, des_scale);
|
|
DoHomo();
|
|
ViewCorner();
|
|
lines = new GUILine[4];
|
|
for (int i = 0; i < lines.Length; i++)
|
|
{
|
|
lines[i] = new GUILine();
|
|
}
|
|
SetLinePos();
|
|
/*
|
|
destination[0] = new Vector2(0, 0); // TL
|
|
destination[1] = new Vector2(1, 0); // TR
|
|
destination[2] = new Vector2(0, 1); // BL
|
|
destination[3] = new Vector2(1, 1); // BR
|
|
*/
|
|
//textureSize = new Vector4(resolution.x, resolution.y, 0, 0);
|
|
|
|
}
|
|
|
|
void SetLinePos()
|
|
{
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
{
|
|
if(i+1 < lines.Length)
|
|
{
|
|
lines[i].startPt = corners[i].position + (new Vector2((float)Screen.width, (float)Screen.height) /2) ;
|
|
lines[i].endPt = corners[i+1].position + (new Vector2((float)Screen.width, (float)Screen.height) / 2);
|
|
// print(destination[i] + ";"+ destination[i+1]);
|
|
}
|
|
else
|
|
{
|
|
lines[i].startPt = corners[i].position + (new Vector2((float)Screen.width, (float)Screen.height) / 2);
|
|
lines[i].endPt = corners[0].position + (new Vector2((float)Screen.width, (float)Screen.height) / 2);
|
|
|
|
}
|
|
|
|
lines[i].startPt.y = Screen.height -lines[i].startPt.y;
|
|
lines[i].endPt.y = Screen.height - lines[i].endPt.y;
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
#if false
|
|
if (reset)
|
|
{
|
|
reset = false;
|
|
ResetCorners();
|
|
}
|
|
|
|
if (Input.GetKeyDown(KeyCode.F2))
|
|
{
|
|
show = !show;
|
|
}
|
|
|
|
var cg = GetComponent<CanvasGroup>();
|
|
cg.alpha = show ? 1.0f : 0.0f;
|
|
cg.interactable = cg.blocksRaycasts = show;
|
|
|
|
|
|
|
|
for (int i = 0; i < source.Length; i++)
|
|
{
|
|
source[i] = corners[i].position;
|
|
}
|
|
|
|
Vector2 mul = new Vector2(1.0f / resolution.x, 1.0f / resolution.y);
|
|
|
|
for (int i = 0; i <= 3; i++)
|
|
{
|
|
source[i].y = resolution.y - source[i].y;
|
|
source[i] = Vector2.Scale(source[i], mul);
|
|
}
|
|
|
|
|
|
var homography = targetCamera.GetComponent<ScreenHomography>();
|
|
if (homography == null)
|
|
homography = targetCamera.gameObject.AddComponent<ScreenHomography>();
|
|
|
|
homography.material.SetMatrix("matrixHomo", homo);
|
|
homography.material.SetVector("textureSize", textureSize);
|
|
#endif
|
|
ViewCorner();
|
|
|
|
if (Input.GetKeyDown(KeyCode.C))
|
|
{
|
|
show = !show;
|
|
ViewCorner();
|
|
}
|
|
|
|
if (!show)
|
|
return;
|
|
|
|
DoHomo();
|
|
|
|
}
|
|
|
|
void ViewCorner()
|
|
{
|
|
foreach (UIDragableObj homocorner in corners)
|
|
{
|
|
homocorner.gameObject.SetActive(show);
|
|
}
|
|
}
|
|
|
|
void DoHomo()
|
|
{
|
|
Vector2 des_scale = new Vector2(2.0f / (float)Screen.width, 2.0f / (float)Screen.height);
|
|
for (int i = 0; i < destination.Length; i++)
|
|
{
|
|
destination[i] = corners[i].position;
|
|
|
|
destination[i].y = -destination[i].y;
|
|
SetLinePos();
|
|
destination[i] = Vector2.Scale(destination[i], des_scale);
|
|
}
|
|
destination1 = destination[0];
|
|
destination2 = destination[1];
|
|
destination3 = destination[2];
|
|
destination4 = destination[3];
|
|
destination1.y = -destination1.y;
|
|
destination2.y = -destination2.y;
|
|
destination3.y = -destination3.y;
|
|
destination4.y = -destination4.y;
|
|
|
|
FindHomography(ref source, ref destination, ref homo);
|
|
|
|
mat.SetMatrix("matrixH", homo);
|
|
}
|
|
|
|
|
|
public struct GUILine
|
|
{
|
|
public Vector2 startPt;
|
|
public Vector2 endPt;
|
|
}
|
|
|
|
private GUILine[] lines = new GUILine[4];
|
|
private float length = 10;
|
|
private void OnGUI()
|
|
{
|
|
if(show)
|
|
{
|
|
foreach (GUILine line in lines)
|
|
{
|
|
Texture2D lineTex = new Texture2D(10, 10);
|
|
Matrix4x4 matrixBackup = GUI.matrix;
|
|
float width = 8.0f;
|
|
GUI.color = Color.red;
|
|
length = (line.startPt - line.endPt).magnitude;
|
|
float angle = Mathf.Atan2(line.endPt.y - line.startPt.y, line.endPt.x - line.startPt.x) * 180f / Mathf.PI;
|
|
|
|
GUIUtility.RotateAroundPivot(angle, line.startPt);
|
|
GUI.DrawTexture(new Rect(line.startPt.x,line.startPt.y, length, width), lineTex);
|
|
GUI.matrix = matrixBackup;
|
|
float t_size = 60;
|
|
GUI.DrawTexture(new Rect(line.startPt.x - t_size/2, line.startPt.y - t_size/2, t_size, t_size), lineTex);
|
|
|
|
}
|
|
}
|
|
}
|
|
void setLinePoints(GUILine line)
|
|
{
|
|
line.startPt = setPoint(line.startPt);
|
|
line.endPt = setPoint(line.endPt);
|
|
length = (line.startPt - line.endPt).magnitude;
|
|
}
|
|
Vector2 setPoint(Vector2 point)
|
|
{
|
|
point.x = (int)point.x;
|
|
point.y = Screen.height - (int)point.y;
|
|
return point;
|
|
}
|
|
|
|
void DrawLine(Vector2 pointA, Vector2 pointB)
|
|
{
|
|
pointA = setPoint(pointA);
|
|
pointB = setPoint(pointB);
|
|
Texture2D lineTex = new Texture2D(1, 1);
|
|
Matrix4x4 matrixBackup = GUI.matrix;
|
|
float width = 8.0f;
|
|
GUI.color = Color.red;
|
|
float angle = Mathf.Atan2(pointB.y - pointA.y, pointB.x - pointA.x) * 180f / Mathf.PI;
|
|
|
|
GUIUtility.RotateAroundPivot(angle, pointA);
|
|
GUI.DrawTexture(new Rect(pointA.x, pointA.y, length, width), lineTex);
|
|
GUI.matrix = matrixBackup;
|
|
}
|
|
|
|
|
|
void FindHomography(ref Vector2[] src, ref Vector2[] dest, ref Matrix4x4 homography)
|
|
{
|
|
|
|
float[,] P = new float[,]{
|
|
{-src[0].x, -src[0].y, -1, 0, 0, 0, src[0].x*dest[0].x, src[0].y*dest[0].x, -dest[0].x }, // h11
|
|
{ 0, 0, 0, -src[0].x, -src[0].y, -1, src[0].x*dest[0].y, src[0].y*dest[0].y, -dest[0].y }, // h12
|
|
|
|
{-src[1].x, -src[1].y, -1, 0, 0, 0, src[1].x*dest[1].x, src[1].y*dest[1].x, -dest[1].x }, // h13
|
|
{ 0, 0, 0, -src[1].x, -src[1].y, -1, src[1].x*dest[1].y, src[1].y*dest[1].y, -dest[1].y }, // h21
|
|
|
|
{-src[2].x, -src[2].y, -1, 0, 0, 0, src[2].x*dest[2].x, src[2].y*dest[2].x, -dest[2].x }, // h22
|
|
{ 0, 0, 0, -src[2].x, -src[2].y, -1, src[2].x*dest[2].y, src[2].y*dest[2].y, -dest[2].y }, // h23
|
|
|
|
{-src[3].x, -src[3].y, -1, 0, 0, 0, src[3].x*dest[3].x, src[3].y*dest[3].x, -dest[3].x }, // h31
|
|
{ 0, 0, 0, -src[3].x, -src[3].y, -1, src[3].x*dest[3].y, src[3].y*dest[3].y, -dest[3].y }, // h32
|
|
};
|
|
|
|
GaussianElimination(ref P, 9);
|
|
|
|
float[] aux_H ={ P[0,8],P[3,8],0,P[6,8], // h11 h21 0 h31
|
|
P[1,8],P[4,8],0,P[7,8], // h12 h22 0 h32
|
|
0 , 0,1,0, // 0 0 0 0
|
|
P[2,8],P[5,8],0,1}; // h13 h23 0 h33
|
|
|
|
for (int i = 0; i < 16; i++) homography[i] = aux_H[i];
|
|
|
|
}
|
|
|
|
void GaussianElimination(ref float[,] A, int n)
|
|
{
|
|
|
|
int i = 0;
|
|
int j = 0;
|
|
int m = n - 1;
|
|
while (i < m && j < n)
|
|
{
|
|
|
|
int maxi = i;
|
|
for (int k = i + 1; k < m; k++)
|
|
{
|
|
if (Mathf.Abs(A[k, j]) > Mathf.Abs(A[maxi, j]))
|
|
{
|
|
maxi = k;
|
|
}
|
|
}
|
|
if (A[maxi, j] != 0)
|
|
{
|
|
|
|
if (i != maxi)
|
|
for (int k = 0; k < n; k++)
|
|
{
|
|
float aux = A[i, k];
|
|
A[i, k] = A[maxi, k];
|
|
A[maxi, k] = aux;
|
|
}
|
|
|
|
float A_ij = A[i, j];
|
|
for (int k = 0; k < n; k++)
|
|
{
|
|
A[i, k] /= A_ij;
|
|
}
|
|
|
|
for (int u = i + 1; u < m; u++)
|
|
{
|
|
|
|
float A_uj = A[u, j];
|
|
for (int k = 0; k < n; k++)
|
|
{
|
|
A[u, k] -= A_uj * A[i, k];
|
|
}
|
|
|
|
}
|
|
|
|
i++;
|
|
}
|
|
j++;
|
|
}
|
|
for (int k = m - 2; k >= 0; k--)
|
|
{
|
|
for (int l = k + 1; l < n - 1; l++)
|
|
{
|
|
A[k, m] -= A[k, l] * A[l, m];
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
public static Vector2 UIPosToHomographyPos(Vector2 vec)
|
|
{
|
|
vec.y = -vec.y;
|
|
vec = new Vector2(vec.x * 2 / (float)Screen.width, vec.y * 2 / (float)Screen.height);
|
|
|
|
Vector2 nnn_pos = new Vector2(Input.mousePosition.x, Input.mousePosition.y) - new Vector2(Screen.width, Screen.height) / 2;
|
|
Vector2 aa22 = new Vector2(Input.mousePosition.x, Input.mousePosition.y) - new Vector2(Screen.width, Screen.height) / 2;
|
|
Vector2 aa = nnn_pos;
|
|
nnn_pos.y = -nnn_pos.y;
|
|
nnn_pos = new Vector2(nnn_pos.x * 2 / (float)Screen.width, nnn_pos.y * 2 / (float)Screen.height);
|
|
nnn_pos = UC.DoHomography.gethomo.inverse.MultiplyPoint(nnn_pos);
|
|
nnn_pos.y = -nnn_pos.y;
|
|
nnn_pos = new Vector2(nnn_pos.x * (float)Screen.width / 2, nnn_pos.y * (float)Screen.height / 2);
|
|
nnn_pos = nnn_pos + new Vector2(Screen.width, Screen.height) / 2;
|
|
nnn_pos.y = Screen.height - nnn_pos.y;
|
|
nnn_pos = nnn_pos - new Vector2(Screen.width, Screen.height) / 2;
|
|
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|