好了,终于到了可以看到图片的环节了。之前的类,你一定要实现好了。所有关于World类的报错,现在我们一个一个解决来了。

先看看World类的声明:

#pragma once
#ifndef __WORLD_HEADER__
#define __WORLD_HEADER__

#include "geometry.h"
#include "viewplane.h"
#include "../objects/primitive/sphere.h"
#include "../tracers/tracer.h"

class World {
public:
	World();
	World(const World& wr);
	~World();
	void build();//初始化数据
	void render();//渲染
	void add_object(Geometrics* obj);//添加几何对象
	void remove_object(Geometrics* obj);//删除几何对象
	integer get_object_size() const;//几何对象个数,这个在SingleSphere类中用到了哈
	ShadeRec hit_bare_bones_objects(const Ray& ray);
private:
	void open_window(const integer hres, const integer vres);//初始化视窗,有条件的可以用DirectX或者OpenGL显示,我这里用ppm文件显示
	void display_pixel(const integer row, const integer column, const RGBColor& color);//写入像素
	std::stringstream ss;//缓存
	std::vector<Geometrics*> objects;
	ViewPlane vp;//视窗类
	RGBColor backgrd_color;//背景色
	Tracer* tracer_ptr;//光线和几何对象的碰撞
};
#endif

  

类实现:

#include "pch.h"
#include "world.h"
#include "../tracers/singlesphere.h"

World::World():tracer_ptr(nullptr) {}

World::~World() {//写入到ppm文件
	std::ofstream fout;
	fout.open("test.ppm", std::ios::out);
	fout.write(ss.str().c_str(), ss.str().size());
	fout.close();
}

World::World(const World& wr)
	: vp(wr.vp), backgrd_color(wr.backgrd_color), tracer_ptr(wr.tracer_ptr) {
	objects.clear();
}

void World::build() {
	vp.set_hres(200);
	vp.set_vres(100);//200*100像素图片
	tracer_ptr = new SingleSphere(this);
	Geometrics* obj = new Sphere(0, 0.5);
	obj->set_color(RGBColor(1, 0, 0));//球体颜色是红色
	add_object(obj);
}

void World::render() {
	Ray ray;
	ldouble x, y;
	open_window(vp.hres, vp.vres);
	Point3 sp;
	ray.o = Point3(0, 0, 1);//光线源位置
	for (integer r = vp.vres - 1; r >= 0; r--)//render from left-corner to right-corner, 书上是错误的,必须这样渲染,不然图像是颠倒的
		for (integer c = 0; c < vp.hres; c++) {
			RGBColor color;
			x = vp.s * (c - 0.5 * vp.hres);
			y = vp.s * (r - 0.5 * vp.vres);
			ray.d = Point3(x, y, -1);//只需要改变光线的方向
			color = tracer_ptr->trace_ray(ray);
			display_pixel(r, c, color);
		}
}

void World::add_object(Geometrics* obj) {
	objects.push_back(obj);
}

void World::remove_object(Geometrics* obj) {
	for (auto it = objects.begin(); it != objects.end(); it++)
		if ((*it) == obj)
			objects.erase(it);
}

integer World::get_object_size() const {
	return objects.size();
}

ShadeRec World::hit_bare_bones_objects(const Ray& ray) {//这个就是经常出现在SingleSphere和MultiSphere类中的函数了
	ShadeRec sr(*this);
	ldouble t, tmin= std::numeric_limits<ldouble>::max();
	for (auto obj : objects)
		if (obj->hit(ray, t, sr) && t < tmin) {
			sr.hit_an_object = true;
			tmin = t;
			sr.color = obj->get_color();//保存碰撞后的颜色
		}
	return sr;
}

void World::open_window(const integer hres, const integer vres) {
	ss.clear();
	ss << "P3\n" << hres << " " << vres << "\n255\n";//ppm文件头
}

void World::display_pixel(const integer row, const integer column, const RGBColor& color) {
	RGBColor c = color;
	if (vp.g != 1.0)
		c = color.powc(vp.g);
	integer ir = (integer)(255.99 * c.r),
		ig = (integer)(255.99 * c.g),
		ib = (integer)(255.99 * c.b);
	ss << ir << " " << ig << " " << ib << "\n";//写入颜色值
}

 

好了,现在我们看下main函数的调用吧(以后main函数的调用都是一样的,所以不再重复了)

#include "../Common/RayTracingGroundUp/utilities/world.h"

int main() {
	World w;
	w.build();
	w.render();
	return 0;
}

 

得到的图像如下(因为我是mac电脑下开的win7虚拟机,所以mac自带读取ppm文件,如果你的win7不能打开,请用photoshop等作图软件打开就行了),终于成功了:

posted on 2020-03-31 04:19  dalgleish  阅读(181)  评论(0编辑  收藏  举报