Actually, I can share it here. It was written for non-commercial purpose.
See attached

Nick


On Thu, Jun 19, 2014 at 9:57 AM, Trajce Nikolov NICK <
[email protected]> wrote:

> Hi Nikita,
>
> I have sample of that. Ping me on my email I can share my sample with you
>
> Nick
>
>
> On Thu, Jun 19, 2014 at 9:51 AM, Robert Osfield <[email protected]>
> wrote:
>
>> HI Nikita,
>>
>> The way to do overlays like this is to render using a Camera with an
>> orthographic projection that effectively creates a 2D view, then just
>> create the geometry your draw in the standard OSG way using Nodes,
>> Geometry and StateSet as you'd do with a 3D scene graph.  The osghud
>> example shows various ways of creating this extra view.  The OSG's
>> onscreen stats also has a frame rate profile chart that is similar to
>> what you'll need to show, have a look at
>> src/osgViewer/StatsHandler.cpp.
>>
>> Robert.
>>
>> On 19 June 2014 08:28, Nikita Petrov <[email protected]> wrote:
>> > Hi,
>> >
>> > I'm developing application with osgEarth. What I want to do now is a
>> plane flying in the sky and in the bottom of the screen I want to show
>> vertical profile of the flight H(t). I've tried to find something to draw
>> charts on overlay (HUD) in OSG, but found nothing! I don't believe that
>> there is no such basic thing in OSG.
>> > The question is how I should do it? What is the easiest way? I'm
>> working with 3D graphics only for several months, so I'm at the beginner
>> level. :)
>> >
>> > Thank you!
>> >
>> > Cheers,
>> > Nikita
>> >
>> > ------------------
>> > Read this topic online here:
>> > http://forum.openscenegraph.org/viewtopic.php?p=59808#59808
>> >
>> >
>> >
>> >
>> >
>> > _______________________________________________
>> > osg-users mailing list
>> > [email protected]
>> >
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>> _______________________________________________
>> osg-users mailing list
>> [email protected]
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>
>
>
>
> --
> trajce nikolov nick
>



-- 
trajce nikolov nick
#include <Windows.h>

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>

#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>

#include <osgGA/TrackballManipulator>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/Camera>
#include <osg/RenderInfo>

#include <osgDB/WriteFile>

#include <osgText/Text>

#define NORMALIZE_RANDOM_SIGNAL_Y	100
#define SIGNALS_PER_SECOND			250

class ThreadSignalDataPipe : public OpenThreads::Thread, public osg::Referenced
{
public:
	ThreadSignalDataPipe(const osg::Vec4& window, unsigned int size = 300)
		: OpenThreads::Thread()
		, m_ThreadIsRunning(false)
		, m_X(0.f)
		, m_Size(size)
		, m_Vertices( new osg::Vec3Array )
		, m_Window(window)
	{
		for ( unsigned int i=0; i<m_Size; ++i )
		{
			m_Vertices->push_back(osg::Vec3(window.x()+m_X++,window.y(),0.f));
		}
	}

	typedef std::vector<float>					SignalData;
	typedef std::vector<float>::iterator		SignalDataIterator;
	typedef std::vector<float>::const_iterator	SignalDataConstIterator;

	virtual void addData(const SignalData& data)
	{
		OpenThreads::ScopedLock<OpenThreads::Mutex> lock(m_Mutex);
		m_Data.clear();
		m_Data.insert(m_Data.end(), data.begin(), data.end());
	}

	virtual void run()
	{
		m_ThreadIsRunning = true;

		while (m_ThreadIsRunning)
		{
			{
				OpenThreads::ScopedLock<OpenThreads::Mutex> lock(m_Mutex);

				if (m_Data.size())
				{
					float signal = m_Data.front();
					m_Data.erase(m_Data.begin());

#if 0
					m_Vertices->erase( m_Vertices->begin() );
					m_Vertices->push_back( osg::Vec3(m_Window.x()+m_X++,m_Window.y()+signal,0.f) );
#else
					(*m_Vertices)[(int)m_X] = osg::Vec3(m_Window.x()+m_X++,m_Window.y()+signal,0.f);
#endif

				}
				else
				{
#if 0
					m_Vertices->erase( m_Vertices->begin() );
					m_Vertices->push_back( osg::Vec3(m_Window.x()+m_X++,m_Window.y(),0.f) );
#else
					(*m_Vertices)[(int)m_X] = osg::Vec3(m_Window.x()+m_X++,m_Window.y(),0.f);
#endif
				}
				if (m_X >= m_Size)
				{
					m_X = 0.f;
				}

			}

			OpenThreads::Thread::microSleep(100);
		}

		m_ThreadIsRunning = false;

		cancel();
	}

	bool isRunning() const
	{
		return m_ThreadIsRunning;
	}

	void setIsRunning(bool running)
	{
		m_ThreadIsRunning = running;
	}

	osg::Vec3Array* getVertexArray() const
	{
		return m_Vertices.get();
	}

	float getSliderPosition() const
	{
		return m_X;
	}

	osg::Vec4 getWindow() const
	{
		return m_Window;
	}

	OpenThreads::Mutex& getMutex() const
	{
		return m_Mutex;
	}

protected:
	mutable OpenThreads::Mutex		m_Mutex;
	SignalData						m_Data;
	bool							m_ThreadIsRunning;
	float							m_X;
	unsigned int					m_Size;
	osg::ref_ptr< osg::Vec3Array >	m_Vertices;
	osg::Vec4						m_Window;
};

class DataGeneratorThread : public OpenThreads::Thread, public osg::Referenced
{
public:
	DataGeneratorThread(unsigned int numOfSignalsPerChunk = SIGNALS_PER_SECOND)
		: OpenThreads::Thread()
		, osg::Referenced()
		, m_ThreadIsRunning(false)
		, m_NumOfSignalsPerChunk(numOfSignalsPerChunk)
	{
	}

	virtual ~DataGeneratorThread()
	{
		DataPipesIterator itr = m_DataPipes.begin();
		for ( ; itr != m_DataPipes.end(); ++itr )
		{
			(**itr).setIsRunning( false );
			while ((**itr).isRunning());
			OpenThreads::Thread::microSleep(100000);
		}
		m_DataPipes.clear();
	}

	typedef std::vector< osg::ref_ptr<ThreadSignalDataPipe> >					DataPipes;
	typedef std::vector< osg::ref_ptr<ThreadSignalDataPipe> >::iterator			DataPipesIterator;
	typedef std::vector< osg::ref_ptr<ThreadSignalDataPipe> >::const_iterator	DataPipesConstIterator;

	void addDataPipe( ThreadSignalDataPipe* dataPipe )
	{
		m_DataPipes.push_back( dataPipe );
	}

	virtual void run()
	{
		m_ThreadIsRunning = true;

		while (m_ThreadIsRunning)
		{
			DataPipesIterator itr = m_DataPipes.begin();
			for ( ; itr != m_DataPipes.end(); ++itr )
			{
				ThreadSignalDataPipe::SignalData chunk;

				for ( unsigned int i=0; i<m_NumOfSignalsPerChunk; ++i )
				{
#if 0
					chunk.push_back( rand() % NORMALIZE_RANDOM_SIGNAL_Y );
#else
					if (i==0)
					{
						chunk.push_back(0);

					}
					else
					{
						int sign = rand() % 2;
						switch (sign)
						{
						case 0:
							sign = -1;
							break;
						case 1:
							sign = 1;
							break;
						}
						chunk.push_back(chunk.at(chunk.size()-1)+sign*(rand() % NORMALIZE_RANDOM_SIGNAL_Y/5));
					}
#endif
				}

				(**itr).addData( chunk );
			}
			OpenThreads::Thread::microSleep((1.f/SIGNALS_PER_SECOND)*1000000);
		}

		m_ThreadIsRunning = false;

		cancel();
	}

	bool isRunning() const
	{
		return m_ThreadIsRunning;
	}

	void setIsRunning(bool running)
	{
		m_ThreadIsRunning = running;
	}

protected:
	bool						m_ThreadIsRunning;
	DataPipes					m_DataPipes;
	unsigned int				m_NumOfSignalsPerChunk;
};

class GeometryUpdateCallback : public osg::Geometry::UpdateCallback
{
public:
	GeometryUpdateCallback( ThreadSignalDataPipe* pipe )
		: m_Pipe(pipe)
	{
	}

	virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)
	{
		osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
		if (!geometry) return;

		OpenThreads::ScopedLock<OpenThreads::Mutex> lock(m_Pipe->getMutex());
		float slider = m_Pipe->getSliderPosition();

		osg::Vec3Array* vertices = new osg::Vec3Array;
		vertices->insert( vertices->end(), m_Pipe->getVertexArray()->begin(), m_Pipe->getVertexArray()->end() );
		vertices->push_back( osg::Vec3( m_Pipe->getWindow().x()+slider, m_Pipe->getWindow().y(), 0.f ) );
		vertices->push_back( osg::Vec3( m_Pipe->getWindow().x()+slider, m_Pipe->getWindow().y()+150, 0.f ) );
		geometry->setVertexArray(vertices);
		geometry->removePrimitiveSet(0,2);
		geometry->addPrimitiveSet( new osg::DrawArrays( GL_LINE_STRIP, 0, m_Pipe->getVertexArray()->size() ) );
		geometry->addPrimitiveSet( new osg::DrawArrays( GL_LINES, m_Pipe->getVertexArray()->size(), 2 ) );
	}

protected:
	ThreadSignalDataPipe*	m_Pipe;
};

osg::ref_ptr< DataGeneratorThread > dataGeneratorThread = 0;

osg::Geometry* createSignalControl( float x, float y, const osg::Vec4& color, unsigned int size )
{
	ThreadSignalDataPipe* pipe = new ThreadSignalDataPipe(osg::Vec4(x,y,0,0),size);
	pipe->startThread();

	dataGeneratorThread->addDataPipe( pipe );

	osg::Geometry* geometry = new osg::Geometry;
	geometry->setVertexArray(pipe->getVertexArray());
	geometry->addPrimitiveSet( new osg::DrawArrays( GL_LINE_STRIP, 0, pipe->getVertexArray()->size() ) );
	geometry->addPrimitiveSet( new osg::DrawArrays( GL_LINES, pipe->getVertexArray()->size(), 2 ) );
	geometry->setUseDisplayList( false );
	geometry->setUseVertexBufferObjects( false );
	geometry->setUpdateCallback( new GeometryUpdateCallback(pipe) );

	osg::Vec4Array* colors = new osg::Vec4Array;
	colors->push_back(color);
	colors->push_back(osg::Vec4(0,0,0,1));
	geometry->setColorArray(colors);
	geometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);

	return geometry;
}

osg::Camera* createHUD()
{
    // create a camera to set up the projection and model view matrices, and the subgraph to draw in the HUD
    osg::Camera* camera = new osg::Camera;

    // set the projection matrix
    camera->setProjectionMatrix(osg::Matrix::ortho2D(0,800,0,600));

    // set the view matrix    
    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    camera->setViewMatrix(osg::Matrix::identity());

    // only clear the depth buffer
    camera->setClearMask(GL_DEPTH_BUFFER_BIT);

    // draw subgraph after main camera view.
    camera->setRenderOrder(osg::Camera::POST_RENDER);

    // we don't want the camera to grab event focus from the viewers main camera(s).
    camera->setAllowEventFocus(false);

    // add to this camera a subgraph to render
    {

        osg::Geode* geode = new osg::Geode();

        // turn lighting off for the text and disable depth test to ensure it's always ontop.
        osg::StateSet* stateset = geode->getOrCreateStateSet();
        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

		dataGeneratorThread = new DataGeneratorThread;

		{
			
			geode->addDrawable( createSignalControl( 100, 100, osg::Vec4(1,0,0,1),300 ) );
			geode->addDrawable( createSignalControl( 100, 300, osg::Vec4(1,0,1,1),300 ) );
			geode->addDrawable( createSignalControl( 500, 300, osg::Vec4(0,0,1,1),200 ) );
			geode->addDrawable( createSignalControl( 500, 100, osg::Vec4(0,1,0,1),200 ) );
			geode->addDrawable( createSignalControl( 100, 500, osg::Vec4(0,1,1,1),300 ) );
			geode->addDrawable( createSignalControl( 500, 500, osg::Vec4(1,1,0,1),200 ) );

		}
        camera->addChild(geode);

		dataGeneratorThread->startThread();
    }

    return camera;
}

int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);


    // read the scene from the list of file specified commandline args.
	osg::ref_ptr<osg::Node> scene = new osg::Group;
    
    {
        // construct the viewer.
        osgViewer::Viewer viewer;
		viewer.setUpViewInWindow( 100, 100, 800, 600 );
        
        osg::ref_ptr<osg::Group> group  = new osg::Group;

        // add the HUD subgraph.    
        if (scene.valid()) group->addChild(scene.get());
        group->addChild(createHUD());

        // set the scene to render
        viewer.setSceneData(group.get());

		// white color
		viewer.getCamera()->setClearColor(osg::Vec4(1,1,1,1));

		viewer.run();

		dataGeneratorThread->setIsRunning( false );
		while ( dataGeneratorThread->isRunning() );
		dataGeneratorThread->microSleep(10000);
		dataGeneratorThread = 0;

		return 0;
    }
    
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to