static int tool_laser_iter(goxel_t *goxel, const inputs_t *inputs, int state, const vec2_t *view_size, bool inside) { vec3_t pos, normal; box_t box; painter_t painter = goxel->painter; mesh_t *mesh = goxel->image->active_layer->mesh; const bool down = inputs->mouse_down[0]; // XXX: would be nice if we got the vec4_t view instead of view_size, // and why input->pos is not already in win pos? vec4_t view = vec4(0, 0, view_size->x, view_size->y); vec2_t win = inputs->mouse_pos; win.y = view_size->y - win.y; painter.op = OP_SUB; painter.shape = &shape_cylinder; // Create the tool box from the camera along the visible ray. camera_get_ray(&goxel->camera, &win, &view, &pos, &normal); box.mat = mat4_identity; box.w = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat), vec4(1, 0, 0, 0)).xyz; box.h = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat), vec4(0, 1, 0, 0)).xyz; box.d = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat), vec4(0, 0, 1, 0)).xyz; box.d = vec3_neg(normal); box.p = pos; // Just a large value for the size of the laser box. mat4_itranslate(&box.mat, 0, 0, -1024); mat4_iscale(&box.mat, goxel->tool_radius, goxel->tool_radius, 1024); render_box(&goxel->rend, &box, false, NULL, false); if (state == STATE_IDLE) { if (down) { state = STATE_PAINT; image_history_push(goxel->image); } } if (state == STATE_PAINT) { if (!down) { return STATE_IDLE; } mesh_op(mesh, &painter, &box); goxel_update_meshes(goxel, -1); } return state; }
// Get the raytracing ray of the camera at a given screen position. void camera_get_ray(const camera_t *camera, const vec2_t *win, const vec4_t *view, vec3_t *o, vec3_t *d) { // XXX: ugly algo. mat4_t inv; vec3_t p; vec3_t norm_pos = vec3((2 * win->x - view->v[0]) / view->v[2] - 1, (2 * win->y - view->v[1]) / view->v[3] - 1, - 1); if (camera->ortho) { inv = mat4_inverted(mat4_mul(camera->proj_mat, camera->view_mat)); *o = mat4_mul_vec(inv, vec4(norm_pos.x, norm_pos.y, 0, 1)).xyz; *d = mat4_mul_vec(inv, vec4(0, 0, -1, 0)).xyz; } else { inv = mat4_inverted(camera->view_mat); *o = mat4_mul_vec(inv, vec4(0, 0, 0, 1)).xyz; inv = mat4_mul(camera->proj_mat, camera->view_mat); mat4_invert(&inv); p = mat4_mul_vec3(inv, norm_pos); *d = vec3_sub(p, *o); } }
static int tool_laser_iter(goxel_t *goxel, const inputs_t *inputs, int state, const vec2_t *view_size, bool inside) { vec3_t pos, normal; box_t box; painter_t painter = goxel->painter; mesh_t *mesh = goxel->image->active_layer->mesh; const bool down = inputs->mouse_down[0]; painter.op = OP_SUB; painter.shape = &shape_cylinder; // Create the laser box with an inifinity width. goxel_unproject_on_screen(goxel, view_size, &inputs->mouse_pos, &pos, &normal); box.mat = mat4_identity; box.w = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat), vec4(1, 0, 0, 0)).xyz; box.h = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat), vec4(0, 1, 0, 0)).xyz; box.d = mat4_mul_vec(mat4_inverted(goxel->camera.view_mat), vec4(0, 0, 1, 0)).xyz; box.p = pos; mat4_itranslate(&box.mat, 0, 0, -128); mat4_iscale(&box.mat, goxel->tool_radius, goxel->tool_radius, 128); render_box(&goxel->rend, &box, false, NULL, false); if (state == STATE_IDLE) { if (down) state = STATE_PAINT; } if (state == STATE_PAINT) { if (!down) { image_history_push(goxel->image); return STATE_IDLE; } mesh_op(mesh, &painter, &box); goxel_update_meshes(goxel, false); } return state; }