File indexing completed on 2025-01-18 10:03:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef _BVH_RadixSorter_Header
0017 #define _BVH_RadixSorter_Header
0018
0019 #include <BVH_Sorter.hxx>
0020 #include <BVH_Builder.hxx>
0021 #include <NCollection_Array1.hxx>
0022 #include <NCollection_Shared.hxx>
0023 #include <OSD_Parallel.hxx>
0024
0025 #include <algorithm>
0026
0027
0028 typedef std::pair<unsigned int, Standard_Integer> BVH_EncodedLink;
0029
0030
0031
0032 template<class T, int N>
0033 class BVH_RadixSorter : public BVH_Sorter<T, N>
0034 {
0035 public:
0036
0037 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
0038
0039 public:
0040
0041
0042 BVH_RadixSorter (const BVH_Box<T, N>& theBox) : myBox (theBox) { }
0043
0044
0045 virtual void Perform (BVH_Set<T, N>* theSet) Standard_OVERRIDE { Perform (theSet, 0, theSet->Size() - 1); }
0046
0047
0048 virtual void Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal) Standard_OVERRIDE;
0049
0050
0051 const NCollection_Array1<BVH_EncodedLink>& EncodedLinks() const { return *myEncodedLinks; }
0052
0053 protected:
0054
0055
0056 BVH_Box<T, N> myBox;
0057
0058
0059 Handle(NCollection_Shared<NCollection_Array1<BVH_EncodedLink> >) myEncodedLinks;
0060
0061 };
0062
0063 namespace BVH
0064 {
0065
0066 struct BitPredicate
0067 {
0068 unsigned int myBit;
0069
0070
0071 BitPredicate (const Standard_Integer theDigit) : myBit (1U << theDigit) {}
0072
0073
0074 bool operator() (const BVH_EncodedLink theLink) const
0075 {
0076 return !(theLink.first & myBit);
0077 }
0078 };
0079
0080
0081 struct BitComparator
0082 {
0083 unsigned int myBit;
0084
0085
0086 BitComparator (const Standard_Integer theDigit) : myBit (1U << theDigit) {}
0087
0088
0089 bool operator() (BVH_EncodedLink theLink1, BVH_EncodedLink )
0090 {
0091 return !(theLink1.first & myBit);
0092 }
0093 };
0094
0095
0096 class RadixSorter
0097 {
0098 public:
0099
0100 typedef NCollection_Array1<BVH_EncodedLink>::iterator LinkIterator;
0101
0102 private:
0103
0104
0105 struct SortRange
0106 {
0107 LinkIterator myStart;
0108 LinkIterator myFinal;
0109 Standard_Integer myDigit;
0110 };
0111
0112
0113 class Functor
0114 {
0115 public:
0116 Functor(const SortRange (&aSplits)[2], const Standard_Boolean isParallel)
0117 : mySplits (aSplits),
0118 myIsParallel (isParallel)
0119 {
0120 }
0121
0122
0123 void operator()(const Standard_Integer theIndex) const
0124 {
0125 RadixSorter::Sort (mySplits[theIndex].myStart, mySplits[theIndex].myFinal,
0126 mySplits[theIndex].myDigit, myIsParallel);
0127 }
0128
0129 private:
0130 void operator=(const Functor&);
0131
0132 private:
0133 const SortRange (&mySplits)[2];
0134 Standard_Boolean myIsParallel;
0135 };
0136
0137 public:
0138
0139 static void Sort (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit, const Standard_Boolean isParallel)
0140 {
0141 if (theDigit < 24)
0142 {
0143 BVH::RadixSorter::perform (theStart, theFinal, theDigit);
0144 }
0145 else
0146 {
0147 LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theDigit));
0148 SortRange aSplits[2] = {
0149 {theStart, anOffset, theDigit - 1},
0150 {anOffset, theFinal, theDigit - 1}
0151 };
0152
0153 OSD_Parallel::For (0, 2, Functor (aSplits, isParallel), !isParallel);
0154 }
0155 }
0156
0157 protected:
0158
0159
0160 static void perform (LinkIterator theStart, LinkIterator theFinal, Standard_Integer theDigit = 29)
0161 {
0162 while (theStart != theFinal && theDigit >= 0)
0163 {
0164 LinkIterator anOffset = std::partition (theStart, theFinal, BitPredicate (theDigit--));
0165 perform (theStart, anOffset, theDigit);
0166 theStart = anOffset;
0167 }
0168 }
0169 };
0170 }
0171
0172
0173
0174
0175
0176 template<class T, int N>
0177 void BVH_RadixSorter<T, N>::Perform (BVH_Set<T, N>* theSet, const Standard_Integer theStart, const Standard_Integer theFinal)
0178 {
0179 Standard_STATIC_ASSERT (N == 2 || N == 3 || N == 4);
0180
0181 const Standard_Integer aDimension = 1024;
0182 const Standard_Integer aNbEffComp = N == 2 ? 2 : 3;
0183
0184 const BVH_VecNt aSceneMin = myBox.CornerMin();
0185 const BVH_VecNt aSceneMax = myBox.CornerMax();
0186
0187 BVH_VecNt aNodeMinSizeVecT (static_cast<T>(BVH::THE_NODE_MIN_SIZE));
0188 BVH::BoxMinMax<T, N>::CwiseMax (aNodeMinSizeVecT, aSceneMax - aSceneMin);
0189
0190 const BVH_VecNt aReverseSize = BVH_VecNt (static_cast<T>(aDimension)) / aNodeMinSizeVecT;
0191
0192 myEncodedLinks = new NCollection_Shared<NCollection_Array1<BVH_EncodedLink> >(theStart, theFinal);
0193
0194
0195 for (Standard_Integer aPrimIdx = theStart; aPrimIdx <= theFinal; ++aPrimIdx)
0196 {
0197 const BVH_VecNt aCenter = theSet->Box (aPrimIdx).Center();
0198 const BVH_VecNt aVoxelF = (aCenter - aSceneMin) * aReverseSize;
0199
0200 unsigned int aMortonCode = 0;
0201 for (Standard_Integer aCompIter = 0; aCompIter < aNbEffComp; ++aCompIter)
0202 {
0203 const Standard_Integer aVoxelI = BVH::IntFloor (BVH::VecComp<T, N>::Get (aVoxelF, aCompIter));
0204
0205 unsigned int aVoxel = static_cast<unsigned int>(Max (0, Min (aVoxelI, aDimension - 1)));
0206
0207 aVoxel = (aVoxel | (aVoxel << 16)) & 0x030000FF;
0208 aVoxel = (aVoxel | (aVoxel << 8)) & 0x0300F00F;
0209 aVoxel = (aVoxel | (aVoxel << 4)) & 0x030C30C3;
0210 aVoxel = (aVoxel | (aVoxel << 2)) & 0x09249249;
0211
0212 aMortonCode |= (aVoxel << aCompIter);
0213 }
0214
0215 myEncodedLinks->ChangeValue (aPrimIdx) = BVH_EncodedLink (aMortonCode, aPrimIdx);
0216 }
0217
0218
0219 BVH::RadixSorter::Sort (myEncodedLinks->begin(), myEncodedLinks->end(), 29, this->IsParallel());
0220
0221 NCollection_Array1<Standard_Integer> aLinkMap (theStart, theFinal);
0222 for (Standard_Integer aLinkIdx = theStart; aLinkIdx <= theFinal; ++aLinkIdx)
0223 {
0224 aLinkMap (myEncodedLinks->Value (aLinkIdx).second) = aLinkIdx;
0225 }
0226
0227
0228 Standard_Integer aPrimIdx = theStart;
0229 while (aPrimIdx <= theFinal)
0230 {
0231 const Standard_Integer aSortIdx = aLinkMap (aPrimIdx);
0232 if (aPrimIdx != aSortIdx)
0233 {
0234 theSet->Swap (aPrimIdx, aSortIdx);
0235 std::swap (aLinkMap (aPrimIdx),
0236 aLinkMap (aSortIdx));
0237 }
0238 else
0239 {
0240 ++aPrimIdx;
0241 }
0242 }
0243 }
0244
0245 #endif