vr场景互动程序_vr程序生成场景中的运动

vr场景互动程序

In my article Physical Spaces in Virtual Realities, I motivate the use of procedural generation in VR development as a tool for creating custom environments tailored to the user’s play area.

在我的文章《 虚拟现实中的物理空间》中 ,我鼓励在VR开发中使用过程生成作为一种工具,以创建适合于用户游戏区域的自定义环境。

By using procedural generation in this way, we can expand the limitations of movement in VR — that is, we can make experiences that allow users to explore all of the available play space. In essence, we can have a new tool that allows us to build environments that scale and allow for more locomotion within the virtual world.

通过以这种方式使用过程生成,我们可以扩展VR中运动的局限性-也就是说,我们可以提供使用户能够探索所有可用游戏空间的体验。 从本质上讲,我们可以拥有一个新工具,使我们能够构建可扩展的环境,并允许在虚拟世界中进行更多移动。

In this article, I will illustrate the generation of procedural environments by creating an island. Many VR platforms let the user define boundaries that set the play area (mostly for avoiding walls and physical objects), but Oculus actually provides this as an API with the Guardian system.

在本文中,我将通过创建一个岛来说明过程环境的生成。 许多VR平台都允许用户定义设置游戏区域的边界(主要是为了避开墙壁和物理对象),但是Oculus实际上将其作为Guardian系统的API提供。

Footage of the final result from Oculus Quest. The Guardian input is drawn on the island.
Oculus Quest最终结果的画面。 监护人输入在岛上绘制。

Let’s understand how we can use its data for curating an experience. While I focus on Oculus Quest, this walkthrough is relevant for Oculus Rift as well.

让我们了解如何使用其数据来策划体验。 当我专注于Oculus Quest时,本演练也与Oculus Rift有关。

获取输入 (Getting the Inputs)

Image for post

The play area, which is accessible to developers as a polygon or a rectangle, can be used to procedurally generate the scene.

开发人员可以将其作为多边形或矩形访问的游乐区可用于程序生成场景。

We will create an island where sand marks the play area (bounded by the polygon) and the ocean around it the unplayable area (everything outside the polygon) and connect the two with a smooth gradient.

我们将创建一个岛,在该岛上用沙子标记游戏区域(由多边形限制),在其周围的海洋作为不可游戏区域(多边形之外的所有内容),并将两者之间的平滑坡度连接起来。

We will place interactive props procedurally, ensuring they are physically reachable to the user despite the size of the play area. Here are several islands generated from various inputs (the inputs are shown below):

我们将按照程序放置交互式道具,以确保尽管游戏区域很大,但用户在身体上仍可以接触到它们。 这是由各种输入生成的几个岛(输入如下所示):

Image for post

To start playing with the idea, I recorded several Guardian configurations in my living room and saved them locally. You can access my living room data here, or record it yourself using this script. Here are few boundaries I recorded (I tried to create interesting shapes):

为了开始考虑这个想法,我在客厅里录制了一些Guardian配置并将其保存在本地。 您可以在此处访问我的客厅数据,也可以使用此脚本自己记录。 这是我记录的一些边界(我尝试创建有趣的形状):

Image for post
Guardian recordings from my living room.
我客厅里的监护人录音。

To get these shapes, we make two queries to the GetGeometry API call. One, to get the outer boundary polygon (which is used for creating the environment):

为了获得这些形状,我们对GetGeometry API调用进行了两个查询。 一种,获取外部边界多边形 (用于创建环境):

OVRManager.boundary.GetGeometry(OVRBoundary.BoundaryType.OuterBoundary);

And the second, to get the play area rectangle (which is used to properly position the props):

第二,获取游戏区域矩形 (用于正确放置道具):

OVRManager.boundary.GetGeometry(OVRBoundary.BoundaryType.PlayArea);

Now that we have our inputs, we can start thinking about what features our island will have.

现在我们有了输入,我们可以开始考虑我们的岛屿将具有什么特征。

是什么使一个岛成为一个岛? (What Makes an Island an Island?)

An island is a piece of land protruding from the ocean. So, our island should be elevated and smoothly transition into the ocean surrounding it.

岛屿是从海洋伸出的一块土地。 因此,我们的岛屿应该升高并平稳过渡到周围的海洋中。

Translating this to some technical terms:

将其翻译成一些技术术语:

Image for post
  • Floor Level — the height of the island relative to the user space

    楼层高度-岛相对于用户空间的高度

  • Low Level — the height of the ocean relative to the user space

    低水位 -海洋相对于用户空间的高度

  • Horizontal Distance — the horizontal length of the transition from Floor Level to Low Level (how far the island stretches until it reaches the ocean)

    水平距离 -从地面到低层的过渡的水平长度(岛屿延伸到到达海洋的距离)

  • Floor Elevation — the horizontal length of the transition from Floor Level to Low Level (how far the island descends until it reaches the ocean)

    地面高程 -从地面到低层的过渡的水平长度(岛屿下降到到达海洋的距离)

  • Falloff Function — a function we will use to generate a smooth curve between Floor Level and Low Level

    衰减功能 -我们将用来在最低水平和最低水平之间生成平滑曲线的函数

寻找地板 (Finding The Floor)

Next, we will generate a basic mesh from the outer boundary we extracted. To do this, we will need the position of the physical floor relative to our scene and use this position to create a mesh (in which the island is heightened).

接下来,我们将从提取的外部边界生成基本网格。 为此,我们将需要物理地板相对于场景的位置,并使用该位置来创建网格(在该网格中岛被加高)。

To get Floor Level, we need to use Oculus APIs. The Oculus SDK for Unity abstracts this information to fit most scenarios. There is even an enum called Tracking Origin Type in OVRManager that we could theoretically set to FloorLevel.

要获得下限级别,我们需要使用Oculus API。 Oculus SDK for Unity提取了此信息以适合大多数情况。 在OVRManager中甚至有一个名为Tracking Origin Type的枚举,理论上我们可以将其设置为FloorLevel

The problem with this approach is the space we’re building won’t stay in the correct position relative to the physical space when the headset re-centers. If you dig really deep into Oculus Documentation, you find this explanation:

这种方法的问题在于,当耳机重新居中时,我们正在建立的空间不会相对于物理空间保持正确的位置。 如果你真的挖成深Oculus公司的文档, 你会发现这样的解释

The default tracking space is Local, which means re-centering works as normal. This is the correct behavior for most apps.

默认跟踪空间为“本地”,这意味着重新居中可以正常进行。 这是大多数应用程序的正确行为。

Some apps may want to remain anchored to the same space for the duration of the experience because they lay out according to the user’s Guardian bounds. […] These apps may want to use the Stage tracking space.

一些应用可能希望在体验期间保持锚定在相同的空间,因为它们会根据用户的“监护人”范围进行布局。 […]这些应用可能需要使用舞台跟踪空间。

From this, we can understand that we need to set Tracking Origin Type to Stage — it saves us from worrying about accumulating offsets when the app re-centers. But, using Stage also means floor level is arbitrary, so it alone won’t suffice. In contrast, the play area polygon described earlier is calibrated to the actual floor level. So, we can use a combination of the two!

由此可见,我们需要将“ Tracking Origin Type设置为“ Stage ,这使我们不必担心在应用重新居中时累积偏移量。 但是,使用Stage也意味着最低层是任意的,因此仅凭它是不够的。 相反,先前描述的游乐区多边形被校准为实际地板高度。 因此,我们可以将两者结合使用!

创建高程 (Creating Elevation)

Now we know how to position things relative to the player’s floor. It’s a good start which allows us to easily create an elevation difference between the island and the ocean below it. The elevation can be achieved in multiple ways, and here is an overview of my strategy:

现在我们知道了如何相对于玩家的地板放置东西。 这是一个很好的开始,它使我们能够轻松地在岛屿和其下方的海洋之间创建高程差。 可以通过多种方式实现海拔提升,这是我的策略概述:

  1. Procedurally generate a dense plane around the polygon

    程序地在多边形周围生成一个密集平面
  2. Get all the plane vertices which lay outside the polygon

    获取位于多边形外部的所有平面顶点
  3. Lower these vertices to Low Level (the “ocean level”)

    降低这些顶点到低电平 (“海平面”)

生成飞机 (Generating a plane)

Depending on the polygon, the plane might look like this:

取决于多边形,平面可能如下所示:

Image for post
Horizontal Distance we defined earlier should pad the entire island’s perimeter. 水平距离”应该覆盖整个岛屿的周长。

Notice how the plane is generated from squares (pairs of triangles, to be precise). The square count is proportional to the density of the mesh and therefore will affect how smooth the island and its edges will appear.

请注意,如何从正方形(精确地说是成对的三角形)生成平面。 平方数与网格的密度成正比,因此会影响岛及其边缘的平滑程度。

Image for post
Generating environments with different vertices count affects the fidelity of the final result. 生成具有不同顶点数的环境会影响最终结果的保真度。

As vertex count increases, the model’s resolution increases. I found that 1000 vertices provided a good balance between smoothness and performance.

随着顶点数量的增加,模型的分辨率也随之提高。 我发现1000个顶点在平滑度和性能之间提供了良好的平衡。

降低多边形外部顶点的高度 (Lowering the height of vertices outside the polygon)

Next, we will lower the position of all points outside the polygon to Low Level. I used this code snippet to help me find whether a point is inside a polygon. This generated a promising result:

接下来,我们将多边形外所有点的位置降低到Low Level 。 我使用此代码段帮助我确定一个点是否在多边形内。 这产生了可喜的结果:

Image for post
Our plane with all the vertices outside the polygon lowered.
降低了多边形外部所有顶点的平面。

平滑高程 (Smoothing the Elevation)

The result so far is literally rough around the edges, but it’s definitely starting to look like an island. What we need now is to smooth things out .

到目前为止,结果实际上在边缘上是粗糙的,但是肯定开始看起来像一个孤岛。 我们现在需要的是解决问题。

Recall that we created some spare mesh around the polygon using the Horizontal Distance. We can take the edges of the polygon and gradually heighten the mesh until it reaches sea level:

回想一下,我们使用“ 水平距离”在多边形周围创建了一些备用网格。 我们可以采用多边形的边缘并逐渐加高网格,直到达到海平面:

Image for post

It’s subtle, but the points closest to the polygon have lowered. If we repeat the process over and over again until we reach Horizontal Distance away from the island, all vertices will be lowered in gradient fashion.

它很微妙,但是最接近多边形的点降低了。 如果我们一遍又一遍地重复此过程,直到达到离岛的“ 水平距离 ”,所有顶点将以渐变方式降低。

To get a basic algorithm working, let’s define a simple linear transition between the island (Floor Level) and the sea (Low Level). A straight line would radiate from every point on the island perimeter towards the surrounding ocean.

为了使基本算法起作用,让我们定义一个在岛( Floor Level )和海( Low Level )之间的简单线性过渡。 一条直线将从岛周围的每个点向周围的海洋辐射。

Image for post

We need to know the distance of every mesh vertex to the polygon in order to know how much to lower it. Theoretically, this would require checking the distance between the point and each side of the polygon (each line segment). Since the polygon we get from Oculus is dense enough we can just assume it’s roughly the same distance to the closest point on the polygon.

我们需要知道每个网格顶点到多边形的距离才能知道降低多少。 从理论上讲,这将需要检查点与多边形每一边(每条线段)之间的距离。 由于我们从Oculus获得的多边形足够密集,因此我们可以假设它与多边形上最近点的距离大致相同。

With all the pieces in place, multiple iterations of the algorithm generate this:

在所有组件都准备就绪的情况下,该算法的多次迭代生成了以下代码:

Image for post
The island mesh, built iteratively from the perimeter of the polygon.
从多边形的边界迭代构建的岛状网格。

After 13 iterations, the outermost vertices reach sea level and the smoothing is complete.

经过13次迭代后,最外面的顶点到达海平面,并且平滑完成。

抛光 (Polishing)

美化过渡 (Beautify the transition)

Until now, we used a linear falloff function to smooth the island’s transition into the ocean. To make the transition look even more natural, we can apply a non-linear falloff function. There are many interesting falloff functions we can choose from.

到目前为止,我们使用线性衰减函数来平滑岛屿向海洋的过渡。 为了使过渡看起来更加自然,我们可以应用非线性衰减函数。 我们可以选择许多有趣的衰减功能

Image for post
With a non-linear falloff function, vertices are positioned in different heights.
使用非线性衰减功能,顶点可以放置在不同的高度。

After playing with some options, I chose 3x² — 2x³. Using this function instead, we get the final result:

在玩了一些选项之后,我选择了3x² — 2x³ 。 使用此函数,我们得到最终结果:

Image for post
The island mesh with a non-linear falloff function (3x² — 2x³)
具有非线性衰减功能(3x²—2x³)的孤岛网格

This transition looks natural and convincing! After applying shaders to render the sand texture and the ocean, we get this:

这种过渡看起来自然而令人信服! 应用着色器渲染沙子纹理和海洋后,我们得到以下信息:

Image for post
A custom shader is used on the generated mesh, creating a natural-looking island.
在生成的网格上使用自定义着色器,以创建看起来自然的岛。

带有一些道具的香料 (Spice with some props)

Lastly, we can decorate our environment with interactable props. I chose to use the playable rectangle to procedurally position the props, but the polygon could also be used.

最后,我们可以使用可交互的道具来装饰环境。 我选择使用可播放的矩形在程序上放置道具,但是也可以使用多边形。

Image for post
Using the play area rectangle to generate props.
使用游戏区域矩形生成道具。

This gives us the complete interactive island:

这给了我们完整的交互式岛:

Image for post

相同的概念,新的环境 (Same Concept, New Environments)

I tried to keep the island parameters flexible enough to play with. By just changing a few of them, we can generate vastly different results:

我试图使孤岛参数足够灵活地使用。 通过仅更改其中一些,我们可以产生截然不同的结果:

调整海拔高度: (Tweaking the elevation:)

Image for post
Horizontal Distance and 水平距离Floor Elevation can dramatically change the resulting mesh. 地板高程可以极大地改变最终的网格。

倒车楼层低等级的角色: (Reversing the roles of Floor Level and Low Level:)

Image for post
Floor Elevation to have negative values can create interesting valley-like meshes. 楼层高程设置为负值可以创建有趣的山谷状网格。

I uploaded the source code and a playable demo of everything I showed here, in case you want to try it yourself.

我上载了我在此处显示的所有内容的源代码可播放的演示 ,以防您想自己尝试。

结语 (Wrapping It Up)

Since Oculus exposed the play area polygon in their APIs, I haven’t been able to find any VR experiences that utilize it (if you’ve seen one, please let me know in the comments!). I have played the innovative indie game Tea For God, which uses the play area rectangle to procedurally generate a maze, but that’s the extent of what I found.

由于Oculus在其API中公开了游戏区域多边形,因此我无法找到任何利用它的VR体验(如果您已经看过,请在评论中告诉我!)。 我玩过创新的独立游戏Tea For God ,它使用游戏区域矩形以程序方式生成一个迷宫,但这就是我所发现的范围。

Perhaps this is because the information is buried deep in the Oculus documentation and is mostly left unnoticed; maybe it’s too new, underdeveloped and a bit buggy; or perhaps its usage and potential just isn’t obvious.

也许是因为这些信息被深埋在Oculus文档中,并且几乎没有被注意到。 也许它太新了,欠发达并且有一些bug。 也许它的用途和潜力并不明显。

Whatever the reason, I believe the VR world should be more aware of its existence. My goal here was to demonstrate that, despite the currently limited capabilities of this new input, it’s still possible to explore its potential.

无论出于何种原因,我都认为VR世界应该更加意识到它的存在。 我在这里的目的是证明,尽管此新输入的功能目前有限,但仍有可能挖掘其潜力。

Image for post

In this particular demo, we saw how the play area polygon served as an input to the procedural generation of an environment, allowing us to create a custom environment that scales to the user’s playable surroundings. This is just one thing we can do with the user’s physical space, and more generally, with Virtual Reality as a whole.

在这个特定的演示中,我们看到了游乐区多边形如何用作环境的过程生成的输入,从而使我们能够创建可缩放到用户可玩环境的自定义环境。 这只是我们可以处理用户的物理空间, 更广泛而言,可以使用虚拟现实作为整体的一件事。

Many thanks to Polygon Punch for the great 3D assets.

非常感谢 Polygon Punch 提供的出色3D资产。

翻译自: https://medium.com/@thebne/locomotion-in-vr-procedural-generation-of-a-scene-2e1cc22c1f8b

vr场景互动程序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值