[Bf-blender-cvs] [d225331ac7d] sybren-usd: USD: Added exporting the camera

Sybren A. Stüvel noreply at git.blender.org
Fri Jul 5 18:11:26 CEST 2019


Commit: d225331ac7d72d87f56e7dc7711702b997fe847a
Author: Sybren A. Stüvel
Date:   Fri Jul 5 18:11:04 2019 +0200
Branches: sybren-usd
https://developer.blender.org/rBd225331ac7d72d87f56e7dc7711702b997fe847a

USD: Added exporting the camera

Only perspective cameras are supported for now. I also had to add a function
`BKE_camera_sensor_size_for_render()` that calculates the sensor width
or height, depending on the fitting parameter and the scene render
resolution aspect ratio.

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

M	source/blender/blenkernel/BKE_camera.h
M	source/blender/blenkernel/intern/camera.c
M	source/blender/usd/CMakeLists.txt
M	source/blender/usd/intern/usd_hierarchy_iterator.cc
M	source/blender/usd/intern/usd_writer_abstract.cc
M	source/blender/usd/intern/usd_writer_abstract.h
A	source/blender/usd/intern/usd_writer_camera.cc
A	source/blender/usd/intern/usd_writer_camera.h

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

diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index caed4959eff..b299f6831f5 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -61,6 +61,12 @@ float BKE_camera_object_dof_distance(struct Object *ob);
 int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey);
 float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y);
 
+/* Return the clamped sensor width/height for the given render data. */
+void BKE_camera_sensor_size_for_render(const struct Camera *camera,
+                                       const struct RenderData *rd,
+                                       float *r_sensor_x,
+                                       float *r_sensor_y);
+
 /* Camera Parameters:
  *
  * Intermediate struct for storing camera parameters from various sources,
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index a8f38c3c4ce..deb047d84f5 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -168,6 +168,32 @@ int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey)
   return sensor_fit;
 }
 
+void BKE_camera_sensor_size_for_render(const Camera *camera,
+                                       const struct RenderData *rd,
+                                       float *r_sensor_x,
+                                       float *r_sensor_y)
+{
+  /* Compute the final image size in pixels. */
+  float sizex = rd->xsch * rd->xasp;
+  float sizey = rd->ysch * rd->yasp;
+
+  int sensor_fit = BKE_camera_sensor_fit(camera->sensor_fit, sizex, sizey);
+
+  switch (sensor_fit) {
+    case CAMERA_SENSOR_FIT_HOR:
+      *r_sensor_x = camera->sensor_x;
+      *r_sensor_y = camera->sensor_x * sizey / sizex;
+      break;
+    case CAMERA_SENSOR_FIT_VERT:
+      *r_sensor_x = camera->sensor_y * sizex / sizey;
+      *r_sensor_y = camera->sensor_y;
+      break;
+    case CAMERA_SENSOR_FIT_AUTO:
+      BLI_assert(!"Camera fit should be either horizontal or vertical");
+      break;
+  }
+}
+
 /******************************** Camera Params *******************************/
 
 void BKE_camera_params_init(CameraParams *params)
diff --git a/source/blender/usd/CMakeLists.txt b/source/blender/usd/CMakeLists.txt
index 3694e85e3a2..3c76c95e31c 100644
--- a/source/blender/usd/CMakeLists.txt
+++ b/source/blender/usd/CMakeLists.txt
@@ -51,6 +51,7 @@ set(SRC
   intern/usd_capi.cc
   intern/usd_hierarchy_iterator.cc
   intern/usd_writer_abstract.cc
+  intern/usd_writer_camera.cc
   intern/usd_writer_hair.cc
   intern/usd_writer_mesh.cc
   intern/usd_writer_transform.cc
@@ -59,6 +60,7 @@ set(SRC
   intern/abstract_hierarchy_iterator.h
   intern/usd_hierarchy_iterator.h
   intern/usd_writer_abstract.h
+  intern/usd_writer_camera.h
   intern/usd_writer_hair.h
   intern/usd_writer_mesh.h
   intern/usd_writer_transform.h
diff --git a/source/blender/usd/intern/usd_hierarchy_iterator.cc b/source/blender/usd/intern/usd_hierarchy_iterator.cc
index de10a8e7e44..3cae06536a5 100644
--- a/source/blender/usd/intern/usd_hierarchy_iterator.cc
+++ b/source/blender/usd/intern/usd_hierarchy_iterator.cc
@@ -2,6 +2,7 @@
 
 #include "usd_hierarchy_iterator.h"
 #include "usd_writer_abstract.h"
+#include "usd_writer_camera.h"
 #include "usd_writer_hair.h"
 #include "usd_writer_mesh.h"
 #include "usd_writer_transform.h"
@@ -85,6 +86,9 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
     case OB_MESH:
       data_writer = new USDMeshWriter(usd_export_context);
       break;
+    case OB_CAMERA:
+      data_writer = new USDCameraWriter(usd_export_context);
+      break;
 
     case OB_EMPTY:
     case OB_CURVE:
@@ -92,7 +96,6 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
     case OB_FONT:
     case OB_MBALL:
     case OB_LAMP:
-    case OB_CAMERA:
     case OB_SPEAKER:
     case OB_LIGHTPROBE:
     case OB_LATTICE:
@@ -107,7 +110,7 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_data_writer(const Hierarch
       return nullptr;
   }
 
-  if (!data_writer->is_supported()) {
+  if (!data_writer->is_supported(context.object)) {
     // printf("USD-\033[34mXFORM-ONLY\033[0m object %s  type=%d (data writer rejects the data)\n",
     //        context.object->id.name,
     //        context.object->type);
diff --git a/source/blender/usd/intern/usd_writer_abstract.cc b/source/blender/usd/intern/usd_writer_abstract.cc
index 793ff7c1ed7..6c2787f7384 100644
--- a/source/blender/usd/intern/usd_writer_abstract.cc
+++ b/source/blender/usd/intern/usd_writer_abstract.cc
@@ -25,7 +25,7 @@ USDAbstractWriter::~USDAbstractWriter()
 {
 }
 
-bool USDAbstractWriter::is_supported() const
+bool USDAbstractWriter::is_supported(const Object * /*object*/) const
 {
   return true;
 }
diff --git a/source/blender/usd/intern/usd_writer_abstract.h b/source/blender/usd/intern/usd_writer_abstract.h
index 3e2feb3faf9..667baf0dc43 100644
--- a/source/blender/usd/intern/usd_writer_abstract.h
+++ b/source/blender/usd/intern/usd_writer_abstract.h
@@ -37,7 +37,7 @@ class USDAbstractWriter : public AbstractHierarchyWriter {
 
   /* Returns true iff the data to be written is actually supported. This would, for example, allow
    * a hypothetical camera writer accept a perspective camera but reject an orthogonal one. */
-  virtual bool is_supported() const;
+  virtual bool is_supported(const Object *object) const;
 
   const pxr::SdfPath &usd_path() const;
 
diff --git a/source/blender/usd/intern/usd_writer_camera.cc b/source/blender/usd/intern/usd_writer_camera.cc
new file mode 100644
index 00000000000..4fe52deb664
--- /dev/null
+++ b/source/blender/usd/intern/usd_writer_camera.cc
@@ -0,0 +1,61 @@
+#include "usd_writer_camera.h"
+#include "usd_hierarchy_iterator.h"
+
+#include <pxr/usd/usdGeom/camera.h>
+#include <pxr/usd/usdGeom/tokens.h>
+
+extern "C" {
+#include "BKE_camera.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_scene_types.h"
+}
+
+USDCameraWriter::USDCameraWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx)
+{
+}
+
+bool USDCameraWriter::is_supported(const Object *object) const
+{
+  Camera *camera = static_cast<Camera *>(object->data);
+  return camera->type == CAM_PERSP;
+}
+
+void USDCameraWriter::do_write(HierarchyContext &context)
+{
+  pxr::UsdTimeCode timecode = get_export_time_code();
+  pxr::UsdGeomCamera usd_camera = pxr::UsdGeomCamera::Define(stage, usd_path_);
+
+  Camera *camera = static_cast<Camera *>(context.object->data);
+  Scene *scene = DEG_get_evaluated_scene(depsgraph);
+
+  usd_camera.CreateProjectionAttr().Set(pxr::UsdGeomTokens->perspective);
+
+  /* USD stores the focal length in "millimeters or tenths of world units", because at some point
+   * they decided world units might be centimeters. Quite confusing, as the USD Viewer shows the
+   * correct FoV when we write millimeters and not "tenths of world units".
+   */
+  usd_camera.CreateFocalLengthAttr().Set(camera->lens, timecode);
+
+  float aperture_x, aperture_y;
+  BKE_camera_sensor_size_for_render(camera, &scene->r, &aperture_x, &aperture_y);
+
+  float film_aspect = aperture_x / aperture_y;
+  usd_camera.CreateHorizontalApertureAttr().Set(aperture_x, timecode);
+  usd_camera.CreateVerticalApertureAttr().Set(aperture_y, timecode);
+  usd_camera.CreateHorizontalApertureOffsetAttr().Set(aperture_x * camera->shiftx, timecode);
+  usd_camera.CreateVerticalApertureOffsetAttr().Set(aperture_y * camera->shifty * film_aspect,
+                                                    timecode);
+
+  usd_camera.CreateClippingRangeAttr().Set(
+      pxr::VtValue(pxr::GfVec2f(camera->clip_start, camera->clip_end)), timecode);
+
+  // Write DoF-related attributes.
+  if (camera->dof.flag & CAM_DOF_ENABLED) {
+    usd_camera.CreateFStopAttr().Set(camera->dof.aperture_fstop, timecode);
+
+    float focus_distance = scene->unit.scale_length *
+                           BKE_camera_object_dof_distance(context.object);
+    usd_camera.CreateFocusDistanceAttr().Set(focus_distance, timecode);
+  }
+}
diff --git a/source/blender/usd/intern/usd_writer_camera.h b/source/blender/usd/intern/usd_writer_camera.h
new file mode 100644
index 00000000000..b5fb8074c1f
--- /dev/null
+++ b/source/blender/usd/intern/usd_writer_camera.h
@@ -0,0 +1,16 @@
+#ifndef __USD__USD_WRITER_CAMERA_H__
+#define __USD__USD_WRITER_CAMERA_H__
+
+#include "usd_writer_abstract.h"
+
+/* Writer for writing camera data to UsdGeomCamera. */
+class USDCameraWriter : public USDAbstractWriter {
+ public:
+  USDCameraWriter(const USDExporterContext &ctx);
+
+ protected:
+  virtual bool is_supported(const Object *object) const override;
+  virtual void do_write(HierarchyContext &context) override;
+};
+
+#endif /* __USD__USD_WRITER_CAMERA_H__ */



More information about the Bf-blender-cvs mailing list