123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- /*
- * DoRayMe - a quick and dirty Raytracer
- * Constructive Solid Geometry (CSG) implementation
- *
- * Created by Manoël Trapier
- * Copyright (c) 2020 986-Studio.
- *
- */
- #include <tuple.h>
- #include <ray.h>
- #include <shape.h>
- #include <csg.h>
- #include <math_helper.h>
- CSG::CSG(OperationType operation, Shape *left, Shape *right) : Shape(SHAPE_CSG), operation(operation), left(left), right(right)
- {
- stats.addCsg();
- this->left->parent = this;
- this->right->parent = this;
- this->bounds | this->left->getBounds();
- this->bounds | this->right->getBounds();
- }
- Intersect CSG::localIntersect(Ray r)
- {
- int i;
- Intersect leftxs = this->left->intersect(r);
- Intersect rightxs = this->right->intersect(r);
- for(i = 0; i < rightxs.count(); i++)
- {
- leftxs.add(rightxs[i]);
- }
- Intersect ret = this->filterIntersections(leftxs);
- return ret;
- }
- Intersect CSG::intersect(Ray r)
- {
- return localIntersect(r);
- }
- Tuple CSG::localNormalAt(Tuple point, Intersection *hit)
- {
- return Vector(1, 0, 0);
- }
- BoundingBox CSG::getLocalBounds()
- {
- return this->bounds;
- }
- BoundingBox CSG::getBounds()
- {
- if (this->bounds.isEmpty()) { this->updateBoundingBox(); }
- return this->bounds;
- }
- void CSG::updateBoundingBox()
- {
- this->bounds.reset();
- this->bounds | this->left->getBounds();
- this->bounds | this->right->getBounds();
- }
- void CSG::updateTransform()
- {
- Shape::updateTransform();
- this->left->updateTransform();
- this->right->updateTransform();
- /* Once the full stack being notified of the changes, let's update the
- * bounding box
- */
- this->updateBoundingBox();
- }
- bool CSG::includes(Shape *b)
- {
- if (this->left->includes(b)) { return true; }
- if (this->right->includes(b)) { return true; }
- if (this == b) { return true; }
- return false;
- }
- bool CSG::intersectionAllowed(bool leftHit, bool inLeft, bool inRight)
- {
- switch(this->operation)
- {
- case CSG::UNION: return (leftHit && !inRight) || (!leftHit && !inLeft);
- case CSG::INTERSECTION: return (!leftHit && inLeft) || (leftHit && inRight);
- case CSG::DIFFERENCE: return (leftHit && !inRight) || (!leftHit && inLeft);
- }
- return false;
- }
- Intersect CSG::filterIntersections(Intersect &xs)
- {
- bool inl = false;
- bool inr = false;
- Intersect ret = Intersect();
- int i;
- for(i = 0; i < xs.count(); i++)
- {
- bool lhit = this->left->includes(xs[i].object);
- if (this->intersectionAllowed(lhit, inl, inr))
- {
- ret.add(xs[i]);
- }
- if (lhit)
- {
- inl = !inl;
- }
- else
- {
- inr = !inr;
- }
- }
- return ret;
- }
- void CSG::dumpMe(FILE *fp)
- {
- }
|