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)