Commit 900d2e5d authored by Mathias Goldau's avatar Mathias Goldau

[MERGE]

parents cdd24905 4083309f
......@@ -91,6 +91,13 @@ void WProperties::addProperty( boost::shared_ptr< WPropertyBase > prop )
}
}
// PV_PURPOSE_INFORMATION groups do not allow PV_PURPOSE_PARAMETER properties but vice versa.
if ( getPurpose() == PV_PURPOSE_INFORMATION )
{
prop->setPurpose( PV_PURPOSE_INFORMATION );
}
// INFORMATION properties are allowed inside PARAMETER groups -> do not set the properties purpose.
m_propAccess->get().push_back( prop );
m_propAccess->endWrite();
}
......
......@@ -37,6 +37,7 @@ WPropertyBase::WPropertyBase( std::string name, std::string description ):
m_name( name ),
m_description( description ),
m_hidden( false ),
m_purpose( PV_PURPOSE_PARAMETER ),
m_updateCondition( new WConditionSet() )
{
// check name validity
......@@ -67,6 +68,16 @@ PROPERTY_TYPE WPropertyBase::getType() const
return m_type;
}
PROPERTY_PURPOSE WPropertyBase::getPurpose() const
{
return m_purpose;
}
void WPropertyBase::setPurpose( PROPERTY_PURPOSE purpose )
{
m_purpose = purpose;
}
void WPropertyBase::updateType()
{
m_type = PV_UNKNOWN;
......
......@@ -92,6 +92,27 @@ public:
*/
virtual PROPERTY_TYPE getType() const;
/**
* Gets the purpose of a property. See PROPERTY_PURPOSE for more details. For short: it helps the GUI and others to understand what a module
* (or whomever created this property) intents with this property. Typically this value is PV_PURPOSE_PARAMETER, meaning that it is used to
* tune the behaviour of a module.
*
* \note always assume this to be a hint. It does not actually prevent someone from writing or interpreting a parameter property as an
* information property.
*
* \see PROPERTY_PURPOSE
* \return the purpose.
*/
virtual PROPERTY_PURPOSE getPurpose() const;
/**
* Sets the purpose of the property. See \ref getPurpose for more details. You generally should avoid setting this value after
* initialization.
*
* \param purpose the purpose to set.
*/
virtual void setPurpose( PROPERTY_PURPOSE purpose );
/**
* This methods allows properties to be set by a string value. This is especially useful when a property is only available as string and the
* real type of the property is unknown. This is a shortcut for casting the property and then setting the lexically casted value.
......@@ -235,6 +256,11 @@ protected:
*/
PROPERTY_TYPE m_type;
/**
* The purpose of this property. PropertyBase always initializes it with PV_PURPOSE_PARAMETER.
*/
PROPERTY_PURPOSE m_purpose;
/**
* Calculates the type of the property. This has to be done by the implementing class.
*/
......
......@@ -53,20 +53,33 @@ class WProperties;
*/
typedef enum
{
PV_UNKNOWN, // type not know
PV_GROUP, // the group property
PV_INT, // integer value
PV_DOUBLE, // floating point value
PV_BOOL, // boolean
PV_STRING, // a string
PV_PATH, // a Boost Path object denoting a filename/path
PV_SELECTION, // a list of strings, selectable
PV_POSITION, // a position property
PV_COLOR, // a color property
PV_TRIGGER // for triggering an event
PV_UNKNOWN, //!< type not known
PV_GROUP, //!< the group property
PV_INT, //!< integer value
PV_DOUBLE, //!< floating point value
PV_BOOL, //!< boolean
PV_STRING, //!< a string
PV_PATH, //!< a Boost Path object denoting a filename/path
PV_SELECTION, //!< a list of strings, selectable
PV_POSITION, //!< a position property
PV_COLOR, //!< a color property
PV_TRIGGER //!< for triggering an event
}
PROPERTY_TYPE;
/**
* Enum of all possible purpose of a property. The purpose describes which meaning a property has for the creator of it. A PP_PARAMETER is a
* property which is meant to be modified to adopt the behaviour of the module (or whomever has created it). A PP_INFORMATION is only an output
* from the creator who wants to inform the outside world about values, states or whatever.
*/
typedef enum
{
PV_PURPOSE_INFORMATION, //!< information property not meant to be modified from someone (except the creating object)
PV_PURPOSE_PARAMETER //!< a parameter meant to be modified by others to manipulate the behaviour of the module (or whomever created
//!< the property)
}
PROPERTY_PURPOSE;
/**
* Namespace containing all base types of the WPropertyVariables. Use these types instead of issuing int32_t, double, bool, ...
* directly. It also contains some user defined types including the needed operators.
......
......@@ -112,10 +112,10 @@ double WDataSetScalar::interpolate( const wmath::WPosition& pos, bool* success )
throw WException( std::string( "This data set has a grid whose type is not yet supported for interpolation." ) );
}
// TODO(wiebel): change this to eassert.
// if( grid->getTransformationMatrix() != wmath::WMatrix<double>( 4, 4 ).makeIdentity() )
// {
// throw WException( std::string( "Only feasible for untranslated grid so far." ) );
// }
// if( grid->getTransformationMatrix() != wmath::WMatrix<double>( 4, 4 ).makeIdentity() )
// {
// throw WException( std::string( "Only feasible for untranslated grid so far." ) );
// }
// TODO(wiebel): change this to eassert.
if( !( m_valueSet->order() == 0 && m_valueSet->dimension() == 1 ) )
{
......
......@@ -51,8 +51,8 @@ WDataSetSingle::WDataSetSingle( boost::shared_ptr< WValueSetBase > newValueSet,
WDataSetSingle::WDataSetSingle()
: WDataSet(),
m_valueSet(),
m_grid(),
m_valueSet(),
m_texture3D()
{
// default constructor used by the prototype mechanism
......
......@@ -22,9 +22,11 @@
//
//---------------------------------------------------------------------------
#include <string>
#include <vector>
#include "../common/WAssert.h"
#include "WDataSetSingle.h"
#include "WDataSetVector.h"
// prototype instance as singleton
......@@ -59,3 +61,96 @@ boost::shared_ptr< WPrototyped > WDataSetVector::getPrototype()
return m_prototype;
}
wmath::WVector3D WDataSetVector::interpolate( const wmath::WPosition& pos, bool *success )
{
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( m_grid );
// TODO(wiebel): change this to eassert.
if( !grid )
{
throw WException( std::string( "This data set has a grid whose type is not yet supported for interpolation." ) );
}
// TODO(wiebel): change this to eassert.
// if( grid->getTransformationMatrix() != wmath::WMatrix<double>( 4, 4 ).makeIdentity() )
// {
// throw WException( std::string( "Only feasible for untranslated grid so far." ) );
// }
// TODO(wiebel): change this to eassert.
if( !( m_valueSet->order() == 1 && m_valueSet->dimension() == 3 ) )
{
throw WException( std::string( "Only implemented for 3D Vectors so far." ) );
}
*success = grid->encloses( pos );
if( !*success )
{
return wmath::WVector3D( 0, 0, 0 );
}
std::vector< size_t > vertexIds = grid->getCellVertexIds( grid->getCellId( pos ) );
wmath::WPosition localPos = pos - grid->getPosition( vertexIds[0] );
double lambdaX = localPos[0] / grid->getOffsetX();
double lambdaY = localPos[1] / grid->getOffsetY();
double lambdaZ = localPos[2] / grid->getOffsetZ();
std::vector< double > h( 8 );
// lZ lY
// | /
// | 6___/_7
// |/: /|
// 4_:___5 |
// | :...|.|
// |.2 | 3
// |_____|/ ____lX
// 0 1
h[0] = ( 1 - lambdaX ) * ( 1 - lambdaY ) * ( 1 - lambdaZ );
h[1] = ( lambdaX ) * ( 1 - lambdaY ) * ( 1 - lambdaZ );
h[2] = ( 1 - lambdaX ) * ( lambdaY ) * ( 1 - lambdaZ );
h[3] = ( lambdaX ) * ( lambdaY ) * ( 1 - lambdaZ );
h[4] = ( 1 - lambdaX ) * ( 1 - lambdaY ) * ( lambdaZ );
h[5] = ( lambdaX ) * ( 1 - lambdaY ) * ( lambdaZ );
h[6] = ( 1 - lambdaX ) * ( lambdaY ) * ( lambdaZ );
h[7] = ( lambdaX ) * ( lambdaY ) * ( lambdaZ );
wmath::WVector3D result( 0, 0, 0 );
for( size_t i = 0; i < 8; ++i )
{
result += h[i] * getVectorAt( vertexIds[i] );
}
*success = true;
return result;
}
wmath::WVector3D WDataSetVector::getVectorAt( size_t index ) const
{
switch( getValueSet()->getDataType() )
{
case W_DT_UNSIGNED_CHAR:
{
return boost::shared_dynamic_cast< WValueSet< unsigned char > >( getValueSet() )->getVector3D( index );
}
case W_DT_INT16:
{
return boost::shared_dynamic_cast< WValueSet< int16_t > >( getValueSet() )->getVector3D( index );
}
case W_DT_SIGNED_INT:
{
return boost::shared_dynamic_cast< WValueSet< int32_t > >( getValueSet() )->getVector3D( index );
}
case W_DT_FLOAT:
{
return boost::shared_dynamic_cast< WValueSet< float > >( getValueSet() )->getVector3D( index );
}
case W_DT_DOUBLE:
{
return boost::shared_dynamic_cast< WValueSet< double > >( getValueSet() )->getVector3D( index );
}
default:
assert( false && "Unknow data type in dataset." );
}
return wmath::WVector3D( 0, 0, 0 );
}
......@@ -61,6 +61,26 @@ public:
*/
static boost::shared_ptr< WPrototyped > getPrototype();
/**
* Interpolates the vector field at the given position
*
* \param pos position to interpolate
* \param success if the position was inside the grid
*
* \return Vector beeing the interpolate.
*/
wmath::WVector3D interpolate( const wmath::WPosition &pos, bool *success );
/**
* Get the vector on the given position in value set.
* \note currently only implmented for WVector3D
*
* \param index the position where to get the vector from
*
* \return the vector
*/
wmath::WVector3D getVectorAt( size_t index ) const;
protected:
/**
......
......@@ -29,9 +29,11 @@
#include <cstddef>
#include <vector>
#include "WValueSetBase.h"
#include "WDataHandlerEnums.h"
#include "../common/math/WValue.h"
#include "../common/math/WVector3D.h"
#include "../common/WAssert.h"
#include "WDataHandlerEnums.h"
#include "WValueSetBase.h"
/**
* Base Class for all value set types.
......@@ -107,6 +109,15 @@ public:
return static_cast< double >( m_data[i] );
}
/**
* Get the i'th vector
*
* \param index the index number of the vector
*
* \return the vector
*/
wmath::WVector3D getVector3D( size_t index ) const;
/**
* Sometimes we need raw access to the data array, for e.g. OpenGL.
*/
......@@ -133,4 +144,11 @@ private:
const std::vector< T > m_data; // WARNING: don't remove constness since &m_data[0] won't work anymore!
};
template< typename T > wmath::WVector3D WValueSet< T >::getVector3D( size_t index ) const
{
WAssert( m_order == 1 && m_dimension == 3, "WValueSet<T>::getVector3D only implemented for order==1, dim==3 value sets" );
size_t offset = index * 3;
return wmath::WVector3D( m_data[ offset ], m_data[ offset + 1 ], m_data[ offset + 2 ] );
}
#endif // WVALUESET_H
//---------------------------------------------------------------------------
//
// 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 WDATASETVECTOR_TEST_H
#define WDATASETVECTOR_TEST_H
#include <vector>
#include <cxxtest/TestSuite.h>
#include "../WDataSetVector.h"
/**
* TODO(lmath): Document this!
*/
class WDataSetVectorTest : public CxxTest::TestSuite
{
public:
/**
* An interpolate of an vector is as if every components were interpolated
*/
void testInterpolate( void )
{
boost::shared_ptr< WGrid > grid = boost::shared_ptr< WGrid >( new WGridRegular3D( 5, 3, 3, 1, 1, 1 ) );
std::vector< double > data( grid->size() * 3 );
for( size_t i = 0; i < grid->size() * 3; ++i )
{
data[i] = i;
}
boost::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
WDataSetVector ds( valueSet, grid );
bool success = false;
TS_ASSERT_EQUALS( ds.interpolate( wmath::WPosition(), &success )[0], data[0] );
TS_ASSERT_EQUALS( ds.interpolate( wmath::WPosition(), &success )[1], data[1] );
TS_ASSERT_EQUALS( ds.interpolate( wmath::WPosition(), &success )[2], data[2] );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 0, 0 ), &success )[0], data[3], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 0, 0 ), &success )[1], data[4], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 0, 0 ), &success )[2], data[5], 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 1, 0 ), &success )[0], data[15], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 1, 0 ), &success )[1], data[16], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 1, 0 ), &success )[2], data[17], 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 1, 0 ), &success )[0], data[18], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 1, 0 ), &success )[1], data[19], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 1, 0 ), &success )[2], data[20], 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 0, 1 ), &success )[0], data[45], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 0, 1 ), &success )[1], data[46], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 0, 1 ), &success )[2], data[47], 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 0, 1 ), &success )[0], data[48], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 0, 1 ), &success )[1], data[49], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 0, 1 ), &success )[2], data[50], 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 1, 1 ), &success )[0], data[60], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 1, 1 ), &success )[1], data[61], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0, 1, 1 ), &success )[2], data[62], 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 1, 1 ), &success )[0], data[63], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 1, 1 ), &success )[1], data[64], 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 1, 1, 1 ), &success )[2], data[65], 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0.3, 0.4, 0.5 ), &success )[0], 29.4, 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0.3, 0.4, 0.5 ), &success )[1], 30.4, 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0.3, 0.4, 0.5 ), &success )[2], 31.4, 1e-9 );
TS_ASSERT( success );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0.5, 0.5, 0.5 ), &success )[0], 31.5, 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0.5, 0.5, 0.5 ), &success )[1], 32.5, 1e-9 );
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0.5, 0.5, 0.5 ), &success )[2], 33.5, 1e-9 );
TS_ASSERT( success );
}
};
#endif // WDATASETVECTOR_TEST_H
......@@ -63,14 +63,16 @@ WGEViewer::WGEViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int
switch( projectionMode )
{
case( WGECamera::ORTHOGRAPHIC ):
m_pickHandler = new WPickHandler( name );
m_View->addEventHandler( m_pickHandler );
if ( name != std::string( "main" ) )
break;
case( WGECamera::PERSPECTIVE ):
// camera manipulator
m_View->setCameraManipulator( new WGEZoomTrackballManipulator() );
m_View->setLightingMode( osg::View::HEADLIGHT ); // this is the default anyway
m_pickHandler = new WPickHandler();
m_View->addEventHandler( m_pickHandler );
break;
case( WGECamera::TWO_D ):
// no manipulators nor gui handlers
......
......@@ -33,9 +33,19 @@
WPickHandler::WPickHandler()
: m_hitResult( WPickInfo() ),
m_startPick( WPickInfo() ),
m_shift( false )
m_shift( false ),
m_viewerName( "" )
{
}
WPickHandler::WPickHandler( std::string viewerName )
: m_hitResult( WPickInfo() ),
m_startPick( WPickInfo() ),
m_shift( false ),
m_viewerName( viewerName )
{
}
WPickHandler::~WPickHandler()
{
}
......@@ -110,7 +120,7 @@ void WPickHandler::unpick( )
{
if( m_hitResult != WPickInfo() )
{
m_hitResult = WPickInfo( "unpick", wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
m_hitResult = WPickInfo( "unpick", m_viewerName, wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
m_startPick = WPickInfo();
}
m_pickSignal( getHitResult() );
......@@ -137,6 +147,22 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
float x = ea.getX(); // pixel position in x direction
float y = ea.getY(); // pixel position in x direction
// if we are in another viewer than the main view we just need the pixel position
if ( m_viewerName != "" && m_viewerName != "main" )
{
WPickInfo pickInfo;
pickInfo = WPickInfo( "", m_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
m_startPick.getModifierKey(), m_startPick.getPickNormal() );
m_hitResult = pickInfo;
// if nothing was picked before remember the currently picked.
m_startPick = pickInfo;
m_pickSignal( getHitResult() );
return;
}
bool intersetionsExist = view->computeIntersections( x, y, intersections );
// if something is picked, get the right thing from the list, because it might be hidden.
......@@ -158,7 +184,7 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
{
while( ( hitr != intersections.end() ) && !startPickIsStillInList )
{
WPickInfo pickInfoTmp( extractSuitableName( hitr ), wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
WPickInfo pickInfoTmp( extractSuitableName( hitr ), m_viewerName, wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
startPickIsStillInList |= ( pickInfoTmp.getName() == m_startPick.getName() );
if( !startPickIsStillInList ) // if iteration not finished yet go on in list
......@@ -183,13 +209,13 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
pickNormal[0] = hitr->getWorldIntersectNormal()[0];
pickNormal[1] = hitr->getWorldIntersectNormal()[1];
pickNormal[2] = hitr->getWorldIntersectNormal()[2];
pickInfo = WPickInfo( extractSuitableName( hitr ), pickPos, std::make_pair( x, y ), WPickInfo::NONE, pickNormal );
pickInfo = WPickInfo( extractSuitableName( hitr ), m_viewerName, pickPos, std::make_pair( x, y ), WPickInfo::NONE, pickNormal );
}
// Use the old PickInfo with updated pixel info if we have previously picked something but the old is not in list anymore
if( !startPickIsStillInList && m_startPick.getName() != "" && m_startPick.getName() != "unpick" )
{
pickInfo = WPickInfo( m_startPick.getName(), m_startPick.getPickPosition(), std::make_pair( x, y ),
pickInfo = WPickInfo( m_startPick.getName(), m_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
m_startPick.getModifierKey(), m_startPick.getPickNormal() );
}
......
......@@ -61,6 +61,13 @@ public:
*/
WPickHandler();
/**
* Constructor that initalizes members with sensible defaults and sets the name of the viewer
*
* \param viewerName name of the viewer
*/
explicit WPickHandler( std::string viewerName );
/**
* Deals with the events found by the osg.
* \param ea Event class for storing Keyboard, mouse and window events.
......@@ -105,6 +112,7 @@ protected:
WPickInfo m_hitResult; //!< Textual representation of the result of a pick.
WPickInfo m_startPick; //!< indicates what was first picked. Should be "" after unpick.
bool m_shift; //!< is shift pressed?
std::string m_viewerName; //!< which viewer sends the signal
private:
boost::signals2::signal1<void, WPickInfo > m_pickSignal; //!< One can register to this signal to receive pick events.
......
......@@ -52,12 +52,14 @@ public:
/**
* Creates an object with the needed information.
* \param name name of picked object
* \param viewerName name of the viewer
* \param pickPosition position where object was hit
* \param pixelCoords pixel coordinates fo the mouse
* \param pixelCoords pixel coordinates of the mouse
* \param modKey relevant modifier key pressed during the pick
* \param pickNormal normal at position where object was hit. (0,0,0) means not set.
*/
inline WPickInfo( std::string name,
std::string viewerName,
wmath::WPosition pickPosition,
std::pair< float, float > pixelCoords,
modifierKey modKey,
......@@ -80,10 +82,15 @@ public:
inline void setModifierKey( const modifierKey& modKey );
/**
* Get name of picked object.
*/
* Get name of picked object.
*/
inline std::string getName() const;
/**
* Get name of the viewer.
*/
inline std::string getViewerName() const;
/**
* Get position where object was hit.
*/
......@@ -115,6 +122,7 @@ protected:
private:
std::string m_name; //!< name of picked object.
std::string m_viewerName; //!< name of the viewer
wmath::WPosition m_pickPosition; //!< position where object was hit.
std::pair< float, float > m_pixelCoords; //!< Pixel coordinates of the mouse.
modifierKey m_modKey; //!< modifier key associated with the pick
......@@ -122,11 +130,13 @@ private:
};
WPickInfo::WPickInfo( std::string name,
std::string viewerName,
wmath::WPosition pickPosition,
std::pair< float, float > pixelCoords,
modifierKey modKey,
wmath::WVector3D pickNormal ) :
m_name( name ),
m_viewerName( viewerName ),
m_pickPosition( pickPosition ),
m_pixelCoords( pixelCoords ),
m_modKey( modKey ),
......@@ -136,6 +146,7 @@ WPickInfo::WPickInfo( std::string name,
WPickInfo::WPickInfo() :
m_name( "" ),
m_viewerName( "" ),