diff --git a/library/PolyVoxCore/include/Array.h b/library/PolyVoxCore/include/Array.h index 9e0f8220..e3002c8f 100644 --- a/library/PolyVoxCore/include/Array.h +++ b/library/PolyVoxCore/include/Array.h @@ -35,26 +35,71 @@ freely, subject to the following restrictions: namespace PolyVox { + ///Provides an efficient implementation of a multidimensional array. + //////////////////////////////////////////////////////////////////////////////// + /// While C++ provides one-dimensional arrays as a language feature, it does not + /// provide a simple and intuitive way of working with multidimensional arrays + /// whose sizes are specified at runtime. Such a construct is very useful within + /// the context of PolyVox, and this Array class provides such functionality + /// implemented via templates and partial specialisation. + /// + /// The following code snippet illustrates the basic usage of the class by writing + /// a different value into each element: + /// + /// \code + /// int width = 5; + /// int height = 10; + /// int depth = 20; + /// + /// Array<3, int> myArray(ArraySizes(width)(height)(depth)); + /// + /// int ct = 1; + /// for(int z = 0; z < depth; z++) + /// { + /// for(int y = 0; y < height; y++) + /// { + /// for(int x = 0; x < width; x++) + /// { + /// myArray[x][y][z] = ct; + /// ct++; + /// } + /// } + /// } + /// \endcode + /// + /// Although the constructor and resize() function both take the required dimensions + /// as an array of ints, note that the ArraySizes class can be used to build this + /// inline. This is a more convienient way of specifying these dimensions. + /// + /// Note also that this class has a private assignment operator and copy constructor + /// in order to prevent copying. This is because a deep copy is a potentially slow + /// operation and can often be performed inadvertantly by functions such as std::swap, + /// while a shallow copy introduces confusion over memory ownership. + //////////////////////////////////////////////////////////////////////////////// template class Array { public: + ///Constructor Array(); - + ///Constructor Array(const uint32_t (&pDimensions)[noOfDims]); - + ///Destructor ~Array(); + ///Subarray access SubArray operator[](uint32_t uIndex); - + ///Subarray access const SubArray operator[](uint32_t uIndex) const; + ///Gets the total number of elements in this array uint32_t getNoOfElements(void) const; - + ///Gets a pointer to the first element of the array ElementType* getRawData(void) const; + ///Resize the array to the specified dimensions void resize(const uint32_t (&pDimensions)[noOfDims]); - + ///Swaps the contents of this array with the one specified void swap(Array& rhs); private: diff --git a/library/PolyVoxCore/include/Array.inl b/library/PolyVoxCore/include/Array.inl index 1bd7c59e..61164a75 100644 --- a/library/PolyVoxCore/include/Array.inl +++ b/library/PolyVoxCore/include/Array.inl @@ -23,6 +23,10 @@ distribution. namespace PolyVox { + //////////////////////////////////////////////////////////////////////////////// + /// Creates an empty array with no elements. You will have to call resize() on this + /// array befire it can be used. + //////////////////////////////////////////////////////////////////////////////// template Array::Array() :m_pElements(0) @@ -32,6 +36,12 @@ namespace PolyVox { } + //////////////////////////////////////////////////////////////////////////////// + /// Creates an array with the specified dimensions. + /// \param pDimensions The dimensions of the array. You can also use the ArraySizes + /// class to construct this more easily. + /// \sa ArraySizes + //////////////////////////////////////////////////////////////////////////////// template Array::Array(const uint32_t (&pDimensions)[noOfDims]) :m_pElements(0) @@ -42,12 +52,24 @@ namespace PolyVox resize(pDimensions); } + //////////////////////////////////////////////////////////////////////////////// + /// Destroys the array and releases all owned memory. + //////////////////////////////////////////////////////////////////////////////// template Array::~Array() { deallocate(); } + //////////////////////////////////////////////////////////////////////////////// + /// An N-dimensional array can be conceptually consists of N subarrays each of which + /// has N-1 dimensions. For example, a 3D array conceptually consists of three 2D + /// arrays. This operator is used to access the subarray at the specified index. + /// Crucially, the subarray defines a similar operator allowing them to be chained + /// together to convieniently access a particular element. + /// \param uIndex The zero-based index of the subarray to retrieve. + /// \return The requested SubArray + //////////////////////////////////////////////////////////////////////////////// template SubArray Array::operator[](uint32_t uIndex) { @@ -57,6 +79,15 @@ namespace PolyVox m_pDimensions+1, m_pOffsets+1); } + //////////////////////////////////////////////////////////////////////////////// + /// An N-dimensional array can be conceptually consists of N subarrays each of which + /// has N-1 dimensions. For example, a 3D array conceptually consists of three 2D + /// arrays. This operator is used to access the subarray at the specified index. + /// Crucially, the subarray defines a similar operator allowing them to be chained + /// together to convieniently access a particular element. + /// \param uIndex The zero-based index of the subarray to retrieve. + /// \return The requested SubArray + //////////////////////////////////////////////////////////////////////////////// template const SubArray Array::operator[](uint32_t uIndex) const { @@ -66,18 +97,36 @@ namespace PolyVox m_pDimensions+1, m_pOffsets+1); } + //////////////////////////////////////////////////////////////////////////////// + /// \return The number of elements in the array. + /// \sa getRawData() + //////////////////////////////////////////////////////////////////////////////// template uint32_t Array::getNoOfElements(void) const { return m_uNoOfElements; } + //////////////////////////////////////////////////////////////////////////////// + /// Sometimes it is useful to directly manipulate the underlying array without + /// going through this classes interface. Although this does not honour the principle + /// of encapsulation it can be done safely if you are careful and can sometimes be + /// useful. Use getNoOfElements() to determine how far you can safely write. + /// \return A pointer to the first element of the array + /// \sa getNoOfElements() + //////////////////////////////////////////////////////////////////////////////// template ElementType* Array::getRawData(void) const { return m_pElements; } + //////////////////////////////////////////////////////////////////////////////// + /// Please note that the existing contents of the array will be lost. + /// \param pDimensions The new dimensions of the array. You can also use the + /// ArraySizes class to specify this more easily. + /// \sa ArraySizes + //////////////////////////////////////////////////////////////////////////////// template void Array::resize(const uint32_t (&pDimensions)[noOfDims]) { @@ -104,6 +153,12 @@ namespace PolyVox m_pElements = new ElementType[m_uNoOfElements]; } + //////////////////////////////////////////////////////////////////////////////// + /// Because this class does not have a public assignment operator or copy constructor + /// it cnnot be used with the STL swap() function. This function provides an efficient + /// implementation of that feature. + /// \param rhs The array to swap this object with. + //////////////////////////////////////////////////////////////////////////////// template void Array::swap(Array& rhs) { @@ -158,7 +213,9 @@ namespace PolyVox m_uNoOfElements = 0; } - //////////////////////////////////////////////////////////////////////////////// + //****************************************************************************// + // One dimensional specialisation begins here // + //****************************************************************************// template Array<1, ElementType>::Array()