Commit cf404c33 authored by Laurent Belcour's avatar Laurent Belcour
Browse files

Adding the retro Blinn function

parent cdb81ce4
#include "function.h"
#include <string>
#include <iostream>
#include <fstream>
#include <limits>
#include <algorithm>
#include <cmath>
#include <core/common.h>
ALTA_DLL_EXPORT function* provide_function()
{
return new retroblinn_function();
}
// Overload the function operator
vec retroblinn_function::operator()(const vec& x) const
{
return value(x);
}
vec retroblinn_function::value(const vec& x) const
{
vec res(dimY());
for(int i=0; i<dimY(); ++i)
{
res[i] = _ks[i] * std::pow(x[0], _N[i]);
}
return res;
}
//! Load function specific files
void retroblinn_function::load(std::istream& in)
{
// Parse line until the next comment
while(in.peek() != '#')
{
char line[256];
in.getline(line, 256);
}
// Checking for the comment line #FUNC nonlinear_function_retroblinn
std::string token;
in >> token;
if(token != "FUNC") { std::cerr << "<<ERROR>> parsing the stream. The #FUNC is not the next line defined." << std::endl; }
in >> token;
if(token != "nonlinear_function_retroblinn") { std::cerr << "<<ERROR>> parsing the stream. function name is not the next token." << std::endl; }
// ks [double]
// N [double]
for(int i=0; i<dimY(); ++i)
{
in >> token >> _ks[i];
in >> token >> _N[i];
}
}
//! Number of parameters to this non-linear function
int retroblinn_function::nbParameters() const
{
return 2*dimY();
}
//! Get the vector of parameters for the function
vec retroblinn_function::parameters() const
{
vec res(2*dimY());
for(int i=0; i<dimY(); ++i)
{
res[i*2 + 0] = _ks[i];
res[i*2 + 1] = _N[i];
}
return res;
}
//! Update the vector of parameters for the function
void retroblinn_function::setParameters(const vec& p)
{
for(int i=0; i<dimY(); ++i)
{
_ks[i] = p[i*2 + 0];
_N[i] = p[i*2 + 1];
}
}
//! Obtain the derivatives of the function with respect to the
//! parameters.
vec retroblinn_function::parametersJacobian(const vec& x) const
{
vec jac(dimY()*nbParameters());
for(int i=0; i<dimY(); ++i)
for(int j=0; j<dimY(); ++j)
{
if(i == j)
{
// df / dk_s
jac[i*nbParameters() + j*2+0] = std::pow(x[0], _N[j]);
// df / dN
if(x[0] == 0.0)
jac[i*nbParameters() + j*2+1] = 0.0;
else
jac[i*nbParameters() + j*2+1] = _ks[j] * std::log(x[0]) * std::pow(x[0], _N[j]);
}
else
{
jac[i*nbParameters() + j*2+0] = 0.0;
jac[i*nbParameters() + j*2+1] = 0.0;
}
}
return jac;
}
void retroblinn_function::bootstrap(const data* d, const arguments& args)
{
}
void retroblinn_function::save_call(std::ostream& out,
const arguments& args) const
{
bool is_alta = !args.is_defined("export") || args["export"] == "alta";
if(is_alta)
{
out << "#FUNC nonlinear_function_retroblinn" << std::endl ;
for(int i=0; i<_nY; ++i)
{
out << "Ks " << _ks[i] << std::endl;
out << "N " << _N[i] << std::endl;
}
out << std::endl;
}
else
{
out << "retroblinn(L, V, N, X, Y, vec3(";
for(int i=0; i<_nY; ++i)
{
out << _ks[i];
if(i < _nY-1) { out << ", "; }
}
out << "), vec3(";
for(int i=0; i<_nY; ++i)
{
out << _N[i];
if(i < _nY-1) { out << ", "; }
}
out << "))";
}
}
void retroblinn_function::save_body(std::ostream& out,
const arguments& args) const
{
bool is_shader = args["export"] == "shader" || args["export"] == "explorer";
if(is_shader)
{
out << "vec3 retroblinn(vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y, vec ks, vec3 N)" << std::endl;
out << "{" << std::endl;
out << "\tvec3 Vp = 2.0f*N*(dot(N,V)) - V;" << std::endl;
out << "\tvec3 K = L + Vp;" << std::endl;
out << "\tvec3 K /= norm(K);" << std::endl;
out << "\tvec3 ext_dot = dot(K,N);" << std::endl;
out << "\treturn pow(max(ext_dot, vec3(0,0,0)), Nl);" << std::endl;
out << "}" << std::endl;
}
}
#pragma once
// Include STL
#include <vector>
#include <string>
// Interface
#include <core/function.h>
#include <core/rational_function.h>
#include <core/data.h>
#include <core/fitter.h>
#include <core/args.h>
#include <core/common.h>
/*! \brief A retroblinn lobe class. It is provided for testing with the nonlinear
* fitting algorithms.
*
* \details
* A retroblinn lobe is defined as \f$k_d + k_s |N.H|^a\f$
* \todo Finish implementation
*/
class retroblinn_function : public nonlinear_function
{
public: // methods
// Overload the function operator
virtual vec operator()(const vec& x) const ;
virtual vec value(const vec& x) const ;
//! \brief Boostrap the function by defining the diffuse term
virtual void bootstrap(const data* d, const arguments& args);
//! \brief Load function specific files
virtual void load(std::istream& filename) ;
//! \brief Number of parameters to this non-linear function
virtual int nbParameters() const ;
//! \brief Get the vector of parameters for the function
virtual vec parameters() const ;
//! \brief Update the vector of parameters for the function
virtual void setParameters(const vec& p) ;
//! \brief Obtain the derivatives of the function with respect to the
//! parameters.
virtual vec parametersJacobian(const vec& x) const ;
//! \brief Provide the dimension of the input space of the function
virtual int dimX() const
{
return 1 ;
}
//! \brief Provide the parametrization of the input space of the function.
virtual params::input parametrization() const
{
return params::COS_TH ;
}
virtual void setParametrization(params::input new_param)
{
std::cerr << "Cannot change the ouput parametrization "
<< __FILE__ << ":" << __LINE__ << std::endl;
throw;
}
void setDimY(int nY)
{
_nY = nY ;
// Update the length of the vectors
_ks.resize(_nY) ;
_N.resize(_nY) ;
}
//! \brief Export function
virtual void save_call(std::ostream& out, const arguments& args) const;
virtual void save_body(std::ostream& out, const arguments& args) const;
private: // data
//! \brief The retroblinn lobe data
vec _ks, _N;
} ;
TEMPLATE = lib
CONFIG *= qt \
plugin \
eigen
DESTDIR = ../../build
INCLUDEPATH += ../..
HEADERS = function.h
SOURCES = function.cpp
LIBS += -L../../build \
-lcore
......@@ -15,6 +15,7 @@ SUBDIRS = \
nonlinear_fresnel_schlick \
nonlinear_function_diffuse \
nonlinear_function_phong \
nonlinear_function_retroblinn \
nonlinear_function_lafortune \
nonlinear_function_isotropic_lafortune \
data_merl \
......
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