VirtualCamera.cpp
Go to the documentation of this file.
00001 /* 
00002  * Copyright (c) 2013 University of Jaume-I.
00003  * All rights reserved. This program and the accompanying materials
00004  * are made available under the terms of the GNU Public License v3.0
00005  * which accompanies this distribution, and is available at
00006  * http://www.gnu.org/licenses/gpl.html
00007  * 
00008  * Contributors:
00009  *     Mario Prats
00010  *     Javier Perez
00011  */
00012 
00013 #include <uwsim/VirtualCamera.h>
00014 #include <uwsim/UWSimUtils.h>
00015 #include <uwsim/SceneBuilder.h>
00016 #include <iostream>
00017 
00018 #include <osg/PositionAttitudeTransform>
00019 
00020 class UpdateUnderWater : public osg::Uniform::Callback
00021 {
00022 public:
00023   UpdateUnderWater(osg::Camera* camera) :
00024       mCamera(camera)
00025   {
00026   }
00027   virtual void operator ()(osg::Uniform* u, osg::NodeVisitor*)
00028   {
00029     u->set(true); //TODO: Should check waterheight!!
00030   }
00031 
00032 protected:
00033   osg::Camera* mCamera;
00034 };
00035 
00036 class UpdateNoiseSeed : public osg::Uniform::Callback
00037 {
00038 public:
00039   UpdateNoiseSeed()
00040   {
00041   }
00042   virtual void operator ()(osg::Uniform* u, osg::NodeVisitor*)
00043   {
00044     u->set(osg::Vec4f(rand()/(float)RAND_MAX,rand()/(float)RAND_MAX,rand()/(float)RAND_MAX,rand()/(float)RAND_MAX));
00045   }
00046 
00047 protected:
00048 };
00049 
00050 class UpdateEye : public osg::Uniform::Callback
00051 {
00052 public:
00053   UpdateEye(osg::Camera* camera) :
00054       mCamera(camera)
00055   {
00056   }
00057   virtual void operator ()(osg::Uniform* u, osg::NodeVisitor*)
00058   {
00059     osg::Vec3d eye, center, up;
00060     mCamera->getViewMatrixAsLookAt(eye, center, up);
00061     u->set(eye);
00062   }
00063 
00064 protected:
00065   osg::Camera* mCamera;
00066 };
00067 
00068 class UpdateVMI : public osg::Uniform::Callback
00069 {
00070 public:
00071   UpdateVMI(osg::Camera* camera) :
00072       mCamera(camera)
00073   {
00074   }
00075   virtual void operator ()(osg::Uniform* u, osg::NodeVisitor*)
00076   {
00077     u->set(mCamera->getInverseViewMatrix());
00078   }
00079 
00080 protected:
00081   osg::Camera* mCamera;
00082 };
00083 
00084 VirtualCamera::VirtualCamera()
00085 {
00086 }
00087 
00088 void VirtualCamera::init(osg::Group *uwsim_root, std::string name, std::string parentName, osg::Node *trackNode, int width,
00089                          int height, double baseline, std::string frameId, Parameters *params, int range, double fov,
00090                          double aspectRatio, double near, double far, int bw, int widget, SceneBuilder *oscene, float std)
00091 {
00092   this->uwsim_root = uwsim_root;
00093   this->name = name;
00094   this->parentLinkName=parentName;
00095   this->std=std;
00096 
00097   this->trackNode = trackNode;
00098   //Add a switchable frame geometry on the camera frame
00099   osg::ref_ptr < osg::Node > axis = UWSimGeometry::createSwitchableFrame();
00100   //Add label to switchable frame
00101   axis->asGroup()->addChild(UWSimGeometry::createLabel(name));
00102   this->trackNode->asGroup()->addChild(axis);
00103 
00104   this->width = width;
00105   this->height = height;
00106   this->baseline = baseline;
00107   this->frameId = frameId;
00108   this->fov = fov;
00109   this->aspectRatio = aspectRatio;
00110   this->near = near;
00111   this->far = far;
00112   if (params != NULL)
00113   {
00114     this->fx = params->fx;
00115     this->fy = params->fy;
00116     this->far = params->f;
00117     this->near = params->n;
00118     this->cx = params->x0;
00119     this->cy = params->y0;
00120     this->k = params->k;
00121     this->paramsOn = 1;
00122   }
00123   else
00124     this->paramsOn = 0;
00125   this->range = range;
00126   this->bw = bw;
00127   this->widget = widget;
00128 
00129   if (!range)
00130   {
00131     renderTexture = new osg::Image();
00132     renderTexture->allocateImage(width, height, 1, GL_RGB, GL_UNSIGNED_BYTE);
00133   }
00134   else
00135   {
00136     depthTexture = new osg::Image();
00137     depthTexture->allocateImage(width, height, 1, GL_DEPTH_COMPONENT, GL_FLOAT);
00138   }
00139 
00140   createCamera();
00141   //Add a cull mask to hide Augmented Reality objects from virtual cameras
00142   if(oscene)
00143     textureCamera->setCullMask(~oscene->scene->getOceanScene()->getARMask());
00144   loadShaders(oscene);
00145 }
00146 
00147 VirtualCamera::VirtualCamera(osg::Group *uwsim_root, std::string name,std::string parentName, osg::Node *trackNode, int width,
00148                              double fov, double range)
00149 { //Used in multibeam
00150   //Z-buffer has very low resolution near far plane so we extend it and cut far plane later.
00151   init(uwsim_root, name, parentName, trackNode, 1, width, 0.0, "", NULL, 1, fov, 1.0 / width, 0.8, range * 1.2, 0, 0,NULL,0);
00152 
00153 }
00154 
00155 VirtualCamera::VirtualCamera(osg::Group *uwsim_root, std::string name,std::string parentName, osg::Node *trackNode, int width,
00156                              int height, double fov, double aspectRatio)
00157 { //Used in structured light projector as shadow camera
00158   init(uwsim_root, name, parentName, trackNode, width, height, 0.0, "", NULL, 1, fov, aspectRatio, 0.1, 20, 0, 0,NULL,0);
00159 }
00160 
00161 VirtualCamera::VirtualCamera(osg::Group *uwsim_root, std::string name,std::string parentName, osg::Node *trackNode, int width,
00162                              int height,double baseline, std::string frameId,double fov,SceneBuilder *oscene,float std,  Parameters *params=NULL, int range=0, int bw=0)
00163 {//Standard camera / depth camera
00164   init(uwsim_root, name, parentName, trackNode, width, height, baseline, frameId, params, range, fov, width/(float)height, 0.18, 20, bw, 1,oscene,std);
00165 }
00166 
00167 void VirtualCamera::createCamera()
00168 {
00169   textureCamera = new osg::Camera;
00170   textureCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
00171   textureCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00172   textureCamera->setViewport(0, 0, width, height);
00173 
00174   // Frame buffer objects are the best option
00175   textureCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
00176 
00177   // We need to render to the texture BEFORE we render to the screen
00178   textureCamera->setRenderOrder(osg::Camera::PRE_RENDER);
00179 
00180   // The camera will render into the texture that we created earlier
00181   if (!range)
00182     textureCamera->attach(osg::Camera::COLOR_BUFFER, renderTexture.get());
00183   else
00184     textureCamera->attach(osg::Camera::DEPTH_BUFFER, depthTexture.get());
00185 
00186   textureCamera->setName("CamViewCamera");
00187   textureCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
00188 
00189   if (!paramsOn)
00190   {
00191     //set default fov, near and far parameters (default parameters on init function as some of them change depending on camera type (shadow,depth,texture))
00192     textureCamera->setProjectionMatrixAsPerspective(fov, aspectRatio, near, far);
00193     osg::Matrixd m;
00194     m = textureCamera->getProjectionMatrix();
00195     fx = m(0, 0) * width / 2.0;
00196     fy = m(1, 1) * height / 2.0;
00197     cx = -(m(0, 2) - 1) * width / 2.0;
00198     cy = -(m(1, 2) - 1) * height / 2.0;
00199   }
00200   else
00201   {
00202     //set opengl projection matrix from calibration parameters fx, fy, w, h, x0, y0, n
00203     // How to obtain opengl projection matrix from camera calibration parameters:
00204     // 2.0*fx/w    2.0*k/w    1-2*x0/w       0
00205     // 0          2.0*fy/h   1-2*y0/h       0
00206     // 0           0          (f+n)/(n-f)    2*fn/(n-f)
00207     // 0           0         -1              0
00208     //osg::Matrixd m(2.0*fx/width,2.0*k/width,1-(2*cx/width),0,0,2.0*fy/height,1-(2.0*cy/height),0,0,0,(far+near)/(near-far),2*far*near/(near-far),0,0,-1,0); //osg Uses trasposed matrix
00209     osg::Matrixd m(2.0 * fx / width, 0, 0, 0, 2.0 * k / width, 2.0 * fy / height, 0, 0, 1 - (2 * cx / width),
00210                    1 - (2.0 * cy / height), (far + near) / (near - far), -1, 0, 0, 2 * far * near / (near - far), 0);
00211     textureCamera->setProjectionMatrix(m);
00212 
00213   }
00214 
00215   Tx = (-fx * baseline);
00216   Ty = 0.0;
00217 
00218   node_tracker = new MyNodeTrackerCallback(uwsim_root, depthTexture, textureCamera);
00219   trackNode->setEventCallback(node_tracker);
00220 
00221   //Uniforms for independence from main camera (underwater effects on shaders)
00222   osg::Uniform* u = new osg::Uniform("osgOcean_EyeUnderwater", true);
00223   u->setUpdateCallback(new UpdateUnderWater(textureCamera));
00224 
00225   textureCamera->getOrCreateStateSet()->addUniform(u);
00226   osg::Vec3d eye, center, up;
00227   textureCamera->getViewMatrixAsLookAt(eye, center, up);
00228   osg::Uniform* u2 = new osg::Uniform("osgOcean_Eye", eye);
00229   u2->setUpdateCallback(new UpdateEye(textureCamera));
00230   textureCamera->getOrCreateStateSet()->addUniform(u2);
00231 
00232   osg::Uniform* u3 = new osg::Uniform("osg_ViewMatrixInverse", textureCamera->getInverseViewMatrix());
00233   u3->setUpdateCallback(new UpdateVMI(textureCamera));
00234   textureCamera->getOrCreateStateSet()->addUniform(u3);
00235 }
00236 
00237 void VirtualCamera::loadShaders(SceneBuilder *oscene)
00238 {
00239 
00240   if(oscene)
00241   {
00242     static const char model_vertex[] = "default_scene.vert";
00243     static const char model_fragment[] = "default_scene.frag";
00244     osg::Program* program = osgOcean::ShaderManager::instance().createProgram("object_shader", model_vertex,model_fragment, "", "");
00245 
00246     textureCamera->getOrCreateStateSet()->setAttributeAndModes(program, osg::StateAttribute::ON);
00247 
00248     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_EnableGlare", oscene->scene->getOceanScene()->isGlareEnabled()) );
00249     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_EnableUnderwaterScattering", oscene->scene->getOceanScene()->isUnderwaterScatteringEnabled()) );
00250     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_EnableDOF", oscene->scene->getOceanScene()->isUnderwaterDOFEnabled()) );
00251  
00252     float UWFogDensity= oscene->scene->getOceanScene()->getUnderwaterFogDensity();
00253     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_UnderwaterFogDensity", -UWFogDensity*UWFogDensity*1.442695f) );
00254     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_UnderwaterFogColor", oscene->scene->getOceanScene()->getUnderwaterFogColor() ) );
00255 
00256     float AWFogDensity= oscene->scene->getOceanScene()->getAboveWaterFogDensity();
00257     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_AboveWaterFogDensity", -AWFogDensity*AWFogDensity*1.442695f ) );
00258     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_AboveWaterFogColor", oscene->scene->getOceanScene()->getAboveWaterFogColor() ) );
00259 
00260     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_DOF_Near",  oscene->scene->getOceanScene()->getDOFNear() ) );
00261     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_DOF_Far",  oscene->scene->getOceanScene()->getDOFFar() ) );
00262     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_DOF_Focus",  oscene->scene->getOceanScene()->getDOFFocalDistance() ) );
00263     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_DOF_Clamp",  oscene->scene->getOceanScene()->getDOFFarClamp() ) );
00264 
00265     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_WaterHeight", float(oscene->scene->getOceanScene()->getOceanSurfaceHeight()) ) );
00266 
00267     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_UnderwaterAttenuation", oscene->scene->getOceanScene()->getUnderwaterAttenuation() ) );
00268     textureCamera->getStateSet()->addUniform( new osg::Uniform("osgOcean_UnderwaterDiffuse", oscene->scene->getOceanScene()->getUnderwaterDiffuse() ) );
00269 
00270     /*textureCamera->getStateSet()->addUniform(new osg::Uniform("uOverlayMap", 1));
00271     textureCamera->getStateSet()->addUniform(new osg::Uniform("uNormalMap", 2));
00272     textureCamera->getStateSet()->addUniform(new osg::Uniform("SLStex", 3));
00273     textureCamera->getStateSet()->addUniform(new osg::Uniform("SLStex2", 4));*/
00274 
00275     osg::Uniform* u = new osg::Uniform("offsets", osg::Vec4f(1,2,3,4));
00276     u->setUpdateCallback(new UpdateNoiseSeed());
00277     textureCamera->getStateSet()->addUniform(u);
00278 
00279     textureCamera->getStateSet()->addUniform( new osg::Uniform("stddev", std ) );
00280     textureCamera->getStateSet()->addUniform( new osg::Uniform("mean", 0.0f ) );
00281 
00282   }
00283   else
00284   {
00285     textureCamera->getOrCreateStateSet()->setAttributeAndModes(new osg::Program(), osg::StateAttribute::ON); //Unset shader
00286   }
00287 }
00288 
00289 osg::ref_ptr<osgWidget::Window> VirtualCamera::getWidgetWindow()
00290 {
00291   osg::ref_ptr < osgWidget::Box > box = new osgWidget::Box("VirtualCameraBox", osgWidget::Box::HORIZONTAL, true);
00292   osg::ref_ptr < osgWidget::Widget > widget = new osgWidget::Widget("VirtualCameraWidget", width, height);
00293   if (!range)
00294     widget->setImage(renderTexture.get(), true, false);
00295   else
00296     widget->setImage(depthTexture.get(), true, false);
00297   box->addWidget(widget.get());
00298   box->getBackground()->setColor(1.0f, 0.0f, 0.0f, 0.8f);
00299   box->attachMoveCallback();
00300   box->attachScaleCallback();
00301   return box;
00302 }
00303 
00304 int VirtualCamera::getTFTransform(tf::Pose & pose, std::string & parent){
00305   parent=parentLinkName;
00306   pose.setOrigin(tf::Vector3(trackNode->asTransform()->asPositionAttitudeTransform()->getPosition().x(),
00307                         trackNode->asTransform()->asPositionAttitudeTransform()->getPosition().y(),
00308                         trackNode->asTransform()->asPositionAttitudeTransform()->getPosition().z()));
00309   pose.setRotation( tf::Quaternion(trackNode->asTransform()->asPositionAttitudeTransform()->getAttitude().x(),
00310                         trackNode->asTransform()->asPositionAttitudeTransform()->getAttitude().y(),
00311                         trackNode->asTransform()->asPositionAttitudeTransform()->getAttitude().z(),
00312                         trackNode->asTransform()->asPositionAttitudeTransform()->getAttitude().w()));
00313   return 1;
00314 
00315 }


uwsim
Author(s): Mario Prats , Javier Perez
autogenerated on Fri Aug 28 2015 13:28:58