// // Created by goksu on 4/6/19. // #include #include "rasterizer.hpp" #include #include #include rst::pos_buf_id rst::rasterizer::load_positions(const std::vector &positions) { auto id = get_next_id(); pos_buf.emplace(id, positions); return {id}; } rst::ind_buf_id rst::rasterizer::load_indices(const std::vector &indices) { auto id = get_next_id(); ind_buf.emplace(id, indices); return {id}; } // Bresenham's line drawing algorithm // Code taken from a stack overflow answer: https://stackoverflow.com/a/16405254 void rst::rasterizer::draw_line(Eigen::Vector3f begin, Eigen::Vector3f end) { auto x1 = begin.x(); auto y1 = begin.y(); auto x2 = end.x(); auto y2 = end.y(); Eigen::Vector3f line_color = {255, 255, 255}; int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i; dx=x2-x1; dy=y2-y1; dx1=fabs(dx); dy1=fabs(dy); px=2*dy1-dx1; py=2*dx1-dy1; if(dy1<=dx1) { if(dx>=0) { x=x1; y=y1; xe=x2; } else { x=x2; y=y2; xe=x1; } Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f); set_pixel(point,line_color); for(i=0;x0 && dy>0)) { y=y+1; } else { y=y-1; } px=px+2*(dy1-dx1); } // delay(0); Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f); set_pixel(point,line_color); } } else { if(dy>=0) { x=x1; y=y1; ye=y2; } else { x=x2; y=y2; ye=y1; } Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f); set_pixel(point,line_color); for(i=0;y0 && dy>0)) { x=x+1; } else { x=x-1; } py=py+2*(dx1-dy1); } // delay(0); Eigen::Vector3f point = Eigen::Vector3f(x, y, 1.0f); set_pixel(point,line_color); } } } auto to_vec4(const Eigen::Vector3f& v3, float w = 1.0f) { return Vector4f(v3.x(), v3.y(), v3.z(), w); } void rst::rasterizer::draw(rst::pos_buf_id pos_buffer, rst::ind_buf_id ind_buffer, rst::Primitive type) { if (type != rst::Primitive::Triangle) { throw std::runtime_error("Drawing primitives other than triangle is not implemented yet!"); } auto& buf = pos_buf[pos_buffer.pos_id]; auto& ind = ind_buf[ind_buffer.ind_id]; float f1 = (100 - 0.1) / 2.0; float f2 = (100 + 0.1) / 2.0; Eigen::Matrix4f mvp = projection * view * model; for (auto& i : ind) { Triangle t; Eigen::Vector4f v[] = { mvp * to_vec4(buf[i[0]], 1.0f), mvp * to_vec4(buf[i[1]], 1.0f), mvp * to_vec4(buf[i[2]], 1.0f) }; for (auto& vec : v) { vec /= vec.w(); } for (auto & vert : v) { vert.x() = 0.5*width*(vert.x()+1.0); vert.y() = 0.5*height*(vert.y()+1.0); vert.z() = vert.z() * f1 + f2; } for (int i = 0; i < 3; ++i) { t.setVertex(i, v[i].head<3>()); t.setVertex(i, v[i].head<3>()); t.setVertex(i, v[i].head<3>()); } t.setColor(0, 255.0, 0.0, 0.0); t.setColor(1, 0.0 ,255.0, 0.0); t.setColor(2, 0.0 , 0.0,255.0); rasterize_wireframe(t); } } void rst::rasterizer::rasterize_wireframe(const Triangle& t) { draw_line(t.c(), t.a()); draw_line(t.c(), t.b()); draw_line(t.b(), t.a()); } void rst::rasterizer::set_model(const Eigen::Matrix4f& m) { model = m; } void rst::rasterizer::set_view(const Eigen::Matrix4f& v) { view = v; } void rst::rasterizer::set_projection(const Eigen::Matrix4f& p) { projection = p; } void rst::rasterizer::clear(rst::Buffers buff) { if ((buff & rst::Buffers::Color) == rst::Buffers::Color) { std::fill(frame_buf.begin(), frame_buf.end(), Eigen::Vector3f{0, 0, 0}); } if ((buff & rst::Buffers::Depth) == rst::Buffers::Depth) { std::fill(depth_buf.begin(), depth_buf.end(), std::numeric_limits::infinity()); } } rst::rasterizer::rasterizer(int w, int h) : width(w), height(h) { frame_buf.resize(w * h); depth_buf.resize(w * h); } int rst::rasterizer::get_index(int x, int y) { return (height-y)*width + x; } void rst::rasterizer::set_pixel(const Eigen::Vector3f& point, const Eigen::Vector3f& color) { //old index: auto ind = point.y() + point.x() * width; if (point.x() < 0 || point.x() >= width || point.y() < 0 || point.y() >= height) return; auto ind = (height-1-point.y())*width + point.x(); frame_buf[ind] = color; }