Ray Tracing in One Weekend Part2

#include <iostream>
#include<fstream>
#include<string>
#include "v3d.h"
#include "ray.h"
#include "color.h"
using namespace std;
// Type aliases for vec3
using point3 = vec3;   // 3D point
using color = vec3;    // RGB color

inline std::ostream& operator<<(std::ostream& out, const vec3& v) {
	return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2];
}

inline vec3 operator+(const vec3& u, const vec3& v) {
	return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1], u.e[2] + v.e[2]);
}

inline vec3 operator-(const vec3& u, const vec3& v) {
	return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1], u.e[2] - v.e[2]);
}

inline vec3 operator*(const vec3& u, const vec3& v) {
	return vec3(u.e[0] * v.e[0], u.e[1] * v.e[1], u.e[2] * v.e[2]);
}

inline vec3 operator*(double t, const vec3& v) {
	return vec3(t * v.e[0], t * v.e[1], t * v.e[2]);
}

inline vec3 operator*(const vec3& v, double t) {
	return vec3(t * v.e[0], t * v.e[1], t * v.e[2]);
}

inline vec3 operator/(vec3 v, double t) {
	return vec3((1 / t) * v.e[0], (1 / t) * v.e[1], (1 / t) * v.e[2]);
	//(1 / t) * v;
}

inline double dot(const vec3& u, const vec3& v) {
	return u.e[0] * v.e[0]
		+ u.e[1] * v.e[1]
		+ u.e[2] * v.e[2];
}

inline vec3 cross(const vec3& u, const vec3& v) {
	return vec3(u.e[1] * v.e[2] - u.e[2] * v.e[1],
		u.e[2] * v.e[0] - u.e[0] * v.e[2],
		u.e[0] * v.e[1] - u.e[1] * v.e[0]);
}

inline vec3 unit_vector(vec3 v) {
	return vec3(v.e[0] / v.length(), v.e[1] / v.length(), v.e[2] / v.length());
}


bool hit_sphere(const point3& center, double radius, const ray& r) {
	vec3 oc = r.origin() - center;
	auto a = dot(r.direction(), r.direction());//t2b⋅b+2tb⋅(A−C)+(A−C)⋅(A−C)−r2=0 函数关于t, P(t)=A+tb
	auto b = 2.0 * dot(oc, r.direction());
	auto c = dot(oc, oc) - radius * radius;
	auto discriminant = b * b - 4 * a * c;
	return (discriminant > 0);
}

color ray_color(const ray& r) {
	if (hit_sphere(point3(0, 0, -1), 0.5, r))//如果打中了球,在球的范围内,就变成红色
		return color(1, 0, 0);
	vec3 unit_direction = unit_vector(r.direction());
	//显示蓝色背景
	auto t = 0.5 * (unit_direction.y() + 1.0);
	return (1.0 - t) * color(1.0, 1.0, 1.0) + t * color(0.5, 0.7, 1.0);
}

int main()
{
	// Image
	const auto aspect_ratio = 16.0 / 9.0;
	const int image_width = 400;
	const int image_height = static_cast<int>(image_width / aspect_ratio);

	// Camera

	auto viewport_height = 2.0;
	auto viewport_width = aspect_ratio * viewport_height;
	auto focal_length = 1.0;

	auto origin = point3(0, 0, 0);
	auto horizontal = vec3(viewport_width, 0, 0);
	auto vertical = vec3(0, viewport_height, 0);
	auto lower_left_corner = origin - horizontal / 2 - vertical / 2 - vec3(0, 0, focal_length);

	// Render
	ofstream file("graph1-1.ppm");
	file << "P3\n" << image_width << ' ' << image_height << "\n255\n";

	for (int j = image_height - 1; j >= 0; --j) {
		std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush;
		for (int i = 0; i < image_width; ++i) {
			auto u = double(i) / (image_width - 1);
			auto v = double(j) / (image_height - 1);
			auto add = lower_left_corner + u * horizontal + v * vertical - origin;
			ray r(origin, add);
			color pixel_color = ray_color(r);
			write_color(file, pixel_color);
		}
	}

	std::cerr << "\nDone.\n";
}

更新:问题已解决,没有理解endif的意思,在endif后面的内容都会不进行编译 

出现了一点小问题,inline函数需要放到主程序而不是头文件才能正常调用,否则会出现双重定义的bug,暂时还没有解决

 

inline 函数:
关键字inline 必须与函数定义体放在一起才能使函数成为内联,即不能先定义后写具体内容

最好把inline函数的定义放到头文件中,在每个调用该inline函数的文件中包含该头文件。这种方法保证对每个inline函数只有一个定义,否则可能会报错多次定义

 

posted @ 2022-07-03 15:54  LOFU  阅读(18)  评论(0编辑  收藏  举报