/* 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 #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) { } double angleBetweenVectors(const osg::Vec2d& v1, const osg::Vec2d& v2) const { osg::Vec2d v3(-v2.y(), v2.x()); double p1 = v1*v2; double p2 = v1*v3; double a = atan2(p2, p1); return a; } osg::Vec2d rotateVector(osg::Vec2d& v, double s, double c) const { return osg::Vec2d(v.x()*c-v.y()*s, v.y()*c+v.x()*s); } 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; angle = (angleBetweenVectors(cp.top_left, osg::Vec2d(-1.0,1.0)) + angleBetweenVectors(cp.top_right, osg::Vec2d(1.0,1.0)) + angleBetweenVectors(cp.bottom_right, osg::Vec2d(1.0,-1.0)) + angleBetweenVectors(cp.bottom_left, osg::Vec2d(-1.0,-1.0)))*0.25; OSG_NOTICE<<"cp.top_left="<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"< group = new osg::Group; group->addChild(model.get()); double screenWidth = osg::DisplaySettings::instance()->getScreenWidth(); double screenHeight = osg::DisplaySettings::instance()->getScreenHeight(); double screenDistance = osg::DisplaySettings::instance()->getScreenDistance(); double fovy = osg::RadiansToDegrees(2.0*atan2(screenHeight/2.0,screenDistance)); double aspectRatio = screenWidth/screenHeight; osg::ref_ptr camera = new osg::Camera; camera->setClearMask(0x0); camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); camera->setProjectionMatrixAsPerspective(fovy, aspectRatio, 0.1, 1000.0); camera->addChild(createGrid(osg::Vec3(-screenWidth*0.5, -screenHeight*0.5, -screenDistance), osg::Vec3(screenWidth, 0.0, 0.0), osg::Vec3(0.0, screenHeight, 0.0), osg::Vec4(1.0,0.0,0.0,1.0))); viewer.setSceneData(group.get()); // add the state manipulator viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); // add the stats handler viewer.addEventHandler(new osgViewer::StatsHandler); // add camera manipulator viewer.setCameraManipulator(new osgGA::TrackballManipulator()); viewer.realize(); viewer.getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); osg::Matrixd original_pm = viewer.getCamera()->getProjectionMatrix(); osg::Matrixd original_grid_pm = camera->getProjectionMatrix(); group->addChild(camera.get()); // Add keystone handler viewer.addEventHandler(new KeystoneHandler(keystone)); while(!viewer.done()) { viewer.advance(); viewer.eventTraversal(); viewer.updateTraversal(); if (keystone.valid()) { viewer.getCamera()->setProjectionMatrix(original_pm * keystone->computeKeystoneMatrix()); camera->setProjectionMatrix(original_grid_pm * keystone->computeKeystoneMatrix()); } viewer.renderingTraversals(); } return 0; }