我有一个由对象空间中心点和半径表示的球体。球体被转换为世界空间,其变换矩阵可以包括尺度,旋转和平移。我需要在世界空间中为球体构建一个轴对齐的边界框,但我不知道该怎么做。
这是我当前的方法,适用于某些情况:
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));
}
但是,我怀疑这一切都会奏效。它不应该因为非均匀缩放而失败吗?
答案 0 :(得分:9)
通常,变换后的球体将是某种椭圆体。得到一个精确的边界框并不难;如果你不想通过所有的数学运算:
M
是您的转换矩阵(比例,旋转,翻译等)S
R
,如末尾所述x
计算y
,z
和R
界限,如上所述。一般圆锥曲线(包括球体及其变换)可以表示为对称的4x4矩阵:当p
时,同构点S
位于圆锥p^t S p < 0
内。通过矩阵M转换空间M转换S矩阵如下(下面的约定是点是列向量):
A unit-radius sphere about the origin is represented by:
S = [ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 -1 ]
point p is on the conic surface when:
0 = p^t S p
= p^t M^t M^t^-1 S M^-1 M p
= (M p)^t (M^-1^t S M^-1) (M p)
transformed point (M p) should preserve incidence
-> conic S transformed by matrix M is: (M^-1^t S M^-1)
圆锥的对偶,适用于平面而不是点,用S的倒数表示;对于平面q(表示为行向量):
plane q is tangent to the conic when:
0 = q S^-1 q^t
= q M^-1 M S^-1 M^t M^t^-1 q^t
= (q M^-1) (M S^-1 M^t) (q M^-1)^t
transformed plane (q M^-1) should preserve incidence
-> dual conic transformed by matrix M is: (M S^-1 M^t)
因此,您正在寻找与变换后的圆锥相切的轴对齐平面:
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
和yz-aligned plane:
x = (r14 +/- sqrt(r14^2 - r44 r11) ) / r44
这为您提供了转换球体的精确边界框。
答案 1 :(得分:2)
@comingstorm的答案很优雅,因为它使用了圆锥的齐次坐标和对偶性。
该问题也可以看作是约束最大问题,可以通过拉格朗日乘数法来解决。以y轴的AABB为例。优化目标是
约束是椭球方程
拉格朗日是
其中lambda是乘数。极值只是以下方程的解
给出
答案 2 :(得分:1)
这不适用于非均匀缩放。用拉格朗日乘子(KKT定理)计算任意可逆仿射变换是可能的,我相信它会变得丑陋。
然而 - 你确定你需要一个确切的AABB吗?您可以通过变换球体的原始AABB并获得其AABB来近似它。它比确切的AABB大,因此它可能适合您的应用。
为此,我们需要有三个伪函数:
GetAABB(sphere)
将获得球体的AABB。
GetAABB(points-list)
将获得给定点集的AABB(仅对所有点的最小/最大坐标)。
GetAABBCorners(p, q)
将获得AABB的所有8个角点(p和q都在其中)。
(p, q) = GetAABB(sphere);
V = GetAABBCorners(p, q);
for i = 1 to 8 do
V[i] = Transform(T, V[i]);
(p, q) = GetAABB(V);
答案 3 :(得分:1)
@ 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且其中心位于原点。)
我写了一篇带有证明here的博文,这对于合理的Stack Overflow答案来说太长了。