ARFoundation - 实现物体旋转, 平移,缩放
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 - 实现物体旋转, 平移,缩放的更多相关文章
- OpenGL中旋转平移缩放等变换的顺序对模型的影响
l 前提: 0x01. 假设绘制顶点的语句为Draw Array,变换的语句(旋转.平移.缩放)为M,而 M0; M1; M2; Draw Array; 则称对Array先进行M2再进行M1.M0 0 ...
- Three.js三维模型几何体旋转、缩放和平移
创建场景中的三维模型往往需要设置显示大小.位置.角度,three.js提供了一系列网格模型对象的几何变换方法,从WebGL的角度看,旋转.缩放.平移对应的都是模型变换矩阵,关于矩阵变换内容可以观看本人 ...
- 【转载】Unity中矩阵的平移、旋转、缩放
By:克森 简介 在这篇文章中,我们将会学到几个概念:平移矩阵.旋转矩阵.缩放矩阵.在学这几个基本概念的同时,我们会用到 Mesh(网格).数学运算.4x4矩阵的一些简单的操作.但由于克森也是新手,文 ...
- Unity3D 几个基本动画(控制物体移动、旋转、缩放)
Transform基本移动函数: 1.指定方向移动: //移动速度 float TranslateSpeed = 10f; //Vector3.forward 表示"向前" tra ...
- 二维坐标的平移,旋转,缩放及matlab实现
本文结合matlab 软件解释二维坐标系下的平移,旋转,缩放 首先确定点在二维坐标系下的表达方法,使用一个1*3矩阵: Pt = [x,y,1] 其中x,y 分别为点的X,Y坐标,1为对二维坐标的三维 ...
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
常常需要最图像进行仿射变换,仿射变换后,我们可能需要将原来图像中的特征点坐标进行重新计算,获得原来图像中例如眼睛瞳孔坐标的新的位置,用于在新得到图像中继续利用瞳孔位置坐标. 仿射变换在:http:// ...
- WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示
原文:WPF/Silverlight中图形的平移,缩放,旋转,倾斜变换演示 为方便描述, 这里仅以正方形来做演示, 其他图形从略. 运行时效果图:XAML代码:// Transform.XAML< ...
- 使用C++实现图形的旋转、缩放、平移
编译环境:VS2017 编译框架:MFC 实验内容:显示一个三角形,并将其绕中心进行旋转.缩放以及平移等操作 实验步骤: 1.打开VS2017,并创建MFC项目,具体方法参见:http://www.c ...
- 初学Direct X(7) ——位图的旋转,缩放以及平移
初学Direct X(7) --位图的旋转,缩放以及平移 本文旨在实现通过D3DXMatrixTransformation2D函数实现位图的旋转,缩放以及平移操作,但是具体的原理部分会在后面进一步的探 ...
随机推荐
- React Refs All In One
React Refs All In One https://reactjs.org/docs/react-api.html#refs Ref https://reactjs.org/docs/refs ...
- DOH & TRR & HTTPS & DNS
DOH & TRR & HTTPS & DNS DNS over HTTPS Trusted Recursive Resolver DNS 解析过程图解 DNS 解析过程 递归 ...
- React LifeCycle API
React LifeCycle API old API & new API 不可以混用 demo https://codesandbox.io/s/react-parent-child-lif ...
- Angular Routing
Angular Routing v9.0.7 https://angular.io/start/start-routing
- TypeScript 3.7 RC & Assertion Functions
TypeScript 3.7 RC & Assertion Functions assertion functions, assert https://devblogs.microsoft.c ...
- XML & XPath & XQuery
XML & XPath & XQuery full XPath demo https://www.w3.org/TR/xpath-full-text-30/ https://www.w ...
- nodejs 查看进程表
psaux tasklist system-tasks const { exec } = require("child_process"); const isWindows = p ...
- JavaScript 中的执行上下文和执行栈
JavaScript - 原理系列 在日常开发中,每当我们接手一个现有项目后,我们总喜欢先去看看别人写的代码.每当我们看到别人写出很酷的代码的时候,我们总会感慨!写出这么优美而又简洁的代码的兄弟到 ...
- Python算法_盛最多水的容器(04)
给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0).找出其中的两条线, ...
- Java自学第7期——异常(Exception)
1.概念: 异常 :指的是程序在执行过程中,出现的非正常的情况,终会导致JVM的非正常停止. 在Java等面向对象的编程语言中,异常本身是一个类, 产生异常就是创建异常对象并抛出了一个异常对象. Ja ...