Commit 3e1e4863 authored by Jan Möbius's avatar Jan Möbius

t push

Merge branch 'master' into warnings
parents 9112178a 61f76792
Pipeline #3511 passed with stage
in 82 minutes and 21 seconds
......@@ -45,3 +45,14 @@ VS2013-Qt-5.5.1-x64:
artifacts:
paths:
- rel/*.exe
Mac-Cpp11:
script: "CI/ci-mac.sh"
cache:
paths:
- build-release/
tags:
- Apple
artifacts:
paths:
- build-release/*.dmg
......@@ -446,6 +446,9 @@ class ScenegraphTraversalStackEl {
void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode &_node, const ACG::SceneGraph::Material &_mat )
{
renderObjectSource_.clear();
overlayObjectSource_.clear();
if (_node.status() == ACG::SceneGraph::BaseNode::HideSubtree)
return;
......@@ -478,6 +481,10 @@ void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph
if (cur.node->status() != ACG::SceneGraph::BaseNode::HideNode)
cur.node->getRenderObjects(this, *_glState, nodeDM, cur.material);
// keep track of which node added objects
size_t numAddedObjects = renderObjects_.size() - renderObjectSource_.size();
renderObjectSource_.insert(renderObjectSource_.end(), numAddedObjects, cur.node);
// Process children?
if (cur.node->status() != ACG::SceneGraph::BaseNode::HideChildren) {
// Process all children which are second pass
......@@ -565,11 +572,21 @@ void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph
lineGL42Objects_.clear();
lineGL42Objects_.reserve(numLineObjects);
sortListObjects_.clear();
sortListObjects_.reserve(numRenderObjects);
sortListOverlays_.clear();
sortListOverlays_.reserve(numOverlayObjects);
// init sorted objects array
for (size_t i = 0; i < renderObjects_.size(); ++i)
{
if (renderObjects_[i].overlay)
{
overlayObjects_.push_back(&renderObjects_[i]);
sortListOverlays_.push_back(i);
}
else if (enableLineThicknessGL42_ && numLineObjects && renderObjects_[i].isDefaultLineObject())
{
renderObjects_[i].shaderDesc.geometryTemplateFile = "Wireframe/gl42/geometry.tpl";
......@@ -582,7 +599,10 @@ void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph
lineGL42Objects_.push_back(&renderObjects_[i]);
}
else
{
sortedObjects_.push_back(&renderObjects_[i]);
sortListObjects_.push_back(i);
}
}
sortRenderObjects();
......@@ -790,16 +810,50 @@ void IRenderer::clearInputFbo( const ACG::Vec4f& clearColor )
namespace {
struct RenderObjectComparator {
bool operator() (ACG::RenderObject *a, ACG::RenderObject * b) {
return (a->priority < b->priority);
RenderObjectComparator(const std::vector<ACG::RenderObject>& _vec) : vec_(_vec) {
}
bool operator() (int a, int b) {
return (vec_[a].priority < vec_[b].priority);
}
const std::vector<ACG::RenderObject>& vec_;
};
}
void IRenderer::sortRenderObjects()
{
std::sort(sortedObjects_.begin(), sortedObjects_.end(), RenderObjectComparator());
std::sort(overlayObjects_.begin(), overlayObjects_.end(), RenderObjectComparator());
size_t numObjs = sortListObjects_.size();
size_t numOverlays = sortListOverlays_.size();
RenderObjectComparator cmpOp(renderObjects_);
std::sort(sortListObjects_.begin(), sortListObjects_.end(), cmpOp);
std::sort(sortListOverlays_.begin(), sortListOverlays_.end(), cmpOp);
// apply sorting list
std::vector<ACG::SceneGraph::BaseNode*> temp;
renderObjectSource_.swap(temp);
renderObjectSource_.resize(numObjs, 0);
overlayObjectSource_.resize(numOverlays, 0);
for (size_t i = 0; i < numObjs; ++i)
{
int objID = sortListObjects_[i];
sortedObjects_[i] = &renderObjects_[objID];
renderObjectSource_[i] = temp[objID];
}
for (size_t i = 0; i < numOverlays; ++i)
{
int objID = sortListOverlays_[i];
overlayObjects_[i] = &renderObjects_[objID];
overlayObjectSource_[i] = temp[objID];
}
}
......@@ -1148,6 +1202,18 @@ ACG::RenderObject* IRenderer::getOverlayRenderObject( int i )
return overlayObjects_[i];
}
ACG::SceneGraph::BaseNode* IRenderer::getRenderObjectNode( int i )
{
return renderObjectSource_[i];
}
ACG::SceneGraph::BaseNode* IRenderer::getOverlayRenderObjectNode( int i )
{
return overlayObjectSource_[i];
}
ACG::RenderObject* IRenderer::getLineGL42RenderObject( int i )
{
if (lineGL42Objects_.empty())
......
......@@ -446,6 +446,14 @@ protected:
const ACG::Vec3f& getGlobalAmbientScale() const {return globalLightModelAmbient_;}
/// Get node that emitted the render object in the sorted list by index (not including overlay objects)
ACG::SceneGraph::BaseNode* getRenderObjectNode(int i);
/// Get node that emitted the render object in the sorted list by index (only overlay objects)
ACG::SceneGraph::BaseNode* getOverlayRenderObjectNode(int i);
/** Enable/disable line thickness rendering with opengl4.2
*
* Instead of quad extrusion in a geometry shader, thick lines are manually rasterized in a load/store image.
......@@ -498,6 +506,10 @@ protected:
/// array of renderobjects, filled by addRenderObject()
std::vector<ACG::RenderObject> renderObjects_;
/// map sortedID -> original renderObjectID
std::vector<int> sortListObjects_;
/// map sortedID -> original renderObjectID
std::vector<int> sortListOverlays_;
/// sorted list of renderobjects without overlay objects (sorted in rendering order)
std::vector<ACG::RenderObject*> sortedObjects_;
......@@ -508,6 +520,12 @@ protected:
/// active render object modifiers
std::vector<ACG::RenderObjectModifier*> renderObjectModifiers_;
/// source node that added the render object (map renderObjectID -> scenegraph node)
std::vector<ACG::SceneGraph::BaseNode*> renderObjectSource_;
/// source node that added the overlay render object (map renderObjectID -> scenegraph node)
std::vector<ACG::SceneGraph::BaseNode*> overlayObjectSource_;
/**
* Stores fbo containing a depth map for each viewport.
* The depth map is computed in a z-prepass if at least one RenderObject makes use of the scene depth map.
......
......@@ -65,7 +65,7 @@
#if defined(ARCH_DARWIN)
#include <gl/glew.h>
#include <GL/glew.h>
#elif defined(WIN32)
......
......@@ -61,6 +61,8 @@
#include <vector>
#include <iostream>
#include "../Math/Matrix3x3T.hh"
namespace ACG {
namespace Geometry {
......@@ -631,7 +633,72 @@ roundness( const VectorT<Scalar, N>& _v0,
const VectorT<Scalar, N>& _v1,
const VectorT<Scalar, N>& _v2 );
/** @} */
/** @} */
template<typename Vector>
Vector closestPointLineSegment(Vector x, Vector p1, Vector p2) {
const auto delta = ((p2-p1)|(x-p1)) / (p2-p1).sqrnorm();
//std::cout << "\x1b[32mdelta = " << delta << "\x1b[0m" << std::endl;
if (delta <= 0) {
//std::cout << "\x1b[43mdelta <= 0\x1b[0m" << std::endl;
return p1;
} else if (delta >= 1) {
//std::cout << "\x1b[43mdelta >= 1\x1b[0m" << std::endl;
return p2;
} else if (delta != delta) { // p1 = p2 or x = p1
//std::cout << "\x1b[43mdelta != delta\x1b[0m" << std::endl;
return (x-p1).sqrnorm() < (x-p2).sqrnorm() ? p1 : p2;
} else {
//std::cout << "\x1b[43mdelta \\in [0, 1]\x1b[0m" << std::endl;
return (1 - delta) * p1 + delta * p2;
}
};
template<typename Vector>
Vector closestPointTri(Vector p, Vector a, Vector b, Vector c) {
constexpr double thresh = 1e-8;
const auto n = ((b - a) % (c - a)); // normalization unnecessary
if ((b-a).sqrnorm() < thresh || (c-a).sqrnorm() < thresh || n.sqrnorm() < thresh) {
//std::cout << "\x1b[42mDegenerate case.\x1b[0m" << std::endl;
// Degenerate triangle. Find distance to longest segment.
std::array<ACG::Vec3d, 2> max_segment = {a, b};
double max_len = (b-a).sqrnorm();
if ((c-a).sqrnorm() > max_len)
max_segment = {a, c};
if ((c-b).sqrnorm() > max_len)
max_segment = {b, c};
// closestPointLineSegment is stable, even if the segment is super short
return closestPointLineSegment(p, max_segment[0], max_segment[1]);
}
const auto abd = Matrix3x3d::fromColumns(a-c, b-c, n).inverse() * (p - c);
const bool alpha = (abd[0] >= 0.0),
beta = (abd[1] >= 0.0),
gamma = (1.0-abd[0]-abd[1] >= 0.0);
if (alpha && beta && gamma) {
//std::cout << "\x1b[42mInside case.\x1b[0m" << std::endl;
// Inside triangle.
return abd[0] * a + abd[1] * b + (1.0 - abd[0] - abd[1]) * c;
} else if (!alpha) {
//std::cout << "\x1b[42m!alpha case.\x1b[0m" << std::endl;
// Closest to line segment (b, c).
return closestPointLineSegment(p, b, c);
} else if (!beta) {
//std::cout << "\x1b[42m!beta case.\x1b[0m" << std::endl;
// Closest to line segment (a, c).
return closestPointLineSegment(p, a, c);
} else if (!gamma) {
//std::cout << "\x1b[42m!gamma case.\x1b[0m" << std::endl;
// Closest to line segment (a, b).
return closestPointLineSegment(p, a, b);
} else {
throw std::logic_error("This cannot happen.");
}
}
//=============================================================================
} // namespace Geometry
......
......@@ -63,7 +63,7 @@
#include "BSPImplT.hh"
#include <cfloat>
#include <cmath>
//== CLASS DEFINITION =========================================================
#include <vector>
......@@ -180,6 +180,16 @@ nearestRaycollision(const Point& _p, const Point& _r) const {
return RayCollision(data.hit_handles);
}
template<class BSPCore>
template<class Callback>
void
BSPImplT<BSPCore>::
intersectBall(const Point &_c, Scalar _r, Callback _callback) const
{
_intersect_ball(*(this->root_), _c, _r, _callback);
}
//-----------------------------------------------------------------------------
......@@ -309,8 +319,42 @@ _raycollision_nearest_directional(Node* _node, RayCollisionData& _data) const
if ( second_node && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, second_node->bb_min, second_node->bb_max, tmin, tmax) && (tmin < dist) ) {
_raycollision_nearest_directional(second_node, _data);
}
}
}
}
template<class BSPCore>
template<class Callback>
void BSPImplT<BSPCore>::
_intersect_ball(const Node &_node,
const Point &_c,
Scalar _r,
Callback _callback) const
{
// terminal node
if (!_node.left_child_)
{
const double r_sqr = _r * _r;
for (const auto &fh: _node) {
const double dist = this->traits_.sqrdist(fh, _c);
if (dist < r_sqr) {
_callback(fh);
}
}
}
else // non-terminal node
{
const Scalar dist = _node.plane_.distance(_c);
const Node &left = *_node.left_child_;
const Node &right = *_node.right_child_;
if (dist > -_r){
_intersect_ball(left, _c, _r, _callback);
}
if (dist < _r) {
_intersect_ball(right, _c, _r, _callback);
}
}
}
//=============================================================================
......@@ -144,7 +144,21 @@ public: //---------------------------------------------------------------------
* @param _r Ray direction
* @return Collision information
*/
RayCollision nearestRaycollision(const Point& _p, const Point& _r) const;
RayCollision nearestRaycollision(const Point& _p, const Point& _r) const;
/** \brief intersect mesh with open ball
*
* All triangles that have at least one vertex (!) inside the ball are given to the Callback,
* triangles which have no vertex inside the ball but intersect it MAY be returned. (TODO)
* Each triangle can be returned up to three times, make sure to handle this, e.g.
* by putting the values into an std::(unordered_)set.
*
* @param _c Center of the ball
* @param _r Radius of the ball
* @param _callback Callable that accepts Handle or const Handle&, e.g. (const Handle &h) -> void
*/
template<class Callback>
void intersectBall(const Point & _c, Scalar _r, Callback _callback) const;
private: //---------------------------------------------------------------------
......@@ -188,7 +202,10 @@ private: //---------------------------------------------------------------------
*/
void _raycollision_directional(Node* _node, RayCollisionData& _data) const;
void _raycollision_nearest_directional(Node* _node, RayCollisionData& _data) const;
void _raycollision_nearest_directional(Node* _node, RayCollisionData& _data) const;
template<class Callback>
void _intersect_ball(const Node& _node, const Point & _c, Scalar _r, Callback _callback) const;
template<typename T,typename U>
struct less_pair_second: public std::binary_function<T,U,bool> {
......
......@@ -68,16 +68,17 @@
//== CLASS DEFINITION =========================================================
// Node of the tree: contains parent, children and splitting plane
template <class Mesh>
template <class BSPTraits>
struct TreeNode
{
typedef typename Mesh::FaceHandle Handle;
typedef typename Mesh::Point Point;
typedef typename Mesh::VertexHandle VertexHandle;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef typename Point::value_type Scalar;
typedef ACG::Geometry::PlaneT<Scalar> Plane;
typedef typename BSPTraits::Handle Handle;
typedef typename BSPTraits::Point Point;
typedef typename BSPTraits::VertexHandle VertexHandle;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef typename Handles::const_iterator HandleConstIter;
typedef typename Point::value_type Scalar;
typedef ACG::Geometry::PlaneT<Scalar> Plane;
TreeNode(const Handles& _handles, TreeNode* _parent)
: handles_(_handles),
......@@ -99,10 +100,19 @@ struct TreeNode
HandleIter begin() {
return handles_.begin();
}
HandleIter end() {
return handles_.end();
}
HandleConstIter begin() const {
return handles_.begin();
}
HandleConstIter end() const {
return handles_.end();
}
size_t size() const {
return handles_.size();
}
......@@ -194,10 +204,10 @@ struct TreeNode
};
template<class Mesh>
std::ostream &operator<< (std::ostream &stream, const TreeNode<Mesh> &node) {
template<class BSPTraits>
std::ostream &operator<< (std::ostream &stream, const TreeNode<BSPTraits> &node) {
stream << "[TreeNode instance. Handles: ";
for (typename std::vector<typename TreeNode<Mesh>::Handle>::const_iterator it = node.handles_.begin(), it_end = node.handles_.end();
for (typename TreeNode<BSPTraits>::Handles::const_iterator it = node.handles_.begin(), it_end = node.handles_.end();
it != it_end; ++it) {
stream << it->idx();
if (it < it_end-1) stream << ", ";
......
......@@ -66,8 +66,8 @@
#include "TriangleBSPCoreT.hh"
#include "BSPImplT.hh"
//== CLASS DEFINITION =========================================================
#include <list>
//== CLASS DEFINITION =========================================================
template <class BSPTraits>
class TriangleBSPT : public BSPImplT< TriangleBSPCoreT<BSPTraits> >
......@@ -81,129 +81,144 @@ public:
//== CLASS DEFINITION =========================================================
template <class Mesh>
class OpenMeshTriangleBSPTraits
template <class Mesh, class SpecificTraits>
class OVMOMCommonTriangleBSPTraits : public SpecificTraits
{
public:
typedef typename Mesh::Scalar Scalar;
typedef typename Mesh::Point Point;
typedef typename Mesh::FaceHandle Handle;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef TreeNode<Mesh> Node;
typedef typename SpecificTraits::Point Point;
typedef typename SpecificTraits::Handle Handle;
typedef typename Point::value_type Scalar;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef TreeNode<SpecificTraits> Node;
OpenMeshTriangleBSPTraits(const Mesh& _mesh) : mesh_(_mesh) {}
OVMOMCommonTriangleBSPTraits(const Mesh& _mesh) : SpecificTraits(_mesh) {}
/// Returns the points belonging to the face handle _h
inline void points(const Handle _h, Point& _p0, Point& _p1, Point& _p2) const
{
typename Mesh::CFVIter fv_it(mesh_.cfv_iter(_h));
_p0 = mesh_.point(*fv_it);
++fv_it;
_p1 = mesh_.point(*fv_it);
++fv_it;
_p2 = mesh_.point(*fv_it);
}
Scalar sqrdist(const Handle _h, const Point& _p) const
{
Point p0, p1, p2, q;
points(_h, p0, p1, p2);
return ACG::Geometry::distPointTriangleSquaredStable(_p, p0, p1, p2, q);
}
void calculateBoundingBox(Node* _node, Point& median, int& axis)
{
//determine splitting axis
HandleIter it_h;
Point p0, p1, p2, bb_min, bb_max;
bb_min.vectorize(std::numeric_limits<typename Point::value_type>::infinity());
bb_max.vectorize(-std::numeric_limits<typename Point::value_type>::infinity());
std::list<Point> vertices;
for (it_h = _node->begin(); it_h != _node->end(); ++it_h) {
points(*it_h, p0, p1, p2);
/*
bb_min.minimize(p0);
bb_min.minimize(p1);
bb_min.minimize(p2);
bb_max.maximize(p0);
bb_max.maximize(p1);
bb_max.maximize(p2);*/
vertices.push_back(p0);
vertices.push_back(p1);
vertices.push_back(p2);
}
bb_min = _node->bb_min;
bb_max = _node->bb_max;
// split longest side of bounding box
Point bb = bb_max - bb_min;
Scalar length = bb[0];
axis = 0;
if (bb[1] > length)
length = bb[(axis = 1)];
if (bb[2] > length)
length = bb[(axis = 2)];
//calculate the median value in axis-direction
switch (axis) {
case 0:
vertices.sort(x_sort());
break;
case 1:
vertices.sort(y_sort());
break;
case 2:
vertices.sort(z_sort());
break;
Scalar sqrdist(const Handle _h, const Point& _p) const
{
Point p0, p1, p2, q;
this->points(_h, p0, p1, p2);
return ACG::Geometry::distPointTriangleSquaredStable(_p, p0, p1, p2, q);
}
vertices.unique(); ///todo: does this work with Points?!
size_t size = vertices.size();
typename std::list<Point>::iterator it_v;
it_v = vertices.begin();
std::advance(it_v, size / 2);
median = *it_v;
void calculateBoundingBox(Node* _node, Point& median, int& axis)
{
//determine splitting axis
HandleIter it_h;
Point p0, p1, p2, bb_min, bb_max;
bb_min.vectorize(std::numeric_limits<typename Point::value_type>::infinity());
bb_max.vectorize(-std::numeric_limits<typename Point::value_type>::infinity());
std::list<Point> vertices;
for (it_h = _node->begin(); it_h != _node->end(); ++it_h) {
this->points(*it_h, p0, p1, p2);
/*
bb_min.minimize(p0);
bb_min.minimize(p1);
bb_min.minimize(p2);
bb_max.maximize(p0);
bb_max.maximize(p1);
bb_max.maximize(p2);*/
vertices.push_back(p0);
vertices.push_back(p1);
vertices.push_back(p2);
}
bb_min = _node->bb_min;
bb_max = _node->bb_max;
// split longest side of bounding box
Point bb = bb_max - bb_min;
Scalar length = bb[0];
axis = 0;
if (bb[1] > length)
length = bb[(axis = 1)];
if (bb[2] > length)
length = bb[(axis = 2)];
//calculate the median value in axis-direction
switch (axis) {
case 0:
vertices.sort(x_sort());
break;
case 1:
vertices.sort(y_sort());
break;
case 2:
vertices.sort(z_sort());