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/instancer.cpp')
-rw-r--r--intern/cycles/hydra/instancer.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/intern/cycles/hydra/instancer.cpp b/intern/cycles/hydra/instancer.cpp
new file mode 100644
index 00000000000..ade5141cd19
--- /dev/null
+++ b/intern/cycles/hydra/instancer.cpp
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2022 NVIDIA Corporation
+ * Copyright 2022 Blender Foundation */
+
+#include "hydra/instancer.h"
+
+#include <pxr/base/gf/quatd.h>
+#include <pxr/imaging/hd/sceneDelegate.h>
+
+HDCYCLES_NAMESPACE_OPEN_SCOPE
+
+HdCyclesInstancer::HdCyclesInstancer(HdSceneDelegate *delegate,
+ const SdfPath &instancerId
+#if PXR_VERSION <= 2011
+ ,
+ const SdfPath &parentId
+#endif
+ )
+ : HdInstancer(delegate,
+ instancerId
+#if PXR_VERSION <= 2011
+ ,
+ parentId
+#endif
+ )
+{
+}
+
+HdCyclesInstancer::~HdCyclesInstancer()
+{
+}
+
+#if PXR_VERSION > 2011
+void HdCyclesInstancer::Sync(HdSceneDelegate *sceneDelegate,
+ HdRenderParam *renderParam,
+ HdDirtyBits *dirtyBits)
+{
+ _UpdateInstancer(sceneDelegate, dirtyBits);
+
+ if (HdChangeTracker::IsAnyPrimvarDirty(*dirtyBits, GetId())) {
+ SyncPrimvars();
+ }
+}
+#endif
+
+void HdCyclesInstancer::SyncPrimvars()
+{
+ HdSceneDelegate *const sceneDelegate = GetDelegate();
+ const HdDirtyBits dirtyBits =
+ sceneDelegate->GetRenderIndex().GetChangeTracker().GetInstancerDirtyBits(GetId());
+
+ for (const HdPrimvarDescriptor &desc :
+ sceneDelegate->GetPrimvarDescriptors(GetId(), HdInterpolationInstance)) {
+ if (!HdChangeTracker::IsPrimvarDirty(dirtyBits, GetId(), desc.name)) {
+ continue;
+ }
+
+ const VtValue value = sceneDelegate->Get(GetId(), desc.name);
+ if (value.IsEmpty()) {
+ continue;
+ }
+
+ if (desc.name == HdInstancerTokens->translate) {
+ _translate = value.Get<VtVec3fArray>();
+ }
+ else if (desc.name == HdInstancerTokens->rotate) {
+ _rotate = value.Get<VtVec4fArray>();
+ }
+ else if (desc.name == HdInstancerTokens->scale) {
+ _scale = value.Get<VtVec3fArray>();
+ }
+ else if (desc.name == HdInstancerTokens->instanceTransform) {
+ _instanceTransform = value.Get<VtMatrix4dArray>();
+ }
+ }
+
+ sceneDelegate->GetRenderIndex().GetChangeTracker().MarkInstancerClean(GetId());
+}
+
+VtMatrix4dArray HdCyclesInstancer::ComputeInstanceTransforms(const SdfPath &prototypeId)
+{
+#if PXR_VERSION <= 2011
+ SyncPrimvars();
+#endif
+
+ const VtIntArray instanceIndices = GetDelegate()->GetInstanceIndices(GetId(), prototypeId);
+ const GfMatrix4d instanceTransform = GetDelegate()->GetInstancerTransform(GetId());
+
+ VtMatrix4dArray transforms;
+ transforms.reserve(instanceIndices.size());
+
+ for (int index : instanceIndices) {
+ GfMatrix4d transform = instanceTransform;
+
+ if (index < _translate.size()) {
+ GfMatrix4d translateMat(1);
+ translateMat.SetTranslate(_translate[index]);
+ transform *= translateMat;
+ }
+
+ if (index < _rotate.size()) {
+ GfMatrix4d rotateMat(1);
+ const GfVec4f &quat = _rotate[index];
+ rotateMat.SetRotate(GfQuatd(quat[0], quat[1], quat[2], quat[3]));
+ transform *= rotateMat;
+ }
+
+ if (index < _scale.size()) {
+ GfMatrix4d scaleMat(1);
+ scaleMat.SetScale(_scale[index]);
+ transform *= scaleMat;
+ }
+
+ if (index < _instanceTransform.size()) {
+ transform *= _instanceTransform[index];
+ }
+
+ transforms.push_back(transform);
+ }
+
+ VtMatrix4dArray resultTransforms;
+
+ if (const auto instancer = static_cast<HdCyclesInstancer *>(
+ GetDelegate()->GetRenderIndex().GetInstancer(GetParentId()))) {
+ for (const GfMatrix4d &parentTransform : instancer->ComputeInstanceTransforms(GetId())) {
+ for (const GfMatrix4d &localTransform : transforms) {
+ resultTransforms.push_back(parentTransform * localTransform);
+ }
+ }
+ }
+ else {
+ resultTransforms = std::move(transforms);
+ }
+
+ return resultTransforms;
+}
+
+HDCYCLES_NAMESPACE_CLOSE_SCOPE