Commit 25ab3fc4 authored by Laurent Belcour's avatar Laurent Belcour

[Debug] Found the bug in the conversion to STARK_3D. The sine needed to

be signed!
[Update] The plugin data_brdf_slice support multiple export format now!
parent 07fe18e6
......@@ -285,97 +285,38 @@ void params::to_cartesian(const double* invec, params::input intype,
break;
case STARK_3D:
{
// Constructing the Half vector
const double Hx = invec[0];
const double Hy = 0;
const double Hz = sqrt(1.0 - invec[0]*invec[0] - invec[1]*invec[1]);
double const sqr_norm_H_bar = invec[0] * invec[0];
double const sqr_norm_K = invec[1] * invec[1];
double const test2 = sqr_norm_H_bar + sqr_norm_K;
// First TEST TO DONE BEFIRE THE NEXT ONE
if( test2 > 1.0 )
{
#ifdef DEBUG
std::cout << " RADIUS superior to 1. Below Hemisphere " << test2 << std::endl;
std::cout << " sqr_norm_H_bar = " << sqr_norm_H_bar << " sqr_norm_K = " << sqr_norm_K << std::endl;
std::cout << " invec = " << invec << std::endl;
#endif
//Returning an invalid CONFIGURATION
outvec[0] = 0.0;
outvec[1] = 0.0;
outvec[2] = -1.0;
outvec[3] = 0.0;
outvec[4] = 0.0;
outvec[5] = -1.0;
return;
}
const double Hz = sqrt(1.0 - sqr_norm_H_bar - sqr_norm_K);
// Ensuring that <H,B> = 0
// Constructing the Back vector using azimuth and elevation angles
const double cosPhi = cos(invec[2]);
const double sinPhi = sin(invec[2]);
assert( Hx * cos( invec[2]) > 0.0 );
const double cosThe = cos(atan(-Hz / (Hx*cos(invec[2]))));
//Another way to compute it
//double const cosThe = cos( atan2( -Hz , Hx*cos(invec[2])) );
double const test = sqr_norm_H_bar + sqr_norm_K *(1.0+cosThe*cosThe);
if( test > 1.0)
{
#ifdef DEBUG_PARAM
std::cout << " BELOW HEMISPHERE" << std::endl;
std::cout << " sqr_norm_H_bar = " << sqr_norm_H_bar << " sqr_norm_K = " << sqr_norm_K << std::endl;
std::cout << " invec[0] = " << invec[0] << " " << invec[1] << " " << invec[2] << " " << invec[3] << " " << std::endl;
#endif
#define STARK_BUILDING_THETA
//Returning an invalid CONFIGURATION
outvec[0] = 0.0;
outvec[1] = 0.0;
outvec[2] = -1.0;
outvec[3] = 0.0;
outvec[4] = 0.0;
outvec[5] = -1.0;
return;
}
assert( (1.0 - Hx*Hx - invec[1]*invec[1]) >= 0.0 );
assert( !std::isinf(cosThe) ); assert( !isnan(cosThe) );
assert( cosThe >= 0.0 );
assert( cosThe <= 1.0 );
const double sinThe = sqrt(1.0 - cosThe*cosThe);
#ifdef STARK_BUILDING_THETA
const double Theta = atan2(-Hz, invec[0]*cosPhi);
const double cosThe = cos(Theta);
const double sinThe = sin(Theta);
#else
// Pascal Barla's way to do it
const double cosThe = -cosPhi*invec[0] / sqrt(Hz*Hz + cosPhi*cosPhi*invec[0]*invec[0]);
const double sinThe = Hz / (sqrt(Hz*Hz + cosPhi*cosPhi * invec[0]*invec[0]));
#endif
const double Bx = invec[1]*sinThe*cosPhi;
const double By = invec[1]*sinThe*sinPhi;
const double Bz = invec[1]*cosThe;
outvec[0] = Hx-Bx;
outvec[1] = Hy-By;
outvec[2] = Hz-Bz;
outvec[3] = Hx+Bx;
outvec[4] = Hy+By;
outvec[5] = Hz+Bz;
assert( outvec[2] >= 0.0);
assert( outvec[5] >= 0.0);
#ifdef DEBUG_PARAM
std::cout << __FILE__ << " " << __LINE__ << std::endl;
std::cout << " outvec = " << outvec[0] << " " << outvec[1] << " " << outvec[2] << " " << outvec[3]
<< " " << outvec[4] << " " << outvec[5] << std::endl;
#endif
}
break;
break;
case NEUMANN_3D:
{
const double cosPhi = cos(invec[2]);
......@@ -388,7 +329,7 @@ void params::to_cartesian(const double* invec, params::input intype,
outvec[4] = - sinPhi*invec[1];
outvec[5] = sqrt(1.0 - outvec[3]*outvec[3] - outvec[4]*outvec[4]);
}
break;
break;
// 4D Parametrization
case params::RUSIN_TH_PH_TD_PD:
......
......@@ -95,10 +95,6 @@ class params
\theta_v \sin(\Delta\phi).\f$]*/
ISOTROPIC_TD_PD, /*!< Difference between two directions such as R and H */
BARYCENTRIC_ALPHA_SIGMA, /*!< Barycentric parametrization defined input Stark et al. [2004].
Coordinates are: \f$[\alpha, \sigma] = [{1\over 2}(1 - (L.V)),
(1-(H.N)^2)(1 - \alpha)]\f$ */
STARK_2D, /*!< Modified Stark et al. 2D parametrization. This parametrization
is defined by the couple \f$ \vec{x} = ||\tilde{H}_p||,
||\tilde{B}|| \f$, where \f$ \tilde{H} = \frac{1}{2}(L+V) \f$
......
......@@ -178,15 +178,16 @@ public: // methods
if( res[0] < 0.0 || res[1] < 0.0 || res[2] < 0.0 )
{
#ifdef DEBUG
std::cout << __FILE__ << " " << __LINE__ << " in[0] = " << in[0]
<< " in[1] = " << in[1] << " in[2] = " << in[2] << std::endl;
std::cout << "res = " << res << std::endl;
#endif
res[0] = 0.0;
res[1] = 0.0;
res[2] = 0.0;
assert(0);
//assert(0);
}
return res;
}
......@@ -419,7 +420,7 @@ private: //methods
green_val = brdf[ind + BRDF_SAMPLING_RES_THETA_H*BRDF_SAMPLING_RES_THETA_D*BRDF_SAMPLING_RES_PHI_D/2] * GREEN_SCALE;
blue_val = brdf[ind + BRDF_SAMPLING_RES_THETA_H*BRDF_SAMPLING_RES_THETA_D*BRDF_SAMPLING_RES_PHI_D] * BLUE_SCALE;
//#ifdef DEBUG
#ifdef DEBUG
if (red_val < 0.0 || green_val < 0.0 || blue_val < 0.0)
{
fprintf(stderr, "Negative value [%f, %f, %f].\n", theta_half, theta_diff, fi_diff);
......@@ -427,7 +428,7 @@ private: //methods
std::cerr << " AT INDEX = " << ind << std::endl;
}
//#endif
#endif
}
// Read BRDF data
......
......@@ -38,8 +38,10 @@ class BrdfSlice : public data {
public:
int width, height, slice;
vec _max, _min;
double _phi;
double* _data;
bool _reverse;
BrdfSlice(const arguments& args) : data()
{
......@@ -54,7 +56,7 @@ class BrdfSlice : public data {
_out_param = params::RGB_COLOR;
_nX = 2;
_nY = 3;
// Allow to load a different parametrization depending on the
// parameters provided.
if(args.is_defined("param")) {
......@@ -78,6 +80,16 @@ class BrdfSlice : public data {
std::cout << "<<ERROR>> Must have 2D input dimension" << std::endl;
}
}
// Is the position of the slice componnent (third coordinate)
// reversed? This ensure that some params can be displayed.
_reverse = _in_param == params::ISOTROPIC_TL_TV_PROJ_DPHI ||
_in_param == params::SCHLICK_TL_TK_PROJ_DPHI ||
_in_param == params::RETRO_TL_TVL_PROJ_DPHI;
// Update the domain
_max = max();
_min = min();
}
~BrdfSlice()
......@@ -113,12 +125,17 @@ class BrdfSlice : public data {
const int k = id / (width*height);
const int j = (id - k*width*height) / width;
res[0] = (i+0.5) / double(width);
res[1] = (j+0.5) / double(height);
res[0] = (i+0.5) * (_max[0]-_min[0]) / double(width) + _min[0];
res[1] = (j+0.5) * (_max[1]-_min[1]) / double(height) + _min[1];
if(_nX == 3) {
res[2] = _phi;
}
// Reverse the first part of the vector
if(_reverse) {
res.segment(0, _nX).reverseInPlace();
}
res[_nX+0] = _data[3*id + 0];
res[_nX+1] = _data[3*id + 1];
res[_nX+2] = _data[3*id + 2];
......@@ -133,19 +150,27 @@ class BrdfSlice : public data {
//! \todo Test this function
void set(const vec& x)
{
assert(x.size() == _nX+_nY);
assert(x[0] <= 1.0/*0.5*M_PI*/ && x[0] >= 0.0);
assert(x[1] <= 1.0/*0.5*M_PI*/ && x[1] >= 0.0);
// Copy vector is required
vec _x = x;
const int i = floor(x[0] * width / /*(0.5*M_PI)*/ 1.0);
const int j = floor(x[1] * height / /*(0.5*M_PI)*/ 1.0);
// Reverse the first part of the vector
if(_reverse) {
_x.segment(0, _nX).reverseInPlace();
}
assert(_x.size() == _nX+_nY);
assert(_x[0] <= _max[0] && _x[0] >= _min[0]);
assert(_x[1] <= _max[1] && _x[1] >= _min[1]);
const int i = floor((_x[0]-_min[0]) * width / (_max[0] - _min[0]));
const int j = floor((_x[1]-_min[1]) * height / (_max[1] - _min[1]));
const int k = 0;
//const int k = floor(x[2] * slice / (M_PI));
const int id = i + j*width + k*width*height;
_data[3*id + 0] = x[_nX+0];
_data[3*id + 1] = x[_nX+1];
_data[3*id + 2] = x[_nX+2];
_data[3*id + 0] = _x[_nX+0];
_data[3*id + 1] = _x[_nX+1];
_data[3*id + 2] = _x[_nX+2];
}
void set(int id, const vec& x)
{
......@@ -158,22 +183,29 @@ class BrdfSlice : public data {
vec value(const vec& x) const
{
// Copy vector is required
vec _x = x;
// Reverse the first part of the vector
if(_reverse) {
_x.segment(0, _nX).reverseInPlace();
}
// Safeguard. We can use either asserting or returning zero in case
// the query values are not within reach.
if(x[0] > 1.0 || x[0] < 0.0 || x[1] > 1.0 || x[1] < 0.0 ||
isnan(x[0]) || isnan(x[1])) {
if(_x[0] > _max[0] || x[0] < _min[0] || x[1] > _max[1] || x[1] < _min[1] ||
isnan(_x[0]) || isnan(x[1])) {
vec res(3);
return res;
}
/*
assert(x[0] <= 1.0 && x[0] >= 0.0);
assert(x[1] <= 1.0 && x[1] >= 0.0);
assert(_x[0] <= 1.0 && x[0] >= 0.0);
assert(_x[1] <= 1.0 && x[1] >= 0.0);
*/
const int i = floor(x[0] * width / 1.0);
const int j = floor(x[1] * height / 1.0);
const int i = floor((_x[0]-_min[0]) * width / (_max[0] - _min[0]));
const int j = floor((_x[1]-_min[1]) * height / (_max[1] - _min[1]));
const int k = 1;
//const int k = floor(x[2] * slice / (M_PI));
//const int k = floor(_x[2] * slice / (M_PI));
const int id = (i + j*width)*k;
if(i < 0 || i >= width) { std::cerr << "<<ERROR>> out of bounds: " << x << std::endl; }
......@@ -196,20 +228,56 @@ class BrdfSlice : public data {
vec min() const
{
vec res(_nX);
res[0] = 0.0 ;
res[1] = 0.0 ;
// First fill the third dimension. It can be overwritten by the next
// part when the parametrization is reversed (projected ones).
if(_nX == 3) {
res[2] = 0.0 ;
}
// Fill the first two dimension unless the parametrization is a
// projected one then it will fill the three components.
if(_in_param == params::ISOTROPIC_TL_TV_PROJ_DPHI ||
_in_param == params::ISOTROPIC_TV_TL_DPHI) {
res[0] = -0.5*M_PI ;
res[1] = -0.5*M_PI ;
} else if(_in_param == params::ISOTROPIC_TL_TV_PROJ_DPHI ||
_in_param == params::SCHLICK_TL_TK_PROJ_DPHI ||
_in_param == params::RETRO_TL_TVL_PROJ_DPHI) {
res[0] = -0.5*M_PI ;
res[1] = -0.5*M_PI ;
res[2] = -0.5*M_PI ;
} else {
res[0] = 0.0 ;
res[1] = 0.0 ;
}
return res ;
}
vec max() const
{
vec res(2);
res[0] = M_PI / 2 ;
res[1] = M_PI / 2 ;
vec res(_nX);
// First fill the third dimension. It can be overwritten by the next
// part when the parametrization is reversed (projected ones).
if(_nX == 3) {
res[2] = 0.0 ;
res[2] = 2.0*M_PI;
}
// Fill the first two dimension unless the parametrization is a
// projected one then it will fill the three components.
if(_in_param == params::RUSIN_TH_TD_PD ||
_in_param == params::ISOTROPIC_TV_TL_DPHI) {
res[0] = 0.5*M_PI ;
res[1] = 0.5*M_PI ;
} else if(_in_param == params::ISOTROPIC_TL_TV_PROJ_DPHI ||
_in_param == params::SCHLICK_TL_TK_PROJ_DPHI ||
_in_param == params::RETRO_TL_TVL_PROJ_DPHI) {
res[0] = 0.5*M_PI ;
res[1] = 0.5*M_PI ;
res[2] = 0.5*M_PI ;
} else {
res[0] = 1.0 ;
res[1] = 1.0 ;
}
return res ;
}
......
......@@ -197,13 +197,24 @@ int main(int argc, char** argv)
vec x = d_out->get(i);
params::convert(&x[0], d_out->parametrization(), params::CARTESIAN, &cart[0]);
// Check if the output configuration is below the hemisphere when converted to
// cartesian coordinates. Note that this prevent from converting BTDF data.
if(cart[2] >= 0.0 || cart[5] >= 0.0) {
params::convert(&cart[0], params::CARTESIAN, d_in->parametrization(), &temp[0]);
/*
y[0] = temp[0];
y[1] = temp[1];
y[2] = temp[2];
/*/
y = d_in->value(temp);
//*/
} else {
y.setZero();
}
// Convert the value stored in the input data in the value format of the output
// data file.
params::convert(&y[0], d_in->output_parametrization(), d_in->dimY(), d_out->output_parametrization(), d_out->dimY(), &x[d_out->dimX()]);
d_out->set(x);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment