155 lines
4.3 KiB
C++
155 lines
4.3 KiB
C++
/* SPDX-FileCopyrightText: 2022 NVIDIA Corporation
|
|
* SPDX-FileCopyrightText: 2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#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 PXR_VERSION < 2311
|
|
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>();
|
|
}
|
|
#else
|
|
if (desc.name == HdInstancerTokens->instanceTranslations) {
|
|
_translate = value.Get<VtVec3fArray>();
|
|
}
|
|
else if (desc.name == HdInstancerTokens->instanceRotations) {
|
|
_rotate = value.Get<VtVec4fArray>();
|
|
}
|
|
else if (desc.name == HdInstancerTokens->instanceScales) {
|
|
_scale = value.Get<VtVec3fArray>();
|
|
}
|
|
else if (desc.name == HdInstancerTokens->instanceTransforms) {
|
|
_instanceTransform = value.Get<VtMatrix4dArray>();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
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
|