19 #include <nori/object.h>
20 #include <Eigen/Geometry>
22 #include <filesystem/resolver.h>
25 #if defined(PLATFORM_LINUX)
29 #if defined(PLATFORM_WINDOWS)
33 #if defined(PLATFORM_MACOS)
34 #include <sys/sysctl.h>
39 std::string indent(
const std::string &
string,
int amount) {
42 std::istringstream iss(
string);
43 std::ostringstream oss;
44 std::string spacer(amount,
' ');
45 bool firstLine =
true;
46 for (std::string line; std::getline(iss, line); ) {
57 bool endsWith(
const std::string &value,
const std::string &ending) {
58 if (ending.size() > value.size())
60 return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
63 std::string toLower(
const std::string &value) {
65 result.resize(value.size());
66 std::transform(value.begin(), value.end(), result.begin(), ::tolower);
70 bool toBool(
const std::string &str) {
71 std::string value = toLower(str);
74 else if (value ==
"true")
77 throw NoriException(
"Could not parse boolean value \"%s\"", str);
80 int toInt(
const std::string &str) {
81 char *end_ptr =
nullptr;
82 int result = (int) strtol(str.c_str(), &end_ptr, 10);
84 throw NoriException(
"Could not parse integer value \"%s\"", str);
88 unsigned int toUInt(
const std::string &str) {
89 char *end_ptr =
nullptr;
90 unsigned int result = (int) strtoul(str.c_str(), &end_ptr, 10);
92 throw NoriException(
"Could not parse integer value \"%s\"", str);
96 float toFloat(
const std::string &str) {
97 char *end_ptr =
nullptr;
98 float result = (float) strtof(str.c_str(), &end_ptr);
100 throw NoriException(
"Could not parse floating point value \"%s\"", str);
104 size_t vectorSize(
const std::string &str) {
105 std::vector<std::string> tokens = tokenize(str);
106 return tokens.size();
109 Eigen::Vector2f toVector2f(
const std::string &str) {
110 std::vector<std::string> tokens = tokenize(str);
111 if (tokens.size() != 2)
113 Eigen::Vector2f result;
114 for (
int i=0; i<2; ++i)
115 result[i] = toFloat(tokens[i]);
118 Eigen::Vector3f toVector3f(
const std::string &str) {
119 std::vector<std::string> tokens = tokenize(str);
120 if (tokens.size() != 3)
122 Eigen::Vector3f result;
123 for (
int i=0; i<3; ++i)
124 result[i] = toFloat(tokens[i]);
128 std::vector<std::string> tokenize(
const std::string &
string,
const std::string &delim,
bool includeEmpty) {
129 std::string::size_type lastPos = 0, pos =
string.find_first_of(delim, lastPos);
130 std::vector<std::string> tokens;
132 while (lastPos != std::string::npos) {
133 if (pos != lastPos || includeEmpty)
134 tokens.push_back(
string.substr(lastPos, pos - lastPos));
136 if (lastPos != std::string::npos) {
138 pos =
string.find_first_of(delim, lastPos);
145 std::string timeString(
double time,
bool precise) {
146 if (std::isnan(time) || std::isinf(time))
149 std::string suffix =
"ms";
151 time /= 1000; suffix =
"s";
153 time /= 60; suffix =
"m";
155 time /= 60; suffix =
"h";
157 time /= 12; suffix =
"d";
163 std::ostringstream os;
164 os << std::setprecision(precise ? 4 : 1)
165 << std::fixed << time << suffix;
170 std::string memString(
size_t size,
bool precise) {
171 double value = (double) size;
172 const char *suffixes[] = {
173 "B",
"KiB",
"MiB",
"GiB",
"TiB",
"PiB"
176 while (suffix < 5 && value > 1024.0f) {
177 value /= 1024.0f; ++suffix;
180 std::ostringstream os;
181 os << std::setprecision(suffix == 0 ? 0 : (precise ? 4 : 1))
182 << std::fixed << value <<
" " << suffixes[suffix];
187 filesystem::resolver *getFileResolver() {
188 static filesystem::resolver *resolver =
new filesystem::resolver();
195 for (
int i=0; i<3; ++i) {
196 float value = coeff(i);
198 if (value <= 0.0031308f)
199 result[i] = 12.92f * value;
201 result[i] = (1.0f + 0.055f)
202 * std::pow(value, 1.0f/2.4f) - 0.055f;
211 for (
int i=0; i<3; ++i) {
212 float value = coeff(i);
214 if (value <= 0.04045f)
215 result[i] = value * (1.0f / 12.92f);
217 result[i] = std::pow((value + 0.055f)
218 * (1.0f / 1.055f), 2.4f);
225 for (
int i=0; i<3; ++i) {
226 float value = coeff(i);
227 if (value < 0 || !std::isfinite(value))
234 return coeff(0) * 0.212671f + coeff(1) * 0.715160f + coeff(2) * 0.072169f;
238 : m_transform(trafo), m_inverse(trafo.inverse()) { }
241 std::ostringstream oss;
242 oss << m_transform.format(Eigen::IOFormat(4, 0,
", ",
";\n",
"",
"",
"[",
"]"));
247 return Transform(m_transform * t.m_transform,
248 t.m_inverse * m_inverse);
251 Vector3f sphericalDirection(
float theta,
float phi) {
252 float sinTheta, cosTheta, sinPhi, cosPhi;
254 sincosf(theta, &sinTheta, &cosTheta);
255 sincosf(phi, &sinPhi, &cosPhi);
267 std::atan2(v.y(), v.x())
270 result.y() += 2*M_PI;
275 if (std::abs(a.x()) > std::abs(a.y())) {
276 float invLen = 1.0f / std::sqrt(a.x() * a.x() + a.z() * a.z());
277 c =
Vector3f(a.z() * invLen, 0.0f, -a.x() * invLen);
279 float invLen = 1.0f / std::sqrt(a.y() * a.y() + a.z() * a.z());
280 c =
Vector3f(0.0f, a.z() * invLen, -a.y() * invLen);
285 float fresnel(
float cosThetaI,
float extIOR,
float intIOR) {
286 float etaI = extIOR, etaT = intIOR;
288 if (extIOR == intIOR)
293 if (cosThetaI < 0.0f) {
294 std::swap(etaI, etaT);
295 cosThetaI = -cosThetaI;
300 float eta = etaI / etaT,
301 sinThetaTSqr = eta*eta * (1-cosThetaI*cosThetaI);
303 if (sinThetaTSqr > 1.0f)
306 float cosThetaT = std::sqrt(1.0f - sinThetaTSqr);
308 float Rs = (etaI * cosThetaI - etaT * cosThetaT)
309 / (etaI * cosThetaI + etaT * cosThetaT);
310 float Rp = (etaT * cosThetaI - etaI * cosThetaT)
311 / (etaT * cosThetaI + etaI * cosThetaT);
313 return (Rs * Rs + Rp * Rp) / 2.0f;
Simple exception class, which stores a human-readable error description.
Represents a linear RGB color value.
bool isValid() const
Check if the color vector contains a NaN/Inf/negative value.
float getLuminance() const
Return the associated luminance.
Color3f toLinearRGB() const
Convert from sRGB to linear RGB.
Color3f toSRGB() const
Convert from linear RGB to sRGB.