C++ 优化球体锈蚀检查

C++ 优化球体锈蚀检查,c++,c,algorithm,opengl,C++,C,Algorithm,Opengl,我在这里有一个sphereinfrastrum函数: 0.49% int FrustumG::sphereInFrustum(Vec3 &p, float radius) { int result = INSIDE; float distance; 2.40% for(int i=0; i < 6; i++) { 7.94% distance = pl[i].distance(p); 12.21% if (distan

我在这里有一个sphereinfrastrum函数:

0.49%  int FrustumG::sphereInFrustum(Vec3 &p, float radius) {

        int result = INSIDE;
        float distance;

2.40%   for(int i=0; i < 6; i++) {
7.94%       distance = pl[i].distance(p);
12.21%      if (distance < -radius)
0.67%           return OUTSIDE;
3.67%       else if (distance < radius)
                result =  INTERSECT;
        }
        return(result);

       }

我想留下一条评论来问一个问题,但我似乎只能留下一个答案,这只是一个观察:

这段代码真的做了你想做的吗

        int result = INSIDE;
        float distance;

2.40%   for(int i=0; i < 6; i++) {
7.94%       distance = pl[i].distance(p);
12.21%      if (distance < -radius)
0.67%           return OUTSIDE;
3.67%       else if (distance < radius)
                result =  INTERSECT;
int结果=内部;
浮动距离;
2.40%(int i=0;i<6;i++){
7.94%距离=pl[i]。距离(p);
12.21%如果(距离<-半径)
0.67%的外部收益率;
如果(距离<半径),则为3.67%
结果=相交;
这个函数对我的理解是,假设球体在里面,对于锥台i上的每个点,取i和球体中心p之间的距离,如果这个距离小于负半径……这里我的范例被破坏了

因此,如果负距离小于负半径,这会提前返回?这真的是你想要的吗?

一些想法(按照复杂性增加的顺序)

  • Elimintate分支-计算所有6个距离并基于最小距离返回可能更快(取决于平台和编译器)。例如,在PowerPC上,
    minDist=(d
    可以使用
    fsel
    指令计算,并避免分支

  • 展开(第一部分)展开所有六个平面的循环可能会让编译器有更好的机会优化代码(通过隐藏指令延迟)

  • 展开(第二部分)您可以同时处理多个球体吗?同样,您可以隐藏一些延迟

  • SIMD-如果您不介意用SIMD弄脏您的手,您可以将3个平面的“转置”存储在4个四边形中。这使您可以更轻松地计算点积,而无需执行“水平”SIMD操作。象征性地,这看起来



  • 实际的SIMD代码将取决于平台和编译器

    还有一些方法可以在kd树上执行截头体查询(例如)-我从未尝试过,但它应该可以大大减少需要查询的球体数量


    希望这能有所帮助,如果有什么不清楚的地方,请告诉我。

    您真的在为每个球体执行此代码吗?如果您这样做,怪不得它会变慢


    你应该使用分层方法,它可以在一次调用中剔除整个场景部分。例如,你可以使用球体的四叉树。

    我需要知道的是,它是进还是出,我不在乎它是如何完成的,如果我不得不猜测的话,我会说这些是平面,不是点,距离是标准化的。平面一侧的点平截头体的内侧是正的,而面对平截头体外侧的平面上的点是负的。因此,如果球体的中心距平面为-40,球体的半径为30,那么由于-40<-30,它完全在平截头体之外。@P爸爸:这比我想的更有意义。谢谢e解释。看起来您使用的是此处给出的平截头体推进:。对吗?很难相信一个简单的浮点比较真的占用了您12.21%的执行时间。如果是这样,那么您的距离函数必须非常快(如负时钟周期快)。可能探查器将距离函数的部分执行归因于此处的
    if
    测试。你能发布
    距离
    的代码吗?我想那里会有更多的优化机会。是的,这是正确的,它工作得很好,但当我得到大量对象时,检查会超过测试所有这些方法都是常量!使用常量关键字!确保
    distance
    innerProduct
    都是内联的。
            int result = INSIDE;
            float distance;
    
    2.40%   for(int i=0; i < 6; i++) {
    7.94%       distance = pl[i].distance(p);
    12.21%      if (distance < -radius)
    0.67%           return OUTSIDE;
    3.67%       else if (distance < radius)
                    result =  INTERSECT;
    
    vec4 sphereX = sphere.splat(0);
    vec4 sphereY = sphere.splat(1);
    vec4 sphereZ = sphere.splat(2);
    
    vec4 dot = sphereX * planesX; // planesX is the x components of 3 planes
    dot += sphereY * planesY; 
    dot += sphereZ * planesZ;
    dot += planesDistance;
    // dot now contains the results of 3 distances
    // now do the same for the other 3 planes