Skip to content
Snippets Groups Projects
Group.cpp 1.98 KiB
#include "Group.h"

#include "../material/Material.h"
#include "../tools/Vec3.h"

namespace shapes {
Group::Group(const util::Transformation& transform, bool rebuildBB)
    : shapeList(std::vector<std::shared_ptr<Shape>>()),
      transform(transform),
      rebuildBB(rebuildBB) {
}
Group::Group(const util::Mat4& matrix, bool rebuildBB)
    : shapeList(std::vector<std::shared_ptr<Shape>>()),
      transform(util::Transformation(matrix)),
      rebuildBB(rebuildBB) {
}

std::optional<cam::Hit> Group::intersect(const cam::Ray& r) const {
	cam::Ray imagR(transform.fromWorld.transformPoint(r.x0),
	               transform.fromWorld.transformDir(r.d), r.tmin, r.tmax,
	               r.normalize);

	std::optional<cam::Hit> result = std::nullopt;

	for (std::shared_ptr<Shape> s : shapeList) {
		if (s->bounds().intersects(imagR)) {
			std::optional<cam::Hit> temp = s->intersect(imagR);
			if (temp) {
				if (imagR.in_range(temp->scalar())) {
					if (!result) {
						result = temp;
					} else if (result->scalar() > temp->scalar()) {
						result = temp;
					}
				}
			}
		}
	}

	if (result) {
		result = std::optional<cam::Hit>(
		    {transform.toWorld.transformPoint(result->point()),
		     transform.toWorldN.transformDir(result->normal()),
		     result->scalar(), result->material});
	}
	return result;
}
util::AxisAlignedBoundingBox Group::bounds() const {
	return boundingVolume;
}
void Group::setBounds(const util::AxisAlignedBoundingBox& bb) {
	boundingVolume = bb;
}
void Group::add(const Group& group) {
	add(std::make_shared<Group>(group));
}
void Group::add(const ShapeSingleGroup& group) {
	add(std::make_shared<ShapeSingleGroup>(group));
}
void Group::add(const std::shared_ptr<Shape>& shape) {
	shapeList.push_back(shape);
	if (rebuildBB) rebuildBoundingVolume();
}

void Group::rebuildBoundingVolume() {
	util::AxisAlignedBoundingBox bb = shapeList[0]->bounds();
	for (auto shape_bb : shapeList) {
		bb = bb + shape_bb->bounds();
	}
	boundingVolume = bb * transform.toWorld;
}

}  // namespace shapes