⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.cc

📁 机器人人3D仿真工具,可以加入到Simbad仿真环境下应用。
💻 CC
字号:
/* *  Gazebo - Outdoor Multi-Robot Simulator *  Copyright (C) 2003   *     Nate Koenig & Andrew Howard * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *//* Desc: A camera sensor using OpenGL * Author: Nate Koenig * Date: 15 July 2003 * CVS: $Id: Camera.cc,v 1.74 2006/02/14 03:08:17 natepak Exp $ */#if HAVE_CONFIG_H  #include <config.h>#endif#ifndef GL_GLEXT_PROTOTYPES#define GL_GLEXT_PROTOTYPES 1#endif#include <assert.h>#include <stdlib.h>#include <string.h>#include <GL/gl.h>#include <GL/glu.h>#include <GL/glut.h>#include <GL/glext.h>#include "World.hh"#include "Model.hh"#include "Body.hh"#include "WorldFile.hh"#include "Camera.hh"#include "LightGeom.hh"//#include "ShaderManager.hh"//#include "ShaderObject.hh"//////////////////////////////////////////////////////////////////////////////// Constructor Camera::Camera( World *world )    : Sensor( world ){  this->cameraPose = GzPoseSet(GzVectorZero(), GzQuaternIdent());  this->imageWidth = this->imageHeight = 0;  this->rgbImage = NULL;  this->saveEnable = false;  this->saveCount = 0;  this->savePathname = NULL;  //this->shaderManager = new ShaderManager();  return;}//////////////////////////////////////////////////////////////////////////////// DestructorCamera::~Camera(){  //delete this->shaderManager;  //this->shaderManager = NULL;  return;}//////////////////////////////////////////////////////////////////////////////// Initialize the sensorint Camera::Init(int width, int height, double hfov, double minDepth,     double maxDepth, const char *method, int zBufferDepth){  this->imageWidth = width;  this->imageHeight = height;  this->hfov = hfov;  this->nearClip = minDepth;  this->farClip = maxDepth;  // Do some sanity checks  if (this->imageWidth == 0 || this->imageHeight == 0)  {    PRINT_ERR("image has zero size");    return -1;  }  if (this->hfov < 0.01 || this->hfov > M_PI)  {    PRINT_ERR("bad field of view");    return -1;  }  if (this->nearClip < 0.01)  {    PRINT_ERR("near clipping plane (min depth) is zero");    return -1;  }  // Initialize the GL rendering context  if (this->context.Init(this->imageWidth, this->imageHeight, 5, 0,         zBufferDepth, method) != 0)  {    PRINT_ERR("camera initialization failed: no rendering context");    return -1;  } else {    //this->context.MakeCurrent();    this->InitContext(this->context);  }  // Initialize image buffers  int imageSize = this->imageWidth * this->imageHeight;  this->rgbImage = new uint8_t[imageSize * 3];      // Initialize display options  this->renderOpt.displayBBox = false;  this->renderOpt.displayAxes = false;  this->renderOpt.displayCoM = false;  this->renderOpt.displaySkins = false;    this->renderOpt.displayRays = false;  this->renderOpt.displayFrustrums = false;  this->renderOpt.displayMaterials = true;  this->renderOpt.displayTextures = true;  this->renderOpt.polygonMode = GL_FILL;  this->renderOpt.shadeModel = GL_SMOOTH;//  this->shaderObject = this->shaderManager->LoadFromFile("defaultShader.vert", "defaultShader.frag");  //this->shaderObject->SendUniform1i("NumEnabledLights",1);  //this->shaderObject->SendUniform1i("SeparateSpecular",0);  return 0;}void Camera::InitContext( GLContext &context ){  context.MakeCurrent();  glClearColor(this->world->skyColor.r, this->world->skyColor.g,               this->world->skyColor.b, this->world->skyColor.a);  // Normalize normals  glEnable(GL_NORMALIZE);  // Light model (two-sided)  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);  PRINT_GL_ERR();  // Enable blending for transparency  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  PRINT_GL_ERR();  // Use depth buffering for hidden surface elimination  glClearDepth(1.0f);  glDepthFunc(GL_LEQUAL);  glEnable(GL_DEPTH_TEST);  // Enable back face culling  glEnable(GL_CULL_FACE);  glCullFace(GL_BACK);   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Configure fog  if (this->world->fogEnable)  {    glEnable(GL_FOG);    glFogi(GL_FOG_MODE, GL_EXP2);    glFogf(GL_FOG_DENSITY, this->world->fogDensity);    glFogfv(GL_FOG_COLOR, this->world->skyColor);    PRINT_GL_ERR();  }}//////////////////////////////////////////////////////////////////////////////// Finalize the cameraint Camera::Fini(){  this->context.Fini();    return 0;}//////////////////////////////////////////////////////////////////////////////// Update the drawingvoid Camera::Update(){    // Render the image  this->Render();  // Save image frames  if (this->saveEnable)    this->SaveFrame();  return;}//////////////////////////////////////////////////////////////////////////////// Render the scene from the camera perspectivevoid Camera::Render(){  GzPose pose;  GzVector a, b;  // Compute the point to look at, and the orientation vector  pose = this->cameraPose;  a = GzVectorSet(1, 0, 0);  b = GzVectorSet(1, 0, 1);  a = GzCoordPositionAdd(a, pose.pos, pose.rot);  b = GzCoordPositionAdd(b, pose.pos, pose.rot);  b = GzVectorSub(b, a);  // Fill in the current camera index  this->renderOpt.cameraIndex = this->context.GetContextIndex();  this->renderOpt.cameraPose = this->cameraPose;  this->renderOpt.farClip = this->farClip;  // Select the GL context  if (this->context.MakeCurrent() != 0)    return;  // Clear the window  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);  PRINT_GL_ERR();  // Set the camera lens propeties (assumes square pixels)  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  gluPerspective(this->hfov * 180 / M_PI,       (double) this->imageWidth / this->imageHeight, this->nearClip,       this->farClip); PRINT_GL_ERR();  // Store the projection matrix for later use  glGetFloatv(GL_PROJECTION_MATRIX, this->cameraProjectionMatrix);  // Set the camera pose  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  gluLookAt(pose.pos.x, pose.pos.y, pose.pos.z, a.x, a.y, a.z, b.x, b.y, b.z);  PRINT_GL_ERR();  glGetFloatv(GL_MODELVIEW_MATRIX, this->cameraViewMatrix);  // Counter Clockwise rotation are front faces  glFrontFace(GL_CCW);  // Enable lighting  glEnable(GL_LIGHTING);  // Set global rendering properties  glPolygonMode( GL_FRONT_AND_BACK, this->renderOpt.polygonMode );    PRINT_GL_ERR();      glShadeModel(this->renderOpt.shadeModel);  PRINT_GL_ERR();  // Reset material properties  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, GzColor(0.2, 0.2, 0.2, 1.0));  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GzColor(0.8, 0.8, 0.8, 1.0));  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GzColor(0.0, 0.0, 0.0, 1.0));  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0);  PRINT_GL_ERR();  //this->shaderObject->Begin();  // Make multiple passes to ensure geoms get rendered in correct  // order (needed for lights, for example)  for (int p = 0; p < GZ_RENDER_MAX_PASSES; p++)  {    this->RenderModels(p);    PRINT_GL_ERR();  }  //this->shaderObject->End();  // Make sure we are done  glFinish();  PRINT_GL_ERR();  // Get the image from the frame buffer  glPixelStorei(GL_PACK_ALIGNMENT, 1);  glReadPixels(0, 0, this->imageWidth, this->imageHeight,      GL_RGB, GL_UNSIGNED_BYTE, this->rgbImage);  PRINT_GL_ERR();  return;}//////////////////////////////////////////////////////////////////////////////// Get the Z-buffer value at the given image coordinatedouble Camera::GetZValue(int x, int y){  GLfloat iz;  // Flip y axis  y = this->imageHeight - 1 - y;  // Get image z value of first spot  glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &iz);  return iz;}//////////////////////////////////////////////////////////////////////////////// Determine change in camera pose based on two image pointsGzPose Camera::CalcCameraDelta(int mode, GzVector a, GzVector b){  GLfloat ix, iy, iz;  // Image coordates of the first spot  ix = a.x;  iy = this->imageHeight - 1 - a.y;  iz = a.z;  double dx, dy, dz;    // Convert to division coordinates  dx = 2 * ix / this->imageWidth - 1;  dy = 2 * iy / this->imageHeight - 1;  dz = (2 * iz  - 1);  double px, py, pz, pw;  // Compute perspective divisor; assumes well-formed projection matrix  pw = this->cameraProjectionMatrix[14] / (dz + this->cameraProjectionMatrix[10]);  // Convert to projected coordinate  px = dx * pw;  py = dy * pw;  pz = dz * pw;  double cx, cy, cz, cw;    // Convert to camera frame (inverse projection)  cx = 1 / this->cameraProjectionMatrix[0] * px;  cy = 1 / this->cameraProjectionMatrix[5] * py;  cz = -pw;  cw = 1 / this->cameraProjectionMatrix[14] * pz + 1 / this->cameraProjectionMatrix[10] * pw;  double ix_, iy_;  double dx_, dy_;    // Image coordates of the second spot  ix_ = b.x;  iy_ = this->imageHeight - 1 - b.y;  // Convert to division coordinates  dx_ = 2 * ix_ / this->imageWidth - 1;  dy_ = 2 * iy_ / this->imageHeight - 1;  GzPose n;  n.pos = GzVectorZero();  n.rot = GzQuaternIdent();    double nx, ny, nz;  // Translate along x, y  if (mode == 0)  {    nz = 0.0;    nx = - (cz + nz) / this->cameraProjectionMatrix[0] * dx_ - cx;    ny = - (cz + nz) / this->cameraProjectionMatrix[5] * dy_ - cy;  }  // Translate (zoom) along z  else if (mode == 1)  {    ny = 0.0;    nz = - this->cameraProjectionMatrix[5] / (fabs(dy_) + 1e-16) * fabs(cy) - cz;        nx = 0;    // Bound so we dont go too close    if (nz > -cz - 2 * this->nearClip)      nz = -cz - 2 * this->nearClip;    // Bound so we dont go too far away    else if (nz < -0.5 * this->farClip - cz)      nz = -0.5 * this->farClip - cz;  }  else  {    nx = 0;    ny = 0;    nz = 0;  }    // Convert to Gazebo coordinate system (camera axis along +x)  n.pos.x = +nz;  n.pos.y = +nx;  n.pos.z = -ny;  // Rotate (pitch and yaw)  if (mode == 2)  {    double rx, ry;    rx = atan((dx_ - dx)  / this->cameraProjectionMatrix[0]);    ry = atan((dy_ - dy)  / this->cameraProjectionMatrix[5]);    n.rot = GzQuaternFromEuler(0, ry, rx);  }    return n;}//////////////////////////////////////////////////////////////////////////////// Render the modelsvoid Camera::RenderModels( int pass ){  int i;  Model *model;  for (i = 0; i < this->world->GetNumModels(); i++)  {    model = this->world->GetModels()[i];    model->Render(pass, &this->renderOpt);  }}//////////////////////////////////////////////////////////////////////////////// Set the pose of the cameravoid Camera::SetPose(GzPose pose){  this->cameraPose = pose;  return;}//////////////////////////////////////////////////////////////////////////////// Get the pose of the cameraGzPose Camera::GetPose(){  return this->cameraPose;}//////////////////////////////////////////////////////////////////////////////// Set the camera FOV (horizontal)void Camera::SetFOV(double fov){  this->hfov = fov;  return;}//////////////////////////////////////////////////////////////////////////////// Get the camera FOV (horizontal)double Camera::GetFOV() const{  return this->hfov;}//////////////////////////////////////////////////////////////////////////////// Set the rendering optionsvoid Camera::SetRenderOptions(const RenderOptions *opt){  this->renderOpt = *opt;  return;}//////////////////////////////////////////////////////////////////////////////// Get the rendering optionsvoid Camera::GetRenderOptions(RenderOptions *opt) const{  assert(opt != NULL);  *opt = this->renderOpt;  return;}//////////////////////////////////////////////////////////////////////////////// Get the image dimensionsvoid Camera::GetImageSize(int *w, int *h){  *w = this->imageWidth;  *h = this->imageHeight;  return;}//////////////////////////////////////////////////////////////////////////////// Set the base filename for saved framesvoid Camera::SetSavePath(const char *pathname){  char tmp[1024];      this->savePathname = pathname;  this->saveCount = 0;  sprintf(tmp, "mkdir %s 2>>/dev/null", this->savePathname);  system(tmp);  return;}//////////////////////////////////////////////////////////////////////////////// Enable or disable savingvoid Camera::EnableSaveFrame(bool enable){  this->saveEnable = enable;  return;}//////////////////////////////////////////////////////////////////////////////// Save the current frame to diskvoid Camera::SaveFrame(){  char tmp[1024];  FILE *fp;    sprintf(tmp, "%s/%04d.pnm", this->savePathname, this->saveCount);  fp = fopen( tmp, "wb" );  if (!fp)  {    PRINT_ERR1( "unable to open file %s\n for writing", tmp );    return;  }    fprintf( fp, "P6\n# Gazebo\n%d %d\n255\n", this->imageWidth, this->imageHeight);  for (int i = this->imageHeight-1; i >= 0; i--)    fwrite( this->rgbImage + i * this->imageWidth * 3, 1, this->imageWidth * 3, fp );  fclose( fp );  this->saveCount++;  return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -