And CSG! \o/

Still working on a nice scene for it.
This commit is contained in:
Godzil
2020-03-06 19:00:31 +00:00
parent e57b5715e8
commit b5ee92c544
13 changed files with 591 additions and 9 deletions

133
source/shapes/csg.cpp Normal file
View File

@@ -0,0 +1,133 @@
/*
* 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;
}
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)
{
}