我现在被我的RubiksCube项目卡住了。
我想达到的目标:左键点击时检查是否点击了一个小立方体。(点击时立方体可能会旋转)
其他魔方类的代码工作正常。我们需要用数学公式自己计算函数。
当前问题:
- 未检测到单击边缘
- 旋转后,单击某个点有时会导致:标记为点击的图层错误或没有标记为点击的图层
我的总体想法是安全的坐标,每层的4个角点,更新其位置时,旋转和检查交叉点的射线与这些位置的帮助
void MergedCube::Render(float aspectRatio)
{
m_viewProject = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f) *
glm::lookAt(glm::vec3(0.0f, 0.0f, -9.0f),
glm::vec3(0.0f),
glm::vec3(0.0f, 1.0f, 0.0f)) *
glm::mat4_cast(m_orientationQuaternion);
compound = glm::translate(m_viewProject, (glm::vec3(1, 1, 1) - 1.0f));
m_cubieRenderer.Render(compound);
// Calling LayerCalculation() for every Layer with direction -1 or 1
}
这个方法被认为是计算我的辅助向量,2个方向向量和每层的归一化向量
void MergedCube::LayerCalculation(std::vector<glm::vec3>& points, int normDirection) {
while (points.size() > 4) {
points.erase(points.end()-1);
}
glm::vec3 middlePoint = (points[0] + points[2]) / 2.0f;
glm::vec3 firstPoint = (points[0] + points[1]) / 2.0f;
glm::vec3 secondPoint = (points[0] + points[3]) / 2.0f;
glm::vec3 vecA = glm::normalize(firstPoint - middlePoint);
glm::vec3 vecB = glm::normalize(secondPoint - middlePoint);
glm::vec3 normalVector = glm::cross(vecA,vecB) * glm::vec3(direction);
points.push_back(middlePoint);
points.push_back(vecA);
points.push_back(vecB);
points.push_back(normalVector);
}
现在是RayAndCubeIntersection方法。
bool MergedCube::RayAndCubeIntersection(glm::vec3 startingPoint, glm::vec3 direction,
std::vector<glm::vec3> Pts) {
glm::vec3 helperVec = pts[4];
glm::vec3 normVec = pts[7];
glm::vec3 directionVecA = pts[5];
glm::vec3 directionVecB = pts[6];
if (glm::dot(rayDirection, normVec) < 0) {
float res = normVec[0] * helperVec[0] + normVec[1] * helperVec[1] + normVec[2] * helperVec[2];
float directionMultiplikator = (res - normVec[0] * rayStartingPoint[0] - normVec[1] * rayStartingPoint[1] - normVec[2] * rayStartingPoint[2]) /
(normVec[0] * rayDirection[0] + normVec[1] * rayDirection[1] + normVec[2] * rayDirection[2]);
glm::vec3 crosspoint = rayStartingPoint + rayDirection * glm::vec3(directionMultiplikator);
if (glm::dot(crosspoint - helperVec,normVec) == 0) {
float x = glm::dot(directionVecA,crosspoint - helperVec);
float y = glm::dot(directionVecB, crosspoint - helperVec);
if (x > -0.5001 && x < 0.5001) {
if (y > -0.5001 && y < 0.5001) {
return true;
}
}
}
}
return false;
}
编辑:我改变了我的代码相当多,现在点击立方体是在许多情况下被检测到。
1条答案
按热度按时间t3psigkw1#
好了,我想是时候回答我自己的问题了。我的代码的实际问题是检查
glm::dot(crosspoint - helperVec,normVec) == 0
。但是我应该检查glm::abs(glm::dot(crosspoint - helperVec,normVec)) < EPSILON
的EPSILON值非常小。给自己的提示:当使用浮点数时,不要检查0