383 lines
14 KiB
C++
383 lines
14 KiB
C++
/*
|
|
This file is part of Mitsuba, a physically based rendering system.
|
|
|
|
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
|
|
|
This particular file is based on code by Piti Irawan, which is
|
|
redistributed with permission.
|
|
|
|
Mitsuba is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License Version 3
|
|
as published by the Free Software Foundation.
|
|
|
|
Mitsuba is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#if !defined(__IRAWAN_H)
|
|
#define __IRAWAN_H
|
|
|
|
#include <boost/spirit/include/qi.hpp>
|
|
#include <boost/spirit/include/phoenix_core.hpp>
|
|
#include <boost/spirit/include/phoenix_bind.hpp>
|
|
#include <boost/spirit/include/phoenix_operator.hpp>
|
|
#include <boost/spirit/include/phoenix_stl.hpp>
|
|
#include <boost/spirit/home/phoenix/bind/bind_member_variable.hpp>
|
|
#include <boost/spirit/home/phoenix/bind/bind_member_function.hpp>
|
|
#include <boost/spirit/home/phoenix/statement/if.hpp>
|
|
|
|
MTS_NAMESPACE_BEGIN
|
|
|
|
namespace spirit = boost::spirit;
|
|
namespace qi = boost::spirit::qi;
|
|
namespace ph = boost::phoenix;
|
|
|
|
/// Data structure describing the properties of a single yarn
|
|
struct Yarn {
|
|
enum EYarnType {
|
|
EWarp = 0,
|
|
EWeft = 1
|
|
};
|
|
|
|
/// Type of yarn (warp or weft)
|
|
EYarnType type;
|
|
/// Fiber twist angle
|
|
Float psi;
|
|
// Maximum inclination angle
|
|
Float umax;
|
|
/// Spine curvature
|
|
Float kappa;
|
|
/// Width of segment rectangle
|
|
Float width;
|
|
/// Length of segment rectangle
|
|
Float length;
|
|
/*! u coordinate of the yarn segment center,
|
|
* assumes that the tile covers 0 <= u, v <= 1.
|
|
* (0, 0) is lower left corner of the weave pattern
|
|
*/
|
|
Float centerU;
|
|
/// v coordinate of the yarn segment center
|
|
Float centerV;
|
|
/// Diffuse color
|
|
Spectrum kd;
|
|
/// Specular color
|
|
Spectrum ks;
|
|
|
|
Yarn() : type(EWarp),
|
|
psi(0), umax(0), kappa(0), width(0), length(0),
|
|
centerU(0), centerV(0), kd(0.0f), ks(0.0f) { }
|
|
|
|
Yarn(Stream *stream) {
|
|
type = (EYarnType) stream->readInt();
|
|
psi = stream->readFloat();
|
|
umax = stream->readFloat();
|
|
kappa = stream->readFloat();
|
|
width = stream->readFloat();
|
|
length = stream->readFloat();
|
|
centerU = stream->readFloat();
|
|
centerV = stream->readFloat();
|
|
kd = Spectrum(stream);
|
|
ks = Spectrum(stream);
|
|
}
|
|
|
|
void serialize(Stream *stream) const {
|
|
stream->writeInt(type);
|
|
stream->writeFloat(psi);
|
|
stream->writeFloat(umax);
|
|
stream->writeFloat(kappa);
|
|
stream->writeFloat(width);
|
|
stream->writeFloat(length);
|
|
stream->writeFloat(centerU);
|
|
stream->writeFloat(centerV);
|
|
kd.serialize(stream);
|
|
ks.serialize(stream);
|
|
}
|
|
|
|
std::string toString() const {
|
|
std::ostringstream oss;
|
|
oss << "yarn {" << endl
|
|
<< " type = " << ((type == EWarp) ? "warp" : "weft") << "," << endl;
|
|
if (psi != 0)
|
|
oss << " /* Fiber twist angle */" << endl
|
|
<< " psi = " << psi * 180 / M_PI << "," << endl;
|
|
oss << " /* Maximum inclination angle */" << endl
|
|
<< " umax = " << umax * 180 / M_PI << "," << endl;
|
|
if (kappa != 0)
|
|
oss << " /* Spine curvature */" << endl
|
|
<< " kappa = " << kappa << "," << endl;
|
|
oss << " /* Width and length of the segment rectangle */" << endl
|
|
<< " width = " << width << "," << endl
|
|
<< " length = " << length << "," << endl
|
|
<< " /* Yarn segment center in tile space */" << endl
|
|
<< " centerU = " << centerU << "," << endl
|
|
<< " centerV = " << centerV << "," << endl
|
|
<< " /* Diffuse and specular color */" << endl;
|
|
Float r, g, b;
|
|
kd.toLinearRGB(r, g, b);
|
|
oss << " kd = {" << r << ", " << g << ", " << b << "}," << endl;
|
|
ks.toLinearRGB(r, g, b);
|
|
oss << " ks = {" << r << ", " << g << ", " << b << "}," << endl
|
|
<< "}";
|
|
return oss.str();
|
|
}
|
|
};
|
|
|
|
struct WeavePattern {
|
|
/// Name of the weave pattern
|
|
std::string name;
|
|
/// Uniform scattering parameter
|
|
Float alpha;
|
|
/// Forward scattering parameter
|
|
Float beta;
|
|
/// Filament smoothing
|
|
Float ss;
|
|
/// Highlight width
|
|
Float hWidth;
|
|
/// Combined area taken up by the warp & weft
|
|
Float warpArea, weftArea;
|
|
|
|
/// Size of the weave pattern
|
|
uint32_t tileWidth, tileHeight;
|
|
|
|
/* Noise-related parameters */
|
|
Float dWarpUmaxOverDWarp;
|
|
Float dWarpUmaxOverDWeft;
|
|
Float dWeftUmaxOverDWarp;
|
|
Float dWeftUmaxOverDWeft;
|
|
Float fineness, period;
|
|
|
|
/// Detailed weave pattern
|
|
std::vector<uint32_t> pattern;
|
|
|
|
/// List of all yarns referenced in \c pattern
|
|
std::vector<Yarn> yarns;
|
|
|
|
inline WeavePattern() : name(""),
|
|
alpha(0), beta(0), ss(0), hWidth(0),
|
|
warpArea(0), weftArea(0), tileWidth(0), tileHeight(0),
|
|
dWarpUmaxOverDWarp(0), dWarpUmaxOverDWeft(0),
|
|
dWeftUmaxOverDWarp(0), dWeftUmaxOverDWeft(0),
|
|
fineness(0), period(0) { }
|
|
|
|
WeavePattern(Stream *stream) {
|
|
name = stream->readString();
|
|
alpha = stream->readFloat();
|
|
beta = stream->readFloat();
|
|
ss = stream->readFloat();
|
|
hWidth = stream->readFloat();
|
|
warpArea = stream->readFloat();
|
|
weftArea = stream->readFloat();
|
|
tileWidth = stream->readUInt();
|
|
tileHeight = stream->readUInt();
|
|
dWarpUmaxOverDWarp = stream->readFloat();
|
|
dWarpUmaxOverDWeft = stream->readFloat();
|
|
dWeftUmaxOverDWarp = stream->readFloat();
|
|
dWeftUmaxOverDWeft = stream->readFloat();
|
|
fineness = stream->readFloat();
|
|
period = stream->readFloat();
|
|
pattern.resize(tileWidth * tileHeight);
|
|
stream->readUIntArray(&pattern[0], pattern.size());
|
|
size_t yarnCount = stream->readSize();
|
|
yarns.resize(yarnCount);
|
|
for (size_t i=0; i<yarnCount; ++i)
|
|
yarns[i] = Yarn(stream);
|
|
}
|
|
|
|
void serialize(Stream *stream) const {
|
|
stream->writeString(name);
|
|
stream->writeFloat(alpha);
|
|
stream->writeFloat(beta);
|
|
stream->writeFloat(ss);
|
|
stream->writeFloat(hWidth);
|
|
stream->writeFloat(warpArea);
|
|
stream->writeFloat(weftArea);
|
|
stream->writeUInt(tileWidth);
|
|
stream->writeUInt(tileHeight);
|
|
stream->writeFloat(dWarpUmaxOverDWarp);
|
|
stream->writeFloat(dWarpUmaxOverDWeft);
|
|
stream->writeFloat(dWeftUmaxOverDWarp);
|
|
stream->writeFloat(dWeftUmaxOverDWeft);
|
|
stream->writeFloat(fineness);
|
|
stream->writeFloat(period);
|
|
stream->writeUIntArray(&pattern[0], pattern.size());
|
|
stream->writeSize(yarns.size());
|
|
for (size_t i=0; i<yarns.size(); ++i)
|
|
yarns[i].serialize(stream);
|
|
}
|
|
|
|
std::string toString() const {
|
|
std::ostringstream oss;
|
|
oss << "weave {" << endl
|
|
<< " name = \"" << name << "\"," << endl << endl
|
|
<< " /* Tile size of the weave pattern */" << endl
|
|
<< " tileWidth = " << tileWidth << "," << endl
|
|
<< " tileHeight = " << tileHeight << "," << endl << endl
|
|
<< " /* Uniform and forward scattering parameters */" << endl
|
|
<< " alpha = " << alpha << "," << endl
|
|
<< " beta = " << beta << "," << endl << endl
|
|
<< " /* Filament smoothing */" << endl
|
|
<< " ss = " << ss << "," << endl << endl
|
|
<< " /* Highlight width */" << endl
|
|
<< " hWidth = " << hWidth << "," << endl << endl
|
|
<< " /* Combined warp/weft size */" << endl
|
|
<< " warpArea = " << warpArea << "," << endl
|
|
<< " weftArea = " << weftArea << "," << endl << endl
|
|
<< " /* Noise-related parameters */" << endl;
|
|
if (dWarpUmaxOverDWarp != 0)
|
|
oss << " dWarpUmaxOverDWarp = " << dWarpUmaxOverDWarp * 180 / M_PI << "," << endl;
|
|
if (dWeftUmaxOverDWeft != 0)
|
|
oss << " dWarpUmaxOverDWeft = " << dWarpUmaxOverDWeft * 180 / M_PI << "," << endl;
|
|
if (dWarpUmaxOverDWarp != 0)
|
|
oss << " dWeftUmaxOverDWarp = " << dWeftUmaxOverDWarp * 180 / M_PI << "," << endl;
|
|
if (dWeftUmaxOverDWeft != 0)
|
|
oss << " dWeftUmaxOverDWeft = " << dWeftUmaxOverDWeft * 180 / M_PI << "," << endl;
|
|
if (fineness != 0)
|
|
oss << " fineness = " << fineness << "," << endl;
|
|
if (period != 0)
|
|
oss << " period = " << period << "," << endl;
|
|
oss << endl
|
|
<< " /* Weave pattern description */" << endl
|
|
<< " pattern {" << endl
|
|
<< " ";
|
|
for (size_t i=0; i<pattern.size(); ++i) {
|
|
oss << (int) pattern[i];
|
|
if (i+1<pattern.size())
|
|
oss << ", ";
|
|
}
|
|
oss << endl
|
|
<< " }," << endl
|
|
<< endl
|
|
<< " /* Listing of all used yarns */" << endl;
|
|
for (size_t i=0; i<yarns.size(); ++i) {
|
|
oss << " " << indent(yarns[i].toString());
|
|
if (i+1<yarns.size())
|
|
oss << "," << endl;
|
|
oss << endl;
|
|
}
|
|
|
|
oss << "}";
|
|
return oss.str();
|
|
}
|
|
};
|
|
|
|
template <typename Iterator> struct SkipGrammar : qi::grammar<Iterator> {
|
|
SkipGrammar () : SkipGrammar::base_type(start) {
|
|
using qi::char_;
|
|
using qi::space;
|
|
using qi::eol;
|
|
start = space | ("/*" >> *(char_ - "*/") >> "*/");
|
|
}
|
|
qi::rule<Iterator> start;
|
|
};
|
|
|
|
template <typename Iterator> struct YarnGrammar : qi::grammar<Iterator, Yarn(), SkipGrammar<Iterator> > {
|
|
YarnGrammar(const Properties &props)
|
|
: YarnGrammar::base_type(start), props(props) {
|
|
using namespace qi::labels;
|
|
using qi::float_;
|
|
using qi::char_;
|
|
using qi::lit;
|
|
using qi::_val;
|
|
|
|
type = (qi::string("warp") | qi::string("weft"))
|
|
[ ph::if_else(_1 == "warp", _val = Yarn::EWarp, _val = Yarn::EWeft ) ];
|
|
|
|
identifier = qi::lexeme[ lit('$') >> (qi::alpha | char_('_'))
|
|
>> *(qi::alnum | char_('_')) ];
|
|
|
|
spec = ((lit("{") >> float_ >> lit(",") >> float_ >> lit(",") >> float_ >> lit("}"))
|
|
[ ph::bind(&Spectrum::fromLinearRGB, _val, _1, _2, _3) ])
|
|
| (identifier [ _val = ph::bind(&Properties::getSpectrum, ph::ref(props), _1)]);
|
|
|
|
flt = (float_ [ _val = _1 ])
|
|
| (identifier [ _val = ph::bind(&Properties::getFloat, ph::ref(props), _1)]);
|
|
|
|
start = lit("yarn")
|
|
>> lit("{")
|
|
>> (
|
|
(lit("type") >> lit("=") >> type [ ph::bind(&Yarn::type, _val) = _1 ])
|
|
| (lit("psi") >> lit("=") >> flt [ ph::bind(&Yarn::psi, _val) = _1 * M_PI / 180 ])
|
|
| (lit("umax") >> lit("=") >> flt [ ph::bind(&Yarn::umax, _val) = _1 * M_PI / 180 ])
|
|
| (lit("kappa") >> lit("=") >> flt [ ph::bind(&Yarn::kappa, _val) = _1 ])
|
|
| (lit("width") >> lit("=") >> flt [ ph::bind(&Yarn::width, _val) = _1 ])
|
|
| (lit("length") >> lit("=") >> flt [ ph::bind(&Yarn::length, _val) = _1 ])
|
|
| (lit("centerU") >> lit("=") >> flt [ ph::bind(&Yarn::centerU, _val) = _1 ])
|
|
| (lit("centerV") >> lit("=") >> flt [ ph::bind(&Yarn::centerV, _val) = _1 ])
|
|
| (lit("kd") >> lit("=") >> spec [ ph::bind(&Yarn::kd, _val) = _1 ])
|
|
| (lit("ks") >> lit("=") >> spec [ ph::bind(&Yarn::ks, _val) = _1 ])
|
|
) % ','
|
|
>> lit("}");
|
|
}
|
|
|
|
qi::rule<Iterator, Yarn::EYarnType(), SkipGrammar<Iterator> > type;
|
|
qi::rule<Iterator, Yarn(), SkipGrammar<Iterator> > start;
|
|
qi::rule<Iterator, Spectrum(), SkipGrammar<Iterator> > spec;
|
|
qi::rule<Iterator, float(), SkipGrammar<Iterator> > flt;
|
|
qi::rule<Iterator, std::string()> identifier;
|
|
const Properties &props;
|
|
};
|
|
|
|
template <typename Iterator> struct WeavePatternGrammar : qi::grammar<Iterator, WeavePattern(), SkipGrammar<Iterator> > {
|
|
WeavePatternGrammar(const Properties &props)
|
|
: WeavePatternGrammar::base_type(start), yarn(props), props(props) {
|
|
using namespace qi::labels;
|
|
using qi::float_;
|
|
using qi::uint_;
|
|
using qi::char_;
|
|
using qi::lit;
|
|
using qi::_val;
|
|
using ph::push_back;
|
|
|
|
pattern = lit("pattern") >> lit("{")
|
|
>> uint_ [ push_back(_val, _1) ] % ','
|
|
>> lit("}");
|
|
|
|
name = qi::lexeme [ lit("\"") >> *(char_ - "\"") >> lit("\"") ];
|
|
|
|
identifier = qi::lexeme[ lit('$') >> (qi::alpha | char_('_'))
|
|
>> *(qi::alnum | char_('_')) ];
|
|
|
|
flt = (float_ [ _val = _1 ])
|
|
| (identifier [ _val = ph::bind(&Properties::getFloat, ph::ref(props), _1)]);
|
|
|
|
start = lit("weave") >> lit("{") >> (
|
|
lit("name") >> lit("=") >> name [ ph::bind(&WeavePattern::name, _val) = _1 ]
|
|
| lit("tileWidth") >> lit("=") >> uint_ [ ph::bind(&WeavePattern::tileWidth, _val) = _1 ]
|
|
| lit("tileHeight") >> lit("=") >> uint_ [ ph::bind(&WeavePattern::tileHeight, _val) = _1 ]
|
|
| lit("ss") >> lit("=") >> flt [ ph::bind(&WeavePattern::ss, _val) = _1 ]
|
|
| lit("alpha") >> lit("=") >> flt [ ph::bind(&WeavePattern::alpha, _val) = _1 ]
|
|
| lit("beta") >> lit("=") >> flt [ ph::bind(&WeavePattern::beta, _val) = _1 ]
|
|
| lit("warpArea") >> lit("=") >> flt [ ph::bind(&WeavePattern::warpArea, _val) = _1 ]
|
|
| lit("weftArea") >> lit("=") >> flt [ ph::bind(&WeavePattern::weftArea, _val) = _1 ]
|
|
| lit("hWidth") >> lit("=") >> flt [ ph::bind(&WeavePattern::hWidth, _val) = _1 ]
|
|
| lit("dWarpUmaxOverDWarp") >> lit("=") >> flt [ ph::bind(&WeavePattern::dWarpUmaxOverDWarp, _val) = _1 * M_PI / 180 ]
|
|
| lit("dWarpUmaxOverDWeft") >> lit("=") >> flt [ ph::bind(&WeavePattern::dWarpUmaxOverDWeft, _val) = _1 * M_PI / 180 ]
|
|
| lit("dWeftUmaxOverDWarp") >> lit("=") >> flt [ ph::bind(&WeavePattern::dWeftUmaxOverDWarp, _val) = _1 * M_PI / 180 ]
|
|
| lit("dWeftUmaxOverDWeft") >> lit("=") >> flt [ ph::bind(&WeavePattern::dWeftUmaxOverDWeft, _val) = _1 * M_PI / 180 ]
|
|
| lit("fineness") >> lit("=") >> flt [ ph::bind(&WeavePattern::fineness, _val) = _1 ]
|
|
| lit("period") >> lit("=") >> flt [ ph::bind(&WeavePattern::period, _val) = _1 ]
|
|
| pattern [ ph::bind(&WeavePattern::pattern, _val) = _1 ]
|
|
| yarn [ push_back(ph::bind(&WeavePattern::yarns, _val), _1) ]
|
|
) % ','
|
|
>> lit("}") >> qi::eoi;
|
|
}
|
|
|
|
qi::rule<Iterator, WeavePattern(), SkipGrammar<Iterator> > start;
|
|
qi::rule<Iterator, std::vector<uint32_t>(), SkipGrammar<Iterator> > pattern;
|
|
qi::rule<Iterator, std::string(), SkipGrammar<Iterator> > name;
|
|
qi::rule<Iterator, float(), SkipGrammar<Iterator> > flt;
|
|
qi::rule<Iterator, std::string()> identifier;
|
|
YarnGrammar<Iterator> yarn;
|
|
const Properties &props;
|
|
};
|
|
|
|
|
|
MTS_NAMESPACE_END
|
|
|
|
#endif /* __IRAWAN_H */
|