VIEW3D_OT_camera_to_view_selected operator to move the camera to frame
all selected, renderable objects.
This commit is contained in:
@@ -366,6 +366,7 @@ class VIEW3D_MT_view_align(Menu):
|
||||
|
||||
layout.operator("view3d.view_all", text="Center Cursor and View All").center = True
|
||||
layout.operator("view3d.camera_to_view", text="Align Active Camera to View")
|
||||
layout.operator("view3d.camera_to_view_selected", text="Align Active Camera to Selected")
|
||||
layout.operator("view3d.view_selected")
|
||||
layout.operator("view3d.view_center_cursor")
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ struct Object;
|
||||
struct RenderData;
|
||||
struct Scene;
|
||||
struct rctf;
|
||||
struct View3D;
|
||||
|
||||
void *add_camera(const char *name);
|
||||
struct Camera *copy_camera(struct Camera *cam);
|
||||
@@ -63,6 +64,10 @@ void camera_view_frame_ex(struct Scene *scene, struct Camera *camera, float draw
|
||||
|
||||
void camera_view_frame(struct Scene *scene, struct Camera *camera, float r_vec[4][3]);
|
||||
|
||||
int camera_view_frame_fit_to_scene(
|
||||
struct Scene *scene, struct View3D *v3d, struct Object *camera_ob,
|
||||
float r_co[3]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -110,6 +110,17 @@ void object_set_dimensions(struct Object *ob, const float *value);
|
||||
void object_boundbox_flag(struct Object *ob, int flag, int set);
|
||||
void minmax_object(struct Object *ob, float min[3], float max[3]);
|
||||
int minmax_object_duplis(struct Scene *scene, struct Object *ob, float *min, float *max);
|
||||
|
||||
/* sometimes min-max isnt enough, we need to loop over each point */
|
||||
void BKE_object_foreach_display_point(
|
||||
struct Object *ob, float obmat[4][4],
|
||||
void (*func_cb)(const float[3], void *), void *user_data);
|
||||
void BKE_scene_foreach_display_point(
|
||||
struct Scene *scene,
|
||||
struct View3D *v3d,
|
||||
const short flag,
|
||||
void (*func_cb)(const float[3], void *), void *user_data);
|
||||
|
||||
void solve_tracking (struct Object *ob, float targetmat[][4]);
|
||||
int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3]);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_main.h"
|
||||
@@ -394,3 +395,109 @@ void camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
|
||||
dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
|
||||
}
|
||||
|
||||
|
||||
typedef struct CameraViewFrameData {
|
||||
float frame_tx[4][3];
|
||||
float normal_tx[4][3];
|
||||
float dist_vals[4];
|
||||
unsigned int tot;
|
||||
} CameraViewFrameData;
|
||||
|
||||
static void camera_to_frame_view_cb(const float co[3], void *user_data)
|
||||
{
|
||||
CameraViewFrameData *data= (CameraViewFrameData *)user_data;
|
||||
unsigned int i;
|
||||
|
||||
for (i= 0; i < 4; i++) {
|
||||
float nd= -dist_to_plane_v3(co, data->frame_tx[i], data->normal_tx[i]);
|
||||
if (nd < data->dist_vals[i]) {
|
||||
data->dist_vals[i]= nd;
|
||||
}
|
||||
}
|
||||
|
||||
data->tot++;
|
||||
}
|
||||
|
||||
/* dont move the camera, just yield the fit location */
|
||||
int camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
|
||||
{
|
||||
float plane_tx[4][3];
|
||||
float rot_obmat[3][3];
|
||||
const float zero[3]= {0,0,0};
|
||||
CameraViewFrameData data_cb;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);
|
||||
|
||||
copy_m3_m4(rot_obmat, camera_ob->obmat);
|
||||
normalize_m3(rot_obmat);
|
||||
|
||||
for (i= 0; i < 4; i++) {
|
||||
mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
|
||||
}
|
||||
|
||||
for (i= 0; i < 4; i++) {
|
||||
normal_tri_v3(data_cb.normal_tx[i],
|
||||
zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
|
||||
}
|
||||
|
||||
/* initialize callback data */
|
||||
data_cb.dist_vals[0]=
|
||||
data_cb.dist_vals[1]=
|
||||
data_cb.dist_vals[2]=
|
||||
data_cb.dist_vals[3]= FLT_MAX;
|
||||
data_cb.tot= 0;
|
||||
/* run callback on all visible points */
|
||||
BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
|
||||
camera_to_frame_view_cb, &data_cb);
|
||||
|
||||
if (data_cb.tot <= 1) {
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
float plane_isect_1[3], plane_isect_1_other[3];
|
||||
float plane_isect_2[3], plane_isect_2_other[3];
|
||||
|
||||
float plane_isect_pt_1[3], plane_isect_pt_2[3];
|
||||
|
||||
/* apply the dist-from-plane's to the transformed plane points */
|
||||
for (i= 0; i < 4; i++) {
|
||||
mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]);
|
||||
}
|
||||
|
||||
if ( (isect_plane_plane_v3(plane_isect_1, plane_isect_1_other,
|
||||
plane_tx[0], data_cb.normal_tx[0],
|
||||
plane_tx[2], data_cb.normal_tx[2]) == 0) ||
|
||||
(isect_plane_plane_v3(plane_isect_2, plane_isect_2_other,
|
||||
plane_tx[1], data_cb.normal_tx[1],
|
||||
plane_tx[3], data_cb.normal_tx[3]) == 0))
|
||||
{
|
||||
/* this is very unlikely */
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
|
||||
add_v3_v3(plane_isect_1_other, plane_isect_1);
|
||||
add_v3_v3(plane_isect_2_other, plane_isect_2);
|
||||
|
||||
if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
|
||||
plane_isect_2, plane_isect_2_other,
|
||||
plane_isect_pt_1, plane_isect_pt_2) == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
float cam_plane_no[3]= {0.0f, 0.0f, -1.0f};
|
||||
float tvec[3];
|
||||
mul_m3_v3(rot_obmat, cam_plane_no);
|
||||
|
||||
sub_v3_v3v3(tvec, plane_isect_pt_2, plane_isect_pt_1);
|
||||
copy_v3_v3(r_co, dot_v3v3(tvec, cam_plane_no) > 0.0f ?
|
||||
plane_isect_pt_1 : plane_isect_pt_2);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2333,6 +2333,69 @@ int minmax_object_duplis(Scene *scene, Object *ob, float *min, float *max)
|
||||
return ok;
|
||||
}
|
||||
|
||||
void BKE_object_foreach_display_point(
|
||||
Object *ob, float obmat[4][4],
|
||||
void (*func_cb)(const float[3], void *), void *user_data)
|
||||
{
|
||||
float co[3];
|
||||
|
||||
if (ob->derivedFinal) {
|
||||
DerivedMesh *dm= ob->derivedFinal;
|
||||
MVert *mv= dm->getVertArray(dm);
|
||||
int totvert= dm->getNumVerts(dm);
|
||||
int i;
|
||||
|
||||
for (i= 0; i < totvert; i++, mv++) {
|
||||
mul_v3_m4v3(co, obmat, mv->co);
|
||||
func_cb(co, user_data);
|
||||
}
|
||||
}
|
||||
else if (ob->disp.first) {
|
||||
DispList *dl;
|
||||
|
||||
for (dl=ob->disp.first; dl; dl=dl->next) {
|
||||
float *v3= dl->verts;
|
||||
int totvert= dl->nr;
|
||||
int i;
|
||||
|
||||
for (i= 0; i < totvert; i++, v3+=3) {
|
||||
mul_v3_m4v3(co, obmat, v3);
|
||||
func_cb(co, user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_scene_foreach_display_point(
|
||||
Scene *scene, View3D *v3d, const short flag,
|
||||
void (*func_cb)(const float[3], void *), void *user_data)
|
||||
{
|
||||
Base *base;
|
||||
Object *ob;
|
||||
|
||||
for(base= FIRSTBASE; base; base = base->next) {
|
||||
if(BASE_VISIBLE(v3d, base) && (base->flag & flag) == flag) {
|
||||
ob= base->object;
|
||||
|
||||
if ((ob->transflag & OB_DUPLI)==0) {
|
||||
BKE_object_foreach_display_point(ob, ob->obmat, func_cb, user_data);
|
||||
}
|
||||
else {
|
||||
ListBase *lb;
|
||||
DupliObject *dob;
|
||||
|
||||
lb= object_duplilist(scene, ob);
|
||||
for(dob= lb->first; dob; dob= dob->next) {
|
||||
if(dob->no_draw == 0) {
|
||||
BKE_object_foreach_display_point(dob->ob, dob->mat, func_cb, user_data);
|
||||
}
|
||||
}
|
||||
free_object_duplilist(lb); /* does restore */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* copied from DNA_object_types.h */
|
||||
typedef struct ObTfmBack {
|
||||
float loc[3], dloc[3], orig[3];
|
||||
|
||||
@@ -155,7 +155,8 @@ void VIEW3D_OT_select_border(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_select_lasso(struct wmOperatorType *ot);
|
||||
|
||||
void VIEW3D_OT_smoothview(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_setcameratoview(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_camera_to_view(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_camera_to_view_selected(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_localview(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_game_start(struct wmOperatorType *ot);
|
||||
|
||||
@@ -85,7 +85,8 @@ void view3d_operatortypes(void)
|
||||
WM_operatortype_append(VIEW3D_OT_enable_manipulator);
|
||||
WM_operatortype_append(VIEW3D_OT_cursor3d);
|
||||
WM_operatortype_append(VIEW3D_OT_select_lasso);
|
||||
WM_operatortype_append(VIEW3D_OT_setcameratoview);
|
||||
WM_operatortype_append(VIEW3D_OT_camera_to_view);
|
||||
WM_operatortype_append(VIEW3D_OT_camera_to_view_selected);
|
||||
WM_operatortype_append(VIEW3D_OT_object_as_camera);
|
||||
WM_operatortype_append(VIEW3D_OT_localview);
|
||||
WM_operatortype_append(VIEW3D_OT_game_start);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_object.h"
|
||||
@@ -406,9 +407,8 @@ static int view3d_setcameratoview_poll(bContext *C)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VIEW3D_OT_setcameratoview(wmOperatorType *ot)
|
||||
void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
|
||||
{
|
||||
|
||||
/* identifiers */
|
||||
ot->name= "Align Camera To View";
|
||||
ot->description= "Set camera view to active view";
|
||||
@@ -422,6 +422,55 @@ void VIEW3D_OT_setcameratoview(wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* unlike VIEW3D_OT_view_selected this is for framing a render and not
|
||||
* meant to take into account vertex/bone selection for eg. */
|
||||
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
Object *camera_ob= v3d->camera;
|
||||
|
||||
float r_co[3]; /* the new location to apply */
|
||||
|
||||
/* this function does all the important stuff */
|
||||
if (camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co)) {
|
||||
|
||||
ObjectTfmProtectedChannels obtfm;
|
||||
float obmat_new[4][4];
|
||||
|
||||
copy_m4_m4(obmat_new, camera_ob->obmat);
|
||||
copy_v3_v3(obmat_new[3], r_co);
|
||||
|
||||
/* only touch location */
|
||||
object_tfm_protected_backup(camera_ob, &obtfm);
|
||||
object_apply_mat4(camera_ob, obmat_new, TRUE, TRUE);
|
||||
object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
|
||||
|
||||
/* notifiers */
|
||||
DAG_id_tag_update(&camera_ob->id, OB_RECALC_OB);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, camera_ob);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
}
|
||||
|
||||
void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Camera Fit Frame to Selected";
|
||||
ot->description= "Move the camera so selected objects are framed";
|
||||
ot->idname= "VIEW3D_OT_camera_to_view_selected";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= view3d_camera_to_view_selected_exec;
|
||||
// ot->poll= view3d_setcameratoview_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
|
||||
static int view3d_setobjectascamera_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
@@ -461,7 +510,7 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
|
||||
ot->idname= "VIEW3D_OT_object_as_camera";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec= view3d_setobjectascamera_exec;
|
||||
ot->exec= view3d_setobjectascamera_exec;
|
||||
ot->poll= ED_operator_rv3d_unlock_poll;
|
||||
|
||||
/* flags */
|
||||
|
||||
Reference in New Issue
Block a user