diff --git a/src/SConscript b/src/SConscript index e4a52eb..370bd02 100644 --- a/src/SConscript +++ b/src/SConscript @@ -20,6 +20,7 @@ files = [ 'basics.cc', 'camera.cc', 'light.cc', + 'log.cc', 'material.cc', 'object.cc', 'objectBox.cc', diff --git a/src/charles.cc b/src/charles.cc index 5c26414..17a7ba4 100644 --- a/src/charles.cc +++ b/src/charles.cc @@ -9,6 +9,7 @@ #include #include "basics.h" +#include "log.hh" #include "light.h" #include "material.h" #include "object_sphere.h" @@ -17,6 +18,9 @@ #include "scene.h" #include "writer_png.h" +#define LOG_NAME "ROOT" +#include "logModule.hh" + int verbosity = 0; @@ -24,7 +28,8 @@ int verbosity = 0; static void usage(const char *progname) { - fprintf(stderr, "Usage: %s [-hv] [-o ] \n", progname); + fprintf(stderr, "Usage: %s [-hv] [-l ] [-L ] [-o ] \n", + progname); } @@ -32,6 +37,8 @@ int main(int argc, const char *argv[]) { + using namespace charles::log; + Scene scene; scene.get_ambient().set_intensity(1.0); @@ -66,24 +73,42 @@ main(int argc, PointLight *l1 = new PointLight(Vector3(6.0, -4.0, 2), Color::White, 1.0); scene.add_light(l1); + std::string logFilename; + unsigned int logLevel = 0; + std::string outfile, infile; int opt; - while ((opt = getopt(argc, (char *const *)argv, "ho:v")) != -1) { + while ((opt = getopt(argc, (char *const *)argv, "hl:L:o:v:")) != -1) { switch (opt) { case 'h': usage(argv[0]); + exit(0); + break; + case 'l': + logFilename = optarg; + break; + case 'L': + logLevel = std::stoul(optarg); break; case 'o': outfile = optarg; break; case 'v': - ++verbosity; break; } } + /* Set up logging */ + if (logLevel > 0) { + if (logFilename.empty()) { + logFilename = "charles.log"; + } + Log::Init(logFilename, logLevel); + } + if (optind >= argc) { + LOG_ERROR << "Input file required."; fprintf(stderr, "Input file required.\n"); usage(argv[0]); return -1; @@ -102,11 +127,16 @@ main(int argc, } /* Call tracer. */ + LOG_INFO << "Beginning render"; scene.render(); /* Write rendered scene to PNG file. */ PNGWriter writer; scene.write(writer, outfile); + if (logLevel > 0) { + Log::Close(); + } + return 0; } diff --git a/src/log.cc b/src/log.cc new file mode 100644 index 0000000..91ce299 --- /dev/null +++ b/src/log.cc @@ -0,0 +1,119 @@ +/* log.cc + * vim: set tw=80: + * Eryn Wells + */ + +#include "log.hh" + + +namespace charles { +namespace log { + +/** Useful predefined levels. */ +namespace level { + const unsigned int Error = 10; + const unsigned int Warning = 20; + const unsigned int Info = 30; + const unsigned int Debug = 40; + const unsigned int Trace = 50; +}; + + +unsigned int Log::sLevel = 0; +std::ostream* Log::sOutput = nullptr; +Log::LoggerMap Log::sLoggers; + + +/* static */ void +Log::Init(const std::string& filename, + unsigned int level) +{ + assert(sOutput == nullptr); + sOutput = new std::ofstream(filename); + sLevel = level; + + Log("ROOT", 1) << "Opening log file " << filename; + Log("ROOT", 1) << "Log level set to " << sLevel; +} + + +/* static */ void +Log::Close() +{ + assert(sOutput != nullptr); + delete sOutput; + sOutput = nullptr; +} + + +/** + * Construct a Log object. + * + * @param [in] name The name of the log stream. If this name hasn't been + * seen before, a new one will be created for you. + * @param [in] level The level. If this is higher than the level of the log + * stream, nothing will be output. + */ +Log::Log(const std::string& name, + unsigned int level) + : mName(name), + mLevel(level), + mOutput(Log::GetLogger(name)) +{ + using namespace std::chrono; + + /* Write a log message leader: "