三维向量类 vec3.h
#pragma once
#include <cmath>
#include <iostream>
// 三维向量类,用于表示单个像素的颜色
// 每个维度都为 double
class vec3 {
public:
double e[3];
vec3() : e{0, 0, 0} {}
vec3(double e0, double e1, double e2) : e{e0, e1, e2} {}
double x() const { return e[0]; }
double y() const { return e[1]; }
double z() const { return e[2]; }
vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); }
double operator[](int i) const { return e[i]; }
double& operator[](int i) { return e[i]; }
vec3& operator+=(const vec3& v)
{
e[0] += v.e[0];
e[1] += v.e[1];
e[2] += v.e[2];
return *this;
}
vec3& operator*=(double t)
{
e[0] *= t;
e[1] *= t;
e[2] *= t;
return *this;
}
vec3& operator/=(double t)
{
return *this *= 1 / t;
}
// 长度
double length() const
{
return std::sqrt(length_squared());
}
// 长度的平方
double length_squared() const
{
return e[0] * e[0] + e[1] * e[1] + e[2] * e[2];
}
};
using point3 = vec3;
// Vector3 utility Functions
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 t * v;
}
inline vec3 operator/(const vec3& v, double t)
{
return (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(const vec3& v)
{
return v / v.length();
}
射线类 ray.h
#pragma once
#include "vec3.h"
/*
* 射线被作为一个函数看待
* P(t) = A + tb
* P是沿3D直线的一个3D位置
* A是射线的起点
* b是射线的方向
* 参数t是一个实数(double) 对于不同的t的取值,代表着沿P(t)移动点
*/
// 射线类
class ray {
public:
ray() {}
ray(const point3& origin, const vec3& direction) : orig(origin), dir(direction)
{ }
const point3& origin() const { return orig; }
const vec3& direction() const { return dir; }
// 上文中的函数 P(t)
point3 at(double t) const
{
return orig + t * dir;
}
private:
point3 orig; // 起点
vec3 dir; // 方向
};
工具头文件 color.h
其中封装了将颜色写入到标准输出流的函数
#pragma once
#include "vec3.h"
#include <iostream>
using color = vec3;
// 将单个像素的颜色写入输出流中
void write_color(std::ostream& out, const color& pixel_color)
{
auto r = pixel_color.x();
auto g = pixel_color.y();
auto b = pixel_color.z();
// 将 [0,1] 范围内的值映射至 [0,255] 范围内(byte)
int rbyte = int(255.999 * r);
int gbyte = int(255.999 * g);
int bbyte = int(255.999 * b);
out << rbyte << ' ' << gbyte << ' ' << bbyte << '\n';
}
评论区