Fixed boolean objects to determine if rays start inside or outside the boolean; changed constructors to accept a list of shapes instead of just two shapes; changed parser to accept any number of top-level shapes inside of a boolean shape block; changed scenes/die.fart to reflect this change (a drastic simplification)
git-svn-id: svn://anubis/fart/trunk@215 7f9b0f55-74a9-4bce-be96-3c2cd072584d
This commit is contained in:
parent
f103b71ed6
commit
5590c533ce
2
.todo
2
.todo
@ -4,14 +4,12 @@ FART To-Do List
|
||||
High Priority:
|
||||
- Add distribution infrastructure
|
||||
- Multi-threading
|
||||
- Rework booleans to base them on regions instead of in/out for each side
|
||||
|
||||
Medium Priority:
|
||||
- Shape definitions / reusability
|
||||
- Scene file pre-parser to allow includes, macros, and comments
|
||||
- Vim syntax file
|
||||
- Add jitter parameter to lights to effect soft shadow edges
|
||||
- Allow >2 sub-shapes in boolean shape definitions in scene files
|
||||
|
||||
Low Priority:
|
||||
- Refraction
|
||||
|
@ -465,9 +465,8 @@ refptr<Shape> Scene::processSphere(refptr<Node> node)
|
||||
|
||||
refptr<Shape> Scene::processBool(refptr<Node> node)
|
||||
{
|
||||
refptr<Shape> shape1, shape2;
|
||||
vector< refptr<Shape> > shapes;
|
||||
refptr<Material> material;
|
||||
int shapes_seen = 0;
|
||||
|
||||
bool restore_transform = processTransforms(node);
|
||||
|
||||
@ -477,14 +476,9 @@ refptr<Shape> Scene::processBool(refptr<Node> node)
|
||||
{
|
||||
if ( (*it)->isShape() )
|
||||
{
|
||||
switch (shapes_seen)
|
||||
{
|
||||
case 0: shape1 = processShape(*it);
|
||||
break;
|
||||
case 1: shape2 = processShape(*it);
|
||||
break;
|
||||
}
|
||||
shapes_seen++;
|
||||
refptr<Shape> shape = processShape(*it);
|
||||
if ( ! shape.isNull() )
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
else if ( (*it)->isMaterial() )
|
||||
{
|
||||
@ -492,30 +486,20 @@ refptr<Shape> Scene::processBool(refptr<Node> node)
|
||||
}
|
||||
}
|
||||
|
||||
if (shapes_seen < 2 || shape1.isNull() || shape2.isNull())
|
||||
if (shapes.size() < 2)
|
||||
{
|
||||
if (shapes_seen < 2)
|
||||
cerr << __FILE__ << ": " << __LINE__
|
||||
<< ": error: only saw "
|
||||
<< shapes_seen
|
||||
<< " child shapes!"
|
||||
<< endl;
|
||||
if (shape1.isNull())
|
||||
cerr << __FILE__ << ": " << __LINE__
|
||||
<< ": error: shape1 is null!" << endl;
|
||||
if (shape2.isNull())
|
||||
cerr << __FILE__ << ": " << __LINE__
|
||||
<< ": error: shape2 is null!" << endl;
|
||||
cerr << "Error: boolean objects must have 2 or more sub-objects!"
|
||||
<< endl;
|
||||
exit(3);
|
||||
}
|
||||
|
||||
refptr<Shape> shape;
|
||||
if ( typeid(*node) == typeid(IntersectNode) )
|
||||
shape = new Intersect(shape1, shape2);
|
||||
shape = new Intersect(shapes);
|
||||
else if ( typeid(*node) == typeid(UnionNode) )
|
||||
shape = new Union(shape1, shape2);
|
||||
shape = new Union(shapes);
|
||||
else if ( typeid(*node) == typeid(SubtractNode) )
|
||||
shape = new Subtract(shape1, shape2);
|
||||
shape = new Subtract(shapes);
|
||||
else
|
||||
{
|
||||
cerr << __FILE__ << ": " << __LINE__
|
||||
|
@ -103,6 +103,18 @@ scene: SCENE LCURLY scene_items RCURLY {
|
||||
}
|
||||
;
|
||||
|
||||
bool_items: /* empty */
|
||||
| bool_item bool_items {
|
||||
$$ = new ItemsNode();
|
||||
$$->addChild($1);
|
||||
$$->addChildren($2);
|
||||
}
|
||||
;
|
||||
|
||||
bool_item: shape
|
||||
| shape_item
|
||||
;
|
||||
|
||||
box: BOX LCURLY box_items RCURLY {
|
||||
$$ = new BoxNode();
|
||||
$$->addChildren($3);
|
||||
@ -171,11 +183,9 @@ cyl_item: SIZE vector {
|
||||
| shape_item { $$ = $1; }
|
||||
;
|
||||
|
||||
intersect: INTERSECT LCURLY shape shape shape_items RCURLY {
|
||||
intersect: INTERSECT LCURLY bool_items RCURLY {
|
||||
$$ = new IntersectNode();
|
||||
$$->addChild($3);
|
||||
$$->addChild($4);
|
||||
$$->addChildren($5);
|
||||
$$->addChildren($3);
|
||||
}
|
||||
;
|
||||
|
||||
@ -368,11 +378,9 @@ sphere_item: radius { $$ = $1; }
|
||||
| shape_item { $$ = $1; }
|
||||
;
|
||||
|
||||
subtract: SUBTRACT LCURLY shape shape shape_items RCURLY {
|
||||
subtract: SUBTRACT LCURLY bool_items RCURLY {
|
||||
$$ = new SubtractNode();
|
||||
$$->addChild($3);
|
||||
$$->addChild($4);
|
||||
$$->addChildren($5);
|
||||
$$->addChildren($3);
|
||||
}
|
||||
;
|
||||
|
||||
@ -414,11 +422,9 @@ transform_block_item: transform_block { $$ = $1; }
|
||||
| shape { $$ = $1; }
|
||||
;
|
||||
|
||||
union: UNION LCURLY shape shape shape_items RCURLY {
|
||||
union: UNION LCURLY bool_items RCURLY {
|
||||
$$ = new UnionNode();
|
||||
$$->addChild($3);
|
||||
$$->addChild($4);
|
||||
$$->addChildren($5);
|
||||
$$->addChildren($3);
|
||||
}
|
||||
;
|
||||
|
||||
|
136
scenes/die.fart
136
scenes/die.fart
@ -19,115 +19,33 @@ scene
|
||||
|
||||
union
|
||||
{
|
||||
union {
|
||||
union {
|
||||
box { size <1, 0.8, 0.8> }
|
||||
union {
|
||||
box { size <0.8, 1, 0.8> }
|
||||
box { size <0.8, 0.8, 1> }
|
||||
}
|
||||
}
|
||||
union {
|
||||
union {
|
||||
union {
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, 0.4, -0.4>
|
||||
}
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, -0.4, -0.4>
|
||||
}
|
||||
}
|
||||
union {
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <-0.4, 0.4, -0.4>
|
||||
}
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <-0.4, -0.4, -0.4>
|
||||
}
|
||||
}
|
||||
}
|
||||
union {
|
||||
union {
|
||||
union {
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, -0.4, 0.4>
|
||||
rotate -90, <1, 0, 0>
|
||||
}
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, -0.4, -0.4>
|
||||
rotate -90, <1, 0, 0>
|
||||
}
|
||||
}
|
||||
union {
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <-0.4, -0.4, 0.4>
|
||||
rotate -90, <1, 0, 0>
|
||||
}
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <-0.4, -0.4, -0.4>
|
||||
rotate -90, <1, 0, 0>
|
||||
}
|
||||
}
|
||||
}
|
||||
union {
|
||||
union {
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, -0.4, 0.4>
|
||||
rotate -90, <0, 1, 0>
|
||||
}
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, -0.4, -0.4>
|
||||
rotate -90, <0, 1, 0>
|
||||
}
|
||||
}
|
||||
union {
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, 0.4, 0.4>
|
||||
rotate -90, <0, 1, 0>
|
||||
}
|
||||
cyl {
|
||||
size <0.1, 0.1, 0.8>
|
||||
translate <0.4, 0.4, -0.4>
|
||||
rotate -90, <0, 1, 0>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
union {
|
||||
union {
|
||||
union {
|
||||
sphere { radius 0.1 translate <0.4, 0.4, 0.4> }
|
||||
sphere { radius 0.1 translate <0.4, 0.4, -0.4> }
|
||||
}
|
||||
union {
|
||||
sphere { radius 0.1 translate <0.4, -0.4, 0.4> }
|
||||
sphere { radius 0.1 translate <0.4, -0.4, -0.4> }
|
||||
}
|
||||
}
|
||||
union {
|
||||
union {
|
||||
sphere { radius 0.1 translate <-0.4, 0.4, 0.4> }
|
||||
sphere { radius 0.1 translate <-0.4, 0.4, -0.4> }
|
||||
}
|
||||
union {
|
||||
sphere { radius 0.1 translate <-0.4, -0.4, 0.4> }
|
||||
sphere { radius 0.1 translate <-0.4, -0.4, -0.4> }
|
||||
}
|
||||
}
|
||||
}
|
||||
box { size <1, 0.8, 0.8> }
|
||||
box { size <0.8, 1, 0.8> }
|
||||
box { size <0.8, 0.8, 1> }
|
||||
|
||||
cyl { size <0.1, 0.1, 0.8> translate <0.4, 0.4, -0.4> }
|
||||
cyl { size <0.1, 0.1, 0.8> translate <0.4, -0.4, -0.4> }
|
||||
cyl { size <0.1, 0.1, 0.8> translate <-0.4, 0.4, -0.4> }
|
||||
cyl { size <0.1, 0.1, 0.8> translate <-0.4, -0.4, -0.4> }
|
||||
|
||||
cyl { size <.1, .1, .8> translate <.4, -.4, .4> rotate -90, <1, 0, 0> }
|
||||
cyl { size <.1, .1, .8> translate <.4, -.4, -.4> rotate -90, <1, 0, 0> }
|
||||
cyl { size <.1, .1, .8> translate <-.4, -.4, .4> rotate -90, <1, 0, 0> }
|
||||
cyl { size <.1, .1, .8> translate <-.4, -.4, -.4> rotate -90, <1, 0, 0> }
|
||||
|
||||
cyl { size <.1, .1, .8> translate <.4, -.4, .4> rotate -90, <0, 1, 0> }
|
||||
cyl { size <.1, .1, .8> translate <.4, -.4, -.4> rotate -90, <0, 1, 0> }
|
||||
cyl { size <.1, .1, .8> translate <.4, .4, .4> rotate -90, <0, 1, 0> }
|
||||
cyl { size <.1, .1, .8> translate <.4, .4, -.4> rotate -90, <0, 1, 0> }
|
||||
|
||||
sphere { radius .1 translate <.4, .4, .4> }
|
||||
sphere { radius .1 translate <.4, .4, -.4> }
|
||||
sphere { radius .1 translate <.4, -.4, .4> }
|
||||
sphere { radius .1 translate <.4, -.4, -.4> }
|
||||
sphere { radius .1 translate <-.4, .4, .4> }
|
||||
sphere { radius .1 translate <-.4, .4, -.4> }
|
||||
sphere { radius .1 translate <-.4, -.4, .4> }
|
||||
sphere { radius .1 translate <-.4, -.4, -.4> }
|
||||
|
||||
material
|
||||
{
|
||||
|
@ -1,16 +1,6 @@
|
||||
|
||||
#include "BoolShape.h"
|
||||
|
||||
BoolShape::BoolShape(refptr<Shape> shape1, refptr<Shape> shape2)
|
||||
{
|
||||
m_shape1 = shape1;
|
||||
m_shape2 = shape2;
|
||||
}
|
||||
|
||||
BoolShape::~BoolShape()
|
||||
{
|
||||
}
|
||||
|
||||
void BoolShape::setMaterial(refptr<Material> material)
|
||||
{
|
||||
m_material = material;
|
||||
|
@ -7,8 +7,6 @@
|
||||
class BoolShape : public Shape
|
||||
{
|
||||
public:
|
||||
BoolShape(refptr<Shape> shape1, refptr<Shape> shape2);
|
||||
~BoolShape();
|
||||
virtual IntersectionList intersect(refptr<Shape> _this, const Ray & ray) = 0;
|
||||
virtual void setMaterial(refptr<Material> material);
|
||||
|
||||
|
@ -3,9 +3,30 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
Intersect::Intersect(refptr<Shape> shape1, refptr<Shape> shape2)
|
||||
: BoolShape(shape1, shape2)
|
||||
Intersect::Intersect(const vector< refptr<Shape> > & shapes)
|
||||
{
|
||||
int num_shapes = shapes.size();
|
||||
if (num_shapes > 2)
|
||||
{
|
||||
m_shape2 = shapes[num_shapes - 1];
|
||||
vector< refptr<Shape> > rest = shapes;
|
||||
rest.pop_back();
|
||||
m_shape1 = new Intersect(rest);
|
||||
}
|
||||
else if (num_shapes == 2)
|
||||
{
|
||||
m_shape1 = shapes[0];
|
||||
m_shape2 = shapes[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << __FILE__ << ": " << __LINE__
|
||||
<< ": error: Intersect::Intersect() called with only "
|
||||
<< num_shapes
|
||||
<< " sub-shapes!"
|
||||
<< endl;
|
||||
exit(4);
|
||||
}
|
||||
}
|
||||
|
||||
Shape::IntersectionList Intersect::intersect(refptr<Shape> _this, const Ray & ray)
|
||||
@ -16,8 +37,31 @@ Shape::IntersectionList Intersect::intersect(refptr<Shape> _this, const Ray & ra
|
||||
|
||||
IntersectionList res;
|
||||
bool in1 = false, in2 = false;
|
||||
bool in_bool = false;
|
||||
|
||||
/* initially go through the merged intersections to see whether
|
||||
* the ray started inside one of the sub-objects */
|
||||
for (int i = 0, sz = merged.size(), saw1 = 0, saw2 = 0;
|
||||
i < sz && (!saw1 || !saw2);
|
||||
i++)
|
||||
{
|
||||
Vector normal = merged[i].intersection.normal;
|
||||
double dot = - (ray.getDirection() % normal);
|
||||
bool back = dot < 0.0;
|
||||
bool left = merged[i].left;
|
||||
if (back)
|
||||
{
|
||||
if (left && !saw1)
|
||||
in1 = true;
|
||||
else if (!left && !saw2)
|
||||
in2 = true;
|
||||
}
|
||||
if (left)
|
||||
saw1 = 1;
|
||||
else
|
||||
saw2 = 1;
|
||||
}
|
||||
|
||||
bool in_bool = in1 && in2;
|
||||
for (int i = 0, sz = merged.size(); i < sz; i++)
|
||||
{
|
||||
Vector normal = merged[i].intersection.normal;
|
||||
|
@ -3,11 +3,12 @@
|
||||
#define INTERSECT_H INTERSECT_H
|
||||
|
||||
#include "BoolShape.h"
|
||||
#include <vector>
|
||||
|
||||
class Intersect : public BoolShape
|
||||
{
|
||||
public:
|
||||
Intersect(refptr<Shape> shape1, refptr<Shape> shape2);
|
||||
Intersect(const std::vector< refptr<Shape> > & shapes);
|
||||
IntersectionList intersect(refptr<Shape> _this, const Ray & ray);
|
||||
};
|
||||
|
||||
|
@ -3,9 +3,30 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
Subtract::Subtract(refptr<Shape> shape1, refptr<Shape> shape2)
|
||||
: BoolShape(shape1, shape2)
|
||||
Subtract::Subtract(const vector< refptr<Shape> > & shapes)
|
||||
{
|
||||
int num_shapes = shapes.size();
|
||||
if (num_shapes > 2)
|
||||
{
|
||||
m_shape2 = shapes[num_shapes - 1];
|
||||
vector< refptr<Shape> > rest = shapes;
|
||||
rest.pop_back();
|
||||
m_shape1 = new Subtract(rest);
|
||||
}
|
||||
else if (num_shapes == 2)
|
||||
{
|
||||
m_shape1 = shapes[0];
|
||||
m_shape2 = shapes[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << __FILE__ << ": " << __LINE__
|
||||
<< ": error: Subtract::Subtract() called with only "
|
||||
<< num_shapes
|
||||
<< " sub-shapes!"
|
||||
<< endl;
|
||||
exit(4);
|
||||
}
|
||||
}
|
||||
|
||||
Shape::IntersectionList Subtract::intersect(refptr<Shape> _this, const Ray & ray)
|
||||
@ -16,8 +37,31 @@ Shape::IntersectionList Subtract::intersect(refptr<Shape> _this, const Ray & ray
|
||||
|
||||
IntersectionList res;
|
||||
bool in1 = false, in2 = false;
|
||||
bool in_bool = false;
|
||||
|
||||
/* initially go through the merged intersections to see whether
|
||||
* the ray started inside one of the sub-objects */
|
||||
for (int i = 0, sz = merged.size(), saw1 = 0, saw2 = 0;
|
||||
i < sz && (!saw1 || !saw2);
|
||||
i++)
|
||||
{
|
||||
Vector normal = merged[i].intersection.normal;
|
||||
double dot = - (ray.getDirection() % normal);
|
||||
bool back = dot < 0.0;
|
||||
bool left = merged[i].left;
|
||||
if (back)
|
||||
{
|
||||
if (left && !saw1)
|
||||
in1 = true;
|
||||
else if (!left && !saw2)
|
||||
in2 = true;
|
||||
}
|
||||
if (left)
|
||||
saw1 = 1;
|
||||
else
|
||||
saw2 = 1;
|
||||
}
|
||||
|
||||
bool in_bool = in1 && !in2;
|
||||
for (int i = 0, sz = merged.size(); i < sz; i++)
|
||||
{
|
||||
Vector normal = merged[i].intersection.normal;
|
||||
|
@ -3,11 +3,12 @@
|
||||
#define SUBTRACT_H SUBTRACT_H
|
||||
|
||||
#include "BoolShape.h"
|
||||
#include <vector>
|
||||
|
||||
class Subtract : public BoolShape
|
||||
{
|
||||
public:
|
||||
Subtract(refptr<Shape> shape1, refptr<Shape> shape2);
|
||||
Subtract(const std::vector< refptr<Shape> > & shapes);
|
||||
IntersectionList intersect(refptr<Shape> _this, const Ray & ray);
|
||||
};
|
||||
|
||||
|
@ -1,11 +1,33 @@
|
||||
|
||||
#include "Union.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
Union::Union(refptr<Shape> shape1, refptr<Shape> shape2)
|
||||
: BoolShape(shape1, shape2)
|
||||
Union::Union(const vector< refptr<Shape> > & shapes)
|
||||
{
|
||||
int num_shapes = shapes.size();
|
||||
if (num_shapes > 2)
|
||||
{
|
||||
m_shape2 = shapes[num_shapes - 1];
|
||||
vector< refptr<Shape> > rest = shapes;
|
||||
rest.pop_back();
|
||||
m_shape1 = new Union(rest);
|
||||
}
|
||||
else if (num_shapes == 2)
|
||||
{
|
||||
m_shape1 = shapes[0];
|
||||
m_shape2 = shapes[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << __FILE__ << ": " << __LINE__
|
||||
<< ": error: Union::Union() called with only "
|
||||
<< num_shapes
|
||||
<< " sub-shapes!"
|
||||
<< endl;
|
||||
exit(4);
|
||||
}
|
||||
}
|
||||
|
||||
Shape::IntersectionList Union::intersect(refptr<Shape> _this, const Ray & ray)
|
||||
@ -16,8 +38,31 @@ Shape::IntersectionList Union::intersect(refptr<Shape> _this, const Ray & ray)
|
||||
|
||||
IntersectionList res;
|
||||
bool in1 = false, in2 = false;
|
||||
bool in_bool = false;
|
||||
|
||||
/* initially go through the merged intersections to see whether
|
||||
* the ray started inside one of the sub-objects */
|
||||
for (int i = 0, sz = merged.size(), saw1 = 0, saw2 = 0;
|
||||
i < sz && (!saw1 || !saw2);
|
||||
i++)
|
||||
{
|
||||
Vector normal = merged[i].intersection.normal;
|
||||
double dot = - (ray.getDirection() % normal);
|
||||
bool back = dot < 0.0;
|
||||
bool left = merged[i].left;
|
||||
if (back)
|
||||
{
|
||||
if (left && !saw1)
|
||||
in1 = true;
|
||||
else if (!left && !saw2)
|
||||
in2 = true;
|
||||
}
|
||||
if (left)
|
||||
saw1 = 1;
|
||||
else
|
||||
saw2 = 1;
|
||||
}
|
||||
|
||||
bool in_bool = in1 || in2;
|
||||
for (int i = 0, sz = merged.size(); i < sz; i++)
|
||||
{
|
||||
Vector normal = merged[i].intersection.normal;
|
||||
|
@ -3,11 +3,12 @@
|
||||
#define UNION_H UNION_H
|
||||
|
||||
#include "BoolShape.h"
|
||||
#include <vector>
|
||||
|
||||
class Union : public BoolShape
|
||||
{
|
||||
public:
|
||||
Union(refptr<Shape> shape1, refptr<Shape> shape2);
|
||||
Union(const std::vector< refptr<Shape> > & shapes);
|
||||
IntersectionList intersect(refptr<Shape> _this, const Ray & ray);
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user