我发现错误的结果是由于浮点数精度造成的吗?

问题描述 投票:0回答:1

我正在尝试实现一个 GJK 算法,该算法应该返回两个凸形状之间的距离,将来我计划使用它来进行连续碰撞检测。在计算中,我使用浮点数来加快计算时间并使用更少的内存。我知道浮点数不是很精确,例如我经常得到 1...10-6 而不是 0,这并不太令人惊讶。然而,GJK 作为完成条件,类似于 [value <= error] and if i choose a value error below 0.01 GJK never ends. Mathematicly i am supposed to get 0 so this would mean that i have accumulated float errors up to 0.01 is this possible? It's true that the calculation i do are pretty big, i do matrix inversions and multiplications and than i calculate determinants and divide them. In the code bellow i show the two functions that do most of the calculations. If this is a precison problem how could i fix this? Although i don't really need more than 0.1 in precision i still think that this is a bit odd. I will also add that this algorithm prints values that seem correct and detects collision correctly so this mainly why i think it is a precision problem even though i have my doubts.

//this code calls the calculations, as you can see there are some Matrix calculations here.
void ConvexShape::getDistance(const Matrix4x4& t1, const ConvexShape& shape, const Matrix4x4& t2)
        {
          Matrix4x4 rt1 = t1;
          rt1.get(0,3) = 0.0;
          rt1.get(1,3) = 0.0;
          rt1.get(2,3) = 0.0;

          Matrix4x4 rt2 = t2;
          rt2.get(0,3) = 0.0;
          rt2.get(1,3) = 0.0;
          rt2.get(2,3) = 0.0;

          Matrix4x4 invRT1 = rt1.invert();
          Matrix4x4 invRT2 = rt2.invert();

          Vector3 v = t1*support(invRT1*Vector3(1,0,0)) - t2*shape.support(invRT2*Vector3(-1,0,0));
          Simplex simplex;
          SupportVertex w(t1*support(invRT1*(-v)), t2*shape.support(invRT2*(v)));
          while(v.dot(v) - v.dot(w.getMdPosition()) > 0.01)
          {
            simplex.addPoint(w);
            v = simplex.getNearZero().getMdPosition();
            w = SupportVertex(t1*support(invRT1*(-v)), t2*shape.support(invRT2*(v)));
          }
          std::cout << "DISTANCE = " << v.getLength() << std::endl;
        }
//this a piece of code that calculated the barycentric coordonated of a thetrahedron it is often used.
void Simplex::getBarycentricCoordonates(const Vector3& OA, const Vector3& OB, const Vector3& OC, const Vector3& OD, float* u, float* v, float* w, float* k)
        {
          Vector3 AB = OB - OA;
          Vector3 AC = OC - OA;
          Vector3 AD = OD - OA;
          Vector3 AO = -OA;

          float ABAB = AB.dot(AB);
          float ACAC = AC.dot(AC);
          float ADAD = AD.dot(AD);

          float ABAC = AB.dot(AC);
          float ABAD = AB.dot(AD);

          float ACAD = AC.dot(AD);

          float AOAB = AO.dot(AB);
          float AOAC = AO.dot(AC);
          float AOAD = AO.dot(AD);

          float detA  = - ABAB*(ACAC*ADAD - ACAD*ACAD)
                        + ABAC*(ABAC*ADAD - ACAD*ABAD)
                        - ABAD*(ABAC*ACAD - ACAC*ABAD);

          float detAv = - AOAB*(ACAC*ADAD - ACAD*ACAD)
                        + AOAC*(ABAC*ADAD - ACAD*ABAD)
                        - AOAD*(ABAC*ACAD - ACAC*ABAD);

          float detAw = - ABAB*(AOAC*ADAD - AOAD*ACAD)
                        + ABAC*(AOAB*ADAD - AOAD*ABAD)
                        - ABAD*(AOAB*ACAD - AOAC*ABAD);

          float detAk = - ABAB*(ACAC*AOAD - ACAD*AOAC)
                        + ABAC*(ABAC*AOAD - ACAD*AOAB)
                        - ABAD*(ABAC*AOAC - ACAC*AOAB);

          float denom = 1.0/detA;

          *v = detAv*denom;
          *w = detAw*denom;
          *k = detAk*denom;
          *u = 1.0 - *v - *w - *k;
        }
c++ precision
1个回答
0
投票
Vector3 v = t1*support(invRT1*Vector3(1,0,0)) -t2*shape.support(invRT2*Vector3(-1,0,0)); 
Simplex simplex;
SupportVertex w(t1*support(invRT1*(-v)), t2*shape.support(invRT2*(v))); 
while(v.dot(v) - v.dot(w.getMdPosition()) > 0.01) ```

这对我来说看起来不太正确,假设我正确地阅读

w.getMdPosition()
作为“获得 shapeA 和 shapeB 方向 -v 和 v 的支持函数结果的中间位置”。考虑 shapeA = shapeB = unit_circle_at_origin 的情况:无论您选择哪个方向 (v),v.dot(v) = 4,并且 midPosition 为 0,所以您当然会得到无限循环。

即使我错误地解释了你的函数名称,循环上方仍然存在另一个错误:你永远不会将

v
添加到单纯形中。

© www.soinside.com 2019 - 2024. All rights reserved.