[Bf-blender-cvs] [b8e592bd77d] asset-metadata: Support object preview thumbnails, generated on asset creation

Julian Eisel noreply at git.blender.org
Sat Jul 4 15:16:42 CEST 2020


Commit: b8e592bd77daf1a142e758e17de626a40605dbc6
Author: Julian Eisel
Date:   Sat Jul 4 15:06:58 2020 +0200
Branches: asset-metadata
https://developer.blender.org/rBb8e592bd77daf1a142e758e17de626a40605dbc6

Support object preview thumbnails, generated on asset creation

To generate the preview, a temporary main data-base is created (think of this
as a virtual .blend within the current .blend) with a new scene and the object
to generate the preview for. It's rendered with a camera from the front, using
the "Camera Fit Frame to Selected" logic.
This should be a simple solution requiring no further setup that should work in
most cases. If needed we can have a way to set up the preview differently.

To see it in action:
* In the Outliner context menu for an object run ID Data > Create Asset
* Save the file
* Open a different file (so you can browse into the former)
* Use link/append to navigate into the saved file with the assets. You should
  see the preview in thumbnail mode.

===================================================================

M	source/blender/editors/include/ED_view3d.h
M	source/blender/editors/interface/interface_icons.c
M	source/blender/editors/render/render_preview.c
M	source/blender/editors/space_view3d/view3d_utils.c
M	source/blender/editors/space_view3d/view3d_view.c

===================================================================

diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 5e706856738..6a9b34a9b87 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -160,6 +160,11 @@ void ED_view3d_to_object(const struct Depsgraph *depsgraph,
                          const float quat[4],
                          const float dist);
 
+bool ED_view3d_camera_to_view_selected(struct Main *bmain,
+                                       struct Depsgraph *depsgraph,
+                                       const struct Scene *scene,
+                                       struct Object *camera_ob);
+
 void ED_view3d_lastview_store(struct RegionView3D *rv3d);
 
 /* Depth buffer */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 7411639a99f..f984db6dce9 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1988,12 +1988,7 @@ static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs)
   }
 
   for (i = 0; i < NUM_ICON_SIZES; i++) {
-    /* check if rect needs to be created; changed
-     * only set by dynamic icons */
-    if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) {
-      icon_set_image(C, NULL, id, pi, i, use_jobs);
-      pi->flag[i] &= ~PRV_CHANGED;
-    }
+    ui_id_preview_image_render_size(C, NULL, id, pi, i, use_jobs);
   }
 }
 
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 33d9e599473..3432a1895a0 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -68,6 +68,7 @@
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_node.h"
+#include "BKE_object.h"
 #include "BKE_scene.h"
 #include "BKE_texture.h"
 #include "BKE_world.h"
@@ -95,12 +96,16 @@
 #include "ED_datafiles.h"
 #include "ED_render.h"
 #include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_view3d_offscreen.h"
 
 #ifndef NDEBUG
 /* Used for database init assert(). */
 #  include "BLI_threads.h"
 #endif
 
+void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect);
+
 ImBuf *get_brush_icon(Brush *brush)
 {
   static const int flags = IB_rect | IB_multilayer | IB_metadata;
@@ -705,6 +710,135 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
   }
 }
 
+/* **************************** Object preview ****************** */
+
+struct ObjectPreviewData {
+  /* The main for the preview, not of the current file. */
+  Main *main;
+  /* The original object to create the preview for. */
+  Object *object;
+  int sizex;
+  int sizey;
+};
+
+static Object *object_preview_camera_create(Main *preview_main,
+                                            Scene *scene,
+                                            ViewLayer *view_layer,
+                                            Object *preview_object,
+                                            int sizex,
+                                            int sizey)
+{
+  Object *camera = BKE_object_add(preview_main, scene, view_layer, OB_CAMERA, "Preview Camera");
+
+  float rotmat[3][3];
+  float dummyscale[3];
+  mat4_to_loc_rot_size(camera->loc, rotmat, dummyscale, preview_object->obmat);
+
+  /* Camera is Y up, so needs additional 90deg rotation around X to match object's Z up. */
+  float drotmat[3][3];
+  axis_angle_to_mat3_single(drotmat, 'X', M_PI_2);
+  mul_m3_m3_post(rotmat, drotmat);
+
+  camera->rotmode = ROT_MODE_QUAT;
+  mat3_to_quat(camera->quat, rotmat);
+
+  /* shader_preview_render() does this too. */
+  if (sizex > sizey) {
+    ((Camera *)camera->data)->lens *= (float)sizey / (float)sizex;
+  }
+
+  return camera;
+}
+
+static Scene *object_preview_scene_create(const struct ObjectPreviewData *preview_data,
+                                          Depsgraph **r_depsgraph)
+{
+  Scene *scene = BKE_scene_add(preview_data->main, "Object preview scene");
+  ViewLayer *view_layer = scene->view_layers.first;
+  Depsgraph *depsgraph = DEG_graph_new(preview_data->main, scene, view_layer, DAG_EVAL_VIEWPORT);
+
+  /* FIXME For now just create a copy of the object for the new main, until we have a better way to
+   * obtain the ID in a different Main (i.e. read from asset file). */
+  Object *preview_object_copy;
+  if (!BKE_id_copy(preview_data->main, &preview_data->object->id, (ID **)&preview_object_copy)) {
+    BLI_assert(false);
+    return NULL;
+  }
+
+  BKE_collection_object_add(preview_data->main, scene->master_collection, preview_object_copy);
+
+  Object *camera_object = object_preview_camera_create(preview_data->main,
+                                                       scene,
+                                                       view_layer,
+                                                       preview_object_copy,
+                                                       preview_data->sizex,
+                                                       preview_data->sizey);
+
+  scene->camera = camera_object;
+  scene->r.xsch = preview_data->sizex;
+  scene->r.ysch = preview_data->sizey;
+  scene->r.size = 100;
+
+  Base *preview_base = BKE_view_layer_base_find(view_layer, preview_object_copy);
+  /* For 'view selected' below. */
+  preview_base->flag |= BASE_SELECTED;
+
+  DEG_graph_build_from_view_layer(depsgraph, preview_data->main, scene, view_layer);
+  DEG_evaluate_on_refresh(preview_data->main, depsgraph);
+
+  ED_view3d_camera_to_view_selected(preview_data->main, depsgraph, scene, camera_object);
+
+  BKE_scene_graph_update_tagged(depsgraph, preview_data->main);
+
+  *r_depsgraph = depsgraph;
+  return scene;
+}
+
+static void object_preview_render(IconPreview *preview, IconPreviewSize *preview_sized)
+{
+  Main *preview_main = BKE_main_new();
+  const float pixelsize_old = U.pixelsize;
+  char err_out[256] = "unknown";
+
+  struct ObjectPreviewData preview_data = {
+      .main = preview_main,
+      .object = (Object *)preview->id,
+      .sizex = preview_sized->sizex,
+      .sizey = preview_sized->sizey,
+  };
+  Depsgraph *depsgraph;
+  Scene *scene = object_preview_scene_create(&preview_data, &depsgraph);
+
+  U.pixelsize = 2.0f;
+
+  ImBuf *ibuf = ED_view3d_draw_offscreen_imbuf_simple(
+      depsgraph,
+      DEG_get_evaluated_scene(depsgraph),
+      NULL,
+      OB_SOLID,
+      DEG_get_evaluated_object(depsgraph, scene->camera),
+      preview_sized->sizex,
+      preview_sized->sizey,
+      IB_rect,
+      V3D_OFSDRAW_NONE,
+      R_ALPHAPREMUL,
+      NULL,
+      NULL,
+      err_out);
+  /* TODO color-management? */
+
+  U.pixelsize = pixelsize_old;
+
+  if (ibuf) {
+    icon_copy_rect(ibuf, preview_sized->sizex, preview_sized->sizey, preview_sized->rect);
+
+    IMB_freeImBuf(ibuf);
+  }
+
+  DEG_graph_free(depsgraph);
+  BKE_main_free(preview_main);
+}
+
 /* **************************** new shader preview system ****************** */
 
 /* inside thread, called by renderer, sets job update value */
@@ -1016,7 +1150,7 @@ static void shader_preview_free(void *customdata)
 
 /* ************************* icon preview ********************** */
 
-static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
+void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect)
 {
   struct ImBuf *ima;
   uint *drect, *srect;
@@ -1240,6 +1374,11 @@ static void icon_preview_startjob_all_sizes(void *customdata,
       continue;
     }
 
+    if (ELEM(GS(ip->id->name), ID_OB)) {
+      object_preview_render(ip, cur_size);
+      continue;
+    }
+
     ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
     const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
 
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 15d6a43d105..b3b47cd9e2c 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -1559,6 +1559,41 @@ void ED_view3d_to_object(const Depsgraph *depsgraph,
   BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true);
 }
 
+bool ED_view3d_camera_to_view_selected(struct Main *bmain,
+                                       Depsgraph *depsgraph,
+                                       const Scene *scene,
+                                       Object *camera_ob)
+{
+  Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
+  float co[3]; /* the new location to apply */
+  float scale; /* only for ortho cameras */
+
+  if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, co, &scale)) {
+    ObjectTfmProtectedChannels obtfm;
+    float obmat_new[4][4];
+
+    if ((camera_ob_eval->type == OB_CAMERA) &&
+        (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) {
+      ((Camera *)camera_ob->data)->ortho_scale = scale;
+    }
+
+    copy_m4_m4(obmat_new, camera_ob_eval->obmat);
+    copy_v3_v3(obmat_new[3], co);
+
+    /* only touch location */
+    BKE_object_tfm_protected_backup(camera_ob, &obtfm);
+    BKE_object_apply_mat4(camera_ob, obmat_new, true, true);
+    BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
+
+    /* notifiers */
+    DEG_id_tag_update_ex(bmain, &camera_ob->id, ID_RECALC_TRANSFORM);
+
+    return true;
+  }
+
+  return false;
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 3fc990160d2..20fb877af5b 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -531,40 +531,18 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
  * meant to take into account vertex/bone selection for eg. */
 static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
 {
+  Main *bmain = CTX_data_main(C);
   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
   Scene *scene = CTX_data_scene(C);
   View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
   Object *camera_ob = v3d ? v3d->camera : scen

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list