首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >three.js -旋转一个长方形精灵球保持最小的接近

three.js -旋转一个长方形精灵球保持最小的接近
EN

Stack Overflow用户
提问于 2018-09-05 22:52:41
回答 1查看 269关注 0票数 1

给定带有three.js静态摄像机场景、0,0,0上的球形和任意维的矩形sprite (例如文本标签),我正在寻找一种“threejs方法”(或公式),该方法允许精灵在不需要剪裁的情况下在最小半径范围内旋转。

到目前为止,我的方法是计算球体上位置的极坐标,然后用活动维数的因子来抵消雪碧,因为它接近球体的起源。我把它稍微修改了一下:

代码语言:javascript
复制
const xPolar = Math.sin(phi) * Math.sin(theta);
const yPolar = Math.cos(phi);
const zPolar = Math.sin(phi) * Math.cos(theta);
const x = xPolar + sprite.radius * xPolar;
const y = yPolar + sprite.radius * yPolar;
const z = zPolar + (theta < 0 ? -sprite.radius : sprite.radius) * xPolar // ahem;

这里的工作示例:https://codepen.io/theprojectsomething/full/xadQvK/

当phi接近极点时,请注意剪裁。在这个例子中不算太糟,但希望有一个更优雅的解决方案,并从一个更好地理解在发挥作用的人的力量!

备注:

  • 非常了解three.js Spherical类;手动计算是为了清晰起见。
  • 在示例中使用three.js默认坐标空间,任何可适应的解决方案都将被接受!
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-06 09:35:53

让我们试着把我们拥有的东西正规化。首先,我们假设我们在一个坐标系中,球体在原点,视图方向是z轴。如果我们不在那个坐标系中,很容易将输入的数据转换成这个坐标系,然后进行计算,最后再转换回原来的坐标系。

我们有一个方向向量d,它指定了我们希望精灵中心出现的方向(在代码片段中,这就是您所称的xyzPolar )。此外,我们有雪碧的宽度w和高度h,我们知道宽度沿x轴扩展,高度沿y轴扩展(因为我们有一个视图对齐坐标系)。

现在,对于任意标量偏移量t,我们可以将sprite的中心指定为t * d。然后,我们的sprite上的要点由以下集合描述:

代码语言:javascript
复制
{ t * d + x * (w/2, 0, 0) + y * (0, h/2, 0) | -1 <= x <= 1, -1 <= y <= 1 }

xy是雪碧上的参数位置,其中(-1, -1)定义左下角,(0, 0)定义中心。我们特别感兴趣的是离球心最近的点,我们希望这个点是r (球体的半径),远离它。因此:

代码语言:javascript
复制
     min          (t * dx + x * w/2)^2 + (t * dy + y * h/2)^2 + (t * dz)^2 = r^2
x, y in [-1, 1]

如果我们知道这个最近点的参数xy,我们可以很容易地求解t,给出精灵的最终中心位置。

然而,我们不知道这些参数。让我们把这个公式分开:

代码语言:javascript
复制
(    min     (t * dx + x * w/2)^2 ) + (    min     (t * dy + y * h/2)^2 ) + (t * dz)^2 = r^2
 x in [-1, 1]                          y in [-1, 1]

如果我们可以设置前两个项,则将最小化。

代码语言:javascript
复制
x = -2 dx t / w
y = -2 dy t / h

在这种情况下,这两个条件将为零,我们可以解决t = r / abs(dz)。本质上,这将把雪碧放在z = +- r所在的xy对齐平面上。如果我们有一个无限的精灵,在这里我们没有约束xy,这就是事实。

然而,我们没有无限的精灵。我们必须限制xy在允许的范围内。因此,如果我们有一个候选的t,我们也可以检查它是否是一个有效的解决方案,只需使用上面的公式计算xy,并检查它们是否在允许的范围内。如果最近的点在精灵中心的某个地方(而不是在边缘或拐角处),这将是正确的。

幸运的是,对于xy,我们只需要检查一些可能的值。因此,该算法将计算所有可能值的t,然后检查该解决方案是否有效,并且只保留单个有效解。现在,xy可能有哪些值?

我们已经知道了-1 <= x <= 1-1 <= y <= 1的情况。此范围内的所有值都是等效的,因为它们使前两个项为零(对最终结果没有影响)。对于每个变量,还有两种情况。x = -1x = 1 (y相同)。这总共给出了我们需要解决的9个组合。但我们可以做得更好。我们知道twh是阳性的。因此,xy将分别具有与dxdy相反的标志。例如,如果dx是正的,我们只需要检查x = -1或第一个项消失的情况(本质上,这意味着如果方向向量指向右侧,雪碧的右边边缘永远不会是最近的点)。同样地,如果dxdy完全为零,我们立即知道相应的术语消失了,我们不需要考虑另一种情况。另外,如果是dz = 0,不要评估前两个项消失的情况

所以我们只剩下四个案子了。作为参考,以下是每个变量的三种不同情况的术语:

代码语言:javascript
复制
            first term
-1 = x      dx^2 * t^2 - dx * t * w + w^2 / 4
-1 < x < 1  0
     x = 1  dx^2 * t^2 + dx * t * w + w^2 / 4

            second term
-1 = y      dy^2 * t^2 - dy * t * h + h^2 / 4
-1 < y < 1  0
     y = 1  dy^2 * t^2 + dy * t * h + h^2 / 4

对于需要评估的四种情况,组合二次方程并求解t。最后,计算xy,并检查它们是否匹配案例(如果您有案例x = 1,检查是否符合x >= 1等)。最后,计算出雪碧中心为t * d

因此,不幸的是,这并不比你所拥有的更优雅,但它更准确。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52194353

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档