Skip to content

Commit

Permalink
handle vertex interpolated uvs on bspline curves (#1792)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpichard authored Jan 5, 2024
1 parent 453ade2 commit a685d60
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

### Bug fixes
- [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);
HdArnoldSetUniformPrimvar(GetArnoldNode(), arnoldAttributeName, desc.role, value);
} 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);
HdArnoldSetVertexPrimvar(GetArnoldNode(), arnoldAttributeName, desc.role, value);
}
}
}
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_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_1416 test_1420 test_1426 test_1427.3 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
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_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_1416 test_1420 test_1426 test_1427.3 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

# Tests in this group will never be executed (you can use it to temporarily disable some tests and/or groups)
ignore:
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: [email protected]

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.

0 comments on commit a685d60

Please sign in to comment.