public Ray ScreenPointToRay(Vector2 screenPoint) { RUISDisplay display = GetDisplayForScreenPoint(screenPoint); if (display) { Camera camera = display.GetCameraForScreenPoint(screenPoint); if (camera) { if (display.enableOculusRift) { screenPoint = display.ConvertOculusScreenPoint(screenPoint); return(camera.ScreenPointToRay(screenPoint)); } else { return(camera.ScreenPointToRay(screenPoint)); } } } return(new Ray(Vector3.zero, Vector3.zero)); }
public static bool ImportDisplay(RUISDisplay display, string filename, TextAsset displaySchema, bool loadFromFileInEditor) { XmlDocument xmlDoc = XMLUtil.LoadAndValidateXml(filename, displaySchema); if (xmlDoc == null) { return(false); } if (Application.isEditor && loadFromFileInEditor) { display.displayCenterPosition = XMLUtil.GetVector3FromXmlNode(xmlDoc.GetElementsByTagName("displayCenterPosition").Item(0)); display.displayUpInternal = XMLUtil.GetVector3FromXmlNode(xmlDoc.GetElementsByTagName("displayUp").Item(0)); display.displayNormalInternal = XMLUtil.GetVector3FromXmlNode(xmlDoc.GetElementsByTagName("displayNormal").Item(0)); display.width = float.Parse(xmlDoc.GetElementsByTagName("displaySize").Item(0).Attributes["width"].Value); display.height = float.Parse(xmlDoc.GetElementsByTagName("displaySize").Item(0).Attributes["height"].Value); display.resolutionX = int.Parse(xmlDoc.GetElementsByTagName("displayResolution").Item(0).Attributes["width"].Value); display.resolutionY = int.Parse(xmlDoc.GetElementsByTagName("displayResolution").Item(0).Attributes["height"].Value); } if (display.linkedCamera) { display.linkedCamera.LoadKeystoningFromXML(xmlDoc); } return(true); }
// Use this for initialization void Start() { try { Input.GetButtonDown("RUISMenu"); } catch (UnityException) { ruisMenuButtonDefined = false; } inputManager = FindObjectOfType(typeof(RUISInputManager)) as RUISInputManager; enablePSMove = inputManager.enablePSMove; psMoveIP = inputManager.PSMoveIP; psMovePort = inputManager.PSMovePort; jumpGesture = FindObjectOfType(typeof(RUISJumpGestureRecognizer)) as RUISJumpGestureRecognizer; displayManager = FindObjectOfType(typeof(RUISDisplayManager)) as RUISDisplayManager; riftDisplay = displayManager.GetOculusRiftDisplay(); // TODO: This menu should work with any stereo view, not just Rift. riftDisplay.linkedCamera is null when Rift is disabled. if (oculusRiftMenu && riftDisplay && riftDisplay.linkedCamera) { windowRect = new Rect(riftDisplay.linkedCamera.leftCamera.pixelRect.x + riftDisplay.resolutionX / 4 - 100, riftDisplay.resolutionY / 2 - 220, 250, 250); } SaveInputChanges(); }
public Ray ScreenPointToRay(Vector2 screenPoint) { RUISDisplay display = GetDisplayForScreenPoint(screenPoint); if (display) { Camera camera = display.GetCameraForScreenPoint(screenPoint); if (camera) { return(camera.ScreenPointToRay(screenPoint)); } } return(new Ray(Vector3.zero, Vector3.zero)); }
public static bool ExportDisplay(RUISDisplay display, string xmlFilename) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "yes"); XmlElement displayRootElement = xmlDoc.CreateElement("ns2", "ruisDisplay", "http://ruisystem.net/display"); xmlDoc.AppendChild(displayRootElement); XmlElement displayCenterPositionElement = xmlDoc.CreateElement("displayCenterPosition"); XMLUtil.WriteVector3ToXmlElement(displayCenterPositionElement, display.displayCenterPosition); displayRootElement.AppendChild(displayCenterPositionElement); XmlElement displayUpElement = xmlDoc.CreateElement("displayUp"); XMLUtil.WriteVector3ToXmlElement(displayUpElement, display.displayUpInternal); displayRootElement.AppendChild(displayUpElement); XmlElement displayNormalElement = xmlDoc.CreateElement("displayNormal"); XMLUtil.WriteVector3ToXmlElement(displayNormalElement, display.displayNormalInternal); displayRootElement.AppendChild(displayNormalElement); XmlElement displaySizeElement = xmlDoc.CreateElement("displaySize"); displaySizeElement.SetAttribute("width", display.width.ToString()); displaySizeElement.SetAttribute("height", display.height.ToString()); displayRootElement.AppendChild(displaySizeElement); XmlElement displayResolutionElement = xmlDoc.CreateElement("displayResolution"); displayResolutionElement.SetAttribute("width", display.resolutionX.ToString()); displayResolutionElement.SetAttribute("height", display.resolutionY.ToString()); displayRootElement.AppendChild(displayResolutionElement); display.linkedCamera.SaveKeystoningToXML(displayRootElement); XMLUtil.SaveXmlToFile(xmlFilename, xmlDoc); return(true); }
// TODO: Depends on OVR version IEnumerator ForceOculusSettings(float waitTime) { yield return(new WaitForSeconds(waitTime)); OVRManager.DismissHSWDisplay(); // Enforce Low Persistence settings // TODO: In the distant future it might be possible to have multiple Rifts in the same computer with different LP settings? RUISDisplay oculusDisplay = GetOculusRiftDisplay(); if (oculusDisplay) { // HACK: Counter hack to OVRDisplays hack which forces LP on in the first frame for (int i = 0; i < 2; ++i) { if (oculusDisplay.oculusLowPersistence != getOculusLowPersistence()) { setOculusLowPersistence(oculusDisplay.oculusLowPersistence); } yield return(new WaitForSeconds(2)); } } }
public static bool ExportDisplay(RUISDisplay display, string xmlFilename) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "yes"); XmlElement displayRootElement = xmlDoc.CreateElement("ns2", "ruisDisplay", "http://ruisystem.net/display"); xmlDoc.AppendChild(displayRootElement); XmlElement displayCenterPositionElement = xmlDoc.CreateElement("displayCenterPosition"); XMLUtil.WriteVector3ToXmlElement(displayCenterPositionElement, display.displayCenterPosition); displayRootElement.AppendChild(displayCenterPositionElement); XmlElement displayUpElement = xmlDoc.CreateElement("displayUp"); XMLUtil.WriteVector3ToXmlElement(displayUpElement, display.displayUpInternal); displayRootElement.AppendChild(displayUpElement); XmlElement displayNormalElement = xmlDoc.CreateElement("displayNormal"); XMLUtil.WriteVector3ToXmlElement(displayNormalElement, display.displayNormalInternal); displayRootElement.AppendChild(displayNormalElement); XmlElement displaySizeElement = xmlDoc.CreateElement("displaySize"); displaySizeElement.SetAttribute("width", display.width.ToString()); displaySizeElement.SetAttribute("height", display.height.ToString()); displayRootElement.AppendChild(displaySizeElement); XmlElement displayResolutionElement = xmlDoc.CreateElement("displayResolution"); displayResolutionElement.SetAttribute("width", display.resolutionX.ToString()); displayResolutionElement.SetAttribute("height", display.resolutionY.ToString()); displayRootElement.AppendChild(displayResolutionElement); display.linkedCamera.SaveKeystoningToXML(displayRootElement); XMLUtil.SaveXmlToFile(xmlFilename, xmlDoc); return true; }
public Ray ScreenPointToRay(Vector2 screenPoint) { RUISDisplay display = GetDisplayForScreenPoint(screenPoint); if (display) { Camera camera = display.GetCameraForScreenPoint(screenPoint); if (camera) { if (UnityEngine.VR.VRSettings.enabled && camera.stereoTargetEye != StereoTargetEyeMask.None) // if(display.isHmdDisplay) { // *** TODO remove this hack when Camera.ScreenPointToRay() works again return(HMDScreenPointToRay(screenPoint, camera)); } else { return(camera.ScreenPointToRay(screenPoint)); } } } return(new Ray(Vector3.zero, Vector3.zero)); }
// Use this for initialization void Start() { try { Input.GetButtonDown("RUISMenu"); } catch (UnityException) { ruisMenuButtonDefined = false; } inputManager = FindObjectOfType(typeof(RUISInputManager)) as RUISInputManager; enablePSMove = inputManager.enablePSMove; psMoveIP = inputManager.PSMoveIP; psMovePort = inputManager.PSMovePort; jumpGesture = FindObjectOfType(typeof(RUISJumpGestureRecognizer)) as RUISJumpGestureRecognizer; displayManager = FindObjectOfType(typeof(RUISDisplayManager)) as RUISDisplayManager; riftDisplay = displayManager.GetOculusRiftDisplay(); // TODO: This menu should work with any stereo view, not just Rift. riftDisplay.linkedCamera is null when Rift is disabled. if (oculusRiftMenu && riftDisplay && riftDisplay.linkedCamera ) { windowRect = new Rect(riftDisplay.linkedCamera.leftCamera.pixelRect.x + riftDisplay.resolutionX / 4 - 100, riftDisplay.resolutionY / 2 - 220, 250, 250); } SaveInputChanges(); }
public static bool ImportDisplay(RUISDisplay display, string filename, TextAsset displaySchema, bool loadFromFileInEditor) { XmlDocument xmlDoc = XMLUtil.LoadAndValidateXml(filename, displaySchema); if (xmlDoc == null) { return false; } if (Application.isEditor && loadFromFileInEditor) { display.displayCenterPosition = XMLUtil.GetVector3FromXmlNode(xmlDoc.GetElementsByTagName("displayCenterPosition").Item(0)); display.displayUpInternal = XMLUtil.GetVector3FromXmlNode(xmlDoc.GetElementsByTagName("displayUp").Item(0)); display.displayNormalInternal = XMLUtil.GetVector3FromXmlNode(xmlDoc.GetElementsByTagName("displayNormal").Item(0)); display.width = float.Parse(xmlDoc.GetElementsByTagName("displaySize").Item(0).Attributes["width"].Value); display.height = float.Parse(xmlDoc.GetElementsByTagName("displaySize").Item(0).Attributes["height"].Value); display.resolutionX = int.Parse(xmlDoc.GetElementsByTagName("displayResolution").Item(0).Attributes["width"].Value); display.resolutionY = int.Parse(xmlDoc.GetElementsByTagName("displayResolution").Item(0).Attributes["height"].Value); } if(display.linkedCamera) display.linkedCamera.LoadKeystoningFromXML(xmlDoc); return true; }
//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 override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(displaySchema, new GUIContent("XML Schema", "Do not modify this unless you know what you're doing")); EditorGUILayout.PropertyField(xmlFilename, new GUIContent("XML filename", "The XML file with the display specifications")); EditorGUILayout.PropertyField(loadFromFileInEditor, new GUIContent("Load from File in Editor", "Load the information from the xml file while in editor mode.")); EditorGUILayout.PropertyField(resolutionX, new GUIContent("Resolution X", "The pixel width of the display")); EditorGUILayout.PropertyField(resolutionY, new GUIContent("Resolution Y", "The pixel height of the display")); EditorGUILayout.PropertyField(isStereo, new GUIContent("Stereo Display", "Is this display stereo?")); if (isStereo.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(eyeSeparation, new GUIContent("Eye Separation", "Eye separation for the stereo image")); EditorGUILayout.PropertyField(stereoType, new GUIContent("Stereo Type", "The type of stereo to use")); EditorGUILayout.PropertyField(useDoubleTheSpace, new GUIContent("Double the Space used", "Calculate the total resolution of the display based on stereo type. \nSideBySide: Double horizontal resolution \nTopAndBottom: Double vertical resolution.")); EditorGUI.indentLevel--; } EditorGUILayout.PropertyField(camera, new GUIContent("Attached Camera", "The RUISCamera that renders to this display")); EditorGUILayout.PropertyField(isHMD, new GUIContent("Enable Oculus Rift", "Is this display an Oculus Rift?")); if (!isHMD.boolValue) { //disabled for now EditorGUILayout.PropertyField(isKeystoneCorrected, new GUIContent("Keystone Correction", "Should this display be keystone corrected?")); EditorGUILayout.PropertyField(isObliqueFrustum, new GUIContent("Head Tracked CAVE Display", "Should the projection matrix be skewed to use this display as a head tracked CAVE viewport")); if (isObliqueFrustum.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(headTracker, new GUIContent("CAVE Head Tracker", "The head tracker object to use for perspective " + "distortion with CAVE-like displays. This is used only if the associated " + "RUISDisplay has 'Head Tracked CAVE Display' enabled.")); EditorGUILayout.PropertyField(displayWidth, new GUIContent("Display Width", "The real-world width of the display")); EditorGUILayout.PropertyField(displayHeight, new GUIContent("Display Height", "The real-world height of the display")); EditorGUILayout.PropertyField(displayCenterPosition, new GUIContent("Display Center Position", "The location of the screen center in Unity coordinates")); EditorGUILayout.PropertyField(displayNormal, new GUIContent("Display Normal Vector", "The normal vector of the display (will be normalized)")); EditorGUILayout.PropertyField(displayUp, new GUIContent("Display Up Vector", "The up vector of the display (will be normalized)")); EditorGUI.indentLevel--; } } else { isObliqueFrustum.boolValue = false; isKeystoneCorrected.boolValue = false; } serializedObject.ApplyModifiedProperties(); int optimalWidth = Screen.width - 4; int optimalHeight = (int)((float)resolutionY.intValue / resolutionX.intValue * optimalWidth); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(GUILayout.Height(optimalHeight)); if (isStereo.boolValue) { displayBoxStyle.normal.background = stereoDisplayTexture; } else { displayBoxStyle.normal.background = monoDisplayTexture; } RUISDisplay display = target as RUISDisplay; int requiredX = display.rawResolutionX; int requiredY = display.rawResolutionY; string boxText = string.Format("{0}\nTotal required resolution {1}x{2}", target.name, requiredX, requiredY); GUILayout.Box(boxText, displayBoxStyle, GUILayout.Width(optimalWidth), GUILayout.Height(optimalHeight)); EditorGUILayout.EndHorizontal(); displayManager.CalculateTotalResolution(); PlayerSettings.defaultScreenWidth = displayManager.totalRawResolutionX; PlayerSettings.defaultScreenHeight = displayManager.totalRawResolutionY; }
//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 override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(displays, true); EditorGUILayout.Space(); //if there is only one display we want to give the user the opportunity to set fullscreen if (displays.arraySize == 1) { allowResolutionDialog.boolValue = EditorGUILayout.Toggle(new GUIContent("Allow resolution dialog", "Allow the usage of the resolution dialog"), allowResolutionDialog.boolValue); if (allowResolutionDialog.boolValue) { PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Enabled; } else { PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Disabled; } } else { PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Disabled; allowResolutionDialog.boolValue = false; } if (GUILayout.Button("Add display")) { displays.arraySize++; SerializedProperty newDisplayProperty = displays.GetArrayElementAtIndex(displays.arraySize - 1); GameObject newDisplay = Instantiate(displayPrefab) as GameObject; newDisplay.name = "NewDisplay"; newDisplay.GetComponent <RUISDisplay>().xmlFilename = newDisplay.name + displays.arraySize + ".xml"; newDisplay.transform.parent = (target as RUISDisplayManager).transform; newDisplayProperty.objectReferenceValue = newDisplay; } EditorGUILayout.Space(); int removeIndex = -1; for (int i = 0; i < displays.arraySize; i++) { //DisplayEditor(displays.GetArrayElementAtIndex(i)); EditorGUILayout.BeginHorizontal(); //EditorGUILayout.PropertyField(displays.GetArrayElementAtIndex(i)); RUISDisplay display = displays.GetArrayElementAtIndex(i).objectReferenceValue as RUISDisplay; if (display == null) { continue; } EditorGUILayout.LabelField(string.Format("{0} ({1}x{2})", display.name, display.resolutionX, display.resolutionY)); if (displays.arraySize > 1) { if (GUILayout.Button("Move up", GUILayout.ExpandWidth(false))) { MoveUp(i); } if (GUILayout.Button("Move down", GUILayout.ExpandWidth(false))) { MoveDown(i); } } if (GUILayout.Button("Delete", GUILayout.ExpandWidth(false))) { if (EditorUtility.DisplayDialog("Confirm deletion", "Are you sure you want to delete this display?", "Delete", "Cancel")) { removeIndex = i; } } EditorGUILayout.EndHorizontal(); } if (removeIndex != -1) { for (int i = removeIndex + 1; i < displays.arraySize; i++) { MoveUp(i); } displays.DeleteArrayElementAtIndex(displays.arraySize - 1); displays.arraySize--; } RUISDisplayManager displayManager = target as RUISDisplayManager; displayManager.CalculateTotalResolution(); PlayerSettings.defaultScreenWidth = displayManager.totalRawResolutionX; PlayerSettings.defaultScreenHeight = displayManager.totalRawResolutionY; //stuff for drawing the display boxes int optimalWidth = Screen.width - displayManager.displays.Count; int optimalHeight = (int)((float)displayManager.totalResolutionY / displayManager.totalResolutionX * optimalWidth); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(GUILayout.Width(Screen.width), GUILayout.Height(optimalHeight)); foreach (RUISDisplay display in displayManager.displays) { if (display.isStereo) { displayBoxStyle.normal.background = stereoDisplayTexture; } else { displayBoxStyle.normal.background = monoDisplayTexture; } GUILayout.Box(display.name, displayBoxStyle, GUILayout.Width(((float)display.resolutionX / displayManager.totalResolutionX) * optimalWidth), GUILayout.Height(optimalHeight * (float)display.resolutionY / displayManager.totalResolutionY)); } EditorGUILayout.EndHorizontal(); serializedObject.ApplyModifiedProperties(); //remove all child displays that aren't in the list anymore RUISDisplay displayToDestroy = null; foreach (RUISDisplay display in displayManager.GetComponentsInChildren <RUISDisplay>()) { if (!displayManager.displays.Contains(display)) { displayToDestroy = display; } } if (displayToDestroy) { DestroyImmediate(displayToDestroy.gameObject); } }
public override void OnInspectorGUI() { serializedObject.Update(); displayManagerLink.Update(); EditorGUILayout.PropertyField(displays, true); EditorGUILayout.Space(); //if there is only one display we want to give the user the opportunity to set fullscreen if (displays.arraySize == 1) { // allowResolutionDialog.boolValue = EditorGUILayout.Toggle(new GUIContent( "Allow Resolution Dialog", "Enables the Resolution Dialog when your " // + "standalone build starts if you have only one RUISDisplay. NOTE: In " // + "all other cases the 'Display Resolution Dialog' setting in Unity's " // + "Player Settings will be overriden with false. In those cases RUIS " // + "will attempt to force the standalone game window to have the total " // + "resolution that is the sum of your RUISDisplays arranged side-by-side."), // allowResolutionDialog.boolValue); // if (allowResolutionDialog.boolValue) // { // PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Enabled; // } // else // { // PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Disabled; // } } else { EditorStyles.textField.wordWrap = true; EditorGUILayout.TextArea("Below configuration has multiple RUISDisplays. 'Display Resolution Dialog' setting is automatically disabled " + "in Unity's Player Settings.", GUILayout.Height(60)); PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Disabled; // allowResolutionDialog.boolValue = false; } if (GUILayout.Button("Add Display")) { displays.arraySize++; SerializedProperty newDisplayProperty = displays.GetArrayElementAtIndex(displays.arraySize - 1); GameObject newDisplay = Instantiate(displayPrefab) as GameObject; newDisplay.name = "NewDisplay"; newDisplay.GetComponent <RUISDisplay>().xmlFilename = newDisplay.name + displays.arraySize + ".xml"; newDisplay.transform.parent = (target as RUISDisplayManager).transform; newDisplayProperty.objectReferenceValue = newDisplay; } EditorGUILayout.Space(); int removeIndex = -1; for (int i = 0; i < displays.arraySize; i++) { //DisplayEditor(displays.GetArrayElementAtIndex(i)); EditorGUILayout.BeginHorizontal(); //EditorGUILayout.PropertyField(displays.GetArrayElementAtIndex(i)); RUISDisplay display = displays.GetArrayElementAtIndex(i).objectReferenceValue as RUISDisplay; if (display == null) { continue; } EditorGUILayout.LabelField(string.Format("{0} ({1}x{2})", display.name, display.resolutionX, display.resolutionY)); if (displays.arraySize > 1) { if (GUILayout.Button("Move Up", GUILayout.ExpandWidth(false))) { MoveUp(i); } if (GUILayout.Button("Move Down", GUILayout.ExpandWidth(false))) { MoveDown(i); } } if (GUILayout.Button("Delete", GUILayout.ExpandWidth(false))) { if (EditorUtility.DisplayDialog("Confirm deletion", "Are you sure you want to delete this display?", "Delete", "Cancel")) { removeIndex = i; } } EditorGUILayout.EndHorizontal(); } if (removeIndex != -1) { for (int i = removeIndex + 1; i < displays.arraySize; i++) { MoveUp(i); } displays.DeleteArrayElementAtIndex(displays.arraySize - 1); displays.arraySize--; } RUISDisplayManager displayManager = target as RUISDisplayManager; displayManager.CalculateTotalResolution(); PlayerSettings.defaultScreenWidth = displayManager.totalRawResolutionX; PlayerSettings.defaultScreenHeight = displayManager.totalRawResolutionY; //stuff for drawing the display boxes int optimalWidth = Screen.width - displayManager.displays.Count; int optimalHeight = (int)((float)displayManager.totalResolutionY / displayManager.totalResolutionX * optimalWidth); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(GUILayout.Width(Screen.width), GUILayout.Height(optimalHeight)); foreach (RUISDisplay display in displayManager.displays) { if (display.isStereo) { displayBoxStyle.normal.background = stereoDisplayTexture; } else { displayBoxStyle.normal.background = monoDisplayTexture; } GUILayout.Box(display.name, displayBoxStyle, GUILayout.Width(((float)display.resolutionX / displayManager.totalResolutionX) * optimalWidth), GUILayout.Height(optimalHeight * (float)display.resolutionY / displayManager.totalResolutionY)); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Display With RUIS Menu:"); guiDisplayChoices = new List <string>(); for (int i = 0; i < displayManager.displays.Count; ++i) { guiDisplayChoices.Add(i + " " + displayManager.displays[i].name); } //MonoBehaviour.print(guiDisplayChoiceLink + ":" + guiDisplayChoices.Count); if (guiDisplayChoiceLink.intValue >= guiDisplayChoices.Count) { guiDisplayChoiceLink.intValue = 0; } guiDisplayChoiceLink.intValue = EditorGUILayout.Popup(guiDisplayChoiceLink.intValue, guiDisplayChoices.ToArray()); EditorGUILayout.EndHorizontal(); EditorGUILayout.PropertyField(ruisMenuPrefab); EditorGUILayout.LabelField("RUIS Menu Local Coordinates:"); EditorGUILayout.PropertyField(guiX, new GUIContent("X", "X-offset from camera")); EditorGUILayout.PropertyField(guiY, new GUIContent("Y", "Y-offset from camera")); EditorGUILayout.PropertyField(guiZ, new GUIContent("Z", "Z-offset from camera")); EditorGUILayout.Space(); EditorGUILayout.LabelField("RUIS Menu Scale:"); EditorGUILayout.PropertyField(guiScaleX, new GUIContent("X-scale", "Scales menu horizontally")); EditorGUILayout.PropertyField(guiScaleY, new GUIContent("Y-scale", "Scales menu vertically")); EditorGUILayout.Space(); EditorGUILayout.PropertyField(hideMouseOnPlay, new GUIContent("Hide Mouse On Play", "Operating system mouse cursor will be hidden")); EditorGUILayout.Space(); EditorGUILayout.PropertyField(menuCursorPrefab, new GUIContent("Menu Cursor Prefab", "The prefab that will be instantiated when RUIS Menu is " + "invoked (ESC key)")); menuLayer.intValue = EditorGUILayout.LayerField(new GUIContent("Menu Layer", "RUIS Menu mouse cursor ray is cast against objects on this layer only"), menuLayer.intValue); serializedObject.ApplyModifiedProperties(); displayManagerLink.ApplyModifiedProperties(); //remove all child displays that aren't in the list anymore RUISDisplay displayToDestroy = null; foreach (RUISDisplay display in displayManager.GetComponentsInChildren <RUISDisplay>()) { if (!displayManager.displays.Contains(display)) { displayToDestroy = display; } } if (displayToDestroy) { DestroyImmediate(displayToDestroy.gameObject); } }
public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(displaySchema, new GUIContent("XML Schema", "Do not modify this unless you know what you're doing")); EditorGUILayout.PropertyField(xmlFilename, new GUIContent("XML filename", "The XML file with the display specifications")); EditorGUILayout.PropertyField(loadFromFileInEditor, new GUIContent("Load from File in Editor", "Load the information from the xml file while in editor mode.")); EditorGUILayout.PropertyField(resolutionX, new GUIContent("Resolution X", "The pixel width of the display")); EditorGUILayout.PropertyField(resolutionY, new GUIContent("Resolution Y", "The pixel height of the display")); EditorGUILayout.PropertyField(isStereo, new GUIContent("Stereo Display", "Is this display stereo?")); if (isStereo.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(eyeSeparation, new GUIContent("Eye Separation", "Eye separation for the stereo image")); EditorGUILayout.PropertyField(stereoType, new GUIContent("Stereo Type", "The type of stereo to use")); EditorGUILayout.PropertyField(useDoubleTheSpace, new GUIContent("Double the Space used", "Calculate the total resolution of the display based on stereo type. \nSideBySide: Double horizontal resolution \nTopAndBottom: Double vertical resolution.")); EditorGUI.indentLevel--; } EditorGUILayout.PropertyField(camera, new GUIContent("Attached Camera", "The RUISCamera that renders to this display")); EditorGUILayout.PropertyField(enableOculusRift, new GUIContent("Enable Oculus Rift", "Is this display an Oculus Rift?")); // TODO: Depends on OVR version EditorGUI.indentLevel++; GUI.enabled = enableOculusRift.boolValue; EditorGUILayout.PropertyField(oculusLowPersistence, new GUIContent("Low Persistence", "Low persistence reduces pixel blur. Try disabling this option if " + "the Oculus Rift view suffers from 'judder' when rotating your head. NOTE: Disabling " + "this option might cause issues with Oculus runtime 0.4.4 if you're using DX11!")); EditorGUILayout.PropertyField(oculusMirrorMode, new GUIContent("Mirror Mode", "Draw the Oculus viewports also to the main display when Direct Display Mode " + "(Direct HMD Access) is enabled from the Oculus Configuration Utility. This setting has no " + "effect when your application is playing inside the Unity Editor.")); if (enableOculusRift.boolValue && EditorApplication.isPlaying) { if (previousOculusLowPersistenceValue != oculusLowPersistence.boolValue && displayManager) { // Low Persistence value changed, enforce it if application is running in Editor displayManager.setOculusLowPersistence(oculusLowPersistence.boolValue); } } EditorGUI.indentLevel--; GUI.enabled = !enableOculusRift.boolValue; RUISEditorUtility.HorizontalRuler(); EditorGUILayout.PropertyField(isObliqueFrustum, new GUIContent("Head Tracked CAVE Display", "Should the projection matrix be skewed to use this display " + "as a head tracked CAVE viewport")); GUI.enabled = true; if (!enableOculusRift.boolValue) { //disabled for now EditorGUILayout.PropertyField(isKeystoneCorrected, new GUIContent("Keystone Correction", "Should this display be keystone corrected?")); if (isObliqueFrustum.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(headTracker, new GUIContent("CAVE Head Tracker", "The head tracker object to use for perspective " + "distortion with CAVE-like displays. This is used only if the associated " + "RUISDisplay has 'Head Tracked CAVE Display' enabled.")); EditorGUILayout.PropertyField(displayWidth, new GUIContent("Display Width", "The real-world width of the display")); EditorGUILayout.PropertyField(displayHeight, new GUIContent("Display Height", "The real-world height of the display")); EditorGUILayout.PropertyField(displayCenterPosition, new GUIContent("Display Center Position", "The location of the screen center in Unity coordinates")); EditorGUILayout.PropertyField(displayNormal, new GUIContent("Display Normal Vector", "The normal vector of the display (will be normalized)")); EditorGUILayout.PropertyField(displayUp, new GUIContent("Display Up Vector", "The up vector of the display (will be normalized)")); EditorGUI.indentLevel--; } } else { isObliqueFrustum.boolValue = false; isKeystoneCorrected.boolValue = false; } previousOculusLowPersistenceValue = oculusLowPersistence.boolValue; serializedObject.ApplyModifiedProperties(); int optimalWidth = Screen.width - 4; int optimalHeight = (int)((float)resolutionY.intValue / resolutionX.intValue * optimalWidth); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(GUILayout.Height(optimalHeight)); if (isStereo.boolValue) { displayBoxStyle.normal.background = stereoDisplayTexture; } else { displayBoxStyle.normal.background = monoDisplayTexture; } RUISDisplay display = target as RUISDisplay; int requiredX = display.rawResolutionX; int requiredY = display.rawResolutionY; string boxText = string.Format("{0}\nTotal required resolution {1}x{2}", target.name, requiredX, requiredY); GUILayout.Box(boxText, displayBoxStyle, GUILayout.Width(optimalWidth), GUILayout.Height(optimalHeight)); EditorGUILayout.EndHorizontal(); displayManager.CalculateTotalResolution(); PlayerSettings.defaultScreenWidth = displayManager.totalRawResolutionX; PlayerSettings.defaultScreenHeight = displayManager.totalRawResolutionY; }
public static bool ExportDisplay(RUISDisplay display, string xmlFilename) { return(true); }
public static bool ImportDisplay(RUISDisplay display, string filename, TextAsset displaySchema, bool loadFromFileInEditor) { return(true); }