Field3D
SparseField.h
Go to the documentation of this file.
1//----------------------------------------------------------------------------//
2
3/*
4 * Copyright (c) 2009 Sony Pictures Imageworks Inc
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
17 * distribution. Neither the name of Sony Pictures Imageworks nor the
18 * names of its contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36//----------------------------------------------------------------------------//
37
42//----------------------------------------------------------------------------//
43
44#ifndef _INCLUDED_Field3D_SparseField_H_
45#define _INCLUDED_Field3D_SparseField_H_
46
47//----------------------------------------------------------------------------//
48
49#include <vector>
50
51#include <boost/thread/mutex.hpp>
52#include <boost/lexical_cast.hpp>
53
54#include "Field.h"
55#include "SparseFile.h"
56
57#define BLOCK_ORDER 4 // 2^BLOCK_ORDER is the block size along each axis
58
59//----------------------------------------------------------------------------//
60
61#include "ns.h"
62
64
65//----------------------------------------------------------------------------//
66// Forward declarations
67//----------------------------------------------------------------------------//
68
69template <class Field_T>
71template <class Field_T>
73
74//----------------------------------------------------------------------------//
75// LinearSparseFieldInterp
76//----------------------------------------------------------------------------//
77
78/* \class LinearSparseFieldInterp
79 \ingroup field
80 \brief Linear interpolator optimized for fields with a fastValue function
81*/
82
83//----------------------------------------------------------------------------//
84
85template <typename Data_T>
87{
88public:
89
90 // Typedefs ------------------------------------------------------------------
91
92 typedef Data_T value_type;
93 typedef boost::intrusive_ptr<LinearSparseFieldInterp> Ptr;
94
95 // RTTI replacement ----------------------------------------------------------
96
99
100 static const char *staticClassName()
101 {
102 return "LinearSparseFieldInterp";
103 }
104
105 static const char* staticClassType()
106 {
107 return ms_classType.name();
108 }
109
110 // Main methods --------------------------------------------------------------
111
112 value_type sample(const SparseField<Data_T> &field, const V3d &vsP) const
113 {
114 // Pixel centers are at .5 coordinates
115 // NOTE: Don't use contToDisc for this, we're looking for sample
116 // point locations, not coordinate shifts.
117 FIELD3D_VEC3_T<double> p(vsP - FIELD3D_VEC3_T<double>(0.5));
118
119 // Lower left corner
120 V3i c1(static_cast<int>(floor(p.x)),
121 static_cast<int>(floor(p.y)),
122 static_cast<int>(floor(p.z)));
123 // Upper right corner
124 V3i c2(c1 + V3i(1));
125 // C1 fractions
126 FIELD3D_VEC3_T<double> f1(static_cast<FIELD3D_VEC3_T<double> >(c2) - p);
127 // C2 fraction
128 FIELD3D_VEC3_T<double> f2(static_cast<FIELD3D_VEC3_T<double> >(1.0) - f1);
129
130 const Box3i &dataWindow = field.dataWindow();
131
132 // Clamp the coordinates
133 c1.x = std::min(dataWindow.max.x, std::max(dataWindow.min.x, c1.x));
134 c1.y = std::min(dataWindow.max.y, std::max(dataWindow.min.y, c1.y));
135 c1.z = std::min(dataWindow.max.z, std::max(dataWindow.min.z, c1.z));
136 c2.x = std::min(dataWindow.max.x, std::max(dataWindow.min.x, c2.x));
137 c2.y = std::min(dataWindow.max.y, std::max(dataWindow.min.y, c2.y));
138 c2.z = std::min(dataWindow.max.z, std::max(dataWindow.min.z, c2.z));
139
140 // Determine which block we're in
141 int i = c1.x, j = c1.y, k = c1.z, vi, vj, vk, bi, bj, bk;
142 field.applyDataWindowOffset(i, j, k);
143 field.getVoxelInBlock(i, j, k, vi, vj, vk);
144 field.getBlockCoord(i, j, k, bi, bj, bk);
145 int blockSize = 1 << field.blockOrder();
146
147 // If in the middle of a block, optimize lookup stencil
148 if (vi < blockSize - 1 && vj < blockSize - 1 && vk < blockSize - 1) {
149 if (field.blockIsAllocated(bi, bj, bk)) {
150 // Ensure block data is active and kept alive
151 const int blockId = field.blockId(bi, bj, bk);
152 const bool isDynamicLoad = field.isDynamicLoad();
153 if (isDynamicLoad) {
154 field.incBlockRef(blockId);
155 field.activateBlock(blockId);
156 }
157 // Only do work if the block is allocated
158 const Data_T * const p = field.blockData(bi, bj, bk);
159 const Data_T * const c111 =
160 p + vi + vj * blockSize + vk * blockSize * blockSize;
161 const Data_T * const c121 = c111 + blockSize * (c2.y - c1.y);
162 const Data_T * const
163 c112 = c111 + blockSize * blockSize * (c2.z - c1.z);
164 const Data_T * const c122 = c112 + blockSize * (c2.y - c1.y);
165 int xInc = c2.x - c1.x;
166 Data_T value = static_cast<Data_T>
167 (f1.x * (f1.y * (f1.z * *c111 +
168 f2.z * *c112) +
169 f2.y * (f1.z * *c121 +
170 f2.z * *c122)) +
171 f2.x * (f1.y * (f1.z * *(c111 + xInc) +
172 f2.z * *(c112 + xInc)) +
173 f2.y * (f1.z * *(c121 + xInc) +
174 f2.z * *(c122 + xInc))));
175 // Decrement the block ref count
176 if (isDynamicLoad) {
177 field.decBlockRef(blockId);
178 }
179 // Done.
180 return value;
181 } else {
182 return static_cast<Data_T>(field.getBlockEmptyValue(bi, bj, bk));
183 }
184 } else {
185 return static_cast<Data_T>
186 (f1.x * (f1.y * (f1.z * field.fastValue(c1.x, c1.y, c1.z) +
187 f2.z * field.fastValue(c1.x, c1.y, c2.z)) +
188 f2.y * (f1.z * field.fastValue(c1.x, c2.y, c1.z) +
189 f2.z * field.fastValue(c1.x, c2.y, c2.z))) +
190 f2.x * (f1.y * (f1.z * field.fastValue(c2.x, c1.y, c1.z) +
191 f2.z * field.fastValue(c2.x, c1.y, c2.z)) +
192 f2.y * (f1.z * field.fastValue(c2.x, c2.y, c1.z) +
193 f2.z * field.fastValue(c2.x, c2.y, c2.z))));
194 }
195
196 }
197
198private:
199
200 // Static data members -------------------------------------------------------
201
203
204 // Typedefs ------------------------------------------------------------------
205
207 typedef RefBase base;
208
209};
210
211//----------------------------------------------------------------------------//
212
214
215//----------------------------------------------------------------------------//
216// SparseBlock
217//----------------------------------------------------------------------------//
218
221namespace Sparse {
222
226template <typename Data_T>
227struct SparseBlock : boost::noncopyable
228{
229 // Constructors --------------------------------------------------------------
230
233 : isAllocated(false),
234 emptyValue(static_cast<Data_T>(0)),
235 data(NULL)
236 { /* Empty */ }
237
240 {
241 if (data) {
242 delete[] data;
243 }
244 }
245
246 // Main methods --------------------------------------------------------------
247
249 inline Data_T& value(int i, int j, int k, int blockOrder)
251 { return data[(k << blockOrder << blockOrder) + (j << blockOrder) + i]; }
252
255 inline const Data_T& value(int i, int j, int k, int blockOrder) const
256 { return data[(k << blockOrder << blockOrder) + (j << blockOrder) + i]; }
257
259 void resize(int n)
260 {
261 // First hold lock
262 boost::mutex::scoped_lock lock(ms_resizeMutex);
263 // Perform work
264 if (data) {
265 delete[] data;
266 }
267 data = new Data_T[n];
268 isAllocated = true;
269 std::fill_n(data, n, emptyValue);
270 }
271
273 void clear()
274 {
275 // First hold lock
276 boost::mutex::scoped_lock lock(ms_resizeMutex);
277 // Perform work
278 if (data) {
279 delete[] data;
280 data = NULL;
281 }
282 }
283
285 void copy(const SparseBlock &other, size_t n)
286 {
287 if (other.isAllocated) {
288 if (!data) {
289 resize(n);
290 }
291 Data_T *p = data, *end = data + n, *o = other.data;
292 while (p != end) {
293 *p++ = *o++;
294 }
295 } else {
296 clear();
297 }
298 }
299
300 // Data members --------------------------------------------------------------
301
304
309
311 Data_T *data;
312
313private:
314
319
320 // Data members --------------------------------------------------------------
321
325 static boost::mutex ms_resizeMutex;
326
327};
328
329} // namespace Sparse
330
331//----------------------------------------------------------------------------//
332// SparseField
333//----------------------------------------------------------------------------//
334
347//----------------------------------------------------------------------------//
348
349template <class Data_T>
351 : public ResizableField<Data_T>
352{
353public:
354
355 // Typedefs ------------------------------------------------------------------
356
357 typedef boost::intrusive_ptr<SparseField> Ptr;
358 typedef std::vector<Ptr> Vec;
359
362
363 // RTTI replacement ----------------------------------------------------------
364
367
368 static const char *staticClassName()
369 {
370 return "SparseField";
371 }
372
373 static const char *staticClassType()
374 {
376 }
377
378 // Constructors --------------------------------------------------------------
379
382
384 SparseField();
385
387 SparseField(const SparseField &o);
388
390 ~SparseField();
391
395
396 // \}
397
398 // Main methods --------------------------------------------------------------
399
401 virtual void clear(const Data_T &value);
402
405 void setBlockOrder(int order);
406
408 int blockOrder() const;
409
411 int blockSize() const;
412
414 bool voxelIsInAllocatedBlock(int i, int j, int k) const;
415
417 bool blockIsAllocated(int bi, int bj, int bk) const;
418
421 const Data_T getBlockEmptyValue(int bi, int bj, int bk) const;
422
425 void setBlockEmptyValue(int bi, int bj, int bk, const Data_T &val);
426
428 bool blockIndexIsValid(int bi, int bj, int bk) const;
429
431 V3i blockRes() const;
432
438 template <typename Functor_T>
439 int releaseBlocks(Functor_T func);
440
442 int blockId(int blockI, int blockJ, int blockK) const;
443
447 void getBlockCoord(int i, int j, int k, int &bi, int &bj, int &bk) const;
448
452 void getVoxelInBlock(int i, int j, int k, int &vi, int &vj, int &vk) const;
453
455 void applyDataWindowOffset(int &i, int &j, int &k) const
456 {
457 i -= base::m_dataWindow.min.x;
458 j -= base::m_dataWindow.min.y;
459 k -= base::m_dataWindow.min.z;
460 }
461
463 bool isDynamicLoad() const
464 { return m_fileManager != NULL; }
465
467 void incBlockRef(const int blockId) const;
468
470 void activateBlock(const int blockId) const;
471
473 void decBlockRef(const int blockId) const;
474
475 // Threading-related ---------------------------------------------------------
476
478 size_t numGrains() const;
481 bool getGrainBounds(const size_t idx, Box3i &vsBounds) const;
482
483 // From Field base class -----------------------------------------------------
484
487 virtual Data_T value(int i, int j, int k) const;
488 virtual long long int memSize() const;
489 virtual size_t voxelCount() const;
491
492 // From WritableField base class ---------------------------------------------
493
496 virtual Data_T& lvalue(int i, int j, int k);
498
499 // Concrete voxel access -----------------------------------------------------
500
502 Data_T fastValue(int i, int j, int k) const;
504 Data_T& fastLValue(int i, int j, int k);
505
508 Data_T* blockData(int bi, int bj, int bk) const;
509
510 // From FieldBase ------------------------------------------------------------
511
514
516
517 virtual FieldBase::Ptr clone() const
518 { return Ptr(new SparseField(*this)); }
519
521
522 // Iterators -----------------------------------------------------------------
523
526
528 class const_iterator;
529
531 const_iterator cbegin() const;
533 const_iterator cbegin(const Box3i &subset) const;
535 const_iterator cend() const;
538 const_iterator cend(const Box3i &subset) const;
539
543 class iterator;
544
546 iterator begin();
548 iterator begin(const Box3i &subset);
550 iterator end();
553 iterator end(const Box3i &subset);
554
558 class block_iterator;
559
560 block_iterator blockBegin() const;
562 block_iterator blockEnd() const;
563
565
566 // Internal utility functions ------------------------------------------------
567
570 void addReference(const std::string &filename, const std::string &layerPath,
571 int valuesPerBlock, int numVoxels, int occupiedBlocks);
575
576 protected:
577
578 friend class SparseFieldIO;
579
580 // Typedefs ------------------------------------------------------------------
581
584
585 // From ResizableField class -------------------------------------------------
586
587 virtual void sizeChanged()
588 {
589 // Call base class
591 setupBlocks();
592 }
593
594 // Convenience methods -------------------------------------------------------
595
598
600 void setupBlocks();
601
603 void deallocBlock(Block &block, const Data_T &emptyValue);
604
606
607 // Data members --------------------------------------------------------------
608
619
625
627 Data_T m_dummy;
628
629private:
630
631 // Static data members -------------------------------------------------------
632
634
635 // Utility methods -----------------------------------------------------------
636
639 void copySparseField(const SparseField &o);
640
644
645};
646
647//----------------------------------------------------------------------------//
648// Static member instantiations
649//----------------------------------------------------------------------------//
650
652
653namespace Sparse {
654
655template <typename Data_T>
657
658}
659
660//----------------------------------------------------------------------------//
661// Typedefs
662//----------------------------------------------------------------------------//
663
670
671//------------------------------------------------------------------------------
672// Helper functions
673//------------------------------------------------------------------------------
674
675template <typename Data_T>
676Box3i blockCoords(const Box3i &dvsBounds, const SparseField<Data_T> *f)
677{
678 // Check empty bbox input
679 if (!continuousBounds(dvsBounds).hasVolume()) {
680 return Box3i();
681 }
682 // Discrete offset voxel space
683 Box3i dovsBounds = dvsBounds;
684 f->applyDataWindowOffset(dovsBounds.min.x,
685 dovsBounds.min.y,
686 dovsBounds.min.z);
687 f->applyDataWindowOffset(dovsBounds.max.x,
688 dovsBounds.max.y,
689 dovsBounds.max.z);
690 // Discrete block space bounds
691 Box3i dbsBounds;
692 if (f) {
693 f->getBlockCoord(dovsBounds.min.x, dovsBounds.min.y, dovsBounds.min.z,
694 dbsBounds.min.x, dbsBounds.min.y, dbsBounds.min.z);
695 f->getBlockCoord(dovsBounds.max.x, dovsBounds.max.y, dovsBounds.max.z,
696 dbsBounds.max.x, dbsBounds.max.y, dbsBounds.max.z);
697 }
698 return dbsBounds;
699}
700
701//----------------------------------------------------------------------------//
702// Helper functors
703//----------------------------------------------------------------------------//
704
705namespace Sparse {
706
709template <typename Data_T>
711{
720 bool check(const SparseBlock<Data_T> &block, Data_T &retEmptyValue,
721 const V3i &validSize, const V3i &blockSize)
722 {
723 // Store first value
724 Data_T first = block.data[0];
725 // Iterate over rest
726 bool match = true;
727 size_t len = blockSize.x * blockSize.y * blockSize.z;
728 if (validSize == blockSize) {
729 // interior block so look at all voxels
730 for (size_t i = 0; i < len; i++) {
731 if (block.data[i] != first) {
732 match = false;
733 break;
734 }
735 }
736 } else {
737 // only look at valid voxels
738 int x=0, y=0, z=0;
739 for (size_t i = 0; i < len; i++, x++) {
740 if (x >= blockSize.x) {
741 x = 0;
742 ++y;
743 if (y >= blockSize.y) {
744 y = 0;
745 ++z;
746 }
747 }
748 if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
749 continue;
750 }
751 if (block.data[i] != first) {
752 match = false;
753 break;
754 }
755 }
756 } // end of interior block test
757
758 if (match) {
759 retEmptyValue = first;
760 return true;
761 } else {
762 return false;
763 }
764 }
765};
766
767//----------------------------------------------------------------------------//
768
769template <typename Data_T>
770inline bool isAnyLess(const Data_T &left, const Data_T &right)
771{
772 return (std::abs(left) < right);
773}
774
775//----------------------------------------------------------------------------//
776
777template <>
778inline bool isAnyLess(const V3h &left, const V3h &right)
779{
780 return (std::abs(left.x) < right.x ||
781 std::abs(left.y) < right.y ||
782 std::abs(left.z) < right.z );
783}
784
785//----------------------------------------------------------------------------//
786
787template <>
788inline bool isAnyLess(const V3f &left, const V3f &right)
789{
790 return (std::abs(left.x) < right.x ||
791 std::abs(left.y) < right.y ||
792 std::abs(left.z) < right.z );
793}
794
795//----------------------------------------------------------------------------//
796
797template <>
798inline bool isAnyLess(const V3d &left, const V3d &right)
799{
800 return (std::abs(left.x) < right.x ||
801 std::abs(left.y) < right.y ||
802 std::abs(left.z) < right.z );
803}
804
805//----------------------------------------------------------------------------//
806
810template <typename Data_T>
812{
814 CheckMaxAbs(Data_T maxValue)
815 : m_maxValue(maxValue)
816 { }
825 bool check(const SparseBlock<Data_T> &block, Data_T &retEmptyValue,
826 const V3i &validSize, const V3i &blockSize)
827 {
828 // Store first value
829 Data_T first = block.data[0];
830 // Iterate over rest
831 bool allGreater = true;
832 size_t len = blockSize.x * blockSize.y * blockSize.z;
833
834 if (validSize == blockSize) {
835 // interior block so look at all voxels
836 for (size_t i = 0; i < len; i++) {
837 if (isAnyLess<Data_T>(block.data[i], m_maxValue)) {
838 allGreater = false;
839 break;
840 }
841 }
842 } else {
843 // only look at valid voxels
844 int x=0, y=0, z=0;
845 for (size_t i = 0; i < len; i++, x++) {
846 if (x >= blockSize.x) {
847 x = 0;
848 ++y;
849 if (y >= blockSize.y) {
850 y = 0;
851 ++z;
852 }
853 }
854 if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
855 continue;
856 }
857 if (isAnyLess<Data_T>(block.data[i], m_maxValue)) {
858 allGreater = false;
859 break;
860 }
861 }
862 } // end of interior block test
863
864 if (allGreater) {
865 retEmptyValue = first;
866 return true;
867 } else {
868 return false;
869 }
870 }
871private:
873};
874
875//----------------------------------------------------------------------------//
876
877} // namespace Sparse
878
879//----------------------------------------------------------------------------//
880// SparseField::const_iterator
881//----------------------------------------------------------------------------//
882
884template <class Data_T>
886{
887 public:
888#if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
889 typedef std::forward_iterator_tag iterator_category;
890 typedef Data_T value_type;
891 typedef ptrdiff_t difference_type;
892 typedef ptrdiff_t distance_type;
893 typedef Data_T *pointer;
894 typedef Data_T& reference;
895#endif
896
899 const Box3i &window,
900 const V3i &currentPos, int blockOrder)
901 : x(currentPos.x), y(currentPos.y), z(currentPos.z),
902 m_p(NULL), m_blockIsActivated(false),
903 m_blockStepsTicker(0), m_blockOrder(blockOrder),
904 m_blockId(-1), m_window(window), m_field(&field)
905 {
906 m_manager = m_field->m_fileManager;
907 setupNextBlock(x, y, z);
908 }
910 if (m_manager && m_blockId >= 0 &&
911 m_blockId < static_cast<int>(m_field->m_numBlocks)) {
912 if (m_field->m_blocks[m_blockId].isAllocated)
913 m_manager->decBlockRef<Data_T>(m_field->m_fileId, m_blockId);
914 }
915 }
916 const const_iterator& operator ++ ()
917 {
918 bool resetPtr = false;
919 // Check against end of data window
920 if (x == m_window.max.x) {
921 if (y == m_window.max.y) {
922 x = m_window.min.x;
923 y = m_window.min.y;
924 ++z;
925 resetPtr = true;
926 } else {
927 x = m_window.min.x;
928 ++y;
929 resetPtr = true;
930 }
931 } else {
932 ++x;
933 }
934 // These can both safely be incremented here
935 ++m_blockStepsTicker;
936 // ... but only step forward if we're in a non-empty block
937 if (!m_isEmptyBlock && (!m_manager || m_blockIsActivated))
938 ++m_p;
939 // Check if we've reached the end of this block
940 if (m_blockStepsTicker == (1 << m_blockOrder))
941 resetPtr = true;
942 if (resetPtr) {
943 // If we have, we need to reset the current block, etc.
944 m_blockStepsTicker = 0;
945 setupNextBlock(x, y, z);
946 }
947 return *this;
948 }
949 template <class Iter_T>
950 inline bool operator == (const Iter_T &rhs) const
951 {
952 return x == rhs.x && y == rhs.y && z == rhs.z;
953 }
954 template <class Iter_T>
955 inline bool operator != (const Iter_T &rhs) const
956 {
957 return x != rhs.x || y != rhs.y || z != rhs.z;
958 }
959 inline const Data_T& operator * () const
960 {
961 if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
962 m_manager->activateBlock<Data_T>(m_field->m_fileId, m_blockId);
963 m_blockIsActivated = true;
964 const Block &block = m_field->m_blocks[m_blockId];
965 int vi, vj, vk;
966 m_field->getVoxelInBlock(x, y, z, vi, vj, vk);
967 m_p = &block.value(vi, vj, vk, m_blockOrder);
968 }
969 return *m_p;
970 }
971 inline const Data_T* operator -> () const
972 {
973 if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
974 SparseFileManager *manager = m_field->m_fileManager;
975 manager->activateBlock<Data_T>(m_field->m_fileId, m_blockId);
976 m_blockIsActivated = true;
977 const Block &block = m_field->m_blocks[m_blockId];
978 int vi, vj, vk;
979 m_field->getVoxelInBlock(x, y, z, vi, vj, vk);
980 m_p = &block.value(vi, vj, vk, m_blockOrder);
981 }
982 return m_p;
983 }
984
985 // Public data members -------------------------------------------------------
986
988 int x, y, z;
989
990private:
991
992 // Typedefs ------------------------------------------------------------------
993
995
996 // Convenience methods -------------------------------------------------------
997
998 void setupNextBlock(int i, int j, int k)
999 {
1000 m_field->applyDataWindowOffset(i, j, k);
1001 m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
1002 int oldBlockId = m_blockId;
1003 m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
1004 if (m_manager && oldBlockId != m_blockId &&
1005 oldBlockId >= 0 &&
1006 oldBlockId < static_cast<int>(m_field->m_numBlocks) &&
1007 m_field->m_blocks[oldBlockId].isAllocated) {
1008 m_manager->decBlockRef<Data_T>(m_field->m_fileId, oldBlockId);
1009 }
1010 if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
1011 m_isEmptyBlock = true;
1012 return;
1013 }
1014
1015 const Block &block = m_field->m_blocks[m_blockId];
1016 int vi, vj, vk;
1017 m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1018 m_blockStepsTicker = vi;
1019 if (block.isAllocated) {
1020 if (m_manager && oldBlockId != m_blockId && m_blockId >= 0) {
1021 m_manager->incBlockRef<Data_T>(m_field->m_fileId, m_blockId);
1022 // this is a managed field, so the block may not be loaded
1023 // yet, so don't bother setting m_p yet (it'll get set in the
1024 // * and -> operators when the block is activated)
1025 } else {
1026 // only set m_p to the voxel's address if this is not a
1027 // managed field, i.e., if the data is already in memory.
1028 m_p = &block.value(vi, vj, vk, m_blockOrder);
1029 }
1030 m_isEmptyBlock = false;
1031 } else {
1032 m_p = &block.emptyValue;
1033 m_isEmptyBlock = true;
1034 }
1035 if (m_field->m_fileManager) {
1036 m_blockIsActivated = false;
1037 }
1038 }
1039
1041 mutable const Data_T *m_p;
1052 int m_blockI, m_blockJ, m_blockK, m_blockId;
1059};
1060
1061//----------------------------------------------------------------------------//
1062// SparseField::iterator
1063//----------------------------------------------------------------------------/
1064
1066template <class Data_T>
1067class SparseField<Data_T>::iterator
1068{
1069 public:
1070#if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1071 typedef std::forward_iterator_tag iterator_category;
1072 typedef Data_T value_type;
1073 typedef ptrdiff_t difference_type;
1074 typedef ptrdiff_t distance_type;
1075 typedef Data_T *pointer;
1076 typedef Data_T& reference;
1077#endif
1078
1081 const Box3i &window,
1082 const V3i &currentPos, int blockOrder)
1083 : x(currentPos.x), y(currentPos.y), z(currentPos.z),
1084 m_p(NULL), m_blockStepsTicker(0), m_blockOrder(blockOrder),
1085 m_blockId(-1), m_window(window), m_field(&field)
1086 {
1087 setupNextBlock(x, y, z);
1088 }
1089 const iterator& operator ++ ()
1090 {
1091 bool resetPtr = false;
1092 // Check against end of data window
1093 if (x == m_window.max.x) {
1094 if (y == m_window.max.y) {
1095 x = m_window.min.x;
1096 y = m_window.min.y;
1097 ++z;
1098 resetPtr = true;
1099 } else {
1100 x = m_window.min.x;
1101 ++y;
1102 resetPtr = true;
1103 }
1104 } else {
1105 ++x;
1106 }
1107 // These can both safely be incremented here
1108 ++m_blockStepsTicker;
1109 // ... but only step forward if we're in a non-empty block
1110 if (!m_isEmptyBlock)
1111 ++m_p;
1112 // Check if we've reached the end of this block
1113 if (m_blockStepsTicker == (1 << m_blockOrder))
1114 resetPtr = true;
1115 if (resetPtr) {
1116 // If we have, we need to reset the current block, etc.
1117 m_blockStepsTicker = 0;
1118 setupNextBlock(x, y, z);
1119 }
1120 return *this;
1121 }
1122 inline bool operator == (const iterator &rhs) const
1123 {
1124 return x == rhs.x && y == rhs.y && z == rhs.z;
1125 }
1126 inline bool operator != (const iterator &rhs) const
1127 {
1128 return x != rhs.x || y != rhs.y || z != rhs.z;
1129 }
1130 inline Data_T& operator * ()
1131 {
1132 if (m_field->m_fileManager) {
1133 assert(false && "Dereferencing iterator on a dynamic-read sparse field");
1134 Msg::print(Msg::SevWarning, "Dereferencing iterator on a dynamic-read "
1135 "sparse field");
1136 return *m_p;
1137 }
1138 // If the block is currently empty, we must allocate it
1139 if (m_isEmptyBlock) {
1140 // Touch the voxel to allocate the block
1141 m_field->lvalue(x, y, z);
1142 // Set up the block again
1143 setupNextBlock(x, y, z);
1144 }
1145 return *m_p;
1146 }
1147 inline Data_T* operator -> ()
1148 {
1149 if (m_field->m_fileManager) {
1150 assert(false && "Dereferencing iterator on a dynamic-read sparse field");
1151 Msg::print(Msg::SevWarning, "Dereferencing iterator on a dynamic-read "
1152 "sparse field");
1153 return m_p;
1154 }
1155 // If the block is currently empty, we must allocate it
1156 if (m_isEmptyBlock) {
1157 // Touch the voxel to allocate the block
1158 m_field->lvalue(x, y, z);
1159 // Set up the block again
1160 setupNextBlock(x, y, z);
1161 }
1162 return m_p;
1163 }
1164 // Public data members
1165 int x, y, z;
1166private:
1169 void setupNextBlock(int i, int j, int k)
1170 {
1171 m_field->applyDataWindowOffset(i, j, k);
1172 m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
1173 m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
1174 if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
1175 m_isEmptyBlock = true;
1176 return;
1177 }
1178 Block &block = m_field->m_blocks[m_blockId];
1179 int vi, vj, vk;
1180 m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1181 m_blockStepsTicker = vi;
1182 if (block.isAllocated) {
1183 m_p = &block.value(vi, vj, vk, m_blockOrder);
1184 m_isEmptyBlock = false;
1185 } else {
1186 m_p = &block.emptyValue;
1187 m_isEmptyBlock = true;
1188 }
1189 }
1191 Data_T *m_p;
1199 int m_blockI, m_blockJ, m_blockK, m_blockId;
1204};
1205
1206//----------------------------------------------------------------------------//
1207// SparseField::block_iterator
1208//----------------------------------------------------------------------------/
1209
1212template <class Data_T>
1214{
1215 public:
1219 block_iterator(const class_type &field, const Box3i &window,
1220 const V3i &currentPos)
1221 : x(currentPos.x), y(currentPos.y), z(currentPos.z),
1222 m_window(window), m_field(field)
1223 {
1224 recomputeBlockBoundingBox();
1225 }
1227 const block_iterator& operator ++ ()
1228 {
1229 if (x == m_window.max.x) {
1230 if (y == m_window.max.y) {
1231 x = m_window.min.x;
1232 y = m_window.min.y;
1233 ++z;
1234 } else {
1235 x = m_window.min.x;
1236 ++y;
1237 }
1238 } else {
1239 ++x;
1240 }
1241 recomputeBlockBoundingBox();
1242 return *this;
1243 }
1245 inline bool operator == (const block_iterator &rhs) const
1246 {
1247 return x == rhs.x && y == rhs.y && z == rhs.z;
1248 }
1250 inline bool operator != (const block_iterator &rhs) const
1251 {
1252 return x != rhs.x || y != rhs.y || z != rhs.z;
1253 }
1256 {
1257 return m_currentBlockWindow;
1258 }
1260 int x, y, z;
1261private:
1263 {
1264 Box3i box;
1265 int blockSize = m_field.blockSize();
1266 box.min = V3i(x * blockSize, y * blockSize, z * blockSize);
1267 box.max = box.min + V3i(blockSize - 1, blockSize - 1, blockSize - 1);
1268 // Clamp the box
1269 box.min = FIELD3D_CLIP(box.min, m_field.dataWindow());
1270 box.max = FIELD3D_CLIP(box.max, m_field.dataWindow());
1271 // Set the member variable
1272 m_currentBlockWindow = box;
1273 }
1280};
1281
1282//----------------------------------------------------------------------------//
1283// SparseField implementations
1284//----------------------------------------------------------------------------//
1285
1286template <class Data_T>
1288 : base(),
1289 m_blockOrder(BLOCK_ORDER),
1290 m_blocks(NULL),
1291 m_fileManager(NULL)
1292{
1293 setupBlocks();
1294}
1295
1296//----------------------------------------------------------------------------//
1297
1298template <class Data_T>
1300 : base(o),
1301 m_blockOrder(o.m_blockOrder),
1302 m_blocks(NULL),
1303 m_fileManager(o.m_fileManager)
1304{
1305 copySparseField(o);
1306}
1307
1308//----------------------------------------------------------------------------//
1309
1310template <class Data_T>
1312{
1313 if (m_fileManager) {
1314 // this file is dynamically managed, so we need to ensure the
1315 // cache doesn't point to this field's blocks because they are
1316 // about to be deleted
1317 m_fileManager->removeFieldFromCache<Data_T>(m_fileId);
1318 }
1319 if (m_blocks) {
1320 delete[] m_blocks;
1321 }
1322}
1323
1324//----------------------------------------------------------------------------//
1325
1326template <class Data_T>
1329{
1330 if (this != &o) {
1331 this->base::operator=(o);
1332 copySparseField(o);
1333 }
1334 return *this;
1335}
1336
1337//----------------------------------------------------------------------------//
1338
1339template <class Data_T>
1340void
1342{
1343 m_blockOrder = o.m_blockOrder;
1344 if (o.m_fileManager) {
1345 // allocate m_blocks, sets m_blockRes, m_blockXYSize, m_blocks
1346 setupBlocks();
1347 m_fileManager = o.m_fileManager;
1348 SparseFile::Reference<Data_T> *oldReference =
1349 m_fileManager->reference<Data_T>(o.m_fileId);
1350 addReference(oldReference->filename, oldReference->layerPath,
1351 oldReference->valuesPerBlock,
1352 oldReference->numVoxels,
1353 oldReference->occupiedBlocks);
1354 copyBlockStates(o);
1355 setupReferenceBlocks();
1356 } else {
1357 // directly copy all values and blocks from the source, no extra setup
1358 m_blockRes = o.m_blockRes;
1359 m_blockXYSize = o.m_blockXYSize;
1360 if (m_blocks) {
1361 delete[] m_blocks;
1362 }
1363 m_numBlocks = o.m_numBlocks;
1364 m_blocks = new Block[m_numBlocks];
1365 for (size_t i = 0; i < m_numBlocks; ++i) {
1366 m_blocks[i].isAllocated = o.m_blocks[i].isAllocated;
1367 m_blocks[i].emptyValue = o.m_blocks[i].emptyValue;
1368 m_blocks[i].copy(o.m_blocks[i],
1369 1 << m_blockOrder << m_blockOrder << m_blockOrder);
1370 }
1371 m_fileId = -1;
1372 m_fileManager = NULL;
1373 }
1374}
1375
1376//----------------------------------------------------------------------------//
1377
1378template <class Data_T>
1379void SparseField<Data_T>::addReference(const std::string &filename,
1380 const std::string &layerPath,
1381 int valuesPerBlock,
1382 int numVoxels,
1383 int occupiedBlocks)
1384{
1385 m_fileManager = &SparseFileManager::singleton();
1386 m_fileId = m_fileManager->getNextId<Data_T>(filename, layerPath);
1387 // Set up the manager data
1389 m_fileManager->reference<Data_T>(m_fileId);
1390 reference->valuesPerBlock = valuesPerBlock;
1391 reference->numVoxels = numVoxels;
1392 reference->occupiedBlocks = occupiedBlocks;
1393 reference->setNumBlocks(m_numBlocks);
1394}
1395
1396//----------------------------------------------------------------------------//
1397
1398template <class Data_T>
1400{
1401 if (m_numBlocks != o.m_numBlocks) return;
1402
1403 for (size_t i = 0; i < m_numBlocks; ++i) {
1404 m_blocks[i].isAllocated = o.m_blocks[i].isAllocated;
1405 m_blocks[i].emptyValue = o.m_blocks[i].emptyValue;
1406 m_blocks[i].clear();
1407 }
1408}
1409
1410//----------------------------------------------------------------------------//
1411
1412template <class Data_T>
1414{
1415 if (!m_fileManager || m_fileId < 0) return;
1416
1418 m_fileManager->reference<Data_T>(m_fileId);
1419
1420#if F3D_NO_BLOCKS_ARRAY
1421 std::vector<int>::iterator fb = reference->fileBlockIndices.begin();
1422 reference->blocks = m_blocks;
1423 int nextBlockIdx = 0;
1424 for (size_t i = 0; i < m_numBlocks; ++i, ++fb) {
1425 if (m_blocks[i].isAllocated) {
1426 *fb = nextBlockIdx;
1427 nextBlockIdx++;
1428 } else {
1429 *fb = -1;
1430 }
1431 }
1432#else
1433 std::vector<int>::iterator fb = reference->fileBlockIndices.begin();
1435 reference->blocks.begin();
1436 int nextBlockIdx = 0;
1437 for (size_t i = 0; i < m_numBlocks; ++i, ++fb, ++bp) {
1438 if (m_blocks[i].isAllocated) {
1439 *fb = nextBlockIdx;
1440 *bp = m_blocks + i;
1441 nextBlockIdx++;
1442 } else {
1443 *fb = -1;
1444 }
1445 }
1446#endif
1447}
1448
1449//----------------------------------------------------------------------------//
1450
1451template <class Data_T>
1452void SparseField<Data_T>::clear(const Data_T &value)
1453{
1454 // If we're clearing, we can get rid of all current blocks
1455 setupBlocks();
1456 Block *p = m_blocks, *end = m_blocks + m_numBlocks;
1457 while (p != end) {
1458 p->emptyValue = value;
1459 ++p;
1460 }
1461}
1462
1463//----------------------------------------------------------------------------//
1464
1465template <class Data_T>
1467{
1468 m_blockOrder = order;
1469 setupBlocks();
1470}
1471
1472//----------------------------------------------------------------------------//
1473
1474template <class Data_T>
1476{
1477 return m_blockOrder;
1478}
1479
1480//----------------------------------------------------------------------------//
1481
1482template <class Data_T>
1484{
1485 return 1 << m_blockOrder;
1486}
1487
1488//----------------------------------------------------------------------------//
1489
1490template <class Data_T>
1492{
1493 int bi, bj, bk;
1494 applyDataWindowOffset(i, j, k);
1495 getBlockCoord(i, j, k, bi, bj, bk);
1496 return blockIsAllocated(bi, bj, bk);
1497}
1498
1499//----------------------------------------------------------------------------//
1500
1501template <class Data_T>
1502bool SparseField<Data_T>::blockIsAllocated(int bi, int bj, int bk) const
1503{
1504 const Block &block = m_blocks[blockId(bi, bj, bk)];
1505 return block.isAllocated;
1506}
1507
1508//----------------------------------------------------------------------------//
1509
1510template <class Data_T>
1511const Data_T SparseField<Data_T>::getBlockEmptyValue(int bi, int bj, int bk) const
1512{
1513 return m_blocks[blockId(bi, bj, bk)].emptyValue;
1514}
1515
1516//----------------------------------------------------------------------------//
1517
1518template <class Data_T>
1520 const Data_T &val)
1521{
1522 Block &block = m_blocks[blockId(bi, bj, bk)];
1523 if (block.isAllocated) {
1524 deallocBlock(block, val);
1525 } else {
1526 block.emptyValue = val;
1527 }
1528}
1529
1530//----------------------------------------------------------------------------//
1531
1532template <class Data_T>
1533bool SparseField<Data_T>::blockIndexIsValid(int bi, int bj, int bk) const
1534{
1535 return bi >= 0 && bj >= 0 && bk >= 0 &&
1536 bi < m_blockRes.x && bj < m_blockRes.y && bk < m_blockRes.z;
1537}
1538
1539//----------------------------------------------------------------------------//
1540
1541template <class Data_T>
1543{
1544 return m_blockRes;
1545}
1546
1547//----------------------------------------------------------------------------//
1548
1549template <class Data_T>
1550template <typename Functor_T>
1552{
1553 Data_T emptyValue;
1554 int numDeallocs = 0;
1555
1556 // If the block is on the edge of the field, it may have unused
1557 // voxels, with undefined values. We need to pass the range of
1558 // valid voxels into the check function, so it only looks at valid
1559 // voxels.
1560 V3i dataRes = FieldRes::dataResolution();
1561 V3i validSize;
1562 V3i blockAllocSize(blockSize());
1563
1564 int bx = 0, by = 0, bz = 0;
1565 for (size_t i = 0; i < m_numBlocks; ++i, ++bx) {
1566 if (bx >= m_blockRes.x) {
1567 bx = 0;
1568 ++by;
1569 if (by >= m_blockRes.y) {
1570 by = 0;
1571 ++bz;
1572 }
1573 }
1574 validSize = blockAllocSize;
1575 if (bx == m_blockRes.x-1) {
1576 validSize.x = dataRes.x - bx * blockAllocSize.x;
1577 }
1578 if (by == m_blockRes.y-1) {
1579 validSize.y = dataRes.y - by * blockAllocSize.y;
1580 }
1581 if (bz == m_blockRes.z-1) {
1582 validSize.z = dataRes.z - bz * blockAllocSize.z;
1583 }
1584
1585 if (m_blocks[i].isAllocated) {
1586 if (func.check(m_blocks[i], emptyValue, validSize, blockAllocSize)) {
1587 deallocBlock(m_blocks[i], emptyValue);
1588 numDeallocs++;
1589 }
1590 }
1591 }
1592 return numDeallocs;
1593}
1594
1595//----------------------------------------------------------------------------//
1596
1597template <class Data_T>
1598Data_T SparseField<Data_T>::value(int i, int j, int k) const
1599{
1600 return fastValue(i, j, k);
1601}
1602
1603//----------------------------------------------------------------------------//
1604
1605template <class Data_T>
1606Data_T& SparseField<Data_T>::lvalue(int i, int j, int k)
1607{
1608 return fastLValue(i, j, k);
1609}
1610
1611//----------------------------------------------------------------------------//
1612
1613template <class Data_T>
1614Data_T SparseField<Data_T>::fastValue(int i, int j, int k) const
1615{
1616 assert (i >= base::m_dataWindow.min.x);
1617 assert (i <= base::m_dataWindow.max.x);
1618 assert (j >= base::m_dataWindow.min.y);
1619 assert (j <= base::m_dataWindow.max.y);
1620 assert (k >= base::m_dataWindow.min.z);
1621 assert (k <= base::m_dataWindow.max.z);
1622 // Add crop window offset
1623 applyDataWindowOffset(i, j, k);
1624 // Find block coord
1625 int bi, bj, bk;
1626 getBlockCoord(i, j, k, bi, bj, bk);
1627 // Find coord in block
1628 int vi, vj, vk;
1629 getVoxelInBlock(i, j, k, vi, vj, vk);
1630 // Get the actual block
1631 int id = blockId(bi, bj, bk);
1632 const Block &block = m_blocks[id];
1633 // Check if block data is allocated
1634 if (block.isAllocated) {
1635 if (m_fileManager) {
1636 m_fileManager->incBlockRef<Data_T>(m_fileId, id);
1637 m_fileManager->activateBlock<Data_T>(m_fileId, id);
1638 Data_T tmpValue = block.value(vi, vj, vk, m_blockOrder);
1639 m_fileManager->decBlockRef<Data_T>(m_fileId, id);
1640 return tmpValue;
1641 } else {
1642 return block.value(vi, vj, vk, m_blockOrder);
1643 }
1644 } else {
1645 return block.emptyValue;
1646 }
1647}
1648
1649//----------------------------------------------------------------------------//
1650
1652template <class Data_T>
1653Data_T& SparseField<Data_T>::fastLValue(int i, int j, int k)
1654{
1655 assert (i >= base::m_dataWindow.min.x);
1656 assert (i <= base::m_dataWindow.max.x);
1657 assert (j >= base::m_dataWindow.min.y);
1658 assert (j <= base::m_dataWindow.max.y);
1659 assert (k >= base::m_dataWindow.min.z);
1660 assert (k <= base::m_dataWindow.max.z);
1661
1662 if (m_fileManager) {
1663 assert(false && "Called fastLValue() on a dynamic-read sparse field");
1664 Msg::print(Msg::SevWarning, "Called fastLValue() on a dynamic-read "
1665 "sparse field");
1666 return m_dummy;
1667 }
1668
1669 // Add crop window offset
1670 applyDataWindowOffset(i, j, k);
1671 // Find block coord
1672 int bi, bj, bk;
1673 getBlockCoord(i, j, k, bi, bj, bk);
1674 // Find coord in block
1675 int vi, vj, vk;
1676 getVoxelInBlock(i, j, k, vi, vj, vk);
1677 // Get the actual block
1678 int id = blockId(bi, bj, bk);
1679 Block &block = m_blocks[id];
1680 // If block is allocated, return a reference to the data
1681 if (block.isAllocated) {
1682 return block.value(vi, vj, vk, m_blockOrder);
1683 } else {
1684 // ... Otherwise, allocate block
1685 size_t blockSize = 1 << m_blockOrder << m_blockOrder << m_blockOrder;
1686 block.resize(blockSize);
1687 return block.value(vi, vj, vk, m_blockOrder);
1688 }
1689}
1690
1691//----------------------------------------------------------------------------//
1692
1693template <class Data_T>
1694Data_T* SparseField<Data_T>::blockData(int bi, int bj, int bk) const
1695{
1696 int id = blockId(bi, bj, bk);
1697 const Block &block = m_blocks[id];
1698 if (block.isAllocated) {
1699 return block.data;
1700 } else {
1701 return NULL;
1702 }
1703}
1704
1705//----------------------------------------------------------------------------//
1706
1707template <class Data_T>
1708long long int SparseField<Data_T>::memSize() const
1709{
1710 long long int blockSize = m_numBlocks * sizeof(Block);
1711 long long int dataSize = 0;
1712
1713 for (size_t i = 0; i < m_numBlocks; ++i) {
1714 if (m_blocks[i].data) {
1715 dataSize += (1 << m_blockOrder << m_blockOrder << m_blockOrder) *
1716 sizeof(Data_T);
1717 }
1718 }
1719
1720 return sizeof(*this) + dataSize + blockSize;
1721}
1722
1723//----------------------------------------------------------------------------//
1724
1725template <class Data_T>
1727{
1728 size_t count = 0;
1729 const size_t blockSize = (1 << m_blockOrder << m_blockOrder << m_blockOrder);
1730
1731 for (size_t i = 0; i < m_numBlocks; ++i) {
1732 if (m_blocks[i].isAllocated) {
1733 count += blockSize;
1734 }
1735 }
1736
1737 return count;
1738}
1739
1740//----------------------------------------------------------------------------//
1741
1742template <class Data_T>
1745{
1746 if (FieldRes::dataResolution() == V3i(0))
1747 return cend();
1748 return const_iterator(*this, base::m_dataWindow, base::m_dataWindow.min,
1749 m_blockOrder);
1750}
1751
1752//----------------------------------------------------------------------------//
1753
1754template <class Data_T>
1757{
1758 if (subset.isEmpty())
1759 return cend(subset);
1760 return const_iterator(*this, subset, subset.min, m_blockOrder);
1761}
1762
1763//----------------------------------------------------------------------------//
1764
1765template <class Data_T>
1768{
1769 return const_iterator(*this, base::m_dataWindow,
1770 V3i(base::m_dataWindow.min.x,
1771 base::m_dataWindow.min.y,
1772 base::m_dataWindow.max.z + 1),
1773 m_blockOrder);
1774}
1775
1776//----------------------------------------------------------------------------//
1777
1778template <class Data_T>
1781{
1782 return const_iterator(*this, subset,
1783 V3i(subset.min.x,
1784 subset.min.y,
1785 subset.max.z + 1), m_blockOrder);
1786}
1787
1788//----------------------------------------------------------------------------//
1789
1790template <class Data_T>
1793{
1794 if (FieldRes::dataResolution() == V3i(0))
1795 return end();
1796 return iterator(*this, base::m_dataWindow,
1797 base::m_dataWindow.min, m_blockOrder); }
1798
1799//----------------------------------------------------------------------------//
1800
1801template <class Data_T>
1804{
1805 if (subset.isEmpty())
1806 return end(subset);
1807 return iterator(*this, subset, subset.min, m_blockOrder);
1808}
1809
1810//----------------------------------------------------------------------------//
1811
1812template <class Data_T>
1815{
1816 return iterator(*this, base::m_dataWindow,
1817 V3i(base::m_dataWindow.min.x,
1818 base::m_dataWindow.min.y,
1819 base::m_dataWindow.max.z + 1), m_blockOrder);
1820}
1821
1822//----------------------------------------------------------------------------//
1823
1824template <class Data_T>
1827{
1828 return iterator(*this, subset,
1829 V3i(subset.min.x, subset.min.y, subset.max.z + 1),
1830 m_blockOrder);
1831}
1832
1833//----------------------------------------------------------------------------//
1834
1835template <class Data_T>
1838{
1839 if (FieldRes::dataResolution() == V3i(0))
1840 return blockEnd();
1841 return block_iterator(*this, Box3i(V3i(0), m_blockRes - V3i(1)),
1842 V3i(0));
1843}
1844
1845//----------------------------------------------------------------------------//
1846
1847template <class Data_T>
1850{
1851 return block_iterator(*this, Box3i(V3i(0), m_blockRes - V3i(1)),
1852 V3i(0, 0, m_blockRes.z));
1853}
1854
1855//----------------------------------------------------------------------------//
1856
1857template <class Data_T>
1859{
1860 // Do calculation in floating point so we can round up later
1861 V3f res(base::m_dataWindow.size() + V3i(1));
1862 V3f blockRes(res / (1 << m_blockOrder));
1863 blockRes.x = ceil(blockRes.x);
1864 blockRes.y = ceil(blockRes.y);
1865 blockRes.z = ceil(blockRes.z);
1866 V3i intBlockRes(static_cast<int>(blockRes.x),
1867 static_cast<int>(blockRes.y),
1868 static_cast<int>(blockRes.z));
1869 m_blockRes = intBlockRes;
1870 m_blockXYSize = m_blockRes.x * m_blockRes.y;
1871 if (m_blocks) {
1872 delete[] m_blocks;
1873 }
1874 m_numBlocks = intBlockRes.x * intBlockRes.y * intBlockRes.z;
1875 m_blocks = new Block[m_numBlocks];
1876}
1877
1878//----------------------------------------------------------------------------//
1879
1880template <class Data_T>
1881int SparseField<Data_T>::blockId(int blockI, int blockJ, int blockK) const
1882{
1883 return blockK * m_blockXYSize + blockJ * m_blockRes.x + blockI;
1884}
1885
1886//----------------------------------------------------------------------------//
1887
1889template <class Data_T>
1890void SparseField<Data_T>::getBlockCoord(int i, int j, int k,
1891 int &bi, int &bj, int &bk) const
1892{
1893 assert(i >= 0);
1894 assert(j >= 0);
1895 assert(k >= 0);
1896 bi = i >> m_blockOrder;
1897 bj = j >> m_blockOrder;
1898 bk = k >> m_blockOrder;
1899}
1900
1901//----------------------------------------------------------------------------//
1902
1904template <class Data_T>
1906 int &vi, int &vj, int &vk) const
1907{
1908 assert(i >= 0);
1909 assert(j >= 0);
1910 assert(k >= 0);
1911 vi = i & ((1 << m_blockOrder) - 1);
1912 vj = j & ((1 << m_blockOrder) - 1);
1913 vk = k & ((1 << m_blockOrder) - 1);
1914}
1915
1916//----------------------------------------------------------------------------//
1917
1918template <class Data_T>
1919void SparseField<Data_T>::incBlockRef(const int blockId) const
1920{
1921 m_fileManager->incBlockRef<Data_T>(m_fileId, blockId);
1922}
1923
1924//----------------------------------------------------------------------------//
1925
1926template <class Data_T>
1927void SparseField<Data_T>::activateBlock(const int blockId) const
1928{
1929 m_fileManager->activateBlock<Data_T>(m_fileId, blockId);
1930}
1931
1932//----------------------------------------------------------------------------//
1933
1934template <class Data_T>
1935void SparseField<Data_T>::decBlockRef(const int blockId) const
1936{
1937 m_fileManager->decBlockRef<Data_T>(m_fileId, blockId);
1938}
1939
1940//----------------------------------------------------------------------------//
1941
1942template <class Data_T>
1944{
1945 return m_numBlocks;
1946}
1947
1948//----------------------------------------------------------------------------//
1949
1950template <class Data_T>
1951bool SparseField<Data_T>::getGrainBounds(const size_t idx, Box3i &bounds) const
1952{
1953 // Block size
1954 const size_t blockSide = (1 << m_blockOrder);
1955 // Block coordinate
1956 const V3i bCoord = indexToCoord(idx, m_blockRes);
1957 // Block bbox
1958 const V3i start(bCoord * blockSide + base::m_dataWindow.min);
1959 const V3i end (start + Imath::V3i(blockSide - 1));
1960 // Bounds must be clipped against data window
1961 const Box3i unclipped(start, end);
1962 bounds = clipBounds(unclipped, base::m_dataWindow);
1963 // Whether it's a contiguous block
1964 return bounds == unclipped;
1965}
1966
1967//----------------------------------------------------------------------------//
1968
1969template <class Data_T>
1970void SparseField<Data_T>::deallocBlock(Block &block, const Data_T &emptyValue)
1971{
1972 block.isAllocated = false;
1974 block.clear();
1975 block.emptyValue = emptyValue;
1976}
1977
1978//----------------------------------------------------------------------------//
1979
1981
1982//----------------------------------------------------------------------------//
1983
1984#endif // Include guard
FIELD3D_VEC3_T< T > operator*(S s, const FIELD3D_VEC3_T< T > vec)
Scalar times Vec3 multiplication. Makes the interpolation calls cleaner.
Definition: FieldInterp.h:1558
Contains Field, WritableField and ResizableField classes.
Box3d continuousBounds(const Box3i &bbox)
Definition: Field.h:1111
Box3i clipBounds(const Box3i &bbox, const Box3i &bounds)
Definition: Field.h:1145
V3i indexToCoord(const size_t idx, const V3i &res)
Definition: Field.h:1187
bool match(const std::string &name, const std::string &attribute, const std::vector< std::string > &patterns, const MatchFlags flags=MatchEmptyPattern)
Matches a <name>:<attribute> string against a set of patterns.
SparseField< V3h > SparseField3h
Definition: SparseField.h:667
SparseField< V3d > SparseField3d
Definition: SparseField.h:669
SparseField< float > SparseFieldf
Definition: SparseField.h:665
SparseField< half > SparseFieldh
Definition: SparseField.h:664
SparseField< V3f > SparseField3f
Definition: SparseField.h:668
Box3i blockCoords(const Box3i &dvsBounds, const SparseField< Data_T > *f)
Definition: SparseField.h:676
#define BLOCK_ORDER
Definition: SparseField.h:57
FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(LinearSparseFieldInterp)
SparseField< double > SparseFieldd
Definition: SparseField.h:666
Contains functions controlling the loading of sparse fields.
Imath::V3i V3i
Definition: SpiMathLib.h:71
Imath::V3d V3d
Definition: SpiMathLib.h:74
Imath::Box3i Box3i
Definition: SpiMathLib.h:77
Imath::Vec3< half > V3h
Definition: SpiMathLib.h:72
Imath::V3f V3f
Definition: SpiMathLib.h:73
#define FIELD3D_CLIP
Definition: SpiMathLib.h:90
boost::intrusive_ptr< FieldBase > Ptr
Definition: Field.h:97
std::string name
Optional name of the field.
Definition: Field.h:171
V3i const dataResolution() const
Definition: Field.h:256
Box3i m_dataWindow
Defines the area where data is allocated. This should be treated as a closed (i.e....
Definition: Field.h:310
const Box3i & dataWindow() const
Returns the data window. Any coordinate inside this window is safe to pass to value() in the Field su...
Definition: Field.h:253
Data_T value_type
Allows us to reference the template class.
Definition: Field.h:398
LinearSparseFieldInterp class_type
Definition: SparseField.h:97
boost::intrusive_ptr< LinearSparseFieldInterp > Ptr
Definition: SparseField.h:93
value_type sample(const SparseField< Data_T > &field, const V3d &vsP) const
Definition: SparseField.h:112
static const char * staticClassType()
Definition: SparseField.h:105
static TemplatedFieldType< LinearSparseFieldInterp< Data_T > > ms_classType
Definition: SparseField.h:202
RefBase base
Convenience typedef for referring to base class.
Definition: SparseField.h:207
static const char * staticClassName()
Definition: SparseField.h:100
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc....
Definition: Field.h:901
const class_type & m_field
Pointer to field we're traversing.
Definition: SparseField.h:1277
SparseField< Data_T > class_type
Convenience typedef.
Definition: SparseField.h:1217
Box3i m_window
Bounding box for block indices.
Definition: SparseField.h:1275
int x
Current block index.
Definition: SparseField.h:1260
const Box3i & blockBoundingBox()
Returns a reference to the bounding box representing the current block.
Definition: SparseField.h:1255
Box3i m_currentBlockWindow
Bounding box in voxel coordinates for the current block.
Definition: SparseField.h:1279
block_iterator(const class_type &field, const Box3i &window, const V3i &currentPos)
Constructor.
Definition: SparseField.h:1219
bool m_blockIsActivated
Used with delayed-load fields. Check if we've already activated the current blocks.
Definition: SparseField.h:1046
Box3i m_window
Window to traverse.
Definition: SparseField.h:1054
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
Definition: SparseField.h:1048
void setupNextBlock(int i, int j, int k)
Definition: SparseField.h:998
const_iterator(const class_type &field, const Box3i &window, const V3i &currentPos, int blockOrder)
Definition: SparseField.h:898
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:994
SparseFileManager * m_manager
Pointer to the singleton file manager.
Definition: SparseField.h:1058
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
Definition: SparseField.h:1043
const class_type * m_field
Reference to field we're traversing.
Definition: SparseField.h:1056
int x
Current x/y/z coord.
Definition: SparseField.h:988
int m_blockI
Current block index.
Definition: SparseField.h:1052
SparseField< Data_T > class_type
Definition: SparseField.h:897
const Data_T * m_p
Current pointed-to element.
Definition: SparseField.h:1041
int m_blockOrder
Block size.
Definition: SparseField.h:1197
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:1167
int m_blockI
Current block index.
Definition: SparseField.h:1199
Box3i m_window
Window to traverse.
Definition: SparseField.h:1201
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
Definition: SparseField.h:1195
void setupNextBlock(int i, int j, int k)
Convenience.
Definition: SparseField.h:1169
iterator(class_type &field, const Box3i &window, const V3i &currentPos, int blockOrder)
Definition: SparseField.h:1080
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
Definition: SparseField.h:1193
SparseField< Data_T > class_type
Definition: SparseField.h:1079
class_type * m_field
Reference to field we're traversing.
Definition: SparseField.h:1203
Data_T * m_p
Current pointed-to element.
Definition: SparseField.h:1191
This Field subclass stores voxel data in block-allocated arrays.
Definition: SparseField.h:352
CubicGenericFieldInterp< SparseField< Data_T > > CubicInterp
Definition: SparseField.h:361
bool isDynamicLoad() const
Whether the field is dynamically loaded.
Definition: SparseField.h:463
size_t numGrains() const
Number of 'grains' to use with threaded access.
Definition: SparseField.h:1943
void setBlockOrder(int order)
Sets the block order (i.e. the power-of-2 to use as block size.
Definition: SparseField.h:1466
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:583
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc....
Definition: SparseField.h:587
SparseFileManager * m_fileManager
Pointer to SparseFileManager. Used when doing dynamic reading. NULL if not in use.
Definition: SparseField.h:622
bool getGrainBounds(const size_t idx, Box3i &vsBounds) const
Bounding box of the given 'grain'.
Definition: SparseField.h:1951
iterator end()
Iterator pointing one element past the last valid one.
Definition: SparseField.h:1814
void setBlockEmptyValue(int bi, int bj, int bk, const Data_T &val)
Sets the constant value of an block. If the block is already allocated, it gets deallocated.
Definition: SparseField.h:1519
void setupBlocks()
Initializes the block structure. Will clear any existing data.
Definition: SparseField.h:1858
block_iterator blockEnd() const
Const iterator pointing to element one past the last valid block.
Definition: SparseField.h:1849
int releaseBlocks(Functor_T func)
Releases any blocks that are deemed empty. This can be used to clean up after algorithms that write "...
Definition: SparseField.h:1551
void applyDataWindowOffset(int &i, int &j, int &k) const
Applies data window offset.
Definition: SparseField.h:455
block_iterator blockBegin() const
Definition: SparseField.h:1837
static const char * staticClassName()
Definition: SparseField.h:368
V3i blockRes() const
Returns the resolution of the block array.
Definition: SparseField.h:1542
iterator begin()
Iterator to first element.
Definition: SparseField.h:1792
virtual void clear(const Data_T &value)
Clears all the voxels in the storage.
Definition: SparseField.h:1452
FIELD3D_CLASSNAME_CLASSTYPE_IMPLEMENTATION
Definition: SparseField.h:515
DEFINE_FIELD_RTTI_CONCRETE_CLASS
Definition: SparseField.h:366
static TemplatedFieldType< SparseField< Data_T > > ms_classType
Definition: SparseField.h:633
Block * m_blocks
Array of blocks. Not using std::vector since SparseBlock is noncopyable.
Definition: SparseField.h:616
virtual Data_T & lvalue(int i, int j, int k)
Write access to a voxel. The coordinates are global coordinates.
Definition: SparseField.h:1606
const Data_T getBlockEmptyValue(int bi, int bj, int bk) const
Returns the constant value of an block, whether it's allocated already or not..
Definition: SparseField.h:1511
Data_T * blockData(int bi, int bj, int bk) const
Returns a pointer to the data in a block, or null if the given block is unallocated.
Definition: SparseField.h:1694
int m_blockXYSize
Block array res.x * res.y.
Definition: SparseField.h:614
bool blockIndexIsValid(int bi, int bj, int bk) const
Returns whether a block index is valid.
Definition: SparseField.h:1533
ResizableField< Data_T > base
Definition: SparseField.h:582
int m_fileId
File id. Used with m_fileManager if active. Otherwise -1.
Definition: SparseField.h:624
void addReference(const std::string &filename, const std::string &layerPath, int valuesPerBlock, int numVoxels, int occupiedBlocks)
Internal function to create a Reference for the current field, for use in dynamic reading.
Definition: SparseField.h:1379
bool blockIsAllocated(int bi, int bj, int bk) const
Checks if a block is allocated.
Definition: SparseField.h:1502
void decBlockRef(const int blockId) const
Decrements the block ref count for the given block.
Definition: SparseField.h:1935
void deallocBlock(Block &block, const Data_T &emptyValue)
Deallocated the data of the given block and sets its empty value.
Definition: SparseField.h:1970
static const char * staticClassType()
Definition: SparseField.h:373
Data_T m_dummy
Dummy value used when needing to return but indicating a failed call.
Definition: SparseField.h:627
~SparseField()
Destructor.
Definition: SparseField.h:1311
SparseField()
Constructs an empty buffer.
Definition: SparseField.h:1287
SparseField< Data_T > class_type
Definition: SparseField.h:365
size_t m_numBlocks
Number of blocks in field.
Definition: SparseField.h:618
boost::intrusive_ptr< SparseField > Ptr
Definition: SparseField.h:357
Data_T fastValue(int i, int j, int k) const
Read access to voxel. Notice that this is non-virtual.
Definition: SparseField.h:1614
bool voxelIsInAllocatedBlock(int i, int j, int k) const
Checks if a voxel is in an allocated block.
Definition: SparseField.h:1491
friend class SparseFieldIO
Definition: SparseField.h:578
void activateBlock(const int blockId) const
Activates a given block.
Definition: SparseField.h:1927
Data_T & fastLValue(int i, int j, int k)
Write access to voxel. Notice that this is non-virtual.
Definition: SparseField.h:1653
int m_blockOrder
Block order (size = 2^blockOrder)
Definition: SparseField.h:610
std::vector< Ptr > Vec
Definition: SparseField.h:358
LinearSparseFieldInterp< Data_T > LinearInterp
Definition: SparseField.h:360
const_iterator cend() const
Const iterator pointing one element past the last valid one.
Definition: SparseField.h:1767
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
Definition: SparseField.h:517
virtual long long int memSize() const
Returns the memory usage (in bytes)
Definition: SparseField.h:1708
SparseField & operator=(const SparseField &o)
Assignment operator. For cache-managed fields, it creates a new file reference, and for non-managed f...
Definition: SparseField.h:1328
int blockSize() const
Returns the block size.
Definition: SparseField.h:1483
int blockOrder() const
Returns the block order.
Definition: SparseField.h:1475
void getVoxelInBlock(int i, int j, int k, int &vi, int &vj, int &vk) const
Calculates the coordinates in a block for the given voxel index.
Definition: SparseField.h:1905
void setupReferenceBlocks()
Internal function to setup the Reference's block pointers, for use with dynamic reading.
Definition: SparseField.h:1413
void getBlockCoord(int i, int j, int k, int &bi, int &bj, int &bk) const
Calculates the block coordinates that a given set of voxel coords are in.
Definition: SparseField.h:1890
V3i m_blockRes
Block array resolution.
Definition: SparseField.h:612
virtual size_t voxelCount() const
Counts the number of voxels. For most fields, this is just the volume of the data window,...
Definition: SparseField.h:1726
virtual Data_T value(int i, int j, int k) const
Read access to a voxel. The coordinates are in integer voxel space .
Definition: SparseField.h:1598
void copyBlockStates(const SparseField< Data_T > &o)
Internal function to copy empty values and allocated flags, without copying data, used when copying a...
Definition: SparseField.h:1399
void copySparseField(const SparseField &o)
Copies internal data, including blocks, from another SparseField, used by copy constructor and operat...
Definition: SparseField.h:1341
const_iterator cbegin() const
Const iterator to first element. "cbegin" matches the tr1 c++ standard.
Definition: SparseField.h:1744
int blockId(int blockI, int blockJ, int blockK) const
Calculates the block number based on a block i,j,k index.
Definition: SparseField.h:1881
void incBlockRef(const int blockId) const
Increments the block ref count for the given block.
Definition: SparseField.h:1919
void activateBlock(int fileId, int blockIdx)
Called by SparseField when it's about to read from a block. This should not be called by the user,...
Definition: SparseFile.h:1257
static SparseFileManager & singleton()
Returns a reference to the singleton instance.
Definition: SparseFile.cpp:66
std::string layerPath
Definition: SparseFile.h:128
BlockPtrs blocks
Pointers to each block. This is so we can go in and manipulate them as we please.
Definition: SparseFile.h:141
std::vector< int > fileBlockIndices
Index in file for each block.
Definition: SparseFile.h:135
std::string filename
Definition: SparseFile.h:127
@ SevWarning
Definition: Log.h:68
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity.
Definition: Log.cpp:70
Namespace for sparse field specifics.
Definition: SparseField.h:221
bool isAnyLess(const Data_T &left, const Data_T &right)
Definition: SparseField.h:770
FIELD3D_VEC3_T< T > ceil(const FIELD3D_VEC3_T< T > &v)
Ceil function for Vec3.
Definition: CoordSys.h:114
T max(const T a, const T2 b)
Max operation on mixed types.
Definition: FieldSampler.h:32
T min(const T a, const T2 b)
Min operation on mixed types.
Definition: FieldSampler.h:25
FIELD3D_VEC3_T< T > floor(const FIELD3D_VEC3_T< T > &v)
Floor function for Vec3.
Definition: CoordSys.h:104
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Definition: ns.h:58
Checks if all the values in the SparseBlock are equal. Used by SparseField::releaseBlocks().
Definition: SparseField.h:711
bool check(const SparseBlock< Data_T > &block, Data_T &retEmptyValue, const V3i &validSize, const V3i &blockSize)
Checks whether a given block can be released. It's safe to assume that the block is allocated if this...
Definition: SparseField.h:720
Checks if all the absolute values in the SparseBlock are greater than some number....
Definition: SparseField.h:812
bool check(const SparseBlock< Data_T > &block, Data_T &retEmptyValue, const V3i &validSize, const V3i &blockSize)
Checks whether a given block can be released. It's safe to assume that the block is allocated if this...
Definition: SparseField.h:825
CheckMaxAbs(Data_T maxValue)
Constructor. Takes max value.
Definition: SparseField.h:814
Storage for one individual block of a SparseField.
Definition: SparseField.h:228
bool isAllocated
Whether the block is allocated or not.
Definition: SparseField.h:303
const SparseBlock & operator=(const SparseBlock &)
Non-copyable.
void copy(const SparseBlock &other, size_t n)
Copy data from another block.
Definition: SparseField.h:285
SparseBlock(const SparseBlock &)
Non-copyable.
void resize(int n)
Alloc data.
Definition: SparseField.h:259
void clear()
Remove data.
Definition: SparseField.h:273
const Data_T & value(int i, int j, int k, int blockOrder) const
Gets the const value of a given voxel.
Definition: SparseField.h:255
Data_T emptyValue
The value to use if the block isn't allocated. We allow setting this per block so that we for example...
Definition: SparseField.h:308
Data_T & value(int i, int j, int k, int blockOrder)
Gets the value of a given voxel.
Definition: SparseField.h:249
Data_T * data
Pointer to data. Null if block is unallocated.
Definition: SparseField.h:311
static boost::mutex ms_resizeMutex
Prevents concurrent allocation of blocks. There should be little contention, and this prevents multip...
Definition: SparseField.h:325
Used to return a string for the name of a templated field.
Definition: Traits.h:283
const char * name()
Definition: Traits.h:284