5

समस्या के केंद्र के चारों ओर रोटेशन Polygon::FindAxisLeastPenetration में है:अलग अक्ष प्रमेय: बड़े पैमाने पर

double Polygon::FindAxisLeastPenetration(unsigned int *faceIndex, const Polygon &polygonA, const Polygon &polygonB) const { 
    double bestDistance = -std::numeric_limits<double>::infinity(); 
    unsigned int bestIndex; 

    for (unsigned int i = 0; i < polygonA.points.size(); i++) { 
    Vector2D n = polygonA.normals[i]; 
    Vector2D nw = polygonA.rotationMatrix * n; //ROTATION 
    Matrix22 buT = polygonB.rotationMatrix.Transposed(); 
    n = buT * nw; //ROTATION 

    Vector2D support = polygonB.points[polygonB.GetSupport(-n)]; 

    Vector2D vertex = polygonA.points[i]; 
    vertex = polygonA.rotationMatrix * vertex; //ROTATION 
    vertex.Add(polygonA.body->GetPosition()); 
    vertex.Subtract(polygonB.body->GetPosition()); 
    vertex = buT * vertex; // ROTATION 
    double distance = n.DotProduct(support - vertex); 
    if (distance > bestDistance) { 
     bestDistance = distance; 
     bestIndex = i; 
    } 
    } 
    *faceIndex = bestIndex; 

    return bestDistance; 
} 

unsigned int Polygon::GetSupport(const Vector2D &dir) const { 
    double bestProjection = -std::numeric_limits<double>::infinity(); 
    unsigned int bestIndex = 0; 

    for (unsigned int i = 0; i < points.size(); i++) { 
    Vector2D vertex = points[i]; 
    double projection = vertex.DotProduct(dir); 

    if (projection > bestProjection) { 
     bestProjection = projection; 
     bestIndex = i; 
    } 
    } 

    return bestIndex; 
} 

Manifold Polygon::CheckCollision(const Polygon &polygonA, const Polygon &polygonB) const { 
    Manifold result; 
    result.objectA = polygonA.body; 
    result.objectB = polygonB.body; 
    unsigned int indexA; 
    double penetrationA = Polygon::FindAxisLeastPenetration(&indexA, polygonA, polygonB); 
    if (penetrationA >= 0.0) { 
    result.intersects = false; 
    return result; 
    } 

    unsigned int indexB; 
    double penetrationB = Polygon::FindAxisLeastPenetration(&indexB, polygonB, polygonA); 

    if (penetrationB >= 0.0) { 
    result.intersects = false; 
    return result; 
    } 

    result.intersects = true; 
    //... 
    return result; 

Rectangle::Rectangle(double width, double height) : Polygon() { 
    double hw = width/2.0; 
    double hh = height/2.0; 
    points.push_back(Vector2D(-hw, -hh)); 
    points.push_back(Vector2D(hw, -hh)); 
    points.push_back(Vector2D(hw, hh)); 
    points.push_back(Vector2D(-hw, hh)); 

    // points.push_back(Vector2D(0, 0)); 
    // points.push_back(Vector2D(width, 0)); 
    // points.push_back(Vector2D(width, height)); 
    // points.push_back(Vector2D(0, height)); 

    normals.push_back(Vector2D(0.0, -1.0)); 
    normals.push_back(Vector2D(1.0, 0.0)); 
    normals.push_back(Vector2D(0.0, 1.0)); 
    normals.push_back(Vector2D(-1.0, 0.0)); 

    center.x = 0; 
    center.y = 0; 

}

polygon.rotationMatrix प्रकार Matrix22 की एक वस्तु है जो एक 2x2 मैट्रिक्स है।
polygon.pointsstd::vector<Vector2D> वैक्टर से भरे हुए हैं।
polygon.bodyObject उदाहरण के लिए एक सूचक है। इस मामले में यह केवल स्थिति पाने के लिए प्रयोग किया जाता है।
polygon.body->positionVector2D का उदाहरण है X और Y निर्देशांक।
Vector2D polygon.body->GetPosition() एक शरीर की स्थिति वेक्टर लौटाता है।

यह ठीक काम करता है, सिवाय इसके कि घूर्णन [0, 0] बिंदु के आसपास किया जाता है लेकिन यह द्रव्यमान के केंद्र के चारों ओर घुमाने वाला माना जाता है।

मैं जानता हूँ कि एक बिंदु के आसपास है कि रोटेशन इस तरह किया जा सकता है:

rotationMatrix * (vertex - point) + point 

और यह ठीक काम करता है जब बहुभुज प्रतिपादन। लेकिन टकराव का पता लगाने में नहीं।

मैं इस मामले में एक निश्चित बिंदु के आसपास वैक्टर कैसे घुमा सकता हूं?

संपादित करें: यहाँ क्या मैं अब तक

double Polygon::FindAxisLeastPenetration(unsigned int *faceIndex, const Polygon &polygonA, const Polygon &polygonB) const { 
    double bestDistance = -std::numeric_limits<double>::infinity(); 
    unsigned int bestIndex; 

    for (unsigned int i = 0; i < polygonA.points.size(); i++) { 
    // Calculate normal 
    unsigned int j = i == points.size() ? 0 : i + 1; 
    Vector2D n; 
    // Rotate points 
    Vector2D p1 = polygonA.rotationMatrix * (polygonA.points[i] - polygonA.Center()) + polygonA.Center(); 
    Vector2D p2 = polygonA.rotationMatrix * (polygonA.points[j] - polygonA.Center()) + polygonA.Center(); 
    n.x = p2.y - p1.y; 
    n.y = -(p2.x - p1.x); 
    n.Normalize(); 

    Vector2D support = polygonB.points[polygonB.GetSupport(-n)]; 
    support = polygonB.rotationMatrix * (support - polygonB.Center()) + polygonB.Center(); 
    support.Add(polygonB.body->GetPosition()); 

    Vector2D vertex = polygonA.points[i]; 
    vertex = polygonA.rotationMatrix * (vertex - polygonA.Center()) + polygonA.Center(); //ROTATION 
    vertex.Add(polygonA.body->GetPosition()); 

    double distance = n.DotProduct(support - vertex); 
    if (distance > bestDistance) { 
     bestDistance = distance; 
     bestIndex = i; 
    } 
    } 
    *faceIndex = bestIndex; 

    return bestDistance; 
} 

unsigned int Polygon::GetSupport(const Vector2D &dir) const { 
    double bestProjection = -std::numeric_limits<double>::infinity(); 
    unsigned int bestIndex = 0; 

    for (unsigned int i = 0; i < points.size(); i++) { 
    Vector2D vertex = rotationMatrix * (points[i] - center) + center; 
    double projection = vertex.DotProduct(dir); 

    if (projection > bestProjection) { 
     bestProjection = projection; 
     bestIndex = i; 
    } 
    } 

    return bestIndex; 
} 

अभी मैं वास्तव में अनुकूलन के बारे में परवाह नहीं है है है। एक ही समस्या है। जब केंद्र टकराव के चारों ओर घूमते समय ठीक से पता नहीं लगाया जा रहा है। हालांकि, अगर केंद्र [0, 0] है या इसका उपयोग नहीं किया जाता है, तो टक्कर का पता लगाने ठीक से काम करता है, लेकिन फिर घूर्णन गलत किया जा रहा है।

संपादित करें: टकराव का पता लगाने से पहले घुमाए जाने पर भी, मुझे एक ही समस्या मिलती है। अब तक का सबसे अच्छा दृष्टिकोण बहुभुज का अनुवाद करना था ताकि उसका केंद्र [0, 0] पर होगा, लेकिन कुछ कोणों पर टकराव नहीं पाए जा रहे हैं। पता नहीं अब क्या करना है।

संपादित करें: स्क्रीनशॉट टकराव का पता लगाने में अच्छी तरह से यहाँ Collision detection didn't work well here

टकराव का पता लगाने नहीं किया काम नहीं किया (बहुभुज अनुवाद किया जा रहा है ताकि बड़े पैमाने पर की अपनी केन्द्रों [0, 0] में हमेशा से रहे हैं, बहुभुज इस मामले में आयताकार होते हैं) काम अच्छी तरह से यहाँ भी Collision detection didn't work well here too

टकराव का पता लगाने के लिए यहाँ अच्छी तरह से काम Collision detection worked well here

संपादित करें: मैं Rectangle कक्षा जोड़ा गया।

+0

आप किस लाइब्रेरी का उपयोग कर रहे हैं? – uitty400

+0

@ uitty400 कोई नहीं। सब कुछ कस्टम है। क्या आप कुछ फ़ंक्शन या कक्षा के कार्यान्वयन की तलाश में हैं? – ivknv

+0

आपको यह स्पष्ट करने की आवश्यकता है कि आप क्या कर रहे हैं। यह दो बहुभुजों के चौराहे कोड की तरह नहीं दिखता है। 'अंक 'क्या है और यह कहां से आता है? 'Polygon.GetSupport()' क्या है? 'Polygon.body' और इसकी '.osition' क्या है? –

उत्तर

1

यह काम करना चाहिए कि बहुभुज उत्पत्ति गुरुत्वाकर्षण के केंद्र में गठबंधन है या नहीं। मैं सबसे महत्वपूर्ण चीजों से शुरू करूंगा, और समर्थन विधियों के साथ समाप्त हो जाऊंगा।

संपादित करें: संशोधित कार्यान्वयन।

struct Response { 
     Response() 
      : overlap(std::numeric_limits<double>::max()) {} 
     Vector2D axis; 
     double overlap; 
}; 

bool FindAxisLeastPenetration(const Polygon& a, const Polygon& b, 
     Response* response) 
{ 
     for (unsigned long i = 0; i < a.points.size(); i++) 
     { 
      Vector2D axis = a.normals[i]; 
      Vector2D support = b.GetSupport(-axis); 

      double overlap = axis.DotProduct(a.points[i] - support); 
      if (overlap <= 0.0) 
       return false; 
      if (overlap < response->overlap) 
      { 
       response->overlap = overlap; 
       response->axis = axis; 
      } 
     } 
     return true; 
} 

bool CheckCollisionLocal(const Polygon& a, const Polygon& b, 
     Vector2D* min_translation) 
// @note assumes untransformed polygons. 
{ 
     Polygon worldA = a.ToWorld(); 
     Polygon worldB = b.ToWorld(); 

     Response responseA; 
     Response responseB; 

     if (!FindAxisLeastPenetration(worldA, worldB, &responseA)) 
      return false; 
     if (!FindAxisLeastPenetration(worldB, worldA, &responseB)) 
      return false; 

     if (responseA.overlap <= responseB.overlap) 
      *min_translation = responseA.axis * responseA.overlap; 
     else 
      *min_translation = -responseB.axis * responseB.overlap; 
     return true; 
} 

मामले का प्रयोग करें,

bool HandleCollisionLocal(Polygon& a, Polygon& b) 
{ 
     Vector2D translation; 
     if (!CheckCollisionLocal(a, b, &translation)) 
      return false; 
     if (MOVE_POLYGON_A) 
      a.body.SetPosition(a.body.GetPosition() - translation); 
     else 
      b.body.SetPosition(b.body.GetPosition() + translation); 
     return true; 
} 

सहायता,

Polygon Polygon::ToWorld() const 
{ 
     Polygon result = *this; 
     for (auto& point : result.points) 
     { 
      point = result.rotationMatrix * point; 
      point.Add(result.body.GetPosition()); 
     } 
     for (auto& normal : result.normals) 
      normal = result.rotationMatrix * normal; 
     return result; 
} 

Vector2D Polygon::GetSupport(const Vector2D& direction) const 
{ 
     double best_projection = -std::numeric_limits<double>::max(); 
     Vector2D best_point; 

     for (auto point : points) 
     { 
      double projection = point.DotProduct(direction); 
      if (projection > best_projection) 
      { 
       best_projection = projection; 
       best_point = point; 
      } 
     } 
     return best_point; 
} 

नोट: इस संस्करण में उलट के अनुरूप अनुवाद वेक्टर - मानक - क्या हो रहा है।

संबंधित मुद्दे