#include "hdPrman/context.h"
#include "hdPrman/coordSys.h"
#include "hdPrman/debugCodes.h"
#include "hdPrman/material.h"
#include "hdPrman/renderDelegate.h"
#include "hdPrman/rixStrings.h"
#include "pxr/base/arch/fileSystem.h"
#include "pxr/base/tf/stringUtils.h"
#include "pxr/base/tf/getenv.h"
#include "pxr/base/gf/matrix4d.h"
#include "pxr/base/gf/matrix4f.h"
#include "pxr/base/gf/vec2f.h"
#include "pxr/base/gf/vec3f.h"
#include "pxr/base/gf/vec4f.h"
#include "pxr/usd/sdf/path.h"
#include "pxr/imaging/hd/extComputationUtils.h"
#include "pxr/imaging/hd/sceneDelegate.h"
#include "pxr/base/plug/registry.h"
#include "pxr/base/plug/plugin.h"
#include "pxr/base/tf/debug.h"
#include "pxr/usd/sdr/registry.h"
#include "Riley.h"
#include "RtParamList.h"
#include "RixRiCtl.h"
#include "RixShadingUtils.h"
#include "RixPredefinedStrings.hpp"
PXR_NAMESPACE_OPEN_SCOPE
HdPrman_Context::HdPrman_Context() :
rix(nullptr),
ri(nullptr),
mgr(nullptr),
riley(nullptr),
_instantaneousShutter(false)
{
}
void
HdPrman_Context::IncrementLightLinkCount(TfToken const& name)
{
std::lock_guard<std::mutex> lock(_lightLinkMutex);
++_lightLinkRefs[name];
}
void
HdPrman_Context::DecrementLightLinkCount(TfToken const& name)
{
std::lock_guard<std::mutex> lock(_lightLinkMutex);
if (--_lightLinkRefs[name] == 0) {
_lightLinkRefs.erase(name);
}
}
bool
HdPrman_Context::IsLightLinkUsed(TfToken const& name)
{
std::lock_guard<std::mutex> lock(_lightLinkMutex);
return _lightLinkRefs.find(name) != _lightLinkRefs.end();
}
bool
HdPrman_Context::IsShutterInstantaneous() const
{
return _instantaneousShutter;
}
void
HdPrman_Context::SetInstantaneousShutter(bool instantaneousShutter)
{
_instantaneousShutter = instantaneousShutter;
}
void
HdPrman_Context::IncrementLightFilterCount(TfToken const& name)
{
std::lock_guard<std::mutex> lock(_lightFilterMutex);
++_lightFilterRefs[name];
}
void
HdPrman_Context::DecrementLightFilterCount(TfToken const& name)
{
std::lock_guard<std::mutex> lock(_lightFilterMutex);
if (--_lightFilterRefs[name] == 0) {
_lightFilterRefs.erase(name);
}
}
bool
HdPrman_Context::IsLightFilterUsed(TfToken const& name)
{
std::lock_guard<std::mutex> lock(_lightFilterMutex);
return _lightFilterRefs.find(name) != _lightFilterRefs.end();
}
inline static RtDetailType
_RixDetailForHdInterpolation(HdInterpolation interp)
{
switch (interp) {
case HdInterpolationInstance:
return RtDetailType::k_constant;
case HdInterpolationConstant:
return RtDetailType::k_constant;
case HdInterpolationUniform:
return RtDetailType::k_uniform;
case HdInterpolationVertex:
return RtDetailType::k_vertex;
case HdInterpolationVarying:
return RtDetailType::k_varying;
case HdInterpolationFaceVarying:
return RtDetailType::k_facevarying;
default:
TF_CODING_ERROR("Unknown HdInterpolation value");
return RtDetailType::k_constant;
}
}
enum _ParamType {
_ParamTypePrimvar,
_ParamTypeAttribute,
};
static bool
_SetParamValue(RtUString const& name,
VtValue const& val,
RtDetailType const& detail,
TfToken const& role,
RtParamList& params)
{
if (val.IsHolding<float>()) {
float v = val.UncheckedGet<float>();
params.SetFloat(name, v);
} else if (val.IsHolding<double>()) {
double v = val.UncheckedGet<double>();
params.SetFloat(name, static_cast<float>(v));
} else if (val.IsHolding<VtArray<float>>()) {
const VtArray<float>& v = val.UncheckedGet<VtArray<float>>();
if (detail == RtDetailType::k_constant) {
params.SetFloatArray(name, v.cdata(), v.size());
} else {
params.SetFloatDetail(name, v.cdata(), detail);
}
} else if (val.IsHolding<VtArray<double>>()) {
const VtArray<double>& vd = val.UncheckedGet<VtArray<double>>();
VtArray<float> v;
v.resize(vd.size());
for (size_t i=0,n=vd.size(); i<n; ++i) {
v[i] = float(vd[i]);
}
if (detail == RtDetailType::k_constant) {
params.SetFloatArray(name, v.cdata(), v.size());
} else {
params.SetFloatDetail(name, v.cdata(), detail);
}
} else if (val.IsHolding<int>()) {
int v = val.UncheckedGet<int>();
params.SetInteger(name, v);
} else if (val.IsHolding<VtArray<int>>()) {
const VtArray<int>& v = val.UncheckedGet<VtArray<int>>();
if (detail == RtDetailType::k_constant) {
params.SetIntegerArray(name, v.cdata(), v.size());
} else {
params.SetIntegerDetail(name, v.cdata(), detail);
}
} else if (val.IsHolding<long>()) {
long v = val.UncheckedGet<long>();
params.SetInteger(name, (int)v);
} else if (val.IsHolding<long long>()) {
long long v = val.UncheckedGet<long long>();
params.SetInteger(name, (int)v);
} else if (val.IsHolding<GfVec2i>()) {
GfVec2i v = val.UncheckedGet<GfVec2i>();
params.SetIntegerArray(
name, reinterpret_cast<const int*>(&v), 2);
} else if (val.IsHolding<GfVec2f>()) {
GfVec2f v = val.UncheckedGet<GfVec2f>();
params.SetFloatArray(
name, reinterpret_cast<const float*>(&v), 2);
} else if (val.IsHolding<VtArray<GfVec2f>>()) {
const VtArray<GfVec2f>& v = val.UncheckedGet<VtArray<GfVec2f>>();
params.SetFloatArrayDetail(name,
reinterpret_cast<const float*>(v.cdata()), 2, detail);
} else if (val.IsHolding<GfVec2d>()) {
GfVec2d vd = val.UncheckedGet<GfVec2d>();
float v[2] = {float(vd[0]), float(vd[1])};
params.SetFloatArray(name, v, 2);
} else if (val.IsHolding<VtArray<GfVec2d>>()) {
const VtArray<GfVec2d>& vd = val.UncheckedGet<VtArray<GfVec2d>>();
VtArray<GfVec2f> v;
v.resize(vd.size());
for (size_t i=0,n=vd.size(); i<n; ++i) {
v[i] = GfVec2f(vd[i]);
}
params.SetFloatArrayDetail(name,
reinterpret_cast<const float*>(v.cdata()), 2, detail);
} else if (val.IsHolding<GfVec3f>()) {
GfVec3f v = val.UncheckedGet<GfVec3f>();
if (role == HdPrimvarRoleTokens->color) {
params.SetColor(name, RtColorRGB(v[0], v[1], v[2]));
} else if (role == HdPrimvarRoleTokens->point) {
params.SetPoint(name, RtPoint3(v[0], v[1], v[2]));
} else if (role == HdPrimvarRoleTokens->normal) {
params.SetPoint(name, RtNormal3(v[0], v[1], v[2]));
} else if (role == HdPrimvarRoleTokens->vector) {
params.SetVector(name, RtVector3(v[0], v[1], v[2]));
} else {
params.SetFloatArray(name,
reinterpret_cast<const float*>(&v), 3);
}
} else if (val.IsHolding<VtArray<GfVec3f>>()) {
const VtArray<GfVec3f>& v = val.UncheckedGet<VtArray<GfVec3f>>();
if (role == HdPrimvarRoleTokens->color) {
params.SetColorDetail(
name, reinterpret_cast<const RtColorRGB*>(v.cdata()),
detail);
} else if (role == HdPrimvarRoleTokens->point) {
params.SetPointDetail(
name, reinterpret_cast<const RtPoint3*>(v.cdata()),
detail);
} else if (role == HdPrimvarRoleTokens->normal) {
params.SetNormalDetail(
name, reinterpret_cast<const RtNormal3*>(v.cdata()),
detail);
} else if (role == HdPrimvarRoleTokens->vector) {
params.SetVectorDetail(
name, reinterpret_cast<const RtVector3*>(v.cdata()),
detail);
} else {
params.SetFloatArrayDetail(
name, reinterpret_cast<const float*>(v.cdata()),
3, detail);
}
} else if (val.IsHolding<GfVec3d>()) {
GfVec3f v(val.UncheckedGet<GfVec3d>());
if (role == HdPrimvarRoleTokens->color) {
params.SetColor(name, RtColorRGB(v[0], v[1], v[2]));
} else if (role == HdPrimvarRoleTokens->point) {
params.SetPoint(name, RtPoint3(v[0], v[1], v[2]));
} else if (role == HdPrimvarRoleTokens->normal) {
params.SetPoint(name, RtNormal3(v[0], v[1], v[2]));
} else if (role == HdPrimvarRoleTokens->vector) {
params.SetVector(name, RtVector3(v[0], v[1], v[2]));
} else {
params.SetFloatArray(name,
reinterpret_cast<const float*>(&v), 3);
}
} else if (val.IsHolding<VtArray<GfVec3d>>()) {
const VtArray<GfVec3d>& vd = val.UncheckedGet<VtArray<GfVec3d>>();
VtArray<GfVec3f> v;
v.resize(vd.size());
for (size_t i=0,n=vd.size(); i<n; ++i) {
v[i] = GfVec3f(vd[i]);
}
if (role == HdPrimvarRoleTokens->color) {
params.SetColorDetail(
name, reinterpret_cast<const RtColorRGB*>(v.cdata()),
detail);
} else if (role == HdPrimvarRoleTokens->point) {
params.SetPointDetail(
name, reinterpret_cast<const RtPoint3*>(v.cdata()),
detail);
} else if (role == HdPrimvarRoleTokens->normal) {
params.SetNormalDetail(
name, reinterpret_cast<const RtNormal3*>(v.cdata()),
detail);
} else if (role == HdPrimvarRoleTokens->vector) {
params.SetVectorDetail(
name, reinterpret_cast<const RtVector3*>(v.cdata()),
detail);
} else {
params.SetFloatArrayDetail(
name, reinterpret_cast<const float*>(v.cdata()),
3, detail);
}
} else if (val.IsHolding<GfVec4f>()) {
GfVec4f v = val.UncheckedGet<GfVec4f>();
params.SetFloatArray(
name, reinterpret_cast<const float*>(&v), 4);
} else if (val.IsHolding<VtArray<GfVec4f>>()) {
const VtArray<GfVec4f>& v = val.UncheckedGet<VtArray<GfVec4f>>();
params.SetFloatArrayDetail(
name, reinterpret_cast<const float*>(v.cdata()), 4, detail);
} else if (val.IsHolding<GfVec4d>()) {
GfVec4f v(val.UncheckedGet<GfVec4d>());
params.SetFloatArray(
name, reinterpret_cast<const float*>(&v), 4);
} else if (val.IsHolding<VtArray<GfVec4d>>()) {
const VtArray<GfVec4d>& vd = val.UncheckedGet<VtArray<GfVec4d>>();
VtArray<GfVec4f> v;
v.resize(vd.size());
for (size_t i=0,n=vd.size(); i<n; ++i) {
v[i] = GfVec4f(vd[i]);
}
params.SetFloatArrayDetail(
name, reinterpret_cast<const float*>(v.cdata()), 4, detail);
} else if (val.IsHolding<GfMatrix4d>()) {
GfMatrix4d v = val.UncheckedGet<GfMatrix4d>();
params.SetMatrix(name, HdPrman_GfMatrixToRtMatrix(v));
} else if (val.IsHolding<int>()) {
int v = val.UncheckedGet<int>();
params.SetInteger(name, v);
} else if (val.IsHolding<VtArray<int>>()) {
const VtArray<int>& v = val.UncheckedGet<VtArray<int>>();
params.SetIntegerArrayDetail(
name, reinterpret_cast<const int*>(v.cdata()), 1, detail);
} else if (val.IsHolding<bool>()) {
int v = val.UncheckedGet<bool>();
params.SetInteger(name, v);
} else if (val.IsHolding<VtArray<bool>>()) {
const VtArray<bool>& vb = val.UncheckedGet<VtArray<bool>>();
VtArray<int> v;
v.resize(vb.size());
for (size_t i=0,n=vb.size(); i<n; ++i) {
v[i] = int(vb[i]);
}
params.SetIntegerArrayDetail(
name, reinterpret_cast<const int*>(v.cdata()), 1, detail);
} else if (val.IsHolding<TfToken>()) {
TfToken v = val.UncheckedGet<TfToken>();
params.SetString(name, RtUString(v.GetText()));
} else if (val.IsHolding<std::string>()) {
std::string v = val.UncheckedGet<std::string>();
params.SetString(name, RtUString(v.c_str()));
} else if (val.IsHolding<VtArray<std::string>>()) {
const VtArray<std::string>& v =
val.UncheckedGet<VtArray<std::string>>();
std::vector<RtUString> us;
us.reserve(v.size());
for (std::string const& s: v) {
us.push_back(RtUString(s.c_str()));
}
if (detail == RtDetailType::k_constant) {
params.SetStringArray(name, &us[0], us.size());
} else {
params.SetStringDetail(name, &us[0], detail);
}
} else if (val.IsHolding<VtArray<TfToken>>()) {
const VtArray<TfToken>& v =
val.UncheckedGet<VtArray<TfToken>>();
std::vector<RtUString> us;
us.reserve(v.size());
for (TfToken const& s: v) {
us.push_back(RtUString(s.GetText()));
}
if (detail == RtDetailType::k_constant) {
params.SetStringArray(name, &us[0], us.size());
} else {
params.SetStringDetail(name, &us[0], detail);
}
} else {
return false;
}
return true;
}
static RtUString
_GetPrmanPrimvarName(TfToken const& hdPrimvarName,
RtDetailType const& )
{
if (hdPrimvarName == HdTokens->points) {
return RixStr.k_P;
} else if (hdPrimvarName == HdTokens->normals) {
return RixStr.k_N;
} else if (hdPrimvarName == HdTokens->widths) {
return RixStr.k_width;
}
return RtUString(hdPrimvarName.GetText());
}
static HdExtComputationPrimvarDescriptorVector
_GetComputedPrimvars(HdSceneDelegate* sceneDelegate,
SdfPath const& id,
HdInterpolation interp,
HdDirtyBits dirtyBits)
{
HdExtComputationPrimvarDescriptorVector dirtyCompPrimvars;
HdExtComputationPrimvarDescriptorVector compPrimvars;
compPrimvars = sceneDelegate->GetExtComputationPrimvarDescriptors
(id,interp);
for (auto const& pv: compPrimvars) {
if (HdChangeTracker::IsPrimvarDirty(dirtyBits, id, pv.name)) {
dirtyCompPrimvars.emplace_back(pv);
}
}
return dirtyCompPrimvars;
}
static bool
_IsMasterAttribute(TfToken const& primvarName)
{
typedef std::unordered_set<TfToken, TfToken::HashFunctor> TfTokenSet;
static const TfTokenSet masterAttributes = {
TfToken("ri:attributes:identifier:object"),
TfToken("ri:attributes:derivatives:extrapolate"),
TfToken("ri:attributes:displacement:ignorereferenceinstance"),
TfToken("ri:attributes:displacementbound:CoordinateSystem"),
TfToken("ri:attributes:displacementbound:offscreen"),
TfToken("ri:attributes:displacementbound:sphere"),
TfToken("ri:attributes:Ri:Orientation"),
TfToken("ri:attributes:trace:autobias"),
TfToken("ri:attributes:trace:bias"),
TfToken("ri:attributes:trace:displacements"),
TfToken("ri:attributes:dice:micropolygonlength"),
TfToken("ri:attributes:dice:offscreenstrategy"),
TfToken("ri:attributes:dice:rasterorient"),
TfToken("ri:attributes:dice:referencecamera"),
TfToken("ri:attributes:dice:referenceinstance"),
TfToken("ri:attributes:dice:strategy"),
TfToken("ri:attributes:dice:worlddistancelength"),
TfToken("ri:attributes:Ri:GeometricApproximationFocusFactor"),
TfToken("ri:attributes:Ri:GeometricApproximationMotionFactor"),
TfToken("ri:attributes:falloffpower"),
TfToken("ri:attributes:dice:minlength"),
TfToken("ri:attributes:dice:minlengthspace"),
TfToken("ri:attributes:Ri:Bound"),
TfToken("ri:attributes:volume:dsominmax"),
TfToken("ri:attributes:dice:pretessellate"),
TfToken("ri:attributes:dice:watertight"),
TfToken("ri:attributes:shade:faceset"),
TfToken("ri:attributes:stitchbound:CoordinateSystem"),
TfToken("ri:attributes:stitchbound:sphere"),
TfToken("ri:attributes:trimcurve:sense"),
TfToken("ri:attributes:polygon:concave"),
TfToken("ri:attributes:polygon:smoothdisplacement"),
TfToken("ri:attributes:polygon:smoothnormals"),
TfToken("ri:attributes:procedural:immediatesubdivide"),
TfToken("ri:attributes:procedural:reentrant")
};
return masterAttributes.count(primvarName) > 0;
}
static void
_Convert(HdSceneDelegate *sceneDelegate, SdfPath const& id,
HdInterpolation hdInterp, RtParamList& params,
_ParamType paramType, int expectedSize)
{
const char* label =
(paramType == _ParamTypePrimvar) ? "primvar" : "attribute";
const RtDetailType detail = _RixDetailForHdInterpolation(hdInterp);
TF_DEBUG(HDPRMAN_PRIMVARS)
.Msg("HdPrman: _Convert called -- <%s> %s %s\n",
id.GetText(),
TfEnum::GetName(hdInterp).c_str(),
label);
if (paramType == _ParamTypePrimvar) {
HdExtComputationPrimvarDescriptorVector computedPrimvars =
_GetComputedPrimvars(sceneDelegate, id, hdInterp,
HdChangeTracker::AllDirty);
if (!computedPrimvars.empty()) {
HdExtComputationUtils::ValueStore valueStore
= HdExtComputationUtils::GetComputedPrimvarValues(
computedPrimvars, sceneDelegate);
for (auto const& compPrimvar : computedPrimvars) {
auto const it = valueStore.find(compPrimvar.name);
if (!TF_VERIFY(it != valueStore.end())) {
continue;
}
VtValue val = it->second;
if (val.IsEmpty() ||
(val.IsArrayValued() && val.GetArraySize() == 0)) {
continue;
}
RtUString name = _GetPrmanPrimvarName(compPrimvar.name, detail);
TF_DEBUG(HDPRMAN_PRIMVARS)
.Msg("HdPrman: <%s> %s %s "
"Computed Primvar \"%s\" (%s) = \"%s\"\n",
id.GetText(),
TfEnum::GetName(hdInterp).c_str(),
label,
compPrimvar.name.GetText(),
name.CStr(),
TfStringify(val).c_str());
if (val.IsArrayValued() &&
val.GetArraySize() != static_cast<size_t>(expectedSize)) {
TF_WARN("<%s> %s '%s' size (%zu) did not match "
"expected (%d)", id.GetText(), label,
compPrimvar.name.GetText(), val.GetArraySize(),
expectedSize);
continue;
}
if (!_SetParamValue(name, val, detail,
compPrimvar.role, params)) {
TF_WARN("Ignoring unhandled %s of type %s for %s.%s\n",
label, val.GetTypeName().c_str(), id.GetText(),
compPrimvar.name.GetText());
}
}
}
}
for (HdPrimvarDescriptor const& primvar:
sceneDelegate->GetPrimvarDescriptors(id, hdInterp))
{
TF_DEBUG(HDPRMAN_PRIMVARS)
.Msg("HdPrman: authored id <%s> hdInterp %s label %s primvar \"%s\"\n",
id.GetText(),
TfEnum::GetName(hdInterp).c_str(),
label,
primvar.name.GetText());
if (primvar.name == HdTokens->points) {
continue;
}
RtUString name;
if (hdInterp == HdInterpolationConstant) {
static const char *userAttrPrefix = "user:";
static const char *riAttrPrefix = "ri:attributes:";
bool hasUserPrefix =
TfStringStartsWith(primvar.name.GetString(), userAttrPrefix);
bool hasRiAttributesPrefix =
TfStringStartsWith(primvar.name.GetString(), riAttrPrefix);
bool skipPrimvar = false;
if (paramType == _ParamTypeAttribute) {
if (!hasUserPrefix && !hasRiAttributesPrefix) {
skipPrimvar = true;
} else if (hasRiAttributesPrefix) {
if (_IsMasterAttribute(primvar.name)) {
skipPrimvar = true;
}
}
} else {
if (hasUserPrefix) {
skipPrimvar = true;
} else if (hasRiAttributesPrefix) {
if (!_IsMasterAttribute(primvar.name)) {
skipPrimvar = true;
}
}
}
if (skipPrimvar) {
continue;
}
if (hasRiAttributesPrefix) {
const char *strippedName = primvar.name.GetText();
strippedName += strlen(riAttrPrefix);
name = _GetPrmanPrimvarName(TfToken(strippedName), detail);
} else {
name = _GetPrmanPrimvarName(primvar.name, detail);
}
} else {
name = _GetPrmanPrimvarName(primvar.name, detail);
}
const size_t maxNumTimeSamples = 1;
float times[1];
VtValue val;
sceneDelegate->SamplePrimvar(id, primvar.name, maxNumTimeSamples,
times, &val);
TF_DEBUG(HDPRMAN_PRIMVARS)
.Msg("HdPrman: <%s> %s %s \"%s\" (%s) = \"%s\"\n",
id.GetText(),
TfEnum::GetName(hdInterp).c_str(),
label,
primvar.name.GetText(),
name.CStr(),
TfStringify(val).c_str());
if (val.IsEmpty() ||
(val.IsArrayValued() && val.GetArraySize() == 0)) {
continue;
}
if (val.IsArrayValued() &&
val.GetArraySize() != static_cast<size_t>(expectedSize)) {
TF_WARN("<%s> %s '%s' size (%zu) did not match "
"expected (%d)", id.GetText(), label,
primvar.name.GetText(), val.GetArraySize(), expectedSize);
continue;
}
if (!_SetParamValue(name, val, detail, primvar.role, params)) {
TF_WARN("Ignoring unhandled %s of type %s for %s.%s\n",
label, val.GetTypeName().c_str(), id.GetText(),
primvar.name.GetText());
}
}
}
void
HdPrman_ConvertPrimvars(HdSceneDelegate *sceneDelegate, SdfPath const& id,
RtParamList& primvars, int numUniform, int numVertex,
int numVarying, int numFaceVarying)
{
const HdInterpolation hdInterpValues[] = {
HdInterpolationConstant,
HdInterpolationUniform,
HdInterpolationVertex,
HdInterpolationVarying,
HdInterpolationFaceVarying,
};
const int primvarSizes[] = {
1,
numUniform,
numVertex,
numVarying,
numFaceVarying
};
const int modeCount = 5;
for (size_t i = 0; i < modeCount; ++i) {
_Convert(sceneDelegate, id, hdInterpValues[i], primvars,
_ParamTypePrimvar, primvarSizes[i]);
}
}
RtParamList
HdPrman_Context::ConvertAttributes(HdSceneDelegate *sceneDelegate,
SdfPath const& id)
{
RtParamList attrs;
const HdInterpolation hdInterpValues[] = {
HdInterpolationConstant,
};
for (HdInterpolation hdInterp: hdInterpValues) {
_Convert(sceneDelegate, id, hdInterp, attrs, _ParamTypeAttribute, 1);
}
attrs.SetString(RixStr.k_identifier_name, RtUString(id.GetText()));
if (!sceneDelegate->GetVisible(id)) {
attrs.SetInteger(RixStr.k_visibility_camera, 0);
attrs.SetInteger(RixStr.k_visibility_indirect, 0);
attrs.SetInteger(RixStr.k_visibility_transmission, 0);
}
VtArray<TfToken> categories = sceneDelegate->GetCategories(id);
ConvertCategoriesToAttributes(id, categories, attrs);
return attrs;
}
void
HdPrman_Context::ConvertCategoriesToAttributes(
SdfPath const& id,
VtArray<TfToken> const& categories,
RtParamList& attrs)
{
if (categories.empty()) {
attrs.SetString( RixStr.k_lightfilter_subset,
RtUString("") );
attrs.SetString( RixStr.k_lighting_subset,
RtUString("default") );
TF_DEBUG(HDPRMAN_LIGHT_LINKING)
.Msg("HdPrman: <%s> no categories; lighting:subset = \"default\"\n",
id.GetText());
return;
}
std::string membership;
for (TfToken const& category: categories) {
if (!membership.empty()) {
membership += " ";
}
membership += category;
}
RtUString inputGrouping = RtUString("");
attrs.GetString(RixStr.k_grouping_membership, inputGrouping);
if (inputGrouping != RtUString("")) {
std::string input = inputGrouping.CStr();
membership += " " + input;
}
attrs.SetString( RixStr.k_grouping_membership,
RtUString(membership.c_str()) );
TF_DEBUG(HDPRMAN_LIGHT_LINKING)
.Msg("HdPrman: <%s> grouping:membership = \"%s\"\n",
id.GetText(), membership.c_str());
std::string lightingSubset = "default";
for (TfToken const& category: categories) {
if (IsLightLinkUsed(category)) {
if (!lightingSubset.empty()) {
lightingSubset += " ";
}
lightingSubset += category;
}
}
attrs.SetString( RixStr.k_lighting_subset,
RtUString(lightingSubset.c_str()) );
TF_DEBUG(HDPRMAN_LIGHT_LINKING)
.Msg("HdPrman: <%s> lighting:subset = \"%s\"\n",
id.GetText(), lightingSubset.c_str());
std::string lightFilterSubset = "default";
for (TfToken const& category: categories) {
if (IsLightFilterUsed(category)) {
if (!lightFilterSubset.empty()) {
lightFilterSubset += " ";
}
lightFilterSubset += category;
}
}
attrs.SetString( RixStr.k_lightfilter_subset,
RtUString(lightFilterSubset.c_str()) );
TF_DEBUG(HDPRMAN_LIGHT_LINKING)
.Msg("HdPrman: <%s> lightFilter:subset = \"%s\"\n",
id.GetText(), lightFilterSubset.c_str());
}
bool
HdPrman_ResolveMaterial(HdSceneDelegate *sceneDelegate,
SdfPath const& hdMaterialId,
riley::MaterialId *materialId,
riley::DisplacementId *dispId)
{
if (hdMaterialId != SdfPath()) {
if (const HdSprim *sprim = sceneDelegate->GetRenderIndex().GetSprim(
HdPrimTypeTokens->material, hdMaterialId)) {
const HdPrmanMaterial *material =
dynamic_cast<const HdPrmanMaterial*>(sprim);
if (material && material->IsValid()) {
*materialId = material->GetMaterialId();
*dispId = material->GetDisplacementId();
return true;
}
}
}
return false;
}
HdPrman_Context::RileyCoordSysIdVecRefPtr
HdPrman_Context::ConvertAndRetainCoordSysBindings(
HdSceneDelegate *sceneDelegate,
SdfPath const& id)
{
HdIdVectorSharedPtr hdIdVecPtr =
sceneDelegate->GetCoordSysBindings(id);
if (!hdIdVecPtr) {
return nullptr;
}
std::lock_guard<std::mutex> lock(_coordSysMutex);
_HdToRileyCoordSysMap::const_iterator it =
_hdToRileyCoordSysMap.find(hdIdVecPtr);
if (it != _hdToRileyCoordSysMap.end()) {
_geomToHdCoordSysMap[id] = hdIdVecPtr;
return it->second;
}
RileyCoordSysIdVec rileyIdVec;
rileyIdVec.reserve(hdIdVecPtr->size());
for (SdfPath const& hdId: *hdIdVecPtr) {
const HdSprim *sprim =
sceneDelegate->GetRenderIndex()
.GetSprim(HdPrimTypeTokens->coordSys, hdId);
if (TF_VERIFY(sprim)) {
const HdPrmanCoordSys *prmanSprim =
dynamic_cast<const HdPrmanCoordSys*>(sprim);
if (TF_VERIFY(prmanSprim) && prmanSprim->IsValid()) {
rileyIdVec.push_back(prmanSprim->GetCoordSysId());
}
}
}
RileyCoordSysIdVecRefPtr rileyIdVecPtr =
std::make_shared<RileyCoordSysIdVec>(rileyIdVec);
_hdToRileyCoordSysMap[hdIdVecPtr] = rileyIdVecPtr;
_geomToHdCoordSysMap[id] = hdIdVecPtr;
return rileyIdVecPtr;
}
void
HdPrman_Context::ReleaseCoordSysBindings(SdfPath const& id)
{
std::lock_guard<std::mutex> lock(_coordSysMutex);
_GeomToHdCoordSysMap::iterator geomIt = _geomToHdCoordSysMap.find(id);
if (geomIt == _geomToHdCoordSysMap.end()) {
return;
}
if (TF_VERIFY(geomIt->second) && geomIt->second.use_count() == 1) {
_hdToRileyCoordSysMap.erase(geomIt->second);
}
_geomToHdCoordSysMap.erase(geomIt);
}
static void
_GetShutterInterval(
HdRenderSettingsMap& renderSettings,
float* shutterOpen,
float* shutterClose)
{
auto const& shutterOpenEntry =
renderSettings.find(HdPrmanRenderSettingsTokens->shutterOpen);
auto const& shutterCloseEntry =
renderSettings.find(HdPrmanRenderSettingsTokens->shutterClose);
if (shutterOpenEntry != renderSettings.end() &&
shutterCloseEntry != renderSettings.end())
{
VtValue shutterOpenVal = shutterOpenEntry->second;
VtValue shutterCloseVal = shutterCloseEntry->second;
if (shutterOpenVal.IsHolding<float>()) {
*shutterOpen = shutterOpenVal.UncheckedGet<float>();
} else if (shutterOpenVal.IsHolding<double>()) {
double v = shutterOpenVal.UncheckedGet<double>();
*shutterOpen = static_cast<float>(v);
}
if (shutterCloseVal.IsHolding<float>()) {
*shutterOpen = shutterCloseVal.UncheckedGet<float>();
} else if (shutterCloseVal.IsHolding<double>()) {
double v = shutterCloseVal.UncheckedGet<double>();
*shutterClose = static_cast<float>(v);
}
}
}
void
HdPrman_Context::SetOptionsFromRenderSettings(
HdPrmanRenderDelegate *renderDelegate,
RtParamList& options)
{
HdRenderSettingsMap renderSettings = renderDelegate->GetRenderSettingsMap();
for (auto const& entry : renderSettings) {
TfToken token = entry.first;
VtValue val = entry.second;
bool hasRiPrefix = TfStringStartsWith(token.GetText(), "ri:");
if (hasRiPrefix) {
bool hasIntegratorPrefix =
TfStringStartsWith(token.GetText(), "ri:integrator");
if (hasIntegratorPrefix)
{
continue;
}
RtUString riName;
riName = RtUString(token.GetText()+3);
_SetParamValue(riName, val, RtDetailType::k_constant,
TfToken(), options);
} else {
if (token == HdPrmanRenderSettingsTokens->pixelAspectRatio) {
options.SetFloat(RixStr.k_Ri_FormatPixelAspectRatio,
val.UncheckedGet<float>());
} else if (token == HdPrmanRenderSettingsTokens->resolution ) {
auto const& res = val.UncheckedGet<GfVec2i>();
options.SetIntegerArray(RixStr.k_Ri_FormatResolution,
&res[0], 2);
} else if (token ==
HdPrmanRenderSettingsTokens->instantaneousShutter ) {
_instantaneousShutter = val.UncheckedGet<bool>();
}
}
}
float shutterOpen = 0.0f;
float shutterClose = 0.0f;
_GetShutterInterval(renderSettings, &shutterOpen, &shutterClose);
float shutterInterval[2] = { shutterOpen, shutterOpen };
if (!_instantaneousShutter)
{
shutterInterval[1] = shutterClose;
}
options.SetFloatArray(RixStr.k_Ri_Shutter, shutterInterval, 2);
}
void
HdPrman_Context::SetIntegratorParamsFromRenderSettings(
HdPrmanRenderDelegate *renderDelegate,
std::string& integratorName,
RtParamList& params)
{
static const RtUString us_PxrPathTracer("PxrPathTracer");
HdRenderSettingsMap renderSettings = renderDelegate->GetRenderSettingsMap();
TfToken preFix(std::string("ri:integrator:") + integratorName);
for (auto const& entry : renderSettings) {
TfToken token = entry.first;
VtValue val = entry.second;
bool hasRiPrefix = TfStringStartsWith(token.GetText(),
preFix.GetText());
if (hasRiPrefix) {
RtUString riName;
riName = RtUString(token.GetText()+preFix.size()+1);
_SetParamValue(riName, val, RtDetailType::k_constant,
TfToken(), params);
}
}
}
void
HdPrman_UpdateSearchPathsFromEnvironment(RtParamList& options)
{
std::string shaderpath = TfGetenv("RMAN_SHADERPATH");
if (!shaderpath.empty()) {
NdrStringVec paths = TfStringSplit(shaderpath, ARCH_PATH_LIST_SEP);
shaderpath = TfStringJoin(paths, ":");
options.SetString( RixStr.k_searchpath_shader,
RtUString(shaderpath.c_str()) );
} else {
NdrStringVec paths;
std::string rmantree = TfGetenv("RMANTREE");
if (!rmantree.empty()) {
paths.push_back(TfStringCatPaths(rmantree, "lib/shaders"));
}
PlugPluginPtr plugin =
PlugRegistry::GetInstance().GetPluginWithName("hdPrmanLoader");
if (plugin)
{
std::string path = TfGetPathName(plugin->GetPath());
if (!path.empty()) {
paths.push_back(TfStringCatPaths(path, "resources/shaders"));
}
}
shaderpath = TfStringJoin(paths, ":");
options.SetString( RixStr.k_searchpath_shader,
RtUString(shaderpath.c_str()) );
}
std::string rixpluginpath = TfGetenv("RMAN_RIXPLUGINPATH");
if (!rixpluginpath.empty()) {
NdrStringVec paths = TfStringSplit(rixpluginpath, ARCH_PATH_LIST_SEP);
rixpluginpath = TfStringJoin(paths, ":");
options.SetString( RixStr.k_searchpath_rixplugin,
RtUString(rixpluginpath.c_str()) );
} else {
NdrStringVec paths;
std::string rmantree = TfGetenv("RMANTREE");
if (!rmantree.empty()) {
paths.push_back(TfStringCatPaths(rmantree, "lib/plugins"));
}
rixpluginpath = TfStringJoin(paths, ":");
options.SetString( RixStr.k_searchpath_rixplugin,
RtUString(rixpluginpath.c_str()) );
}
std::string texturepath = TfGetenv("RMAN_TEXTUREPATH");
if (!texturepath.empty()) {
NdrStringVec paths = TfStringSplit(texturepath, ARCH_PATH_LIST_SEP);
texturepath = TfStringJoin(paths, ":");
options.SetString( RixStr.k_searchpath_texture,
RtUString(texturepath.c_str()) );
} else {
NdrStringVec paths;
std::string rmantree = TfGetenv("RMANTREE");
if (!rmantree.empty()) {
paths.push_back(TfStringCatPaths(rmantree, "lib/textures"));
paths.push_back(TfStringCatPaths(rmantree, "lib/plugins"));
}
PlugPluginPtr plugin =
PlugRegistry::GetInstance().GetPluginWithName("hdPrmanLoader");
if (plugin)
{
std::string path = TfGetPathName(plugin->GetPath());
if (!path.empty()) {
paths.push_back(path);
}
}
texturepath = TfStringJoin(paths, ":");
options.SetString( RixStr.k_searchpath_texture,
RtUString(texturepath.c_str()) );
}
std::string proceduralpath = TfGetenv("RMAN_PROCEDURALPATH");
if (!proceduralpath.empty()) {
NdrStringVec paths = TfStringSplit(proceduralpath, ARCH_PATH_LIST_SEP);
proceduralpath = TfStringJoin(paths, ":");
options.SetString( RixStr.k_searchpath_procedural,
RtUString(proceduralpath.c_str()) );
}
}
PXR_NAMESPACE_CLOSE_SCOPE