diff --git a/lib/mayaHydra/hydraExtensions/adapters/cameraAdapter.cpp b/lib/mayaHydra/hydraExtensions/adapters/cameraAdapter.cpp index d1ffaedae..c6ae3a24c 100644 --- a/lib/mayaHydra/hydraExtensions/adapters/cameraAdapter.cpp +++ b/lib/mayaHydra/hydraExtensions/adapters/cameraAdapter.cpp @@ -25,6 +25,9 @@ #include #include +#include +#include +#include #include PXR_NAMESPACE_OPEN_SCOPE @@ -130,48 +133,22 @@ VtValue MayaHydraCameraAdapter::Get(const TfToken& key) { return MayaHydraShapeA VtValue MayaHydraCameraAdapter::GetCameraParamValue(const TfToken& paramName) { - constexpr double mayaInchToHydraCentimeter = 0.254; - constexpr double mayaInchToHydraMillimeter = 0.0254; - constexpr double mayaFocaLenToHydra = 0.01; + constexpr double inchToMM = 25.4; MStatus status; auto convertFit = [&](const MFnCamera& camera) -> CameraUtilConformWindowPolicy { const auto mayaFit = camera.filmFit(&status); - if (mayaFit == MFnCamera::kHorizontalFilmFit) - return CameraUtilConformWindowPolicy::CameraUtilMatchHorizontally; - if (mayaFit == MFnCamera::kVerticalFilmFit) - return CameraUtilConformWindowPolicy::CameraUtilMatchVertically; - - const auto fitMatcher = camera.horizontalFilmAperture() > camera.verticalFilmAperture() - ? MFnCamera::kOverscanFilmFit - : MFnCamera::kFillFilmFit; - return mayaFit == fitMatcher ? CameraUtilConformWindowPolicy::CameraUtilMatchHorizontally - : CameraUtilConformWindowPolicy::CameraUtilMatchVertically; - }; - - auto apertureConvert = [&](const MFnCamera& camera, double glApertureX, double glApertureY) { - const auto usdFit = convertFit(camera); - const double aperture = usdFit == CameraUtilConformWindowPolicy::CameraUtilMatchHorizontally - ? camera.horizontalFilmAperture() - : camera.verticalFilmAperture(); - const double glAperture - = usdFit == CameraUtilConformWindowPolicy::CameraUtilMatchHorizontally ? glApertureX - : glApertureY; - return (0.02 / aperture) * (aperture / glAperture); - }; - - auto viewParameters = [&](const MFnCamera& camera, - const GfVec4d* viewport, - double& apertureX, - double& apertureY, - double& offsetX, - double& offsetY) -> MStatus { - double aspectRatio = viewport - ? ((*viewport)[2] - (*viewport)[0]) / ((*viewport)[3] - (*viewport)[1]) - : camera.aspectRatio(); - return camera.getViewParameters( - aspectRatio, apertureX, apertureY, offsetX, offsetY, true, false, true); + switch (mayaFit) { + case MFnCamera::kFillFilmFit: + return CameraUtilConformWindowPolicy::CameraUtilCrop; + case MFnCamera::kHorizontalFilmFit: + return CameraUtilConformWindowPolicy::CameraUtilMatchHorizontally; + case MFnCamera::kVerticalFilmFit: + return CameraUtilConformWindowPolicy::CameraUtilMatchVertically; + default: + return CameraUtilConformWindowPolicy::CameraUtilFit; + } }; auto hadError = [&](MStatus& status) -> bool { @@ -220,23 +197,13 @@ VtValue MayaHydraCameraAdapter::GetCameraParamValue(const TfToken& paramName) auto focusDistance = camera.focusDistance(&status); if (hadError(status)) return {}; - return VtValue(float(focusDistance * mayaInchToHydraCentimeter)); + return VtValue(float(focusDistance)); } if (paramName == HdCameraTokens->focalLength) { - const double aspectRatio = _viewport - ? (((*_viewport)[2] - (*_viewport)[0]) / ((*_viewport)[3] - (*_viewport)[1])) - : camera.aspectRatio(); - - double left, right, bottom, top; - status = camera.getViewingFrustum(aspectRatio, left, right, bottom, top, true, false, true); - - const double cameraNear = camera.nearClippingPlane(); - - const double focalLen - = (convertFit(camera) == CameraUtilConformWindowPolicy::CameraUtilMatchVertically) - ? (2.0 * cameraNear) / (top - bottom) - : (2.0 * cameraNear) / (right - left); - return VtValue(float(focalLen * mayaFocaLenToHydra)); + auto focalLength = camera.focalLength(&status); + if (hadError(status)) + return {}; + return VtValue(float(focalLength)); /// focalLength is in mm, so no conversion needed } if (paramName == HdCameraTokens->clippingRange) { const double cameraNear = camera.nearClippingPlane(); @@ -253,32 +220,35 @@ VtValue MayaHydraCameraAdapter::GetCameraParamValue(const TfToken& paramName) return VtValue(float(fStop)); } if (paramName == HdCameraTokens->horizontalAperture) { - double apertureX, apertureY, offsetX, offsetY; - status = viewParameters(camera, _viewport.get(), apertureX, apertureY, offsetX, offsetY); + // Lens squeeze ratio applies horizontally only. + const double horizontalAperture = camera.horizontalFilmAperture(&status) * camera.lensSqueezeRatio(&status); if (hadError(status)) return {}; - return VtValue(float(apertureX * apertureConvert(camera, apertureX, apertureY))); + return VtValue(float(horizontalAperture * inchToMM)); } if (paramName == HdCameraTokens->verticalAperture) { - double apertureX, apertureY, offsetX, offsetY; - status = viewParameters(camera, _viewport.get(), apertureX, apertureY, offsetX, offsetY); + const double verticalAperture = camera.verticalFilmAperture(); if (hadError(status)) return {}; - return VtValue(float(apertureY * apertureConvert(camera, apertureX, apertureY))); + return VtValue(float(verticalAperture * inchToMM)); } if (paramName == HdCameraTokens->horizontalApertureOffset) { - double apertureX, apertureY, offsetX, offsetY; - status = viewParameters(camera, _viewport.get(), apertureX, apertureY, offsetX, offsetY); + // Film offset and shake (when enabled) have the same effect on film back + const double horizontalApertureOffset = + (camera.shakeEnabled(&status) ? camera.horizontalFilmOffset(&status) + camera.horizontalShake(&status) + : camera.horizontalFilmOffset(&status)); if (hadError(status)) return {}; - return VtValue(float(offsetX * mayaInchToHydraMillimeter)); + return VtValue(float(horizontalApertureOffset * inchToMM)); } if (paramName == HdCameraTokens->verticalApertureOffset) { - double apertureX, apertureY, offsetX, offsetY; - status = viewParameters(camera, _viewport.get(), apertureX, apertureY, offsetX, offsetY); + // Film offset and shake (when enabled) have the same effect on film back + const double verticalApertureOffset = + (camera.shakeEnabled(&status) ? camera.verticalFilmOffset(&status) + camera.verticalShake(&status) + : camera.verticalFilmOffset(&status)); if (hadError(status)) return {}; - return VtValue(float(offsetY * mayaInchToHydraMillimeter)); + return VtValue(float(verticalApertureOffset * inchToMM)); } if (paramName == HdCameraTokens->windowPolicy) { const auto windowPolicy = convertFit(camera); @@ -293,7 +263,66 @@ VtValue MayaHydraCameraAdapter::GetCameraParamValue(const TfToken& paramName) return VtValue(HdCamera::Perspective); } } - + // Look for requested parameter as camera attribute + auto plug = camera.findPlug(paramName.GetText(), true); + if (plug.isNull()) + return {}; + MObject attribute = plug.attribute(); + if ( attribute.hasFn( MFn::kNumericAttribute ) ) { + MFnNumericAttribute fnAttrib(attribute); + switch(fnAttrib.unitType()) + { + case MFnNumericData::kBoolean: { + bool value; + plug.getValue(value); + return VtValue(value); + } + case MFnNumericData::kInt: { + int value; + plug.getValue(value); + return VtValue(value); + } + case MFnNumericData::kFloat: { + float value; + plug.getValue(value); + return VtValue(value); + } + case MFnNumericData::kDouble:{ + double value; + plug.getValue(value); + return VtValue(value); + } + default: { + TF_WARN( + "Unsupported numeric attribute type %d for '%s' at %s\n", + static_cast(fnAttrib.unitType()), paramName.GetText(), GetID().GetText()); + break; + } + } + } + else if (attribute.hasFn(MFn::kTypedAttribute)) { + MFnTypedAttribute fnAttrib(attribute); + switch (fnAttrib.attrType()) { + case MFnData::kString: { + MString value; + plug.getValue(value); + return VtValue(std::string(value.asChar())); + } + default: + TF_WARN( + "Unsupported typed attribute type %d for '%s' at %s\n", + static_cast(fnAttrib.attrType()), paramName.GetText(), GetID().GetText()); + break; + } + } else if (attribute.hasFn(MFn::kEnumAttribute)) { + MFnEnumAttribute fnEnumAttrib(attribute); + const auto value = fnEnumAttrib.fieldName(plug.asShort()); + return VtValue(TfToken(value.asChar())); + } else { + TF_WARN( + "Unsupported attribute type for camera parameter '%s' at %s\n", + paramName.GetText(), GetID().GetText()); + } return {}; }