From aede861fb31bf60ceebd50d830b531672c180636 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 22 Oct 2010 21:42:16 +0200 Subject: [PATCH] work on hair primitive --- SConstruct | 3 +- src/shapes/cylinder.cpp | 1 - src/shapes/hair.cpp | 207 +++++++++++++++++++++++++--------------- src/shapes/hair_old.cpp | 103 ++++++++++++++++++++ 4 files changed, 232 insertions(+), 82 deletions(-) create mode 100644 src/shapes/hair_old.cpp diff --git a/SConstruct b/SConstruct index 6211c66b..62d3c92c 100644 --- a/SConstruct +++ b/SConstruct @@ -511,7 +511,6 @@ plugins += env.SharedLibrary('plugins/roughglass', ['src/bsdfs/roughglass.cpp']) plugins += env.SharedLibrary('plugins/roughmetal', ['src/bsdfs/roughmetal.cpp']) plugins += env.SharedLibrary('plugins/composite', ['src/bsdfs/composite.cpp']) - # Phase functions plugins += env.SharedLibrary('plugins/isotropic', ['src/phase/isotropic.cpp']) plugins += env.SharedLibrary('plugins/hg', ['src/phase/hg.cpp']) @@ -524,7 +523,7 @@ plugins += env.SharedLibrary('plugins/ply', ['src/shapes/ply/ply.cpp', 'src/shap plugins += env.SharedLibrary('plugins/serialized', ['src/shapes/serialized.cpp']) plugins += env.SharedLibrary('plugins/sphere', ['src/shapes/sphere.cpp']) plugins += env.SharedLibrary('plugins/cylinder', ['src/shapes/cylinder.cpp']) -#plugins += env.SharedLibrary('plugins/hair', ['src/shapes/hair.cpp', 'src/shapes/miterseg.cpp']) +#plugins += env.SharedLibrary('plugins/hair', ['src/shapes/hair.cpp']) #plugins += env.SharedLibrary('plugins/group', ['src/shapes/group.cpp']) # Samplers diff --git a/src/shapes/cylinder.cpp b/src/shapes/cylinder.cpp index 07a1aa8a..b93ebc71 100644 --- a/src/shapes/cylinder.cpp +++ b/src/shapes/cylinder.cpp @@ -21,7 +21,6 @@ #include #include #include -#include MTS_NAMESPACE_BEGIN diff --git a/src/shapes/hair.cpp b/src/shapes/hair.cpp index b75137e7..426b6bcf 100644 --- a/src/shapes/hair.cpp +++ b/src/shapes/hair.cpp @@ -1,103 +1,152 @@ -#include +/* + This file is part of Mitsuba, a physically based rendering system. + + Copyright (c) 2007-2010 by Wenzel Jakob and others. + + 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 . +*/ #include #include -#include +#include +#include +#include +#include #include -#include "hair.h" -#include "miterseg.h" - MTS_NAMESPACE_BEGIN -Hair::Hair(const Properties &props) : Shape(props) { - std::string filename = props.getString("filename"); +class Hair : public Shape { +public: + Hair(const Properties &props) : Shape(props) { + fs::path path = Thread::getThread()->getFileResolver()->resolve( props.getString("filename")); - m_radius = (Float) props.getFloat("radius", 0.05f); - m_name = FileResolver::getInstance()->resolve(filename); + m_radius = (Float) props.getFloat("radius", 0.05f); - Log(EInfo, "Loading hair geometry from \"%s\" ..", m_name.c_str()); + Log(EInfo, "Loading hair geometry from \"%s\" ..", path.leaf().c_str()); - std::ifstream is(m_name.c_str()); - if (is.fail()) - Log(EError, "Could not open \"%s\"!", m_name.c_str()); + fs::ifstream is(path); + if (is.fail()) + Log(EError, "Could not open \"%s\"!", path.file_string().c_str()); - std::string line; - bool newFiber = true; - Point p; - while (is.good()) { - std::getline(is, line); - if (line.length() > 0 && line[0] == '#') - continue; - if (line.length() == 0) { - newFiber = true; - } else { - std::istringstream iss(line); - iss >> p.x >> p.y >> p.z; - if (!iss.fail()) { - m_vertices.push_back(p); - m_startFiber.push_back(newFiber); - newFiber = false; + std::string line; + bool newFiber = true; + Point p; + size_t segmentCount = 0; + + while (is.good()) { + std::getline(is, line); + if (line.length() > 0 && line[0] == '#') + continue; + if (line.length() == 0) { + newFiber = true; + } else { + std::istringstream iss(line); + iss >> p.x >> p.y >> p.z; + if (!iss.fail()) { + if (newFiber) + segmentCount++; + m_vertices.push_back(p); + m_startFiber.push_back(newFiber); + newFiber = false; + } } } + m_startFiber.push_back(true); + + for (size_t i=0; ireadFloat(); - size_t segmentCount = stream->readUInt(); - - m_vertices.reserve(segmentCount); - for (size_t i=0; ireadBool()); - - buildSegIndex(); -} - -void Hair::serialize(Stream *stream, InstanceManager *manager) const { - Shape::serialize(stream, manager); - - stream->writeFloat(m_radius); - size_t segmentCount = m_vertices.size(); - stream->writeUInt(segmentCount); - - for (size_t i=0; iwriteBool(m_startFiber[i]); -} - -Shape *Hair::getElement(int index) { - if ((size_t) index >= m_segIndex.size()) - return NULL; - - MiterHairSegment *segment = new MiterHairSegment(this, m_segIndex[index]); - segment->addChild("bsdf", m_bsdf); - segment->configure(); - return segment; -} + inline Vector secondMiterNormal(int iv) const { + if (!m_startFiber[iv+2]) + return normalize(tangent(iv) + tangent(iv+1)); + else + return tangent(); + } -void Hair::buildSegIndex() { - // Compute the index of the first vertex in each segment. - m_segIndex.clear(); - for (size_t i=0; i m_startFiber; + std::vector m_segIndex; + std::vector m_vertices; + AABB m_aabb; + Float m_radius; +}; MTS_IMPLEMENT_CLASS_S(Hair, false, Shape) -MTS_EXPORT_PLUGIN(Hair, "Hair geometry"); +MTS_EXPORT_PLUGIN(Hair, "Hair intersection primitive"); MTS_NAMESPACE_END diff --git a/src/shapes/hair_old.cpp b/src/shapes/hair_old.cpp new file mode 100644 index 00000000..b75137e7 --- /dev/null +++ b/src/shapes/hair_old.cpp @@ -0,0 +1,103 @@ +#include + +#include +#include +#include +#include + +#include "hair.h" +#include "miterseg.h" + +MTS_NAMESPACE_BEGIN + +Hair::Hair(const Properties &props) : Shape(props) { + std::string filename = props.getString("filename"); + props.getString("filename")); + m_radius = (Float) props.getFloat("radius", 0.05f); + m_name = FileResolver::getInstance()->resolve(filename); + + Log(EInfo, "Loading hair geometry from \"%s\" ..", m_name.c_str()); + + std::ifstream is(m_name.c_str()); + if (is.fail()) + Log(EError, "Could not open \"%s\"!", m_name.c_str()); + + std::string line; + bool newFiber = true; + Point p; + while (is.good()) { + std::getline(is, line); + if (line.length() > 0 && line[0] == '#') + continue; + if (line.length() == 0) { + newFiber = true; + } else { + std::istringstream iss(line); + iss >> p.x >> p.y >> p.z; + if (!iss.fail()) { + m_vertices.push_back(p); + m_startFiber.push_back(newFiber); + newFiber = false; + } + } + } + m_startFiber.push_back(true); + + buildSegIndex(); + + Log(EDebug, "Read %i hair vertices, %i segments,", m_vertices.size(), m_segIndex.size()); +} + +Hair::Hair(Stream *stream, InstanceManager *manager) : Shape(stream, manager) { + m_radius = stream->readFloat(); + size_t segmentCount = stream->readUInt(); + + m_vertices.reserve(segmentCount); + for (size_t i=0; ireadBool()); + + buildSegIndex(); +} + +void Hair::serialize(Stream *stream, InstanceManager *manager) const { + Shape::serialize(stream, manager); + + stream->writeFloat(m_radius); + size_t segmentCount = m_vertices.size(); + stream->writeUInt(segmentCount); + + for (size_t i=0; iwriteBool(m_startFiber[i]); +} + +Shape *Hair::getElement(int index) { + if ((size_t) index >= m_segIndex.size()) + return NULL; + + MiterHairSegment *segment = new MiterHairSegment(this, m_segIndex[index]); + segment->addChild("bsdf", m_bsdf); + segment->configure(); + return segment; +} + + +void Hair::buildSegIndex() { + // Compute the index of the first vertex in each segment. + m_segIndex.clear(); + for (size_t i=0; i