Hi,
I'm programming a C raytracer.
I'm having trouble getting the camera to rotate. I've tried many methods, but after many tries it's always flawed. I would like the camera to rotate by pressing keys (F for left, H for right, T for up, G for down, R and Y for Z axis).
This is how the camera axis are initialized at the beginning of the program (do it once) :
void init_camera_vecs(t_camera *cam)
{
t_vec3 forward;
forward = get_normalised(invert(cam->vec));
cam->up = (t_vec3){0, 0, 0};
if (fabs(cam->vec.y) > 0.7)
cam->right = vec_cross((t_vec3){0, 0, -1}, forward);
else
cam->right = vec_cross((t_vec3){0, 1, 0}, forward);
cam->up = vec_cross(forward, cam->right);
}
This is my get_ray_dir() function which gives the direction of the ray from camera space to world space:
static t_vec3 lookat(t_camera *cam, t_vec3 ray_coord)
{
t_vec3 forward;
t_vec3 ray_dir;
forward = get_normalised(invert(cam->vec));
ray_dir.x = ray_coord.x * cam->right.x + ray_coord.y * cam->up.x
+ ray_coord.z * forward.x;
ray_dir.y = ray_coord.x * cam->right.y + ray_coord.y * cam->up.y
+ ray_coord.z * forward.y;
ray_dir.z = ray_coord.x * cam->right.z + ray_coord.y * cam->up.z
+ ray_coord.z * forward.z;
return (ray_dir);
}
static t_vec3 get_ray_dir(int i, int j, t_resolution res, t_camera *cam)
{
t_ray ray;
float scale;
float point_x;
float point_y;
float ratio;
ratio = res.x / (float)res.y;
scale = tan(cam->fov / 2 * M_PI / 180);
point_x = (2 * (j + 0.5) / (float)res.x - 1) * ratio * scale;
point_y = (1 - 2 * (i + 0.5) / res.y) * scale;
ray.coord = (t_vec3){point_x, point_y, -1};
ray.dir = lookat(cam, ray.coord);
normalize(&ray.dir);
return (ray.dir);
}
I tried this :
void make_rotation_x(t_vec3 *rot_x, float angle)
{
float c;
float s;
c = cos(angle);
s = sin(angle);
rot_x[0] = (t_vec3){1, 0, 0};
rot_x[1] = (t_vec3){0, c, -s};
rot_x[2] = (t_vec3){0, s, c};
}
void make_rotation_y(t_vec3 *rot_y, float angle)
{
float c;
float s;
c = cos(angle);
s = sin(angle);
rot_y[0] = (t_vec3){c, 0, s};
rot_y[1] = (t_vec3){0, 1, 0};
rot_y[2] = (t_vec3){-s, 0, c};
}
void make_rotation_z(t_vec3 *rot_z, float angle)
{
float c;
float s;
c = cos(angle);
s = sin(angle);
rot_z[0] = (t_vec3){c, -s, 0};
rot_z[1] = (t_vec3){s, c, 0};
rot_z[2] = (t_vec3){0, 0, 1};
}
void mult_matrix(t_vec3 *res, t_vec3 *lhs, t_vec3 *rhs)
{
res[0] = rotate_vector(lhs, rhs[0]);
res[1] = rotate_vector(lhs, rhs[1]);
res[2] = rotate_vector(lhs, rhs[2]);
}
void cpy_matrix(t_vec3 *dst, t_vec3 *src)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
}
void apply_rotation_x(t_vec3 *orientation, float angle)
{
t_vec3 matrix[3];
t_vec3 res[3];
make_rotation_x(matrix, angle);
mult_matrix(res, orientation, matrix);
cpy_matrix(orientation, res);
}
void apply_rotation_y(t_vec3 *orientation, float angle)
{
t_vec3 matrix[3];
t_vec3 res[3];
make_rotation_y(matrix, angle);
mult_matrix(res, orientation, matrix);
cpy_matrix(orientation, res);
}
void apply_rotation_z(t_vec3 *orientation, float angle)
{
t_vec3 matrix[3];
t_vec3 res[3];
make_rotation_z(matrix, angle);
mult_matrix(res, orientation, matrix);
cpy_matrix(orientation, res);
}
void move_cam(t_specs *s, int key)
{
t_camera *cam;
t_vec3 orientation[3];
float angle;
angle = 4.5 * (M_PI / 180);
cam = s->current_cam;
orientation[0] = cam->right;
orientation[1] = cam->up;
orientation[2] = cam->vec;
if (key == KEY_W)
cam->coord = vec_add(cam->coord, cam->up);
else if (key == KEY_S)
cam->coord = vec_sub(cam->coord, cam->up);
else if (key == KEY_A)
cam->coord = vec_sub(cam->coord, cam->right);
else if (key == KEY_D)
cam->coord = vec_add(cam->coord, cam->right);
else if (key == KEY_Q)
cam->coord = vec_sub(cam->coord, cam->vec);
else if (key == KEY_E)
cam->coord = vec_add(cam->coord, cam->vec);
else if (key == KEY_H)
apply_rotation_y(orientation, -angle);
else if (key == KEY_F)
apply_rotation_y(orientation, angle);
else if (key == KEY_G)
apply_rotation_x(orientation, -angle);
else if (key == KEY_T)
apply_rotation_x(orientation, angle);
else if (key == KEY_R)
apply_rotation_z(orientation, -angle);
else if (key == KEY_Y)
apply_rotation_z(orientation, angle);
s->current_cam->right = orientation[0];
s->current_cam->up = orientation[1];
s->current_cam->vec = orientation[2];
normalize(&s->current_cam->right);
normalize(&s->current_cam->up);
normalize(&s->current_cam->vec);
}
When I rotate on two axes, the third axis is influenced, which I don't want.
Example :
I would be very grateful for any help you could give me in order to be able to perform this camera rotation function.