0
\$\begingroup\$

I am working on a voxel game right now in OpenGL and working on implementing raycasting so I can pick blocks in my world. So far what I have created works quite well except for when the x or z axis that is created from my rayWOR vector nears 0 or ±1. I have tried to investigate this further by doing ceil when below zero and floor otherwise but still problematic. I attached what I have created - it is modified from this for C++.

I attempted to introduce an epsilon variable for calculating the d and max variables but that did not fix my problem and I noticed no changes. If anyone happens to notice something I am not doing - or shouldn't be doing, it would be greatly appreciated.

glm::vec3 chunkManager::mouseVoxel(Raycast &ray, Camera &camera) {
    using namespace glm;

    float distance = 10.0f;
    float cellSize = 1.0f;

    vec3 rayWOR = ray.getCurrentRay(); //normalized direction vector from ray (at enter of screen)
    vec3 startPoint = camera.getCameraWorldPosition();

    vec3 endPoint = startPoint + (rayWOR * distance);

    vec3 startCell (startPoint.x < 0.0f ? ceil(startPoint.x) : floor(startPoint.x), startPoint.y < 0.0f ? ceil(startPoint.y) : floor(startPoint.y) , startPoint.z < 0.0f ? ceil(startPoint.z) : floor(startPoint.z)); /*floor(startPoint)*/
    vec3 endCell ( (endPoint.x < 0.0f) ? ceil(endPoint.x) : floor(endPoint.x), (endPoint.y < 0.0f) ? ceil(endPoint.y) : floor(endPoint.y) , (endPoint.z < 0.0f) ? ceil(endPoint.z) : floor(endPoint.z)); /*floor(endPoint)*/

    vec3 direction = endPoint - startPoint;
    vec3 norm_direction = normalize(direction);

    // Determine the step direction for raycasting
    int stepX = sign(rayWOR.x);
    int stepY = sign(rayWOR.y);
    int stepZ = sign(rayWOR.z);

    // Determine the step direction for raycasting
    // Distance to nearest square side
    float near_x = (stepX >= 0) ? ((startCell.x + 1) * cellSize - startPoint.x) : (startPoint.x - (startCell.x * cellSize)) ;
    float near_y = (stepY >= 0) ? ((startCell.y + 1) * cellSize - startPoint.y) : (startPoint.y - (startCell.y * cellSize)) ;
    float near_z = (stepZ >= 0) ? ((startCell.z + 1) * cellSize - startPoint.z) : (startPoint.z - (startCell.z * cellSize)) ;

    const float EPSILON = 1e-6f;
    float maxX = (std::abs(norm_direction.x) > EPSILON) ? near_x / norm_direction.x : DBL_MAX;
    float maxY = (std::abs(norm_direction.y) > EPSILON) ? near_y / norm_direction.y : DBL_MAX;
    float masZ = (std::abs(norm_direction.z) > EPSILON) ? near_z / norm_direction.z : DBL_MAX;

    float dx = (std::abs(norm_direction.x) > EPSILON) ? cellSize / norm_direction.x : DBL_MAX;
    float dy = (std::abs(norm_direction.y) > EPSILON) ? cellSize / norm_direction.y : DBL_MAX;
    float dz = (std::abs(norm_direction.z) > EPSILON) ? cellSize / norm_direction.z : DBL_MAX;

    vec3 pos = startPoint; 

    int gridBoundX = std::abs(endCell.x - startCell.x);
    int gridBoundY = std::abs(endCell.y - startCell.y);
    int gridBoundZ = std::abs(endCell.z - startCell.z);

    int counter = 0;

    while(counter != (gridBoundX + gridBoundY + gridBoundZ)) {
      if(std::abs(maxX) < std::abs(maxY)) {
        if(std::abs(maxX) < std::abs(masZ)) {
          maxX += dx;
          pos.x += stepX;
        } else {
          masZ += dz;
          pos.z += stepZ;
        }
      } else {
        if(std::abs(maxY) < std::abs(masZ)) {
          maxY += dy;
          pos.y += stepY;
        } else {
          masZ += dz;
          pos.z += stepZ;
        }
      }
 
      if(pos.y < 0)
        break;

      if(blockExists(pos.x, pos.y, pos.z)) {
        return pos;
      }
      ++counter;
    }

    return vec3(0.0, -1.0, 0.0);
}
\$\endgroup\$
1
  • \$\begingroup\$ please don't chat to the readers ... ask an answerable question instead \$\endgroup\$
    – jsotola
    Commented Aug 30 at 21:53

0

You must log in to answer this question.

Browse other questions tagged .