//compares projected world points to the expected corner points and calculates the total square distance private static float CalcValue(KeystoningSpecification spec, Camera camera, Matrix4x4 originalProjectionMatrix, KeystoningCorners corners, RUISDisplay display, bool firstPhase)//, Vector3[] worldPoints) { Vector2[] untransformedCorners = KeystoningCorners.untransformedCorners; float distanceFromCorners = 0; // sum of squared distances for (int pnum = 0; pnum < 4; pnum++) { // transformed coordinates (should match ’corners’ as good // as possible) float w = spec.m * untransformedCorners[pnum].x + spec.n * untransformedCorners[pnum].y + 1; float tx = (spec.a * untransformedCorners[pnum].x + spec.b * untransformedCorners[pnum].y + spec.d) / w; float ty = (spec.e * untransformedCorners[pnum].x + spec.f * untransformedCorners[pnum].y + spec.h) / w; Vector2 transformedCorner = corners.GetCornerNormalizedViewpointCoordinates(pnum); distanceFromCorners += Vector2.SqrMagnitude(new Vector2(tx, ty) - transformedCorner); if (float.IsNaN(distanceFromCorners)) { Debug.Log("was nan " + w + " " + pnum + " " + tx + " " + ty); break; } } return distanceFromCorners; //Debug.Log(CreateKeystonedMatrix(a, b, d, e, f, h, m, n)); //camera.projectionMatrix = originalProjectionMatrix * spec.GetMatrix(); /*Vector2[] newPoints = new Vector2[worldPoints.Length]; for(int i = 0; i < worldPoints.Length; i++) { newPoints[i] = camera.WorldToViewportPoint(worldPoints[i]); }*/ /*Vector2[] newPoints = new Vector2[10]; newPoints[0] = camera.WorldToViewportPoint(display.TopLeftPosition); newPoints[1] = camera.WorldToViewportPoint(display.TopRightPosition); newPoints[2] = camera.WorldToViewportPoint(display.BottomRightPosition); newPoints[3] = camera.WorldToViewportPoint(display.BottomLeftPosition); newPoints[4] = camera.WorldToViewportPoint(display.displayCenterPosition); newPoints[5] = camera.WorldToViewportPoint(display.TopLeftPosition + (display.TopLeftPosition - camera.transform.position) * 10); newPoints[6] = camera.WorldToViewportPoint(display.TopRightPosition + (display.TopRightPosition - camera.transform.position) * 10); newPoints[7] = camera.WorldToViewportPoint(display.BottomRightPosition + (display.BottomRightPosition - camera.transform.position) * 10); newPoints[8] = camera.WorldToViewportPoint(display.BottomLeftPosition + (display.BottomLeftPosition - camera.transform.position) * 10); newPoints[9] = camera.WorldToViewportPoint(display.displayCenterPosition + (display.displayCenterPosition - camera.transform.position) * 10); float distanceFromCorners = 0; // sum of squared distances for (int i = 0; i < (firstPhase ? 3 : 4); i++) { distanceFromCorners += (corners[i] - newPoints[i]).sqrMagnitude; distanceFromCorners += (corners[i] - newPoints[i+5]).sqrMagnitude; } if(!firstPhase){ Vector2 diagonalCenter = corners.GetDiagonalCenter(); distanceFromCorners += (diagonalCenter - newPoints[4]).sqrMagnitude; distanceFromCorners += (diagonalCenter - newPoints[9]).sqrMagnitude; } //distanceFromCorners += (diagonalCenter - newPoints[9]).sqrMagnitude; return distanceFromCorners;*/ }
//compares projected world points to the expected corner points and calculates the total square distance private static float CalcValue(KeystoningSpecification spec, Camera camera, Matrix4x4 originalProjectionMatrix, KeystoningCorners corners, RUISDisplay display, bool firstPhase)//, Vector3[] worldPoints) { Vector2[] untransformedCorners = KeystoningCorners.untransformedCorners; float distanceFromCorners = 0; // sum of squared distances for (int pnum = 0; pnum < 4; pnum++) { // transformed coordinates (should match ’corners’ as good // as possible) float w = spec.m * untransformedCorners[pnum].x + spec.n * untransformedCorners[pnum].y + 1; float tx = (spec.a * untransformedCorners[pnum].x + spec.b * untransformedCorners[pnum].y + spec.d) / w; float ty = (spec.e * untransformedCorners[pnum].x + spec.f * untransformedCorners[pnum].y + spec.h) / w; Vector2 transformedCorner = corners.GetCornerNormalizedViewpointCoordinates(pnum); distanceFromCorners += Vector2.SqrMagnitude(new Vector2(tx, ty) - transformedCorner); if (float.IsNaN(distanceFromCorners)) { Debug.Log("was nan " + w + " " + pnum + " " + tx + " " + ty); break; } } return(distanceFromCorners); //Debug.Log(CreateKeystonedMatrix(a, b, d, e, f, h, m, n)); //camera.projectionMatrix = originalProjectionMatrix * spec.GetMatrix(); /*Vector2[] newPoints = new Vector2[worldPoints.Length]; * for(int i = 0; i < worldPoints.Length; i++) * { * newPoints[i] = camera.WorldToViewportPoint(worldPoints[i]); * }*/ /*Vector2[] newPoints = new Vector2[10]; * newPoints[0] = camera.WorldToViewportPoint(display.TopLeftPosition); * newPoints[1] = camera.WorldToViewportPoint(display.TopRightPosition); * newPoints[2] = camera.WorldToViewportPoint(display.BottomRightPosition); * newPoints[3] = camera.WorldToViewportPoint(display.BottomLeftPosition); * newPoints[4] = camera.WorldToViewportPoint(display.displayCenterPosition); * newPoints[5] = camera.WorldToViewportPoint(display.TopLeftPosition + (display.TopLeftPosition - camera.transform.position) * 10); * newPoints[6] = camera.WorldToViewportPoint(display.TopRightPosition + (display.TopRightPosition - camera.transform.position) * 10); * newPoints[7] = camera.WorldToViewportPoint(display.BottomRightPosition + (display.BottomRightPosition - camera.transform.position) * 10); * newPoints[8] = camera.WorldToViewportPoint(display.BottomLeftPosition + (display.BottomLeftPosition - camera.transform.position) * 10); * newPoints[9] = camera.WorldToViewportPoint(display.displayCenterPosition + (display.displayCenterPosition - camera.transform.position) * 10); * * * float distanceFromCorners = 0; // sum of squared distances * for (int i = 0; i < (firstPhase ? 3 : 4); i++) * { * distanceFromCorners += (corners[i] - newPoints[i]).sqrMagnitude; * distanceFromCorners += (corners[i] - newPoints[i+5]).sqrMagnitude; * } * * if(!firstPhase){ * Vector2 diagonalCenter = corners.GetDiagonalCenter(); * distanceFromCorners += (diagonalCenter - newPoints[4]).sqrMagnitude; * distanceFromCorners += (diagonalCenter - newPoints[9]).sqrMagnitude; * } * //distanceFromCorners += (diagonalCenter - newPoints[9]).sqrMagnitude; * * return distanceFromCorners;*/ }
public static float Optimize(Camera camera, Matrix4x4 originalProjectionMatrix, RUISDisplay display, KeystoningCorners corners, ref KeystoningSpecification spec) { if (!spec.isValid) Debug.Log("INVALID SPEC"); spec = /*spec != null && spec.isValid ? spec : */new KeystoningSpecification(); //Debug.Log(spec.GetMatrix()); //save all the relevant world points that we use for optimizing the keystoning matrix //camera.projectionMatrix = originalProjectionMatrix; /*Vector3[] worldPoints = new Vector3[10]; worldPoints[0] = camera.ViewportToWorldPoint(new Vector3(0, 1, camera.nearClipPlane)); worldPoints[1] = camera.ViewportToWorldPoint(new Vector3(1, 1, camera.nearClipPlane)); worldPoints[2] = camera.ViewportToWorldPoint(new Vector3(1, 0, camera.nearClipPlane)); worldPoints[3] = camera.ViewportToWorldPoint(new Vector3(0, 0, camera.nearClipPlane)); worldPoints[4] = camera.ViewportToWorldPoint(new Vector3(0, 1, camera.farClipPlane)); worldPoints[5] = camera.ViewportToWorldPoint(new Vector3(1, 1, camera.farClipPlane)); worldPoints[6] = camera.ViewportToWorldPoint(new Vector3(1, 0, camera.farClipPlane)); worldPoints[7] = camera.ViewportToWorldPoint(new Vector3(0, 0, camera.farClipPlane)); worldPoints[8] = camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, camera.nearClipPlane)); worldPoints[9] = camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, camera.farClipPlane)); */ /*Debug.Log("---------------------------------------------------------------"); foreach (Vector3 worldPoint in worldPoints) { Debug.Log(worldPoint); Debug.Log(camera.WorldToViewportPoint(worldPoint)); } Debug.Log("--------------------------------------------------------------");*/ float stepSize = 0.1f; float[] grad = new float[amountOfParameters]; float currentValue = 0; /*while (stepSize > 0.000001f) { // compute gradient currentValue = CalcValue(spec, camera, originalProjectionMatrix, corners, display, true); Debug.Log("**********************************************"); foreach (Vector3 worldPoint in worldPoints) { Debug.Log(camera.WorldToViewportPoint(worldPoint)); } Debug.Log("**********************************************"); //Debug.Log(currentValue); for (int i = 0; i < amountOfParameters-2; i++) { grad[i] = CalcValue(spec.ModifyWithStep(i, 0.1f * stepSize), camera, originalProjectionMatrix, corners, display, true) - currentValue; } // step in direction of gradient with length of stepSize float gradSquaredLength = 0; for (int i = 0; i < amountOfParameters-2; i++) { gradSquaredLength += grad[i] * grad[i]; } float gradLength = Mathf.Sqrt((float)gradSquaredLength); for (int i = 0; i < amountOfParameters-2; i++) { spec = spec.ModifyWithStep(i, -stepSize * grad[i] / gradLength); } stepSize *= 0.99f; } */ stepSize = 0.1f; grad = new float[amountOfParameters]; currentValue = 0; while (stepSize > 0.000001f) //for(int iterations = 0; iterations < 10; iterations++) { // compute gradient currentValue = CalcValue(spec, camera, originalProjectionMatrix, corners, display, false); for (int i = 0; i < amountOfParameters; i++) { grad[i] = CalcValue(spec.ModifyWithStep(i, 0.1f * stepSize), camera, originalProjectionMatrix, corners, display, false) - currentValue; } // step in direction of gradient with length of stepSize float gradSquaredLength = 0; for (int i = 0; i < amountOfParameters; i++) { gradSquaredLength += grad[i] * grad[i]; } float gradLength = Mathf.Sqrt((float)gradSquaredLength); if (gradLength == 0) Debug.Log("CAUTIOOOOOOOOOOOOON"); for (int i = 0; i < amountOfParameters; i++) { spec = spec.ModifyWithStep(i, -stepSize * grad[i] / gradLength); } stepSize *= 0.99f; } //Debug.Log("final: " + spec.GetMatrix()); //Debug.Log("currentValue: " + currentValue); return currentValue; }
public static float Optimize(Camera camera, Matrix4x4 originalProjectionMatrix, RUISDisplay display, KeystoningCorners corners, ref KeystoningSpecification spec) { if (!spec.isValid) { Debug.Log("INVALID SPEC"); } spec = /*spec != null && spec.isValid ? spec : */ new KeystoningSpecification(); //Debug.Log(spec.GetMatrix()); //save all the relevant world points that we use for optimizing the keystoning matrix //camera.projectionMatrix = originalProjectionMatrix; /*Vector3[] worldPoints = new Vector3[10]; * worldPoints[0] = camera.ViewportToWorldPoint(new Vector3(0, 1, camera.nearClipPlane)); * worldPoints[1] = camera.ViewportToWorldPoint(new Vector3(1, 1, camera.nearClipPlane)); * worldPoints[2] = camera.ViewportToWorldPoint(new Vector3(1, 0, camera.nearClipPlane)); * worldPoints[3] = camera.ViewportToWorldPoint(new Vector3(0, 0, camera.nearClipPlane)); * worldPoints[4] = camera.ViewportToWorldPoint(new Vector3(0, 1, camera.farClipPlane)); * worldPoints[5] = camera.ViewportToWorldPoint(new Vector3(1, 1, camera.farClipPlane)); * worldPoints[6] = camera.ViewportToWorldPoint(new Vector3(1, 0, camera.farClipPlane)); * worldPoints[7] = camera.ViewportToWorldPoint(new Vector3(0, 0, camera.farClipPlane)); * worldPoints[8] = camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, camera.nearClipPlane)); * worldPoints[9] = camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, camera.farClipPlane)); */ /*Debug.Log("---------------------------------------------------------------"); * foreach (Vector3 worldPoint in worldPoints) * { * Debug.Log(worldPoint); * Debug.Log(camera.WorldToViewportPoint(worldPoint)); * } * Debug.Log("--------------------------------------------------------------");*/ float stepSize = 0.1f; float[] grad = new float[amountOfParameters]; float currentValue = 0; /*while (stepSize > 0.000001f) * { * // compute gradient * * currentValue = CalcValue(spec, camera, originalProjectionMatrix, corners, display, true); * * * Debug.Log("**********************************************"); * foreach (Vector3 worldPoint in worldPoints) * { * Debug.Log(camera.WorldToViewportPoint(worldPoint)); * } * Debug.Log("**********************************************"); * * //Debug.Log(currentValue); * for (int i = 0; i < amountOfParameters-2; i++) * { * grad[i] = CalcValue(spec.ModifyWithStep(i, 0.1f * stepSize), camera, originalProjectionMatrix, corners, display, true) - currentValue; * } * * // step in direction of gradient with length of stepSize * float gradSquaredLength = 0; * for (int i = 0; i < amountOfParameters-2; i++) * { * gradSquaredLength += grad[i] * grad[i]; * } * float gradLength = Mathf.Sqrt((float)gradSquaredLength); * for (int i = 0; i < amountOfParameters-2; i++) * { * spec = spec.ModifyWithStep(i, -stepSize * grad[i] / gradLength); * } * stepSize *= 0.99f; * } */ stepSize = 0.1f; grad = new float[amountOfParameters]; currentValue = 0; while (stepSize > 0.000001f) //for(int iterations = 0; iterations < 10; iterations++) { // compute gradient currentValue = CalcValue(spec, camera, originalProjectionMatrix, corners, display, false); for (int i = 0; i < amountOfParameters; i++) { grad[i] = CalcValue(spec.ModifyWithStep(i, 0.1f * stepSize), camera, originalProjectionMatrix, corners, display, false) - currentValue; } // step in direction of gradient with length of stepSize float gradSquaredLength = 0; for (int i = 0; i < amountOfParameters; i++) { gradSquaredLength += grad[i] * grad[i]; } float gradLength = Mathf.Sqrt((float)gradSquaredLength); if (gradLength == 0) { Debug.Log("CAUTIOOOOOOOOOOOOON"); } for (int i = 0; i < amountOfParameters; i++) { spec = spec.ModifyWithStep(i, -stepSize * grad[i] / gradLength); } stepSize *= 0.99f; } //Debug.Log("final: " + spec.GetMatrix()); //Debug.Log("currentValue: " + currentValue); return(currentValue); }