//--------------------------------------------------------------------------- // // Project: OpenWalnut ( http://www.openwalnut.org ) // // Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-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 . // //--------------------------------------------------------------------------- #include #include #include #include "../../kernel/WKernel.h" #include "../../dataHandler/WDataHandler.h" #include "../../dataHandler/WDataTexture3D.h" #include "../../dataHandler/WSubject.h" #include "WMDatasetManipulator.xpm" #include "WMDatasetManipulator.h" // This line is needed by the module loader to actually find your module. Do not remove. Do NOT add a ";" here. W_LOADABLE_MODULE( WMDatasetManipulator ) WMDatasetManipulator::WMDatasetManipulator(): WModule() { } WMDatasetManipulator::~WMDatasetManipulator() { // Cleanup! } boost::shared_ptr< WModule > WMDatasetManipulator::factory() const { // See "src/modules/template/" for an extensively documented example. return boost::shared_ptr< WModule >( new WMDatasetManipulator() ); } const char** WMDatasetManipulator::getXPMIcon() const { return WMDatasetManipulator_xpm; // Please put a real icon here. } const std::string WMDatasetManipulator::getName() const { // Specify your module name here. This name must be UNIQUE! return "DatasetManipulator"; } const std::string WMDatasetManipulator::getDescription() const { // Specify your module description here. Be detailed. This text is read by the user. // See "src/modules/template/" for an extensively documented example. return "This module allows manipulation of the dataset properties via manipulators in the 3D scene"; } void WMDatasetManipulator::connectors() { // the input dataset is just used as source for resolurtion and transformation matrix m_input = boost::shared_ptr< WModuleInputData < WDataSetSingle > >( new WModuleInputData< WDataSetSingle >( shared_from_this(), "in", "The input dataset." ) ); addConnector( m_input ); m_output = boost::shared_ptr< WModuleOutputData < WDataSetSingle > >( new WModuleOutputData< WDataSetSingle >( shared_from_this(), "out", "The modified dataset." ) ); addConnector( m_output ); WModule::connectors(); } void WMDatasetManipulator::properties() { // Initialize the properties m_propCondition = boost::shared_ptr< WCondition >( new WCondition() ); m_showManipulators = m_properties->addProperty( "Show manipulators", "Hide/Show manipulators.", true, m_propCondition ); m_rotationMode = m_properties->addProperty( "Rotation mode", "Toggles rotation mode", false, m_propCondition ); m_groupTexManip = m_properties->addPropertyGroup( "Texture Manipulation", "Properties only related to the texture manipulation." ); m_translationX = m_groupTexManip->addProperty( "X translation", "", 0, m_propCondition ); m_translationX->setMax( 500 ); m_translationX->setMin( -500 ); m_translationY = m_groupTexManip->addProperty( "Y translation", "", 0, m_propCondition ); m_translationY->setMax( 500 ); m_translationY->setMin( -500 ); m_translationZ = m_groupTexManip->addProperty( "Z translation", "", 0, m_propCondition ); m_translationZ->setMax( 500 ); m_translationZ->setMin( -500 ); m_stretchX = m_groupTexManip->addProperty( "Voxel size X", "", 1.0, m_propCondition ); m_stretchX->setMax( 10. ); m_stretchX->setMin( -10. ); m_stretchY = m_groupTexManip->addProperty( "Voxel size Y", "", 1.0, m_propCondition ); m_stretchY->setMax( 10. ); m_stretchY->setMin( -10. ); m_stretchZ = m_groupTexManip->addProperty( "Voxel size Z", "", 1.0, m_propCondition ); m_stretchZ->setMax( 10. ); m_stretchZ->setMin( -10. ); m_rotationX = m_groupTexManip->addProperty( "X rotation", "", 0, m_propCondition ); m_rotationX->setMax( 180 ); m_rotationX->setMin( -180 ); m_rotationY = m_groupTexManip->addProperty( "Y rotation", "", 0, m_propCondition ); m_rotationY->setMax( 180 ); m_rotationY->setMin( -180 ); m_rotationZ = m_groupTexManip->addProperty( "Z rotation", "", 0, m_propCondition ); m_rotationZ->setMax( 180 ); m_rotationZ->setMin( -180 ); // TODO(schurade): activate this m_rotationX->setHidden( true ); m_rotationY->setHidden( true ); m_rotationZ->setHidden( true ); WModule::properties(); } void WMDatasetManipulator::init() { m_grid = m_input->getData()->getTexture()->getGrid(); std::pair< wmath::WVector3D, wmath::WVector3D >bb = m_grid->getBoundingBox(); wmath::WPosition center = wmath::WPosition( ( bb.second[0] - bb.first[0] ) / 2.0, ( bb.second[1] - bb.first[1] ) / 2.0, ( bb.second[2] - bb.first[2] ) / 2.0 ); m_knobCenter = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knobx1 = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knobx2 = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knoby1 = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knoby2 = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knobz1 = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knobz2 = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knobRotCenter = boost::shared_ptr( new WROISphere( center, 2.5 ) ); m_knobRot = boost::shared_ptr( new WROISphere( center, 2.5 ) ); setManipulatorsFromBoundingBox(); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knobCenter ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knobx1 ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knobx2 ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knoby1 ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knoby2 ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knobz1 ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knobz2 ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knobRotCenter ) ); WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *m_knobRot ) ); boost::function< void() > changeRoiSignal = boost::bind( &WMDatasetManipulator::manipulatorMoved, this ); m_knobCenter->addChangeNotifier( changeRoiSignal ); m_knobx1->addChangeNotifier( changeRoiSignal ); m_knobx2->addChangeNotifier( changeRoiSignal ); m_knoby1->addChangeNotifier( changeRoiSignal ); m_knoby2->addChangeNotifier( changeRoiSignal ); m_knobz1->addChangeNotifier( changeRoiSignal ); m_knobz2->addChangeNotifier( changeRoiSignal ); boost::function< void() > changeRotRoiSignal = boost::bind( &WMDatasetManipulator::manipulatorRotMoved, this ); m_knobRotCenter->addChangeNotifier( changeRotRoiSignal ); m_knobRot->addChangeNotifier( changeRotRoiSignal ); setManipulatorMode(); } void WMDatasetManipulator::setManipulatorsFromBoundingBox() { std::pair< wmath::WVector3D, wmath::WVector3D >bb = m_grid->getBoundingBox(); m_posCenter = wmath::WPosition( bb.first[0] + ( bb.second[0] - bb.first[0] ) / 2.0, bb.first[1] + ( bb.second[1] - bb.first[1] ) / 2.0, bb.first[2] + ( bb.second[2] - bb.first[2] ) / 2.0 ); m_posx1 = wmath::WPosition( bb.first[0], m_posCenter[1], m_posCenter[2] ); m_posx2 = wmath::WPosition( bb.second[0], m_posCenter[1], m_posCenter[2] ); m_posy1 = wmath::WPosition( m_posCenter[0], bb.first[1], m_posCenter[2] ); m_posy2 = wmath::WPosition( m_posCenter[0], bb.second[1], m_posCenter[2] ); m_posz1 = wmath::WPosition( m_posCenter[0], m_posCenter[1], bb.first[2] ); m_posz2 = wmath::WPosition( m_posCenter[0], m_posCenter[1], bb.second[2] ); m_knobCenter->setPosition( m_posCenter ); m_knobx1->setPosition( m_posx1 ); m_knobx2->setPosition( m_posx2 ); m_knoby1->setPosition( m_posy1 ); m_knoby2->setPosition( m_posy2 ); m_knobz1->setPosition( m_posz1 ); m_knobz2->setPosition( m_posz2 ); m_posCenterOrig = m_posCenter; m_posx1Orig = m_posx1; m_posx2Orig = m_posx2; m_posy1Orig = m_posy1; m_posy2Orig = m_posy2; m_posz1Orig = m_posz1; m_posz2Orig = m_posz2; m_posRotCenter = m_posCenter; m_posRot = wmath::WPosition( ( m_posCenter.x() + ( fabs( m_posCenter.x() - m_posx1.x() ) / 2.0 ) ), m_posx1.y(), m_posx1.z() ); m_posRotOrig = m_posRot; m_knobRotCenter->setPosition( m_posRotCenter ); m_knobRot->setPosition( m_posRot ); } void WMDatasetManipulator::setManipulatorMode() { m_knobx1->setLockX( false ); m_knobx1->setLockY( true ); m_knobx1->setLockZ( true ); m_knobx2->setLockX( false ); m_knobx2->setLockY( true ); m_knobx2->setLockZ( true ); m_knoby1->setLockY( false ); m_knoby1->setLockX( true ); m_knoby1->setLockZ( true ); m_knoby2->setLockY( false ); m_knoby2->setLockX( true ); m_knoby2->setLockZ( true ); m_knobz1->setLockZ( false ); m_knobz1->setLockY( true ); m_knobz1->setLockX( true ); m_knobz2->setLockZ( false ); m_knobz2->setLockY( true ); m_knobz2->setLockX( true ); if ( m_rotationMode->get( true ) ) { m_knobCenter->hide(); m_knobx1->hide(); m_knobx2->hide(); m_knoby1->hide(); m_knoby2->hide(); m_knobz1->hide(); m_knobz2->hide(); m_knobRotCenter->unhide(); m_knobRot->unhide(); } else { m_knobCenter->unhide(); m_knobx1->unhide(); m_knobx2->unhide(); m_knoby1->unhide(); m_knoby2->unhide(); m_knobz1->unhide(); m_knobz2->unhide(); m_knobRotCenter->hide(); m_knobRot->hide(); } } void WMDatasetManipulator::manipulatorMoved() { wmath::WPosition newOffset( m_knobCenter->getPosition() - m_posCenter ); m_knobx1->setPosition( m_knobx1->getPosition() + newOffset ); m_knobx2->setPosition( m_knobx2->getPosition() + newOffset ); m_knoby1->setPosition( m_knoby1->getPosition() + newOffset ); m_knoby2->setPosition( m_knoby2->getPosition() + newOffset ); m_knobz1->setPosition( m_knobz1->getPosition() + newOffset ); m_knobz2->setPosition( m_knobz2->getPosition() + newOffset ); wmath::WPosition stretch( 1.0, 1.0, 1.0 ); float orgsizex = static_cast( ( m_posx2Orig - m_posx1Orig ).x() ); float orgsizey = static_cast( ( m_posy2Orig - m_posy1Orig ).y() ); float orgsizez = static_cast( ( m_posz2Orig - m_posz1Orig ).z() ); m_grid->translate( wmath::WPosition( m_grid->getTranslate().x() + ( m_knobx1->getPosition().x() - m_posx1.x() ) * ( static_cast( m_grid->getNbCoordsX() / orgsizex ) ), m_grid->getTranslate().y() + ( m_knoby1->getPosition().y() - m_posy1.y() ) * ( static_cast( m_grid->getNbCoordsY() / orgsizey ) ), m_grid->getTranslate().z() + ( m_knobz1->getPosition().z() - m_posz1.z() ) * ( static_cast( m_grid->getNbCoordsZ() / orgsizez ) ) ) ); m_translationX->set( m_grid->getTranslate().x(), true ); m_translationY->set( m_grid->getTranslate().y(), true ); m_translationZ->set( m_grid->getTranslate().z(), true ); stretch.x() = ( m_knobx2->getPosition().x() - m_knobx1->getPosition().x() ) / orgsizex; stretch.y() = ( m_knoby2->getPosition().y() - m_knoby1->getPosition().y() ) / orgsizey; stretch.z() = ( m_knobz2->getPosition().z() - m_knobz1->getPosition().z() ) / orgsizez; m_grid->stretch( stretch ); m_stretchX->set( stretch.x(), true ); m_stretchY->set( stretch.y(), true ); m_stretchZ->set( stretch.z(), true ); adjustManipulatorPositions(); WDataHandler::getDefaultSubject()->getChangeCondition()->notify(); } void WMDatasetManipulator::manipulatorRotMoved() { wmath::WPosition newOffset( m_knobRotCenter->getPosition() - m_posRotCenter ); m_knobRot->setPosition( m_knobRot->getPosition() + newOffset ); wmath::WPosition p1 = ( m_posRotCenter - m_posRot ); m_posRotCenter = m_knobRotCenter->getPosition(); m_posRot = m_knobRot->getPosition(); wmath::WPosition p2 = ( m_posRotCenter - m_posRot ); osg::Matrixf rot; rot.makeRotate( p2, p1 ); m_grid->rotate( rot, m_posRotCenter ); WDataHandler::getDefaultSubject()->getChangeCondition()->notify(); } void WMDatasetManipulator::adjustManipulatorPositions() { float cx = m_knobx1->getPosition().x() + ( ( m_knobx2->getPosition().x() - m_knobx1->getPosition().x() ) / 2.0 ); float cy = m_knoby1->getPosition().y() + ( ( m_knoby2->getPosition().y() - m_knoby1->getPosition().y() ) / 2.0 ); float cz = m_knobz1->getPosition().z() + ( ( m_knobz2->getPosition().z() - m_knobz1->getPosition().z() ) / 2.0 ); m_knobCenter->setPosition( wmath::WPosition( cx, cy, cz ) ); m_knobx1->setY( cy ); m_knobx2->setY( cy ); m_knobx1->setZ( cz ); m_knobx2->setZ( cz ); m_knoby1->setX( cx ); m_knoby2->setX( cx ); m_knoby1->setZ( cz ); m_knoby2->setZ( cz ); m_knobz1->setY( cy ); m_knobz2->setY( cy ); m_knobz1->setX( cx ); m_knobz2->setX( cx ); m_posCenter = m_knobCenter->getPosition(); m_posx1 = m_knobx1->getPosition(); m_posx2 = m_knobx2->getPosition(); m_posy1 = m_knoby1->getPosition(); m_posy2 = m_knoby2->getPosition(); m_posz1 = m_knobz1->getPosition(); m_posz2 = m_knobz2->getPosition(); } void WMDatasetManipulator::moduleMain() { m_moduleState.setResetable( true, true ); m_moduleState.add( m_propCondition ); m_moduleState.add( m_active->getUpdateCondition() ); m_moduleState.add( m_input->getDataChangedCondition() ); ready(); while ( !m_shutdownFlag() ) { m_moduleState.wait(); if ( m_shutdownFlag() ) { break; } boost::shared_ptr< WDataSetSingle > newDataSet = m_input->getData(); bool dataChanged = ( m_dataSet != newDataSet ); bool dataValid = ( newDataSet ); if( dataValid ) { if( dataChanged ) { m_dataSet = newDataSet; init(); break; } } } while ( !m_shutdownFlag() ) { m_moduleState.wait(); if ( m_shutdownFlag() ) { break; } if ( m_active->changed() || m_showManipulators->changed() ) { if ( m_active->get( true ) && m_showManipulators->get( true ) ) { setManipulatorMode(); } else { m_knobCenter->hide(); m_knobx1->hide(); m_knobx2->hide(); m_knoby1->hide(); m_knoby2->hide(); m_knobz1->hide(); m_knobz2->hide(); m_knobRotCenter->hide(); m_knobRot->hide(); } } if ( m_rotationMode->changed() ) { setManipulatorMode(); } if ( m_translationX->changed() || m_translationY->changed() || m_translationZ->changed() ) { wmath::WPosition pos( m_translationX->get( true ), m_translationY->get( true ), m_translationZ->get( true ) ); m_grid->translate( pos ); setManipulatorsFromBoundingBox(); WDataHandler::getDefaultSubject()->getChangeCondition()->notify(); } if ( m_stretchX->changed() || m_stretchY->changed() || m_stretchZ->changed() ) { wmath::WPosition str( m_stretchX->get( true ), m_stretchY->get( true ), m_stretchZ->get( true ) ); m_grid->stretch( str ); setManipulatorsFromBoundingBox(); WDataHandler::getDefaultSubject()->getChangeCondition()->notify(); } if ( m_rotationX->changed() || m_rotationY->changed() || m_rotationZ->changed() ) { float pi = 3.14159265; float rotx = static_cast( m_rotationX->get( true ) ) / 180. * pi; float roty = static_cast( m_rotationY->get( true ) ) / 180. * pi; float rotz = static_cast( m_rotationZ->get( true ) ) / 180. * pi; wmath::WPosition rot( rotx, roty, rotz ); //grid->rotate( rot ); WDataHandler::getDefaultSubject()->getChangeCondition()->notify(); } } }