Another week of ray tracing learning seven objects

Posted by saint4 on Fri, 12 Jun 2020 12:12:41 +0200

See Monte Carlo ray tracing technology series Monte Carlo ray tracing technology

There are usually two blocks in the Cornell box. They rotate relative to the wall. First, let's make an axis aligned block primitive that contains six rectangles:

class box :public hitable {
	box(const vec3&p0, const vec3&p1, material *ptr);
	virtual bool hit(const ray&r, float t0, float t1, hit_record&rec)const;
	virtual bool bounding_box(float t0, float t1, aabb&box)const {
		box = aabb(pmin, pmax);
		return true;
	vec3 pmin, pmax;
	hitable *list_ptr;

box::box(const vec3&p0, const vec3&p1, material *ptr) {
	pmin = p0;
	pmax = p1;
	hitable **list = new hitable*[6];
	list[0] = new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr);
	list[1] = new flip_normals(new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr));
	list[2] = new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr);
	list[3] = new flip_normals(new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr));
	list[4] = new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr);
	list[5] = new flip_normals(new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr));
	list_ptr = new hitable_list(list, 6);//At the beginning, it was written as 0. As a result, there was no cube.

bool box::hit(const ray&r, float t0, float t1, hit_record&rec)const {
	return list_ptr->hit(r, t0, t1, rec);

Now we can add two blocks (but not rotate):

	list[i++] = new box(vec3(130, 0, 65), vec3(295, 165, 230), white);
	list[i++] = new box(vec3(265, 0, 295), vec3(430, 330, 460), white);

There is something wrong in the last section, which leads to some differences in the results. There are two areas that need to be changed:

	list[i++] = new flip_normals(new xz_rect(0, 555, 0, 555, 555, white));
	list[i++] = new xz_rect(0, 555, 0, 555, 0, white);


Each pixel is sampled 1000 times, and the following figure is obtained: (running for five minutes)

Now that we have the boxes, we need to rotate them a little bit to match the real Cornell box. In ray tracing, this is usually done in kind. A physical object is geometry that moves or rotates in some way. This is particularly easy in ray tracing because we don't move anything; instead, we move the light in the opposite direction. For example, consider a translate (often called a move). We can take the pink box at the origin and add up all its X components by 2, or (as we almost always do in ray tracing) keep the box, but in its hit object, subtract 2 from the x component of the ray origin.

Whether you think it's a move or a change in coordinates depends on you. The code used to move any underlying hitable is a translate instance.

#ifndef __CHANGE_H__
#define __CHANGE_H__
#include "hitable.h"
class translate :public hitable {
	translate(hitable*p,const vec3&displacement):ptr(p),offset(displacement){}
	virtual bool hit(const ray&r, float t_min, float t_max, hit_record&rec)const;
	virtual bool bounding_box(float t0, float t1, aabb&box)const;
	hitable *ptr;
	vec3 offset;
bool translate::hit(const ray&r, float t_min, float t_max, hit_record&rec)const {
	ray moved_r(r.origin() - offset, r.direction, r.time());
	if (ptr->hit(moved_r, t_min, t_max, rec)) {
		rec.p += offset;
		return true;
		return false;
bool translate::bounding_box(float t0, float t1, aabb&box)const {
	if (ptr->bounding_box(t0, t1, box)) {
		box = aabb(box.rmin() + offset, box.rmax() + offset);
		return true;
		return false;