/* 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 . */ #if !defined(__IRAWAN_H) #define __IRAWAN_H #include #include #include #include #include #include #include #include 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 pattern; /// List of all yarns referenced in \c pattern std::vector 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; iwriteString(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 struct SkipGrammar : qi::grammar { SkipGrammar () : SkipGrammar::base_type(start) { using qi::char_; using qi::space; using qi::eol; start = space | ("/*" >> *(char_ - "*/") >> "*/"); } qi::rule start; }; template struct YarnGrammar : qi::grammar > { 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 > type; qi::rule > start; qi::rule > spec; qi::rule > flt; qi::rule identifier; const Properties &props; }; template struct WeavePatternGrammar : qi::grammar > { 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 > start; qi::rule(), SkipGrammar > pattern; qi::rule > name; qi::rule > flt; qi::rule identifier; YarnGrammar yarn; const Properties &props; }; MTS_NAMESPACE_END #endif /* __IRAWAN_H */