From 0e2f47a633f1ee5b0c32287801edd0075f65c939 Mon Sep 17 00:00:00 2001 From: InkSoul Date: Wed, 31 Jan 2024 21:12:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=8A=A0=E8=BD=BDobj?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E4=B8=89=E8=A7=92=E9=9D=A2=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tinyrender/CMakeLists.txt | 2 +- tinyrender/geometry.h | 73 ++++++++++++++++++++++++++++++++++++++ tinyrender/main.cpp | 46 +++++++++++++++--------- tinyrender/objLoader.cpp | 74 +++++++++++++++++++++++++++++++++++++++ tinyrender/objLoader.h | 28 +++++++++++++++ 5 files changed, 205 insertions(+), 18 deletions(-) create mode 100644 tinyrender/geometry.h create mode 100644 tinyrender/objLoader.cpp create mode 100644 tinyrender/objLoader.h diff --git a/tinyrender/CMakeLists.txt b/tinyrender/CMakeLists.txt index 1916678..8795a19 100644 --- a/tinyrender/CMakeLists.txt +++ b/tinyrender/CMakeLists.txt @@ -3,7 +3,7 @@ # # 将源代码添加到此项目的可执行文件。 -add_executable (tinyrender "main.cpp" "tgaimage.h" "tgaimage.cpp") +add_executable (tinyrender "main.cpp" "tgaimage.h" "tgaimage.cpp" "objLoader.h" "objLoader.cpp" "geometry.h") if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET tinyrender PROPERTY CXX_STANDARD 20) diff --git a/tinyrender/geometry.h b/tinyrender/geometry.h new file mode 100644 index 0000000..0abd449 --- /dev/null +++ b/tinyrender/geometry.h @@ -0,0 +1,73 @@ +#pragma once +#ifndef _GEOMETRY_H_ +#define _GEOMETRY_H_ + +#include +#include + + +template struct Vec2 +{ + union + { + struct + { + t u, v; + }; + struct + { + t x, y; + }; + t raw[2]; + }; + Vec2(): u(0),v(0){} + Vec2(t _u,t _v):u(_u),v(_v){} + inline Vec2 operator + (const Vec2& V) const { return Vec2(u + V.u, v + V.v); } + inline Vec2 operator - (const Vec2& V) const { return Vec2(u - V.u, v - V.v); } + inline Vec2 operator * (float f) const { return Vec2(u * f, v * f); } + template friend std::ostream& operator<< (std::ostream& s, Vec2& v); +}; + +template struct Vec3 +{ + union + { + struct + { + t x,y,z ; + }; + struct + { + t ivert, iuv, inorm; + }; + t raw[3]; + }; + Vec3() : x(0), y(0),z(0) {} + Vec3(t _x, t _y,t _z) :x(_x), y(_y),z(_z) {} + inline Vec3 operator ^ (const Vec3& v) const { return Vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } + inline Vec3 operator - (const Vec3& v) const { return Vec3(x - v.x, y - v.y,z-v.z); } + inline Vec3 operator + (const Vec3& v) const { return Vec3(x + v.x, y + v.y, z + v.z); } + inline Vec3 operator * (float f) const { return Vec3(x * f, y * f,z * f); } + inline t operator *(const Vec3& v) const { return x * v.x + y * v.y + z * v.z; } + float norm() const { return std::sqrt(x * x + y * y + z * z); } + Vec3& normalize(t l = 1) { *this = (*this) * (l / norm()); return *this; } + template friend std::ostream& operator<< (std::ostream& s, Vec3& v); +}; + +typedef Vec2 Vec2f; +typedef Vec2 Vec2i; +typedef Vec3 Vec3f; +typedef Vec3 Vec3i; + + +template std::ostream& operator<<(std::ostream& s, Vec2& v) { + s << "(" << v.x << ", " << v.y << ")\n"; + return s; +} + +template std::ostream& operator<<(std::ostream& s, Vec3& v) { + s << "(" << v.x << ", " << v.y << ","<< v.z << ")\n"; + return s; +} + +#endif // _GEOMETRY_H_ diff --git a/tinyrender/main.cpp b/tinyrender/main.cpp index e1aceb4..bb6537f 100644 --- a/tinyrender/main.cpp +++ b/tinyrender/main.cpp @@ -1,7 +1,11 @@ #include "tgaimage.h" +#include "objLoader.h" const TGAColor white = TGAColor(255, 255, 255, 255); const TGAColor red = TGAColor(255, 0, 0, 255); +objModel* model = NULL; +const int height = 800; +const int width = 800; void line(int x0, int y0, int x1, int y1, TGAImage& image, TGAColor color) { @@ -17,13 +21,11 @@ void line(int x0, int y0, int x1, int y1, TGAImage& image, TGAColor color) { std::swap(x0, x1); std::swap(y0, y1); } - int dx = x1 - x0; - int dy = y1 - y0; - int derror2 = std::abs(dy) * 2; - int error2 = 0; - int y = y0; + for (int x = x0; x <=x1; x++) { + float t = (x - x0) / (float)(x1 - x0); + int y = y0 * (1. - t) + y1 * t; if (steep) { image.set(y, x, color); @@ -32,28 +34,38 @@ void line(int x0, int y0, int x1, int y1, TGAImage& image, TGAColor color) { { image.set(x, y, color); } - error2 += derror2; - - if (error2 > dx) // 误差值,提供从当前位置到最佳直线的距离 - { - y += (y1 > y0 ? 1 : -1); - error2 -= dx * 2; - } } } int main(int argc, char** argv) { - TGAImage image(100, 100, TGAImage::RGB); - for (int i = 0; i < 1000000; i++) + if (2==argc) { - line(13, 20, 80, 40, image, white); - line(20, 13, 40, 80, image, red); - line(80, 40, 13, 20, image, red); + model = new objModel(argv[1]); + } + else + { + model = new objModel("obj/african_head.obj"); + } + TGAImage image(width, height, TGAImage::RGB); + for (int i = 0; i < model->nfaces(); i++) + { + std::vector face = model->face(i); + for (int j = 0; j < 3; j++) + { + Vec3f v0 = model->vert(face[j]); + Vec3f v1 = model->vert(face[(j + 1) % 3]); + int x0 = (v0.x + 1.) * width / 2.; + int y0 = (v0.y + 1.) * height / 2.; + int x1 = (v1.x + 1.) * width / 2.; + int y1 = (v1.y + 1.) * height / 2.; + line(x0, y0, x1, y1, image, white); + } } image.flip_vertically(); // i want to have the origin at the left bottom corner of the image image.write_tga_file("output.tga"); + delete model; return 0; } diff --git a/tinyrender/objLoader.cpp b/tinyrender/objLoader.cpp new file mode 100644 index 0000000..546ead6 --- /dev/null +++ b/tinyrender/objLoader.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include "objLoader.h" + +objModel::objModel(const char* filename) : verts_(), faces_() { + + std::cout << "model loading" << std::endl; + std::ifstream in; + in.open(filename, std::ifstream::in); + if (in.fail()) + { + std::cout << "fail"<> trash; + Vec3f v; + for (int i = 0; i < 3; i++) + { + iss >> v.raw[i]; + } + verts_.push_back(v); + } + else if(!line.compare(0,2,"f ")) + { + std::vector f; + int itrash, idx; + iss >> trash; + while (iss >> idx >> trash >> itrash >> trash >> itrash) + { + idx--; + f.push_back(idx); + } + faces_.push_back(f); + } + + } + std::cout << "vector size: " << verts_.size() << " \nface size: " << faces_.size() << std::endl; + +} + +objModel::~objModel() { + +} + +int objModel::nfaces() { + return (int)faces_.size(); + +} + +int objModel::nverts() { + return (int)verts_.size(); +} + +std::vector objModel::face(int idx) { + return faces_[idx]; +} + +Vec3f objModel::vert(int i) { + return verts_[i]; +} + + diff --git a/tinyrender/objLoader.h b/tinyrender/objLoader.h new file mode 100644 index 0000000..94a1ea2 --- /dev/null +++ b/tinyrender/objLoader.h @@ -0,0 +1,28 @@ +#pragma once + +#ifndef _OBJLOADER_H_ +#define _OBJLOADER_H_ + +#include +#include "geometry.h" + +class objModel +{ +public: + objModel(const char* filename); + ~objModel(); + int nverts(); + int nfaces(); + Vec3f vert(int i); + std::vector face(int idx); + + + +private: + std::vector verts_; + std::vector> faces_; +}; + + + +#endif \ No newline at end of file