static void calc_ray_shift(rcti *rect, float x, float y, const float source[2], float ray_length)
{
	float co[2] = {(float)x, (float)y};
	float dir[2], dist;

	/* move (x,y) vector toward the source by ray_length distance */
	sub_v2_v2v2(dir, co, source);
	dist = normalize_v2(dir);
	mul_v2_fl(dir, min_ff(dist, ray_length));
	sub_v2_v2(co, dir);

	int ico[2] = {(int)co[0], (int)co[1]};
	BLI_rcti_do_minmax_v(rect, ico);
}
Exemple #2
0
/* Convert the object-space axis-aligned bounding box (expressed as
 * its minimum and maximum corners) into a screen-space rectangle,
 * returns zero if the result is empty */
bool paint_convert_bb_to_rect(rcti *rect,
                              const float bb_min[3],
                              const float bb_max[3],
                              const ARegion *ar,
                              RegionView3D *rv3d,
                              Object *ob)
{
	float projection_mat[4][4];
	int i, j, k;

	BLI_rcti_init_minmax(rect);

	/* return zero if the bounding box has non-positive volume */
	if (bb_min[0] > bb_max[0] || bb_min[1] > bb_max[1] || bb_min[2] > bb_max[2])
		return 0;

	ED_view3d_ob_project_mat_get(rv3d, ob, projection_mat);

	for (i = 0; i < 2; ++i) {
		for (j = 0; j < 2; ++j) {
			for (k = 0; k < 2; ++k) {
				float vec[3], proj[2];
				int proj_i[2];
				vec[0] = i ? bb_min[0] : bb_max[0];
				vec[1] = j ? bb_min[1] : bb_max[1];
				vec[2] = k ? bb_min[2] : bb_max[2];
				/* convert corner to screen space */
				ED_view3d_project_float_v2_m4(ar, vec, proj, projection_mat);
				/* expand 2D rectangle */

				/* we could project directly to int? */
				proj_i[0] = proj[0];
				proj_i[1] = proj[1];

				BLI_rcti_do_minmax_v(rect, proj_i);
			}
		}
	}

	/* return false if the rectangle has non-positive area */
	return rect->xmin < rect->xmax && rect->ymin < rect->ymax;
}