Commit 355d5a6d authored by Dominik Sibbing's avatar Dominik Sibbing
Browse files

Simple Picking, undo scale and translate when writing file to hd

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@13009 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 74be0a5d
......@@ -65,25 +65,25 @@ namespace SceneGraph {
void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax )
{
ACG::Vec3f bbMin( FLT_MAX, FLT_MAX, FLT_MAX );
ACG::Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX );
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 )
{
const Point &p = *pointIter;
PointVector::const_iterator pointIter;
for ( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
const Point &p = *pointIter;
ACG::Vec3f acgp( p[0], p[1], p[2] );
ACG::Vec3f acgp( p[0], p[1], p[2] );
bbMin.minimize( acgp );
bbMax.maximize( acgp );
}
bbMin.minimize( acgp );
bbMax.maximize( acgp );
}
ACG::Vec3d bbMind = ACG::Vec3d( bbMin );
ACG::Vec3d bbMaxd = ACG::Vec3d( bbMax );
ACG::Vec3d bbMind = ACG::Vec3d( bbMin );
ACG::Vec3d bbMaxd = ACG::Vec3d( bbMax );
_bbMin.minimize( bbMind );
_bbMax.maximize( bbMaxd );
_bbMin.minimize( bbMind );
_bbMax.maximize( bbMaxd );
}
......@@ -92,69 +92,69 @@ void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax )
void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode )
{
static const int RENDERMODE_POINTS = 0;
static const int RENDERMODE_DOTS = 1;
static const int RENDERMODE_SPLATS = 2;
// check if drawmode is valid
int rendermode;
if( _drawMode.containsAtomicDrawMode( splatsDrawMode_ ) )
rendermode = RENDERMODE_SPLATS;
else if( _drawMode.containsAtomicDrawMode( dotsDrawMode_ ) )
rendermode = RENDERMODE_DOTS;
else if( _drawMode.containsAtomicDrawMode( pointsDrawMode_ ) )
rendermode = RENDERMODE_POINTS;
else
return;
// set desired depth function
ACG::GLState::depthFunc( _state.depthFunc() );
// is vertex-buffer-object is invalid then rebuild
if( !vboValid_ )
rebuildVBO();
// if vertex-buffer-object is valid now...
// (if not it will be rebuilt the next time, but this should not happen)
if( vboValid_ )
{
// activate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
// tell GL where our data is (NULL = beginning of vertex-buffer-object)
glInterleavedArrays( GL_C4F_N3F_V3F, 0, 0 );
// arrays are automatically enabled by glInterleavedArrays()
//glEnableClientState( GL_VERTEX_ARRAY );
//glEnableClientState( GL_NORMAL_ARRAY );
//glEnableClientState( GL_COLOR_ARRAY );
// Normals are always needed for backface culling, even in drawmode 'Points'!
// Colors are always needed for pointsizes, even in color picking mode!
// enable "pointsize by program" depending on current rendermode
if( rendermode != RENDERMODE_POINTS )
{
ACG::GLState::enable( GL_VERTEX_PROGRAM_POINT_SIZE );
}
// draw as GLpoints
glDrawArrays( GL_POINTS, 0, numPoints() );
// disable "pointsize by program" if it was enabled
if( rendermode != RENDERMODE_POINTS )
{
ACG::GLState::disable( GL_VERTEX_PROGRAM_POINT_SIZE );
}
// disable arrays
ACG::GLState::disableClientState( GL_VERTEX_ARRAY );
ACG::GLState::disableClientState( GL_NORMAL_ARRAY );
ACG::GLState::disableClientState( GL_COLOR_ARRAY );
// deactivate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
}
static const int RENDERMODE_POINTS = 0;
static const int RENDERMODE_DOTS = 1;
static const int RENDERMODE_SPLATS = 2;
// check if drawmode is valid
int rendermode;
if ( _drawMode.containsAtomicDrawMode( splatsDrawMode_ ) )
rendermode = RENDERMODE_SPLATS;
else if ( _drawMode.containsAtomicDrawMode( dotsDrawMode_ ) )
rendermode = RENDERMODE_DOTS;
else if ( _drawMode.containsAtomicDrawMode( pointsDrawMode_ ) )
rendermode = RENDERMODE_POINTS;
else
return;
// set desired depth function
ACG::GLState::depthFunc( _state.depthFunc() );
// is vertex-buffer-object is invalid then rebuild
if ( !vboValid_ )
rebuildVBO();
// if vertex-buffer-object is valid now...
// (if not it will be rebuilt the next time, but this should not happen)
if ( vboValid_ )
{
// activate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
// tell GL where our data is (NULL = beginning of vertex-buffer-object)
glInterleavedArrays( GL_C4F_N3F_V3F, 0, 0 );
// arrays are automatically enabled by glInterleavedArrays()
//glEnableClientState( GL_VERTEX_ARRAY );
//glEnableClientState( GL_NORMAL_ARRAY );
//glEnableClientState( GL_COLOR_ARRAY );
// Normals are always needed for backface culling, even in drawmode 'Points'!
// Colors are always needed for pointsizes, even in color picking mode!
// enable "pointsize by program" depending on current rendermode
if ( rendermode != RENDERMODE_POINTS )
{
ACG::GLState::enable( GL_VERTEX_PROGRAM_POINT_SIZE );
}
// draw as GLpoints
glDrawArrays( GL_POINTS, 0, numPoints() );
// disable "pointsize by program" if it was enabled
if ( rendermode != RENDERMODE_POINTS )
{
ACG::GLState::disable( GL_VERTEX_PROGRAM_POINT_SIZE );
}
// disable arrays
ACG::GLState::disableClientState( GL_VERTEX_ARRAY );
ACG::GLState::disableClientState( GL_NORMAL_ARRAY );
ACG::GLState::disableClientState( GL_COLOR_ARRAY );
// deactivate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
}
}
......@@ -164,43 +164,98 @@ void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode
// TODO: hack, because pick() doesn't get a drawmode
static DrawModes::DrawMode g_pickDrawMode;
void SplatCloudNode::enterPick( GLState &_state, PickTarget _target, const DrawModes::DrawMode &_drawMode )
{ g_pickDrawMode = _drawMode; }
{
g_pickDrawMode = _drawMode;
}
// ----
void SplatCloudNode::pick( GLState &_state, PickTarget _target )
{
if( !_state.pick_set_maximum( 1 ) )
return;
// if ( !_state.pick_set_maximum( points_.size() ) )
// return;
if( _target == PICK_ANYTHING )
{
// change GL's primary color according to pick name
_state.pick_set_name( 0 );
if ( _target == PICK_ANYTHING || _target == PICK_VERTEX )
{
// change GL's primary color according to pick name
// _state.pick_set_name( 0 );
// Copy GL's primary color to texture coordinate, which will be outputted by the picking shader as color.
// This enables us to use RGBA instead of just RGB as it is the case when using GL's secondary color.
GLfloat color[4];
glGetFloatv( GL_CURRENT_COLOR, color );
glTexCoord4fv( color );
// Copy GL's primary color to texture coordinate, which will be outputted by the picking shader as color.
// This enables us to use RGBA instead of just RGB as it is the case when using GL's secondary color.
// GLfloat color[4];
// glGetFloatv( GL_CURRENT_COLOR, color );
// glTexCoord4fv( color );
// TODO: see above ( enterPick() )
draw( _state, g_pickDrawMode );
// TODO: see above ( enterPick() )
// draw( _state, g_pickDrawMode );
}
draw_pick( _state );
}
}
//----------------------------------------------------------------
void
SplatCloudNode::
draw_pick( GLState &_state )
{
_state.pick_set_maximum(points_.size());
for ( unsigned int i = 0; i < points_.size(); ++i )
{
_state.pick_set_name(i);
glBegin(GL_POINTS);
glVertex3f( float(points_[i][0] ),float(points_[i][1] ),float(points_[i][2] ) );
glEnd();
}
/*
if (!_state.pick_set_maximum (points_.size()))
{
std::cerr << "Splat Node::draw_pick: color range too small, " << "picking failed\n";
return;
}
if ( updateVertexPicking_ || _state.pick_current_index () != vertexPickingBaseIndex_) {
pick_colors_.clear();
pick_colors_.reserve( points_.size() );
for ( unsigned int i = 0; i < points_.size(); ++i )
pick_colors_[i] = _state.pick_get_name_color( i );
vertexPickingBaseIndex_ = _state.pick_current_index ();
updateVertexPicking_ = false;
}
// For this version we load the colors directly not from vbo
ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
ACG::GLState::colorPointer( &(pick_colors_[0]) );
ACG::GLState::enableClientState(GL_COLOR_ARRAY);
// vertex positions
ACG::GLState::vertexPointer( &(points_[0]) );
ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
// Draw color picking
glDrawArrays(GL_POINTS, 0, points_.size());
// Disable color array
ACG::GLState::disableClientState(GL_COLOR_ARRAY);
// disable vertex array
ACG::GLState::disableClientState(GL_VERTEX_ARRAY);*/
}
//----------------------------------------------------------------
void SplatCloudNode::createVBO()
{
// create a new vertex-buffer-object if not already existing
if( vboGlId_ == 0 )
{
glGenBuffersARB( 1, &vboGlId_ );
}
// create a new vertex-buffer-object if not already existing
if ( vboGlId_ == 0 )
{
glGenBuffersARB( 1, &vboGlId_ );
}
}
......@@ -209,15 +264,15 @@ void SplatCloudNode::createVBO()
void SplatCloudNode::destroyVBO()
{
// delete existing vertex-buffer-object
if( vboGlId_ != 0 )
{
glDeleteBuffersARB( 1, &vboGlId_ );
vboGlId_ = 0;
}
// make vertex-buffer-object invalid so it will not be used
vboValid_ = false;
// delete existing vertex-buffer-object
if ( vboGlId_ != 0 )
{
glDeleteBuffersARB( 1, &vboGlId_ );
vboGlId_ = 0;
}
// make vertex-buffer-object invalid so it will not be used
vboValid_ = false;
}
......@@ -226,14 +281,14 @@ void SplatCloudNode::destroyVBO()
static void addFloatToBuffer( float _value, unsigned char *&_buffer )
{
// get pointer
unsigned char *v = (unsigned char *) &_value;
// copy over 4 bytes
*_buffer++ = *v++;
*_buffer++ = *v++;
*_buffer++ = *v++;
*_buffer++ = *v;
// get pointer
unsigned char *v = (unsigned char *) &_value;
// copy over 4 bytes
*_buffer++ = *v++;
*_buffer++ = *v++;
*_buffer++ = *v++;
*_buffer++ = *v;
}
......@@ -242,77 +297,182 @@ static void addFloatToBuffer( float _value, unsigned char *&_buffer )
void SplatCloudNode::rebuildVBO()
{
// check if vertex-buffer-object has already been created (and not destroyed so far)
if( vboGlId_ == 0 )
// 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 )
{
vboValid_ = false;
return;
}
// we use GL_C4F_N3F_V3F as interleaved array type, so we have 4+3+3 = 10 floats per splat
unsigned int size = numPoints() * 10 * sizeof(float);
// activate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
// tell GL that we are seldom updating the vertex-buffer-object but are often drawing it
glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, 0, GL_STATIC_DRAW_ARB );
// get pointer to vertex-buffer-object's memory
unsigned char *buffer = (unsigned char *) glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
// if pointer is valid...
if ( buffer )
{
bool hasNrm = hasNormals();
bool hasPS = hasPointsizes();
bool hasCol = hasColors();
// for all points...
int i, num = numPoints();
for ( i=0; i<num; ++i )
{
static const float RCP255 = 1.0f / 255.0f;
// add color
const Color &c = hasCol ? colors_[i] : defaultColor_;
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_;
addFloatToBuffer( ps, buffer );
// add normal
const Normal &n = hasNrm ? normals_[i] : defaultNormal_;
addFloatToBuffer( n[0], buffer );
addFloatToBuffer( n[1], buffer );
addFloatToBuffer( n[2], buffer );
// add point
const Point &p = points_[i];
addFloatToBuffer( p[0], buffer );
addFloatToBuffer( p[1], buffer );
addFloatToBuffer( p[2], buffer );
// add pick color
}
}
// release pointer to vertex-buffer-object's memory
bool success = glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
// deactivate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
// mark vertex-buffer-object as valid only if it was successfully updated and unmaped
vboValid_ = (buffer != 0) && success;
}
//----------------------------------------------------------------
void SplatCloudNode::normalizeSize()
{
// check if there is nothing to do
if( points_.size() == 0 )
return;
// check if there could be a valid vertex-buffer-object
if( numPoints() == 0 )
// 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 )
{
vboValid_ = false;
return;
const SplatCloudNode::Point &p = *pointIter;
cogX += p[0];
cogY += p[1];
cogZ += p[2];
}
// we use GL_C4F_N3F_V3F as interleaved array type, so we have 4+3+3 = 10 floats per splat
unsigned int size = numPoints() * 10 * sizeof(float);
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];
}
// activate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
float s = (float) sqrt( sqLength * rcp_count );
// tell GL that we are seldom updating the vertex-buffer-object but are often drawing it
glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, 0, GL_STATIC_DRAW_ARB );
if( s == 0.0f )
return;
cur_scale_factor_ = 1.0f / s;
// get pointer to vertex-buffer-object's memory
unsigned char *buffer = (unsigned char *) glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
scale( cur_scale_factor_ );
std::cout << "SplatCloudNode::normalizeSize(): scaling points with factor: " << cur_scale_factor_ << std::endl;
}
// if pointer is valid...
if( buffer )
//----------------------------------------------------------------
void SplatCloudNode::translate( const Point& _t )
{
SplatCloudNode::PointVector::iterator pointIter;
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
bool hasNrm = hasNormals();
bool hasPS = hasPointsizes();
bool hasCol = hasColors();
SplatCloudNode::Point &p = *pointIter;
p[0] += _t[0];
p[1] += _t[1];
p[2] += _t[2];
}
}
//----------------------------------------------------------------
// for all points...
int i, num = numPoints();
for( i=0; i<num; ++i )
void SplatCloudNode::scale( const float _scale )
{
// scale points (and pointsizes as well) by calculated scale
SplatCloudNode::PointVector::iterator pointIter;
if( pointsizes_.size() == points_.size() )
{
SplatCloudNode::PointsizeVector::iterator pointsizeIter = pointsizes_.begin();
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter, ++pointsizeIter )
{
static const float RCP255 = 1.0f / 255.0f;
// add color
const Color &c = hasCol ? colors_[i] : defaultColor_;
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_;
addFloatToBuffer( ps, buffer );
// add normal
const Normal &n = hasNrm ? normals_[i] : defaultNormal_;
addFloatToBuffer( n[0], buffer );
addFloatToBuffer( n[1], buffer );
addFloatToBuffer( n[2], buffer );
// add point
const Point &p = points_[i];
addFloatToBuffer( p[0], buffer );
addFloatToBuffer( p[1], buffer );
addFloatToBuffer( p[2], buffer );
SplatCloudNode::Point &p = *pointIter;
SplatCloudNode::Pointsize &ps = *pointsizeIter;
p[0] *= _scale;
p[1] *= _scale;
p[2] *= _scale;
ps *= _scale; // scale pointsize as well
}
}
else
{
for( pointIter = points_.begin(); pointIter != points_.end(); ++pointIter )
{
SplatCloudNode::Point &p = *pointIter;
// release pointer to vertex-buffer-object's memory
bool success = glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
// deactivate vertex-buffer-object
ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
// mark vertex-buffer-object as valid only if it was successfully updated and unmaped
vboValid_ = (buffer != 0) && success;
p[0] *= _scale;
p[1] *= _scale;
p[2] *= _scale;
}
}
}
//================================================================
......
......@@ -94,11 +94,13 @@ public:
typedef ACG::Vec3f Normal;
typedef float Pointsize;
typedef ACG::Vec3uc Color;
typedef ACG::Vec4uc PickColor;
typedef std::vector<Point> PointVector;
typedef std::vector<Normal> NormalVector;
typedef std::vector<Pointsize> PointsizeVector;
typedef std::vector<Color> ColorVector;
typedef std::vector<PickColor> PickColorVector;
//----------------------------------------------------------------
......@@ -111,10 +113,16 @@ public:
vboGlId_ ( 0 ),
vboValid_ ( false )
{
cur_translation_ = Point( 0.0f,0.0f,0.0f );
cur_scale_factor_ = 1.0;
// add (possibly) new drawmodes
pointsDrawMode_ = DrawModes::addDrawMode( "Points" );
dotsDrawMode_ = DrawModes::addDrawMode( "Dots" );
splatsDrawMode_ = DrawModes::addDrawMode( "Splats" );