完成加载obj输出三角面片
							parent
							
								
									8d51a6f1f3
								
							
						
					
					
						commit
						0e2f47a633
					
				| 
						 | 
					@ -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)
 | 
					if (CMAKE_VERSION VERSION_GREATER 3.12)
 | 
				
			||||||
  set_property(TARGET tinyrender PROPERTY CXX_STANDARD 20)
 | 
					  set_property(TARGET tinyrender PROPERTY CXX_STANDARD 20)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,73 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#ifndef _GEOMETRY_H_
 | 
				
			||||||
 | 
					#define _GEOMETRY_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					#include <ostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <class t> 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<t> operator + (const Vec2<t>& V) const { return Vec2<t>(u + V.u, v + V.v); }
 | 
				
			||||||
 | 
						inline Vec2<t> operator - (const Vec2<t>& V) const { return Vec2<t>(u - V.u, v - V.v); }
 | 
				
			||||||
 | 
						inline Vec2<t> operator * (float f) const { return Vec2<t>(u * f, v * f); }
 | 
				
			||||||
 | 
						template <class> friend std::ostream& operator<< (std::ostream& s, Vec2<t>& v);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <class t> 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<t> operator ^ (const Vec3<t>& v) const { return Vec3<t>(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
 | 
				
			||||||
 | 
						inline Vec3<t> operator - (const Vec3<t>& v) const { return Vec3<t>(x - v.x, y - v.y,z-v.z); }
 | 
				
			||||||
 | 
						inline Vec3<t> operator + (const Vec3<t>& v) const { return Vec3<t>(x + v.x, y + v.y, z + v.z); }
 | 
				
			||||||
 | 
						inline Vec3<t> operator * (float f) const { return Vec3<t>(x * f, y * f,z * f); }
 | 
				
			||||||
 | 
						inline t operator *(const Vec3<t>& 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<t>& normalize(t l = 1) { *this = (*this) * (l / norm()); return *this; }
 | 
				
			||||||
 | 
						template <class> friend std::ostream& operator<< (std::ostream& s, Vec3<t>& v);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef Vec2<float> Vec2f;
 | 
				
			||||||
 | 
					typedef Vec2<int> Vec2i;
 | 
				
			||||||
 | 
					typedef Vec3<float> Vec3f;
 | 
				
			||||||
 | 
					typedef Vec3<int> Vec3i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <class t> std::ostream& operator<<(std::ostream& s, Vec2<t>& v) {
 | 
				
			||||||
 | 
						s << "(" << v.x << ", " << v.y << ")\n";
 | 
				
			||||||
 | 
						return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <class t> std::ostream& operator<<(std::ostream& s, Vec3<t>& v) {
 | 
				
			||||||
 | 
						s << "(" << v.x << ", " << v.y << ","<< v.z << ")\n";
 | 
				
			||||||
 | 
						return s;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _GEOMETRY_H_
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,11 @@
 | 
				
			||||||
#include "tgaimage.h"
 | 
					#include "tgaimage.h"
 | 
				
			||||||
 | 
					#include "objLoader.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TGAColor white = TGAColor(255, 255, 255, 255);
 | 
					const TGAColor white = TGAColor(255, 255, 255, 255);
 | 
				
			||||||
const TGAColor red = TGAColor(255, 0, 0, 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) {
 | 
					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(x0, x1);
 | 
				
			||||||
		std::swap(y0, y1);
 | 
							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++)
 | 
						for (int x = x0; x <=x1; x++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							float t = (x - x0) / (float)(x1 - x0);
 | 
				
			||||||
 | 
							int y = y0 * (1. - t) + y1 * t;
 | 
				
			||||||
		if (steep) 
 | 
							if (steep) 
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			image.set(y, x, color);
 | 
								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);
 | 
								image.set(x, y, color);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		error2 += derror2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (error2 > dx) // 误差值,提供从当前位置到最佳直线的距离
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			y += (y1 > y0 ? 1 : -1);
 | 
					 | 
				
			||||||
			error2 -= dx * 2;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char** argv) {
 | 
					int main(int argc, char** argv) {
 | 
				
			||||||
	TGAImage image(100, 100, TGAImage::RGB);
 | 
						if (2==argc)
 | 
				
			||||||
	for (int i = 0; i < 1000000; i++)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		line(13, 20, 80, 40, image, white);
 | 
							model = new objModel(argv[1]);
 | 
				
			||||||
		line(20, 13, 40, 80, image, red);
 | 
						}
 | 
				
			||||||
		line(80, 40, 13, 20, image, red);
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							model = new	objModel("obj/african_head.obj");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						TGAImage image(width, height, TGAImage::RGB);
 | 
				
			||||||
 | 
						for (int i = 0; i < model->nfaces(); i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::vector<int> 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.flip_vertically(); // i want to have the origin at the left bottom corner of the image
 | 
				
			||||||
	image.write_tga_file("output.tga");
 | 
						image.write_tga_file("output.tga");
 | 
				
			||||||
 | 
						delete model;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,74 @@
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#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"<<std::endl;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						std::string line;
 | 
				
			||||||
 | 
						while (!in.eof())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::getline(in, line);
 | 
				
			||||||
 | 
							std::istringstream iss(line.c_str());
 | 
				
			||||||
 | 
							char trash;
 | 
				
			||||||
 | 
							if (!line.compare(0, 2, "v "))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								iss >> 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<int> 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<int> objModel::face(int idx) {
 | 
				
			||||||
 | 
						return faces_[idx];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Vec3f objModel::vert(int i) {
 | 
				
			||||||
 | 
						return verts_[i];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,28 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _OBJLOADER_H_
 | 
				
			||||||
 | 
					#define _OBJLOADER_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include "geometry.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class objModel
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						objModel(const char* filename);
 | 
				
			||||||
 | 
						~objModel();
 | 
				
			||||||
 | 
						int nverts();
 | 
				
			||||||
 | 
						int nfaces();
 | 
				
			||||||
 | 
						Vec3f vert(int i);
 | 
				
			||||||
 | 
						std::vector<int> face(int idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						std::vector<Vec3f> verts_;
 | 
				
			||||||
 | 
						std::vector<std::vector<int>> faces_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Loading…
	
		Reference in New Issue