精确的缩放变焦

时间:2015-05-20 12:39:51

标签: c# unity3d camera multi-touch pinchzoom

我正在试图弄清楚如何在Unity3D / C#中为我的相机创建精确的捏缩放。它必须基于地形上的物理点。下图说明了我想要达到的效果。

enter image description here

相机是零的子项,可以缩放(在0.1和1之间)到“缩放”,以免弄乱相机的视角。

所以我到目前为止所提出的是每个手指必须使用光线投射来获得A& B点以及相机父级的当前比例。

EG:A(10,0,2),B(14,0,4),S(0.8,0.8,0.8)> A(10,0,2),B(14,0,4),S(0.3,0.3,0.3)

手指的位置会改变,但hit.point值应该通过改变比例保持不变。

奖励:作为奖励,将相机放大到手指之间的点,而不仅仅是中心,这会很棒。

非常感谢任何帮助或参考。

修改 到目前为止,我已经提出了这个问题,但这并不是我想要的方式。它结合了我上面提到的一些想法,我认为问题在于它不应该是/ 1000,而是以某种方式包含当前比例的等式。

if (Input.touchCount == 2) {
        if (!CamZoom) {
            CamZoom = true;
            var rayA = Camera.main.ScreenPointToRay (Input.GetTouch (0).position);
            var rayB = Camera.main.ScreenPointToRay (Input.GetTouch (1).position);
            int layerMask = (1 << 8);
            if (Physics.Raycast (rayA, out hit, 1500, layerMask)) {
                PrevA = new Vector3 (hit.point.x, 0, hit.point.z);
                Debug.Log ("PrevA: " + PrevA);
            }
            if (Physics.Raycast (rayB, out hit, 1500, layerMask)) {
                PrevB = new Vector3 (hit.point.x, 0, hit.point.z);
                Debug.Log ("PrevB: " + PrevB);
            }
            PrevDis = Vector3.Distance (PrevB, PrevA);
            Debug.Log ("PrevDis: " + PrevDis);
            PrevScaleV = new Vector3 (PrevScale, PrevScale, PrevScale);
            PrevScale = this.transform.localScale.x;
            Debug.Log ("PrevScale: " + PrevScale);
        }
        if (CamZoom) {
            var rayA = Camera.main.ScreenPointToRay (Input.GetTouch (0).position);
            var rayB = Camera.main.ScreenPointToRay (Input.GetTouch (1).position);
            int layerMask = (1 << 8);
            if (Physics.Raycast (rayA, out hit, 1500, layerMask)) {
                NewA = new Vector3 (hit.point.x, 0, hit.point.z);
            }
            if (Physics.Raycast (rayB, out hit, 1500, layerMask)) {
                NewB = new Vector3 (hit.point.x, 0, hit.point.z);
            }
            DeltaDis = PrevDis - (Vector3.Distance (NewB, NewA));
            Debug.Log ("Delta: " + DeltaDis);
            NewScale = PrevScale + (DeltaDis / 1000);
            Debug.Log ("NewScale: " + NewScale);
            NewScaleV = new Vector3 (NewScale, NewScale, NewScale);
            this.transform.localScale = Vector3.Lerp(PrevScaleV,NewScaleV,Time.deltaTime);
            PrevScaleV = NewScaleV;
            CamAngle();
        }
    }

2 个答案:

答案 0 :(得分:1)

简介

我最近必须解决同样的问题,并采用与你相同的方法开始,这就是把它想象成用户正在与场景交互,我们需要弄清楚他们的手指在场景中的位置和它们是如何移动然后反转这些动作以在我们的相机中反映它们。

但是,我们真正想要实现的目标要简单得多。我们只是希望用户感觉屏幕区域的缩小变化大小与其捏合变化的比例相同。

目标

首先让我们总结一下我们的目标和约束:

  • 目标:当用户捏住时,压缩区域应按比例缩放以匹配夹点。
  • 约束:我们不想更改任何对象的比例。
  • 约束:我们的相机是透视相机。
  • 约束:我们不想更改相机上的视野。
  • 约束:我们的解决方案应该是解决方案/设备无关的。

考虑到所有这些,并且鉴于我们知道透视摄影机对象在更接近更小时会出现更大当他们进一步时,似乎缩放用户看到的唯一解决方案是将相机移入/移出场景。

解决方案

为了使场景在我们的焦点处看起来更大,我们需要定位摄像机,使得摄像机在焦点处的截头体的横截面相当小。

这是一个更好地解释的图表:

solution

图像的上半部分是我们想要实现的“幻觉”,使用户在屏幕上扩展两倍的区域。图像的下半部分是我们需要如何移动相机以使平截头体以一种给人留下印象的方式定位。

然后问题变成我可以移动相机多远以达到所需的横截面

为此,当相机的视角以度为单位时,我们可以利用距离相机 d 的平截头体高度 h 之间的关系>θ

trig

由于我们的视角θ根据约定的约束是恒定的,我们可以看到 h d 是线性比例的。< / p>

linearly proportional

这很有用,因为它意味着 h 的任何乘法/除法都同样反映在 d 中。这意味着我们可以直接将乘数应用于距离,无需额外计算将高度转换为所需的距离!

实施

所以我们终于得到了代码。

首先,我们将用户所需的尺寸变化视为手指之间距离的倍数:

Touch touch0 = Input.GetTouch(0);
Touch touch1 = Input.GetTouch(1);
Vector2 prevTouchPosition0 = touch0.position - touch0.deltaPosition;
Vector2 prevTouchPosition1 = touch1.position - touch1.deltaPosition;
float touchDistance = (touch1.position - touch0.position).magnitude;
float prevTouchDistance = (prevTouchPosition1 - prevTouchPosition1).magnitude;
float touchChangeMultiplier = touchDistance / prevTouchDistance;

现在我们知道用户想要缩放他们捏的区域的数量,我们可以将相机与焦点的距离缩小相反的量。

焦点是相机的前向光线与您放大的物体的交点。为了一个简单的例子,我只是将原点作为我的焦点。

Vector3 focalPoint = Vector3.zero;
Vector3 direction = camera.transform.position - focalPoint;
float newDistance = direction.magnitude / touchChangeMultiplier;
camera.transform.position = newDistance * direction.normalized;
camera.transform.LookAt(focalPoint);

这就是它的全部内容。

加成

这个答案已经很长了。因此,简要回答一下有关将相机放在捏的地方的问题:

  • 首次检测到2指触摸时,请存储屏幕位置和相关的世界位置。
  • 缩放时,移动相机以将世界位置放回同一屏幕位置。

答案 1 :(得分:0)

这是一个小例子:

abc
cba
cccc

this教程的第二个视频中解释了它