/* OpenSceneGraph example, osganimate. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include class ControlPoints : public osg::Referenced { public: ControlPoints(): bottom_left(-1.0,-1.0), bottom_right(1.0,-1.0), top_left(-1.0,1.0), top_right(1.0,1.0) {} void reset() { bottom_left.set(-1.0,-1.0); bottom_right.set(1.0,-1.0); top_left.set(-1.0,1.0); top_right.set(1.0,1.0); } ControlPoints& operator = (const ControlPoints& rhs) { if (&rhs==this) return *this; bottom_left = rhs.bottom_left; bottom_right = rhs.bottom_right; top_left = rhs.top_left; top_right = rhs.top_right; return *this; } osg::Vec2d bottom_left; osg::Vec2d bottom_right; osg::Vec2d top_left; osg::Vec2d top_right; }; class Keystone : public osg::Referenced { public: Keystone(): translate(0.0,0.0), scale(1.0,1.0), taper(1.0,1.0), angle(0.0) { } void updateKeystone(ControlPoints cp) { // compute translation translate = (cp.bottom_left+cp.bottom_right+cp.top_left+cp.top_right)*0.25; // adjust control points to fit translation cp.top_left += translate; cp.top_right += translate; cp.bottom_right += translate; cp.bottom_left += translate; // compute scaling scale.x() = ( (cp.top_right.x()-cp.top_left.x()) + (cp.bottom_right.x()-cp.bottom_left.x()) )/4.0; scale.y() = ( (cp.top_right.y()-cp.bottom_right.y()) + (cp.top_left.y()-cp.bottom_left.y()) )/4.0; // adjust control points to fit scaling cp.top_left.x() *= scale.x(); cp.top_right.x() *= scale.x(); cp.bottom_right.x() *= scale.x(); cp.bottom_left.x() *= scale.x(); cp.top_left.y() *= scale.y(); cp.top_right.y() *= scale.y(); cp.bottom_right.y() *= scale.y(); cp.bottom_left.y() *= scale.y(); //angle = atan2(-cp.bottom_left.x(),(-cp.bottom_left.y()) //taper.x() = (cp.top_left-cp.bottom_left).length() / (cp.top_right-cp.bottom_right).length(); //taper.y() = (cp.top_right-cp.top_left).length() / (cp.bottom_right-cp.bottom_left).length(); OSG_NOTICE<<"translate="<top_left += delta; break; case(TOP): _currentControlPoints->top_left += delta; _currentControlPoints->top_right += delta; break; case(TOP_RIGHT): _currentControlPoints->top_right += delta; break; case(RIGHT): _currentControlPoints->top_right += delta; _currentControlPoints->bottom_right += delta; break; case(BOTTOM_RIGHT): _currentControlPoints->bottom_right += delta; break; case(BOTTOM): _currentControlPoints->bottom_right += delta; _currentControlPoints->bottom_left += delta; break; case(BOTTOM_LEFT): _currentControlPoints->bottom_left += delta; break; case(LEFT): _currentControlPoints->bottom_left += delta; _currentControlPoints->top_left += delta; break; case(CENTER): _currentControlPoints->bottom_left += delta; _currentControlPoints->top_left += delta; _currentControlPoints->bottom_right += delta; _currentControlPoints->top_right += delta; break; case(NONE_SELECTED): break; } _keystone->updateKeystone(*_currentControlPoints); return true; } return false; } case(osgGA::GUIEventAdapter::RELEASE): { OSG_NOTICE<<"Mouse released "<reset(); _currentControlPoints->reset(); _keystone->updateKeystone(*_currentControlPoints); } return false; } default: return false; } } int main( int argc, char **argv ) { osg::ArgumentParser arguments(&argc,argv); // initialize the viewer. osgViewer::Viewer viewer(arguments); osg::ref_ptr keystone = new Keystone; double distance, width, view_angle; if (arguments.read("-p",distance, width, view_angle)) { keystone->taper.x() = (2.0 + (width/distance) * sin(osg::inDegrees(view_angle))) / (2.0 - (width/distance) * sin(osg::inDegrees(view_angle))); //scale.x() = 1.0/cos(osg::inDegrees(view_angle)); OSG_NOTICE<<"scale "<scale<taper<angle)) { OSG_NOTICE<<"angle = "<angle<angle = osg::inDegrees(keystone->angle); } if (arguments.read("-t",keystone->translate.x(), keystone->translate.y())) { OSG_NOTICE<<"translate = "<translate<scale.x(), keystone->scale.y())) { OSG_NOTICE<<"scale = "<scale<taper.x(), keystone->taper.y())) { OSG_NOTICE<<"taper = "<taper< model = osgDB::readNodeFiles(arguments); if (!model) { OSG_NOTICE<<"No models loaded, please specify a model file on the command line"<setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); osg::Matrixd original_pm = viewer.getCamera()->getProjectionMatrix(); viewer.addEventHandler(new KeystoneHandler(keystone)); while(!viewer.done()) { viewer.advance(); viewer.eventTraversal(); viewer.updateTraversal(); if (keystone.valid()) { viewer.getCamera()->setProjectionMatrix(original_pm * keystone->computeKeystoneMatrix()); } viewer.renderingTraversals(); } return 0; }