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

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 { ...@@ -63,13 +63,58 @@ namespace SceneGraph {
//== IMPLEMENTATION ============================================== //== 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 ) 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 bbMin( FLT_MAX, FLT_MAX, FLT_MAX );
ACG::Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX ); ACG::Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX );
PointVector::const_iterator pointIter; SplatCloud::PointVector::const_iterator pointIter, pointsEnd = splatCloud_->points().end();
for ( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter ) for ( pointIter = splatCloud_->points().begin(); pointIter != pointsEnd; ++pointIter )
{ {
const Point &p = *pointIter; const Point &p = *pointIter;
...@@ -79,11 +124,8 @@ void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax ) ...@@ -79,11 +124,8 @@ void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax )
bbMax.maximize( acgp ); bbMax.maximize( acgp );
} }
ACG::Vec3d bbMind = ACG::Vec3d( bbMin ); _bbMin.minimize( ACG::Vec3d( bbMin ) );
ACG::Vec3d bbMaxd = ACG::Vec3d( bbMax ); _bbMax.maximize( ACG::Vec3d( bbMax ) );
_bbMin.minimize( bbMind );
_bbMax.maximize( bbMaxd );
} }
...@@ -92,6 +134,10 @@ void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, 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 ) 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_POINTS = 0;
static const int RENDERMODE_DOTS = 1; static const int RENDERMODE_DOTS = 1;
static const int RENDERMODE_SPLATS = 2; static const int RENDERMODE_SPLATS = 2;
...@@ -140,7 +186,7 @@ void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode ...@@ -140,7 +186,7 @@ void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode
} }
// draw as GLpoints // draw as GLpoints
glDrawArrays( GL_POINTS, 0, numPoints() ); glDrawArrays( GL_POINTS, 0, splatCloud_->numPoints() );
// disable "pointsize by program" if it was enabled // disable "pointsize by program" if it was enabled
if ( rendermode != RENDERMODE_POINTS ) if ( rendermode != RENDERMODE_POINTS )
...@@ -174,11 +220,15 @@ void SplatCloudNode::enterPick( GLState &_state, PickTarget _target, const DrawM ...@@ -174,11 +220,15 @@ void SplatCloudNode::enterPick( GLState &_state, PickTarget _target, const DrawM
void SplatCloudNode::pick( GLState &_state, PickTarget _target ) void SplatCloudNode::pick( GLState &_state, PickTarget _target )
{ {
// if something went wrong in the initialization, abort
if( !splatCloud_ )
return;
// if pick target is valid... // if pick target is valid...
if( _target == PICK_ANYTHING || _target == PICK_VERTEX ) if( _target == PICK_ANYTHING || _target == PICK_VERTEX )
{ {
// set number of pick colors used (each points gets a unique pick color) // 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; std::cerr << "SplatCloudNode::pick() : Color range too small, picking failed." << std::endl;
return; return;
...@@ -201,6 +251,21 @@ void SplatCloudNode::pick( GLState &_state, PickTarget _target ) ...@@ -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() void SplatCloudNode::createVBO()
{ {
// create a new vertex-buffer-object if not already existing // create a new vertex-buffer-object if not already existing
...@@ -249,19 +314,23 @@ static void addFloatToBuffer( float _value, unsigned char *&_buffer ) ...@@ -249,19 +314,23 @@ static void addFloatToBuffer( float _value, unsigned char *&_buffer )
void SplatCloudNode::rebuildVBO( GLState &_state ) 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) // check if vertex-buffer-object has already been created (and not destroyed so far)
if ( vboGlId_ == 0 ) if ( vboGlId_ == 0 )
return; return;
// check if there could be a valid vertex-buffer-object // check if there could be a valid vertex-buffer-object
if ( numPoints() == 0 ) if ( splatCloud_->numPoints() == 0 )
{ {
vboValid_ = false; vboValid_ = false;
return; return;
} }
// we use GL_T4F_C4F_N3F_V4F as interleaved array type, so we have 4+4+3+4 = 15 floats per splat // 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 // activate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ ); ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
...@@ -275,10 +344,6 @@ void SplatCloudNode::rebuildVBO( GLState &_state ) ...@@ -275,10 +344,6 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
// if pointer is valid... // if pointer is valid...
if ( buffer ) if ( buffer )
{ {
bool hasNrm = hasNormals();
bool hasPS = hasPointsizes();
bool hasCol = hasColors();
// if in color picking mode... // if in color picking mode...
if( _state.color_picking() ) if( _state.color_picking() )
{ {
...@@ -287,7 +352,7 @@ void SplatCloudNode::rebuildVBO( GLState &_state ) ...@@ -287,7 +352,7 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
} }
// for all points... // for all points...
int i, num = numPoints(); int i, num = splatCloud_->numPoints();
for ( i=0; i<num; ++i ) for ( i=0; i<num; ++i )
{ {
static const float RCP255 = 1.0f / 255.0f; static const float RCP255 = 1.0f / 255.0f;
...@@ -300,23 +365,23 @@ void SplatCloudNode::rebuildVBO( GLState &_state ) ...@@ -300,23 +365,23 @@ void SplatCloudNode::rebuildVBO( GLState &_state )
addFloatToBuffer( RCP255 * pc[3], buffer ); addFloatToBuffer( RCP255 * pc[3], buffer );
// add color // add color
const Color &c = hasCol ? colors_[i] : defaultColor_; const Color &c = getColor( i );
addFloatToBuffer( RCP255 * c[0], buffer ); addFloatToBuffer( RCP255 * c[0], buffer );
addFloatToBuffer( RCP255 * c[1], buffer ); addFloatToBuffer( RCP255 * c[1], buffer );
addFloatToBuffer( RCP255 * c[2], buffer ); addFloatToBuffer( RCP255 * c[2], buffer );
// add pointsize (as alpha-component of color) // add pointsize (as alpha-component of color)
const Pointsize &ps = hasPS ? pointsizes_[i] : defaultPointsize_; const Pointsize &ps = getPointsize( i );
addFloatToBuffer( ps, buffer ); addFloatToBuffer( ps, buffer );
// add normal // add normal
const Normal &n = hasNrm ? normals_[i] : defaultNormal_; const Normal &n = getNormal( i );
addFloatToBuffer( n[0], buffer ); addFloatToBuffer( n[0], buffer );
addFloatToBuffer( n[1], buffer ); addFloatToBuffer( n[1], buffer );
addFloatToBuffer( n[2], buffer ); addFloatToBuffer( n[2], buffer );
// add point // add point
const Point &p = points_[i]; const Point &p = getPoint( i );
addFloatToBuffer( p[0], buffer ); addFloatToBuffer( p[0], buffer );
addFloatToBuffer( p[1], buffer ); addFloatToBuffer( p[1], buffer );
addFloatToBuffer( p[2], buffer ); addFloatToBuffer( p[2], buffer );
...@@ -335,111 +400,6 @@ void SplatCloudNode::rebuildVBO( GLState &_state ) ...@@ -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() )