8 #ifndef OPENVDB_HOUDINI_ATTRIBUTE_TRANSFER_UTIL_HAS_BEEN_INCLUDED
9 #define OPENVDB_HOUDINI_ATTRIBUTE_TRANSFER_UTIL_HAS_BEEN_INCLUDED
17 #include <GA/GA_PageIterator.h>
18 #include <GA/GA_SplittableRange.h>
19 #include <GEO/GEO_PrimPolySoup.h>
20 #include <SYS/SYS_Types.h>
29 #include <type_traits>
40 template <
typename ValueType>
inline ValueType
41 evalAttr(
const GA_Attribute* atr,
const GA_AIFTuple* aif,
42 GA_Offset off,
int idx)
45 aif->get(atr, off, value, idx);
46 return ValueType(value);
49 template <>
inline float
51 GA_Offset off,
int idx)
54 aif->get(atr, off, value, idx);
59 evalAttr<openvdb::Int32>(
const GA_Attribute* atr,
const GA_AIFTuple* aif,
60 GA_Offset off,
int idx)
63 aif->get(atr, off, value, idx);
68 evalAttr<openvdb::Int64>(
const GA_Attribute* atr,
const GA_AIFTuple* aif,
69 GA_Offset off,
int idx)
72 aif->get(atr, off, value, idx);
77 evalAttr<openvdb::Vec3i>(
const GA_Attribute* atr,
const GA_AIFTuple* aif,
83 aif->get(atr, off, comp, 0);
86 aif->get(atr, off, comp, 1);
89 aif->get(atr, off, comp, 2);
96 evalAttr<openvdb::Vec3s>(
const GA_Attribute* atr,
const GA_AIFTuple* aif,
102 aif->get(atr, off, comp, 0);
103 vec[0] = float(comp);
105 aif->get(atr, off, comp, 1);
106 vec[1] = float(comp);
108 aif->get(atr, off, comp, 2);
109 vec[2] = float(comp);
115 evalAttr<openvdb::Vec3d>(
const GA_Attribute* atr,
const GA_AIFTuple* aif,
121 aif->get(atr, off, comp, 0);
122 vec[0] = double(comp);
124 aif->get(atr, off, comp, 1);
125 vec[1] = double(comp);
127 aif->get(atr, off, comp, 2);
128 vec[2] = double(comp);
139 template <
typename ValueType>
inline ValueType
140 combine(
const ValueType& v0,
const ValueType& v1,
const ValueType& v2,
143 return ValueType(v0 * w[0] + v1 * w[1] + v2 * w[2]);
150 if (w[2] > w[0] && w[2] > w[1])
return v2;
151 if (w[1] > w[0] && w[1] > w[2])
return v1;
159 if (w[2] > w[0] && w[2] > w[1])
return v2;
160 if (w[1] > w[0] && w[1] > w[2])
return v1;
168 if (w[2] > w[0] && w[2] > w[1])
return v2;
169 if (w[1] > w[0] && w[1] > w[2])
return v1;
179 vec[0] = float(v0[0] * w[0] + v1[0] * w[1] + v2[0] * w[2]);
180 vec[1] = float(v0[1] * w[0] + v1[1] * w[1] + v2[1] * w[2]);
181 vec[2] = float(v0[2] * w[0] + v1[2] * w[1] + v2[2] * w[2]);
192 vec[0] = v0[0] * w[0] + v1[0] * w[1] + v2[0] * w[2];
193 vec[1] = v0[1] * w[0] + v1[1] * w[1] + v2[1] * w[2];
194 vec[2] = v0[2] * w[0] + v1[2] * w[1] + v2[2] * w[2];
205 template <
typename ValueType>
inline ValueType
209 defaults.get(idx, value);
210 return ValueType(value);
213 template <>
inline float
217 defaults.get(0, value);
222 evalAttrDefault<openvdb::Int32>(
const GA_Defaults& defaults,
int idx)
225 defaults.get(idx, value);
230 evalAttrDefault<openvdb::Int64>(
const GA_Defaults& defaults,
int idx)
233 defaults.get(idx, value);
238 evalAttrDefault<openvdb::Vec3i>(
const GA_Defaults& defaults,
int)
243 defaults.get(0, value);
246 defaults.get(1, value);
249 defaults.get(2, value);
256 evalAttrDefault<openvdb::Vec3s>(
const GA_Defaults& defaults,
int)
261 defaults.get(0, value);
262 vec[0] = float(value);
264 defaults.get(1, value);
265 vec[1] = float(value);
267 defaults.get(2, value);
268 vec[2] = float(value);
274 evalAttrDefault<openvdb::Vec3d>(
const GA_Defaults& defaults,
int)
279 defaults.get(0, value);
280 vec[0] = double(value);
282 defaults.get(1, value);
283 vec[1] = double(value);
285 defaults.get(2, value);
286 vec[2] = double(value);
291 template <>
inline openvdb::math::Quat<float>
292 evalAttrDefault<openvdb::math::Quat<float>>(
const GA_Defaults& defaults, int)
294 openvdb::math::Quat<float> quat;
297 for (
int i = 0; i < 4; i++) {
298 defaults.get(i, value);
299 quat[i] = float(value);
305 template <>
inline openvdb::math::Quat<double>
306 evalAttrDefault<openvdb::math::Quat<double>>(
const GA_Defaults& defaults, int)
308 openvdb::math::Quat<double> quat;
311 for (
int i = 0; i < 4; i++) {
312 defaults.get(i, value);
313 quat[i] = double(value);
319 template <>
inline openvdb::math::Mat3<float>
320 evalAttrDefault<openvdb::math::Mat3<float>>(
const GA_Defaults& defaults, int)
322 openvdb::math::Mat3<float> mat;
324 float* data = mat.asPointer();
326 for (
int i = 0; i < 9; i++) {
327 defaults.get(i, value);
328 data[i] = float(value);
334 template <>
inline openvdb::math::Mat3<double>
335 evalAttrDefault<openvdb::math::Mat3<double>>(
const GA_Defaults& defaults, int)
337 openvdb::math::Mat3<double> mat;
339 double* data = mat.asPointer();
341 for (
int i = 0; i < 9; i++) {
342 defaults.get(i, value);
343 data[i] = double(value);
349 template <>
inline openvdb::math::Mat4<float>
350 evalAttrDefault<openvdb::math::Mat4<float>>(
const GA_Defaults& defaults, int)
352 openvdb::math::Mat4<float> mat;
354 float* data = mat.asPointer();
356 for (
int i = 0; i < 16; i++) {
357 defaults.get(i, value);
358 data[i] = float(value);
364 template <>
inline openvdb::math::Mat4<double>
365 evalAttrDefault<openvdb::math::Mat4<double>>(
const GA_Defaults& defaults, int)
367 openvdb::math::Mat4<double> mat;
369 double* data = mat.asPointer();
371 for (
int i = 0; i < 16; i++) {
372 defaults.get(i, value);
373 data[i] = double(value);
386 using Ptr = std::shared_ptr<AttributeDetailBase>;
399 virtual std::string&
name() = 0;
414 template <
class VDBGr
idType>
422 const GA_Attribute* attribute,
423 const GA_AIFTuple* tupleAIF,
424 const int tupleIndex,
425 const bool isVector =
false);
433 std::string&
name()
override {
return mName; }
442 typename VDBGridType::Accessor mAccessor;
444 const GA_Attribute* mAttribute;
445 const GA_AIFTuple* mTupleAIF;
446 const int mTupleIndex;
451 template <
class VDBGr
idType>
460 template <
class VDBGr
idType>
463 const GA_Attribute* attribute,
464 const GA_AIFTuple* tupleAIF,
465 const int tupleIndex,
466 const bool isVector):
468 mAccessor(
openvdb::GridBase::grid<VDBGridType>(mGrid)->getAccessor()),
469 mAttribute(attribute),
471 mTupleIndex(tupleIndex)
473 std::ostringstream
name;
474 name << mAttribute->getName();
476 const int tupleSize = mTupleAIF->getTupleSize(mAttribute);
478 if(!isVector && tupleSize != 1) {
479 name <<
"_" << mTupleIndex;
486 template <
class VDBGr
idType>
492 mAttribute, mTupleAIF, offsets[0], mTupleIndex);
495 mAttribute, mTupleAIF, offsets[1], mTupleIndex);
498 mAttribute, mTupleAIF, offsets[2], mTupleIndex);
500 mAccessor.setValue(ijk, combine<ValueType>(v0, v1, v2, weights));
503 template <
class VDBGr
idType>
507 mAccessor.setValue(ijk,
508 evalAttr<ValueType>(mAttribute, mTupleAIF, offset, mTupleIndex));
511 template <
class VDBGr
idType>
528 using IterRange = openvdb::tree::IteratorRange<openvdb::Int32Tree::LeafCIter>;
536 const openvdb::math::Transform& transform,
537 const GU_Detail& meshGdp);
555 const openvdb::math::Transform& mTransform;
557 const GA_Detail &mMeshGdp;
566 const openvdb::math::Transform& transform,
567 const GU_Detail& meshGdp):
568 mPointAttributes(pointAttributes),
569 mVertexAttributes(vertexAttributes),
570 mPrimitiveAttributes(primitiveAttributes),
571 mClosestPrimGrid(closestPrimGrid),
572 mTransform(transform),
579 mPointAttributes(other.mPointAttributes.size()),
580 mVertexAttributes(other.mVertexAttributes.size()),
581 mPrimitiveAttributes(other.mPrimitiveAttributes.size()),
582 mClosestPrimGrid(other.mClosestPrimGrid),
583 mTransform(other.mTransform),
584 mMeshGdp(other.mMeshGdp)
589 for (
size_t i = 0, N = other.mPointAttributes.size(); i < N; ++i) {
590 mPointAttributes[i] = other.mPointAttributes[i]->copy();
593 for (
size_t i = 0, N = other.mVertexAttributes.size(); i < N; ++i) {
594 mVertexAttributes[i] = other.mVertexAttributes[i]->copy();
597 for (
size_t i = 0, N = other.mPrimitiveAttributes.size(); i < N; ++i) {
598 mPrimitiveAttributes[i] = other.mPrimitiveAttributes[i]->copy();
607 tbb::parallel_for(range, *
this);
625 const bool ptnAttrTransfer = mPointAttributes.size() > 0;
626 const bool vtxAttrTransfer = mVertexAttributes.size() > 0;
628 GA_Offset vtxOffsetList[4], ptnOffsetList[4], vtxOffsets[3], ptnOffsets[3], prmOffset;
631 for ( ; range; ++range) {
632 iter = range.iterator()->beginValueOn();
633 for ( ; iter; ++iter) {
637 const GA_Index prmIndex = iter.
getValue();
638 prmOffset = mMeshGdp.primitiveOffset(prmIndex);
641 for (
size_t i = 0, N = mPrimitiveAttributes.size(); i < N; ++i) {
642 mPrimitiveAttributes[i]->set(ijk, prmOffset);
645 if (!ptnAttrTransfer && !vtxAttrTransfer)
continue;
648 const GA_Primitive * primRef = mMeshGdp.getPrimitiveList().get(prmOffset);
650 const GA_Size vtxn = primRef->getVertexCount();
653 for (GA_Size vtx = 0; vtx < vtxn; ++vtx) {
654 const GA_Offset vtxoff = primRef->getVertexOffset(vtx);
655 ptnOffsetList[vtx] = mMeshGdp.vertexPoint(vtxoff);
656 vtxOffsetList[vtx] = vtxoff;
658 UT_Vector3 p = mMeshGdp.getPos3(ptnOffsetList[vtx]);
659 ptnList[vtx][0] = double(p[0]);
660 ptnList[vtx][1] = double(p[1]);
661 ptnList[vtx][2] = double(p[2]);
664 xyz = mTransform.indexToWorld(ijk);
669 ptnList[0], ptnList[2], ptnList[1], xyz, uvw);
671 vtxOffsets[0] = vtxOffsetList[0];
672 ptnOffsets[0] = ptnOffsetList[0];
673 vtxOffsets[1] = vtxOffsetList[2];
674 ptnOffsets[1] = ptnOffsetList[2];
675 vtxOffsets[2] = vtxOffsetList[1];
676 ptnOffsets[2] = ptnOffsetList[1];
680 ptnList[0], ptnList[3], ptnList[2], xyz, uvw2);
682 if ((cpt2 - xyz).lengthSqr() < (
cpt - xyz).lengthSqr()) {
684 vtxOffsets[1] = vtxOffsetList[3];
685 ptnOffsets[1] = ptnOffsetList[3];
686 vtxOffsets[2] = vtxOffsetList[2];
687 ptnOffsets[2] = ptnOffsetList[2];
692 for (
size_t i = 0, N = mVertexAttributes.size(); i < N; ++i) {
693 mVertexAttributes[i]->set(ijk, vtxOffsets, uvw);
697 for (
size_t i = 0, N = mPointAttributes.size(); i < N; ++i) {
698 mPointAttributes[i]->set(ijk, ptnOffsets, uvw);
715 using IterRange = openvdb::tree::IteratorRange<openvdb::Int32Tree::LeafCIter>;
720 const GU_Detail& ptGeop);
735 const GA_Detail &mPtGeo;
742 const GU_Detail& ptGeop):
743 mPointAttributes(pointAttributes),
744 mClosestPtnIdxGrid(closestPtnIdxGrid),
751 mPointAttributes(other.mPointAttributes.size()),
752 mClosestPtnIdxGrid(other.mClosestPtnIdxGrid),
758 for (
size_t i = 0, N = other.mPointAttributes.size(); i < N; ++i) {
759 mPointAttributes[i] = other.mPointAttributes[i]->copy();
768 tbb::parallel_for(range, *
this);
785 for ( ; range; ++range) {
786 iter = range.iterator()->beginValueOn();
787 for ( ; iter; ++iter) {
791 const GA_Index pointIndex = iter.
getValue();
792 const GA_Offset pointOffset = mPtGeo.pointOffset(pointIndex);
795 for (
size_t i = 0, N = mPointAttributes.size(); i < N; ++i) {
796 mPointAttributes[i]->set(ijk, pointOffset);
810 using Ptr = std::shared_ptr<AttributeCopyBase>;
813 virtual void copy(GA_Offset , GA_Offset ) = 0;
814 virtual void copy(GA_Offset&, GA_Offset&, GA_Offset&, GA_Offset ,
821 template<
class ValueType>
826 : mSourceAttr(sourceAttr)
827 , mTargetAttr(targetAttr)
828 , mAIFTuple(*mSourceAttr.getAIFTuple())
829 , mTupleSize(mAIFTuple.getTupleSize(&mSourceAttr))
833 void copy(GA_Offset source, GA_Offset target)
override
836 for (
int i = 0; i < mTupleSize; ++i) {
837 mAIFTuple.get(&mSourceAttr, source, data, i);
838 mAIFTuple.set(&mTargetAttr, target, data, i);
842 void copy(GA_Offset& v0, GA_Offset& v1, GA_Offset& v2, GA_Offset target,
845 doCopy<ValueType>(v0, v1, v2, target, uvw);
850 typename std::enable_if<std::is_integral<T>::value>::type
851 doCopy(GA_Offset& v0, GA_Offset& v1, GA_Offset& v2, GA_Offset target,
const openvdb::Vec3d& uvw)
853 GA_Offset source = v0;
860 if (uvw[2] <
min) source = v2;
864 for (
int i = 0; i < mTupleSize; ++i) {
865 mAIFTuple.get(&mSourceAttr, source, data, i);
866 mAIFTuple.set(&mTargetAttr, target, data, i);
870 template <
typename T>
871 typename std::enable_if<std::is_floating_point<T>::value>::type
872 doCopy(GA_Offset& v0, GA_Offset& v1, GA_Offset& v2, GA_Offset target,
const openvdb::Vec3d& uvw)
875 for (
int i = 0; i < mTupleSize; ++i) {
876 mAIFTuple.get(&mSourceAttr, v0, a, i);
877 mAIFTuple.get(&mSourceAttr, v1, b, i);
878 mAIFTuple.get(&mSourceAttr, v2, c, i);
879 mAIFTuple.set(&mTargetAttr, target, a*uvw[0] + b*uvw[1] + c*uvw[2], i);
884 const GA_Attribute& mSourceAttr;
885 GA_Attribute& mTargetAttr;
886 const GA_AIFTuple& mAIFTuple;
902 void copy(GA_Offset source, GA_Offset target)
override
909 void copy(GA_Offset& v0, GA_Offset& v1, GA_Offset& v2, GA_Offset target,
912 GA_Offset source = v0;
919 if (uvw[2] <
min) source = v2;
929 const GA_AIFSharedStringTuple&
mAIF;
940 const GA_AIFTuple * aifTuple = sourceAttr.getAIFTuple();
944 const GA_Storage sourceStorage = aifTuple->getStorage(&sourceAttr);
945 const GA_Storage targetStorage = aifTuple->getStorage(&targetAttr);
947 const int sourceTupleSize = aifTuple->getTupleSize(&sourceAttr);
948 const int targetTupleSize = aifTuple->getTupleSize(&targetAttr);
950 if (sourceStorage == targetStorage && sourceTupleSize == targetTupleSize) {
951 switch (sourceStorage)
962 case GA_STORE_REAL16:
963 case GA_STORE_REAL32:
967 case GA_STORE_REAL64:
976 const GA_AIFSharedStringTuple * aifString = sourceAttr.getAIFSharedStringTuple();
991 const GU_Detail& geo,
const std::set<GA_Index>& primitives,
const openvdb::Vec3d& p,
992 GA_Offset& vert0, GA_Offset& vert1, GA_Offset& vert2,
openvdb::Vec3d& uvw)
994 std::set<GA_Index>::const_iterator it = primitives.begin();
996 GA_Offset primOffset = GA_INVALID_OFFSET;
997 const GA_Primitive * primRef =
nullptr;
1001 UT_Vector3 tmpPoint;
1003 for (; it != primitives.end(); ++it) {
1005 const GA_Offset offset = geo.primitiveOffset(*it);
1006 primRef = geo.getPrimitiveList().get(offset);
1008 const GA_Size vertexCount = primRef->getVertexCount();
1011 if (vertexCount == 3 || vertexCount == 4) {
1013 tmpPoint = geo.getPos3(primRef->getPointOffset(0));
1014 a[0] = tmpPoint.
x();
1015 a[1] = tmpPoint.y();
1016 a[2] = tmpPoint.z();
1018 tmpPoint = geo.getPos3(primRef->getPointOffset(1));
1019 b[0] = tmpPoint.x();
1020 b[1] = tmpPoint.y();
1021 b[2] = tmpPoint.z();
1023 tmpPoint = geo.getPos3(primRef->getPointOffset(2));
1024 c[0] = tmpPoint.x();
1025 c[1] = tmpPoint.y();
1026 c[2] = tmpPoint.z();
1031 if (tmpDist < minDist) {
1033 primOffset = offset;
1035 vert0 = primRef->getVertexOffset(0);
1036 vert1 = primRef->getVertexOffset(2);
1037 vert2 = primRef->getVertexOffset(1);
1040 if (vertexCount == 4) {
1041 tmpPoint = geo.getPos3(primRef->getPointOffset(3));
1042 d[0] = tmpPoint.x();
1043 d[1] = tmpPoint.y();
1044 d[2] = tmpPoint.z();
1047 a, d, c, p, tmpUVW)).lengthSqr();
1048 if (tmpDist < minDist) {
1050 primOffset = offset;
1052 vert0 = primRef->getVertexOffset(0);
1053 vert1 = primRef->getVertexOffset(3);
1054 vert2 = primRef->getVertexOffset(2);
1068 const GU_Detail& geo, std::vector<GA_Index>& primitives,
const openvdb::Vec3d& p,
1069 GA_Offset& vert0, GA_Offset& vert1, GA_Offset& vert2,
openvdb::Vec3d& uvw)
1071 GA_Offset primOffset = GA_INVALID_OFFSET;
1072 const GA_Primitive * primRef =
nullptr;
1076 UT_Vector3 tmpPoint;
1078 std::sort(primitives.begin(), primitives.end());
1080 GA_Index lastPrim = -1;
1081 for (
size_t n = 0, N = primitives.size(); n < N; ++n) {
1082 if (primitives[n] == lastPrim)
continue;
1083 lastPrim = primitives[n];
1085 const GA_Offset offset = geo.primitiveOffset(lastPrim);
1086 primRef = geo.getPrimitiveList().get(offset);
1088 const GA_Size vertexCount = primRef->getVertexCount();
1091 if (vertexCount == 3 || vertexCount == 4) {
1093 tmpPoint = geo.getPos3(primRef->getPointOffset(0));
1094 a[0] = tmpPoint.x();
1095 a[1] = tmpPoint.y();
1096 a[2] = tmpPoint.z();
1098 tmpPoint = geo.getPos3(primRef->getPointOffset(1));
1099 b[0] = tmpPoint.x();
1100 b[1] = tmpPoint.y();
1101 b[2] = tmpPoint.z();
1103 tmpPoint = geo.getPos3(primRef->getPointOffset(2));
1104 c[0] = tmpPoint.x();
1105 c[1] = tmpPoint.y();
1106 c[2] = tmpPoint.z();
1111 if (tmpDist < minDist) {
1113 primOffset = offset;
1115 vert0 = primRef->getVertexOffset(0);
1116 vert1 = primRef->getVertexOffset(2);
1117 vert2 = primRef->getVertexOffset(1);
1120 if (vertexCount == 4) {
1121 tmpPoint = geo.getPos3(primRef->getPointOffset(3));
1122 d[0] = tmpPoint.x();
1123 d[1] = tmpPoint.y();
1124 d[2] = tmpPoint.z();
1127 a, d, c, p, tmpUVW)).lengthSqr();
1128 if (tmpDist < minDist) {
1130 primOffset = offset;
1132 vert0 = primRef->getVertexOffset(0);
1133 vert1 = primRef->getVertexOffset(3);
1134 vert2 = primRef->getVertexOffset(2);
1148 template<
class Gr
idType>
1157 const GU_Detail& sourceGeo,
1158 GU_Detail& targetGeo,
1159 const GridType& indexGrid,
1162 : mSourceGeo(sourceGeo)
1163 , mTargetGeo(targetGeo)
1164 , mIndexGrid(indexGrid)
1165 , mPrimAttributes(primAttributes)
1166 , mVertAttributes(vertAttributes)
1170 inline void operator()(
const GA_SplittableRange&)
const;
1173 inline void copyPrimAttrs(
const GA_Primitive&,
const UT_Vector3&,
IndexAccT&)
const;
1175 template<
typename PrimT>
1176 inline void copyVertAttrs(
const PrimT&,
const UT_Vector3&,
IndexAccT&)
const;
1178 const GU_Detail& mSourceGeo;
1179 GU_Detail& mTargetGeo;
1180 const GridType& mIndexGrid;
1186 template<
class Gr
idType>
1190 if (mPrimAttributes.empty() && mVertAttributes.empty())
return;
1192 auto polyIdxAcc = mIndexGrid.getConstAccessor();
1194 for (GA_PageIterator pageIt = range.beginPages(); !pageIt.atEnd(); ++pageIt) {
1195 auto start = GA_Offset(), end = GA_Offset();
1196 for (GA_Iterator blockIt(pageIt.begin()); blockIt.blockAdvance(start, end); ) {
1197 for (
auto targetOffset = start; targetOffset < end; ++targetOffset) {
1198 const auto* target = mTargetGeo.getPrimitiveList().get(targetOffset);
1199 if (!target)
continue;
1201 const auto targetN = mTargetGeo.getGEOPrimitive(targetOffset)->computeNormal();
1203 if (!mPrimAttributes.empty()) {
1205 copyPrimAttrs(*target, targetN, polyIdxAcc);
1208 if (!mVertAttributes.empty()) {
1209 if (target->getTypeId() != GA_PRIMPOLYSOUP) {
1210 copyVertAttrs(*target, targetN, polyIdxAcc);
1212 if (
const auto* soup = UTverify_cast<const GEO_PrimPolySoup*>(target)) {
1214 using SizeRange = UT_BlockedRange<GA_Size>;
1215 const auto processPolyRange = [&](
const SizeRange& range) {
1216 auto threadLocalPolyIdxAcc = mIndexGrid.getConstAccessor();
1217 for (GEO_PrimPolySoup::PolygonIterator it(*soup, range.begin());
1218 !it.atEnd() && (it.polygon() < range.end()); ++it)
1220 copyVertAttrs(it, it.computeNormal(), threadLocalPolyIdxAcc);
1223 UTparallelFor(
SizeRange(0, soup->getPolygonCount()), processPolyRange);
1238 template<
class Gr
idType>
1241 const GA_Primitive& targetPrim,
1242 const UT_Vector3& targetNormal,
1243 IndexAccT& polyIdxAcc)
const
1245 const auto& transform = mIndexGrid.transform();
1247 UT_Vector3 sourceN, targetN = targetNormal;
1248 const bool isPolySoup = (targetPrim.getTypeId() == GA_PRIMPOLYSOUP);
1252 int count =
static_cast<int>(targetPrim.getVertexCount());
1253 for (
int vtx = 0; vtx < count; ++vtx) {
1254 pos += UTvdbConvert(targetPrim.getPos3(vtx));
1256 if (count > 1) pos /= double(count);
1261 std::vector<GA_Index> primitives(8), similarPrimitives(8);
1264 for (
int d = 0; d < 8; ++d) {
1265 ijk[0] = coord[0] + (((d & 0x02) >> 1) ^ (d & 0x01));
1266 ijk[1] = coord[1] + ((d & 0x02) >> 1);
1267 ijk[2] = coord[2] + ((d & 0x04) >> 2);
1269 if (polyIdxAcc.probeValue(ijk, primIndex) &&
1272 GA_Offset tmpOffset = mSourceGeo.primitiveOffset(primIndex);
1273 sourceN = mSourceGeo.getGEOPrimitive(tmpOffset)->computeNormal();
1278 if (isPolySoup || sourceN.dot(targetN) > 0.5) {
1279 similarPrimitives.push_back(primIndex);
1281 primitives.push_back(primIndex);
1286 if (!primitives.empty() || !similarPrimitives.empty()) {
1287 GA_Offset source, v0, v1, v2;
1289 if (!similarPrimitives.empty()) {
1291 mSourceGeo, similarPrimitives, pos, v0, v1, v2, uvw);
1294 mSourceGeo, primitives, pos, v0, v1, v2, uvw);
1298 const auto targetOffset = targetPrim.getMapOffset();
1299 for (
size_t n = 0, N = mPrimAttributes.size(); n < N; ++n) {
1300 mPrimAttributes[n]->copy(source, targetOffset);
1311 template<
typename Gr
idType>
1312 template<
typename PrimT>
1314 TransferPrimitiveAttributesOp<GridType>::copyVertAttrs(
1315 const PrimT& targetPrim,
1316 const UT_Vector3& targetNormal,
1317 IndexAccT& polyIdxAcc)
const
1319 const auto& transform = mIndexGrid.transform();
1323 UT_Vector3 sourceNormal;
1324 std::vector<GA_Index> primitives(8), similarPrimitives(8);
1326 for (GA_Size vtx = 0, vtxN = targetPrim.getVertexCount(); vtx < vtxN; ++vtx) {
1327 pos = UTvdbConvert(targetPrim.getPos3(vtx));
1331 similarPrimitives.clear();
1333 for (
int d = 0; d < 8; ++d) {
1334 ijk[0] = coord[0] + (((d & 0x02) >> 1) ^ (d & 0x01));
1335 ijk[1] = coord[1] + ((d & 0x02) >> 1);
1336 ijk[2] = coord[2] + ((d & 0x04) >> 2);
1338 if (polyIdxAcc.probeValue(ijk, primIndex) &&
1341 GA_Offset tmpOffset = mSourceGeo.primitiveOffset(primIndex);
1342 sourceNormal = mSourceGeo.getGEOPrimitive(tmpOffset)->computeNormal();
1343 if (sourceNormal.dot(targetNormal) > 0.5) {
1344 primitives.push_back(primIndex);
1349 if (!primitives.empty() || !similarPrimitives.empty()) {
1350 GA_Offset v0, v1, v2;
1351 if (!similarPrimitives.empty()) {
1357 for (
size_t n = 0, N = mVertAttributes.size(); n < N; ++n) {
1358 mVertAttributes[n]->copy(v0, v1, v2, targetPrim.getVertexOffset(vtx), uvw);
1368 template<
class Gr
idType>
1373 const GU_Detail& sourceGeo, GU_Detail& targetGeo,
const GridType& indexGrid,
1374 std::vector<AttributeCopyBase::Ptr>& pointAttributes,
1375 const GA_PrimitiveGroup* surfacePrims =
nullptr);
1377 void operator()(
const GA_SplittableRange&)
const;
1379 const GU_Detail& mSourceGeo;
1380 GU_Detail& mTargetGeo;
1381 const GridType& mIndexGrid;
1382 std::vector<AttributeCopyBase::Ptr>& mPointAttributes;
1383 const GA_PrimitiveGroup* mSurfacePrims;
1386 template<
class Gr
idType>
1388 const GU_Detail& sourceGeo, GU_Detail& targetGeo,
const GridType& indexGrid,
1389 std::vector<AttributeCopyBase::Ptr>& pointAttributes,
1390 const GA_PrimitiveGroup* surfacePrims)
1391 : mSourceGeo(sourceGeo)
1392 , mTargetGeo(targetGeo)
1393 , mIndexGrid(indexGrid)
1394 , mPointAttributes(pointAttributes)
1395 , mSurfacePrims(surfacePrims)
1399 template<
class Gr
idType>
1403 using IndexT =
typename GridType::ValueType;
1405 GA_Offset start, end, vtxOffset, primOffset, target, v0, v1, v2;
1407 typename GridType::ConstAccessor polyIdxAcc = mIndexGrid.getConstAccessor();
1408 const openvdb::math::Transform& transform = mIndexGrid.transform();
1410 std::vector<GA_Index> primitives(8);
1413 for (GA_PageIterator pageIt = range.beginPages(); !pageIt.atEnd(); ++pageIt) {
1414 for (GA_Iterator blockIt(pageIt.begin()); blockIt.blockAdvance(start, end); ) {
1415 for (target = start; target < end; ++target) {
1418 vtxOffset = mTargetGeo.pointVertex(target);
1421 if (mSurfacePrims) {
1422 bool surfacePrim =
false;
1424 while (GAisValid(vtxOffset)) {
1426 primOffset = mTargetGeo.vertexPrimitive(vtxOffset);
1428 if (mSurfacePrims->containsIndex(mTargetGeo.primitiveIndex(primOffset))) {
1433 vtxOffset = mTargetGeo.vertexToNextVertex(vtxOffset);
1436 if (!surfacePrim)
continue;
1439 const UT_Vector3 p = mTargetGeo.getPos3(target);
1444 indexPos = transform.worldToIndex(pos);
1445 coord[0] = int(std::floor(indexPos[0]));
1446 coord[1] = int(std::floor(indexPos[1]));
1447 coord[2] = int(std::floor(indexPos[2]));
1452 for (
int d = 0; d < 8; ++d) {
1453 ijk[0] = coord[0] + (((d & 0x02) >> 1) ^ (d & 0x01));
1454 ijk[1] = coord[1] + ((d & 0x02) >> 1);
1455 ijk[2] = coord[2] + ((d & 0x04) >> 2);
1457 if (polyIdxAcc.probeValue(ijk, primIndex) &&
1459 primitives.push_back(primIndex);
1463 if (!primitives.empty()) {
1466 v0 = mSourceGeo.vertexPoint(v0);
1467 v1 = mSourceGeo.vertexPoint(v1);
1468 v2 = mSourceGeo.vertexPoint(v2);
1470 for (
size_t n = 0, N = mPointAttributes.size(); n < N; ++n) {
1471 mPointAttributes[n]->copy(v0, v1, v2, target, uvw);
1483 template<
class Gr
idType>
1486 const GU_Detail& sourceGeo,
1487 GU_Detail& targetGeo,
1488 GridType& indexGrid,
1490 const GA_PrimitiveGroup* primitives =
nullptr)
1493 GA_AttributeDict::iterator it = sourceGeo.primitiveAttribs().begin(GA_SCOPE_PUBLIC);
1495 if (indexGrid.activeVoxelCount() == 0)
return;
1497 std::vector<AttributeCopyBase::Ptr> primAttributeList;
1500 for (; !it.atEnd(); ++it) {
1501 const GA_Attribute* sourceAttr = it.attrib();
1502 if (
nullptr == targetGeo.findPrimitiveAttribute(it.name())) {
1503 targetGeo.addPrimAttrib(sourceAttr);
1505 GA_Attribute* targetAttr = targetGeo.findPrimitiveAttribute(it.name());
1507 if (sourceAttr && targetAttr) {
1509 if(att) primAttributeList.push_back(att);
1515 std::vector<AttributeCopyBase::Ptr> vertAttributeList;
1517 it = sourceGeo.vertexAttribs().begin(GA_SCOPE_PUBLIC);
1520 for (; !it.atEnd(); ++it) {
1521 const GA_Attribute* sourceAttr = it.attrib();
1522 if (
nullptr == targetGeo.findVertexAttribute(it.name())) {
1523 targetGeo.addVertexAttrib(sourceAttr);
1525 GA_Attribute* targetAttr = targetGeo.findVertexAttribute(it.name());
1527 if (sourceAttr && targetAttr) {
1528 targetAttr->hardenAllPages();
1530 if(att) vertAttributeList.push_back(att);
1534 if (!boss.
wasInterrupted() && (!primAttributeList.empty() || !vertAttributeList.empty())) {
1536 UTparallelFor(GA_SplittableRange(targetGeo.getPrimitiveRange(primitives)),
1538 primAttributeList, vertAttributeList));
1542 std::vector<AttributeCopyBase::Ptr> pointAttributeList;
1543 it = sourceGeo.pointAttribs().begin(GA_SCOPE_PUBLIC);
1546 for (; !it.atEnd(); ++it) {
1547 if (std::string(it.name()) ==
"P")
continue;
1549 const GA_Attribute* sourceAttr = it.attrib();
1550 if (
nullptr == targetGeo.findPointAttribute(it.name())) {
1551 targetGeo.addPointAttrib(sourceAttr);
1553 GA_Attribute* targetAttr = targetGeo.findPointAttribute(it.name());
1555 if (sourceAttr && targetAttr) {
1557 if(att) pointAttributeList.push_back(att);
1562 UTparallelFor(GA_SplittableRange(targetGeo.getPointRange()),
1564 pointAttributeList, primitives));
1572 #endif // OPENVDB_HOUDINI_ATTRIBUTE_TRANSFER_UTIL_HAS_BEEN_INCLUDED