英文:
How to fit/clip an axis aligned bounding box around a portion of a triangle
问题
以下是您提供的内容的翻译:
I have looked and looked and cannot find any resources on. I want to clip an axis aligned bounding box against a triangle in a way that creates a new tight fitting axis aligned bounding box around or in the triangle (I have seen the reverse a lot, a triangle clipped against an axis aligned bounding box, but never seen the reverse case). I tried computing the clipped triangle then building a bounding box from it. But it is grossly inefficient and I don't think my code is correct. Does anyone know how to clip a bounding box against a triangle efficiently?
我已经反复查找,但找不到任何相关资源。我想要剪裁一个轴对齐的边界框,以一种方式创建一个新的轴对齐的边界框,紧密围绕或在三角形内部(我经常看到相反的情况,即将三角形剪裁到轴对齐的边界框中,但从未看到相反的情况)。我尝试计算剪裁后的三角形,然后从中构建边界框。但这非常低效,我认为我的代码不正确。有谁知道如何高效地将边界框剪裁到三角形中吗?
这是描述我目前的做法的图片:
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef float f32;
typedef double f64;
struct Point
{
union
{
f32 a[3];
struct
{
f32 x;
f32 y;
f32 z;
};
};
};
struct BoundingBox3
{
Point m_vMin = {FLT_MAX,FLT_MAX,FLT_MAX};
Point m_vMax = {-FLT_MAX,-FLT_MAX,-FLT_MAX};
};
inline
s8 Classify( s8 sign, u8 axis, const Point *c_v, const Point *p_v )
{
const f64 d = sign * ( p_v->a[axis] - c_v->a[axis] );
if ( d > EPSILON )
{
return 1;
}
else if ( d < -EPSILON )
{
return -1;
}
return 0;
}
#define POINT_BUFFER_SIZE 9
inline
void Clip3D_plane( Point *pVerts, s8 sign, u8 axis, u8 *pdwNumVerts, const Point *pPointOnPlane )
{
u8 dwNumVerts = ( *pdwNumVerts );
if ( dwNumVerts == 0 )
{
return;
}
else if ( dwNumVerts == 1 )
{
*pdwNumVerts = 0;
return;
}
Point vNewVerts[POINT_BUFFER_SIZE];
u8 k = 0;
bool b = true; // polygon is fully located on clipping plane
Point v1 = pVerts[dwNumVerts - 1];
s8 d1 = Classify( sign, axis, pPointOnPlane, &v1 );
for ( u8 j = 0; j < dwNumVerts; ++j )
{
const Point &v2 = pVerts[j];
s8 d2 = Classify( sign, axis, pPointOnPlane, &v2 );
if ( d2 != 0 )
{
b = false;
if ( ( 0x80 & ( d2 ^ d1 ) ) != 0 ) //if signs differ
{
const f32 fAlpha = ( v2.a[axis] - pPointOnPlane->a[axis] ) / ( v2.a[axis] - v1.a[axis] );
Point_Lerp( &v2, &v1, fAlpha, &vNewVerts[k++] );
}
else if ( d1 == 0 && ( k == 0 || !Point_Equals( &vNewVerts[k - 1], &v1 ) ) )
{
vNewVerts[k++] = v1;
}
if ( d2 > 0 )
{
vNewVerts[k++] = v2;
}
}
else
{
if ( d1 != 0 )
{
vNewVerts[k++] = v2;
}
}
v1 = v2;
d1 = d2;
}
if ( b )
{
return;
}
*pdwNumVerts = k;
for ( u8 j = 0; j < k; ++j )
{
pVerts[j] = vNewVerts[j];
}
}
inline void BoundingBox_Append( BoundingBox3 *pBB, const Point *pvPoint )
{
pBB->m_vMin.x = min( pBB->m_vMin.x, pvPoint->x );
pBB->m_vMin.y = min( pBB->m_vMin.y, pvPoint->y );
pBB->m_vMin.z = min( pBB->m_vMin.z, pvPoint->z );
pBB->m_vMax.x = max( pBB->m_vMax.x, pvPoint->x );
pBB->m_vMax.y = max( pBB->m_vMax.y, pvPoint->y );
pBB->m_vMax.z = max( pBB->m_vMax.z, pvPoint->z );
}
void BoundingBox_ClipAndAppendTri( BoundingBox3 *pBB3, Point *pVerts, u8 *phwNumVerts, const BoundingBox3 *pClipBox )
{
for ( u8 axis = 0; axis < 3; ++axis )
{
Clip3D_plane( pVerts, 1, axis, phwNumVerts, &pClipBox->m_vMin );
Clip3D_plane( pVerts, -1, axis, phwNumVerts, &pClipBox->m_vMax );
}
for ( u8 vert = 0; vert < *phwNumVerts; ++vert )
{
BoundingBox_Append( pBB3, &pVerts[vert] );
}
}
希望这些翻译对您有所帮助。如果您有任何其他问题或需要进一步的翻译,请随时提问。
英文:
I have looked and looked and cannot find any resources on. I want to clip an axis aligned bounding box against a triangle in a way that creates a new tight fitting axis aligned bounding box around or in the triangle (I have seen the reverse a lot, a triangle clipped against an axis alinged bounding, but never seen the reverse case). I tried computing the clipped tiangle then building a bounding box from it. But it is grossly inefficent and I don't think my code is correct. Does anyone know how to clip a bounding box against a triangle efficently?
Here is pictures describing what I currently do
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef float f32;
typedef double f64;
struct Point
{
union
{
f32 a[3];
struct
{
f32 x;
f32 y;
f32 z;
};
};
};
struct BoundingBox3
{
Point m_vMin = {FLT_MAX,FLT_MAX,FLT_MAX};
Point m_vMax = {-FLT_MAX,-FLT_MAX,-FLT_MAX};
};
inline
s8 Classify( s8 sign, u8 axis, const Point *c_v, const Point *p_v )
{
const f64 d = sign * ( p_v->a[axis] - c_v->a[axis] );
if ( d > EPSILON )
{
return 1;
}
else if ( d < -EPSILON )
{
return -1;
}
return 0;
}
#define POINT_BUFFER_SIZE 9
inline
void Clip3D_plane( Point *pVerts, s8 sign, u8 axis, u8 *pdwNumVerts, const Point *pPointOnPlane )
{
u8 dwNumVerts = ( *pdwNumVerts );
if ( dwNumVerts == 0 )
{
return;
}
else if ( dwNumVerts == 1 )
{
*pdwNumVerts = 0;
return;
}
Point vNewVerts[POINT_BUFFER_SIZE];
u8 k = 0;
bool b = true; // polygon is fully located on clipping plane
Point v1 = pVerts[dwNumVerts - 1];
s8 d1 = Classify( sign, axis, pPointOnPlane, &v1 );
for ( u8 j = 0; j < dwNumVerts; ++j )
{
const Point &v2 = pVerts[j];
s8 d2 = Classify( sign, axis, pPointOnPlane, &v2 );
if ( d2 != 0 )
{
b = false;
if ( ( 0x80 & ( d2 ^ d1 ) ) != 0 ) //if signs differ
{
const f32 fAlpha = ( v2.a[axis] - pPointOnPlane->a[axis] ) / ( v2.a[axis] - v1.a[axis] );
Point_Lerp( &v2, &v1, fAlpha, &vNewVerts[k++] );
}
else if ( d1 == 0 && ( k == 0 || !Point_Equals( &vNewVerts[k - 1], &v1 ) ) )
{
vNewVerts[k++] = v1;
}
if ( d2 > 0 )
{
vNewVerts[k++] = v2;
}
}
else
{
if ( d1 != 0 )
{
vNewVerts[k++] = v2;
}
}
v1 = v2;
d1 = d2;
}
if ( b )
{
return;
}
*pdwNumVerts = k;
for ( u8 j = 0; j < k; ++j )
{
pVerts[j] = vNewVerts[j];
}
}
inline void BoundingBox_Append( BoundingBox3 *pBB, const Point *pvPoint )
{
pBB->m_vMin.x = min( pBB->m_vMin.x, pvPoint->x );
pBB->m_vMin.y = min( pBB->m_vMin.y, pvPoint->y );
pBB->m_vMin.z = min( pBB->m_vMin.z, pvPoint->z );
pBB->m_vMax.x = max( pBB->m_vMax.x, pvPoint->x );
pBB->m_vMax.y = max( pBB->m_vMax.y, pvPoint->y );
pBB->m_vMax.z = max( pBB->m_vMax.z, pvPoint->z );
}
void BoundingBox_ClipAndAppendTri( BoundingBox3 *pBB3, Point *pVerts, u8 *phwNumVerts, const BoundingBox3 *pClipBox )
{
for ( u8 axis = 0; axis < 3; ++axis )
{
Clip3D_plane( pVerts, 1, axis, phwNumVerts, &pClipBox->m_vMin );
Clip3D_plane( pVerts, -1, axis, phwNumVerts, &pClipBox->m_vMax );
}
for ( u8 vert = 0; vert < *phwNumVerts; ++vert )
{
BoundingBox_Append( pBB3, &pVerts[vert] );
}
}
答案1
得分: 2
你通常不能避免计算三角形的边与矩形的边之间的交点。要获得正确的结果,您需要计算这两种形状的交点,例如使用Sutherland-Hodgman算法,您可以专门针对三角形和矩形的情况进行优化。如果我没记错,在最坏的情况下,您会得到一个七边形。
然后获得AABB并不困难。
或者,您可以实现一种线段剪切算法,针对多边形(三角形或矩形)窗口。对于AA窗口的专用算法是Cohen-Sutherland算法。然后将所有三角形边剪切为矩形,将所有矩形边剪切为三角形。
英文:
In general you can't escape computing intersection points between the sides of the triangle and those of the box. To get a correct result, you need to compute the intersection of the two shapes, for instance using the Sutherland-Hodgman algorithm, that you can specialize for the case of a triangle and a rectangle. If I am right, in the worst case you get an heptagon.
Then getting the AABB is no big deal.
Alternatively, you can implement a line-segment clipping algorithm against a poygonal (triangular or rectangular) window. A specialization to an AA window is the Cohen-Sutherland algorithm. Then clip all triangle sides against the rectangle and all rectangle sides against the triangle.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论