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

View File

@@ -62,9 +62,9 @@ Canvas Camera::render(World world, uint32_t depth)
uint32_t x, y;
Canvas image = Canvas(this->horizontalSize, this->verticalSize);
#pragma omp parallel private(x, y) shared(image, stats)
#pragma omp parallel default(shared) private(x, y) shared(image, stats)
{
#pragma omp for
#pragma omp for schedule(dynamic, 5)
for (y = 0 ; y < this->verticalSize ; y++)
{
for (x = 0 ; x < this->horizontalSize ; x++)

52
source/include/csg.h Normal file
View File

@@ -0,0 +1,52 @@
/*
* DoRayMe - a quick and dirty Raytracer
* CSG header
*
* Created by Manoël Trapier
* Copyright (c) 2020 986-Studio.
*
*/
#ifndef DORAYME_CSG_H
#define DORAYME_CSG_H
#include <shape.h>
class CSG : public Shape
{
public:
enum OperationType
{
UNION,
DIFFERENCE,
INTERSECTION
};
protected:
Shape *left;
Shape *right;
OperationType operation;
BoundingBox bounds;
protected:
Intersect localIntersect(Ray r);
Tuple localNormalAt(Tuple point, Intersection *hit = nullptr);
BoundingBox getLocalBounds();
bool intersectionAllowed(bool leftHit, bool inLeft, bool inRight);
Intersect filterIntersections(Intersect &xs);
void updateBoundingBox();
BoundingBox getBounds();
public:
CSG(OperationType operation, Shape *left, Shape *right);
bool includes(Shape *b);
void updateTransform();
void dumpMe(FILE *fp);
};
#endif /* DORAYME_CSG_H */

View File

@@ -44,6 +44,8 @@ public:
void updateBoundingBox();
void updateTransform();
bool includes(Shape *b);
Group();
void dumpMe(FILE * fp);

View File

@@ -61,6 +61,8 @@ public:
BoundingBox getLocalBounds();
BoundingBox getBounds();
bool includes(Shape *b);
void updateBoundingBox();
void updateTransform();

View File

@@ -24,6 +24,7 @@ private:
uint64_t triangleCount; /* Total number of triangle */
uint64_t smoothTriangleCount; /* Total number of smooth triangle */
uint64_t objfileCount; /* Total number of OBJ File */
uint64_t csgCount; /* Total number of CSG */
uint64_t pixelCount; /* Total number of rendered pixels */
uint64_t rayCount; /* Total number of rays */
@@ -42,7 +43,7 @@ public:
RenderStats() : coneCount(0), cylinderCount(0), cubeCount(0), groupCount(0), lightCount(0), planeCount(0), sphereCount(0), triangleCount(0),
pixelCount(0), rayCount(0), lightRayEmitedCount(0), reflectionRayCount(0), refractedRayCount(0),
intersectCount(0), intersectionCount(0), reallocCallCount(0), mallocCallCount(0), smoothTriangleCount(0),
discardedIntersectCount(0), maxDepthAttained(UINT64_MAX), maxIntersectOnARay(0), objfileCount(0) {};
discardedIntersectCount(0), maxDepthAttained(UINT64_MAX), maxIntersectOnARay(0), objfileCount(0), csgCount(0) {};
#ifdef RENDER_STATS
void addCone();
void addCylinder();
@@ -51,6 +52,7 @@ public:
void addLight();
void addPlane();
void addSphere();
void addCsg();
void addOBJFile();
void addTriangle();
void addSmoothTriangle();
@@ -90,7 +92,8 @@ public:
static void addMalloc() {};
static void addRealloc() {};
static void setMaxIntersect(uint32_t count) {};
static void void RenderStats::addOBJFile() {};
static void addOBJFile() {};
static void addCsg() {};
#endif
};

View File

@@ -31,6 +31,7 @@ enum ShapeType
SHAPE_TRIANGLE,
SHAPE_OBJFILE,
SHAPE_SMOOTHTRIANGLE,
SHAPE_CSG,
};
/* Base class for all object that can be presented in the world */
@@ -58,7 +59,6 @@ public:
Shape(ShapeType = SHAPE_NONE);
virtual Intersect intersect(Ray r);
virtual Intersect intersectOOB(Ray r) { return this->intersect(r); };
Tuple normalAt(Tuple point, Intersection *hit = nullptr);
/* Bounding box points are always world value */
@@ -68,6 +68,8 @@ public:
virtual void updateTransform();
virtual bool includes(Shape *b) { return this == b; };
virtual void dumpMe(FILE *fp);
Tuple worldToObject(Tuple point) { return this->inverseTransform * point; };
@@ -75,9 +77,9 @@ public:
Tuple normalToWorld(Tuple normalVector);
void setTransform(Matrix transform);
void setMaterial(Material material) { this->material = material; };
Ray transform(Ray r) { return Ray(this->transformMatrix * r.origin, this->transformMatrix * r.direction); };
Ray invTransform(Ray r) { return Ray(this->inverseTransform * r.origin, this->inverseTransform * r.direction); };
void setMaterial(Material material) { this->material = material; this->materialSet = true; };
Ray transform(Ray r) { return Ray(this->transformMatrix * r.origin, this->transformMatrix * r.direction); };
Ray invTransform(Ray r) { return Ray(this->inverseTransform * r.origin, this->inverseTransform * r.direction); };
bool operator==(const Shape &b) const { return this->material == b.material &&
this->type == b.type &&

View File

@@ -133,6 +133,13 @@ void RenderStats::addDiscardedIntersect()
this->discardedIntersectCount++;
};
void RenderStats::addCsg()
{
#pragma omp atomic
this->csgCount++;
};
void RenderStats::setMaxDepth(uint32_t depth)
{
if (this->maxDepthAttained > depth)
@@ -162,6 +169,7 @@ void RenderStats::printStats()
printf("Triangles : %lld\n", this->triangleCount);
printf("Smooth Triangles : %lld\n", this->smoothTriangleCount);
printf("OBJ File : %lld\n", this->objfileCount);
printf("CSG : %lld\n", this->csgCount);
printf("==================================================\n");
printf("Pixel rendered : %lld\n", this->pixelCount);
printf("Ray casted : %lld\n", this->rayCount);

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)
{
}

View File

@@ -67,6 +67,35 @@ Intersect Group::intersect(Ray r)
return ret;
}
bool Group::includes(Shape *b)
{
if (this->objectCount > 0)
{
int i;
for (i = 0 ; i < this->objectCount ; i++)
{
if (this->objectList[i] == b)
{
return true;
}
}
}
/* We are force to do them all the time */
if (this->unboxableObjectCount > 0)
{
int i;
for(i = 0; i < this->unboxableObjectCount; i++)
{
if (this->unboxableObjectList[i] == b)
{
return true;
}
}
}
return false;
}
Intersect Group::localIntersect(Ray r)
{
return Intersect();

View File

@@ -130,6 +130,22 @@ Intersect OBJFile::intersect(Ray r)
return ret;
}
bool OBJFile::includes(Shape *b)
{
int i;
if (this->faceGroupCount > 0)
{
for (i = 0 ; i < this->faceGroupCount ; i++)
{
if (this->faceGroupList[i] == b)
{
return true;
}
}
}
return false;
}
Intersect OBJFile::localIntersect(Ray r)
{
return Intersect();