Commit 5d7c859f authored by Alexander Wiebel's avatar Alexander Wiebel
Browse files

[MERGE]

parents f6635196 833e6154
......@@ -24,6 +24,7 @@
#include <utility>
#include <core/common/math/WMath.h>
#include <core/graphicsEngine/WGETexture.h>
#include "WAssert.h"
#include "WHistogram2D.h"
......@@ -124,10 +125,9 @@ WGETexture2D::RPtr WHistogram2D::getTexture()
osg::ref_ptr< osg::Image > image = new osg::Image();
size_t imageWidth = m_buckets[0];
size_t imageHeight = m_buckets[1];
//get max bin for scaling
float maxCount = 0;
for( size_t j = 0; j < imageHeight; ++j )
for( size_t j = 0; j < imageHeight; ++j ) // get max bin for scaling
{
for( size_t i = 0; i < imageWidth; ++i )
{
......@@ -140,8 +140,8 @@ WGETexture2D::RPtr WHistogram2D::getTexture()
image->allocateImage( imageWidth, imageHeight, 1, GL_RED, GL_FLOAT );
image->setInternalTextureFormat( GL_RED );
float* data = reinterpret_cast< float* >( image->data() );
for( size_t j = 0; j < imageHeight; ++j )
{
for( size_t i = 0; i < imageWidth; ++i )
......@@ -152,3 +152,53 @@ WGETexture2D::RPtr WHistogram2D::getTexture()
return WGETexture2D::RPtr( new WGETexture2D( image ) );
}
/**
* Unnamed namespace for helper functions keeping the code DRY as possible.
*/
namespace
{
double calcAreaScale( const double bucket, const size_t j )
{
double theta = piDouble - ( j * bucket + ( bucket / 2.0 ) );
return 1.0 / sin( theta );
}
}
WGETexture2D::RPtr WHistogram2D::getSphereTexture()
{
osg::ref_ptr< osg::Image > image = new osg::Image();
size_t imageWidth = m_buckets[0];
size_t imageHeight = m_buckets[1];
double maxCount = 0.0;
const double bucket = piDouble / static_cast< double >( imageHeight );
double areaScale = 0.0;
for( size_t j = 0; j < imageHeight; ++j ) // get max bin for scaling
{
areaScale = calcAreaScale( bucket, j );
for( size_t i = 0; i < imageWidth; ++i )
{
if( areaScale * m_bins( i, j ) > maxCount)
{
maxCount = areaScale * static_cast< double >( m_bins( i, j ) );
}
}
}
image->allocateImage( imageWidth, imageHeight, 1, GL_RED, GL_FLOAT );
image->setInternalTextureFormat( GL_RED );
float* data = reinterpret_cast< float* >( image->data() );
for( size_t j = 0; j < imageHeight; ++j )
{
areaScale = calcAreaScale( bucket, j );
for( size_t i = 0; i < imageWidth; ++i )
{
data[i + j * imageWidth] = areaScale * static_cast< double >( m_bins( i, j ) ) / maxCount;
}
}
return WGETexture2D::RPtr( new WGETexture2D( image ) );
}
......@@ -131,6 +131,13 @@ public:
*/
WGETexture2D::RPtr getTexture();
/**
* Copy-convert this into a spherical texture. \e Spherical means hereby, that buckets representing areas near the poles have scaled counters.
*
* \return \c osg::ref_ptr to the two-dimensional spherical texture.
*/
WGETexture2D::RPtr getSphereTexture();
protected:
private:
/**
......
......@@ -103,14 +103,14 @@ void WDataSetPoints::init( bool calcBB )
float maxZ = minZ;
// go through each point
for( size_t pointIdx = 1; pointIdx < m_vertices->size(); ++pointIdx )
for( size_t pointIdx = 3; pointIdx < m_vertices->size(); pointIdx+=3 )
{
minX = std::min( m_vertices->operator[]( pointIdx * 3 + 0 ), minX );
minY = std::min( m_vertices->operator[]( pointIdx * 3 + 1 ), minY );
minZ = std::min( m_vertices->operator[]( pointIdx * 3 + 2 ), minZ );
maxX = std::max( m_vertices->operator[]( pointIdx * 3 + 0 ), maxX );
maxY = std::max( m_vertices->operator[]( pointIdx * 3 + 1 ), maxY );
maxZ = std::max( m_vertices->operator[]( pointIdx * 3 + 2 ), maxZ );
minX = std::min( m_vertices->operator[]( pointIdx + 0 ), minX );
minY = std::min( m_vertices->operator[]( pointIdx + 1 ), minY );
minZ = std::min( m_vertices->operator[]( pointIdx + 2 ), minZ );
maxX = std::max( m_vertices->operator[]( pointIdx + 0 ), maxX );
maxY = std::max( m_vertices->operator[]( pointIdx + 1 ), maxY );
maxZ = std::max( m_vertices->operator[]( pointIdx + 2 ), maxZ );
}
m_bb = WBoundingBox( minX, minY, minZ, maxX, maxY, maxZ );
......
......@@ -63,6 +63,7 @@ WTriangleMesh::WTriangleMesh( size_t vertNum, size_t triangleNum )
: m_countVerts( 0 ),
m_countTriangles( 0 ),
m_meshDirty( true ),
m_autoNormal( true ),
m_neighborsCalculated( false ),
m_curvatureCalculated( false )
{
......@@ -80,6 +81,7 @@ WTriangleMesh::WTriangleMesh( osg::ref_ptr< osg::Vec3Array > vertices, const std
: m_countVerts( vertices->size() ),
m_countTriangles( triangles.size() / 3 ),
m_meshDirty( true ),
m_autoNormal( true ),
m_neighborsCalculated( false ),
m_verts( vertices ),
m_textureCoordinates( new osg::Vec3Array( vertices->size() ) ),
......@@ -96,14 +98,19 @@ WTriangleMesh::~WTriangleMesh()
{
}
void WTriangleMesh::addVertex( float x, float y, float z )
void WTriangleMesh::setAutoRecalcNormals( bool autoRecalc )
{
addVertex( osg::Vec3( x, y, z ) );
m_autoNormal = autoRecalc;
}
void WTriangleMesh::addVertex( WPosition vert )
size_t WTriangleMesh::addVertex( float x, float y, float z )
{
addVertex( osg::Vec3( vert[0], vert[1], vert[2] ) );
return addVertex( osg::Vec3( x, y, z ) );
}
size_t WTriangleMesh::addVertex( WPosition vert )
{
return addVertex( osg::Vec3( vert[0], vert[1], vert[2] ) );
}
void WTriangleMesh::addTriangle( size_t vert0, size_t vert1, size_t vert2 )
......@@ -134,10 +141,14 @@ void WTriangleMesh::setVertexNormal( size_t index, osg::Vec3 normal )
void WTriangleMesh::setVertexNormal( size_t index, WPosition normal )
{
WAssert( index < m_countVerts, "set vertex normal: index out of range" );
setVertexNormal( index, osg::Vec3( normal[0], normal[1], normal[2] ) );
}
void WTriangleMesh::setVertexNormal( size_t index, float x, float y, float z )
{
setVertexNormal( index, osg::Vec3( x, y, z ) );
}
void WTriangleMesh::setVertexColor( size_t index, osg::Vec4 color )
{
WAssert( index < m_countVerts, "set vertex color: index out of range" );
......@@ -172,7 +183,7 @@ osg::ref_ptr< const osg::Vec3Array > WTriangleMesh::getTextureCoordinateArray()
osg::ref_ptr< osg::Vec3Array >WTriangleMesh::getVertexNormalArray( bool forceRecalc )
{
if( forceRecalc || m_meshDirty )
if( forceRecalc || ( m_meshDirty && m_autoNormal ) )
{
recalcVertNormals();
}
......@@ -181,7 +192,7 @@ osg::ref_ptr< osg::Vec3Array >WTriangleMesh::getVertexNormalArray( bool forceRec
osg::ref_ptr< osg::Vec3Array >WTriangleMesh::getTriangleNormalArray( bool forceRecalc )
{
if( forceRecalc || m_meshDirty )
if( forceRecalc || ( m_meshDirty && m_autoNormal ) )
{
recalcVertNormals();
}
......
......@@ -101,8 +101,9 @@ public:
* adds a vertex position to the mesh
*
* \param vert
* \return the index of the vertex
*/
void addVertex( osg::Vec3 vert );
size_t addVertex( osg::Vec3 vert );
/**
* adds a vertex position to the mesh
......@@ -110,15 +111,18 @@ public:
* \param x
* \param y
* \param z
*
* \return the index of the vertex
*/
void addVertex( float x, float y, float z );
size_t addVertex( float x, float y, float z );
/**
* adds a vertex position to the mesh
*
* \param vert
* \param vert vertex to add
* \return the index of the vertex
*/
void addVertex( WPosition vert );
size_t addVertex( WPosition vert );
/**
* Adds a texture coordinate for the vertex.
......@@ -170,6 +174,16 @@ public:
*/
void setVertexNormal( size_t index, osg::Vec3 normal );
/**
* sets the normal for a given vertex
*
* \param index
* \param x x coordinate
* \param y y coordinate
* \param z z coordinate
*/
void setVertexNormal( size_t index, float x, float y, float z );
/**
* sets the normal for a given vertex
*
......@@ -476,6 +490,13 @@ public:
*/
void recalcVertNormals();
/**
* Set this to true to force automatic normal calculation. Set it to false if you specify your own normals.
*
* \param autoRecalc auto normal calculation.
*/
void setAutoRecalcNormals( bool autoRecalc = true );
protected:
static boost::shared_ptr< WPrototyped > m_prototype; //!< The prototype as singleton.
private:
......@@ -718,6 +739,8 @@ private:
bool m_meshDirty; //!< flag indicating a change took place which requires a recalculation of components
bool m_autoNormal; //!< flag denoting whether normals should be calculated automatically.
bool m_neighborsCalculated; //!< flag indicating whether the neighbor information has been calculated yet
//! Indicates whether the curvature and its principal directions have been calculated.
......@@ -800,7 +823,7 @@ inline void WTriangleMesh::addTextureCoordinate( float x, float y, float z )
addTextureCoordinate( osg::Vec3( x, y, z ) );
}
inline void WTriangleMesh::addVertex( osg::Vec3 vert )
inline size_t WTriangleMesh::addVertex( osg::Vec3 vert )
{
if( ( *m_verts ).size() == m_countVerts )
{
......@@ -813,10 +836,19 @@ inline void WTriangleMesh::addVertex( osg::Vec3 vert )
if( ( *m_vertColors ).size() == m_countVerts )
{
( *m_vertColors ).resize( m_countVerts + 1 );
( *m_vertColors )[ m_countVerts ] = osg::Vec4( 1.0, 1.0, 1.0, 1.0 );
}
if( ( *m_vertNormals ).size() == m_countVerts )
{
( *m_vertNormals ).resize( m_countVerts + 1 );
}
size_t index = m_countVerts;
( *m_verts )[index] = vert;
( *m_vertNormals )[index] = osg::Vec3( 1.0, 1.0, 1.0 );
( *m_verts )[m_countVerts] = vert;
++m_countVerts;
return index;
}
inline const std::string WTriangleMesh::getName() const
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <algorithm>
#include <string>
#include <vector>
#include "core/kernel/WKernel.h"
#include "core/common/WPropertyHelper.h"
#include "core/common/math/WMath.h"
#include "core/dataHandler/WDataHandler.h"
#include "WMMeshToPoints.h"
// This line is needed by the module loader to actually find your module. You need to add this to your module too. Do NOT add a ";" here.
W_LOADABLE_MODULE( WMMeshToPoints )
WMMeshToPoints::WMMeshToPoints():
WModule()
{
}
WMMeshToPoints::~WMMeshToPoints()
{
// Cleanup!
}
boost::shared_ptr< WModule > WMMeshToPoints::factory() const
{
return boost::shared_ptr< WModule >( new WMMeshToPoints() );
}
const char** WMMeshToPoints::getXPMIcon() const
{
return NULL;
}
const std::string WMMeshToPoints::getName() const
{
return "Mesh To Points";
}
const std::string WMMeshToPoints::getDescription() const
{
return "This module converts mesh data to points by using the fiber vertex points and colors..";
}
void WMMeshToPoints::connectors()
{
// The input fiber dataset
m_meshInput = boost::shared_ptr< WModuleInputData < WTriangleMesh > >(
new WModuleInputData< WTriangleMesh >( shared_from_this(), "mesh", "The mesh dataset" )
);
// As properties, every connector needs to be added to the list of connectors.
addConnector( m_meshInput );
// the points
m_pointsOutput = boost::shared_ptr< WModuleOutputData < WDataSetPoints > >(
new WModuleOutputData< WDataSetPoints >( shared_from_this(), "out", "The point data." )
);
// As above: make it known.
addConnector( m_pointsOutput );
// call WModule's initialization
WModule::connectors();
}
void WMMeshToPoints::properties()
{
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
m_doRefinement = m_properties->addProperty( "Resample", "If enabled, the mesh is sampled more dense.", false, m_propCondition );
m_minDistance = m_properties->addProperty( "Min Distance",
"Minimal distance between two samples. If reached, iteration will stop.", 1.0,
m_propCondition );
m_maxIterations = m_properties->addProperty( "Max Iterations", "Maximum number of iterations.", 2, m_propCondition );
// call WModule's initialization
WModule::properties();
}
void refine( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3, WDataSetPoints::VertexArray points,
size_t c, const size_t& maxCount, const double& minDistance )
{
// add first verticies
if( c == 0 )
{
points->push_back( v1.x() );
points->push_back( v1.y() );
points->push_back( v1.z() );
points->push_back( v2.x() );
points->push_back( v2.y() );
points->push_back( v2.z() );
points->push_back( v3.x() );
points->push_back( v3.y() );
points->push_back( v3.z() );
}
// abort
if( c == maxCount )
{
return;
}
// get vertices in the middle of each edge
osg::Vec3 v12 = v1 + ( ( v2 - v1 ) * 0.5 );
osg::Vec3 v23 = v2 + ( ( v3 - v2 ) * 0.5 );
osg::Vec3 v31 = v3 + ( ( v1 - v3 ) * 0.5 );
bool l12 = ( ( v2 - v1 ).length() < minDistance );
bool l23 = ( ( v3 - v2 ).length() < minDistance );
bool l31 = ( ( v1 - v3 ).length() < minDistance );
if( l12 + l23 + l31 >= 2 )
{
return;
}
points->push_back( v12.x() );
points->push_back( v12.y() );
points->push_back( v12.z() );
points->push_back( v23.x() );
points->push_back( v23.y() );
points->push_back( v23.z() );
points->push_back( v31.x() );
points->push_back( v31.y() );
points->push_back( v31.z() );
// build new triangle and refine this
refine( v1, v12, v31, points, c + 1, maxCount, minDistance );
refine( v2, v23, v12, points, c + 1, maxCount, minDistance );
refine( v3, v31, v23, points, c + 1, maxCount, minDistance );
refine( v12, v23, v31, points, c + 1, maxCount, minDistance );
}
void WMMeshToPoints::moduleMain()
{
// get notified about data changes
m_moduleState.setResetable( true, true );
m_moduleState.add( m_meshInput->getDataChangedCondition() );
// Remember the condition provided to some properties in properties()? The condition can now be used with this condition set.
m_moduleState.add( m_propCondition );
ready();
// main loop
while( !m_shutdownFlag() )
{
debugLog() << "Waiting ...";
m_moduleState.wait();
// woke up since the module is requested to finish?
if( m_shutdownFlag() )
{
break;
}
// To query whether an input was updated, simply ask the input:
bool dataUpdated = m_meshInput->handledUpdate();
boost::shared_ptr< WTriangleMesh > dataSet = m_meshInput->getData();
bool dataValid = ( dataSet );
bool propsChanged = m_doRefinement->changed() || m_maxIterations->changed() || m_minDistance->changed();
// reset everything if input was disconnected/invalid
if( !dataValid )
{
debugLog() << "Resetting output.";
m_pointsOutput->reset();
continue;
}
if( dataValid && !dataUpdated && !propsChanged )
{
continue;
}
// progress indication
WProgress::SPtr progress = WProgress::SPtr( new WProgress( "Creating Points from mesh." ) );
m_progress->addSubProgress( progress );
osg::ref_ptr< osg::Vec3Array > verts = dataSet->getVertexArray();
osg::ref_ptr< osg::Vec4Array > colors = dataSet->getVertexColorArray();
std::vector< size_t > faces = dataSet->getTriangles();
debugLog() << "Creating point data. Num Points = " << verts->size() / 3 << ".";
// convert to std array
WDataSetPoints::VertexArray vecConv( new WDataSetPoints::VertexArray::element_type() );
WDataSetPoints::ColorArray colConv( new WDataSetPoints::ColorArray::element_type() );
WAssert( verts->size() == colors->size(), "Not enough colors for all vertices." );
for( size_t i = 0; i < faces.size(); i += 3 )
{
osg::Vec3 v1 = verts->operator[]( faces[ i + 0 ] );
osg::Vec3 v2 = verts->operator[]( faces[ i + 1 ] );
osg::Vec3 v3 = verts->operator[]( faces[ i + 2 ] );
refine( v1, v2, v3, vecConv, 0, m_doRefinement->get() ? m_maxIterations->get() : 0, m_minDistance->get() );
}
// TriangleMesh is implemented in a very ugly way, causing the color array to be (0,0,0,0) for each color -> invisible points.
WDataSetPoints::SPtr result( new WDataSetPoints( vecConv, WDataSetPoints::ColorArray() ) );
m_pointsOutput->updateData( result );
progress->finish();
m_progress->removeSubProgress( progress );
}
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WMMESHTOPOINTS_H
#define WMMESHTOPOINTS_H
#include <string>
#include "core/graphicsEngine/WTriangleMesh.h"
#include "core/dataHandler/WDataSetPoints.h"
#include "core/kernel/WModule.h"
#include "core/kernel/WModuleInputData.h"
#include "core/kernel/WModuleOutputData.h"
/**
* This modules takes a mesh and extracts its vertices to build a point dataset
*
* \ingroup modules
*/
class WMMeshToPoints: public WModule
{
public:
/**
* Default constructor.
*/
WMMeshToPoints();
/**
* Destructor.
*/
virtual ~WMMeshToPoints();
/**
* Gives back the name of this module.
* \return the module's name.
*/
virtual const std::string getName() const;
/**
* Gives back a description of this module.
* \return description to module.
*/
virtual const std::string getDescription() const;
/**
* Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it
* should never be initialized or modified in some other way. A simple new instance is required.
*
* \return the prototype used to create every module in OpenWalnut.
*/
virtual boost::shared_ptr< WModule > factory() const;
/**
* Get the icon for this module in XPM format.
* \return The icon.