Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Graphics 计算变换球体的AABB_Graphics_Aabb - Fatal编程技术网

Graphics 计算变换球体的AABB

Graphics 计算变换球体的AABB,graphics,aabb,Graphics,Aabb,我有一个球体,在物体空间中用一个中心点和一个半径来表示。球体通过变换矩阵变换到世界空间,变换矩阵可能包括缩放、旋转和平移。我需要为世界空间中的球体构建一个轴对齐的边界框,但我不确定如何实现 以下是我目前的方法,适用于某些情况: public void computeBoundingBox() { // center is the middle of the sphere // averagePosition is the middle of the AABB // get

我有一个球体,在物体空间中用一个中心点和一个半径来表示。球体通过变换矩阵变换到世界空间,变换矩阵可能包括缩放、旋转和平移。我需要为世界空间中的球体构建一个轴对齐的边界框,但我不确定如何实现

以下是我目前的方法,适用于某些情况:

public void computeBoundingBox() {
    // center is the middle of the sphere
    // averagePosition is the middle of the AABB
    // getObjToWorldTransform() is a matrix from obj to world space
    getObjToWorldTransform().rightMultiply(center, averagePosition);

    Point3 onSphere = new Point3(center);
    onSphere.scaleAdd(radius, new Vector3(1, 1, 1));
    getObjToWorldTransform().rightMultiply(onSphere);

    // but how do you know that the transformed radius is uniform?
    double transformedRadius = onSphere.distance(averagePosition);

    // maxBound is the upper limit of the AABB
    maxBound.set(averagePosition);
    maxBound.scaleAdd(transformedRadius, new Vector3(1, 1, 1));

    // minBound is the lower limit of the AABB
    minBound.set(averagePosition);
    minBound.scaleAdd(transformedRadius, new Vector3(-1,-1,-1));
}

然而,我怀疑这是否会一直奏效。非均匀缩放不应该失败吗?

这不适用于非均匀缩放。用拉格朗日乘子(KKT定理)计算任意可逆仿射变换是可能的,我相信它会变得丑陋

但是-您确定需要准确的AABB吗?可以通过变换球体的原始AABB并获得其AABB来近似它。它比精确的AABB大,因此可能适合您的应用程序

为此,我们需要三个伪函数:

GetAABB(球体)
将获取球体的AABB

GetAABB(点列表)
将获取给定点集的AABB(所有点的最小/最大坐标)

GetAABBCorners(p,q)
将获得AABB的所有8个角点(p和q在其中)


通常,变换后的球体将是某种椭球体。要得到一个精确的边界框并不难;如果您不想完成所有的数学运算:

  • 请注意,
    M
    是变换矩阵(缩放、旋转、平移等)
  • 阅读下面的
    S
    的定义
  • 计算
    R
    ,如末尾所述
  • 如前所述,基于
    R
    计算
    x
    y
    z
    边界

一般二次曲线(包括球体及其变换)可以表示为对称4x4矩阵:当
p^ts p<0
时,齐次点
p
位于二次曲线
S
内。通过矩阵M变换空间按如下方式变换S矩阵(下面的约定是点是列向量):

适用于平面而非点的二次曲线的对偶由S的逆表示;对于平面q(表示为行向量):

因此,您正在寻找与变换的圆锥曲线相切的轴对齐平面:

let (M S^-1 M^t) = R = [ r11 r12 r13 r14 ]  (note that R is symmetric: R=R^t)
                       [ r12 r22 r23 r24 ]
                       [ r13 r23 r33 r34 ]
                       [ r14 r24 r34 r44 ]

axis-aligned planes are:
  xy planes:  [ 0 0 1 -z ]
  xz planes:  [ 0 1 0 -y ]
  yz planes:  [ 1 0 0 -x ]
要查找与R相切的xy对齐平面,请执行以下操作:

  [0 0 1 -z] R [ 0 ] = r33 - 2 r34 z + r44 z^2 = 0
               [ 0 ]
               [ 1 ]
               [-z ]

  so, z = ( 2 r34 +/- sqrt(4 r34^2 - 4 r44 r33) ) / ( 2 r44 )
        = (r34 +/- sqrt(r34^2 - r44 r33) ) / r44
类似地,对于xz对齐的平面:

      y = (r24 +/- sqrt(r24^2 - r44 r22) ) / r44
      x = (r14 +/- sqrt(r14^2 - r44 r11) ) / r44
和yz对齐平面:

      y = (r24 +/- sqrt(r24^2 - r44 r22) ) / r44
      x = (r14 +/- sqrt(r14^2 - r44 r11) ) / r44

这为变换后的球体提供了一个精确的边界框。

@comingstorm的答案很好,但可以简化很多。如果
M
是球体的变换矩阵,从1开始索引,则

x = M[1,4] +/- sqrt(M[1,1]^2 + M[1,2]^2 + M[1,3]^2)
y = M[2,4] +/- sqrt(M[2,1]^2 + M[2,2]^2 + M[2,3]^2)
z = M[3,4] +/- sqrt(M[3,1]^2 + M[3,2]^2 + M[3,3]^2)
(这假设球体在变换之前半径为1,其中心位于原点。)


我写了一篇带有证明的博文,这对于合理的堆栈溢出答案来说太长了。

@comingstorm的答案很优雅,因为它使用了齐次坐标和二次曲线的对偶性

该问题也可以看作是一个约束最大化问题,可以用拉格朗日乘子法求解。以y轴上的AABB为例。优化目标是

约束条件是椭球方程

拉格朗日方程是

其中lambda是乘数。极值只是下列方程的解


这是哪种语言?(看起来像Java。)看起来像C#,但这确实是一个语言不可知的问题,我不需要确切的AABB。然而,我不确定你建议的替代方案是什么。(你能提供伪代码吗?)我应该从未转换的球体生成由两点定义的原始AABB,然后转换这两点,然后…?当然。为此,我们需要三个伪函数:GetAABB(sphere)将获得球体的AABB。GetAABB(点列表)将获得给定点集的AABB(所有点上的最小/最大坐标)。GetAABBCorners(p,q)将获得AABB的所有8个角点(p和q在其中)。(p,q)=GetAABB(球面);V=获得aabbpoints(p,q);对于i=1到8,do V[i]=变换(T,V[i]);(p,q)=GetAABB(V);好啊我看到评论中的张贴代码不起作用。我将编辑我的答案:)注意
S
是一个对合矩阵,因此
S
=
S^-1
x = M[1,4] +/- sqrt(M[1,1]^2 + M[1,2]^2 + M[1,3]^2)
y = M[2,4] +/- sqrt(M[2,1]^2 + M[2,2]^2 + M[2,3]^2)
z = M[3,4] +/- sqrt(M[3,1]^2 + M[3,2]^2 + M[3,3]^2)