Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/hydra/curves.cpp')
-rw-r--r--intern/cycles/hydra/curves.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/intern/cycles/hydra/curves.cpp b/intern/cycles/hydra/curves.cpp
new file mode 100644
index 00000000000..2007a5d09ca
--- /dev/null
+++ b/intern/cycles/hydra/curves.cpp
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2022 NVIDIA Corporation
+ * Copyright 2022 Blender Foundation */
+
+#include "hydra/curves.h"
+#include "hydra/geometry.inl"
+#include "scene/hair.h"
+
+#include <pxr/imaging/hd/extComputationUtils.h>
+
+HDCYCLES_NAMESPACE_OPEN_SCOPE
+
+HdCyclesCurves::HdCyclesCurves(const SdfPath &rprimId
+#if PXR_VERSION < 2102
+ ,
+ const SdfPath &instancerId
+#endif
+ )
+ : HdCyclesGeometry(rprimId
+#if PXR_VERSION < 2102
+ ,
+ instancerId
+#endif
+ )
+{
+}
+
+HdCyclesCurves::~HdCyclesCurves()
+{
+}
+
+HdDirtyBits HdCyclesCurves::GetInitialDirtyBitsMask() const
+{
+ HdDirtyBits bits = HdCyclesGeometry::GetInitialDirtyBitsMask();
+ bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
+ HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology;
+ return bits;
+}
+
+HdDirtyBits HdCyclesCurves::_PropagateDirtyBits(HdDirtyBits bits) const
+{
+ if (bits & (HdChangeTracker::DirtyTopology)) {
+ // Changing topology clears the geometry, so need to populate everything again
+ bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
+ HdChangeTracker::DirtyPrimvar;
+ }
+
+ return bits;
+}
+
+void HdCyclesCurves::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
+{
+ if (HdChangeTracker::IsTopologyDirty(dirtyBits, GetId())) {
+ PopulateTopology(sceneDelegate);
+ }
+
+ if (dirtyBits & HdChangeTracker::DirtyPoints) {
+ PopulatePoints(sceneDelegate);
+ }
+
+ if (dirtyBits & HdChangeTracker::DirtyWidths) {
+ PopulateWidths(sceneDelegate);
+ }
+
+ if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
+ PopulatePrimvars(sceneDelegate);
+ }
+
+ rebuild = (_geom->curve_keys_is_modified()) || (_geom->curve_radius_is_modified());
+}
+
+void HdCyclesCurves::PopulatePoints(HdSceneDelegate *sceneDelegate)
+{
+ VtValue value;
+
+ for (const HdExtComputationPrimvarDescriptor &desc :
+ sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex)) {
+ if (desc.name == HdTokens->points) {
+ auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
+ const auto valueStoreIt = valueStore.find(desc.name);
+ if (valueStoreIt != valueStore.end()) {
+ value = std::move(valueStoreIt->second);
+ }
+ break;
+ }
+ }
+
+ if (value.IsEmpty()) {
+ value = GetPrimvar(sceneDelegate, HdTokens->points);
+ }
+
+ if (!value.IsHolding<VtVec3fArray>()) {
+ TF_WARN("Invalid points data for %s", GetId().GetText());
+ return;
+ }
+
+ const auto &points = value.UncheckedGet<VtVec3fArray>();
+
+ array<float3> pointsDataCycles;
+ pointsDataCycles.reserve(points.size());
+
+ for (const GfVec3f &point : points) {
+ pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
+ }
+
+ _geom->set_curve_keys(pointsDataCycles);
+}
+
+void HdCyclesCurves::PopulateWidths(HdSceneDelegate *sceneDelegate)
+{
+ VtValue value = GetPrimvar(sceneDelegate, HdTokens->widths);
+ const HdInterpolation interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->widths);
+
+ if (!value.IsHolding<VtFloatArray>()) {
+ TF_WARN("Invalid widths data for %s", GetId().GetText());
+ return;
+ }
+
+ const auto &widths = value.UncheckedGet<VtFloatArray>();
+
+ array<float> radiusDataCycles;
+ radiusDataCycles.reserve(widths.size());
+
+ if (interpolation == HdInterpolationConstant) {
+ TF_VERIFY(widths.size() == 1);
+
+ const float constantRadius = widths[0] * 0.5f;
+
+ for (size_t i = 0; i < _geom->num_keys(); ++i) {
+ radiusDataCycles.push_back_reserved(constantRadius);
+ }
+ }
+ else if (interpolation == HdInterpolationVertex) {
+ TF_VERIFY(widths.size() == _geom->num_keys());
+
+ for (size_t i = 0; i < _geom->num_keys(); ++i) {
+ radiusDataCycles.push_back_reserved(widths[i] * 0.5f);
+ }
+ }
+
+ _geom->set_curve_radius(radiusDataCycles);
+}
+
+void HdCyclesCurves::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
+{
+ Scene *const scene = (Scene *)_geom->get_owner();
+
+ const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
+ std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_CURVE_KEY),
+ std::make_pair(HdInterpolationVarying, ATTR_ELEMENT_CURVE_KEY),
+ std::make_pair(HdInterpolationUniform, ATTR_ELEMENT_CURVE),
+ std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
+ };
+
+ for (const auto &interpolation : interpolations) {
+ for (const HdPrimvarDescriptor &desc :
+ GetPrimvarDescriptors(sceneDelegate, interpolation.first)) {
+ // Skip special primvars that are handled separately
+ if (desc.name == HdTokens->points || desc.name == HdTokens->widths) {
+ continue;
+ }
+
+ VtValue value = GetPrimvar(sceneDelegate, desc.name);
+ if (value.IsEmpty()) {
+ continue;
+ }
+
+ const ustring name(desc.name.GetString());
+
+ AttributeStandard std = ATTR_STD_NONE;
+ if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
+ std = ATTR_STD_UV;
+ }
+ else if (desc.name == HdTokens->displayColor &&
+ interpolation.first == HdInterpolationConstant) {
+ if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
+ const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
+ _instances[0]->set_color(make_float3(color[0], color[1], color[2]));
+ }
+ }
+
+ // Skip attributes that are not needed
+ if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
+ _geom->need_attribute(scene, name)) {
+ ApplyPrimvars(_geom->attributes, name, value, interpolation.second, std);
+ }
+ }
+ }
+}
+
+void HdCyclesCurves::PopulateTopology(HdSceneDelegate *sceneDelegate)
+{
+ // Clear geometry before populating it again with updated topology
+ _geom->clear(true);
+
+ HdBasisCurvesTopology topology = GetBasisCurvesTopology(sceneDelegate);
+
+ _geom->reserve_curves(topology.GetNumCurves(), topology.CalculateNeededNumberOfControlPoints());
+
+ const VtIntArray vertCounts = topology.GetCurveVertexCounts();
+
+ for (int curve = 0, key = 0; curve < topology.GetNumCurves(); ++curve) {
+ // Always reference shader at index zero, which is the primitive material
+ _geom->add_curve(key, 0);
+
+ key += vertCounts[curve];
+ }
+}
+
+HDCYCLES_NAMESPACE_CLOSE_SCOPE