/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #if defined(USE_MEM_ALLOCATOR) extern CSHAllocator gsByteAllocator; #endif namespace NSH { /************************************************************************************************************************************************/ #pragma warning (disable : 4291) //simple compatible vector class to make it work with different STLs, keep name similar to stl //be aware that it does not behave completely the same template inline prtvector::prtvector() : m_pElements(NULL), m_ElemCount(0) {} template inline prtvector::prtvector(const uint32 cInitialElemCount) : m_pElements(NULL), m_ElemCount(cInitialElemCount) { if(cInitialElemCount == 0) return; #if defined(USE_MEM_ALLOCATOR) m_pElements = (T*)gsByteAllocator.new_mem_array(m_ElemCount * sizeof(T)); #else m_pElements = (T*)malloc(m_ElemCount * sizeof(T)); #endif for(uint32 i=0; i inline prtvector::~prtvector() { if(m_ElemCount) { for(uint32 i=0; i inline prtvector::prtvector(const prtvector& crCopyFrom) { m_pElements = NULL; m_ElemCount = crCopyFrom.m_ElemCount; if(m_ElemCount == 0) return; #if defined(USE_MEM_ALLOCATOR) m_pElements = (T*)gsByteAllocator.new_mem_array(m_ElemCount * sizeof(T)); #else m_pElements = (T*)malloc(m_ElemCount * sizeof(T)); #endif assert(m_pElements); for(uint32 i=0; i inline prtvector& prtvector::operator=(const prtvector& crAssignFrom) { if(m_pElements) { assert(m_ElemCount > 0); for(uint32 i=0; i inline void prtvector::resize(const size_t cNewElemCount) { if(cNewElemCount > m_ElemCount) { if(m_ElemCount > 0) { for(uint32 i=0; i inline void prtvector::reserve(const size_t cNewElemCount) {} template inline const bool prtvector::empty() const { return (m_ElemCount == 0); } template inline T& prtvector::operator[](const size_t cIndex) { assert(cIndex < m_ElemCount); return m_pElements[cIndex]; } template inline const T& prtvector::operator[](const size_t cIndex) const { assert(cIndex < m_ElemCount); return m_pElements[cIndex]; } template inline typename prtvector::const_iterator prtvector::begin() const { assert(m_ElemCount > 0); return m_pElements; } template inline typename prtvector::iterator prtvector::begin() { assert(m_ElemCount > 0); return m_pElements; } template inline typename prtvector::iterator prtvector::end() { assert(m_ElemCount > 0); return (m_pElements + m_ElemCount); } template inline typename prtvector::const_iterator prtvector::end() const { assert(m_ElemCount > 0); return (m_pElements + m_ElemCount); } template inline const size_t prtvector::size() const { return m_ElemCount; } /************************************************************************************************************************************************/ template template inline struct prtlist::SListElem prtlist::SListElem::CreateDummy() { return SListElem((SListElem*)(UINT_PTR)0xFFFFFFFF, NULL); } template template inline prtlist::SListElem::SListElem(const SListElem& crCopyFrom) : pNext(crCopyFrom.pNext), pPrevious(crCopyFrom.pPrevious), elem(crCopyFrom.elem) {} template template inline prtlist::SListElem::SListElem(SListElem *cpPrevious, SListElem *cpNext) : pNext(cpNext), pPrevious(cpPrevious) {} template template inline prtlist::SListElem::SListElem(const TE& crElem) : pNext(NULL), pPrevious(NULL), elem(crElem) {} template template inline prtlist::SListElem::SListElem() { pPrevious = pNext = NULL; } template template inline TE& prtlist::SListElem::operator*() { return elem; } template template inline const TE& prtlist::SListElem::operator*() const { return elem; } template template inline TE& prtlist::SListElem::operator->() { return elem; } template template inline const TE& prtlist::SListElem::operator->() const { return elem; } template template inline struct prtlist::SListElem& prtlist::SListElem::operator=(const struct prtlist::SListElem& crElem) { pNext = crElem.pNext; pPrevious = crElem.pPrevious; elem = crElem.elem; return *this; } template template inline struct prtlist::SListElem& prtlist::SListElem::operator++() { SListElem *pNextTmp = pNext; if(!pNextTmp) operator=(CreateDummy()); else { pNext = pNextTmp->pNext; pPrevious = pNextTmp->pPrevious; elem = pNextTmp->elem; } return *this; } template template inline struct prtlist::SListElem prtlist::SListElem::operator++(int) { SListElem old(*this); SListElem *pNextTmp = pNext; if(!pNextTmp) operator=(this->m_LastDummy); else { pNext = pNextTmp->pNext; pPrevious = pNextTmp->pPrevious; elem = pNextTmp->elem; } return old; } template template inline const bool prtlist::SListElem::operator !=(const typename prtlist::SListElem& crE) const { return (pPrevious != crE.pPrevious) || (pNext != crE.pNext); } template inline prtlist::prtlist() : m_pFirst(NULL), m_pLastElem(NULL), m_LastDummy(SListElem::CreateDummy()) {} /* template inline typename prtlist::const_iterator prtlist::begin() const { return (const_iterator)*m_pFirst; } */ template inline typename prtlist::iterator prtlist::begin() { return (iterator)*m_pFirst; } /* template inline typename prtlist::const_iterator prtlist::end() const { return (const_iterator)m_LastDummy; } */ template inline typename prtlist::iterator prtlist::end() { return (iterator)m_LastDummy; } template inline void prtlist::remove(const T& crElem) { assert(m_pFirst); SListElem *iter = m_pFirst; while(iter) { if(iter->elem == crElem) { //found element if(iter->pPrevious) iter->pPrevious->pNext = iter->pNext; if(iter->pNext) iter->pNext->pPrevious = iter->pPrevious; if(m_pFirst == iter) m_pFirst = NULL; if(m_pLastElem == iter) { if(m_pLastElem == m_pFirst) m_pLastElem = NULL; else m_pLastElem = iter->pPrevious; } #if defined(USE_MEM_ALLOCATOR) gsByteAllocator.delete_mem(iter, sizeof(SListElem)); #else free(iter); #endif break; } iter = iter->pNext; } } template inline void prtlist::push_back(const T& crElem) { #if defined(USE_MEM_ALLOCATOR) SListElem *pNewElem = (SListElem*)gsByteAllocator.new_mem(sizeof(SListElem)); #else SListElem *pNewElem = (SListElem*)malloc(sizeof(SListElem)); #endif assert(pNewElem); new (pNewElem) SListElem(crElem); if(!m_pFirst) m_pFirst = pNewElem; else pNewElem->pPrevious = m_pLastElem; pNewElem->pNext = &m_LastDummy; m_pLastElem = pNewElem; } #pragma warning (default : 4291) /************************************************************************************************************************************************/ inline const SDescriptor& SDescriptor::operator=(const SDescriptor& rCopyFrom) { Bands = rCopyFrom.Bands; Coefficients = rCopyFrom.Coefficients; return *this; } inline SDescriptor::SDescriptor(const uint8 cNumberOfBands) : Bands(cNumberOfBands), Coefficients(cNumberOfBands*cNumberOfBands){} /************************************************************************************************************************************************/ //!< scalar coefficient type template inline SScalarCoeff_tpl::SScalarCoeff_tpl() : m_Value(0.){} template inline SScalarCoeff_tpl::SScalarCoeff_tpl(const TFloatType cX) : m_Value(cX){} template inline const SScalarCoeff_tpl& SScalarCoeff_tpl::operator=(const TFloatType cX){m_Value = cX;return *this;} template inline SScalarCoeff_tpl::operator TFloatType&(){return m_Value;} template inline SScalarCoeff_tpl::operator const TFloatType&()const{return m_Value;} template inline const TFloatType& SScalarCoeff_tpl::operator[](const size_t cIndex)const{assert(cIndex == 0);return m_Value;} template inline TFloatType& SScalarCoeff_tpl::operator[](const size_t cIndex){assert(cIndex == 0);return m_Value;} template template inline SScalarCoeff_tpl& SScalarCoeff_tpl::operator=(const SScalarCoeff_tpl& crCopyFrom) { m_Value = (TFloatType)crCopyFrom.m_Value; return *this; } /************************************************************************************************************************************************/ template inline SRGBCoeff_tpl::SRGBCoeff_tpl() : ::Vec3_tpl(0.,0.,0.){} template inline SRGBCoeff_tpl::SRGBCoeff_tpl(const TFloatType cX, const TFloatType cY, const TFloatType cZ) : ::Vec3_tpl(cX, cY, cZ){} template inline const SRGBCoeff_tpl& SRGBCoeff_tpl::operator *=(const SRGBCoeff_tpl& rSource) { //multiply componentwise this->x *= rSource.x; this->y *= rSource.y; this->z *= rSource.z; return *this; } template inline const SRGBCoeff_tpl& SRGBCoeff_tpl::operator *=(const TFloatType cScalar) { //multiply componentwise this->x *= cScalar; this->y *= cScalar; this->z *= cScalar; return *this; } template template inline const SRGBCoeff_tpl& SRGBCoeff_tpl::operator =(const Vec3_tpl& rCopyFrom) { this->x = (TFloatType)rCopyFrom.x; this->y = (TFloatType)rCopyFrom.y; this->z = (TFloatType)rCopyFrom.z; return *this; } template inline SRGBCoeff_tpl::SRGBCoeff_tpl(const Vec3_tpl& rCopyFrom) : ::Vec3_tpl(rCopyFrom){} template template inline SRGBCoeff_tpl::operator SRGBCoeff_tpl()const { return SRGBCoeff_tpl((TOtherFloatType)this->x, (TOtherFloatType)this->y, (TOtherFloatType)this->z); } template inline const SRGBCoeff_tpl operator *(const SRGBCoeff_tpl& r0, const SRGBCoeff_tpl& r1) { //multiply componentwise return SRGBCoeff_tpl(r0.x * r1.x, r0.y * r1.y, r0.z * r1.z); } template inline const SRGBCoeff_tpl operator +(const SRGBCoeff_tpl& r0, const SRGBCoeff_tpl& r1) { //multiply componentwise return SRGBCoeff_tpl(r0.x + r1.x, r0.y + r1.y, r0.z + r1.z); } template inline const SRGBCoeff_tpl operator *(const SRGBCoeff_tpl& r0, const TFloatType cScalar) { return SRGBCoeff_tpl(r0.x * cScalar, r0.y * cScalar, r0.z * cScalar); } /************************************************************************************************************************************************/ template inline SPolarCoord_tpl::SPolarCoord_tpl() : theta(0), phi(0){} template inline SPolarCoord_tpl::SPolarCoord_tpl(const TFloatType cTheta, const TFloatType cPhi) : theta(cTheta), phi(cPhi){} template template inline SPolarCoord_tpl::operator SPolarCoord_tpl()const { return SPolarCoord_tpl((TOtherFloatType)theta, (TOtherFloatType)phi); } /************************************************************************************************************************************************/ //!< cartesian coordinate set template inline SCartesianCoord_tpl::SCartesianCoord_tpl() : ::Vec3_tpl(0,0,0){} template inline SCartesianCoord_tpl::SCartesianCoord_tpl(const TFloatType cX, const TFloatType cY, const TFloatType cZ) : ::Vec3_tpl(cX, cY, cZ){} template template inline SCartesianCoord_tpl::SCartesianCoord_tpl(const SCartesianCoord_tpl& rcCopyFrom) : ::Vec3_tpl((TFloatType)rcCopyFrom.x, (TFloatType)rcCopyFrom.y, (TFloatType)rcCopyFrom.z){} template inline const SCartesianCoord_tpl SCartesianCoord_tpl::operator-()const{return SCartesianCoord_tpl(-this->x, -this->y, -this->z);} template template inline const SCartesianCoord_tpl& SCartesianCoord_tpl::operator =(const Vec3_tpl& rcAssignFrom) { this->x = rcAssignFrom.x; this->y = rcAssignFrom.y; this->z = rcAssignFrom.z; return *this; } template template inline SCartesianCoord_tpl::operator SCartesianCoord_tpl()const { return SCartesianCoord_tpl ( (TOtherFloatType)Vec3_tpl::x, (TOtherFloatType)Vec3_tpl::y, (TOtherFloatType)Vec3_tpl::z ); } template inline void ConvertToCartesian(SCartesianCoord_tpl& rCartesian, const SPolarCoord_tpl& crPolar) { rCartesian.x = Sin(crPolar.theta) * Cos(crPolar.phi); rCartesian.y = Sin(crPolar.theta) * Sin(crPolar.phi); rCartesian.z = Cos(crPolar.theta); } template inline void ConvertUnitToPolar(SPolarCoord_tpl& rPolar, const SCartesianCoord_tpl& crCartesian) { const double cS = Sqrt(crCartesian.x * crCartesian.x + crCartesian.y * crCartesian.y); rPolar.theta = (TFloatType)ACos(crCartesian.z); rPolar.phi = (TFloatType)((cS < 0.0000001)?0.:(crCartesian.x>=0.)?ASin(crCartesian.y/cS):(g_cPi-ASin(crCartesian.y/cS))); if(rPolar.phi < 0) rPolar.phi += (TFloatType)(2.0 * g_cPi); assert(rPolar.phi >= 0 && rPolar.phi <= 2 * g_cPi && rPolar.theta >= 0. && rPolar.theta <= g_cPi); /* const double cS = Sqrt(crCartesian.x * crCartesian.x + crCartesian.y * crCartesian.y); rPolar.theta = (TFloatType)ACos(crCartesian.z); const TFloatType cASin = (TFloatType)((abs(crCartesian.x) >= 0.005)?ASin(crCartesian.y/cS) : (crCartesian.y>0.f)? g_cPi*0.5 : -g_cPi*0.5); rPolar.phi = (TFloatType)((cS < 0.00001)?0.:(crCartesian.x>=0.)?cASin:(g_cPi-cASin)); if(rPolar.phi < 0) rPolar.phi += (TFloatType)(2.0 * g_cPi); */ assert(rPolar.phi >= 0 && rPolar.phi <= 2 * g_cPi && rPolar.theta >= 0. && rPolar.theta <= g_cPi); } template inline void ConvertToPolar(SPolarCoord_tpl& rPolar, const SCartesianCoord_tpl& crCartesian) { const double cR = Sqrt(crCartesian.x * crCartesian.x + crCartesian.y * crCartesian.y + crCartesian.z * crCartesian.z); const double cS = Sqrt(crCartesian.x * crCartesian.x + crCartesian.y * crCartesian.y); rPolar.theta = ACos(crCartesian.z/cR); rPolar.phi = (TFloatType)((cS < 0.0000001)?0.:(crCartesian.x>=0.)?ASin(crCartesian.y/cS):(g_cPi-ASin(crCartesian.y/cS))); if(rPolar.phi < 0) rPolar.phi += (TFloatType)(2.0 * g_cPi); assert(rPolar.phi >= 0 && rPolar.phi <= 2 * g_cPi && rPolar.theta >= 0. && rPolar.theta <= g_cPi); } /************************************************************************************************************************************************/ template inline void CalcRotMatrixToSphereOrigin(Matrix33_tpl& rRotMatrix, const TCartesianCoord& rFrom) { //retrieve polar coordinates and concatenate the two rotations TPolarCoord polarCoord; ConvertUnitToPolar(polarCoord, rFrom); rRotMatrix.SetRotationZ((float)-polarCoord.phi); rRotMatrix = Matrix33_tpl::CreateRotationY((float)-polarCoord.theta) * rRotMatrix; //TODO: check ivos method for creating a rotation matrix toward sphere origin //const Vec3 yaxis = GetOrthogonal(rFrom).GetNormalized(); //const Vec3 xaxis = yaxis % rFrom; //rRotMatrix.M00 = xaxis.x; rRotMatrix.M01 = xaxis.y; rRotMatrix.M02 = xaxis.z; //rRotMatrix.M10 = yaxis.x; rRotMatrix.M11 = yaxis.y; rRotMatrix.M12 = yaxis.z; //rRotMatrix.M20 = rFrom.x; rRotMatrix.M21 = rFrom.y; rRotMatrix.M22 = rFrom.z; } template inline void CalcRotMatrixToSphereOrigin(Matrix33_tpl& rRotMatrix, const TPolarCoord& rFrom) { rRotMatrix.SetRotationZ((float)-rFrom.phi); rRotMatrix = Matrix33_tpl::CreateRotationY((float)-rFrom.theta) * rRotMatrix; } template inline void CalcRotMatrixFromSphereOrigin(Matrix33_tpl& rRotMatrix, const TCartesianCoord& rTo) { //retrieve polar coordinates and concatenate the two rotations TPolarCoord polarCoord; ConvertUnitToPolar(polarCoord, rTo); rRotMatrix.SetRotationZ((float)polarCoord.phi); rRotMatrix = Matrix33_tpl::CreateRotationY((float)polarCoord.theta) * rRotMatrix; } template inline void CalcRotMatrixFromSphereOrigin(Matrix33_tpl& rRotMatrix, const TPolarCoord& rTo) { //retrieve polar coordinates and concatenate the two rotations rRotMatrix.SetRotationZ((TFloatType)rTo.phi); rRotMatrix = Matrix33_tpl::CreateRotationY((TFloatType)rTo.theta) * rRotMatrix; } /************************************************************************************************************************************************/ template< typename CoeffType > inline SCoeffList_tpl::~SCoeffList_tpl() {} template< typename CoeffType > inline SCoeffList_tpl::SCoeffList_tpl(const SDescriptor& crDescriptor) : m_Coeffs(crDescriptor.Coefficients){} template< typename CoeffType > inline SCoeffList_tpl::SCoeffList_tpl(const uint32 cCoefficients) : m_Coeffs(cCoefficients){} template< typename CoeffType > template< typename CoeffTypeFrom > inline SCoeffList_tpl::SCoeffList_tpl(const SCoeffList_tpl& rCopyFrom) { if(m_Coeffs.size() != rCopyFrom.size()) m_Coeffs.resize(rCopyFrom.size()); //copy values for(size_t i=0; i template< typename CoeffTypeFrom > inline SCoeffList_tpl& SCoeffList_tpl::operator=(const SCoeffList_tpl& rCopyFrom) { if(m_Coeffs.size() != rCopyFrom.size()) m_Coeffs.resize(rCopyFrom.size()); //copy values for(size_t i=0; i inline void SCoeffList_tpl::ResetToZero() { for(int i=0; i<(int)m_Coeffs.size(); ++i) for(int j=0; j<(int)CoeffType::Components(); ++j) (m_Coeffs[i])[j] = 0.f; } template< typename CoeffType > inline void SCoeffList_tpl::ReSize(const SDescriptor& crDescriptor) { m_Coeffs.resize(crDescriptor.Coefficients); } template< typename CoeffType > inline CoeffType& SCoeffList_tpl::operator()(const int32 cL, const int32 cM) { return (m_Coeffs[cL * (cL + 1) + cM]); } template< typename CoeffType > inline const CoeffType& SCoeffList_tpl::operator()(const int32 cL, const int32 cM) const { return (m_Coeffs[cL * (cL + 1) + cM]); } template< typename CoeffType > inline const SCoeffList_tpl& SCoeffList_tpl::operator +=(const SCoeffList_tpl& rToAdd) { assert(rToAdd.size() == m_Coeffs.size()); const int numberToCopy = (int)std::min((size_t)rToAdd.size(), (size_t)m_Coeffs.size()); for(int i=0; i inline const SCoeffList_tpl& SCoeffList_tpl::operator *=(const double cScalar) { for(size_t i=0; i const CoeffType* const SCoeffList_tpl::GetCoeffs() const { return (m_Coeffs.size() > 0)?(CoeffType*)&m_Coeffs[0] : NULL; } template const CoeffType SCoeffList_tpl::PerformLookup(const CSample_tpl >& crSample, const ECoeffChoice cCoeffChoice) const { //now set up vectors for dot4 assert(crSample.NumberOfCoeffs() > 0 && size() > 0); const SCoeffList_tpl& rSampleCoeffList = crSample.Coeffs(); TComponentType output = m_Coeffs[0] * (typename TComponentType::TComponentType)rSampleCoeffList[0]; if(crSample.NumberOfCoeffs() > 8)//special case only for >=3 bands { for(int i=1; i<=3; ++i) output += m_Coeffs[i] * (typename TComponentType::TComponentType)rSampleCoeffList[i]; if(cCoeffChoice != NO_COEFF_Y2m2)//dont use coeff Y2-2 output += m_Coeffs[4] * (typename TComponentType::TComponentType)rSampleCoeffList[4]; for(int i=5; i<=7; ++i) output += m_Coeffs[i] * (typename TComponentType::TComponentType)rSampleCoeffList[i]; if(cCoeffChoice != NO_COEFF_Y22)//dont use coeff Y22 output += m_Coeffs[8] * (typename TComponentType::TComponentType)rSampleCoeffList[8]; for(int i=9; i inline const size_t SCoeffList_tpl::size()const{return m_Coeffs.size();} template< typename CoeffType > inline CoeffType& SCoeffList_tpl::operator[](const size_t cIndex){assert(cIndex < m_Coeffs.size()); return m_Coeffs[cIndex];} template< typename CoeffType > inline const CoeffType SCoeffList_tpl::operator[](const size_t cIndex)const {assert(cIndex < m_Coeffs.size()); return m_Coeffs[cIndex];} template inline const SCoeffList_tpl operator +(const SCoeffList_tpl& r0, const SCoeffList_tpl& r1) { assert(r0.size() == r1.size()); SCoeffList_tpl sum(r0); sum += r1; return sum; } template inline const SCoeffList_tpl operator *(const SCoeffList_tpl& r0, const SCoeffList_tpl& r1) { assert(r0.size() == r1.size()); SCoeffList_tpl sum(r0); sum *= r1; return sum; } template inline const SCoeffList_tpl operator *(const SCoeffList_tpl& r0, const double cScalar) { SCoeffList_tpl sum(r0); sum *= cScalar; return sum; } /************************************************************************************************************************************************/ template inline CSample_tpl::CSample_tpl(const SDescriptor& crDescriptor, const TPolarCoord& crPolarCoord, const TSampleHandle cHandle) : m_PolarCoord(crPolarCoord), m_Coeffs(crDescriptor), m_Handle(cHandle) { for (int l = 0, c = 0; l < crDescriptor.Bands; l++) for (int m = -l; m <= l; m++, c++) m_Coeffs[c] = (TScalarCoeff::TComponentType)NLegendre::Y(l, m, crPolarCoord.theta, crPolarCoord.phi, NLegendre::SLEGENDRE_CALC_OPTIMIZED() ); ConvertToCartesian(m_CartCoord, crPolarCoord); #if defined(_DEBUG) m_Constructed = true; #endif } template inline CSample_tpl::CSample_tpl(const CSample_tpl& crCopyFrom) : m_CartCoord(crCopyFrom.m_CartCoord), m_PolarCoord(crCopyFrom.m_PolarCoord), m_Coeffs(crCopyFrom.m_Coeffs), m_Handle(0) { #if defined(_DEBUG) m_Constructed = crCopyFrom.m_Constructed; #endif } template inline CSample_tpl::CSample_tpl() : m_PolarCoord(TPolarCoord(0,0)), m_Coeffs(SDescriptor()) { //not constructed, do explicitely ConvertToCartesian(m_CartCoord, m_PolarCoord); #if defined(_DEBUG) m_Constructed = false; #endif } template inline void CSample_tpl::Validate()const { #if defined(_DEBUG) assert(m_Constructed == true); #endif } template inline const uint8 CSample_tpl::NumberOfCoeffs()const{Validate(); return (uint8)m_Coeffs.size();} template inline const TCartesianCoord& CSample_tpl::GetCartesianPos()const{Validate(); return m_CartCoord;} template inline const TPolarCoord& CSample_tpl::GetPolarPos()const{Validate(); return m_PolarCoord;} template inline const CoeffTypeList& CSample_tpl::Coeffs()const{Validate(); return m_Coeffs;} template inline CoeffTypeList& CSample_tpl::Coeffs(){Validate(); return m_Coeffs;} template inline void CSample_tpl::SetHandle(const TSampleHandle cHandle){Validate(); m_Handle = cHandle;} template inline const TSampleHandle CSample_tpl::GetHandle()const{Validate(); return m_Handle;} }//NSH