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; } } }
/* 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; }
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; }
/* 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; }