Authored by Sonny Campbell. Currently when importing a USD file, some of the camera properties are ignored, or the units are not converted correctly from USD world units. On import we currently set the focal length, but not the camera sensor size (horizontal and vertical aperture), so the camera field of view is wrong. The sensor size information is in the USD file, but is ignored for perspective cameras. USD uses "tenth of a world unit" scale for some physical camera properties like focal length and aperture. https://graphics.pixar.com/usd/release/api/class_usd_geom_camera.html#UsdGeom_CameraUnits I have added the UsdStage's metersPerUnit parameter to the ImportSettings so the camera can do the required conversion on import. This will convert from the USD file's world units to millimeters for Blender's camera settings. Reviewed by: Sybren and makowalski. Differential Revision: https://developer.blender.org/D16019
89 lines
3.1 KiB
C++
89 lines
3.1 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Adapted from the Blender Alembic importer implementation.
|
|
* Modifications Copyright 2021 Tangent Animation. All rights reserved. */
|
|
|
|
#include "usd_reader_camera.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "BKE_camera.h"
|
|
#include "BKE_object.h"
|
|
|
|
#include "BLI_math.h"
|
|
|
|
#include <pxr/pxr.h>
|
|
#include <pxr/usd/usdGeom/camera.h>
|
|
|
|
namespace blender::io::usd {
|
|
|
|
void USDCameraReader::create_object(Main *bmain, const double /* motionSampleTime */)
|
|
{
|
|
Camera *bcam = static_cast<Camera *>(BKE_camera_add(bmain, name_.c_str()));
|
|
|
|
object_ = BKE_object_add_only_object(bmain, OB_CAMERA, name_.c_str());
|
|
object_->data = bcam;
|
|
}
|
|
|
|
void USDCameraReader::read_object_data(Main *bmain, const double motionSampleTime)
|
|
{
|
|
Camera *bcam = (Camera *)object_->data;
|
|
|
|
pxr::UsdGeomCamera cam_prim(prim_);
|
|
|
|
if (!cam_prim) {
|
|
return;
|
|
}
|
|
|
|
pxr::VtValue val;
|
|
cam_prim.GetFocalLengthAttr().Get(&val, motionSampleTime);
|
|
pxr::VtValue verApOffset;
|
|
cam_prim.GetVerticalApertureOffsetAttr().Get(&verApOffset, motionSampleTime);
|
|
pxr::VtValue horApOffset;
|
|
cam_prim.GetHorizontalApertureOffsetAttr().Get(&horApOffset, motionSampleTime);
|
|
pxr::VtValue clippingRangeVal;
|
|
cam_prim.GetClippingRangeAttr().Get(&clippingRangeVal, motionSampleTime);
|
|
pxr::VtValue focalDistanceVal;
|
|
cam_prim.GetFocusDistanceAttr().Get(&focalDistanceVal, motionSampleTime);
|
|
pxr::VtValue fstopVal;
|
|
cam_prim.GetFStopAttr().Get(&fstopVal, motionSampleTime);
|
|
pxr::VtValue projectionVal;
|
|
cam_prim.GetProjectionAttr().Get(&projectionVal, motionSampleTime);
|
|
pxr::VtValue verAp;
|
|
cam_prim.GetVerticalApertureAttr().Get(&verAp, motionSampleTime);
|
|
pxr::VtValue horAp;
|
|
cam_prim.GetHorizontalApertureAttr().Get(&horAp, motionSampleTime);
|
|
|
|
/*
|
|
* For USD, these camera properties are in tenths of a world unit.
|
|
* https://graphics.pixar.com/usd/release/api/class_usd_geom_camera.html#UsdGeom_CameraUnits
|
|
* tenth_of_unit = stage_meters_per_unit / 10
|
|
* val_in_meters = val.Get<float>() * tenth_of_unit
|
|
* val_in_millimeters = val_in_meters * 1000
|
|
*/
|
|
const double scale_to_mm = 100.0 * settings_->stage_meters_per_unit;
|
|
bcam->lens = val.Get<float>() * scale_to_mm;
|
|
bcam->sensor_x = horAp.Get<float>() * scale_to_mm;
|
|
bcam->sensor_y = verAp.Get<float>() * scale_to_mm;
|
|
bcam->shiftx = verApOffset.Get<float>() * scale_to_mm;
|
|
bcam->shifty = horApOffset.Get<float>() * scale_to_mm;
|
|
|
|
bcam->type = (projectionVal.Get<pxr::TfToken>().GetString() == "perspective") ? CAM_PERSP :
|
|
CAM_ORTHO;
|
|
|
|
/* Calling UncheckedGet() to silence compiler warnings. */
|
|
bcam->clip_start = max_ff(0.1f, clippingRangeVal.UncheckedGet<pxr::GfVec2f>()[0]);
|
|
bcam->clip_end = clippingRangeVal.UncheckedGet<pxr::GfVec2f>()[1];
|
|
|
|
bcam->dof.focus_distance = focalDistanceVal.Get<float>();
|
|
bcam->dof.aperture_fstop = float(fstopVal.Get<float>());
|
|
|
|
if (bcam->type == CAM_ORTHO) {
|
|
bcam->ortho_scale = max_ff(verAp.Get<float>(), horAp.Get<float>());
|
|
}
|
|
|
|
USDXformReader::read_object_data(bmain, motionSampleTime);
|
|
}
|
|
|
|
} // namespace blender::io::usd
|