Commit de4aaa8c authored by Jan Möbius's avatar Jan Möbius

Split data type out of node for splat clouds

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@13073 383ad7c9-94d9-4d36-a494-682f7c89f535
parent b25609e3
//================================================================
//
// CLASS SplatCloud - IMPLEMENTATION
//
//================================================================
//== INCLUDES ====================================================
#include "SplatCloud.hh"
//== IMPLEMENTATION ==============================================
void SplatCloud::normalizeSize()
{
// check if there is nothing to do
if( points_.size() == 0 )
return;
// calculate center-of-gravety
float cogX = 0.0f;
float cogY = 0.0f;
float cogZ = 0.0f;
PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
const Point &p = *pointIter;
cogX += p[0];
cogY += p[1];
cogZ += p[2];
}
float rcp_count = 1.0f / (float) points_.size();
cogX *= rcp_count;
cogY *= rcp_count;
cogZ *= rcp_count;
translation_ = Point( -cogX, -cogY, -cogZ );
translate( translation_ );
std::cout << "SplatCloud::normalizeSize(): translating points by: " << translation_ << std::endl;
// calculate squared length
float sqLength = 0.0f;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
const Point &p = *pointIter;
sqLength += p[0]*p[0] + p[1]*p[1] + p[2]*p[2];
}
float s = (float) sqrt( sqLength * rcp_count );
if( s == 0.0f )
return;
scaleFactor_ = 1.0f / s;
scale( scaleFactor_ );
std::cout << "SplatCloud::normalizeSize(): scaling points by factor: " << scaleFactor_ << std::endl;
}
//----------------------------------------------------------------
void SplatCloud::translate( const Point &_t )
{
// translate points
PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
Point &p = *pointIter;
p[0] += _t[0];
p[1] += _t[1];
p[2] += _t[2];
}
}
//----------------------------------------------------------------
void SplatCloud::scale( float _s )
{
// scale points (and pointsizes as well)
if( pointsizes_.size() == points_.size() )
{
PointsizeVector::iterator pointsizeIter = pointsizes_.begin();
PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter, ++pointsizeIter )
{
Point &p = *pointIter;
Pointsize &ps = *pointsizeIter;
p[0] *= _s;
p[1] *= _s;
p[2] *= _s;
ps *= _s; // scale pointsize as well
}
}
else
{
PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
Point &p = *pointIter;
p[0] *= _s;
p[1] *= _s;
p[2] *= _s;
}
}
}
//================================================================
//
// CLASS SplatCloud
//
// SplatCloud stores the data for a SplatCloud.
// Points, normals, point sizes and colors are internally stored as arrays.
//
//================================================================
#ifndef SPLATCLOUD_HH
#define SPLATCLOUD_HH
//== INCLUDES ====================================================
#include <ACG/Math/VectorT.hh>
#include <vector>
//== CLASS DEFINITION ============================================
/** \class SplatCloud SplatCloud.hh <ObjectTypes/SplatCloud/SplatCloud/SplatCloud.hh>
*
* Storage of points, normals, point sizes and colors for a SplatCloud.
*/
class SplatCloud
{
public:
//-- TYPEDEFS ----------------------------------------------------
typedef ACG::Vec3f Point;
typedef ACG::Vec3f Normal;
typedef float Pointsize;
typedef ACG::Vec3uc Color;
typedef std::vector<Point> PointVector;
typedef std::vector<Normal> NormalVector;
typedef std::vector<Pointsize> PointsizeVector;
typedef std::vector<Color> ColorVector;
//----------------------------------------------------------------
/// default constructor
inline SplatCloud() : translation_( Point(0.0f,0.0f,0.0f) ), scaleFactor_( 1.0f ) { }
/// copy constructor
inline SplatCloud( const SplatCloud &_splatCloud ) :
points_ ( _splatCloud.points_ ),
normals_ ( _splatCloud.normals_ ),
pointsizes_ ( _splatCloud.pointsizes_ ),
colors_ ( _splatCloud.colors_ ),
translation_( _splatCloud.translation_ ),
scaleFactor_( _splatCloud.scaleFactor_ )
{ }
// ---- data vectors ----
inline void clearPoints() { points_.clear(); }
inline void clearNormals() { normals_.clear(); }
inline void clearPointsizes() { pointsizes_.clear(); }
inline void clearColors() { colors_.clear(); }
inline void clear() { clearPoints(); clearNormals(); clearPointsizes(); clearColors(); }
inline void addPoint ( const Point &_point ) { points_.push_back ( _point ); }
inline void addNormal ( const Normal &_normal ) { normals_.push_back ( _normal ); }
inline void addPointsize( const Pointsize &_pointsize ) { pointsizes_.push_back( _pointsize ); }
inline void addColor ( const Color &_color ) { colors_.push_back ( _color ); }
inline unsigned int numPoints() const { return points_.size(); }
inline unsigned int numNormals() const { return normals_.size(); }
inline unsigned int numPointsizes() const { return pointsizes_.size(); }
inline unsigned int numColors() const { return colors_.size(); }
inline bool hasNormals() const { return normals_.size() == points_.size(); }
inline bool hasPointsizes() const { return pointsizes_.size() == points_.size(); }
inline bool hasColors() const { return colors_.size() == points_.size(); }
inline PointVector &points() { return points_; }
inline NormalVector &normals() { return normals_; }
inline PointsizeVector &pointsizes() { return pointsizes_; }
inline ColorVector &colors() { return colors_; }
inline const PointVector &points() const { return points_; }
inline const NormalVector &normals() const { return normals_; }
inline const PointsizeVector &pointsizes() const { return pointsizes_; }
inline const ColorVector &colors() const { return colors_; }
// ---- translation and scale ----
/// move center-of-gravety to origin and normalize overall size of model (points and pointsizes will be modified)
void normalizeSize();
inline const Point &translation() const { return translation_; }
inline float scaleFactor() const { return scaleFactor_; }
//----------------------------------------------------------------
private:
// ---- data vectors ----
PointVector points_;
NormalVector normals_;
PointsizeVector pointsizes_;
ColorVector colors_;
// ---- translation and scale ----
Point translation_;
float scaleFactor_;
void translate( const Point &_t );
void scale ( float _s );
};
//================================================================
#endif // SPLATCLOUD_HH
......@@ -63,13 +63,58 @@ namespace SceneGraph {
//== IMPLEMENTATION ==============================================
SplatCloudNode::SplatCloudNode( BaseNode *_parent, std::string _name ) :
BaseNode ( _parent, _name ),
defaultNormal_ ( Normal(0.0f,0.0f,1.0f) ),
defaultPointsize_( Pointsize(0.01f) ),
defaultColor_ ( Color(255,255,255) ),
pickingBaseIndex_( 0 ),
vboGlId_ ( 0 ),
vboValid_ ( false )
{
// allocate memory for splat cloud
splatCloud_ = new SplatCloud;
if( !splatCloud_ )
{
std::cerr << "SplatCloudNode::SplatCloudNode() : Out of memory." << std::endl;
}
// add (possibly) new drawmodes
pointsDrawMode_ = DrawModes::addDrawMode( "Points" );
dotsDrawMode_ = DrawModes::addDrawMode( "Dots" );
splatsDrawMode_ = DrawModes::addDrawMode( "Splats" );
// create a new vertex-buffer-object (will be invalid and rebuilt the next time drawn (or picked))
createVBO();
}
//----------------------------------------------------------------
SplatCloudNode::~SplatCloudNode()
{
destroyVBO();
delete splatCloud_;
splatCloud_ = 0;
}
//----------------------------------------------------------------
void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax )
{
// if something went wrong in the initialization, abort
if( !splatCloud_ )
return;
ACG::Vec3f bbMin( FLT_MAX, FLT_MAX, FLT_MAX );
ACG::Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX );
PointVector::const_iterator pointIter;
for ( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
SplatCloud::PointVector::const_iterator pointIter, pointsEnd = splatCloud_->points().end();
for ( pointIter = splatCloud_->points().begin(); pointIter != pointsEnd; ++pointIter )
{
const Point &p = *pointIter;
......@@ -79,11 +124,8 @@ void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax )
bbMax.maximize( acgp );
}
ACG::Vec3d bbMind = ACG::Vec3d( bbMin );
ACG::Vec3d bbMaxd = ACG::Vec3d( bbMax );
_bbMin.minimize( bbMind );
_bbMax.maximize( bbMaxd );
_bbMin.minimize( ACG::Vec3d( bbMin ) );
_bbMax.maximize( ACG::Vec3d( bbMax ) );
}
......@@ -92,6 +134,10 @@ void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax )
void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode )
{
// if something went wrong in the initialization, abort
if( !splatCloud_ )
return;
static const int RENDERMODE_POINTS = 0;
static const int RENDERMODE_DOTS = 1;
static const int RENDERMODE_SPLATS = 2;
......@@ -140,7 +186,7 @@ void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode
}
// draw as GLpoints
glDrawArrays( GL_POINTS, 0, numPoints() );
glDrawArrays( GL_POINTS, 0, splatCloud_->numPoints() );
// disable "pointsize by program" if it was enabled
if ( rendermode != RENDERMODE_POINTS )
......@@ -174,11 +220,15 @@ void SplatCloudNode::enterPick( GLState &_state, PickTarget _target, const DrawM
void SplatCloudNode::pick( GLState &_state, PickTarget _target )
{
// if something went wrong in the initialization, abort
if( !splatCloud_ )
return;
// if pick target is valid...
if( _target == PICK_ANYTHING || _target == PICK_VERTEX )
{
// set number of pick colors used (each points gets a unique pick color)
if( !_state.pick_set_maximum( numPoints() ) )
if( !_state.pick_set_maximum( splatCloud_->numPoints() ) )
{
std::cerr << "SplatCloudNode::pick() : Color range too small, picking failed." << std::endl;
return;
......@@ -201,6 +251,21 @@ void SplatCloudNode::pick( GLState &_state, PickTarget _target )
//----------------------------------------------------------------
void SplatCloudNode::copySplatCloud( const SplatCloud &_splatCloud )
{
delete splatCloud_;
splatCloud_ = new SplatCloud( _splatCloud );
if( !splatCloud_ )
{
std::cerr << "SplatCloudNode::copySplatCloud() : Out of memory." << std::endl;
}
}
//----------------------------------------------------------------
void SplatCloudNode::createVBO()
{
// create a new vertex-buffer-object if not already existing
......@@ -249,19 +314,23 @@ static void addFloatToBuffer( float _value, unsigned char *&_buffer )
void SplatCloudNode::rebuildVBO( GLState &_state )
{
// if something went wrong in the initialization, abort
if( !splatCloud_ )
return;
// check if vertex-buffer-object has already been created (and not destroyed so far)
if ( vboGlId_ == 0 )
return;
// check if there could be a valid vertex-buffer-object
if ( numPoints() == 0 )
if ( splatCloud_->numPoints() == 0 )
{
vboValid_ = false;
return;
}
// we use GL_T4F_C4F_N3F_V4F as interleaved array type, so we have 4+4+3+4 = 15 floats per splat
unsigned int size = numPoints() * 15 * sizeof(float);
unsigned int size = splatCloud_->numPoints() * 15 * sizeof(float);
// activate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
......@@ -275,10 +344,6 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
// if pointer is valid...
if ( buffer )
{
bool hasNrm = hasNormals();
bool hasPS = hasPointsizes();
bool hasCol = hasColors();
// if in color picking mode...
if( _state.color_picking() )
{
......@@ -287,7 +352,7 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
}
// for all points...
int i, num = numPoints();
int i, num = splatCloud_->numPoints();
for ( i=0; i<num; ++i )
{
static const float RCP255 = 1.0f / 255.0f;
......@@ -300,23 +365,23 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
addFloatToBuffer( RCP255 * pc[3], buffer );
// add color
const Color &c = hasCol ? colors_[i] : defaultColor_;
const Color &c = getColor( i );
addFloatToBuffer( RCP255 * c[0], buffer );
addFloatToBuffer( RCP255 * c[1], buffer );
addFloatToBuffer( RCP255 * c[2], buffer );
// add pointsize (as alpha-component of color)
const Pointsize &ps = hasPS ? pointsizes_[i] : defaultPointsize_;
const Pointsize &ps = getPointsize( i );
addFloatToBuffer( ps, buffer );
// add normal
const Normal &n = hasNrm ? normals_[i] : defaultNormal_;
const Normal &n = getNormal( i );
addFloatToBuffer( n[0], buffer );
addFloatToBuffer( n[1], buffer );
addFloatToBuffer( n[2], buffer );
// add point
const Point &p = points_[i];
const Point &p = getPoint( i );
addFloatToBuffer( p[0], buffer );
addFloatToBuffer( p[1], buffer );
addFloatToBuffer( p[2], buffer );
......@@ -335,111 +400,6 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
}
//----------------------------------------------------------------
void SplatCloudNode::normalizeSize()
{
// check if there is nothing to do
if( points_.size() == 0 )
return;
// calculate center-of-gravety
float cogX = 0.0f;
float cogY = 0.0f;
float cogZ = 0.0f;
SplatCloudNode::PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
const SplatCloudNode::Point &p = *pointIter;
cogX += p[0];
cogY += p[1];
cogZ += p[2];
}
float rcp_count = 1.0f / (float) points_.size();
cogX *= rcp_count;
cogY *= rcp_count;
cogZ *= rcp_count;
cur_translation_ = Point( -cogX, -cogY, -cogZ );
translate( cur_translation_ );
std::cout << "SplatCloudNode::normalizeSize(): translate points by: " << cur_translation_ << std::endl;
// calculate squared length
float sqLength = 0.0f;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
SplatCloudNode::Point &p = *pointIter;
sqLength += p[0]*p[0] + p[1]*p[1] + p[2]*p[2];
}
float s = (float) sqrt( sqLength * rcp_count );
if( s == 0.0f )
return;
cur_scale_factor_ = 1.0f / s;
scale( cur_scale_factor_ );
std::cout << "SplatCloudNode::normalizeSize(): scaling points with factor: " << cur_scale_factor_ << std::endl;
}
//----------------------------------------------------------------
void SplatCloudNode::translate( const Point &_t )
{
// translate points
SplatCloudNode::PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
SplatCloudNode::Point &p = *pointIter;
p[0] += _t[0];
p[1] += _t[1];
p[2] += _t[2];
}
}
//----------------------------------------------------------------
void SplatCloudNode::scale( float _s )
{
// scale points (and pointsizes as well)
if( pointsizes_.size() == points_.size() )
{
SplatCloudNode::PointsizeVector::iterator pointsizeIter = pointsizes_.begin();
SplatCloudNode::PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter, ++pointsizeIter )
{
SplatCloudNode::Point &p = *pointIter;
SplatCloudNode::Pointsize &ps = *pointsizeIter;
p[0] *= _s;
p[1] *= _s;
p[2] *= _s;
ps *= _s; // scale pointsize as well
}
}
else
{
SplatCloudNode::PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
SplatCloudNode::Point &p = *pointIter;
p[0] *= _s;
p[1] *= _s;
p[2] *= _s;
}
}
}
//================================================================
......
......@@ -44,9 +44,9 @@
//
// CLASS SplatCloudNode
//
// SplatCloudNode renders splats by passing points, normals, point sizes and colors to the GL.
// These elements are internally stored in arrays and rendered using OpenGL vertex, normal,
// texcoord and color arrays.
// SplatCloudNode renders splats by passing points, normals, point sizes and colors (and picking colors) to the GL.
// These elements are internally stored in an interleaved array using an OpenGL vertex-buffer-object
// including vertices, normals, texcoords and colors.
//
//================================================================
......@@ -58,6 +58,8 @@
//== INCLUDES ====================================================
#include "SplatCloud/SplatCloud.hh"
#include <OpenFlipper/common/GlobalDefines.hh>
#include <ACG/Scenegraph/BaseNode.hh>
......@@ -66,8 +68,6 @@
#include <ACG/GL/gl.hh>
#include <vector>
//== NAMESPACES ==================================================
......@@ -86,45 +86,24 @@ namespace SceneGraph {
class DLLEXPORT SplatCloudNode : public BaseNode
{
public:
private:
//-- TYPEDEFS ----------------------------------------------------
typedef ACG::Vec3f Point;
typedef ACG::Vec3f Normal;
typedef float Pointsize;
typedef ACG::Vec3uc Color;
typedef std::vector<Point> PointVector;
typedef std::vector<Normal> NormalVector;
typedef std::vector<Pointsize> PointsizeVector;
typedef std::vector<Color> ColorVector;
typedef SplatCloud::Point Point;
typedef SplatCloud::Normal Normal;
typedef SplatCloud::Pointsize Pointsize;
typedef SplatCloud::Color Color;
//----------------------------------------------------------------
/// Constructor
SplatCloudNode( BaseNode *_parent = 0, std::string _name = "<SplatCloudNode>" ) :
BaseNode ( _parent, _name ),
pickingBaseIndex_( 0 ),
cur_translation_ ( Point(0.0f,0.0f,0.0f) ),
cur_scale_factor_( 1.0f ),
defaultNormal_ ( Normal(0.0f,0.0f,1.0f) ),
defaultPointsize_( 0.01f ),
defaultColor_ ( Color(255,255,255) ),
vboGlId_ ( 0 ),
vboValid_ ( false )
{
// add (possibly) new drawmodes
pointsDrawMode_ = DrawModes::addDrawMode( "Points" );
dotsDrawMode_ = DrawModes::addDrawMode( "Dots" );
splatsDrawMode_ = DrawModes::addDrawMode( "Splats" );
// create a new vertex-buffer-object (will be invalid and rebuilt the next time drawn (or picked))
createVBO();
}
public:
/// constructor
SplatCloudNode( BaseNode *_parent = 0, std::string _name = "<SplatCloudNode>" );
/// Destructor
~SplatCloudNode() { destroyVBO(); }
/// destructor
~SplatCloudNode();
ACG_CLASSNAME( SplatCloudNode );
......@@ -143,91 +122,56 @@ public:
void enterPick( GLState &_state, PickTarget _target, const DrawModes::DrawMode &_drawMode );
void pick( GLState &_state, PickTarget _target );
// ---- data vectors ----
// ---- splat cloud ----
inline void clearPoints() { points_.clear(); }
inline void clearNormals() { normals_.clear(); }
inline void clearPointsizes() { pointsizes_.clear(); }
inline void clearColors() { colors_.clear(); }
void copySplatCloud( const SplatCloud &_splatCloud );
inline void clear() { clearPoints(); clearNormals(); clearPointsizes(); clearColors(); }
inline void addPoint ( const Point &_point ) { points_.push_back ( _point ); }
inline void addNormal ( const Normal &_normal ) { normals_.push_back ( _normal ); }
inline void addPointsize( const Pointsize &_pointsize ) { pointsizes_.push_back( _pointsize ); }
inline void addColor ( const Color &_color ) { colors_.push_back ( _color ); }
inline unsigned int numPoints() const { return points_.size(); }
inline unsigned int numNormals() const { return normals_.size(); }
inline unsigned int numPointsizes() const { return pointsizes_.size(); }
inline unsigned int numColors() const { return colors_.size(); }
inline bool hasNormals() const { return normals_.size() == points_.size(); }
inline bool hasPointsizes() const { return pointsizes_.size() == points_.size(); }
inline bool hasColors() const { return colors_.size() == points_.size(); }
inline PointVector &points() { return points_; }
inline NormalVector &normals() { return normals_; }
inline PointsizeVector &pointsizes() { return pointsizes_; }
inline ColorVector &colors() { return colors_; }
inline const PointVector &points() const { return points_; }
inline const NormalVector &normals() const { return normals_; }
inline const PointsizeVector &pointsizes() const { return pointsizes_; }
inline const ColorVector &colors() const { return colors_; }
inline SplatCloud *splatCloud() { return splatCloud_; }
inline const SplatCloud *splatCloud() const { return splatCloud_; }
// ---- default values ----
// if an array is not present, changing the default value for this array will make the VBO invalid and trigger a rebuild()
inline void setDefaultNormal ( const Normal &_normal ) { defaultNormal_ = _normal; if( !hasNormals() ) vboValid_ = false; }
inline void setDefaultPointsize( const Pointsize &_pointsize ) { defaultPointsize_ = _pointsize; if( !hasPointsizes() ) vboValid_ = false; }
inline void setDefaultColor ( const Color &_color ) { defaultColor_ = _color; if( !hasColors() ) vboValid_ = false; }
inline void setDefaultNormal ( const Normal &_normal ) { defaultNormal_ = _normal; if( splatCloud_ && !splatCloud_->hasNormals() ) vboValid_ = false; }
inline void setDefaultPointsize( const Pointsize &_pointsize ) { defaultPointsize_ = _pointsize; if( splatCloud_ && !splatCloud_->hasPointsizes() ) vboValid_ = false; }
inline void setDefaultColor ( const Color &_color ) { defaultColor_ = _color; if( splatCloud_ && !splatCloud_->hasColors() ) vboValid_ = false; }
inline const Normal &defaultNormal() const { return defaultNormal_; }
inline const Pointsize &defaultPointsize() const { return defaultPointsize_; }
inline const Color &defaultColor() const { return defaultColor_; }
// if the point, normal, pointsize or color with the given _index exists it is returned, otherwise the default value is returned (check for splatCloud_ != 0 first)
inline Point getPoint ( unsigned int _index ) const { return splatCloud_->points() [ _index ] ; }
inline Normal getNormal ( unsigned int _index ) const { return splatCloud_->hasNormals() ? splatCloud_->normals() [ _index ] : defaultNormal_ ; }