Minenat69

CheckCollisionWithHeightmap

Aug 10th, 2025
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.38 KB | None | 0 0
  1. bool BoxCollider::CheckCollisionWithHeightmap(HeightmapCollider* _pHeightmapCollider, CollisionPoint& _oCollisionResult)
  2. {
  3. // Find where box center is located on heightmap texture
  4. glm::mat4 matModel = _pHeightmapCollider->GetHeightmapModelMatrix();
  5. glm::mat4 matModelInverse = glm::inverse(matModel);
  6. glm::vec3 vLocalHeightmapPosition = matModelInverse * glm::vec4(m_vPosition, 1.f); //[-0.5, 0.5]
  7. vLocalHeightmapPosition += glm::vec3(0.5f, 0.f, 0.5f); // [0, 1]
  8.  
  9. uint32_t nEdgeCellsCount = _pHeightmapCollider->GetEdgeCellsCount();
  10. int iCellIDX = (int)std::floor(vLocalHeightmapPosition.x / (1.f / nEdgeCellsCount));
  11. int iCellIDY = (int)std::floor(vLocalHeightmapPosition.z / (1.f / nEdgeCellsCount));
  12.  
  13. // Skip heightmap boundaries
  14. if (iCellIDX < 0 || iCellIDX > (int)nEdgeCellsCount || iCellIDY < 0 || iCellIDY > (int)nEdgeCellsCount)
  15. return false;
  16.  
  17. // Load heightmap image
  18. int iWidth, iHeight, iBytesPerPixel;
  19. stbi_uc* pData = stbi_load(_pHeightmapCollider->GetImagePath().c_str(),
  20. &iWidth, &iHeight, &iBytesPerPixel, 4);
  21.  
  22. // Coordinates in texture of closest (min) triangle vertex coordinates
  23. int iHeightmapCoordsX0 = (iWidth / nEdgeCellsCount) * iCellIDX;
  24. int iHeightmapCoordsY0 = (iHeight / nEdgeCellsCount) * iCellIDY;
  25. int iHeightmapCoordsX1 = (iWidth / nEdgeCellsCount) * (iCellIDX + 1);
  26. int iHeightmapCoordsY1 = (iHeight / nEdgeCellsCount) * (iCellIDY + 1);
  27.  
  28. // Coordinates of closed X/Y in local space
  29. float fLocalCellX0 = (float)iCellIDX / (float)nEdgeCellsCount;
  30. float fLocalCellX1 = (float)(iCellIDX + 1) / (float)nEdgeCellsCount;
  31. float fLocalCellY0 = (float)iCellIDY / (float)nEdgeCellsCount;
  32. float fLocalCellY1 = (float)(iCellIDY + 1) / (float)nEdgeCellsCount;
  33.  
  34. // Get height between where player is located
  35. // NOT RIGHT VALUES => HOW SAMPLED IS MADE USING STBI ?
  36. float fH00 = (float)*(pData + (iBytesPerPixel * (iHeightmapCoordsY0 * iWidth + iHeightmapCoordsX0))) / 256.f;
  37. float fT0 = pData[0];
  38. float fT1 = pData[1];
  39. float fT2 = pData[2];
  40. float fT3 = pData[3];
  41. float fT4 = pData[4];
  42. float fT5 = pData[5];
  43. float fT6 = pData[6];
  44. float fT7 = pData[7];
  45.  
  46.  
  47. float fH01 = (float)*(pData + (iBytesPerPixel * (iHeightmapCoordsY0 * iWidth + iHeightmapCoordsX1))) / 256.f;
  48. float fH10 = (float)*(pData + (iBytesPerPixel * (iHeightmapCoordsY1 * iWidth + iHeightmapCoordsX0))) / 256.f;
  49. float fH11 = (float)*(pData + (iBytesPerPixel * (iHeightmapCoordsY1 * iWidth + iHeightmapCoordsX1))) / 256.f;
  50.  
  51. // Get triangles in local space
  52. CLTriangle3D oTriangleDown({
  53. glm::vec3(fLocalCellX1, fH11, fLocalCellY1),
  54. glm::vec3(fLocalCellX0, fH01, fLocalCellY1),
  55. glm::vec3(fLocalCellX1, fH10, fLocalCellY0)
  56. });
  57. CLTriangle3D oTriangleUp({
  58. glm::vec3(fLocalCellX0, fH00, fLocalCellY0),
  59. glm::vec3(fLocalCellX1, fH10, fLocalCellY0),
  60. glm::vec3(fLocalCellX0, fH01, fLocalCellY1)
  61. });
  62.  
  63. // Find weights w1 (presence of UV in vect UV0 UV1) and w2 (vect UV0 UV2)
  64. float fW1Num = oTriangleUp[0].x * (oTriangleUp[2].z - oTriangleUp[0].z) + (vLocalHeightmapPosition.x - oTriangleUp[0].z) * (oTriangleUp[2].x - oTriangleUp[0].x) - vLocalHeightmapPosition.z * (oTriangleUp[2].z - oTriangleUp[0].z);
  65. float fW1Den = (oTriangleUp[1].z - oTriangleUp[0].z) * (oTriangleUp[2].x - oTriangleUp[0].x) - (oTriangleUp[1].x - oTriangleUp[0].x) * (oTriangleUp[2].z - oTriangleUp[0].z);
  66. float fW1 = fW1Num / fW1Den;
  67. float fW2 = (vLocalHeightmapPosition.x - oTriangleUp[0].z - fW1 * (oTriangleUp[1].z - oTriangleUp[0].z)) / (oTriangleUp[2].z - oTriangleUp[0].z);
  68. // Interpolate heights using weights to get actual height at position UV
  69. float fHeightFinal = oTriangleUp[0].y + fW1 * (oTriangleUp[1].y - fH00) + fW2 * (oTriangleUp[2].y - oTriangleUp[0].y);
  70.  
  71. // Test collision with bounding box
  72. bool bCollisionFound = false;
  73.  
  74. float fPenetration = 0.0f;
  75.  
  76. glm::vec3 vProjectedPositionTriangleWorldSpace = glm::vec4(vLocalHeightmapPosition.x - 0.5f, oTriangleUp[0].y, vLocalHeightmapPosition.z - 0.5f, 1.f) * matModel;
  77. // Test whether local position is up of down a triangle
  78. // TODONathan : Mismatch : check how fHs is computed
  79. if (fHeightFinal > vLocalHeightmapPosition.y)
  80. bCollisionFound = true;
  81.  
  82. stbi_image_free(pData);
  83. return bCollisionFound;
  84. }
  85.  
Advertisement
Add Comment
Please, Sign In to add comment