Commit 9872743e authored by schultezub's avatar schultezub
Browse files

implemented clipping of face/mesh geometry against plane

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@278 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent d5500750
......@@ -32,6 +32,7 @@
#include "tgt/logmanager.h"
#include "tgt/buffer.h"
#include "tgt/vertexarrayobject.h"
#include "tgt/vertex.h"
namespace TUMVis {
......@@ -142,4 +143,69 @@ namespace TUMVis {
}
}
namespace {
float distanceToPlane(const tgt::vec3& vertex, float p, const tgt::vec3& pNormal, float epsilon) {
float distance = tgt::dot(pNormal, vertex) - p;
if (std::abs(distance) <= epsilon)
return 0;
else
return distance;
}
}
TUMVis::FaceGeometry FaceGeometry::clipAgainstPlane(float p, const tgt::vec3& pNormal, float epsilon /*= 1e-8f*/) const {
tgtAssert(epsilon >= 0, "Epsilon must be positive.");
std::vector<tgt::vec3> verts, texCoords, norms;
std::vector<tgt::vec4> cols;
size_t lastIndex = _vertices.size() - 1;
float lastDistance = distanceToPlane(_vertices.back(), p, pNormal, epsilon);
// Implementation of Sutherland-Hodgman polygon clipping:
for (size_t i = 0; i < _vertices.size(); ++i) {
float currrentDistance = distanceToPlane(_vertices[i], p, pNormal, epsilon);
// case 1: last vertex outside, this vertex inside clip region => clip
if (lastDistance > 0 && currrentDistance <= 0) {
float t = lastDistance / (lastDistance - currrentDistance);
verts.push_back(tgt::mix(_vertices[lastIndex], _vertices[i], t));
if (!_textureCoordinates.empty())
texCoords.push_back(tgt::mix(_textureCoordinates[lastIndex], _textureCoordinates[i], t));
if (!_colors.empty())
cols.push_back(tgt::mix(_colors[lastIndex], _colors[i], t));
if (!_normals.empty())
norms.push_back(tgt::mix(_normals[lastIndex], _normals[i], t));
}
// case 2: last vertex inside, this vertex outside clip region => clip
else if (lastDistance <= 0 && currrentDistance > 0) {
float t = lastDistance / (lastDistance - currrentDistance);
verts.push_back(tgt::mix(_vertices[lastIndex], _vertices[i], t));
if (!_textureCoordinates.empty())
texCoords.push_back(tgt::mix(_textureCoordinates[lastIndex], _textureCoordinates[i], t));
if (!_colors.empty())
cols.push_back(tgt::mix(_colors[lastIndex], _colors[i], t));
if (!_normals.empty())
norms.push_back(tgt::mix(_normals[lastIndex], _normals[i], t));
}
// case 1.2 + case 3: current vertix in front of plane => keep
if (currrentDistance <= 0) {
verts.push_back(_vertices[i]);
if (!_textureCoordinates.empty())
texCoords.push_back(_textureCoordinates[i]);
if (!_colors.empty())
cols.push_back(_colors[i]);
if (!_normals.empty())
norms.push_back(_normals[i]);
}
lastIndex = i;
lastDistance = currrentDistance;
}
return FaceGeometry(verts, texCoords, cols, norms);
}
}
\ No newline at end of file
......@@ -108,6 +108,16 @@ namespace TUMVis {
*/
const tgt::vec3& getFaceNormal() const;
/**
* Clips this FaceGeometry against an aribtrary clip plane.
* The clipped FaceGeometry is returned.
* \param p Point on clip plane
* \param normal Clip plane normal
* \param epsilon Clipping precision
* \return The clipped FaceGeometry
*/
FaceGeometry clipAgainstPlane(float p, const tgt::vec3& normal, float epsilon = 1e-4f) const;
/**
* Renders this FaceGeometry.
* Must be called from a valid OpenGL context.
......
......@@ -33,6 +33,10 @@
#include "tgt/buffer.h"
#include "tgt/vertexarrayobject.h"
#include <algorithm>
#include <list>
#include <utility>
namespace TUMVis {
const std::string MeshGeometry::loggerCat_ = "TUMVis.core.datastructures.MeshGeometry";
......@@ -137,6 +141,8 @@ namespace TUMVis {
size_t startIndex = 0;
for (std::vector<FaceGeometry>::const_iterator it = _faces.begin(); it != _faces.end(); ++it) {
size_t numVertices = it->getVertices().size();
if (numVertices == 0)
continue;
_verticesBuffer->subdata(startIndex * sizeof(tgt::vec3), &(it->getVertices().front()), numVertices * sizeof(tgt::vec3));
......@@ -162,7 +168,7 @@ namespace TUMVis {
}
}
TUMVis::MeshGeometry* MeshGeometry::createCube(const tgt::Bounds& bounds, const tgt::Bounds& texBounds) {
TUMVis::MeshGeometry MeshGeometry::createCube(const tgt::Bounds& bounds, const tgt::Bounds& texBounds) {
const tgt::vec3& llf = bounds.getLLF();
const tgt::vec3& urb = bounds.getURB();
const tgt::vec3& tLlf = texBounds.getLLF();
......@@ -250,7 +256,120 @@ namespace TUMVis {
vertices.clear();
texCoords.clear();
return new MeshGeometry(faces);
return MeshGeometry(faces);
}
namespace {
float distanceToPlane(const tgt::vec3& vertex, float p, const tgt::vec3& pNormal, float epsilon) {
float distance = tgt::dot(pNormal, vertex) - p;
if (std::abs(distance) <= epsilon)
return 0;
else
return distance;
}
struct VertexComparerEquals {
VertexComparerEquals(const std::vector<FaceGeometry>& ref, float epsilon)
: _ref(ref)
, _epsilon(epsilon)
{
};
bool operator() (const std::pair<size_t, size_t>& left, const std::pair<size_t, size_t>& right) const {
return (tgt::distance(_ref[left.first].getVertices()[left.second], _ref[right.first].getVertices()[right.second]) < _epsilon);
};
const tgt::vec3& operator() (const std::pair<size_t, size_t>& index) const {
return _ref[index.first].getVertices()[index.second];
}
const std::vector<FaceGeometry>& _ref;
float _epsilon;
};
}
MeshGeometry MeshGeometry::clipAgainstPlane(float p, const tgt::vec3& normal, bool close /*= true*/, float epsilon /*= 1e-8f*/) const {
std::vector<FaceGeometry> tmp;
for (std::vector<FaceGeometry>::const_iterator it = _faces.begin(); it != _faces.end(); ++it) {
FaceGeometry f = it->clipAgainstPlane(p, normal, epsilon);
if (f.size() > 0)
tmp.push_back(f);
}
if (close) {
typedef std::pair<size_t, size_t> Vertex;
std::list< std::pair<Vertex, Vertex> > unsortedEdges;
std::list< Vertex > sortedVertices;
// find all edges lying on clip plane
for (size_t i = 0; i < tmp.size(); ++i) {
const FaceGeometry& f = tmp[i];
for (size_t j = 0; j < f.size(); ++j) {
if ( distanceToPlane(f.getVertices()[j], p, normal, epsilon) == 0
&& distanceToPlane(f.getVertices()[(j+1) % f.size()], p, normal, epsilon) == 0)
{
unsortedEdges.push_back(std::make_pair(std::make_pair(i, j), std::make_pair(i, (j+1) % f.size())));
++j;
}
}
}
if (! unsortedEdges.empty()) {
// sort edges into sortedVertices list
VertexComparerEquals vce(tmp, epsilon);
sortedVertices.push_back(unsortedEdges.front().second);
unsortedEdges.pop_front();
while (! unsortedEdges.empty()) {
bool didWork = false;
// look for the edge that has one vertex in common with the last added sorted vertex
for (std::list< std::pair<Vertex, Vertex> >::iterator it = unsortedEdges.begin(); it != unsortedEdges.end(); ++it) {
if (vce(sortedVertices.back(), it->first)) {
sortedVertices.push_back(it->second);
unsortedEdges.erase(it);
didWork = true;
break;
}
if (vce(sortedVertices.back(), it->second)) {
sortedVertices.push_back(it->first);
unsortedEdges.erase(it);
didWork = true;
break;
}
}
// emergency break...
if (! didWork)
break;
}
if (sortedVertices.size() > 2) {
// make face ccw
tgt::vec3 closingFaceNormal = tgt::normalize(tgt::cross(vce(sortedVertices.front()), vce(*(++sortedVertices.begin()))));
if (tgt::dot(normal, closingFaceNormal) < 0)
std::reverse(sortedVertices.begin(), sortedVertices.end());
}
// build face
std::vector<tgt::vec3> verts, texCoords, norms;
std::vector<tgt::vec4> cols;
for (std::list< Vertex >::iterator it = sortedVertices.begin(); it != sortedVertices.end(); ++it) {
verts.push_back(tmp[it->first].getVertices()[it->second]);
if (! tmp[it->first].getTextureCoordinates().empty())
texCoords.push_back(tmp[it->first].getTextureCoordinates()[it->second]);
if (! tmp[it->first].getColors().empty())
cols.push_back(tmp[it->first].getColors()[it->second]);
if (! tmp[it->first].getNormals().empty())
norms.push_back(tmp[it->first].getNormals()[it->second]);
}
tmp.push_back(FaceGeometry(verts, texCoords, cols, norms));
}
}
return MeshGeometry(tmp);
}
}
\ No newline at end of file
......@@ -72,6 +72,16 @@ namespace TUMVis {
*/
const std::vector<FaceGeometry>& getFaces() const;
/**
* Clips this MeshGeometry against an aribtrary clip plane.
* The clipped MeshGeometry is returned.
* \param p Point on clip plane
* \param normal Clip plane normal
* \param epsilon Clipping precision
* \return The clipped MeshGeometry
*/
MeshGeometry clipAgainstPlane(float p, const tgt::vec3& normal, bool close = true, float epsilon = 1e-8f) const;
/**
* Renders this MeshGeometry.
* Must be called from a valid OpenGL context.
......@@ -91,7 +101,7 @@ namespace TUMVis {
* \param texBounds texture coordinates at the cube bounds
* \return A MeshGeometry building a cube with the given bounds and texture coordinates
*/
static MeshGeometry* createCube(const tgt::Bounds& bounds, const tgt::Bounds& texBounds);
static MeshGeometry createCube(const tgt::Bounds& bounds, const tgt::Bounds& texBounds);
protected:
......
......@@ -102,10 +102,6 @@ namespace TUMVis {
_canvas,
new CallMemberFunc1ArgJob<VisualizationPipeline, AbstractProcessor*>(this, &VisualizationPipeline::executeProcessor, processor),
OpenGLJobProcessor::SerialJob);
/*tgt::GLContextScopedLock lock(_canvas->getContext());
executeProcessor(processor);
glFinish(); // TODO: is glFlush enough or do we need a glFinish here?
LGL_ERROR;*/
}
void VisualizationPipeline::setCanvas(tgt::GLCanvas* canvas) {
......
......@@ -35,7 +35,7 @@
#include "core/datastructures/imagedatagl.h"
#include "core/datastructures/imagedatarendertarget.h"
#include "core/datastructures/geometrydata.h"
#include "core/datastructures/meshgeometry.h"
namespace TUMVis {
const std::string EEPGenerator::loggerCat_ = "TUMVis.modules.vis.EEPGenerator";
......@@ -72,7 +72,7 @@ namespace TUMVis {
void EEPGenerator::process(DataContainer& data) {
DataContainer::ScopedTypedData<ImageDataGL> img(data, _sourceImageID.getValue());
DataContainer::ScopedTypedData<GeometryData> proxyGeometry(data, _geometryID.getValue());
DataContainer::ScopedTypedData<MeshGeometry> proxyGeometry(data, _geometryID.getValue());
if (img != 0 && proxyGeometry != 0) {
if (img->getDimensionality() == 3) {
......@@ -80,6 +80,8 @@ namespace TUMVis {
tgt::Bounds volumeExtent = img->getWorldBounds();
tgt::Bounds textureBounds(tgt::vec3(0.f), tgt::vec3(1.f));
//MeshGeometry clipped = proxyGeometry->clipAgainstPlane(100, tgt::vec3(1.f), true);
// set modelview and projection matrices
glPushAttrib(GL_ALL_ATTRIB_BITS);
......
......@@ -82,7 +82,7 @@ namespace TUMVis {
tgt::vec3 texURB(static_cast<float>(_clipX.getValue().y), static_cast<float>(_clipY.getValue().y), static_cast<float>(_clipZ.getValue().y));
texURB /= numSlices;
MeshGeometry* cube = MeshGeometry::createCube(volumeExtent, tgt::Bounds(texLLF, texURB));
MeshGeometry* cube = MeshGeometry::createCube(volumeExtent, tgt::Bounds(texLLF, texURB)).clone();
data.addData(_geometryID.getValue(), cube);
}
else {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment