Index: experimental/distortionNG/distortionNG.cpp
===================================================================
--- experimental/distortionNG/distortionNG.cpp	(revision 307)
+++ experimental/distortionNG/distortionNG.cpp	(revision 309)
@@ -1,9 +1,150 @@
 #include "distortionNG.h"
 
-distortionNG::distortionNG(void)
+#include<osg/Texture2D>
+#include<osg/Point>
+#include<osg/ComputeBoundsVisitor>
+
+#include<osgViewer/Viewer>
+
+#include<osgDB/ReadFile>
+
+#include <osgUtil/SmoothingVisitor>
+
+
+
+distortionNG::distortionNG()
 {
 }
 
-distortionNG::~distortionNG(void)
+distortionNG::~distortionNG()
 {
 }
+
+osg::Geometry* distortionNG::createMesh( unsigned int column, unsigned int row )
+{
+	osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(column * row);
+	osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array(column * row);
+	for ( unsigned int i=0; i<row; ++i )
+	{
+		for ( unsigned int j=0; j<column; ++j )
+		{
+			(*vertices)[i*column + j].set( (float)i, (float)j, 0.0f );
+			(*texcoords)[i*column + j].set( (float)i/(float)row, (float)j/(float)column );
+		}
+	}
+
+	osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
+	geom->setUseDisplayList( false );
+	geom->setUseVertexBufferObjects( true );
+	geom->setVertexArray( vertices.get() );
+	geom->setTexCoordArray( 0, texcoords.get() );
+	for ( unsigned int i=0; i<row-1; ++i )
+	{
+		osg::ref_ptr<osg::DrawElementsUInt> de = new osg::DrawElementsUInt(GL_QUAD_STRIP, column*2);
+		for ( unsigned int j=0; j<column; ++j )
+		{
+			(*de)[j*2 + 0] = i*column + j;
+			(*de)[j*2 + 1] = (i+1)*column + j;
+		}
+		geom->addPrimitiveSet( de.get() );
+	}
+
+
+
+	osg::ComputeBoundsVisitor cbv;
+	cbv.applyDrawable(geom);
+	osg::BoundingBox box = cbv.getBoundingBox();
+	if (!box.valid()) 
+		std::cout << "Invalid bounding box!"; 
+	geom->setInitialBound(box);
+
+	osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
+	texture->setImage( osgDB::readImageFile("Images/osg256.png") );
+	texture->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR );
+	texture->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR );
+	geom->getOrCreateStateSet()->setTextureAttributeAndModes( 0, texture.get() );
+
+	// Create normals
+	osgUtil::SmoothingVisitor::smooth( *geom );
+
+	return geom.release();
+}
+
+osg::Geode* distortionHandler::createVertexHighlighter()
+{
+	osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
+	(*colors)[0] = _highlightColor;
+
+	_highlighter = new osg::Geometry;
+	_highlighter->setDataVariance( osg::Object::DYNAMIC );
+	_highlighter->setUseDisplayList( false );
+	_highlighter->setUseVertexBufferObjects( true );
+	_highlighter->setVertexArray( new osg::Vec3Array(1) );
+	_highlighter->setColorArray( colors.get() );
+	_highlighter->setColorBinding( osg::Geometry::BIND_OVERALL );
+	_highlighter->addPrimitiveSet( new osg::DrawArrays(GL_POINTS, 0, 1) );
+
+	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
+	geode->addDrawable( _highlighter.get() );
+	geode->getOrCreateStateSet()->setAttributeAndModes( new osg::Point(10.0f) );
+	geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
+
+	return geode.release();
+}
+
+bool distortionHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
+{
+    if ( ea.getEventType()!=osgGA::GUIEventAdapter::RELEASE ||
+         ea.getButton()!=osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON ||
+         !(ea.getModKeyMask()&osgGA::GUIEventAdapter::MODKEY_CTRL) )
+        return false;
+    
+    osgViewer::View* viewer = dynamic_cast<osgViewer::View*>(&aa);
+    if ( viewer )
+    {
+        osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, ea.getX(), ea.getY());
+        osgUtil::IntersectionVisitor iv( intersector.get() );
+        viewer->getCamera()->accept( iv );
+        
+        if ( intersector->containsIntersections() )
+        {
+            osgUtil::LineSegmentIntersector::Intersection& result = *(intersector->getIntersections().begin());
+            computeSelectedVertex( result );
+        }
+    }
+    return false;
+}
+
+void distortionHandler::computeSelectedVertex( osgUtil::LineSegmentIntersector::Intersection& result )
+{
+	osg::Geometry* geom = dynamic_cast<osg::Geometry*>( result.drawable.get() );
+	if ( !geom || !_highlighter || geom==_highlighter )
+		return;
+
+	osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>( geom->getVertexArray() );
+	osg::Vec3Array* selVertices = dynamic_cast<osg::Vec3Array*>( _highlighter->getVertexArray() );
+	if ( !vertices || !selVertices )
+		return;
+
+	osg::Vec3 point = result.getWorldIntersectPoint();
+	osg::Matrix matrix = osg::computeLocalToWorld( result.nodePath );	// To compute the intersection vertices in world coordinates not in model coordinates
+	//std::cout << "Intersection-indices: Size=" << result.indexList.size() << std::endl;
+	const std::vector<unsigned int>& selIndices = result.indexList;
+	{
+		double maxRatio = 0.0;
+		int closestVertexIndex = 0;
+		for ( unsigned int i=0; i<3 && i<result.ratioList.size(); i++ )	//iterate through rations and search for max
+		{
+			if(result.ratioList[i] > maxRatio)
+			{
+				maxRatio = result.ratioList[i];
+				closestVertexIndex = result.indexList[i];
+			}
+		}
+		osg::Vec3 vertex = (*vertices)[closestVertexIndex] * matrix;
+		selVertices->front() = vertex;
+	}
+
+	selVertices->dirty();
+	_highlighter->dirtyBound(); 
+}
