Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle vertex interpolated uvs on bspline curves #1787

Merged
merged 6 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [usd#1770](https://github.com/Autodesk/arnold-usd/issues/1770) - Fix exr driver always rendering float with husk when productType is arnold
- [usd#1772](https://github.com/Autodesk/arnold-usd/issues/1772) - RectLight texture uvs are now consistent between husk, kick and other renderers.
- [usd#1776](https://github.com/Autodesk/arnold-usd/issues/1776) - Fix incorrect PointInstancer instance orientations in the render delegate.
- [usd#1769](https://github.com/Autodesk/arnold-usd/issues/1769) - Fix curve uvs when they are vertex interpolated.

## [7.2.5.0] - 2023-12-13

Expand Down
63 changes: 37 additions & 26 deletions libs/render_delegate/basis_curves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,30 @@ namespace {

} // namespace


// Function to convert a GfVec3f array to a GfVec2f array, skipping the last component.
// It could be used more generally later by registering it as a VtValue Cast:
//
// VtValue::RegisterCast<VtVec3fArray, VtVec2fArray>(&Vec3fToVec2f);
//
// then simply call the Cast function as follows:
//
// value = VtValue::Cast<VtVec2fArray>(desc.value);
//
VtValue Vec3fToVec2f(VtValue const &val) {
if (val.IsHolding<VtVec3fArray>()) {
const auto& vec3 = val.UncheckedGet<VtVec3fArray>();
VtVec2fArray vec2(vec3.size());
std::transform(
vec3.cbegin(), vec3.cend(), vec2.begin(),
[](const GfVec3f& in) -> GfVec2f {
return {in[0], in[1]};
});
return VtValue::Take(vec2);
}
return {};
}

#if PXR_VERSION >= 2102
HdArnoldBasisCurves::HdArnoldBasisCurves(HdArnoldRenderDelegate* delegate, const SdfPath& id)
: HdArnoldRprim<HdBasisCurves>(str::curves, delegate, id), _interpolation(HdTokens->linear)
Expand Down Expand Up @@ -187,58 +211,45 @@ void HdArnoldBasisCurves::Sync(
}
continue;
}

// The curves node only knows the "uvs" parameter, so we have to rename the attribute
TfToken arnoldAttributeName = primvar.first;
auto value = desc.value;
if (primvar.first == str::t_uv || primvar.first == str::t_st) {
// This is either a VtVec2fArray or VtVec3fArray (in Solaris).
if (desc.value.IsHolding<VtVec2fArray>()) {
const auto& v = desc.value.UncheckedGet<VtVec2fArray>();
AiNodeSetArray(
GetArnoldNode(), str::uvs, AiArrayConvert(v.size(), 1, AI_TYPE_VECTOR2, v.data()));
continue;
}
arnoldAttributeName = str::t_uvs;
// Special case if the uvs attribute has 3 dimensions
if (desc.value.IsHolding<VtVec3fArray>()) {
const auto& v = desc.value.UncheckedGet<VtVec3fArray>();
auto* arr = AiArrayAllocate(v.size(), 1, AI_TYPE_VECTOR2);
if (!v.empty()) {
std::transform(
v.begin(), v.end(), static_cast<GfVec2f*>(AiArrayMap(arr)),
[](const GfVec3f& in) -> GfVec2f {
return {in[0], in[1]};
});
AiArrayUnmap(arr);
}
AiNodeSetArray(GetArnoldNode(), str::uvs, arr);
continue;
}
value = Vec3fToVec2f(desc.value);
}
}

if (desc.interpolation == HdInterpolationConstant) {
// We skip reading the basis for now as it would require remapping the vertices, widths and
// all the primvars.
if (primvar.first != _tokens->basis) {
HdArnoldSetConstantPrimvar(
GetArnoldNode(), primvar.first, desc.role, desc.value, &_visibilityFlags, &_sidednessFlags,
GetArnoldNode(), arnoldAttributeName, desc.role, value, &_visibilityFlags, &_sidednessFlags,
nullptr, GetRenderDelegate());
}
} else if (desc.interpolation == HdInterpolationUniform) {
HdArnoldSetUniformPrimvar(GetArnoldNode(), primvar.first, desc.role, desc.value, GetRenderDelegate());
HdArnoldSetUniformPrimvar(GetArnoldNode(), arnoldAttributeName, desc.role, value, GetRenderDelegate());
} else if (desc.interpolation == HdInterpolationVertex || desc.interpolation == HdInterpolationVarying) {
if (primvar.first == HdTokens->points) {
HdArnoldSetPositionFromValue(GetArnoldNode(), str::points, desc.value);
HdArnoldSetPositionFromValue(GetArnoldNode(), str::points, value);
} else if (primvar.first == HdTokens->normals) {
if (_interpolation == HdTokens->linear)
AiMsgWarning("%s : Orientations not supported on linear curves", AiNodeGetName(GetArnoldNode()));
else
curvesData.SetOrientationFromValue(GetArnoldNode(), desc.value);
curvesData.SetOrientationFromValue(GetArnoldNode(), value);
} else {
auto value = desc.value;
// For pinned curves, vertex interpolation primvars shouldn't be remapped
if (_interpolation != HdTokens->linear &&
!(isPinned && desc.interpolation == HdInterpolationVertex)) {
curvesData.RemapCurvesVertexPrimvar<
bool, VtUCharArray::value_type, unsigned int, int, float, GfVec2f, GfVec3f, GfVec4f,
std::string, TfToken, SdfAssetPath>(value);
}
HdArnoldSetVertexPrimvar(GetArnoldNode(), primvar.first, desc.role, value, GetRenderDelegate());
HdArnoldSetVertexPrimvar(GetArnoldNode(), arnoldAttributeName, desc.role, value, GetRenderDelegate());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion testsuite/groups
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ darwin:
# SPECIAL TEST GROUPS #
#######################
# Tests that can be run in hydra mode
hydra: test_0000 test_0001 test_0002 test_0003 test_0004 test_0005 test_0006 test_0007 test_0008 test_0009 test_0010 test_0011 test_0012 test_0014 test_0016 test_0017 test_0018 test_0019 test_0020 test_0021 test_0022 test_0023 test_0024 test_0025 test_0026 test_0027 test_0028 test_0029 test_0030 test_0031 test_0032 test_0033 test_0034 test_0038 test_0041 test_0046 test_0048 test_0049 test_0055 test_0112 test_0130 test_0132 test_0133 test_0135 test_0139 test_0140 test_0141 test_0142 test_0143 test_0144 test_0145 test_0148 test_0149 test_0150 test_0151 test_0158 test_0159 test_0161 test_0162 test_0163 test_0164 test_0165 test_0166 test_0168 test_0169 test_0170 test_0171 test_0172 test_0173 test_0174 test_0175 test_0177 test_0178 test_0180 test_0183 test_0184 test_0186 test_0187 test_0188 test_0189 test_0191 test_0194 test_0195 test_0196 test_0197 test_0198 test_0200 test_0201 test_0202 test_0204 test_0205 test_0206 test_0207 test_0215 test_0216 test_0217 test_0219 test_0220 test_0221 test_0222 test_0223 test_0225 test_0227 test_0228 test_0229 test_0230 test_0299 test_0232 test_0233 test_0234 test_0238 test_0239 test_0240 test_0242 test_0243 test_0244 test_0245 test_0739 test_1181 test_1204 test_1209 test_1225 test_1245 test_1262 test_1294 test_1309 test_1311 test_1313 test_1333 test_1334 test_1346 test_1416 test_1420 test_1426 test_1427.3 test_1430 test_1433 test_1435 test_1438 test_1457 test_1486 test_1499 test_1524 test_1525 test_1530 test_1535 test_1538 test_1546 test_1550 test_1567 test_1588 test_1590 test_1593 test_1607 test_1613 test_1625 test_1632 test_1654 test_1657 test_1678 test_1718 test_1726 test_1735 test_1772
hydra: test_0000 test_0001 test_0002 test_0003 test_0004 test_0005 test_0006 test_0007 test_0008 test_0009 test_0010 test_0011 test_0012 test_0014 test_0016 test_0017 test_0018 test_0019 test_0020 test_0021 test_0022 test_0023 test_0024 test_0025 test_0026 test_0027 test_0028 test_0029 test_0030 test_0031 test_0032 test_0033 test_0034 test_0038 test_0041 test_0046 test_0048 test_0049 test_0055 test_0112 test_0130 test_0132 test_0133 test_0135 test_0139 test_0140 test_0141 test_0142 test_0143 test_0144 test_0145 test_0148 test_0149 test_0150 test_0151 test_0158 test_0159 test_0161 test_0162 test_0163 test_0164 test_0165 test_0166 test_0168 test_0169 test_0170 test_0171 test_0172 test_0173 test_0174 test_0175 test_0177 test_0178 test_0180 test_0183 test_0184 test_0186 test_0187 test_0188 test_0189 test_0191 test_0194 test_0195 test_0196 test_0197 test_0198 test_0200 test_0201 test_0202 test_0204 test_0205 test_0206 test_0207 test_0215 test_0216 test_0217 test_0219 test_0220 test_0221 test_0222 test_0223 test_0225 test_0227 test_0228 test_0229 test_0230 test_0299 test_0232 test_0233 test_0234 test_0238 test_0239 test_0240 test_0242 test_0243 test_0244 test_0245 test_0739 test_1181 test_1204 test_1209 test_1225 test_1245 test_1262 test_1294 test_1309 test_1311 test_1313 test_1333 test_1334 test_1346 test_1416 test_1420 test_1426 test_1427.3 test_1430 test_1433 test_1435 test_1438 test_1457 test_1486 test_1499 test_1524 test_1525 test_1530 test_1535 test_1538 test_1546 test_1550 test_1567 test_1588 test_1590 test_1593 test_1607 test_1613 test_1625 test_1632 test_1654 test_1657 test_1678 test_1718 test_1726 test_1735 test_1769 test_1772


# Tests in this group will never be executed (you can use it to temporarily disable some tests and/or groups)
Expand Down
7 changes: 7 additions & 0 deletions testsuite/test_1769/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
BSpline curve with vertex interpolated uvs

author: cyril.pichard@autodesk.com

see #1769

PARAMS: {'scene':'test.usda'}
83 changes: 83 additions & 0 deletions testsuite/test_1769/data/test.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#usda 1.0
(
defaultPrim = "sopimport1"
endTimeCode = 1
framesPerSecond = 24
metersPerUnit = 1
startTimeCode = 1
timeCodesPerSecond = 24
upAxis = "Y"
)

def Xform "sopimport1" (
kind = "component"
)
{
def BasisCurves "curve_0"
{
uniform token basis = "bspline"
int[] curveVertexCounts = [9]
float3[] extent = [(0.6149099, 0, 1.2895236), (0.6149099, 0.799, 1.2895236)]
point3f[] points = [(0.6149099, 0, 1.2895236), (0.6149099, 0, 1.2895236), (0.6149099, 0, 1.2895236), (0.6149099, 0.19975, 1.2895236), (0.6149099, 0.3995, 1.2895236), (0.6149099, 0.59925, 1.2895236), (0.6149099, 0.799, 1.2895236), (0.6149099, 0.799, 1.2895236), (0.6149099, 0.799, 1.2895236)] (
interpolation = "vertex"
)
texCoord2f[] primvars:st = [(0.6537275, 0.8223809), (0.6537275, 0.8223809), (0.6537275, 0.8223809), (0.6537275, 0.8223809), (0.6537275, 0.8223809), (0.6537275, 0.8223809), (0.6537275, 0.8223809), (0.6537275, 0.8223809), (0.6537275, 0.8223809)] (
interpolation = "vertex"
)
int[] primvars:st:indices = None
uniform token type = "cubic"
uniform token wrap = "nonperiodic"
}
}

def Xform "lights"
{
def RectLight "arealight1" (
prepend apiSchemas = ["HoudiniViewportLightAPI", "HoudiniViewportGuideAPI"]
)
{
float2 houdini:clippingRange = (0.001, 10000)
bool houdini:inviewermenu = 1
color3f inputs:color = (1, 1, 1)
float inputs:diffuse = 1
bool inputs:enableColorTemperature = 0
float inputs:exposure = 0
float inputs:height = 7.448014
float inputs:intensity = 0.1
bool inputs:normalize = 0
float inputs:specular = 1
asset inputs:texture:file = @@
float inputs:width = 8.364269
rel light:filters = None
matrix4d xformOp:transform = ( (-0.02482371480219213, -0.9990594771725642, 0.03555199368674425, 0), (-1.8395864258974326e-12, -0.035562952619954354, -0.9993674381332178, 0), (0.999691844111684, -0.024808012266881785, 0.0008828045915237619, 0), (1.5704420804977417, 0.43900111317634605, 1.7137359082698838, 1) )
uniform token[] xformOpOrder = ["xformOp:transform"]
}
}

def Xform "cameras"
{
def Camera "camera1" (
prepend apiSchemas = ["HoudiniCameraPlateAPI", "HoudiniViewportGuideAPI"]
)
{
float2 clippingRange = (1, 1000000)
float exposure = 0
float focalLength = 0.45
float focusDistance = 10.78378
float fStop = 0
float horizontalAperture = 0.20955
float horizontalApertureOffset = 0
asset houdini:backgroundimage = @@
asset houdini:foregroundimage = @@
float houdini:guidescale = 1
bool houdini:inviewermenu = 1
token projection = "perspective"
double shutter:close = 0.25
double shutter:open = -0.25
float verticalAperture = 0.11787187
float verticalApertureOffset = 0
matrix4d xformOp:transform = ( (0.5250461978776859, -0.0007888840709954176, -0.8510733621469471, 0), (-0.036986569010682126, 0.999033644144815, -0.023743874569022813, 0), (0.8502696535846755, 0.04394491470755142, 0.5245096382949908, 0), (3.7343048332866244, 0.550095433860866, 3.2061258043688006, 1) )
uniform token[] xformOpOrder = ["xformOp:transform"]
}
}

Binary file added testsuite/test_1769/ref/reference.tif
Binary file not shown.