// in egocentric camera system the "eye" is moving up/down, which means the scene moves in opposite direction public void SceneRateControlledEgogentricPan(FScene scene, fCamera cam, Vector2f curPos, RateControlInfo rc) { float dt = (FPlatform.RealTime() - rc.lastTime); rc.lastTime = FPlatform.RealTime(); float delta_y = (curPos.y - rc.startPos.y); rc.curSpeedY = rc_update_speed(delta_y, rc.rampUpRadius, rc.deadZoneRadius, rc.maxAccel, rc.maxSpeed, dt, rc.curSpeedY); float delta_x = (curPos.x - rc.startPos.x); rc.curSpeedX = rc_update_speed(delta_x, rc.rampUpRadius, rc.deadZoneRadius, rc.maxAccel, rc.maxSpeed, dt, rc.curSpeedX); Frame3f camFrame = cam.GetWorldFrame(); Vector3f forward = camFrame.Z; Vector3f up = camFrame.Y; if (rc.StayLevel) { forward = new Vector3(forward.x, 0.0f, forward.z); forward.Normalize(); up = Vector3.up; } Vector3f right = Vector3.Cross(up, forward); Vector3f curScenePos = scene.RootGameObject.GetPosition(); Vector3f newScenePos = curScenePos - dt * (rc.curSpeedY * up + rc.curSpeedX * right); scene.RootGameObject.SetPosition(newScenePos); }
/// <summary> /// Shift scene towards (+) / away-from (-) camera. /// If bKeepTargetPos == false, then target shifts with scene /// </summary> public void SceneZoom(FScene scene, fCamera cam, float dz, bool bKeepTargetPos = true) { if (dz == 0.0f) { return; } float fScale = scene.GetSceneScale(); //Vector3f fw = cam.gameObject.transform.forward; Vector3f fw = cam.GetTarget() - cam.GetPosition(); float fTargetDist = fw.Length; fw.Normalize(); float fMinTargetDist = 0.1f * fScale; if (dz > 0 && fTargetDist - dz < fMinTargetDist) { dz = fTargetDist - fMinTargetDist; } Vector3f delta = dz * fw; scene.RootGameObject.Translate(-delta, false); if (bKeepTargetPos) { cam.SetTarget(cam.GetTarget() - delta); } }
public void SceneOrbit(FScene scene, fCamera cam, float deltaAzimuth, float deltaAltitude, bool bSet = false) { //Vector3f sceneOrigin = scene.RootGameObject.transform.position; Vector3f rotTarget = cam.GetTarget(); // [RMS] Orbiting around the Target point is kind of a weird concept when // you are moving the scene and not the camera. Basically we want to rotate // the scene around the target, but not incrementally - based on a pair of // spherical angles. So, we have to return to a 'reference' state each update. // Simplest way to do that is to "un-rotate" by the angles before the delta... // (???) Vector3f up = Vector3f.AxisY; Vector3f right = cam.Right(); scene.RootGameObject.RotateAroundD(rotTarget, right, -turntableAltitudeD); scene.RootGameObject.RotateAroundD(rotTarget, up, -turntableAzimuthD); if (bSet) { turntableAzimuthD = deltaAzimuth; turntableAltitudeD = deltaAltitude; } else { turntableAzimuthD -= deltaAzimuth; turntableAltitudeD += deltaAltitude; } turntableAzimuthD = (float)MathUtil.ClampAngleDeg(Convert.ToDouble(turntableAzimuthD), -360d, 360d); turntableAltitudeD = Mathf.Clamp(turntableAltitudeD, -89.9f, 89.9f); scene.RootGameObject.RotateAroundD(rotTarget, up, turntableAzimuthD); scene.RootGameObject.RotateAroundD(rotTarget, right, turntableAltitudeD); }
public void DoCameraControl(FScene scene, fCamera mainCamera, InputState input) { Vector2f mouseDelta = InputExtension.Get.Mouse.PositionDelta; Vector2f stick1 = InputExtension.Get.GamepadLeftStick.Position; Vector2f stick2 = InputExtension.Get.GamepadRightStick.Position; float dx = mouseDelta.x + stick1.x; float dy = mouseDelta.y + stick1.y; float dx2 = stick2.x; float dy2 = stick2.y; if (Input.GetMouseButton(0)) { mainCamera.Manipulator().SceneOrbit(scene, mainCamera, MouseOrbitSpeed * dx, MouseOrbitSpeed * dy); } else if (Input.GetMouseButton(1)) { mainCamera.Manipulator().SceneZoom(scene, mainCamera, -MouseZoomSpeed * dy); //mainCamera.Manipulator().ScenePan(scene, mainCamera, 0.05f * dx, 0); } else if (Input.GetMouseButton(2)) { mainCamera.Manipulator().ScenePan(scene, mainCamera, MousePanSpeed * dx, MousePanSpeed * dy); } else if (InputExtension.Get.GamepadRightShoulder.Down) { mainCamera.Manipulator().SceneZoom(scene, mainCamera, GamepadZoomSpeed * dy); mainCamera.Manipulator().ScenePan(scene, mainCamera, (-0.5f * GamepadPanSpeed * dx) + (-GamepadPanSpeed * dx2), -GamepadPanSpeed * dy2); } else if (InputExtension.Get.GamepadLeftShoulder.Down) { mainCamera.Manipulator().SceneOrbit(scene, mainCamera, GamepadOrbitSpeed * dx, GamepadOrbitSpeed * dy); mainCamera.Manipulator().ScenePan(scene, mainCamera, -GamepadPanSpeed * dx2, -GamepadPanSpeed * dy2); } }
public static float DefaultHeightInM = 1.6f; // 1.6m ~= 5.5 feet // straight teleport: // camera points at hit point, we back off and set target at hit point static public void TeleportTowards(fCamera camera, FScene scene, Vector3f targetPoint, float fPullback) { fPullback *= scene.GetSceneScale(); Vector3f vCurCamFW = camera.GetWorldFrame().Z; Vector3f vNewCamPos = targetPoint - fPullback * vCurCamFW; Vector3f vNewTargetPos = vNewCamPos + fPullback * vCurCamFW; camera.Animator().Teleport(vNewCamPos, vNewTargetPos); }
// level teleport: // first we level the scene (ie scene up is y axis), then camera points // at ray hit point, pulled back along cam direction projected into xz plane static public void TeleportTowards_Level(fCamera camera, FScene scene, Vector3f targetPoint, float fPullback) { fPullback *= scene.GetSceneScale(); Vector3f vCurCamFW = camera.GetWorldFrame().Z; Vector3f vCurCamFWXZ = new Vector3f(vCurCamFW[0], 0.0f, vCurCamFW[2]).Normalized; Vector3f vNewCamPos = targetPoint - fPullback * vCurCamFWXZ; Vector3f vNewTargetPos = vNewCamPos + fPullback * vCurCamFWXZ; camera.Animator().Teleport_Level(vNewCamPos, vNewTargetPos); }
public void SceneTumble(FScene scene, fCamera cam, float dx, float dy) { Vector3f up = cam.Up(); Vector3f right = cam.Right(); //Vector3 curOrigin = scene.RootGameObject.transform.position; Vector3f curOrigin = cam.GetTarget(); scene.RootGameObject.RotateAroundD(curOrigin, up, dx); scene.RootGameObject.RotateAroundD(curOrigin, right, dy); }
public void ScenePan(FScene scene, fCamera cam, float dx, float dy) { float fScale = scene.GetSceneScale(); Frame3f camFrame = cam.GetWorldFrame(); Vector3f right = camFrame.X; Vector3f up = camFrame.Y; Vector3f delta = dx * fScale * right + dy * fScale * up; Vector3f newPos = scene.RootGameObject.GetPosition() + delta; scene.RootGameObject.SetPosition(newPos); }
// use normal angle w/ up vector to decide if we should offset vertically or horizontally // from hit point (threshold hardcoded to 45 degrees right now) static public void Teleport_Normal_Auto(fCamera camera, FScene scene, Vector3f targetPoint, Vector3f targetNormal, float fPullback) { float fDot = Mathf.Abs(Vector3f.Dot(targetNormal, scene.RootGameObject.GetWorldFrame().Y)); float fAngle = Mathf.Acos(fDot) * Mathf.Rad2Deg; if (fAngle > 45.0f) { Teleport_LevelNormalOffset(camera, scene, targetPoint, targetNormal, fPullback, false); } else { Teleport_VerticalNormalOffset(camera, scene, targetPoint, targetNormal, fPullback); } }
public void SceneAdaptivePan(FScene scene, fCamera cam, float xStepFraction, float yStepFraction) { float fScale = scene.GetSceneScale(); Vector3f fw = cam.GetTarget() - cam.GetPosition(); float fTargetDist = fw.Length; float dx = fTargetDist * xStepFraction; float dy = fTargetDist * yStepFraction; Frame3f camFrame = cam.GetWorldFrame(); Vector3f right = camFrame.X; Vector3f up = camFrame.Y; Vector3f delta = dx * fScale * right + dy * fScale * up; Vector3f newPos = scene.RootGameObject.GetPosition() + delta; scene.RootGameObject.SetPosition(newPos); }
/// <summary> /// translates scene so that focusPointS lies on camera forward axis. Also updates /// camera.Target to be at this point. /// </summary> public void PanFocusOnScenePoint(FScene scene, fCamera camera, Vector3f focusPointS) { Vector3f focusPointW = scene.ToWorldP(focusPointS); // figure out the pan that we would apply to camera, then apply the delta to the scene Vector3f camPosW = camera.GetPosition(); Vector3f camForward = camera.Forward(); float fDist = Vector3.Dot((focusPointW - camPosW), camForward); if (fDist == 0) { fDist = 2.0f * ((Camera)camera).nearClipPlane; } Vector3f newCamPosW = focusPointW - fDist * camForward; Vector3f delta = camPosW - newCamPosW; scene.RootGameObject.Translate(delta, false); camera.SetTarget(focusPointW + delta); }
// we orbit view to be level, then again so that the normal of the hit point points towards // the camera. Then we pull back along that direction. Unless we want to face away, // then we rotate an extra 180 degrees, and set the target out by the pullback distance static public void Teleport_LevelNormalOffset(fCamera camera, FScene scene, Vector3f targetPoint, Vector3f targetNormal, float fPullback, bool bFaceAwayFromSurface = false) { fPullback *= scene.GetSceneScale(); Vector3f vCurCamFW = camera.GetWorldFrame().Z; Vector3f vCurCamFWXZ = new Vector3f(vCurCamFW[0], 0.0f, vCurCamFW[2]).Normalized; Vector3f vHitNormalXZ = new Vector3f(targetNormal[0], 0.0f, targetNormal[2]).Normalized; float fFace = bFaceAwayFromSurface ? -1.0f : 1.0f; float fRotate = Vector3f.AngleD(-vCurCamFWXZ, fFace * vHitNormalXZ); float fSign = Vector3f.Cross(vCurCamFWXZ, fFace * vHitNormalXZ)[1] > 0 ? -1 : 1; fRotate *= fSign; // now we use cam instead of normal here because we rotated normal to face cam! Vector3f vNewCamPos = targetPoint - fFace * fPullback * vCurCamFWXZ; Vector3f vNewTargetPos = (bFaceAwayFromSurface) ? vNewCamPos + fPullback * vCurCamFWXZ : targetPoint; camera.Animator().Teleport_Level(vNewCamPos, vNewTargetPos, targetPoint, fRotate); }
// vertical-offset level teleport // assumption is that target point is on ground or ceiling, and we want to offset vertically. // To do that we have to first reset orbit around the hit point. // One small problem here is that the output target pos is really arbitrary. perhaps we should // cast another ray into the scene in the forward direction? static public void Teleport_VerticalNormalOffset(fCamera camera, FScene scene, Vector3f targetPoint, Vector3f targetNormal, float fNewTargetDist) { fNewTargetDist *= scene.GetSceneScale(); Vector3f vCurCamFW = camera.GetWorldFrame().Z; Vector3f vCurCamFWXZ = new Vector3f(vCurCamFW[0], 0.0f, vCurCamFW[2]).Normalized; Vector3f vSceneUp = scene.RootGameObject.GetWorldFrame().Y; // when we are offsetting up we use the DefaultHeightInM value to set eye level, // when offsetting down we use half that distance (arbitrary) float fUp = Vector3f.Dot(targetNormal, vSceneUp) > 0 ? 1.0f : -0.5f; // [RMS] camera height does not work because OVRCameraRig sets eye-level to be origin!! //float fHeight = camera.GetPosition()[1] * scene.GetSceneScale(); //float fHeight = DefaultHeightInM * scene.GetSceneScale(); float fHeight = DefaultHeightInM * (float)Math.Sqrt(scene.GetSceneScale()); // don't scale! otherwise tiny offsets Vector3f vNewCamPos = targetPoint + fUp * fHeight * Vector3f.AxisY; Vector3f vNewTargetPos = vNewCamPos + fNewTargetDist * vCurCamFWXZ; camera.Animator().Teleport_Level(vNewCamPos, vNewTargetPos, targetPoint); }
public void ScenePanFocus(FScene scene, fCamera camera, Vector3f focusPointW, bool bAnimated) { CameraAnimator animator = camera.Animator(); if (bAnimated == false || animator == null) { // figure out the pan that we would apply to camera, then apply the delta to the scene Vector3f camPosW = camera.GetPosition(); Vector3f camForward = camera.Forward(); float fDist = Vector3.Dot((focusPointW - camPosW), camForward); Vector3f newCamPosW = focusPointW - fDist * camForward; Vector3f delta = camPosW - newCamPosW; scene.RootGameObject.Translate(delta, false); camera.SetTarget(focusPointW + delta); } else { animator.PanFocus(focusPointW); } }
public void ScenePanFocus(FScene scene, fCamera camera, Vector3f focusPoint, bool bAnimated) { CameraAnimator animator = camera.Animator(); if (bAnimated == false || animator == null) { // figure out the pan that we would apply to camera, then apply the delta to the scene Vector3f curPos = camera.GetPosition(); Vector3f curDir = camera.GetWorldFrame().Z; float fDist = Vector3.Dot((focusPoint - curPos), curDir); Vector3f newPos = focusPoint - fDist * curDir; Vector3f delta = curPos - newPos; scene.RootGameObject.Translate(delta, false); camera.SetTarget(focusPoint); } else { animator.PanFocus(focusPoint); } }
/// <summary> /// Shift scene towards (+) / away-from (-) camera. /// If bKeepTargetPos == false, then target shifts with scene /// </summary> public void SceneZoom(FScene scene, fCamera cam, float dz, bool bKeepTargetPos = true) { if (dz == 0.0f) { return; } if (cam.IsOrthographic) { float f = cam.OrthoHeight; f = f - dz; if (f < 0) { f = 0.01f; } cam.OrthoHeight = f; scene.Context.CameraManager.UpdateMainCamOrthoSize(); } else { float fScale = scene.GetSceneScale(); Vector3f fw = cam.GetTarget() - cam.GetPosition(); float fTargetDist = fw.Length; fw.Normalize(); float fMinTargetDist = 0.1f * fScale; if (dz > 0 && fTargetDist - dz < fMinTargetDist) { dz = fTargetDist - fMinTargetDist; } Vector3f delta = dz * fw; scene.RootGameObject.Translate(-delta, false); if (bKeepTargetPos) { cam.SetTarget(cam.GetTarget() - delta); } } }
public override void PreRender() { fCamera cam = Parent.Context.ActiveCamera; float zNear = 2 * cam.NearClipPlane; Vector3f forwardW = cam.Forward(); Vector3f gridCenterW = cam.GetPosition() + zNear * forwardW; Vector3f inCenterW = (Parent as FScene).ToWorldP(Center); //Vector3f gridDirS = (Parent as FScene).ToSceneN(forwardW); //Frame3f gridFrame = new Frame3f(gridCenter, gridDir); //Frame3f gridFrame = new Frame3f(Center, gridDirS); //Frame3f gridFrameW = new Frame3f(inCenterW, forwardW); Frame3f gridFrameW = new Frame3f(gridCenterW, forwardW); RootGameObject.SetWorldFrame(gridFrameW); if (grids_valid == false) { update_grids(); } }
// Use this for initialization public void Initialize(FContext controller) { this.controller = controller; // find main camera GameObject[] mainCameras = GameObject.FindGameObjectsWithTag("MainCamera"); if (mainCameras.Length == 0) { throw new MissingComponentException("CameraTracking.Initialize: could not find camera with tag MainCamera"); } var mainCameraObj = mainCameras[0]; if (mainCameras.Length > 1) { DebugUtil.Log(2, "CameraTracking.Initialize: there are multiple objects with tag MainCamera. Using the one named " + mainCameraObj.GetName()); } mainCamera = new fCamera(mainCameraObj.GetComponent <Camera> () as Camera); // on Vive the MainCamera will have some child cameras that are a problem, // so get rid of them if (gs.VRPlatform.CurrentVRDevice == gs.VRPlatform.Device.HTCVive) { List <GameObject> children = new List <GameObject>(mainCameraObj.Children()); foreach (var child in children) { mainCameraObj.RemoveChild(child); child.Destroy(); } } List <Camera> newCameras = new List <Camera>(); Vector3f mainPos = mainCamera.GetPosition(); Quaternionf mainRot = mainCamera.GetRotation(); // create camera for 3D widgets layer widgetCamera = new fCamera(Camera.Instantiate((Camera)mainCamera, mainPos, mainRot)); widgetCamera.SetName("WidgetCamera"); newCameras.Add(widgetCamera); // create camera for HUD layer hudCamera = new fCamera(Camera.Instantiate((Camera)mainCamera, mainPos, mainRot)); hudCamera.SetName("HUDCamera"); newCameras.Add(hudCamera); // create camera for UI uiCamera = new fCamera(Camera.Instantiate((Camera)mainCamera, mainPos, mainRot)); uiCamera.SetName("UICamera"); ((Camera)uiCamera).orthographic = true; ((Camera)uiCamera).orthographicSize = 0.5f; newCameras.Add(uiCamera); // create camera for cursor cursorCamera = new fCamera(Camera.Instantiate((Camera)mainCamera, mainPos, mainRot)); cursorCamera.SetName("CursorCamera"); newCameras.Add(cursorCamera); // configure these cameras // - must disable audio listener if it exists // - do depth clear so we can draw on top of other layers foreach (Camera cam in newCameras) { AudioListener listener = cam.GetComponent <AudioListener>(); if (listener != null) { listener.enabled = false; } cam.clearFlags = CameraClearFlags.Depth; cam.tag = "Untagged"; } // set up camera masks // this camera only renders 3DWidgetOverlay layer, and mainCam does not! int nWidgetLayer = FPlatform.WidgetOverlayLayer; int nHUDLayer = FPlatform.HUDLayer; int nUILayer = FPlatform.UILayer; int nCursorLayer = FPlatform.CursorLayer; ((Camera)widgetCamera).cullingMask = (1 << nWidgetLayer); ((Camera)hudCamera).cullingMask = (1 << nHUDLayer); ((Camera)uiCamera).cullingMask = (1 << nUILayer); ((Camera)cursorCamera).cullingMask = (1 << nCursorLayer); ((Camera)mainCamera).cullingMask &= ~(1 << nWidgetLayer); ((Camera)mainCamera).cullingMask &= ~(1 << nHUDLayer); ((Camera)mainCamera).cullingMask &= ~(1 << nUILayer); ((Camera)mainCamera).cullingMask &= ~(1 << nCursorLayer); // attach camera animation object to main camera CameraAnimator anim = mainCamera.AddComponent <CameraAnimator>(); anim.UseCamera = mainCamera; anim.UseScene = this.controller.Scene; // add target point to camera CameraTarget target = mainCamera.AddComponent <CameraTarget>(); target.TargetPoint = new Vector3f(0.0f, mainCamera.GetPosition().y, 0.0f); target.context = this.controller; // add camera manipulator to camera // TODO: this does not need to be a monobehavior... var manipulator = mainCamera.AddComponent <CameraManipulator>(); manipulator.Camera = mainCamera; // initialize FPlatform FPlatform.MainCamera = mainCamera; FPlatform.WidgetCamera = widgetCamera; FPlatform.HUDCamera = hudCamera; FPlatform.OrthoUICamera = uiCamera; FPlatform.CursorCamera = cursorCamera; }
public void DoCameraControl(FScene scene, fCamera mainCamera, InputState input) { if (bInAction == false) { if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2)) { curPos2D = new Vector2(0, 0); rcInfo = new CameraManipulator.RateControlInfo(curPos2D); bInAction = bUsingMouse = true; } else if (InputExtension.Get.GamepadRightShoulder.Down || InputExtension.Get.GamepadLeftShoulder.Down) { curPos2D = secondPos2D = new Vector2(0, 0); rcInfo = new CameraManipulator.RateControlInfo(curPos2D); rcInfo2 = new CameraManipulator.RateControlInfo(secondPos2D); bInAction = bUsingGamepad = true; } } if (bInAction && bUsingMouse) { Vector2f mouseDelta = InputExtension.Get.Mouse.PositionDelta; curPos2D.x += mouseDelta.x; curPos2D.y += mouseDelta.y; if (Input.GetMouseButton(0)) { mainCamera.Manipulator().SceneRateControlledFly(scene, mainCamera, curPos2D, rcInfo); } else if (Input.GetMouseButton(1)) { mainCamera.Manipulator().SceneRateControlledZoom(scene, mainCamera, curPos2D, rcInfo); } else if (Input.GetMouseButton(2)) { mainCamera.Manipulator().SceneRateControlledEgogentricPan(scene, mainCamera, curPos2D, rcInfo); } } if (bInAction && bUsingGamepad) { Vector2f stick1 = InputExtension.Get.GamepadLeftStick.Position; Vector2f stick2 = InputExtension.Get.GamepadRightStick.Position; float dx = stick1.x; float dy = stick1.y; float dx2 = stick2.x; float dy2 = stick2.y; curPos2D.x += dx; curPos2D.y += dy; secondPos2D.x += dx2; secondPos2D.y += dy2; float use_t = 3.0f; // 5 == hard stop, 1 == bit too soft curPos2D.x = MathUtil.SignedClamp(curPos2D.x, rcInfo.rampUpRadius); curPos2D.x = Mathf.Lerp(curPos2D.x, 0, use_t * Time.deltaTime); curPos2D.y = MathUtil.SignedClamp(curPos2D.y, rcInfo.rampUpRadius); curPos2D.y = Mathf.Lerp(curPos2D.y, 0, use_t * Time.deltaTime); secondPos2D.x = MathUtil.SignedClamp(secondPos2D.x, rcInfo.rampUpRadius); secondPos2D.x = Mathf.Lerp(secondPos2D.x, 0, use_t * Time.deltaTime); secondPos2D.y = MathUtil.SignedClamp(secondPos2D.y, rcInfo.rampUpRadius); secondPos2D.y = Mathf.Lerp(secondPos2D.y, 0, use_t * Time.deltaTime); if (InputExtension.Get.GamepadRightShoulder.Down) { mainCamera.Manipulator().SceneRateControlledZoom(scene, mainCamera, curPos2D, rcInfo); secondPos2D[0] = 0; mainCamera.Manipulator().SceneRateControlledEgogentricPan(scene, mainCamera, secondPos2D, rcInfo2); } else if (InputExtension.Get.GamepadLeftShoulder.Down) { mainCamera.Manipulator().SceneRateControlledFly(scene, mainCamera, curPos2D, rcInfo); mainCamera.Manipulator().SceneRateControlledEgogentricPan(scene, mainCamera, secondPos2D, rcInfo2); } } }