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
#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(); } } }
_______________________________________________ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org