From 27ebbb6d3c240e61a832ede6d10a20774e13d29c Mon Sep 17 00:00:00 2001 From: Laurent Belcour Date: Fri, 30 Aug 2013 10:21:13 +0200 Subject: [PATCH] Moments seem to work. I get strange behaviour for glossy materials --- sources/core/params.cpp | 18 +++++ sources/core/params.h | 66 +++++++++------- sources/plugins/data_merl/data.cpp | 2 + sources/softs/data2moments/main.cpp | 116 ++++++++++++++-------------- 4 files changed, 117 insertions(+), 85 deletions(-) diff --git a/sources/core/params.cpp b/sources/core/params.cpp index 92bba67..eaac450 100644 --- a/sources/core/params.cpp +++ b/sources/core/params.cpp @@ -51,6 +51,7 @@ static const std::map input_map = { /* 4D Params */ {params::RUSIN_TH_PH_TD_PD, {"RUSIN_TH_PH_TD_PD", 4, "Complete Half angle parametrization"}}, {params::SPHERICAL_TL_PL_TV_PV, {"SPHERICAL_TL_PL_TV_PV", 4, "Complete classical parametrization"}}, + {params::STEREOGRAPHIC, {"STEREOGRAPHIC", 4, "Light/View vector in stereographic projection"}}, /* 6D Params */ {params::CARTESIAN, {"CARTESIAN", 6, "Complete vector parametrization"}} @@ -211,6 +212,23 @@ void params::from_cartesian(const double* invec, params::input outtype, #endif break; + case params::STEREOGRAPHIC: + { + // Project the View vector invec[0,1,2] on a 2D direction on the + // surface outvec[0,1] + double dotVN = invec[2]; + outvec[0] = invec[0] / (1.0+dotVN); + outvec[1] = invec[1] / (1.0+dotVN); + + // Project the Light vector invec[0,1,2] on a 2D direction on the + // surface outvec[2,3] + double dotLN = invec[5]; + outvec[2] = invec[3] / (1.0+dotLN); + outvec[3] = invec[4] / (1.0+dotLN); + + break; + } + // 6D Parametrization case params::CARTESIAN: memcpy(outvec, invec, 6*sizeof(double)); diff --git a/sources/core/params.h b/sources/core/params.h index 6a01dc0..ee573e1 100644 --- a/sources/core/params.h +++ b/sources/core/params.h @@ -8,13 +8,13 @@ #include #include -/*! \brief a static class allowing to change from one parametrization - * to another. +/*! \class params * \ingroup core + * \brief a static class allowing to change from one parametrization + * to another. * - * \details - * Any \typedef function object or \typedef data object should have - * an associated parametrization. + * Any function object or data object should have an associated + * parametrization. * * We use the following convention to defined the tangent, normal and * bi-normal of the surface: @@ -31,17 +31,22 @@ class params //! unknown. enum input { - ROMEIRO_TH_TD, - RUSIN_TH_TD, - RUSIN_TH_PH_TD, - RUSIN_TH_TD_PD, - RUSIN_TH_PH_TD_PD, - COS_TH, - COS_TH_TD, - ISOTROPIC_TV_TL_DPHI, - ISOTROPIC_TD_PD, // Difference between two directions such as R and H - CARTESIAN, - SPHERICAL_TL_PL_TV_PV, + RUSIN_TH_PH_TD_PD, /*!< Half-angle parametrization as described in [Rusinkiewicz'98] */ + RUSIN_TH_PH_TD, + RUSIN_TH_TD_PD, + RUSIN_TH_TD, /*!< Half-angle parametrization with no azimutal information */ + COS_TH_TD, + COS_TH, + + STEREOGRAPHIC, /*!< Stereographic projection of the Light and View vectors */ + + SPHERICAL_TL_PL_TV_PV, /*!< Light and View vectors represented in spherical coordinates */ + ISOTROPIC_TV_TL_DPHI, /*!< Light and View vectors represented in spherical coordinates, + with the difference of azimutal coordinates in the last component */ + ISOTROPIC_TD_PD, /*!< Difference between two directions such as R and H */ + + CARTESIAN, /*!< Light and View vectors represented in cartesian coordinates */ + UNKNOWN_INPUT }; @@ -107,14 +112,19 @@ class params static void convert(const double* invec, params::input intype, params::input outtype, double* outvec) { - double temvec[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Temp CARTESIAN vectors - to_cartesian(invec, intype, temvec); -#ifdef DEBUG - std::cout << "<> temp vec = [" - << temvec[0] << ", " << temvec[1] << ", " << temvec[2] << "] => [" - << temvec[3] << ", " << temvec[4] << ", " << temvec[5] << "]" << std::endl; -#endif - from_cartesian(temvec, outtype, outvec); + if(intype != outtype) + { + // temporary CARTESIAN vector + double temvec[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + + to_cartesian(invec, intype, temvec); + from_cartesian(temvec, outtype, outvec); + } + else + { + int dim = dimension(outtype); + for(int i=0; i 0.5*M_PI || fi_diff > M_PI) { + std::cerr << "<> the input vec is incorrect: TL = " << theta_in << ", PL = " << fi_in << ", TV = " << theta_out << ", PV = " << fi_out << std::endl; + std::cerr << "<> the input vec is incorrect: TH = " << theta_half << ", TD = " << theta_diff << ", PD = " << fi_diff << std::endl; throw; //! \todo Add exception list } // Find index. diff --git a/sources/softs/data2moments/main.cpp b/sources/softs/data2moments/main.cpp index cba018f..b1a5b8e 100644 --- a/sources/softs/data2moments/main.cpp +++ b/sources/softs/data2moments/main.cpp @@ -19,29 +19,29 @@ vec coord(vec V, vec L, vec X, vec Y, vec N) { - vec pV = V-dot(V,N)*N; - vec vCoord(2); + vec pV = V-dot(V,N)*N; + vec vCoord(2); vCoord[0] = dot(pV,X); - vCoord[1] = dot(pV,Y); - vCoord /= (1.0+dot(V,N)); + vCoord[1] = dot(pV,Y); + vCoord /= (1.0+dot(V,N)); - vec pL = L-dot(L,N)*N; - vec lCoord(2); - lCoord[0] = dot(pL,X); - lCoord[1] = dot(pL,Y); - lCoord /= (1.0+dot(L,N)); + vec pL = L-dot(L,N)*N; + vec lCoord(2); + lCoord[0] = dot(pL,X); + lCoord[1] = dot(pL,Y); + lCoord /= (1.0+dot(L,N)); - if (norm(lCoord)>EPSILON) - { - vec lDir = normalize(lCoord); + if (norm(lCoord)>EPSILON) + { + vec lDir = normalize(lCoord); - vec temp(2); + vec temp(2); temp[0] = lDir[0]*vCoord[0] + lDir[1]*vCoord[1]; temp[1] = lDir[0]*vCoord[1] - lDir[1]*vCoord[0]; - vCoord = temp; - } + vCoord = temp; + } - return vCoord; + return vCoord; } int main(int argc, char** argv) @@ -85,69 +85,71 @@ int main(int argc, char** argv) const int nX = d->dimX(); const int nY = d->dimY(); - // Normalisation factor for the integration - const int nb_theta_int = 90; - const int nb_phi_int = 180; - const double normalization = M_PI*M_PI / (double)(nb_phi_int*nb_theta_int); + // Normalisation factor for the integration + const int nb_theta_int = 90; + const int nb_phi_int = 360; + const double normalization = M_PI*M_PI / (double)(nb_phi_int*nb_theta_int); double in_angle[4] = {0.0, 0.0, 0.0, 0.0} ; - // Static data - vec X(3); X[0] = 1; X[1] = 0; X[2] = 0; - vec Y(3); Y[0] = 0; Y[1] = 1; Y[2] = 0; - vec N(3); N[0] = 0; N[1] = 0; N[2] = 1; + vec m_0(nY); + vec m_x(nY); + vec m_y(nY); + vec m_xx(nY); + vec m_xy(nY); + vec m_yy(nY); + // compute cumulants + vec k_x(nY); + vec k_y(nY); + vec k_xx(nY); + vec k_xy(nY); + vec k_yy(nY); for(int theta_in=0; theta_in<90; theta_in++) { in_angle[0] = theta_in * 0.5*M_PI / 90.0; - vec m_0(nY); m_0 = vec::Zero(nY); - vec m_x(nY); m_0 = vec::Zero(nY); - vec m_y(nY); m_0 = vec::Zero(nY); - vec m_xx(nY); m_0 = vec::Zero(nY); - vec m_xy(nY); m_0 = vec::Zero(nY); - vec m_yy(nY); m_0 = vec::Zero(nY); + m_0 = vec::Zero(nY); + m_x = vec::Zero(nY); + m_y = vec::Zero(nY); + m_xx = vec::Zero(nY); + m_xy = vec::Zero(nY); + m_yy = vec::Zero(nY); - // Integrate over the light hemisphere + // Theta angle in [0 .. PI / 2] for(int theta_out=0; theta_outvalue(in); - // Get the projected 2D coordinate - vec xy = coord(V, L, X, Y, N); for(int i=0; i