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. Inkscape 太慢

    问题: 在画板上图像较多时, 会在粘贴 / 删除 时会陷入长时间的等待 解决: 最佳: Ubuntu上面的比windows上的快上几十倍, 测试比较, 感觉并不是Ubuntu上多用了GPU, 总之, ...

  2. VSCode 开放式架构的产品实现思路

    VSCode 开放式架构的产品实现思路 https://code.visualstudio.com/ 源码 https://github.com/microsoft/vscode https://gi ...

  3. 为什么国内的好多具备 HTTPS 的网站却没有使用 HTTPS 重定向功能

    为什么国内的好多具备 HTTPS 的网站却没有使用 HTTPS 重定向功能 HTTPS 重定向 good demos ️ HTTPS http://www.xgqfrms.xyz/ https://w ...

  4. ESLint & .eslintignore

    ESLint & .eslintignore https://stackoverflow.com/questions/42250257/disable-eslint-rules-for-fol ...

  5. Interview of Chinese IT companies Ratings and Reviews website/app

    Interview of Chinese IT companies Ratings and Reviews website/app // js hack const getShitRank = (st ...

  6. GeoJSON feature & Mapbox segments

    GeoJSON feature & Mapbox segments custom JSON format ??? { "rows": [], "props&quo ...

  7. vscode & peacock extension

    vscode & peacock extension https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-p ...

  8. Flutter 创建透明的路由页面

    原文 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends St ...

  9. Captain Technology INC浅谈新能源汽车的未来

    近日全世界上最大的资管公司贝莱德向位于的英国电动汽车初创公司Arrival投资1.18亿美元,且该公司已有投资者亚马逊和美国第二大汽车制造商福特汽车参投.中国最知名的电动车公司蔚来股价单日大涨22%, ...

  10. 【Python核心编程笔记】一、Python中一切皆对象

    Python中一切皆对象 本章节首先对比静态语言以及动态语言,然后介绍 python 中最底层也是面向对象最重要的几个概念-object.type和class之间的关系,以此来引出在python如何做 ...