Commit 3385ba97 authored by LEFEBVREJP email's avatar LEFEBVREJP email
Browse files

Merge branch 'geometry' into 'master'

Geometry expansion

See merge request !78
parents 638ea2ac 29945b10
Pipeline #61826 passed with stages
in 15 minutes and 19 seconds
......@@ -3,14 +3,46 @@ TRIBITS_SUBPACKAGE(geometry)
SET(SOURCE
aabb.cc
abstractsurface.cc
bihscene.cc
bihtree.cc
cuboid.cc
cylinder.cc
difference.cc
disc.cc
geometryfactory.cc
geometryobject.cc
geometrypool.cc
grid.cc
instance.cc
interval.cc
plane.cc
scene.cc
shadeinfo.cc
sphere.cc
union.cc
)
SET(HEADERS
aabb.hh
abstractsurface.hh
bihscene.hh
bihtree.hh
cuboid.hh
cylinder.hh
difference.hh
disc.hh
geometryfactory.hh
geometryobject.hh
geometrypool.hh
grid.hh
instance.hh
interval.hh
plane.hh
scene.hh
shadeinfo.hh
sphere.hh
union.hh
)
#
......
......@@ -211,4 +211,4 @@ class RADIX_PUBLIC AABB
} // namespace radix
#endif /* ATLAS_AABB_H */
#endif /* RADIX_RADIXGEOMETRY_AABB_HH_ */
/*
* File: abstractsurface.cc
* Author: a16
*
* Created on August 26, 2013, 9:23 AM
*/
#include "radixgeometry/abstractsurface.hh"
namespace radix
{
AbstractSurface::AbstractSurface()
: GeometryObject()
{
}
AbstractSurface::AbstractSurface(const AbstractSurface& orig)
: GeometryObject(orig)
{
}
AbstractSurface::~AbstractSurface() {}
} // namespace radix
/*
* File: AbstractSurface.h
* Author: a16
*
* Created on August 26, 2013, 9:23 AM
*/
#ifndef RADIX_RADIXGEOMETRY_ABSTRACTSURFACE_HH_
#define RADIX_RADIXGEOMETRY_ABSTRACTSURFACE_HH_
#include "radixgeometry/geometryobject.hh"
#include "radixmath/constants.hh"
#include "radixmath/point3d.hh"
#include "radixmath/ray.hh"
#include <vector>
namespace radix
{
class AbstractSurface : public GeometryObject
{
public:
AbstractSurface();
AbstractSurface(const AbstractSurface& orig);
virtual ~AbstractSurface();
/**
* Determine the relation from the surface to the given point
* @param x - the x component of the point
* @param y - the y component of the point
* @param z - the z component of the point
* @return Real - the relation to the surface ( negative, inside the surface,
* positive, outside the surface, 0 on)
*/
virtual Real Fxyz(Real x, Real y, Real z) const = 0;
virtual bool normal(const Point3D& point, Normal& n) const = 0;
virtual bool hit(const Ray& ray, Real& t) const = 0;
virtual AbstractSurface& transform(const Real& dx, const Real& dy,
const Real& dz, const Real& alpha,
const Real& beta, const Real& gamma) = 0;
/**
* Obtain the hits for this surface
* @param ray - the ray to determine intersection with
* @param hits - the datastructure to populate with hits
* @param limit - the limit to which hits should be returned (hits beyond this
* limit are not returned)
* @return - bool - true, if and only if a hit occurred
*/
virtual bool hits(const Ray& ray, std::vector<Real>& hits,
const Real limit = maxReal) const = 0;
private:
};
} // namespace radix
#endif /* RADIX_RADIXGEOMETRY_ABSTRACTSURFACE_HH_ */
/*
* File: BIHScene.cc
* Author: a16
*
* Created on September 19, 2012, 12:16 PM
*/
#include "radixgeometry/bihscene.hh"
#include <algorithm>
#include "radixbug/bug.hh"
namespace radix
{
BIHScene::BIHScene()
: Scene()
, BIHTree()
{
}
BIHScene::~BIHScene() {}
void BIHScene::add_object(GeometryObject* object)
{
BIHTree::add_object(object);
}
GeometryObject* BIHScene::clone() const
{
throw std::runtime_error("Method BIHScene::clone() is not implemented.");
}
Interval::List BIHScene::intervals(const Ray& ray, const Real& limit) const
{
return BIHTree::intervals(ray, limit);
}
AABB BIHScene::bounding_box() const { return BIHTree::bounding_box(); }
bool BIHScene::hit(const Ray& ray, Real& t, ShadeInfo& s) const
{
return BIHTree::hit(ray, t, s);
}
bool BIHScene::inside(const Point3D& p) const { return BIHTree::inside(p); }
bool BIHScene::on(const Point3D& p) const { return BIHTree::on(p); }
std::string BIHScene::to_string() const { return "BIHScene"; }
} // namespace radix
/*
* File: BIHScene.hh
* Author: a16
*
* Created on September 19, 2012, 12:16 PM
*/
#ifndef RADIX_RADIXGEOMETRY_BIHSCENE_HH_
#define RADIX_RADIXGEOMETRY_BIHSCENE_HH_
#include "radixgeometry/bihtree.hh"
#include "radixgeometry/scene.hh"
#include <cstring>
#include <vector>
namespace radix
{
class RADIX_PUBLIC BIHScene : public Scene, public BIHTree
{
public:
BIHScene();
virtual ~BIHScene();
virtual void add_object(GeometryObject* object);
virtual GeometryObject* clone() const;
virtual Interval::List intervals(const Ray& ray,
const Real& limit = maxReal) const;
virtual AABB bounding_box() const;
virtual bool hit(const Ray& ray, Real& t, ShadeInfo& s) const;
virtual bool inside(const Point3D& p) const;
virtual bool on(const Point3D& p) const;
virtual std::string to_string() const;
};
} // namespace radix
#endif /* RADIX_RADIXGEOMETRY_BIHSCENE_HH_ */
/*
* File: bihtree.cc
* Author: a16
*
* Created on September 26, 2012, 12:15 PM
*/
#include "radixgeometry/bihtree.hh"
#include <algorithm>
#include <queue>
namespace radix
{
BIHTree::BIHTree()
: GeometryObject()
, m_branches(0)
, root(nullptr)
{
}
BIHTree::BIHTree(const BIHTree& orig)
: GeometryObject(orig)
, m_branches(orig.m_branches)
, root(orig.root->clone())
{
root->getLeavesDepthFirst(m_leaves);
}
BIHTree::~BIHTree() { Node::destroy(&root); }
void BIHTree::add_object(GeometryObject* object)
{
radix_require(object != 0);
Node* node;
node = new Node();
node->data = object;
m_leaves.push_back(node);
}
GeometryObject* BIHTree::clone() const { return new BIHTree(*this); }
Interval::List BIHTree::intervals(const Ray& ray, const Real& limit) const
{
radix_require(limit >= 0 && limit <= maxReal);
const NodeList& prospects(getProspects(ray, limit));
Interval::List list;
for (NodeList::const_iterator i = prospects.begin(); i != prospects.end();
i++)
{
const Node* n(*i);
const Interval::List& intervals(n->data->intervals(ray, limit));
list.insert(list.end(), intervals.begin(), intervals.end());
}
std::sort(list.begin(), list.end());
return list;
}
AABB BIHTree::aabb(NodeList::iterator first, NodeList::iterator last) const
{
AABB aabb;
Node* node;
node = *first;
aabb = node->data->bounding_box();
if (first != last)
{
for (first++; first != last; first++)
{
node = *first;
aabb = aabb + node->data->bounding_box();
}
}
return aabb;
}
AABB BIHTree::bounding_box() const { return m_aabb; }
size_t BIHTree::branch_count() const { return m_branches; }
void BIHTree::getCandidates(const AABB& bounds, Candidate candidates[]) const
{
Vector3D diff(bounds.x1 - bounds.x0, bounds.y1 - bounds.y0,
bounds.z1 - bounds.z0);
candidates[0] = Candidate(X_PLANE, diff.x);
candidates[1] = Candidate(Y_PLANE, diff.y);
candidates[2] = Candidate(Z_PLANE, diff.z);
std::sort(candidates, candidates + 3);
for (int i = 0; i < 3; i++)
{
Candidate& candidate(candidates[i]);
switch (candidate.plane)
{
case X_PLANE:
candidate.cut = (bounds.x0 + bounds.x1) / 2;
break;
case Y_PLANE:
candidate.cut = (bounds.y0 + bounds.y1) / 2;
break;
default:
candidate.cut = (bounds.z0 + bounds.z1) / 2;
break;
}
}
}
size_t BIHTree::leaf_count() const { return m_leaves.size(); }
const BIHTree::NodeList& BIHTree::leaves() const { return m_leaves; }
BIHTree::NodeList BIHTree::getProspects(const Ray& ray, Real limit) const
{
std::queue<Node*> nodes;
NodeList prospects;
nodes.push(root);
while (!nodes.empty())
{
Node* node;
node = nodes.front();
nodes.pop();
if (node->isLeaf())
{
prospects.push_back(node);
}
else
{
bool addLeft;
bool addRight;
Real cutDirection;
Real cutOrigin;
bool hitsLeft;
bool hitsRight;
bool inLeft;
bool inRight;
switch (node->plane)
{
case X_PLANE:
cutDirection = ray.d.x;
cutOrigin = ray.o.x;
break;
case Y_PLANE:
cutDirection = ray.d.y;
cutOrigin = ray.o.y;
break;
default:
cutDirection = ray.d.z;
cutOrigin = ray.o.z;
break;
}
inLeft = cutOrigin <= node->cutLeft;
hitsLeft =
cutDirection < 0 && cutOrigin + cutDirection * limit <= node->cutLeft;
addLeft = node->left != 0 && (inLeft || hitsLeft);
inRight = node->cutRight <= cutOrigin;
hitsRight = cutDirection > 0 &&
node->cutRight <= cutOrigin + cutDirection * limit;
addRight = node->right != 0 && (inRight || hitsRight);
if (addLeft && addRight)
{
if (cutDirection >= 0)
{
nodes.push(node->left);
nodes.push(node->right);
}
else
{
nodes.push(node->right);
nodes.push(node->left);
}
}
else if (addLeft)
{
nodes.push(node->left);
}
else if (addRight)
{
nodes.push(node->right);
}
}
}
return prospects;
}
bool BIHTree::hit(const Ray& ray, Real& t, ShadeInfo& s) const
{
const NodeList& prospects(getProspects(ray));
bool hit;
Real tMin;
hit = false;
tMin = maxReal;
for (NodeList::const_iterator i = prospects.begin(); i != prospects.end();
i++)
{
const Node* n(*i);
if (n->data->hit(ray, t, s))
{
hit = true;
tMin = std::min(t, tMin);
}
}
t = tMin;
return hit;
}
bool BIHTree::inside(const Point3D& p) const
{
const NodeList& prospects(getProspects(Ray(p, Vector3D())));
for (NodeList::const_iterator i = prospects.begin(); i != prospects.end();
i++)
{
const Node* n(*i);
if (n->data->inside(p))
{
return true;
}
}
return false;
}
bool BIHTree::on(const Point3D& p) const
{
const NodeList& prospects(getProspects(Ray(p, Vector3D())));
for (NodeList::const_iterator i = prospects.begin(); i != prospects.end();
i++)
{
const Node* n(*i);
if (n->data->on(p))
{
return true;
}
}
return false;
}
void BIHTree::partition(Node* node, NodeList::iterator first,
NodeList::iterator last)
{
AABB aabb_;
Candidate candidates[3];
Candidate chosen;
NodeList::iterator split;
aabb_ = aabb(first, last);
getCandidates(aabb_, candidates);
for (int i = 0; i < 3; i++)
{
NodePartition part(candidates[i]);
chosen = candidates[i];
split = std::stable_partition(first, last, part);
if (first != split && split != last)
{
break;
}
}
node->plane = chosen.plane;
switch (last - first)
{
case 0:
return;
case 1:
setSingleChild(node, first, split);
return;
case 2:
setBothChildren(node, first);
return;
default:
repartition(node, first, split, last);
break;
}
}
void BIHTree::process()
{
// radix_timer( timer );
// radix_timer_start( timer );
root = new Node();
if (!m_leaves.empty())
{
partition(root, m_leaves.begin(), m_leaves.end());
m_aabb = aabb(m_leaves.begin(), m_leaves.end());
}
// radix_timer_stop( timer );
// radix_timer_block( std::cout << "BIHTree::process: " <<
// timer.wall_clock() << std::endl );
}
void BIHTree::process_and_traverse()
{
process();
traverse();
// radix_tagged_line( "branches|leaves: " << branches << "|" <<
// leaves.size() );
}
void BIHTree::repartition(Node* node, NodeList::iterator first,
NodeList::iterator split, NodeList::iterator last)
{
AABB aabb1;
AABB aabb2;
if (first == split || split == last)
{
split = first + (last - first) / 2;
}
aabb1 = aabb(first, split);
aabb2 = aabb(split, last);
switch (node->plane)
{
case X_PLANE:
node->cutLeft = aabb1.x1;
node->cutRight = aabb2.x0;
break;
case Y_PLANE:
node->cutLeft = aabb1.y1;
node->cutRight = aabb2.y0;
break;
default:
node->cutLeft = aabb1.z1;
node->cutRight = aabb2.z0;
break;
}
node->left = new Node();
node->right = new Node();
partition(node->left, first, split);
partition(node->right, split, last);
if (!Node::isValid(node->left))
{
Node::destroy(&(node->left));
}
if (!Node::isValid(node->right))
{
Node::destroy(&(node->right));
}
}
void BIHTree::setBothChildren(Node* node, NodeList::iterator first)
{
AABB aabb1;
AABB aabb2;
node->left = *first;
aabb1 = node->left->data->bounding_box();