Skip to content

Commit

Permalink
UsdAppUtilsFrameRecorder::Record() now auto-frames the scene
Browse files Browse the repository at this point in the history
if a valid camera is not provided.

(Internal change: 1978265)
  • Loading branch information
blevin authored and pixar-oss committed Jun 5, 2019
1 parent e1381ba commit 3cca93e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 6 deletions.
59 changes: 53 additions & 6 deletions pxr/usdImaging/lib/usdAppUtils/frameRecorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@
#include "pxr/usd/sdf/path.h"
#include "pxr/usd/usd/prim.h"
#include "pxr/usd/usd/stage.h"
#include "pxr/usd/usdGeom/bboxCache.h"
#include "pxr/usd/usdGeom/camera.h"
#include "pxr/usd/usdGeom/metrics.h"
#include "pxr/usd/usdGeom/tokens.h"

#include <string>

Expand All @@ -60,6 +63,50 @@ UsdAppUtilsFrameRecorder::UsdAppUtilsFrameRecorder() :
_imagingEngine.SetEnableFloatPointDrawTarget(true);
}

static GfCamera
_ComputeCameraToFrameStage(const UsdStagePtr& stage, UsdTimeCode timeCode)
{
// Start with a default (50mm) perspective GfCamera.
GfCamera gfCamera;
TfTokenVector includedPurposes;
includedPurposes.push_back(UsdGeomTokens->default_);
includedPurposes.push_back(UsdGeomTokens->render);
UsdGeomBBoxCache bboxCache(timeCode, includedPurposes,
/* useExtentsHint = */ true);
GfBBox3d bbox = bboxCache.ComputeWorldBound(stage->GetPseudoRoot());
GfVec3d center = bbox.ComputeCentroid();
GfRange3d range = bbox.ComputeAlignedRange();
GfVec3d dim = range.GetSize();
TfToken upAxis = UsdGeomGetStageUpAxis(stage);
// Find corner of bbox in the focal plane.
GfVec2d plane_corner;
if (upAxis == UsdGeomTokens->y) {
plane_corner = GfVec2d(dim[0], dim[1])/2;
} else {
plane_corner = GfVec2d(dim[0], dim[2])/2;
}
float plane_radius = sqrt(GfDot(plane_corner, plane_corner));
// Compute distance to focal plane.
float half_fov = gfCamera.GetFieldOfView(GfCamera::FOVHorizontal)/2.0;
float distance = plane_radius / tan(GfDegreesToRadians(half_fov));
// Back up to frame the front face of the bbox.
if (upAxis == UsdGeomTokens->y) {
distance += dim[2] / 2;
} else {
distance += dim[1] / 2;
}
// Compute local-to-world transform for camera filmback.
GfMatrix4d xf;
if (upAxis == UsdGeomTokens->y) {
xf.SetTranslate(center + GfVec3d(0, 0, distance));
} else {
xf.SetRotate(GfRotation(GfVec3d(1,0,0), 90));
xf.SetTranslateOnly(center + GfVec3d(0, -distance, 0));
}
gfCamera.SetTransform(xf);
return gfCamera;
}

bool
UsdAppUtilsFrameRecorder::Record(
const UsdStagePtr& stage,
Expand All @@ -72,11 +119,6 @@ UsdAppUtilsFrameRecorder::Record(
return false;
}

if (!usdCamera) {
TF_CODING_ERROR("Invalid UsdGeomCamera");
return false;
}

if (outputImagePath.empty()) {
TF_CODING_ERROR("Invalid empty output image path");
return false;
Expand All @@ -88,7 +130,12 @@ UsdAppUtilsFrameRecorder::Record(

// XXX: If the camera's aspect ratio is animated, then a range of calls to
// this function may generate a sequence of images with different sizes.
const GfCamera gfCamera = usdCamera.GetCamera(timeCode);
GfCamera gfCamera;
if (usdCamera) {
gfCamera = usdCamera.GetCamera(timeCode);
} else {
gfCamera = _ComputeCameraToFrameStage(stage, timeCode);
}
float aspectRatio = gfCamera.GetAspectRatio();
if (GfIsClose(aspectRatio, 0.0f, 1e-4)) {
aspectRatio = 1.0f;
Expand Down
3 changes: 3 additions & 0 deletions pxr/usdImaging/lib/usdAppUtils/frameRecorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class UsdAppUtilsFrameRecorder
/// The recorded image will represent the view from \p usdCamera looking at
/// the imageable prims on USD stage \p stage at time \p timeCode.
///
/// If \p usdCamera is not a valid camera, a camera will be computed
/// to automatically frame the stage geometry.
///
/// Returns true if the image was generated and written successfully, or
/// false otherwise.
USDAPPUTILS_API
Expand Down

0 comments on commit 3cca93e

Please sign in to comment.