#ifndef PASTELGFX_MIPMAP_HPP
#define PASTELGFX_MIPMAP_HPP
#include "pastel/gfx/mipmap/mipmap.h"
#include "pastel/gfx/filter.h"
#include "pastel/gfx/resampling.h"
#include "pastel/sys/array.h"
#include "pastel/sys/view/arrayview.h"
#include "pastel/sys/vector.h"
namespace Pastel
{
template <typename Type, integer N>
MipMap<Type, N>::MipMap()
: mipMapArray_()
, extender_()
{
}
template <typename Type, integer N>
template <typename Image_ConstView>
MipMap<Type, N>::MipMap(
const ConstView<N, Type, Image_ConstView>& image,
const ArrayExtender_& extender,
const FilterPtr& filter)
: mipMapArray_()
, extender_(extender)
{
Vector<integer, N> originalExtent = image.extent();
integer maxExtent = max(originalExtent);
integer roundedExtent = roundUpToPowerOfTwo(maxExtent);
Vector<integer, N> topExtent(roundedExtent);
integer images = integerLog2(roundedExtent) + 1;
std::vector<Array<Type, N> > mipMapArray(images);
mipMapArray.front().setExtent(topExtent);
// Upsample to power-of-two size.
if (topExtent == originalExtent)
{
copy(image, arrayView(mipMapArray.front()));
}
else
{
resample<Type>(
image,
extender,
filter,
arrayView(mipMapArray.front()));
}
// Sequentially downsample to ever smaller images.
Vector<integer, N> resampleExtent = topExtent;
for (integer i = 1;i < images;++i)
{
for (integer k = 0;k < N;++k)
{
resampleExtent[k] >>= 1;
}
mipMapArray[i].setExtent(resampleExtent);
resample<Type>(
constArrayView(mipMapArray[i - 1]),
extender,
filter,
arrayView(mipMapArray[i]));
}
ASSERT(allEqual(mipMapArray.back().extent(), 1));
mipMapArray_.swap(mipMapArray);
}
template <typename Type, integer N>
void MipMap<Type, N>::swap(MipMap& that)
{
mipMapArray_.swap(that.mipMapArray_);
}
template <typename Type, integer N>
void MipMap<Type, N>::clear()
{
mipMapArray_.clear();
}
template <typename Type, integer N>
MipMap<Type, N>& MipMap<Type, N>::operator=(const MipMap& that)
{
MipMap copy(that);
swap(copy);
return *this;
}
template <typename Type, integer N>
template <typename Image_ConstView>
void MipMap<Type, N>::setImage(
const ConstView<N, Type, Image_ConstView>& image,
const ArrayExtender_& extender,
const FilterPtr& filter)
{
MipMap<Type, N> copy(image, extender, filter);
swap(copy);
}
template <typename Type, integer N>
const Array<Type, N>&
MipMap<Type, N>::operator()(
integer level) const
{
PENSURE2(level >= 0 && level < levels(), level, levels());
return mipMapArray_[level];
}
template <typename Type, integer N>
const Array<Type, N>&
MipMap<Type, N>::mostDetailed() const
{
return (*this)(0);
}
template <typename Type, integer N>
const Array<Type, N>&
MipMap<Type, N>::coarsest() const
{
return (*this)(levels() - 1);
}
template <typename Type, integer N>
typename MipMap<Type, N>::MipView
MipMap<Type, N>::view(
integer level)
{
PENSURE2(level >= 0 && level < levels(), level, levels());
return arrayView(mipMapArray_[level]);
}
template <typename Type, integer N>
typename MipMap<Type, N>::ConstMipView
MipMap<Type, N>::view(
integer level) const
{
PENSURE2(level >= 0 && level < levels(), level, levels());
return constArrayView(mipMapArray_[level]);
}
template <typename Type, integer N>
typename MipMap<Type, N>::MipView
MipMap<Type, N>::mostDetailedView()
{
return view(0);
}
template <typename Type, integer N>
typename MipMap<Type, N>::ConstMipView
MipMap<Type, N>::mostDetailedView() const
{
return view(0);
}
template <typename Type, integer N>
typename MipMap<Type, N>::MipView
MipMap<Type, N>::coarsestView()
{
return view(levels() - 1);
}
template <typename Type, integer N>
typename MipMap<Type, N>::ConstMipView
MipMap<Type, N>::coarsestView() const
{
return view(levels() - 1);
}
template <typename Type, integer N>
Vector<integer, N> MipMap<Type, N>::extent() const
{
if (empty())
{
return Vector<integer, N>(0);
}
return mipMapArray_.front().extent();
}
template <typename Type, integer N>
integer MipMap<Type, N>::levels() const
{
return mipMapArray_.size();
}
template <typename Type, integer N>
bool MipMap<Type, N>::empty() const
{
return mipMapArray_.empty();
}
}
#endif