#include "Scene.h" #include #include #include #include #include "BMP.h" #include "shapes/Shape.h" #include "shapes/Sphere.h" using namespace std; Scene::Scene(map options, const char * filename) { m_width = 800; m_height = 600; m_multisample_level = 1; m_output_file_name = "fart.bmp"; m_vfov = 60.0; m_verbose = false; m_data = NULL; load(filename); /* after loading the scene file, apply any command-line render options */ for (map::iterator it = options.begin(); it != options.end(); it++) { if (it->first == "width") { m_width = atoi(it->second); } else if (it->first == "height") { m_height = atoi(it->second); } else if (it->first == "multisample") { m_multisample_level = atoi(it->second); } else if (it->first == "field-of-view") { m_vfov = atof(it->second); } else if (it->first == "output-file") { m_output_file_name = it->second; } else if (it->first == "verbose") { m_verbose = true; } } /* view plane distance is calculated based on the field of view */ m_view_plane_dist = (m_height / 2.0) / tan(M_PI * m_vfov / 360.0); } Scene::~Scene() { if (m_data != NULL) delete m_data; for (vector::iterator it = m_shapes.begin(); it != m_shapes.end(); it++) { delete (*it); } } void Scene::load(const char * filename) { /* TODO: parse file somehow */ Shape * shape = new Sphere(1.0); m_transform.translate(1.0, 5.0, 0.5); shape->setTransform(m_transform); m_shapes.push_back(shape); } void Scene::render() { if (m_verbose) { cout << " *** Beginning scene render ***" << endl; cout << "Parameters:" << endl; cout << "----------------------------------------" << endl; cout << " Width: " << m_width << endl; cout << " Height: " << m_height << endl; cout << " Multisample Level: " << m_multisample_level << endl; cout << " Vertical Field of View: " << m_vfov << endl; cout << "----------------------------------------" << endl; } m_data = new unsigned char[m_width * m_height * 3]; for (int i = 0; i < m_height; i++) { for (int j = 0; j < m_width; j++) { renderPixel(j, i, &m_data[3 * (m_width * i + j)]); } } if (m_verbose) { cout << " *** Ending scene render ***" << endl; cout << "Writing output file '" << m_output_file_name << '\'' << endl; } BMP outputImage(m_output_file_name.c_str(), m_width, m_height, m_data); } void Scene::renderPixel(int x, int y, unsigned char * pixel) { /* calculate the ray going from the camera through this pixel */ double rx = (x + 0.5) - (m_width / 2.0); double rz = (m_height / 2.0) - (y + 0.5); Ray ray(Vector(0, 0, 0), Vector(rx, m_view_plane_dist, rz)); /* loop through all shapes in the scene */ for (vector::iterator it = m_shapes.begin(); it != m_shapes.end(); it++) { /* transform the ray by the inverse of the shape's transform */ Transform inv = (*it)->getTransform().getInverse(); Ray transformed_ray = inv.transform_ray(ray); /* then intersect this inversely transformed ray with the shape */ Solver::Result intersections = (*it)->intersect(transformed_ray); if (intersections.numResults > 0) { Vector local_intersection_point = transformed_ray[intersections.results[0]]; Vector normal = (*it)->getNormalAt(local_intersection_point); double dot = -(normal % transformed_ray.getDirection()); cout << "got dot " << dot << endl; if (dot < 0.0) dot = 0.0; pixel[BMP_RED] = (unsigned char) (0xFF * dot); pixel[BMP_GREEN] = (unsigned char) (0xFF * dot); pixel[BMP_BLUE] = (unsigned char) (0xFF * dot); } else { pixel[BMP_RED] = 0x0; pixel[BMP_GREEN] = 0x0; pixel[BMP_BLUE] = 0x0; } } }