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. 如何在 GitHUb 上使用 gitbook 发布一本在线书籍

    如何在 GitHUb 上使用 gitbook 发布一本在线书籍 ebook / pdf refs https://docs.gitbook.com/integrations/github xgqfrm ...

  2. js with All In One

    js with All In One 不推荐,要废弃 function f(x, o) { with (o) { console.log(x); } } function f(foo, values) ...

  3. leetcode bug & 9. Palindrome Number

    leetcode bug & 9. Palindrome Number bug shit bug "use strict"; /** * * @author xgqfrms ...

  4. web cache & web storage all in one

    web cache & web storage all in one web cache in action web cache best practices web storage in a ...

  5. vue的filter用法,检索内容

    var app5 = new Vue({ el: '#app5', data: { shoppingList: [ "Milk", "Donuts", &quo ...

  6. 【目标检测】用Fast R-CNN训练自己的数据集超详细全过程

    目录: 一.环境准备 二.训练步骤 三.测试过程 四.计算mAP 寒假在家下载了Fast R-CNN的源码进行学习,于是使用自己的数据集对这个算法进行实验,下面介绍训练的全过程. 一.环境准备 我这里 ...

  7. spring5学习笔记

    Spring5 框架概述 1.Spring 是轻量级的开源的 JavaEE 框架 2.Spring 可以解决企业应用开发的复杂性 3.Spring 有两个核心部分:IOC 和 Aop (1)IOC:控 ...

  8. 原生javascript开发计算器实例

    计算器的主要作用是进行数字运算,开发一个计算器功能的web实例,有助于更好的掌握js基础的数字运算能力. 本实例详细分析一个js计算器的开发步骤,学习本教程时最好先具备一些基础的js知识. 计算器包括 ...

  9. javascript 十大经典排序

    首先生成一个数字数组: let arr = Array.from({length:20},x=>{return Math.ceil(Math.random()*10**2)}) console. ...

  10. java基础第12期——反射、注解

    一. 反射 反射: 将类的各个组成部分封装为其他对象. 1.1 获取class对象的方式 Class.forName("全类名"): 将字节码文件加载进内存,返回class对象 多 ...