ARFoundation - 实现物体旋转, 平移,缩放

本文目的是为了确定在移动端怎样通过单指滑动实现物体的旋转,双指实现平移和缩放。

前提知识:

ARFoundation - touch point坐标点测试

旋转

手机的位置确定了相机的位置,那么首先确定下相机的updirection和rightdirection相对于手机屏幕指定的方向是哪。相关代码如下:

Object.transform.RotateAround(center, Camera.main.transform.up, rotateAngle);

物体相对于手机屏幕旋转示意如下:

为了实现物体的旋转,需要确定如下几个元素:

  • 旋转轴;
  • 旋转中心;
  • 旋转角度;

确定旋转中心

旋转中心定位物体的包围盒的中心,旋转轴获取的基本思路如下:

旋转轴的定义为,前一次操作的点,和当前操作的点,构成的向量,逆时针旋转90°(或顺时针旋转90°),即为旋转轴。

令PrePos->CurPos的向量为(x,y),那么逆时针旋转90度得到的向量为(-y,x),那么最后的RotateAxis为:

RotateAxis = Camera.main.transform.right * y + Camera.main.transform.up * (-x)

确定旋转角度

旋转的正角度方向,是通过左手确定的,即大拇指指向旋转轴的方向,四指弯曲的方向为旋转的正方向,为了保证四指弯曲的方向就是手指滑动的方向,于是需要保证旋转轴,为手指滑动方向顺时针旋转90°得到的向量,正如上一节中给出的结果。那么旋转角度的确定可以借助屏幕PrePos和CurPos之间的距离,与屏幕对角线之间距离(lenDiagnoal)的比值,以及旋转角度缩放量(angleZoom)确定(旋转的快慢可以通过调整该值确定),代码如下:

Vector2 delta = _curPos - _prePos;
int lenDiagnoal = Math.Min(Screen.width, Screen.height);
float deltaLength = delta.magnitude;
float angleZoom = 180.0f * 1.5f;
float rotateAngle = deltaLength / lenDiagnoal * angleZoom;

平移

由于相机的投影是基于透视投影的,如果直接将屏幕点转换到世界坐标系中,那么屏幕中不同的点转换后可能得到相同的世界坐标系的点。因此,在转化的时候需要在第三个维度上添加一个增量。转换后的点分别为:PrePos'和CurPos'。PreObj表示的是物体在上一帧的实际位置,CurObj表示物体在当前帧的实际位置,那么三角形O(PreObj)(CurObj)和三角形O(PrePos')(CurPos')相似,那么就可以计算得到平移向量(CurObj)(PreObj)。需要注意的是,如果平移过程中,相机的位置变化了,可能得到预期外的结果。为了控制平移量的大小,给定了translateScale值,代码如下:

Vector3 curPositionInWorld = Camera.main.ScreenToWorldPoint(new Vector3(_curPos.x, _curPos.y, 1));
Vector3 prePositionInWorld = Camera.main.ScreenToWorldPoint(new Vector3(_prePos.x, _prePos.y, 1));
var posDis = (curPositionInWorld - prePositionInWorld).magnitude; // prepos' to curpos'
var objDis = (TissueGroup.transform.position - Camera.main.transform.position).magnitude; // preobj to o
var preDis = (prePositionInWorld - Camera.main.transform.position).magnitude; // preobj' to o
var offset = objDis / preDis * posDis; // preobj to curobj length
Vector3 translateVecInWorld = (curPositionInWorld - prePositionInWorld).normalized * offset;// preobj to curobj vector
float translateScale = 0.5f;
TissueGroup.transform.position += translateVecInWorld * translateScale;

缩放

缩放需要以特定点为pivot点进行缩放。而unity自带的localscale是依据local坐标系的原点进行缩放的。具体实现可以参考:https://forum.unity.com/threads/scale-around-point-similar-to-rotate-around.232768/。

先来看一下示意图:

上面两个图是放大前后的样子。下面两个图是从两个角度出发,O不变,或Pivot不变的情况下,放大的示意图。显然,左下图中(Pivot2)(O)的距离等于右下图中(Pivot)O2的距离。那么基于pivot的缩放,可以理解:

  • 计算平移向量,PivotO2;
  • 将Pivot移动到O2;
  • 进行放大;

代码实现如下:

var O1 = target.transform.localPosition;
var pivotToO1 = O1 - pivot1;
var pivotToO2 = pivotToO1 * scaleFactor;
var O2 = pivot + pivotToO2;
target.transform.localPosition = O2;
target.transform.localScale = target.transform.localScale * scaleFactor;

此时已经知道了如何基于pivot进行缩放,接下来需要确定的事情是,scaleFactor的计算。通过双指进行操作,双指间的距离增大的时候进行放大(距离差>0),双指间的距离减小的时候进行缩小(距离差<0)。那么需要寻找的函数是当x=0时,y=1,当x>0时y>1,当x<0时,y<1。同时y不会小于0。很容易想到满足该条件的是指数方程,那么可实现的一种示例如下(具体可以根据效果进行微调):

Vector2 screenVec = new Vector2(Screen.width, Screen.height);
double scaleFactor = Math.Exp((curLength - preLength)/ screenVec.magnitude * 2.0);

ARFoundation - 实现物体旋转, 平移,缩放的更多相关文章

  1. OpenGL中旋转平移缩放等变换的顺序对模型的影响

    l 前提: 0x01. 假设绘制顶点的语句为Draw Array,变换的语句(旋转.平移.缩放)为M,而 M0; M1; M2; Draw Array; 则称对Array先进行M2再进行M1.M0 0 ...

  2. Three.js三维模型几何体旋转、缩放和平移

    创建场景中的三维模型往往需要设置显示大小.位置.角度,three.js提供了一系列网格模型对象的几何变换方法,从WebGL的角度看,旋转.缩放.平移对应的都是模型变换矩阵,关于矩阵变换内容可以观看本人 ...

  3. 【转载】Unity中矩阵的平移、旋转、缩放

    By:克森 简介 在这篇文章中,我们将会学到几个概念:平移矩阵.旋转矩阵.缩放矩阵.在学这几个基本概念的同时,我们会用到 Mesh(网格).数学运算.4x4矩阵的一些简单的操作.但由于克森也是新手,文 ...

  4. Unity3D 几个基本动画(控制物体移动、旋转、缩放)

    Transform基本移动函数: 1.指定方向移动: //移动速度 float TranslateSpeed = 10f; //Vector3.forward 表示"向前" tra ...

  5. 二维坐标的平移,旋转,缩放及matlab实现

    本文结合matlab 软件解释二维坐标系下的平移,旋转,缩放 首先确定点在二维坐标系下的表达方法,使用一个1*3矩阵: Pt = [x,y,1] 其中x,y 分别为点的X,Y坐标,1为对二维坐标的三维 ...

  6. opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移

    常常需要最图像进行仿射变换,仿射变换后,我们可能需要将原来图像中的特征点坐标进行重新计算,获得原来图像中例如眼睛瞳孔坐标的新的位置,用于在新得到图像中继续利用瞳孔位置坐标. 仿射变换在:http:// ...

  7. WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示

    原文:WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示 为方便描述, 这里仅以正方形来做演示, 其他图形从略. 运行时效果图:XAML代码:// Transform.XAML< ...

  8. 使用C++实现图形的旋转、缩放、平移

    编译环境:VS2017 编译框架:MFC 实验内容:显示一个三角形,并将其绕中心进行旋转.缩放以及平移等操作 实验步骤: 1.打开VS2017,并创建MFC项目,具体方法参见:http://www.c ...

  9. 初学Direct X(7) ——位图的旋转,缩放以及平移

    初学Direct X(7) --位图的旋转,缩放以及平移 本文旨在实现通过D3DXMatrixTransformation2D函数实现位图的旋转,缩放以及平移操作,但是具体的原理部分会在后面进一步的探 ...

随机推荐

  1. React Refs All In One

    React Refs All In One https://reactjs.org/docs/react-api.html#refs Ref https://reactjs.org/docs/refs ...

  2. DOH & TRR & HTTPS & DNS

    DOH & TRR & HTTPS & DNS DNS over HTTPS Trusted Recursive Resolver DNS 解析过程图解 DNS 解析过程 递归 ...

  3. React LifeCycle API

    React LifeCycle API old API & new API 不可以混用 demo https://codesandbox.io/s/react-parent-child-lif ...

  4. Angular Routing

    Angular Routing v9.0.7 https://angular.io/start/start-routing

  5. TypeScript 3.7 RC & Assertion Functions

    TypeScript 3.7 RC & Assertion Functions assertion functions, assert https://devblogs.microsoft.c ...

  6. XML & XPath & XQuery

    XML & XPath & XQuery full XPath demo https://www.w3.org/TR/xpath-full-text-30/ https://www.w ...

  7. nodejs 查看进程表

    psaux tasklist system-tasks const { exec } = require("child_process"); const isWindows = p ...

  8. JavaScript 中的执行上下文和执行栈

    JavaScript - 原理系列 ​ 在日常开发中,每当我们接手一个现有项目后,我们总喜欢先去看看别人写的代码.每当我们看到别人写出很酷的代码的时候,我们总会感慨!写出这么优美而又简洁的代码的兄弟到 ...

  9. Python算法_盛最多水的容器(04)

    给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0).找出其中的两条线, ...

  10. Java自学第7期——异常(Exception)

    1.概念: 异常 :指的是程序在执行过程中,出现的非正常的情况,终会导致JVM的非正常停止. 在Java等面向对象的编程语言中,异常本身是一个类, 产生异常就是创建异常对象并抛出了一个异常对象. Ja ...