[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