跳到主要内容

坐标空间术语

概述

通过本小节的学习你将了解到IdeaXR中的空间变换及变换常用的类操作:

坐标系的定义

IdeaXR中使用右手坐标系,如下图所示:

Docusaurus Plushie
图1-IdeaXR坐标系

我们可以这样用手来比划,沿着正y轴方向伸出你的右臂,手心朝向自己,手指着上方:

  • 大拇指指向右方

  • 食指指向上方

  • 中指向下弯曲90度

此时你的大拇指指向x轴正方向,食指指向y轴正方向,中指指向z轴正方向,到这里你就学会了我们IdeaXR中关于坐标系的定义。

有了坐标系的概念我们继续来学习关于坐标空间的知识

局部坐标空间与世界坐标空间

  • 局部坐标空间: 物体自身的模型顶点构成的空间称为局部空间,在此空间下创建的坐标系称为局部坐标系,它的坐标原点一般以模型为中心。 当我们点击如下按钮就可以让物体以自身为坐标原点进行旋转

Docusaurus Plushie

Docusaurus Plushie

  • 世界坐标空间:拥有局部坐标系的物体,仅仅是一个孤立的3D模型,当需要同时渲染多个3D物体时,就需要把不同的3D模型变换到一个统一的坐标空间中,而这个空间就是世界坐标系空间。 当我们点击如下按钮就可以让物体以世界原点为中心进行旋转

Docusaurus Plushie

Docusaurus Plushie

相机坐标空间与裁剪坐标空间

  • 相机坐标空间:也称为观察空间,是将世界空间坐标转化为视野前方坐标的一种坐标空间,也即视角所观察到的空间。

  • 裁剪坐标空间:因为观察空间依然是个十分大的空间,我们需要将看不到的物体裁剪掉,所以裁剪后保留下来的空间就是裁剪空间。 在相机坐标空间和裁剪坐标空间下又有透视投影正交投影,并且他们都可以进行远近裁剪,其中近裁剪是指靠近摄像机端的裁剪,远裁剪是指远离摄像机端的裁剪。

    透视投影下的空间裁剪

Docusaurus Plushie

正交投影下的空间裁剪

Docusaurus Plushie

屏幕坐标与视口

  • 屏幕坐标空间:屏幕坐标系空间相当于一个二维平面,只是这个平面是显示器的表面,并且宽高也做了一定限制,它的坐标空间就是从0到屏幕的宽高。
  • 窗口坐标空间:窗口坐标空间它定义了我们需要显示什么内容。
  • 视口坐标空间:视口坐标空间指定了显示的内容在窗口的什么位置。

Docusaurus Plushie

如上图所示,我们视觉上可以看到这三个坐标空间之间呈现的位置关系,窗口是一个逻辑坐标环境,它是经一系列坐标空间变换后得到的一个需要在矩形区域内显示的位置空间,并且一个窗口可以有多个视口,视口中的内容是我们真正看到的显示内容。

同一窗口下可以显示多个视口的内容

Docusaurus Plushie

不同视口中的显示内容是不同的数据,虽然在同一窗口中呈现出来,但若没有视口的存在它们是不知道应该显示在哪里的。

空间变换

常见的向量运算

  • 点积

点积是对两个向量的操作,返回一个标量,两个向量点乘记作a · b; 在实际使用时,我们只需要调用内置方法就可以,例如:

var c = a.dot(b)
var c = a.dot(b)
  • 叉积

和点积一样,叉积也是对两个向量的运算,记作a x b。但是,叉乘积的结果是一个方向与两个向量垂直的向量。它的大小取决于相对角度,如果两个向量是平行的,那么叉积的结果将是一个空向量。 叉积是这样计算的:

var c = a.dot(b)
var c = Vector3()
c.x = (a.y * b.z) - (a.z * b.y)
c.y = (a.z * b.x) - (a.x * b.z)
c.z = (a.x * b.y) - (a.y * b.x)

使用IdeaXR的内置方法可以这样计算:

var c = a.cross(b)

常见的矩阵运算方法类

在上面已经介绍了局部坐标系和世界坐标系的不同,以及对一个物体怎样在局部坐标下切换到世界坐标系中。接下来我们将了解这些变换的使用类:

Transform类

transform是个3D变换,可以表示平移,旋转和缩放等。

我们可以通过改变如下参数来达到平移,旋转和缩放效果:

Docusaurus Plushie

AABB和Rect2

AABB

AABB是轴对齐包围盒,它由一个位置,一个size和一些实用函数组成。

它有三个属性:

  • Vector3 end
    Default: Vector3(0,0,0) 终点角,通过position + size计算而来,设置该值会修改大小。

  • Vector3 position
    Default: Vector3(0,0,0) 起点角,通常比end小。

  • Vector3 size
    Default: Vector3(0,0,0) 从positionend的大小,通常所有分量都是正数,如果大小为负,可以用abs修正。

常用类方法说明如下:

  • AABB AABB ( Vector3 position, Vector3 size )

    用一个位置和大小构造AABB.

  • AABB expand ( Vector3 to_point )

返回该 AABB 的副本,该副本扩展至包含给出的点。

构造一个轴对齐包围盒并用给出的点扩展一个副本示例如下:

# position(-3, 2, 0), size(1, 1, 1)
var box = AABB ( Vector3(-3, 2, 0),Vector3(1, 1, 1) )
# position(-3, -1, 0), size(3, 4, 2),包含原来的 AABB 和 Vector3(0, -1, 2)
var box2 = box.expand ( Vector3(0, -1, 2) )

并且也可以用以下方法获取AABB的体积

  • float get_area()

    获取该 AABB 的体积。

Rect2

Rect2是2D轴对齐边界框,它也是由一个位置,一个size和一些实用函数组成。

它有三个属性:

  • Vector2 end
    Default: Vector2(0,0) 终点角,通过position + size计算而来,设置该值会修改大小。

  • Vector2 position
    Default: Vector2(0,0) 起点角,通常比end小。

  • Vector2 size
    Default: Vector2(0,0) 从positionend的大小,通常所有分量都是正数,如果大小为负,可以用abs修正。

常用类方法说明如下:

  • Rect2 Rect2 ( Vector2 position, Vector2 size )

    按位置和大小构造一个Rect2。

  • Rect2 Rect2 ( float x, float y, float width, float height )

    通过x、y、宽度和高度构造一个Rect2。

  • Rect2 abs()

返回具有相同位置和面积的 Rect2,经过修改,使左上角为原点,width 和 height 为正数。

  • Rect2 clip ( Rect2 b )

返回此 Rect2 和 b 的交集。

  • Rect2 expand ( Vector2 to_point )

返回该 Rect2 的副本,该副本扩展至包含给出的点。

构造一个轴对齐边界框并用给出的点扩展一个副本示例如下:

# position(-3, 2), size(1, 1)
var rect = Rect2 ( Vector2(-3, 2),Vector2(1, 1) )
# position(-3, -1), size(3, 4),包含原来的 Rect 和 Vector2(0, -1)
var rect2 = rect.expand ( Vector2(0, -1) )

并且也可以用以下方法获取Rect2的面积

  • float get_area()

    返回 Rect2 面积。

AABB和Rect2的区别

AABB是三维的,Rect2是二维的,它们是互相在不同空间维度的对应物。

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet