Esempio n. 1
0
/**
 * Calculate a 3d location from 2d window coordinates.
 * \param ar The region (used for the window width and height).
 * \param depth_pt The reference location used to calculate the Z depth.
 * \param mval The area relative location (such as event->mval converted to floats).
 * \param out The resulting world-space location.
 */
void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float mval[2], float out[3])
{
	RegionView3D *rv3d = ar->regiondata;

	float ray_origin[3];
	float ray_direction[3];
	float lambda;

	if (rv3d->is_persp) {
		float plane[4];

		copy_v3_v3(ray_origin, rv3d->viewinv[3]);
		ED_view3d_win_to_vector(ar, mval, ray_direction);

		/* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the
		 * view no matter what, so apply the unsigned factor instead */
		plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]);

		isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false);
		lambda = fabsf(lambda);
	}
	else {
		float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f;
		float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f;
		if (rv3d->persp == RV3D_CAMOB) {
			/* ortho camera needs offset applied */
			const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f;
			dx += rv3d->camdx * zoomfac;
			dy += rv3d->camdy * zoomfac;
		}
		ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0];
		ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1];
		ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2];

		copy_v3_v3(ray_direction, rv3d->viewinv[2]);
		lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction);
	}

	madd_v3_v3v3fl(out, ray_origin, ray_direction, lambda);
}
Esempio n. 2
0
/**
 * Sets the depth from #StrokeElem.mval
 */
static bool stroke_elem_project(
        const struct CurveDrawData *cdd,
        const int mval_i[2], const float mval_fl[2],
        float surface_offset, const float radius,
        float r_location_world[3], float r_normal_world[3])
{
	View3D *v3d = cdd->vc.v3d;
	ARegion *ar = cdd->vc.ar;
	RegionView3D *rv3d = cdd->vc.rv3d;

	bool is_location_world_set = false;

	/* project to 'location_world' */
	if (cdd->project.use_plane) {
		/* get the view vector to 'location' */
		float ray_origin[3], ray_direction[3];
		ED_view3d_win_to_ray(cdd->vc.ar, v3d, mval_fl, ray_origin, ray_direction, false);

		float lambda;
		if (isect_ray_plane_v3(ray_origin, ray_direction, cdd->project.plane, &lambda, true)) {
			madd_v3_v3v3fl(r_location_world, ray_origin, ray_direction, lambda);
			if (r_normal_world) {
				zero_v3(r_normal_world);
			}
			is_location_world_set = true;
		}
	}
	else {
		const ViewDepths *depths = rv3d->depths;
		if (depths &&
		    ((unsigned int)mval_i[0] < depths->w) &&
		    ((unsigned int)mval_i[1] < depths->h))
		{
			const double depth = (double)depth_read_zbuf(&cdd->vc, mval_i[0], mval_i[1]);
			if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
				if (depth_unproject(ar, &cdd->mats, mval_i, depth, r_location_world)) {
					is_location_world_set = true;
					if (r_normal_world) {
						zero_v3(r_normal_world);
					}

					if (surface_offset != 0.0f) {
						const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
						float normal[3];
						if (depth_read_normal(&cdd->vc, &cdd->mats, mval_i, normal)) {
							madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
							if (r_normal_world) {
								copy_v3_v3(r_normal_world, normal);
							}
						}
					}
				}
			}
		}
	}

	if (is_location_world_set) {
		if (cdd->project.use_offset) {
			add_v3_v3(r_location_world, cdd->project.offset);
		}
	}

	return is_location_world_set;
}