raycasting – How can I offset a raycast a certain distance from the camera no matter which way it is facing?

I am raycasting from the camera, which allows me to get the object that the player is looking at within a certain range.

The issue I have is that the camera can be zoomed out away from the player, so the raycast can come up short and I need the raycast to be a very specific length.

So I thought that if I get the distance from the camera to the player, I can then offset the starting position of the raycast, and this would also prevent objects getting returned between the camera and the player.

  • Line A is what I am doing right now.
  • Line B is what I get when trying to offset the raycast.
  • Line C is what I want to achieve with the raycast.

Here is my current code I use for raycasting from the camera without trying to offset it. I tried adding the dist to the start but I think I need something else but not sure.

dist = camera_position - player_position
start = camera_position
forward = camera_rotation * Vector3.Forward
end = start + forward * 500

javascript – Need help with fixing Optimized Raycasting / Line of Sight algorithm

I’m trying to implement collision detection with raycasting for my 2D javascript game. The game uses equally-sized tiles as its level structure so to optimize collision detecton I’m trying to use a LOS algorithm very similar to the one at the bottom of this this article.

However, I’ve noticed that at certain angles, tiles that should be detected are not. I’m also noticing an overall “L” shape pattern where tiles that are beyond the ray’s endpoint are being detected when they don’t need to be. I don’t think these are intended behaviors of the algorithm but I can’t quite figure out what I could be doing wrong.

I’ve assembled a small jsfiddle here that includes the most relevant code and an additional visualization. You can click anywhere on the canvas to set a new ray origin.

Would appreciate any help. Thanks.

c# – Having issues with 3rd-person Camera Raycasting / LocalWorld Space / Clipping

I would like my camera to inherit the player in the hierarchy, and get closer when there is a wall or floor between the player and the camera.

Right now I am trying to raycast from the player to the desired position, and set the camera as close as possible to that desired position. But my camera is flicking all over the place.

Both of these scripts are attached to the player’s camera, which inherits from the player.

.. RotateCamera adjusts x rotation of the camera with mouse movement, and sends the desired y-position to the FollowCamera script (y-position should shift to keep player in view). The way this is working is a little hacky, but I’d really like to first focus on the raycast situation before improving this code.

using UnityEngine;

public class RotateCamera : MonoBehaviour
{
    (SerializeField) private float rotSpeed, downAngleLimit;
    (Header("Up angle limit should be negative number"))
    (SerializeField) private float upAngleLimit;
    (SerializeField) private FollowCamera followCamera;
    
    private Vector3 oglocpos;
    private Transform tx;
    
    void Start()
    {
        tx = transform;
        oglocpos = tx.localPosition;
        upAngleLimit += 360;
    }

    void Update()
    {
        GetInput();
    }

    private void LateUpdate()
    {
        ClampAngle();
    }

    void GetInput()
    {
        float mouseY = Input.GetAxis("Mouse Y");
        Rotate(mouseY);
    }

    void Rotate(float degrees)
    {  
        // Just takes care of up/down rotation
        tx.Rotate(Vector3.left * (degrees * rotSpeed * Time.deltaTime));
        ShiftCamera(tx.localEulerAngles.x);
    }

    void ShiftCamera(float degrees)
    {
        // Determines desired y-position by linear equation with current x-angle as variable
        var pos = oglocpos;
        
        if (degrees < upAngleLimit)
        {
            pos.y = .05f * degrees; // f(x) = .05x
        }
        else if (degrees > upAngleLimit)
        {
            pos.y = (.05f * degrees - 18); // f(x) = .05x - 18
        }

        // send this desired position (in local coordinates) to the raycasting script
        followCamera.desiredPosition = pos;
        
    }
    
    void ClampAngle()
    {
        Vector3 eul = Vector3.zero;

        var loceul = tx.localEulerAngles;
        eul.x = loceul.x;
        if (eul.x > upAngleLimit)
        {
            eul.x = Mathf.Clamp(eul.x, upAngleLimit, 360);
        }
        else if (eul.x < downAngleLimit)
        {
            eul.x = Mathf.Clamp(eul.x, 0, downAngleLimit);
        }

        tx.localEulerAngles = eul;
    }
}

.. FollowCamera does the raycasting and actual camera adjustment. I’m sure the issue is in this second script, but I don’t know how else to approach it.

using UnityEngine;

public class FollowCamera : MonoBehaviour
{
    public Vector3 desiredPosition;
    (SerializeField) private Transform ptx; // player transform
    (SerializeField) private LayerMask layerMask;

    void Update()
    {
        // Send raycast from player to camera's desired position (in world space)
        if (Physics.Raycast(ptx.position, transform.TransformPoint(desiredPosition), out var hit, 6f, layerMask))
        {
            // turn that into a local coordinate and send the camera there
            var lochitpos = transform.InverseTransformPoint(hit.point);
            transform.localPosition = lochitpos;
        }
        else
        {
            transform.localPosition = desiredPosition;
        }
    }
}

raycasting – How to find if a Ray intersects a Triangle Clockwise or Counter Clockwise

Assume the triangle’s vertices are wound in the order A, B, C

Form a normal to the triangle N = (B – A) x (C – A)

Now you can detect whether your triangle is clockwise or counter-clockwise by the sign of the dot product between this normal and the ray direction

In a left-handed coordinate system:

  • Negative = Clockwise from ray’s point of view
  • Positive = Counter-clockwise from ray’s point of view

In a right-handed coordinate system, it’s the opposite:

  • Negative = Counter-clockwise from ray’s point of view
  • Positive = Clockwise from ray’s point of view

raycasting – Pinch Gesture for Function Other than Zooming- Unity

I’m working on a game in which I want to pinch outwards on a character, which causes the character to split into 2 smaller copies of itself.

The method I’m thinking about using is to have the “pinch out” gesture destroy the game object and simultaneously create two instances of the smaller game object, and have them follow the fingers that pinch out. The action would also be reversible with the “pinch in” function.

My idea would be to do a raycast to detect the two-finger touch on the object (would I need a collider for that?), then use the beginning and ending touch points to determine if it is pinching out or in.

The problem is I am brand new to Unity and C# and have no idea how to write all of this. All of the tutorials for multi-touch gestures have to do with camera zoom, which is not what I am going for.

Can anyone tell me if I’m on the right track with my logic and provide some guidance on writing the code?

Voxel raycasting algorithm not working correctly

(Apologies, I’m not familiar with Unity/HLSL at all, so my syntax may be wonky.)

Let’s restart, with

float4  eye;     // Player camera position, .w = 0
float4  proj0;   // Corner of the projection plane, .w = 0
float4  projX;   // Projection plane X axis, .w = 0
float4  projY;   // Projection plane Y axis, .w = 0

so that picture plane pixel uint3 id is at proj0 + id.x*projX + id.y*projY in the voxel coordinates. (We’ll use the w component for the distance, saving a number of operations; that’s why these are four-component vectors.)

The ray starting point position and unit direction vector unitdir are then

float4  position = proj0 + id.x*projX + id.y*projY;
float4  unitdir = normalize(start - eye);

We can save some operations if we set

position.w = 0.0f;
unitdir.w = 1.0f;

here, but that’s the sort of optimization you’ll need to do yourself here.

Next, we need the distances to the very first faces the ray intersects (as measured along the ray itself):

float xstart, ystart, zstart;

if (unitdir.x > 0) {
    xstart = (1.0f + floor(unitdir.x) - unitdir.x) / unitdir.x;
} else
if (unitdir.x < 0) {
    xstart = (floor(unitdir.x) - unitdir.x) / unitdir.x;
} else {
    xstart = +INF;
}

if (unitdir.y > 0) {
    ystart = (1.0f + floor(unitdir.y) - unitdir.y) / unitdir.y;
} else
if (unitdir.y < 0) {
    ystart = (floor(unitdir.y) - unitdir.y) / unitdir.y;
} else {
    ystart = +INF;
}

if (unitdir.y > 0) {
    zstart = (1.0f + floor(unitdir.z) - unitdir.z) / unitdir.z;
} else
if (unitdir.y < 0) {
    zstart = (floor(unitdir.z) - unitdir.z) / unitdir.z;
} else {
    zstart = +INF;
}

The part in parentheses is the distance along the axis, so dividing by the same axis unit vector component we get the length along the ray.

Note that xstart, ystart, and zstart are all positive.

Again, the above can be computed much more efficiently. Now, we initialize the first positions where the ray intersects the first face of each type,

float4  xnext = position + xstart * unitdir;
float4  ynext = position + ystart * unitdir;
float4  znext = position + zstart * unitdir;
xnext.w = xstart;  // This can be omitted, since position.w = 0 and unitdir.w = 1
ynext.w = ystart;  // This can be omitted, since position.w = 0 and unitdir.w = 1
znext.w = zstart;  // This can be omitted, since position.w = 0 and unitdir.w = 1

and when we “use” one of those vectors, we add the corresponding delta,

float4  xdelta = (1.0f / unitdir.x) * unitdir;
float4  ydelta = (1.0f / unitdir.y) * unitdir;
float4  zdelta = (1.0f / unitdir.z) * unitdir;
xdelta.w = 1.0f / unitdir.x;  // This can be omitted, since unitdir.w = 1
ydelta.w = 1.0f / unitdir.y;  // This can be omitted, since unitdir.w = 1
zdelta.w = 1.0f / unitdir.z;  // This can be omitted, since unitdir.w = 1

The actual ray traversal loop is then

int4   cell;  /* Cell integer coordinates */
float4 cellf; /* Fractional cell coordinates */
uint   face;  /* Face, edge, or vertex */

while (1) {
    if (position.w >= maxRayDistance) {
        face = 0;
        break;
    }

    if (xnext.w < ynext.w && xnext.w < znext.w) {
        position = xnext;
        xnext += xdelta;
        face = 1;  // X face
    } else
    if (ynext.w < xnext.w && ynext.w < znext.w) {
        position = ynext;
        ynext += ydelta;
        face = 2;  // Y face
    } else
    if (znext.w < xnext.w && znext.w < ynext.w) {
        position = znext;
        znext += zdelta;
        face = 4;  // Z face
    } else
    if (xnext.w == ynext.w && xnext.w < znext.w) {
        position = xnext;
        xnext += xdelta;
        ynext += ydelta;
        face = 3;  // XY edge
    } else
    if (xnext.w == znext.w && xnext.w < ynext.w) {
        position = xnext;
        xnext += xdelta;
        znext += zdelta;
        face = 5;  // XZ edge
    } else
    if (ynext.w == znext.w && ynext.w < xnext.w) {
        position = ynext;
        ynext += ydelta;
        znext += zdelta;
        face = 6;  // YZ edge
    } else
    if (xnext.w == ynext.w && xnext.w == znext.w) {
        position = xnext;
        xnext += xdelta;
        ynext += ydelta;
        znext += zdelta;
        face = 7;  // XYZ vertex
    } else {
        // .w are all +INF
        face = 0;
        break;
    }

    cellf = modf(position, cell);

    // We intersected with 'face' at cell
    //     cell.x, cell.y, cell.z
    // with fractional coordinates
    //     cellf.x, cellf.y, cellf.z
    // The exact coordinates are
    //     position.x = cell.x + cellf.x
    //     position.y = cell.y + cellf.y
    //     position.z = cell.z + cellf.z
    // but note that cellf can be negative.

    // TODO: Examine the voxel buffer.
    // Note: position.w is the distance from the projection plane
    //       to the face intersection point.  This can be useful
    //       for depth buffers.
}

It is up to you if you use face at all, but all eight cases do need to be handled. (It is unlikely the eighth case ever occurs, but it’s good to be thorough, methinks.)

unity – DDA voxel raycasting algorithm not working correctly

I am using Unity with a compute shader to render to a texture. So far I have been checking points along the rays in units of 1 just for testing, so I know it works. Now I am simply trying to write a function that increments the ray to stop at the next voxel face, basically. And I think I understand the algorithm but my implementation is not working correctly.

This is the function I am using in a loop to find how much I should increment the ray by for each increment.

float getRayIncrement(float3 dir, float3 position) {

    float3 d;
    d.x = 0;
    d.y = 0;
    d.z = 0;
    if (dir.x > 0) {
        d.x = (ceil(position.x) - position.x) / dir.x;
    }
    else if (dir.x < 0) {
        d.x = (position.x - floor(position.x)) / dir.x;
    }
    if (dir.y > 0) {
        d.y = (ceil(position.y) - position.y) / dir.y;
    }
    else if (dir.y < 0) {
        d.y = (position.y - floor(position.y)) / dir.y;
    }
    if (dir.z > 0) {
        d.z = (ceil(position.z) - position.z) / dir.z;
    }
    else if (dir.z < 0) {
        d.z = (position.z - floor(position.z)) / dir.z;
    }

    float smallestDistance = 1000;

    if (d.x > 0 && d.x < smallestDistance) {
        smallestDistance = d.x;
    }
    if (d.y > 0 && d.y < smallestDistance) {
        smallestDistance = d.y;
    }
    if (d.z > 0 && d.z < smallestDistance) {
        smallestDistance = d.z;
    }

    return smallestDistance;
}

Then I multiply the normalized direction vector of the ray by the smallestDistance to march the ray like:

        pointHolder += direction * smallestDistance;

But I get very strange results, some cube faces don’t render in, some render as speckles of pixels. Here is the full compute shader:

#pragma kernel CSMain

RWTexture2D<float4> Result; // the actual array of pixels the player sees
float width; // in pixels
float height;

StructuredBuffer<int> voxelMaterials; // for now just getting a flat voxel array
int voxelBufferRowSize;
StructuredBuffer<float3> rayDirections; // A better name would be "projectedPixelScreenPositions"
float maxRayDistance;

float3 playerCameraPosition;
float3 playerWorldForward;
float3 playerWorldRight;
float3 playerWorldUp;


float3 transformDirectionFromPoint(float3 p) {

    float3 u1 = p.x * playerWorldRight;
    float3 u2 = p.y * playerWorldUp;
    float3 u3 = p.z * playerWorldForward;

    return u1 + u2 + u3; // the direction to that point
}

float getRayIncrement(float3 dir, float3 position) {

    float3 d;
    d.x = 0;
    d.y = 0;
    d.z = 0;
    if (dir.x > 0) {
        d.x = (ceil(position.x) - position.x) / dir.x;
    }
    else if (dir.x < 0) {
        d.x = (position.x - floor(position.x)) / dir.x;
    }
    if (dir.y > 0) {
        d.y = (ceil(position.y) - position.y) / dir.y;
    }
    else if (dir.y < 0) {
        d.y = (position.y - floor(position.y)) / dir.y;
    }
    if (dir.z > 0) {
        d.z = (ceil(position.z) - position.z) / dir.z;
    }
    else if (dir.z < 0) {
        d.z = (position.z - floor(position.z)) / dir.z;
    }

    float smallestDistance = 1000;
    if (d.x > 0 && d.x < smallestDistance) {
        smallestDistance = d.x;
    }
    if (d.y > 0 && d.y < smallestDistance) {
        smallestDistance = d.y;
    }
    if (d.z > 0 && d.z < smallestDistance) {
        smallestDistance = d.z;
    }

    return smallestDistance;
}





(numthreads(32, 32, 1))
void CSMain(uint3 id : SV_DispatchThreadID)
{
    float3 pointHolder = playerCameraPosition;
    float3 direction = transformDirectionFromPoint( rayDirections(id.x + (id.y * width)) );
    Result(id.xy) = float4(0, 0, 0, 0.0);

    for (int i = 0; i < maxRayDistance; i++) {

        //pointHolder += direction;

        float increment = getRayIncrement(direction, pointHolder);
        pointHolder += direction * increment;

        //check if point is within bounds of the buffer
        if (pointHolder.x < voxelBufferRowSize && pointHolder.x >= 0
            && pointHolder.y < voxelBufferRowSize && pointHolder.y >= 0
            && pointHolder.z < voxelBufferRowSize && pointHolder.z >= 0) 
        {
            // convert the point into a voxel index and check if a voxel exists there

            bool outOfRange = false; // a secondary check for when the direction is negative and we need to check the voxel next to the hit point
            int voxelIndexX;
            if (direction.x >= 0) {
                voxelIndexX = floor(pointHolder.x);
            }
            else {
                voxelIndexX = floor(pointHolder.x) - 1;
                if (voxelIndexX < 0) {
                    outOfRange = true;
                }
            }

            int voxelIndexY;
            if (direction.y >= 0) {
                voxelIndexY = floor(pointHolder.y) - 1;
                if (voxelIndexY < 0) {
                    outOfRange = true;
                }
            }
            else {
                voxelIndexY = floor(pointHolder.y);
            }

            int voxelIndexZ;
            if (direction.z >= 0) {
                voxelIndexZ = floor(pointHolder.z);
            }
            else {
                voxelIndexZ = floor(pointHolder.z) - 1;
                if (voxelIndexZ < 0) {
                    outOfRange = true;
                }
            }

            if (!outOfRange) {

                //int voxelIndex = floor(pointHolder.x) + (floor(pointHolder.z) * voxelBufferRowSize) + (floor(pointHolder.y) * (voxelBufferRowSize * voxelBufferRowSize));

                int voxelIndex = voxelIndexX + (voxelIndexZ * voxelBufferRowSize) + (voxelIndexY * (voxelBufferRowSize * voxelBufferRowSize));

                if (voxelMaterials(voxelIndex) == 1) {
                    Result(id.xy) = float4(((float)i / maxRayDistance) * 2, (float)voxelIndex / (voxelBufferRowSize * voxelBufferRowSize * voxelBufferRowSize), pointHolder.z, 0.0);
                    break;
                }
            }   


        }


    }
}

raycasting – GLSL compute shader flickering squares/blocks artifact

I’m trying to write a bare minimum GPU raycaster using compute shaders in OpenGL. I’m confident the raycasting itself is functional, as I’ve gotten clean outlines of bounding boxes via a ray-box intersection algorithm.

However, when attempting ray-triangle intersection, I get strange artifacts. My shader is programmed to simply test for a ray-triangle intersection, and color the pixel white if an intersection was found and black otherwise. When the triangle should be visible onscreen, the screen is instead filled with black and white squares/blocks/tiles which flicker randomly like TV static. The squares are at most 8×8 pixels (the size of my compute shader blocks), although there are dots as small as single pixels as well. The white blocks generally lie in the expected area of my triangle, although sometimes they are spread out across the bottom of the screen as well.

Here is a video of the artifact. In my full shader the camera can be rotated around and the shape appears more triangle-like, but the flickering artifact is the key issue and still appears in this video which I generated from the following minimal version of my shader code:

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

uvec2 DIMS = gl_NumWorkGroups.xy*gl_WorkGroupSize.xy;
uvec2 UV = gl_GlobalInvocationID.xy;
vec2 uvf = vec2(UV) / vec2(DIMS);

layout(location = 1, rgba8) uniform writeonly image2D brightnessOut;

struct Triangle
{
    vec3 v0;
    vec3 v1;
    vec3 v2;
};

struct Ray
{
    vec3 origin;
    vec3 direction;
    vec3 inv;
};

// Wikipedia Moller-Trumbore algorithm, GLSL-ified
bool ray_triangle_intersection(vec3 rayOrigin, vec3 rayVector,
    in Triangle inTriangle, out vec3 outIntersectionPoint)
{
    const float EPSILON = 0.0000001;
    vec3 vertex0 = inTriangle.v0;
    vec3 vertex1 = inTriangle.v1;
    vec3 vertex2 = inTriangle.v2;

    vec3 edge1 = {0.0, 0.0, 0.0};
    vec3 edge2 = {0.0, 0.0, 0.0};
    vec3 h = {0.0, 0.0, 0.0};
    vec3 s = {0.0, 0.0, 0.0};
    vec3 q = {0.0, 0.0, 0.0};
    float a = 0.0, f = 0.0, u = 0.0, v = 0.0;
    edge1 = vertex1 - vertex0;
    edge2 = vertex2 - vertex0;
    h = cross(rayVector, edge2);
    a = dot(edge1, h);
    // Test if ray is parallel to this triangle.
    if (a > -EPSILON && a < EPSILON)
    {
        return false;
    }

    f = 1.0/a;
    s = rayOrigin - vertex0;
    u = f * dot(s, h);
    if (u < 0.0 || u > 1.0)
    {
        return false;
    }

    q = cross(s, edge1);
    v = f * dot(rayVector, q);
    if (v < 0.0 || u + v > 1.0)
    {
        return false;
    }

    // At this stage we can compute t to find out where the intersection point is on the line.
    float t = f * dot(edge2, q);
    if (t > EPSILON) // ray intersection
    {
        outIntersectionPoint = rayOrigin + rayVector * t;
        return true;
    }
    return false;
}

void main()
{
    // Generate rays by calculating the distance from the eye
    // point to the screen and combining it with the pixel indices
    // to produce a ray through this invocation's pixel
    const float HFOV = (3.14159265359/180.0)*45.0;
    const float WIDTH_PX = 1280.0;
    const float HEIGHT_PX = 720.0;
    float VIEW_PLANE_D = (WIDTH_PX/2.0)/tan(HFOV/2.0);
    vec2 rayXY = vec2(UV) - vec2(WIDTH_PX/2.0, HEIGHT_PX/2.0);

    // Rays have origin at (0, 0, 20) and generally point towards (0, 0, -1)
    Ray r;
    r.origin = vec3(0.0, 0.0, 20.0);
    r.direction = normalize(vec3(rayXY, -VIEW_PLANE_D));
    r.inv = 1.0 / r.direction;
    
    // Triangle in XY plane at Z=0
    Triangle debugTri;
    debugTri.v0 = vec3(-20.0, 0.0, 0.0);
    debugTri.v1 = vec3(20.0, 0.0, 0.0);
    debugTri.v0 = vec3(0.0, 40.0, 0.0);

    // Test triangle intersection; write 1.0 if hit, else 0.0
    vec3 hitPosDebug = vec3(0.0);
    bool hitDebug = ray_triangle_intersection(r.origin, r.direction, debugTri, hitPosDebug);

    imageStore(brightnessOut, ivec2(UV), vec4(vec3(float(hitDebug)), 1.0));
}

I render the image to a fullscreen triangle using a normal sampler2D and rasterized triangle UVs chosen to map to screen space.

None of this code should be time dependent, and I’ve tried multiple ray-triangle algorithms from various sources including both branching and branch-free versions and all exhibit the same problem which leads me to suspect some sort of memory incoherency behavior I’m not familiar with, a driver issue, or a mistake I’ve made in configuring or dispatching my compute (I dispatch 160x90x1 of my 8x8x1 blocks to cover my 1280×720 framebuffer texture).

I’ve found a few similar issues like this one on SE and the general internet, but they seem to almost exclusively be caused by using uninitialized variables, which I am not doing as far as I can tell. They mention that the pattern continue to move when viewed in the NSight debugger; while RenderDoc doesn’t do that, the contents of the image do vary between draw calls even after the compute shader has finished. E.g. when inspecting the image in the compute draw call there is one pattern of artifacts, but when I scrub to the subsequent draw calls which use my image as input, the pattern in the image has changed.

I also found this post which seems very similar, but that one also seems to be caused by an uninitialized variable, which again I’ve been careful to avoid. I’ve also not been able to alleviate the issue by tweaking the code as they have done.

I’m running the latest NVidia drivers (461.92) on a GTX 1070. I’ve tried inserting glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); (as well as some of the other barrier types) after my compute shader dispatch which I believe is the correct barrier to use if using a sampler2D to draw a texture that was previously modified by an image load/store operation, but it doesn’t seem to change anything.

Odds are that the cause of the problem lies somewhere between my chair and keyboard, but this kind of problem lies outside my usual shader debugging abilities as I’m relatively new to OpenGL. Any ideas would be appreciated! Thanks.

c – Implementation of the DDA algorithm with raycasting

I am making a simple game like Wolfenstein 3d on C using raycasting. To calculate the length of the rays, I use the DDA algorithm. I apply the part of the code that calculates the length of the rays and the size of the wall on the vertical line where the ray hit. How can I optimize and improve my code?


/*
**      Function:           void        calculate()
**
**      Arguments:          main struct and i
**
**      return:             void
**
**      Description:        The raycasting loop is a for loop that goes through every x,
** so there is a calculation for every  vertical stripe of the screen.
*/

void            calculate(t_cub3d *cub)
{
    int i;

    i = 0;
    while (i < cub->window.res_width)
    {
        calculate_cam(cub, &i);
// field_x and field_y represent the current square of the map the ray is in.
        cub->field.field_x = cub->player.x_pos;
        cub->field.field_y = cub->player.y_pos;
        calculate_ray_dir(cub);
        calculate_step(cub);
        calculate_wall(cub);
        calculate_height(cub);
        draw(cub, i);
        i++;
    }
    calculate_sprite(cub);
}


/*
**      Function:           void        calculate_cam()
**
**      Arguments:          main struct, variable counter(width)
**
**      return:             void
**
**      Description:        x_camera is the x-coordinate on the camera plane
** that the current x-coordinate of the screen represents, done this way
** so that the right side of the screen will get coordinate 1, the center
** of the screen gets coordinate 0, and the left side of the screen gets coordinate -1
*/

void            calculate_cam(t_cub3d *cub, int *i)
{
    cub->camera.x_camera = 2 * *i / (double)(cub->window.res_width) - 1;
    cub->ray.dir_ray_x = cub->player.x_dir + cub->camera.x_plane * 
            cub->camera.x_camera;
    cub->ray.dir_ray_y = cub->player.y_dir + cub->camera.y_plane * 
            cub->camera.x_camera;
}


/*
**      Function:           void        calculate_ray_dir()
**
**      Arguments:          main struct
**
**      return:             void
**
**      Description:        x_deltaDist and y_deltaDist are the distance the ray
** has to travel to go from 1 x-side to the next x-side, or from 1 y-side
** to the next y-side.
*/

void            calculate_ray_dir(t_cub3d *cub)
{
    if (cub->ray.dir_ray_y == 0)
        cub->ray.x_deltadist = 0;
    else
    {
        if (cub->ray.dir_ray_x == 0)
            cub->ray.x_deltadist = 1;
        else
            cub->ray.x_deltadist = fabs(1 / cub->ray.dir_ray_x);
    }
    if (cub->ray.dir_ray_x == 0)
        cub->ray.y_deltadist = 0;
    else
    {
        if (cub->ray.dir_ray_y == 0)
            cub->ray.y_deltadist = 1;
        else
            cub->ray.y_deltadist = fabs(1 / cub->ray.dir_ray_y);
    }
}


/*
**      Function:           void        calculate_step()
**
**      Arguments:          main struct
**
**      return:             void
**
**      Description:        x_sideDist and y_sideDist are initially the distance
** the ray has to travel from its start position to the first x-side and
** the first y-side.
*/

void            calculate_step(t_cub3d *cub)
{
    if (cub->ray.dir_ray_x < 0)
    {
        cub->ray.x_ray_step = -1;
        cub->ray.x_sidedist = (cub->player.x_pos - (double)(cub->field.field_x))
                * cub->ray.x_deltadist;
    }
    else
    {
        cub->ray.x_ray_step = 1;
        cub->ray.x_sidedist = (((double)(cub->field.field_x) + 1.0 - 
                cub->player.x_pos) * cub->ray.x_deltadist);
    }
    if (cub->ray.dir_ray_y < 0)
    {
        cub->ray.y_ray_step = -1;
        cub->ray.y_sidedist = (cub->player.y_pos - (double)(cub->field.field_y))
                * cub->ray.y_deltadist;
    }
    else
    {
        cub->ray.y_ray_step = 1;
        cub->ray.y_sidedist = ((double)(cub->field.field_y) + 1.0 - 
                cub->player.y_pos) * cub->ray.y_deltadist;
    }
}


/*
**      Function:           void        calculate_wall()
**
**      Arguments:          main struct
**
**      return:             void
**
**      Description:         DDA algorithm. It's a loop that increments the ray with 1 square
**      every time, until a wall is hit.
*/

void            calculate_wall(t_cub3d *cub)
{
    int     is_wall;

    is_wall = 0;
    cub->window.side = 0;
    while (is_wall == 0)
    {
        if (cub->ray.x_sidedist < cub->ray.y_sidedist)
        {
            cub->ray.x_sidedist += cub->ray.x_deltadist;
            cub->field.field_x += cub->ray.x_ray_step;
            cub->window.side = 0;
        }
        else
        {
            cub->ray.y_sidedist += cub->ray.y_deltadist;
            cub->field.field_y += cub->ray.y_ray_step;
            cub->window.side = 1;
        }
        if (cub->field.map(cub->field.field_y)(cub->field.field_x) == '1')
            is_wall = 1;
    }
    calculate_distto_wall(cub);
}


/*
**      Function:           void        calculate_distto_wall()
**
**      Arguments:          main struct
**
**      return:             void
**
**      Description:        calculate the distance of the ray to the wall
*/

void            calculate_distto_wall(t_cub3d *cub)
{
    if (cub->window.side == 0)
    {
        cub->ray.wall_dist = ((double)(cub->field.field_x) - cub->player.x_pos 
                + (1 - cub->ray.x_ray_step) / 2) / cub->ray.dir_ray_x;
    }
    else
    {
        cub->ray.wall_dist = ((double)(cub->field.field_y) - cub->player.y_pos 
                + (1 - cub->ray.y_ray_step) / 2) / cub->ray.dir_ray_y;
    }
}


/*
**      Function:           void        calculate_height()
**
**      Arguments:          main struct
**
**      return:             void
**
**      Description:        calculate the height of the line that has to be
**      drawn on screen
*/

void            calculate_height(t_cub3d *cub)
{
    cub->window.height_ln = (int)(cub->window.res_height / cub->ray.wall_dist);
    cub->window.top_wall = (cub->window.height_ln * -1) / 2 + 
            cub->window.res_height / 2;
    if (cub->window.top_wall < 0)
        cub->window.top_wall = 0;
    cub->window.bottom_wall = cub->window.height_ln / 2 + 
            cub->window.res_height / 2;
    if (cub->window.bottom_wall >= cub->window.res_height)
        cub->window.bottom_wall = cub->window.res_height - 1;
}