diff --git a/src/main.cpp b/src/main.cpp index 4606092..e051776 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,32 @@ const int windowHeight = 800; const int windowWidth = 800; Model *model = NULL; +void line(Vec2i t0, Vec2i t1, TGAImage &image, TGAColor color) { + bool steep = false; + + // if the line is steep, we transpose the image. + if (abs(t0.x - t1.x) < abs(t0.y - t1.y)) { + swap(t0.x, t0.y); + swap(t1.x, t1.y); + steep = true; + } + // Make it left to right. + if (t0.x > t1.x) { + swap(t0.x, t1.x); + swap(t0.y, t1.y); + } + + for (int x = t0.x; x <= t1.x; x++) { + float t = (x - t0.x) / (float)(t1.x - t0.x); + int y = t0.y * (1.0 - t) + t1.y * t; + if (steep) { + image.set(y, x, color); // if transposed, de-transpose. + } else { + image.set(x, y, color); + } + } +} + Vec3f barycentric(Vec2i *pts, Vec2i P) { Vec3f u = Vec3f(pts[2].x - pts[0].x, pts[1].x - pts[0].x, pts[0].x - P.x) ^ Vec3f(pts[2].y - pts[0].y, pts[1].y - pts[0].y, pts[0].y - P.y); @@ -25,32 +51,7 @@ Vec3f barycentric(Vec2i *pts, Vec2i P) { return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z); } -void triangle(Vec2i t0, Vec2i t1, Vec2i t2, TGAImage &image, TGAColor color) { - if (t0.y == t1.y && t0.y == t2.y) - return; - if (t0.y > t1.y) - swap(t0, t1); - if (t0.y > t2.y) - swap(t0, t2); - if (t1.y > t2.y) - swap(t1, t2); - int total_height = t2.y - t0.y; - for (int i = 0; i < total_height; i++) { - bool second_half = i > t1.y - t0.y || t1.y == t0.y; - int segment_height = second_half ? t2.y - t1.y : t1.y - t0.y; - float alpha = (float)i / total_height; - float beta = - (float)(i - (second_half ? t1.y - t0.y : 0)) / segment_height; - Vec2i A = t0 + (t2 - t0) * alpha; - Vec2i B = second_half ? t1 + (t2 - t1) * beta : t0 + (t1 - t0) * beta; - if (A.x > B.x) - std::swap(A, B); - for (int j = A.x; j <= B.x; j++) { - image.set(j, t0.y + i, color); - } - } -} - +// Triangle function with binding box. void triangle(Vec2i *pts, TGAImage &image, TGAColor colour) { Vec2i boundingBoxMinimum(image.get_width() - 1, image.get_height() - 1); Vec2i boundingBoxMaximum(0, 0); @@ -77,10 +78,37 @@ void triangle(Vec2i *pts, TGAImage &image, TGAColor colour) { } } +// Triangle function via line sweeping. +void triangle(Vec2i t0, Vec2i t1, Vec2i t2, TGAImage &image, TGAColor color) { + if (t0.y == t1.y && t0.y == t2.y) + return; + if (t0.y > t1.y) + swap(t0, t1); + if (t0.y > t2.y) + swap(t0, t2); + if (t1.y > t2.y) + swap(t1, t2); + int total_height = t2.y - t0.y; + for (int i = 0; i < total_height; i++) { + bool second_half = i > t1.y - t0.y || t1.y == t0.y; + int segment_height = second_half ? t2.y - t1.y : t1.y - t0.y; + float alpha = (float)i / total_height; + float beta = + (float)(i - (second_half ? t1.y - t0.y : 0)) / segment_height; + Vec2i A = t0 + (t2 - t0) * alpha; + Vec2i B = second_half ? t1 + (t2 - t1) * beta : t0 + (t1 - t0) * beta; + if (A.x > B.x) + std::swap(A, B); + for (int j = A.x; j <= B.x; j++) { + image.set(j, t0.y + i, color); + } + } +} + + + int main(int argc, char **argv) { TGAImage image(windowWidth, windowHeight, TGAImage::RGB); - Vec2i pts[3] = {Vec2i(30, 30), Vec2i(300, 90), Vec2i(570, 480)}; - // triangle(pts, image, purple); // Model stuff. if (2 == argc) @@ -88,18 +116,24 @@ int main(int argc, char **argv) { else model = new Model("../obj/wolf_head.obj"); + + Vec3f lightDirection(0,0,-1); + for (int i = 0; i < model->nfaces(); i++) { vector face = model->face(i); Vec2i screenCoordinates[3]; + Vec3f worldCoordinates[3]; for (int j = 0; j < 3; j++) { - Vec3f worldCoordinates = model->vert(face[j]); - screenCoordinates[j] = - Vec2i((worldCoordinates.x + 1) * windowWidth / 2.0, - (worldCoordinates.y + 1.0) * windowHeight / 2.0); + Vec3f v = model->vert(face[j]); + screenCoordinates[j] = Vec2i((v.x + 1.0) * windowWidth / 2.0, (v.y + 1.0) * windowHeight / 2.0); + worldCoordinates[j] = v; } - triangle(screenCoordinates[0], screenCoordinates[1], + Vec3f n = (worldCoordinates[2] - worldCoordinates[0]) ^ (worldCoordinates[1] - worldCoordinates[0]); + n.normalize(); + float intensity = n * lightDirection; + if (intensity > 0) triangle(screenCoordinates[0], screenCoordinates[1], screenCoordinates[2], image, - TGAColor(rand() % 255, rand() % 255, rand() % 255, 255)); + TGAColor(intensity * 255, intensity * 255, intensity * 255, 255)); } image.flip_vertically(); image.write_tga_file("output.tga");