My first post here. :) I'm currently coding a raytracer for my school project in C. I already can display spheres, triangles and planes with some light effects. Now I want to display cylinder (then cones, but cylinder first !). I choose to have a cylinder parallel to the Y-Axis. So I have to solve : x² + z² = r². So technically, my function that returns the distance between my camera and the intersection point is :
double          n_ray_cylinder(t_ray *ray, t_cylinder *cylinder, t_data *d)
{
    double a;
    double b;
    double c;
    double delta;
    double root;
    a = ray->dir->x * ray->dir->x + ray->dir->z * ray->dir->z;
    b = 2 * ray->dir->x * (ray->ori->x - cylinder->base->x) + 2 * ray->dir->z * (ray->ori->z - cylinder->base->z);
    c = (ray->ori->x - cylinder->base->x) * (ray->ori->x - cylinder->base->x) + (ray->ori->z - cylinder->base->z) * (ray->ori->z - cylinder->base->z) - cylinder->radius * cylinder->radius;
    delta = b * b - 4 * a * c;
    if (delta > ACC)
    {
            root = (-1 * b - sqrt(delta)) / 2 * a - ACC;
            if (root <= ACC)
                    root = (-1 * b + sqrt(delta)) / 2 * a - ACC;
            return (root);
    }
    return (-1);
}
with x = (ray->ori->x - cylinder->base->x) et z = (ray->ori->z - cylinder->base->z) et r = cylinder->radius. 
And my function that calculates the normal vector is:
t_vect          *cylinder_normal_at(t_cylinder *cylinder, t_vect *intersection)
{
    t_vect *base_tmp;
    t_vect *normal;
    t_vect *intersection_tmp;
    base_tmp = copy_vector(cylinder->base);
    intersection_tmp = copy_vector(intersection);
    base_tmp->y = intersection_tmp->y;
    normal = init_vector(intersection->x - base_tmp->x, intersection->y - base_tmp->y, intersection-> z - base_tmp->z);
    normalize_vector(normal);
    return (normal);
}
With these functions, the result is : Image 1
The reflects "seems" good, the shape too, but the light is not good. Normal problem ? I talked about this to a friend of mine, and he told me to do like him : delete some numbers in my first function. So it becomes :
double          n_ray_cylinder(t_ray *ray, t_cylinder *cylinder, t_data *d)
{
    double a;
    double b;
    double c;
    double delta;
    double root;
    a = ray->dir->x * ray->dir->x + ray->dir->z * ray->dir->z;
    b = ray->dir->x * (ray->ori->x - cylinder->base->x) +
            ray->dir->z * (ray->ori->z - cylinder->base->z);
    c = (ray->ori->x - cylinder->base->x) * (ray->ori->x - cylinder->base->x) +
            (ray->ori->z - cylinder->base->z) * (ray->ori->z - cylinder->base->z) -
            cylinder->radius * cylinder->radius;
    delta = b * b - a * c;
    if (delta > ACC)
    {
            root = (-1 * b - sqrt(delta)) / a - ACC;
            if (root <= ACC)
                    root = (-1 * b + sqrt(delta)) / a - ACC;
            return (root);
    }
    return (-1);
}
The normal function stays the same. And then the light is ok !
The second function seems to work fine. But why ? Isn't the first one the exact 'application' of the cylinder equation ?
Here is a second problem. I want to rotate my cylinder around the Ox axis. x²+(y.cosθ+z.sinθ)² = r².
After developing the equation, I have this function (based on my second function, of my friend)
double          nn_ray_cylinder(t_ray *ray, t_cylinder *cylinder, t_data *d)
{
    double a;
    double b;
    double c;
    double delta;
    double root;
    double deg = M_PI * 45 / 180;
    a = ray->dir->x * ray->dir->x + cos(deg) * cos(deg) * ray->dir->z * ray->dir->z +
            2 * ray->dir->z * cos(deg) * ray->dir->y * sin(deg) + ray->dir->y * ray->dir->y *
            sin(deg) * sin(deg);
    b =  (ray->ori->x - cylinder->base->x) * ray->dir->x + cos(deg) * cos(deg) * (ray->ori->z - cylinder->base->z) * ray->dir->z +
            2 * (ray->ori->z - cylinder->base->z) * cos(deg) * ray->dir->y * sin(deg) + 2 * ray->dir->z * cos(deg) *
            (ray->ori->y - cylinder->base->y) * sin(deg) + 2 * (ray->ori->y - cylinder->base->y) * ray->dir->y * sin(deg) * sin(deg);
    c = (ray->ori->x - cylinder->base->x) * (ray->ori->x - cylinder->base->x) + (ray->ori->z - cylinder->base->z) * (ray->ori->z - cylinder->base->z)* cos(deg) * cos(deg) +
            2 * (ray->ori->z - cylinder->base->z) * cos(deg) * (ray->ori->y - cylinder->base->y) * sin(deg) + (ray->ori->y - cylinder->base->y) * (ray->ori->y - cylinder->base->y) *
            sin(deg) * sin(deg) - cylinder->radius * cylinder->radius;
    delta = b * b -  a * c;
    if (delta > ACC)
    {
            root = (-1 * b - sqrt(delta)) / a - ACC;
            if (root <= ACC)
                    root = (-1 * b + sqrt(delta)) / a - ACC;
            return (root);
    }
    return (-1);
}
The rotation is a success ! But now I have to change the normal vector on this intersection point. For this, I apply an inverted rotation to the intersection point, then I calculate the normal vector like before, then I reapply the rotation to the point to find the normal vector of the rotated cylinder.
t_vect          *cylinder_normal_at(t_cylinder *cylinder, t_vect *intersection)
{
    t_vect *base_tmp;
    t_vect *normal;
    t_vect *intersection_tmp;
    t_matrix *rotate = init_rotation_matrix(45, 1, 0, 0);
    t_matrix *rotate_inverted = init_rotation_matrix(-45, 1, 0, 0);
    base_tmp = copy_vector(cylinder->base);
    intersection_tmp = copy_vector(intersection);
    apply_matrix(rotate_inverted, intersection_tmp);
    base_tmp->y = intersection_tmp->y;
    apply_matrix(rotate, intersection_tmp);
    apply_matrix(rotate, base_tmp);
    normal = init_vector(intersection->x - base_tmp->x,
                    intersection->y - base_tmp->y,
                    intersection->z - base_tmp->z);
    normalize_vector(normal);
    return (normal);
}
The result seems good for a basic cylinder and a cylinder rotated by 90 degrees for example. But the reflects are totally wrong with 45 degrees ...
So where are my mistakes ? Is the normal function wrong, or the other one ? And why ? Thanks a lot to those who can help me. I drown myself in mathematics ...
Edit :
Thanks chux, the quadratic mis-coding is now corrected. The problem about the normal vector is still here.
Here I add some my rotation functions :
t_matrix        *init_rotation_matrix(double theta, double x, double y, double z)
{
    t_matrix *matrix;
    double rad;
    if ((matrix = malloc(sizeof *matrix)) == NULL)
            return (NULL);
    rad = theta * M_PI / 180;
    matrix->m11 = x * x * (1 - cos(rad)) + cos(rad);
    matrix->m12 = x * y * (1 - cos(rad)) - z * sin(rad);
    matrix->m13 = x * z * (1 - cos(rad)) + y * sin(rad);
    matrix->m14 = 0;
    matrix->m21 = y * x * (1 - cos(rad)) + z * sin(rad);
    matrix->m22 = y * y * (1 - cos(rad)) + cos(rad);
    matrix->m23 = y * z * (1 - cos(rad)) - x * sin(rad);
    matrix->m24 = 0;
    matrix->m31 = x * z * (1 - cos(rad)) - y * sin(rad);
    matrix->m32 = y * z * (1 - cos(rad)) + x * sin(rad);
    matrix->m33 = z * z * (1 - cos(rad)) + cos(rad);
    matrix->m34 = 0;
    matrix->m41 = 0;
    matrix->m42 = 0;
    matrix->m43 = 0;
    matrix->m44 = 1;
    return (matrix);
}
void    apply_matrix(t_matrix *matrix, t_vect *v)
{
    double x;
    double y;
    double z;
    x = v->x;
    y = v->y;
    z = v->z;
    v->x = matrix->m11 * x + matrix->m12 * y + matrix->m13 * z + matrix->m14;
    v->y = matrix->m21 * x + matrix->m22 * y + matrix->m23 * z + matrix->m24;
    v->z = matrix->m31 * x + matrix->m32 * y + matrix->m33 * z + matrix->m34;
}
Edit 2 :
In the function that calculates the normal vector, I replaced 45 by -45 and 45 by -45. And now it works ... I must have a problem with my z axis. It seems that the positive z and negative z are inverted ...