Beispiel #1
0
bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval[2], const bool do_fallback)
{
	RegionView3D *rv3d = ar->regiondata;
	float dvec[3];
	int mval_cpy[2];
	eV3DProjStatus ret;

	ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);

	if (ret == V3D_PROJ_RET_OK) {
		const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]),
		                         (float)(mval_cpy[1] - mval[1])};
		const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL);
		ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
		sub_v3_v3(fp, dvec);

		return true;
	}
	else {
		/* fallback to the view center */
		if (do_fallback) {
			negate_v3_v3(fp, rv3d->ofs);
			return view3d_get_view_aligned_coordinate(ar, fp, mval, false);
		}
		else {
			return false;
		}
	}
}
Beispiel #2
0
/* Project screenspace coordinates to 3D-space
 * NOTE: We include this as a utility function, since the standard method
 *       involves quite a few steps, which are invariably always the same
 *       for all GPencil operations. So, it's nicer to just centralise these.
 * WARNING: Assumes that it is getting called in a 3D view only
 */
bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen_co[2], float r_out[3])
{
	View3D *v3d = gsc->sa->spacedata.first;
	RegionView3D *rv3d = gsc->ar->regiondata;
	float *rvec = ED_view3d_cursor3d_get(scene, v3d);
	float ref[3] = {rvec[0], rvec[1], rvec[2]};
	float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
	
	float mval_f[2], mval_prj[2];
	float dvec[3];
	
	copy_v2_v2(mval_f, screen_co);
	
	if (ED_view3d_project_float_global(gsc->ar, ref, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
		sub_v2_v2v2(mval_f, mval_prj, mval_f);
		ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac);
		sub_v3_v3v3(r_out, rvec, dvec);
		
		return true;
	}
	else {
		zero_v3(r_out);
		
		return false;
	}
}
static bool mesh_bisect_interactive_calc(
        bContext *C, wmOperator *op,
        BMEditMesh *em,
        float plane_co[3], float plane_no[3])
{
	wmGesture *gesture = op->customdata;
	BisectData *opdata;

	ARegion *ar = CTX_wm_region(C);
	RegionView3D *rv3d = ar->regiondata;

	int x_start = RNA_int_get(op->ptr, "xstart");
	int y_start = RNA_int_get(op->ptr, "ystart");
	int x_end = RNA_int_get(op->ptr, "xend");
	int y_end = RNA_int_get(op->ptr, "yend");

	/* reference location (some point in front of the view) for finding a point on a plane */
	const float *co_ref = rv3d->ofs;
	float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2];
	float co_a[3], co_b[3];
	const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);

	opdata = gesture->userdata;

	/* view vector */
	ED_view3d_win_to_vector(ar, co_a_ss, co_a);

	/* view delta */
	sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss);
	ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac);

	/* cross both to get a normal */
	cross_v3_v3v3(plane_no, co_a, co_b);
	normalize_v3(plane_no);  /* not needed but nicer for user */

	/* point on plane, can use either start or endpoint */
	ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co);

	if (opdata->is_first == false)
		EDBM_redo_state_restore(opdata->mesh_backup, em, false);

	opdata->is_first = false;

	return true;
}
Beispiel #4
0
float paint_calc_object_space_radius(ViewContext *vc, const float center[3],
                                     float pixel_radius)
{
	Object *ob = vc->obact;
	float delta[3], scale, loc[3];
	const float mval_f[2] = {pixel_radius, 0.0f};
	float zfac;

	mul_v3_m4v3(loc, ob->obmat, center);

	zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
	ED_view3d_win_to_delta(vc->ar, mval_f, delta, zfac);

	scale = fabsf(mat4_to_scale(ob->obmat));
	scale = (scale == 0.0f) ? 1.0f : scale;

	return len_v3(delta) / scale;
}
Beispiel #5
0
/* add a gpencil object to cache to defer drawing */
tGPencilObjectCache *gpencil_object_cache_add(tGPencilObjectCache *cache_array,
                                              Object *ob,
                                              int *gp_cache_size,
                                              int *gp_cache_used)
{
  const DRWContextState *draw_ctx = DRW_context_state_get();
  tGPencilObjectCache *cache_elem = NULL;
  RegionView3D *rv3d = draw_ctx->rv3d;
  View3D *v3d = draw_ctx->v3d;
  tGPencilObjectCache *p = NULL;

  /* By default a cache is created with one block with a predefined number of free slots,
   * if the size is not enough, the cache is reallocated adding a new block of free slots.
   * This is done in order to keep cache small. */
  if (*gp_cache_used + 1 > *gp_cache_size) {
    if ((*gp_cache_size == 0) || (cache_array == NULL)) {
      p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE,
                      "tGPencilObjectCache");
      *gp_cache_size = GP_CACHE_BLOCK_SIZE;
    }
    else {
      *gp_cache_size += GP_CACHE_BLOCK_SIZE;
      p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
    }
    cache_array = p;
  }
  /* zero out all pointers */
  cache_elem = &cache_array[*gp_cache_used];
  memset(cache_elem, 0, sizeof(*cache_elem));

  cache_elem->ob = ob;
  cache_elem->gpd = (bGPdata *)ob->data;
  cache_elem->name = BKE_id_to_unique_string_key(&ob->id);

  copy_v3_v3(cache_elem->loc, ob->obmat[3]);
  copy_m4_m4(cache_elem->obmat, ob->obmat);
  cache_elem->idx = *gp_cache_used;

  /* object is duplicated (particle) */
  if (ob->base_flag & BASE_FROM_DUPLI) {
    /* Check if the original object is not in the viewlayer
     * and cannot be managed as dupli. This is slower, but required to keep
     * the particle drawing FPS and display instanced objects in scene
     * without the original object */
    bool has_original = gpencil_has_noninstanced_object(ob);
    cache_elem->is_dup_ob = (has_original) ? ob->base_flag & BASE_FROM_DUPLI : false;
  }
  else {
    cache_elem->is_dup_ob = false;
  }

  cache_elem->scale = mat4_to_scale(ob->obmat);

  /* save FXs */
  cache_elem->pixfactor = cache_elem->gpd->pixfactor;
  cache_elem->shader_fx = ob->shader_fx;

  /* save wire mode (object mode is always primary option) */
  if (ob->dt == OB_WIRE) {
    cache_elem->shading_type[0] = (int)OB_WIRE;
  }
  else {
    if (v3d) {
      cache_elem->shading_type[0] = (int)v3d->shading.type;
    }
  }

  /* shgrp array */
  cache_elem->tot_layers = 0;
  int totgpl = BLI_listbase_count(&cache_elem->gpd->layers);
  if (totgpl > 0) {
    cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__);
  }

  /* calculate zdepth from point of view */
  float zdepth = 0.0;
  if (rv3d) {
    if (rv3d->is_persp) {
      zdepth = ED_view3d_calc_zfac(rv3d, ob->obmat[3], NULL);
    }
    else {
      zdepth = -dot_v3v3(rv3d->viewinv[2], ob->obmat[3]);
    }
  }
  else {
    /* In render mode, rv3d is not available, so use the distance to camera.
     * The real distance is not important, but the relative distance to the camera plane
     * in order to sort by z_depth of the objects
     */
    float vn[3] = {0.0f, 0.0f, -1.0f}; /* always face down */
    float plane_cam[4];
    struct Object *camera = draw_ctx->scene->camera;
    if (camera) {
      mul_m4_v3(camera->obmat, vn);
      normalize_v3(vn);
      plane_from_point_normal_v3(plane_cam, camera->loc, vn);
      zdepth = dist_squared_to_plane_v3(ob->obmat[3], plane_cam);
    }
  }
  cache_elem->zdepth = zdepth;
  /* increase slots used in cache */
  (*gp_cache_used)++;

  return cache_array;
}