[osg-users] Setting view matrix seems to lag behind on frame

Sebastian Messerschmidt sebastian.messerschmidt at gmx.de
Tue Dec 1 07:59:00 PST 2015


Hi Robert,

I've attached a small example, where I try to set the view matrix in a 
way, the camera always faces a certain direction.
Unfortunately it seems, the view matrix I supply is applied one frame 
too late.

(The camera should always face the geometry, so there should be a cross 
made of blue and a green line)

Is there something wrong with the way I supply the view matrix?

Cheers
Sebastian
-------------- next part --------------
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Array>
#include <osgGA/CameraManipulator>
#include <osgGA/TrackballManipulator>
#include <osg/Drawable>
#include <osg/LineWidth>



class SetCameraManipulator : public osgGA::CameraManipulator
{
public:
	SetCameraManipulator() 
		: osgGA::CameraManipulator()
	{
	}

	void setByMatrix( const osg::Matrixd& matrix )			
	{
		mMatrix  = matrix;
	}

	void setByInverseMatrix( const osg::Matrixd& matrix )	
	{ 
		setByMatrix( osg::Matrixd::inverse(matrix) );
	}

	osg::Matrixd getMatrix() const			
	{ 
		return mMatrix;
	}

	osg::Matrixd getInverseMatrix() const
	{ 
		return osg::Matrixd::inverse(mMatrix);
	} 

	bool handle( const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa )
	{
		return false;
	}

	void computePosition( const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up )
	{
		//empty
	}

private:
	osg::Matrixd mMatrix;
};


osg::Vec3 findPerpendicular(const osg::Vec3& v)
{
	osg::Vec3 p1(v.z(), v.z(), -v.x()-v.y());
	osg::Vec3 p2(-v.y()-v.z(), v.x(), v.x());
	if (osg::equivalent(p2.length(), 0))
	{
		p1.normalize();
		return p1;
	}
	p2.normalize();
	return p2;
}




osg::ref_ptr<osg::Geode> createCross()
{
	osg::ref_ptr<osg::Geode> normal_vis = new osg::Geode;
	osg::Vec3Array* vec3_array = new osg::Vec3Array(6);
	(*vec3_array)[0] = osg::Vec3(0,0,0);
	(*vec3_array)[1] = osg::Vec3(0,0,1);
	(*vec3_array)[2] = osg::Vec3(0,-1,1);
	(*vec3_array)[3] = osg::Vec3(0,1,1);
	(*vec3_array)[4] = osg::Vec3(-1,0,1);
	(*vec3_array)[5] = osg::Vec3(1,0,1);
	osg::Vec4Array* col_array = new osg::Vec4Array(6);
	(*col_array)[0] = osg::Vec4(1,0,0,1);
	(*col_array)[1] = osg::Vec4(1,0,0,1);
	(*col_array)[2] = osg::Vec4(0,1,0,1);
	(*col_array)[3] = osg::Vec4(0,1,0,1);
	(*col_array)[4] = osg::Vec4(0,0,1,1);
	(*col_array)[5] = osg::Vec4(0,0,1,1);
	osg::Geometry* mesh_geometry = new osg::Geometry;
	normal_vis->addDrawable(mesh_geometry);
	mesh_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 6));
	mesh_geometry->setVertexArray(vec3_array);
	mesh_geometry->setColorArray(col_array, osg::Array::BIND_PER_VERTEX);
	mesh_geometry->setUseVertexBufferObjects(true);	
	normal_vis->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(5));
	normal_vis->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
	return normal_vis;
}
/// retrieve a random vector in the unit cube. 
osg::Vec3 randomVec()
{
	return osg::Vec3(static_cast<float>(rand()) / RAND_MAX, static_cast<float>(rand()) / RAND_MAX, static_cast<float>(rand()) /RAND_MAX);
}

int main(int argc, char** argv)
{
	osgViewer::Viewer viewer;
	
	viewer.setUpViewInWindow(110,110,256,256,0);
	
	osg::Group* root = new osg::Group;
	viewer.setSceneData(root);

	osg::ref_ptr<osg::Geode> normal_vis = createCross();
	root->addChild(normal_vis);
	///set out matrix-camera manipulator
	SetCameraManipulator* scm = new SetCameraManipulator;
	viewer.setCameraManipulator(scm);
	//viewer.setCameraManipulator(new osgGA::TrackballManipulator);
	viewer.getCamera()->setProjectionMatrixAsPerspective(45.0,1,0.01, 1000.0);


	std::vector<osg::Vec3> random_points;
	std::vector<osg::Vec3> random_normals;
	
	for (unsigned int i = 0; i < 100; ++i)
	{
		random_points.push_back(randomVec());
		osg::Vec3d normal = randomVec();
		normal.normalize();
		random_normals.push_back(normal);
	}

	osg::Matrix mat;

	viewer.realize();
	while (!viewer.done())
	{
	
		for(unsigned int i = 0; i < random_points.size(); ++i)
		{
			osg::Vec3d normal = random_normals[i];
			osg::Vec3d pos	  = random_points[i];
				
				
			osg::Vec3 perp = findPerpendicular(normal);

			//set the camera manipulator to look at the pos with the given direction
			mat.makeLookAt(pos + normal * 2, pos, perp);
			scm->setByInverseMatrix(mat);
			//viewer.getCamera()->setViewMatrixAsLookAt(pos, pos + normal, perp);
				
			//update the normal;
			osg::Vec3Array* vec3_array = dynamic_cast<osg::Vec3Array*>(normal_vis->getDrawable(0)->asGeometry()->getVertexArray());
			(*vec3_array)[0] = pos;
			(*vec3_array)[1] = pos + normal;

			(*vec3_array)[2] = pos  + perp;
			(*vec3_array)[3] = pos  - perp;
				
			osg::Vec3 cross = (perp ^ normal);
			(*vec3_array)[4] = pos + cross;
			(*vec3_array)[5] = pos - cross;
				
			vec3_array->dirty();
			normal_vis->dirtyBound();
			
				
			//if we do this, we get the correct view every like 2 frames
			//with only one frame call, we seem to lag behind. I.e. the view matrix is applied the frame after the current-
			viewer.frame();
			viewer.frame();
			
		}
		
	}
}


More information about the osg-users mailing list