【问题标题】:Picking with a physics library (OPENGL & BULLET 3D使用物理库进行选择(OPENGL 和 BULLET 3D
【发布时间】:2020-10-14 02:12:04
【问题描述】:

我正在尝试使用子弹物理来绘制射线以击中场景中的游戏对象以便我可以选择它,我正在使用相机矩阵绘制射线然后在空间中选择一个对象然后查看游戏对象列表并查找相同的位置。

在鼠标按下时,我有以下代码,它似乎已关闭,并且只选择了一些项目:

    glm::vec4 lRayStart_NDC(
    ((float)lastX / (float)RECT_WIDTH - 0.5f) * 2.0f, 
    ((float)lastY / (float)RECT_HEIGHT - 0.5f) * 2.0f,
    -1.0,
    1.0f
);

glm::vec4 lRayEnd_NDC(
    ((float)lastX / (float)RECT_WIDTH - 0.5f) * 2.0f,
    ((float)lastY / (float)RECT_HEIGHT - 0.5f) * 2.0f,
    0.0,
    1.0f
);


projection = glm::perspective(glm::radians(SceneManagement::getInstance()->MainCamera->GetVOW()), (float)RECT_WIDTH / (float)RECT_HEIGHT, 0.1f, 100.0f);
glm::mat4 InverseProjectionMatrix = glm::inverse(projection);

view = SceneManagement::getInstance()->MainCamera->GetViewMatrix();
glm::mat4 InverseViewMatrix = glm::inverse(view);

glm::vec4 lRayStart_camera = InverseProjectionMatrix * lRayStart_NDC;    
lRayStart_camera /= lRayStart_camera.w;
glm::vec4 lRayStart_world = InverseViewMatrix * lRayStart_camera; 
lRayStart_world /= lRayStart_world.w;
glm::vec4 lRayEnd_camera = InverseProjectionMatrix * lRayEnd_NDC;      
lRayEnd_camera /= lRayEnd_camera.w;
glm::vec4 lRayEnd_world = InverseViewMatrix * lRayEnd_camera;   
lRayEnd_world /= lRayEnd_world.w;

glm::vec3 lRayDir_world(lRayEnd_world - lRayStart_world);
lRayDir_world = glm::normalize(lRayDir_world);

glm::vec3 out_end = SceneManagement::getInstance()->MainCamera->GetCamPosition() + SceneManagement::getInstance()->MainCamera->GetCamFront() * 1000.0f;

btCollisionWorld::ClosestRayResultCallback RayCallback(
    btVector3(SceneManagement::getInstance()->MainCamera->GetCamPosition().x, SceneManagement::getInstance()->MainCamera->GetCamPosition().y, SceneManagement::getInstance()->MainCamera->GetCamPosition().z),
    btVector3(out_end.x, out_end.y, out_end.z)
);

PhysicsManager::getInstance()->dynamicsWorld->rayTest(
    btVector3(SceneManagement::getInstance()->MainCamera->GetCamPosition().x, SceneManagement::getInstance()->MainCamera->GetCamPosition().y, SceneManagement::getInstance()->MainCamera->GetCamPosition().z),
    btVector3(out_end.x, out_end.y, out_end.z),
    RayCallback
);

if (RayCallback.hasHit()) 
{
    btTransform position = RayCallback.m_collisionObject->getInterpolationWorldTransform();
    printf("Collision \n");
    for (int i = 0; i < SceneManagement::getInstance()->gObjects.size(); i++)
    {
        if (SceneManagement::getInstance()->gObjects.at(i)->transform.Position.x == position.getOrigin().getX() &&
            SceneManagement::getInstance()->gObjects.at(i)->transform.Position.y == position.getOrigin().getY() &&
            SceneManagement::getInstance()->gObjects.at(i)->transform.Position.z == position.getOrigin().getZ())
        {
            int select = i;
            SceneManagement::getInstance()->SelectedGameObject = SceneManagement::getInstance()->gObjects.at(select);
            SceneManagement::getInstance()->SelectedGameObject->DisplayInspectorUI();
            return;
        }
    }
}

【问题讨论】:

  • 问题是什么?
  • 使用上面的代码,我得到奇怪的结果是碰撞器似乎关闭了,当我尝试点击场景中的一个项目时,它按预期工作,一切似乎都关闭了,但是我不知道为什么

标签: c++ glm-math


【解决方案1】:

这张支票

SceneManagement::getInstance()->gObjects.at(i)->transform.Position.x == position.getOrigin().getX() &&
SceneManagement::getInstance()->gObjects.at(i)->transform.Position.y == position.getOrigin().getY() &&
SceneManagement::getInstance()->gObjects.at(i)->transform.Position.z == position.getOrigin().getZ()

由于数值精度问题而失败。

您应该检查向量的“相等性”,直到达到一定精度。

请使用一些距离函数和以下检查,而不是你的 if() 条件:

 const double EPSILON = 1e-4; // experiment with this value
 auto objPos = SceneManagement::getInstance()->gObjects.at(i)->transform.Position;
 bool isWithinRange = distance3D(objPos, position.getOrigin()) < EPSILON;
 if (isWithinRange)
 {
      int select = i;
      ...
 }

distance3D 函数只是 3D 中的欧几里得距离。 glm::distance 函数应该可以,只需将两个向量都转换为 glm::vec3 格式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多