1 // Copyright (C) 2008 Tim Moore 2 // 3 // This program is free software; you can redistribute it and/or 4 // modify it under the terms of the GNU General Public License as 5 // published by the Free Software Foundation; either version 2 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, but 9 // WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 // General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program; if not, write to the Free Software 15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 17 #ifndef CAMERAGROUP_HXX 18 #define CAMERAGROUP_HXX 1 19 20 #include <map> 21 #include <string> 22 #include <vector> 23 #include <memory> 24 25 #include <osg/Matrix> 26 #include <osg/ref_ptr> 27 #include <osg/Referenced> 28 #include <osg/Node> 29 #include <osg/TextureRectangle> 30 #include <osg/Texture2D> 31 #include <osg/TexGen> 32 #include <osgUtil/RenderBin> 33 34 // For osgUtil::LineSegmentIntersector::Intersections, which is a typedef. 35 #include <osgUtil/LineSegmentIntersector> 36 namespace osg 37 { 38 class Camera; 39 } 40 41 namespace osgViewer 42 { 43 class Viewer; 44 } 45 46 class SGPropertyNode; 47 48 namespace flightgear 49 { 50 51 class GraphicsWindow; 52 class CameraViewportListener; 53 class CameraGroupListener; 54 55 struct RenderBufferInfo { RenderBufferInfoflightgear::RenderBufferInfo56 RenderBufferInfo(osg::Texture2D* t = 0, float s = 1.0 ) : texture(t), scaleFactor(s) {} 57 osg::ref_ptr<osg::Texture2D> texture; 58 float scaleFactor; 59 }; 60 typedef std::map<std::string,RenderBufferInfo> RenderBufferMap; 61 typedef std::map<osg::Camera::BufferComponent,std::string> AttachmentMap; 62 63 struct RenderStageInfo { RenderStageInfoflightgear::RenderStageInfo64 RenderStageInfo(osg::Camera* camera_ = 0, int si = -1, bool fs = false) 65 : camera(camera_), slaveIndex(si), scaleFactor(1.0f), fullscreen(fs) 66 , resizable(true) 67 { 68 } 69 70 osg::ref_ptr<osg::Camera> camera; 71 AttachmentMap buffers; 72 int slaveIndex; 73 float scaleFactor; 74 bool fullscreen; 75 bool resizable; 76 }; 77 78 extern const char* MAIN_CAMERA; 79 extern const char* FAR_CAMERA; 80 extern const char* GEOMETRY_CAMERA; 81 extern const char* SHADOW_CAMERA; 82 extern const char* LIGHTING_CAMERA; 83 extern const char* DISPLAY_CAMERA; 84 85 typedef std::map<std::string,RenderStageInfo> CameraMap; 86 87 /** A wrapper around osg::Camera that contains some extra information. 88 */ 89 struct CameraInfo : public osg::Referenced 90 { CameraInfoflightgear::CameraInfo91 CameraInfo(unsigned flags_) 92 : flags(flags_), 93 x(0.0), y(0.0), width(0.0), height(0.0), 94 physicalWidth(0), physicalHeight(0), bezelHeightTop(0), 95 bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0), 96 relativeCameraParent(~0u), 97 bufferSize( new osg::Uniform("fg_BufferSize", osg::Vec2f() ) ), 98 projInverse( new osg::Uniform( "fg_ProjectionMatrixInverse", osg::Matrixf() ) ), 99 viewInverse( new osg::Uniform( "fg_ViewMatrixInverse",osg::Matrixf() ) ), 100 view( new osg::Uniform( "fg_ViewMatrix",osg::Matrixf() ) ), 101 worldPosCart( new osg::Uniform( "fg_CameraPositionCart", osg::Vec3f() ) ), 102 worldPosGeod( new osg::Uniform( "fg_CameraPositionGeod", osg::Vec3f() ) ), 103 du( new osg::Uniform( "fg_du",osg::Vec4() ) ), 104 dv( new osg::Uniform( "fg_dv",osg::Vec4() ) ), 105 viewportListener(NULL) 106 { 107 shadowMatrix[0] = new osg::Uniform("fg_ShadowMatrix_0", osg::Matrixf()); 108 shadowMatrix[1] = new osg::Uniform("fg_ShadowMatrix_1", osg::Matrixf()); 109 shadowMatrix[2] = new osg::Uniform("fg_ShadowMatrix_2", osg::Matrixf()); 110 shadowMatrix[3] = new osg::Uniform("fg_ShadowMatrix_3", osg::Matrixf()); 111 } 112 113 ~CameraInfo(); 114 115 /** Update and resize cameras 116 */ 117 void updateCameras(); 118 void resized(double w, double h); 119 120 /** The name as given in the config file. 121 */ 122 std::string name; 123 /** Properties of the camera. @see CameraGroup::Flags. 124 */ 125 unsigned flags; 126 127 /** Viewport parameters. 128 */ 129 double x; 130 double y; 131 double width; 132 double height; 133 /** Physical size parameters. 134 */ 135 double physicalWidth; 136 double physicalHeight; 137 double bezelHeightTop; 138 double bezelHeightBottom; 139 double bezelWidthLeft; 140 double bezelWidthRight; 141 /** The parent camera for relative camera configurations. 142 */ 143 unsigned relativeCameraParent; 144 145 /** the camera objects 146 */ 147 CameraMap cameras; addCameraflightgear::CameraInfo148 void addCamera( const std::string& k, osg::Camera* c, int si = -1, bool fs = false ) { cameras[k].camera = c; cameras[k].slaveIndex = si; cameras[k].fullscreen = fs; } addCameraflightgear::CameraInfo149 void addCamera( const std::string& k, osg::Camera* c, bool fs ) { cameras[k].camera = c; cameras[k].fullscreen = fs; } addCameraflightgear::CameraInfo150 void addCamera( const std::string& k, osg::Camera* c, float s, bool fs = false ) { cameras[k].camera = c; cameras[k].scaleFactor = s; cameras[k].fullscreen = fs; } 151 osg::Camera* getCamera(const std::string& k) const; 152 int getMainSlaveIndex() const; getRenderStageInfoflightgear::CameraInfo153 RenderStageInfo& getRenderStageInfo( const std::string& k ) { return cameras[k]; } 154 155 /** the buffer objects 156 */ 157 RenderBufferMap buffers; addBufferflightgear::CameraInfo158 void addBuffer(const std::string& k, osg::Texture2D* tex, float scale = 1.0 ) { buffers[k] = RenderBufferInfo(tex,scale); } 159 osg::Texture2D* getBuffer(const std::string& k) const; 160 161 osg::ref_ptr<osg::Uniform> bufferSize; 162 osg::ref_ptr<osg::Uniform> projInverse; 163 osg::ref_ptr<osg::Uniform> viewInverse; 164 osg::ref_ptr<osg::Uniform> view; 165 osg::ref_ptr<osg::Uniform> worldPosCart; 166 osg::ref_ptr<osg::Uniform> worldPosGeod; 167 osg::ref_ptr<osg::Uniform> du; 168 osg::ref_ptr<osg::Uniform> dv; 169 osg::ref_ptr<osg::Uniform> shadowMatrix[4]; 170 171 CameraViewportListener* viewportListener; 172 173 void setMatrices( osg::Camera* c ); 174 175 osgUtil::RenderBin::RenderBinList savedTransparentBins; 176 /** The reference points in the parents projection space. 177 */ 178 osg::Vec2d parentReference[2]; 179 /** The reference points in the current projection space. 180 */ 181 osg::Vec2d thisReference[2]; 182 }; 183 184 class CameraGroup : public osg::Referenced 185 { 186 public: 187 /** properties of a camera. 188 */ 189 enum Flags 190 { 191 VIEW_ABSOLUTE = 0x1, /**< The camera view is absolute, not 192 relative to the master camera. */ 193 PROJECTION_ABSOLUTE = 0x2, /**< The projection is absolute. */ 194 ORTHO = 0x4, /**< The projection is orthographic */ 195 GUI = 0x8, /**< Camera draws the GUI. */ 196 DO_INTERSECTION_TEST = 0x10,/**< scene intersection tests this 197 camera. */ 198 FIXED_NEAR_FAR = 0x20, /**< take the near far values in the 199 projection for real. */ 200 ENABLE_MASTER_ZOOM = 0x40 /**< Can apply the zoom algorithm. */ 201 }; 202 /** Create a camera group associated with an osgViewer::Viewer. 203 * @param viewer the viewer 204 */ 205 CameraGroup(osgViewer::Viewer* viewer); 206 207 ~CameraGroup(); 208 209 /** Get the camera group's Viewer. 210 * @return the viewer 211 */ getViewer()212 osgViewer::Viewer* getViewer() { return _viewer.get(); } 213 /** Create an osg::Camera from a property node and add it to the 214 * camera group. 215 * @param cameraNode the property node. 216 * @return a CameraInfo object for the camera. 217 */ 218 CameraInfo* buildCamera(SGPropertyNode* cameraNode); 219 /** Create a camera from properties that will draw the GUI and add 220 * it to the camera group. 221 * @param cameraNode the property node. This can be 0, in which 222 * case a default GUI camera is created. 223 * @param window the GraphicsWindow to use for the GUI camera. If 224 * this is 0, the window is determined from the property node. 225 * @return a CameraInfo object for the GUI camera. 226 */ 227 CameraInfo* buildGUICamera(SGPropertyNode* cameraNode, 228 GraphicsWindow* window = 0); 229 /** Update the view for the camera group. 230 * @param position the world position of the view 231 * @param orientation the world orientation of the view. 232 */ 233 void update(const osg::Vec3d& position, const osg::Quat& orientation); 234 /** Set the parameters of the viewer's master camera. This won't 235 * affect cameras that have CameraFlags::PROJECTION_ABSOLUTE set. 236 * XXX Should znear and zfar be settable? 237 * @param vfov the vertical field of view angle 238 * @param aspectRatio the master camera's aspect ratio. This 239 * doesn't actually change the viewport, but should reflect the 240 * current viewport. 241 */ 242 void setCameraParameters(float vfov, float aspectRatio); 243 /** Set the default CameraGroup, which is the only one that 244 * matters at this time. 245 * @param group the group to set. 246 */ 247 248 static void buildDefaultGroup(osgViewer::Viewer* viewer); 249 setDefault(CameraGroup * group)250 static void setDefault(CameraGroup* group) { _defaultGroup = group; } 251 /** Get the default CameraGroup. 252 * @return the default camera group. 253 */ getDefault()254 static CameraGroup* getDefault() { return _defaultGroup.get(); } 255 256 typedef std::vector<osg::ref_ptr<CameraInfo> > CameraList; 257 typedef CameraList::iterator CameraIterator; 258 typedef CameraList::const_iterator ConstCameraIterator; 259 /** Get iterator for camera vector. The iterator's value is a ref_ptr. 260 */ camerasBegin()261 CameraIterator camerasBegin() { return _cameras.begin(); } 262 /** Get iteator pointing to the end of the camera list. 263 */ camerasEnd()264 CameraIterator camerasEnd() { return _cameras.end(); } camerasBegin() const265 ConstCameraIterator camerasBegin() const { return _cameras.begin(); } camerasEnd() const266 ConstCameraIterator camerasEnd() const { return _cameras.end(); } addCamera(CameraInfo * info)267 void addCamera(CameraInfo* info) { _cameras.push_back(info); } 268 /** Set the cull mask on all non-GUI cameras 269 */ 270 void setCameraCullMasks(osg::Node::NodeMask nm); 271 /** Update camera properties after a resize event. 272 */ 273 void resized(); 274 275 void buildDistortionCamera(const SGPropertyNode* psNode, 276 osg::Camera* camera); 277 278 /** 279 * get aspect ratio of master camera's viewport 280 */ 281 double getMasterAspectRatio() const; 282 283 /** 284 * find the GUI camera if one is defined 285 */ 286 const CameraInfo* getGUICamera() const; 287 setZNear(float f)288 void setZNear(float f) { _zNear = f; } setZFar(float f)289 void setZFar(float f) { _zFar = f; } setNearField(float f)290 void setNearField(float f) { _nearField = f; } 291 protected: 292 CameraList _cameras; 293 osg::ref_ptr<osgViewer::Viewer> _viewer; 294 static osg::ref_ptr<CameraGroup> _defaultGroup; 295 std::unique_ptr<CameraGroupListener> _listener; 296 297 // Near, far for the master camera if used. 298 float _zNear; 299 float _zFar; 300 float _nearField; 301 302 typedef std::map<std::string, osg::ref_ptr<osg::TextureRectangle> > TextureMap; 303 TextureMap _textureTargets; 304 305 /** Build a complete CameraGroup from a property node. 306 * @param viewer the viewer associated with this camera group. 307 * @param the camera group property node. 308 */ 309 static CameraGroup* buildCameraGroup(osgViewer::Viewer* viewer, 310 SGPropertyNode* node); 311 }; 312 313 } 314 315 namespace flightgear 316 { 317 /** Get the osg::Camera that draws the GUI, if any, from a camera 318 * group. 319 * @param cgroup the camera group 320 * @return the GUI camera or 0 321 */ 322 osg::Camera* getGUICamera(CameraGroup* cgroup); 323 /** Choose a camera using an event and do intersection testing on its 324 * view of the scene. Only cameras with the DO_INTERSECTION_TEST flag 325 * set are considered. 326 * @param cgroup the CameraGroup 327 * @param ea the event containing a window and mouse coordinates 328 * @param intersections container for the result of intersection 329 * testing. 330 * @return true if any intersections are found 331 */ 332 bool computeIntersections(const CameraGroup* cgroup, 333 const osg::Vec2d& windowPos, 334 osgUtil::LineSegmentIntersector::Intersections& 335 intersections); 336 /** Warp the pointer to coordinates in the GUI camera of a camera group. 337 * @param cgroup the camera group 338 * @param x x window coordinate of pointer 339 * @param y y window coordinate of pointer, in "y down" coordinates. 340 */ 341 void warpGUIPointer(CameraGroup* cgroup, int x, int y); 342 } 343 #endif 344