Commit 3f18d6b5 authored by Jan Möbius's avatar Jan Möbius

Dennis:

Implemented color based picking.

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@5208 383ad7c9-94d9-4d36-a494-682f7c89f535
parent d96702ce
//=============================================================================
//
// OpenFlipper
// Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
// www.openflipper.org
//
//-----------------------------------------------------------------------------
//
// License
//
// OpenFlipper 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.
//
// OpenFlipper 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 OpenFlipper. If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
//
// $Revision: 1720 $
// $Author: moebius $
// $Date: 2008-05-09 14:15:53 +0200 (Fr, 09. Mai 2008) $
//
//=============================================================================
//=============================================================================
//
// CLASS ColorStack - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
#include "ColorStack.hh"
#include <iostream>
//== NAMESPACES ===============================================================
namespace ACG {
//== IMPLEMENTATION ==========================================================
ColorStack::ColorStack () :
initialized_(false),
root_ (0),
currentNode_ (0),
error_(false)
{
}
//----------------------------------------------------------------------------
ColorStack::~ColorStack ()
{
if (root_)
delete root_;
}
//----------------------------------------------------------------------------
void ColorStack::initialize ()
{
if (initialized_)
{
delete root_;
}
error_ = false;
translator_.initialize ();
root_ = currentNode_ = new ColorStack::Node (0, 0, &translator_);
initialized_ = true;
}
//----------------------------------------------------------------------------
bool ColorStack::setMaximumIndex (unsigned int _idx)
{
if (initialized_)
{
bool rv = currentNode_->setMaximumIndex (_idx);
if (!rv)
error_ = true;
return rv;
}
return false;
}
//----------------------------------------------------------------------------
void ColorStack::setIndex (unsigned int _idx)
{
if (initialized_)
{
if (!currentNode_->setIndex (_idx))
error_ = true;
}
}
//----------------------------------------------------------------------------
void ColorStack::pushIndex (unsigned int _idx)
{
if (initialized_)
currentNode_ = currentNode_->pushIndex (_idx);
}
//----------------------------------------------------------------------------
void ColorStack::popIndex ()
{
if (initialized_)
currentNode_ = currentNode_->popIndex ();
}
//----------------------------------------------------------------------------
std::vector<unsigned int> ColorStack::colorToStack (Vec3uc _rgb) const
{
std::vector<unsigned int> rv(0);
if (initialized_ && !error_)
{
unsigned int idx = translator_.color2index (_rgb);
if (idx >= root_->startIndex () && idx < root_->endIndex ())
root_->colorToStack (rv, idx);
}
return rv;
}
//----------------------------------------------------------------------------
unsigned int ColorStack::freeIndicies() const
{
if (initialized_)
{
return translator_.max_index () - currentNode_->endIndex ();
}
else
return 0;
}
//----------------------------------------------------------------------------
unsigned int ColorStack::currentIndex () const
{
if (initialized_)
{
return currentNode_->colorIndex ();
}
return 0;
}
//----------------------------------------------------------------------------
ColorStack::Node::Node (unsigned int _idx, Node *_parent, ColorTranslator *_ct) :
parent_(_parent),
index_(_idx),
translator_(_ct),
colorStartIdx_(0),
colorEndIdx_(0)
{
if (parent_)
startIdx_ = endIdx_ = parent_->endIndex ();
else
startIdx_ = endIdx_ = 1;
}
//----------------------------------------------------------------------------
ColorStack::Node::~Node ()
{
for (std::vector<Node *>::iterator it = nodes_.begin (); it != nodes_.end(); ++it)
delete (*it);
}
//----------------------------------------------------------------------------
bool ColorStack::Node::setMaximumIndex (unsigned int _idx)
{
if (colorStartIdx_ == 0 && _idx > 0 && translator_->max_index () > endIdx_ + _idx)
{
colorStartIdx_ = endIdx_;
endIdx_ = colorEndIdx_ = colorStartIdx_ + _idx;
return true;
}
return false;
}
//----------------------------------------------------------------------------
bool ColorStack::Node::setIndex (unsigned int _idx) const
{
if (colorStartIdx_ && colorStartIdx_ + _idx < colorEndIdx_)
{
glColor(translator_->index2color(colorStartIdx_ + _idx));
return true;
}
return false;
}
//----------------------------------------------------------------------------
ColorStack::Node * ColorStack::Node::pushIndex (unsigned int _idx)
{
ColorStack::Node *n = new ColorStack::Node (_idx, this, translator_);
nodes_.push_back (n);
return n;
}
//----------------------------------------------------------------------------
ColorStack::Node * ColorStack::Node::popIndex ()
{
parent_->endIdx_ = endIdx_;
return parent_;
}
//----------------------------------------------------------------------------
void ColorStack::Node::colorToStack (std::vector<unsigned int> &_stack, unsigned int _index)
{
if (_index >= colorStartIdx_ && _index < colorEndIdx_)
{
_stack.push_back (_index - colorStartIdx_);
}
else
{
for (std::vector<Node *>::iterator it = nodes_.begin (); it != nodes_.end(); ++it)
{
ColorStack::Node *n = (*it);
if (_index >= n->startIndex () && _index < n->endIndex ())
n->colorToStack (_stack, _index);
}
}
_stack.push_back (index_);
}
//=============================================================================
} // namespace ACG
//=============================================================================
//=============================================================================
//
// OpenFlipper
// Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
// www.openflipper.org
//
//-----------------------------------------------------------------------------
//
// License
//
// OpenFlipper 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.
//
// OpenFlipper 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 OpenFlipper. If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
//
// $Revision: 3469 $
// $Author: moebius $
// $Date: 2008-10-17 15:15:46 +0200 (Fr, 17. Okt 2008) $
//
//=============================================================================
//=============================================================================
//
// CLASS ColorStack
//
//=============================================================================
#ifndef ACG_COLORSTACK_HH
#define ACG_COLORSTACK_HH
//== INCLUDES =================================================================
#include <vector>
#include "gl.hh"
#include "../Math/VectorT.hh"
#include "ColorTranslator.hh"
//== NAMESPACES ===============================================================
namespace ACG {
//== CLASS DEFINITION =========================================================
/** This class can be used to implement a gl picking stack based on colors
*/
class ACGDLLEXPORT ColorStack
{
public:
/// Default constructor.
ColorStack();
/// Destructor.
~ColorStack();
/// init (takes current GL context/ like glInitNames (); glPushName (0))
void initialize();
/// has it been initialized?
bool initialized() const { return initialized_; }
/// sets the maximum index number used in current node
bool setMaximumIndex (unsigned int _idx);
/// sets the current color the given index (like glLoadName)
void setIndex (unsigned int _idx);
/// creates a new node the stack (like glPushName)
void pushIndex (unsigned int _idx);
/// pops the current node from the stack (like glPopName)
void popIndex ();
/// converts the given color to index values on the stack
std::vector<unsigned int> colorToStack (Vec3uc _rgb) const;
/// returns maximal available index count
unsigned int freeIndicies () const;
/// Did an error occur during picking
bool error () const { return error_ && initialized_; };
/// returns the current color index
unsigned int currentIndex () const;
private:
// Internal class used realize the color stack
class Node {
public:
Node (unsigned int _idx, Node *_parent, ColorTranslator *_ct);
~Node ();
/// sets the maximum index number used in current node
bool setMaximumIndex (unsigned int _idx);
/// sets the current color the given index (like glLoadName)
bool setIndex (unsigned int _idx) const;
/// creates a new node the stack (like glPushName)
Node * pushIndex (unsigned int _idx);
/// pops the current node from the stack (like glPopName)
Node * popIndex ();
void colorToStack (std::vector<unsigned int> &_stack, unsigned int _index);
unsigned int startIndex () { return startIdx_; };
unsigned int endIndex () { return endIdx_; };
unsigned int colorIndex () { return colorStartIdx_; };
private:
Node *parent_;
unsigned int index_;
ColorTranslator *translator_;
std::vector<Node *> nodes_;
unsigned int startIdx_;
unsigned int endIdx_;
unsigned int colorStartIdx_;
unsigned int colorEndIdx_;
};
bool initialized_;
ColorTranslator translator_;
Node *root_;
Node *currentNode_;
bool error_;
};
//=============================================================================
} // namespace ACG
//=============================================================================
#endif // ACG_COLORSTACK_HH defined
//=============================================================================
......@@ -50,7 +50,6 @@
namespace ACG {
namespace SceneGraph {
//== IMPLEMENTATION ==========================================================
......@@ -145,7 +144,6 @@ ColorTranslator::max_index() const
//=============================================================================
} // namespace SceneGraph
} // namespace ACG
//=============================================================================
......@@ -53,7 +53,6 @@
namespace ACG {
namespace SceneGraph {
//== CLASS DEFINITION =========================================================
......@@ -100,7 +99,6 @@ private:
//=============================================================================
} // namespace SceneGraph
} // namespace ACG
//=============================================================================
#endif // ACG_COLORTRANSLATOR_HH defined
......
......@@ -832,6 +832,83 @@ void GLState::pop_modelview_matrix()
}
}
//-----------------------------------------------------------------------------
void GLState::pick_init (bool _color)
{
colorPicking_ = _color;
colorStack_.initialize ();
glInitNames();
glPushName((GLuint) 0);
}
//-----------------------------------------------------------------------------
bool GLState::pick_set_maximum (unsigned int _idx)
{
if (colorPicking_)
return colorStack_.setMaximumIndex (_idx);
return true;
}
//-----------------------------------------------------------------------------
void GLState::pick_set_name (unsigned int _idx)
{
colorStack_.setIndex (_idx);
glLoadName (_idx);
}
//-----------------------------------------------------------------------------
void GLState::pick_push_name (unsigned int _idx)
{
colorStack_.pushIndex (_idx);
glLoadName (_idx);
glPushName (0);
}
//-----------------------------------------------------------------------------
void GLState::pick_pop_name ()
{
colorStack_.popIndex ();
glPopName ();
}
//-----------------------------------------------------------------------------
std::vector<unsigned int> GLState::pick_color_to_stack (Vec3uc _rgb) const
{
if (colorPicking_ && colorStack_.initialized ())
return colorStack_.colorToStack (_rgb);
return std::vector<unsigned int> ();
}
//-----------------------------------------------------------------------------
unsigned int GLState::pick_free_indicies () const
{
if (colorPicking_ && colorStack_.initialized ())
return colorStack_.freeIndicies ();
return -1;
}
//-----------------------------------------------------------------------------
bool GLState::pick_error () const
{
if (colorPicking_)
return colorStack_.error ();
return false;
}
//-----------------------------------------------------------------------------
unsigned int GLState::pick_current_index () const
{
return colorStack_.currentIndex ();
}
//=============================================================================
} // namespace ACG
......
......@@ -50,7 +50,9 @@
#include "../Math/GLMatrixT.hh"
#include "../Math/VectorT.hh"
#include "../Config/ACGDefines.hh"
#include "ColorStack.hh"
#include <stack>
#include <vector>
#ifdef WIN32
#pragma warning(push)
......@@ -364,7 +366,34 @@ public:
/// get whether transparenet or solid objects should be drawn
bool twosided_lighting() { return twosided_lighting_; }
//--- picking ---------------------------------------------------------------
/// initialize name/color picking stack
void pick_init (bool _color);
/// sets the maximum used name index at current stack position (only used in color picking)
bool pick_set_maximum (unsigned int _idx);
/// sets the current name/color
void pick_set_name (unsigned int _idx);
/// creates a new name the stack
void pick_push_name (unsigned int _idx);
/// pops the current name from the stack
void pick_pop_name ();
/// converts the given color to index values on the stack (only used in color picking)
std::vector<unsigned int> pick_color_to_stack (Vec3uc _rgb) const;
/// returns maximal available index count (only used in color picking)
unsigned int pick_free_indicies () const;
/// Did an error occur during picking (only used in color picking)
bool pick_error () const;
/// returns the current color picking index (can be used for caching)
unsigned int pick_current_index () const;
private: //--------------------------------------------------------------------
......@@ -423,6 +452,12 @@ private: //--------------------------------------------------------------------
// time since last redraw
unsigned int msSinceLastRedraw_;
// stack for color picking
ColorStack colorStack_;
// are we using color picking
bool colorPicking_;
};
#ifdef WIN32
......
......@@ -99,8 +99,7 @@ bool QtBaseViewer::pick( SceneGraph::PickTarget _pickTarget,
glLoadMatrixd(modelview.get_raw_data());
glDisable(GL_LIGHTING);
glClear(GL_DEPTH_BUFFER_BIT);
glInitNames();
glPushName((GLuint) 0);
glstate_->pick_init (false);
// do the picking
SceneGraph::PickAction action(_pickTarget);
......
......@@ -34,7 +34,7 @@
//=============================================================================
//
// CLASS ColorTranslator - IMPLEMENTATION
// CLASS QtColorTranslator - IMPLEMENTATION
//
//=============================================================================
......@@ -55,7 +55,7 @@ namespace ACG {
void
ColorTranslator::initialize()
QtColorTranslator::initialize()
{
glGetIntegerv( GL_RED_BITS, &redBits_ );
glGetIntegerv( GL_GREEN_BITS, &greenBits_ );
......@@ -87,7 +87,7 @@ ColorTranslator::initialize()
bool
ColorTranslator::index2color(unsigned int _idx, QRgb& _col) const
QtColorTranslator::index2color(unsigned int _idx, QRgb& _col) const
{
assert(initialized());
unsigned char r, g, b;
......@@ -117,7 +117,7 @@ ColorTranslator::index2color(unsigned int _idx, QRgb& _col) const
bool
ColorTranslator::index2color(unsigned int _idx, QRgb& _fc, QRgb& _bc) const
QtColorTranslator::index2color(unsigned int _idx, QRgb& _fc, QRgb& _bc) const
{
assert(initialized());
unsigned char r, g, b;
......@@ -167,7 +167,7 @@ ColorTranslator::index2color(unsigned int _idx, QRgb& _fc, QRgb& _bc) const
int
ColorTranslator::color2index(QRgb _c) const
QtColorTranslator::color2index(QRgb _c) const
{
assert(initialized());
unsigned int result;
......@@ -186,7 +186,7 @@ ColorTranslator::color2index(QRgb _c) const
int
ColorTranslator::color2index(QRgb _fc, QRgb _bc) const
QtColorTranslator::color2index(QRgb _fc, QRgb _bc) const
{
assert(initialized());
unsigned int result;
......@@ -212,7 +212,7 @@ ColorTranslator::color2index(QRgb _fc, QRgb _bc) const
unsigned int
ColorTranslator::maxIndex() const
QtColorTranslator::maxIndex() const
{
assert(initialized());