Skip to content

Commit

Permalink
Initial support for curve rendering. (#483)
Browse files Browse the repository at this point in the history
Fixes #19.
  • Loading branch information
sirpalee authored Jul 31, 2020
1 parent 36775d9 commit 6b71299
Show file tree
Hide file tree
Showing 15 changed files with 585 additions and 22 deletions.
2 changes: 2 additions & 0 deletions render_delegate/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ set(SRC
nodes/driver_main.cpp
nodes/nodes.cpp

basis_curves.cpp
config.cpp
constant_strings.cpp
debug_codes.cpp
Expand All @@ -24,6 +25,7 @@ set(SRC

set(HDR
api.h
basis_curves.h
config.h
constant_strings.h
debug_codes.h
Expand Down
1 change: 1 addition & 0 deletions render_delegate/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ local_env = env.Clone()

src_dir = os.path.join(env['ROOT_DIR'], 'render_delegate')
source_files = [
'basis_curves.cpp',
'config.cpp',
'constant_strings.cpp',
'debug_codes.cpp',
Expand Down
356 changes: 356 additions & 0 deletions render_delegate/basis_curves.cpp

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions render_delegate/basis_curves.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2020 Autodesk, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// @file basis_curves.h
///
/// Utilities for translating Hydra Basis Curves for the Render Delegate.
#pragma once

#include "api.h"

#include <ai.h>

#include <pxr/pxr.h>

#include <pxr/imaging/hd/basisCurves.h>

#include "shape.h"
#include "utils.h"

PXR_NAMESPACE_OPEN_SCOPE

class HdArnoldBasisCurves : public HdBasisCurves {
public:
HDARNOLD_API
HdArnoldBasisCurves(HdArnoldRenderDelegate* delegate, const SdfPath& id, const SdfPath& instancerId = SdfPath());

/// Syncs the Hydra Basis Curves to the Arnold Curves.
///
/// @param sceneDelegate Pointer to the Scene Delegate.
/// @param renderPaaram Pointer to a HdArnoldRenderParam instance.
/// @param dirtyBits Dirty Bits to sync.
/// @param reprToken Token describing the representation of the mesh.
void Sync(HdSceneDelegate* delegate, HdRenderParam* renderParam, HdDirtyBits* dirtyBits, const TfToken& reprToken)
override;

/// Returns the initial Dirty Bits for the Primitive.
///
/// @return Initial Dirty Bits.
HdDirtyBits GetInitialDirtyBitsMask() const override;

protected:
/// Allows setting additional Dirty Bits based on the ones already set.
///
/// @param bits The current Dirty Bits.
/// @return The new set of Dirty Bits which replace the original one.
HdDirtyBits _PropagateDirtyBits(HdDirtyBits bits) const override;

/// Initialize a given representation for the curves.
///
/// @param reprName Name of the representation to initialize.
/// @param dirtyBits In/Out HdDirtyBits value, that allows the _InitRepr
/// function to set additional Dirty Bits if required for a given
/// representation.
void _InitRepr(const TfToken& reprToken, HdDirtyBits* dirtyBits) override;

HdArnoldShape _shape; ///< Utility class for the curves and instances.
HdArnoldPrimvarMap _primvars; ///< Precomputed list of primvars.
TfToken _interpolation; ///< Interpolation of the curve.
VtIntArray _vertexCounts; ///< Stored vertex counts for curves.
};

PXR_NAMESPACE_CLOSE_SCOPE
13 changes: 11 additions & 2 deletions render_delegate/constant_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ namespace str {
extern const TfToken t_##x
#endif

ASTR2(b_spline, "b-spline");
ASTR2(catmull_rom, "catmull-rom");
ASTR2(defaultStr, "default");
ASTR2(renderPassAOVDriver, "HdArnoldRenderPass_aov_driver");
ASTR2(renderPassCamera, "HdArnoldRenderPass_camera");
ASTR2(renderPassFilter, "HdArnoldRenderPass_beautyFilter");
ASTR2(renderPassClosestFilter, "HdArnoldRenderPass_closestFilter");
ASTR2(renderPassFilter, "HdArnoldRenderPass_beautyFilter");
ASTR2(renderPassMainDriver, "HdArnoldRenderPass_main_driver");
ASTR2(renderPassAOVDriver, "HdArnoldRenderPass_aov_driver");

ASTR(AA_sample_clamp);
ASTR(AA_sample_clamp_affects_aovs);
Expand Down Expand Up @@ -117,6 +119,8 @@ ASTR(barndoor_top_left);
ASTR(barndoor_top_right);
ASTR(base);
ASTR(base_color);
ASTR(basis);
ASTR(bezier);
ASTR(blend_opacity);
ASTR(box_filter);
ASTR(bucket_scanning);
Expand All @@ -134,6 +138,7 @@ ASTR(color_pointer);
ASTR(cone_angle);
ASTR(crease_idxs);
ASTR(crease_sharpness);
ASTR(curves);
ASTR(cylinder_light);
ASTR(depth_pointer);
ASTR(diffuseColor);
Expand Down Expand Up @@ -195,6 +200,7 @@ ASTR(interactive_target_fps_min);
ASTR(ior);
ASTR(latlong);
ASTR(light_path_expressions);
ASTR(linear);
ASTR(log_file);
ASTR(log_flags_console);
ASTR(log_flags_file);
Expand All @@ -216,6 +222,7 @@ ASTR(normal_nonexistant_rename);
ASTR(nsides);
ASTR(opacity);
ASTR(opaque);
ASTR(orientations);
ASTR(outputs);
ASTR(parallel_node_init);
ASTR(penumbra_angle);
Expand Down Expand Up @@ -279,6 +286,7 @@ ASTR(uv);
ASTR(uvcoords);
ASTR(uvidxs);
ASTR(uvlist);
ASTR(uvs);
ASTR(varname);
ASTR(vidxs);
ASTR(viewMtx);
Expand All @@ -288,6 +296,7 @@ ASTR(volume);
ASTR(width);
ASTR(xres);
ASTR(yres);
ASTR(num_points);

#undef ASTR
#undef ASTR2
Expand Down
7 changes: 4 additions & 3 deletions render_delegate/debug_codes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ PXR_NAMESPACE_OPEN_SCOPE
TF_REGISTRY_FUNCTION(TfDebug)
{
TF_DEBUG_ENVIRONMENT_SYMBOL(
HDARNOLD_MATERIAL,
"Print info about material translation for the arnold hydra render "
"delegate");
HDARNOLD_MATERIAL, "Print info about material translation for the arnold hydra render delegate");

TF_DEBUG_ENVIRONMENT_SYMBOL(
HDARNOLD_PRIMVARS, "Print info about primvar translation for the arnold hydra render delegate");
}

PXR_NAMESPACE_CLOSE_SCOPE
2 changes: 1 addition & 1 deletion render_delegate/debug_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ PXR_NAMESPACE_OPEN_SCOPE

// clang-format off
TF_DEBUG_CODES(
HDARNOLD_MATERIAL
HDARNOLD_MATERIAL, HDARNOLD_PRIMVARS
);
// clang-format on

Expand Down
2 changes: 1 addition & 1 deletion render_delegate/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// @file material.h
/// @file render_delegate/material.h
///
/// Utilities for translating Hydra Materials for the Render Delegate.
#pragma once
Expand Down
7 changes: 6 additions & 1 deletion render_delegate/render_delegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <pxr/imaging/hd/rprim.h>
#include <pxr/imaging/hd/tokens.h>

#include "basis_curves.h"
#include "config.h"
#include "constant_strings.h"
#include "instancer.h"
Expand Down Expand Up @@ -133,7 +134,8 @@ void _SetNodeParam(AtNode* node, const TfToken& key, const VtValue& value)

inline const TfTokenVector& _SupportedRprimTypes()
{
static const TfTokenVector r{HdPrimTypeTokens->mesh, HdPrimTypeTokens->volume, HdPrimTypeTokens->points};
static const TfTokenVector r{HdPrimTypeTokens->mesh, HdPrimTypeTokens->volume, HdPrimTypeTokens->points,
HdPrimTypeTokens->basisCurves};
return r;
}

Expand Down Expand Up @@ -539,6 +541,9 @@ HdRprim* HdArnoldRenderDelegate::CreateRprim(const TfToken& typeId, const SdfPat
if (typeId == HdPrimTypeTokens->points) {
return new HdArnoldPoints(this, rprimId, instancerId);
}
if (typeId == HdPrimTypeTokens->basisCurves) {
return new HdArnoldBasisCurves(this, rprimId, instancerId);
}
TF_CODING_ERROR("Unknown Rprim Type %s", typeId.GetText());
return nullptr;
}
Expand Down
64 changes: 51 additions & 13 deletions render_delegate/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "pxr/imaging/hd/extComputationUtils.h"

#include "constant_strings.h"
#include "debug_codes.h"
#include "hdarnold.h"

#include <type_traits>
Expand Down Expand Up @@ -127,6 +128,13 @@ const std::array<HdInterpolation, HdInterpolationCount> interpolations{

inline bool _Declare(AtNode* node, const TfToken& name, const TfToken& scope, const TfToken& type)
{
if (AiNodeEntryLookUpParameter(AiNodeGetNodeEntry(node), name.GetText()) != nullptr) {
TF_DEBUG(HDARNOLD_PRIMVARS)
.Msg(
"Unable to translate %s primvar for %s due to a name collision with a built-in parameter",
name.GetText(), AiNodeGetName(node));
return false;
}
if (AiNodeLookUpUserParameter(node, name.GetText()) != nullptr) {
AiNodeResetParameter(node, name.GetText());
}
Expand All @@ -136,13 +144,17 @@ inline bool _Declare(AtNode* node, const TfToken& name, const TfToken& scope, co
template <typename T>
inline uint32_t _ConvertArray(AtNode* node, const AtString& name, uint8_t arnoldType, const VtValue& value)
{
if (!value.IsHolding<T>()) {
return 0;
if (value.IsHolding<T>()) {
const auto& v = value.UncheckedGet<T>();
AiNodeSetArray(node, name, AiArrayConvert(1, 1, arnoldType, &v));
return 1;
} else if (value.IsHolding<VtArray<T>>()) {
const auto& v = value.UncheckedGet<VtArray<T>>();
auto* arr = AiArrayConvert(v.size(), 1, arnoldType, v.data());
AiNodeSetArray(node, name, arr);
return AiArrayGetNumElements(arr);
}
const auto& v = value.UncheckedGet<T>();
auto* arr = AiArrayConvert(v.size(), 1, arnoldType, v.data());
AiNodeSetArray(node, name, arr);
return AiArrayGetNumElements(arr);
return 0;
}

template <typename T>
Expand Down Expand Up @@ -649,27 +661,27 @@ void HdArnoldSetParameter(AtNode* node, const AtParamEntry* pentry, const VtValu
// And convert/test different type conversions.
case AI_TYPE_INT:
case AI_TYPE_ENUM:
_ConvertArray<VtIntArray>(node, paramName, AI_TYPE_INT, value);
_ConvertArray<int>(node, paramName, AI_TYPE_INT, value);
break;
case AI_TYPE_UINT:
_ConvertArray<VtUIntArray>(node, paramName, arrayType, value);
_ConvertArray<unsigned int>(node, paramName, arrayType, value);
break;
case AI_TYPE_BOOLEAN:
_ConvertArray<VtBoolArray>(node, paramName, arrayType, value);
_ConvertArray<bool>(node, paramName, arrayType, value);
break;
case AI_TYPE_FLOAT:
case AI_TYPE_HALF:
_ConvertArray<VtFloatArray>(node, paramName, AI_TYPE_FLOAT, value);
_ConvertArray<float>(node, paramName, AI_TYPE_FLOAT, value);
break;
case AI_TYPE_VECTOR2:
_ConvertArray<VtVec2fArray>(node, paramName, arrayType, value);
_ConvertArray<GfVec2f>(node, paramName, arrayType, value);
break;
case AI_TYPE_RGB:
case AI_TYPE_VECTOR:
_ConvertArray<VtVec3fArray>(node, paramName, arrayType, value);
_ConvertArray<GfVec3f>(node, paramName, arrayType, value);
break;
case AI_TYPE_RGBA:
_ConvertArray<VtVec4fArray>(node, paramName, arrayType, value);
_ConvertArray<GfVec4f>(node, paramName, arrayType, value);
break;
default:
AiMsgError("Unsupported array parameter %s.%s", AiNodeGetName(node), AiParamGetName(pentry).c_str());
Expand Down Expand Up @@ -924,6 +936,32 @@ void HdArnoldSetRadiusFromPrimvar(AtNode* node, const SdfPath& id, HdSceneDelega
AiNodeSetArray(node, str::radius, arr);
}

void HdArnoldSetRadiusFromValue(AtNode* node, const VtValue& value)
{
AtArray* arr = nullptr;
if (value.IsHolding<VtFloatArray>()) {
const auto& values = value.UncheckedGet<VtFloatArray>();
arr = AiArrayAllocate(values.size(), 1, AI_TYPE_FLOAT);
auto* out = static_cast<float*>(AiArrayMap(arr));
std::transform(values.begin(), values.end(), out, [](const float w) -> float { return w * 0.5f; });
AiArrayUnmap(arr);
} else if (value.IsHolding<VtDoubleArray>()) {
const auto& values = value.UncheckedGet<VtDoubleArray>();
arr = AiArrayAllocate(values.size(), 1, AI_TYPE_FLOAT);
auto* out = static_cast<float*>(AiArrayMap(arr));
std::transform(values.begin(), values.end(), out, [](const double w) -> float { return static_cast<float>(w * 0.5); });
AiArrayUnmap(arr);
} else if (value.IsHolding<float>()) {
arr = AiArray(1, 1, AI_TYPE_FLOAT, value.UncheckedGet<float>() / 2.0f);
} else if (value.IsHolding<double>()) {
arr = AiArray(1, 1, AI_TYPE_FLOAT, static_cast<float>(value.UncheckedGet<double>() / 2.0));
} else {
return;
}

AiNodeSetArray(node, str::radius, arr);
}

AtArray* HdArnoldGenerateIdxs(unsigned int numIdxs, const VtIntArray* vertexCounts)
{
auto* array = AiArrayAllocate(numIdxs, 1, AI_TYPE_UINT);
Expand Down
7 changes: 7 additions & 0 deletions render_delegate/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ void HdArnoldSetPositionFromValue(AtNode* node, const AtString& paramName, const
/// @param delegate Pointer to the Scene Delegate.
HDARNOLD_API
void HdArnoldSetRadiusFromPrimvar(AtNode* node, const SdfPath& id, HdSceneDelegate* delegate);
/// Sets radius attribute on an Arnold shape from a VtValue holding VtFloatArray. We expect this to be a width value,
/// so a (*0.5) function will be applied to the values.
///
/// @param node Pointer to an Arnold node.
/// @param value Value holding a VtFloatfArray.
HDARNOLD_API
void HdArnoldSetRadiusFromValue(AtNode* node, const VtValue& value);
/// Generates the idxs array for flattened USD values. When @p vertexCounts is not nullptr and not empty, the
/// the indices are reversed per polygon. The sum of the values stored in @p vertexCounts is expected to match
/// @p numIdxs.
Expand Down
6 changes: 6 additions & 0 deletions testsuite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ if (BUILD_UNIT_TESTS)
MAIN_DEPENDENCY hdArnold
)

add_unit_test(
GTEST
TEST_NAME test_0136
MAIN_DEPENDENCY hdArnold
)

endif ()
2 changes: 1 addition & 1 deletion testsuite/groups
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ ignore: test_0011 test_0040 test_0101 test_0108
# Notes: - test_0011 needs alembic - test_0040 needs the writer to be compiled -

# Tests that require the render delegate library, its dependencies and google test
unit_render_delegate: test_0039 test_0134
unit_render_delegate: test_0039 test_0134 test_0136

# Tests that require the ndr, its dependencies and google test
unit_ndr_plugin: test_0044
Expand Down
5 changes: 5 additions & 0 deletions testsuite/test_0136/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Testing the basis curve tools in the Render Delegate.

see #19

author: Pal Mezei
Loading

0 comments on commit 6b71299

Please sign in to comment.