static void initData(ModifierData *md) { UVWarpModifierData *umd = (UVWarpModifierData *) md; umd->axis_u = 0; umd->axis_v = 1; copy_v2_fl(umd->center, 0.5f); }
/* reads full rect, converts indices */ uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) { if (UNLIKELY((xmin > xmax) || (ymin > ymax))) { return NULL; } const rcti rect = { .xmin = xmin, .xmax = xmax + 1, .ymin = ymin, .ymax = ymax + 1, }; uint buf_len; uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len); if (r_buf_len) { *r_buf_len = buf_len; } return buf; } /* ************************************************************* */ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) { if (BKE_image_is_stereo(ima)) { iuser->flag |= IMA_SHOW_STEREO; if ((scene->r.scemode & R_MULTIVIEW) == 0) { iuser->multiview_eye = STEREO_LEFT_ID; } else if (v3d->stereo3d_camera != STEREO_3D_ID) { /* show only left or right camera */ iuser->multiview_eye = v3d->stereo3d_camera; } BKE_image_multiview_index(ima, iuser); } else { iuser->flag &= ~IMA_SHOW_STEREO; } } static void view3d_draw_bgpic(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const bool do_foreground, const bool do_camera_frame) { RegionView3D *rv3d = ar->regiondata; int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0; if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) { return; } Camera *cam = v3d->camera->data; for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) { if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) { continue; } { float image_aspect[2]; float x1, y1, x2, y2, centx, centy; void *lock; Image *ima = NULL; /* disable individual images */ if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) { continue; } ImBuf *ibuf = NULL; ImBuf *freeibuf = NULL; ImBuf *releaseibuf = NULL; if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { ima = bgpic->ima; if (ima == NULL) { continue; } ImageUser iuser = bgpic->iuser; iuser.scene = scene; /* Needed for render results. */ BKE_image_user_frame_calc(&iuser, (int)DEG_get_ctime(depsgraph)); if (ima->source == IMA_SRC_SEQUENCE && !(iuser.flag & IMA_USER_FRAME_IN_RANGE)) { ibuf = NULL; /* frame is out of range, dont show */ } else { view3d_stereo_bgpic_setup(scene, v3d, ima, &iuser); ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock); releaseibuf = ibuf; } image_aspect[0] = ima->aspx; image_aspect[1] = ima->aspy; } else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { /* TODO: skip drawing when out of frame range (as image sequences do above) */ MovieClip *clip = NULL; if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) { if (scene->camera) { clip = BKE_object_movieclip_get(scene, scene->camera, true); } } else { clip = bgpic->clip; } if (clip == NULL) { continue; } BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph)); ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser); image_aspect[0] = clip->aspx; image_aspect[1] = clip->aspy; /* working with ibuf from image and clip has got different workflow now. * ibuf acquired from clip is referenced by cache system and should * be dereferenced after usage. */ freeibuf = ibuf; } else { /* perhaps when loading future files... */ BLI_assert(0); copy_v2_fl(image_aspect, 1.0f); } if (ibuf == NULL) { continue; } if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */ if (freeibuf) { IMB_freeImBuf(freeibuf); } if (releaseibuf) { BKE_image_release_ibuf(ima, releaseibuf, lock); } continue; } if (ibuf->rect == NULL) { IMB_rect_from_float(ibuf); } BLI_assert(rv3d->persp == RV3D_CAMOB); { if (do_camera_frame) { rctf vb; ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false); x1 = vb.xmin; y1 = vb.ymin; x2 = vb.xmax; y2 = vb.ymax; } else { x1 = ar->winrct.xmin; y1 = ar->winrct.ymin; x2 = ar->winrct.xmax; y2 = ar->winrct.ymax; } /* apply offset last - camera offset is different to offset in blender units */ /* so this has some sane way of working - this matches camera's shift _exactly_ */ { const float max_dim = max_ff(x2 - x1, y2 - y1); const float xof_scale = bgpic->offset[0] * max_dim; const float yof_scale = bgpic->offset[1] * max_dim; x1 += xof_scale; y1 += yof_scale; x2 += xof_scale; y2 += yof_scale; } centx = (x1 + x2) * 0.5f; centy = (y1 + y2) * 0.5f; /* aspect correction */ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) { /* apply aspect from clip */ const float w_src = ibuf->x * image_aspect[0]; const float h_src = ibuf->y * image_aspect[1]; /* destination aspect is already applied from the camera frame */ const float w_dst = x1 - x2; const float h_dst = y1 - y2; const float asp_src = w_src / h_src; const float asp_dst = w_dst / h_dst; if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) { /* fit X */ const float div = asp_src / asp_dst; x1 = ((x1 - centx) * div) + centx; x2 = ((x2 - centx) * div) + centx; } else { /* fit Y */ const float div = asp_dst / asp_src; y1 = ((y1 - centy) * div) + centy; y2 = ((y2 - centy) * div) + centy; } } } } /* complete clip? */ rctf clip_rect; BLI_rctf_init(&clip_rect, x1, x2, y1, y2); if (bgpic->rotation) { BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); } if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { if (freeibuf) { IMB_freeImBuf(freeibuf); } if (releaseibuf) { BKE_image_release_ibuf(ima, releaseibuf, lock); } continue; } float zoomx = (x2 - x1) / ibuf->x; float zoomy = (y2 - y1) / ibuf->y; /* For some reason; zoom-levels down refuses to use GL_ALPHA_SCALE. */ if (zoomx < 1.0f || zoomy < 1.0f) { float tzoom = min_ff(zoomx, zoomy); int mip = 0; if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { IMB_remakemipmap(ibuf, 0); ibuf->userflags &= ~IB_MIPMAP_INVALID; } else if (ibuf->mipmap[0] == NULL) { IMB_makemipmap(ibuf, 0); } while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) { tzoom *= 2.0f; zoomx *= 2.0f; zoomy *= 2.0f; mip++; } if (mip > 0) { ibuf = ibuf->mipmap[mip - 1]; } } GPU_depth_test(!do_foreground); glDepthMask(GL_FALSE); GPU_blend(true); GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); GPU_matrix_push_projection(); GPU_matrix_push(); ED_region_pixelspace(ar); GPU_matrix_translate_2f(centx, centy); GPU_matrix_scale_1f(bgpic->scale); GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation)); if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) { zoomx *= -1.0f; x1 = x2; } if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) { zoomy *= -1.0f; y1 = y2; } float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha}; IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); immDrawPixelsTex(&state, x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect, zoomx, zoomy, col); GPU_matrix_pop_projection(); GPU_matrix_pop(); GPU_blend(false); glDepthMask(GL_TRUE); GPU_depth_test(true); if (freeibuf) { IMB_freeImBuf(freeibuf); } if (releaseibuf) { BKE_image_release_ibuf(ima, releaseibuf, lock); } } } }