Added new osgGA - GUI Adapter library submitted by Neil Salter. This will

replace the current GUI adapter code inside osgUtil.
This commit is contained in:
Robert Osfield
2002-05-09 10:31:03 +00:00
parent e58b79c997
commit cf4a3500ec
28 changed files with 2617 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ SRC_DIRS = \
osg\
osgUtil\
osgDB\
osgGA\
osgGLUT\
osgPlugins\
osgText\

View File

@@ -30,6 +30,24 @@ Package=<4>
###############################################################################
Project: "Core osgGA"=".\osgGA\osgGA.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name Core osg
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgUtil
End Project Dependency
}}}
###############################################################################
Project: "Core osgGLUT"=".\osgGLUT\osgGLUT.dsp" - Package Owner=<4>
Package=<5>
@@ -45,6 +63,9 @@ Package=<4>
Project_Dep_Name Core osgUtil
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgDB
End Project Dependency
}}}
@@ -99,6 +120,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -123,6 +147,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -168,6 +195,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -192,6 +222,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -216,6 +249,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -240,6 +276,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -267,6 +306,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -291,6 +333,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -315,6 +360,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -339,6 +387,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -363,6 +414,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -390,6 +444,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -429,6 +486,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency
@@ -453,6 +513,9 @@ Package=<4>
Project_Dep_Name Core osgDB
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGA
End Project Dependency
Begin Project Dependency
Project_Dep_Name Core osgGLUT
End Project Dependency
Begin Project Dependency

201
VisualStudio/osgGA/osgGA.dsp Executable file
View File

@@ -0,0 +1,201 @@
# Microsoft Developer Studio Project File - Name="Core osgGA" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=Core osgGA - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "osgGA.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "osgGA.mak" CFG="Core osgGA - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Core osgGA - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "Core osgGA - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "Core osgGA - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "../../lib"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../../lib"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../include" /D "NDEBUG" /D "_MBCS" /D "_USRDLL" /D "OSGUTIL_LIBRARY" /D "WIN32" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 glu32.lib opengl32.lib /nologo /dll /pdb:none /machine:I386 /out:"../../bin/osgGA.dll" /libpath:"../../lib"
!ELSEIF "$(CFG)" == "Core osgGA - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "../../lib"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /vmg /vd0 /GR /GX /Zi /Od /I "../../include" /D "OSGUTIL_LIBRARY" /D "_WINDOWS" /D "WIN32" /D "_DEBUG" /D "OSG_USE_MEMORY_MANAGER" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 glu32.lib opengl32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/osgGAd.dll" /pdbtype:sept /libpath:"../../lib"
# SUBTRACT LINK32 /pdb:none
!ENDIF
# Begin Target
# Name "Core osgGA - Win32 Release"
# Name "Core osgGA - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\src\osgGA\
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\CameraManipulator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\DriveManipulator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\FlightManipulator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\GUIEventHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\GUIEventHandlerVisitor.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\KeySwitchCameraManipulator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\SetSceneViewVisitor.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\StateSetManipulator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\TrackballManipulator.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgGA\Version.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter ";h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\Include\osgGA\CameraManipulator
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\DriveManipulator
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\FlightManipulator
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\GUIActionAdapter
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\GUIEventAdapter
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\GUIEventHandler
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\GUIEventHandlerVisitor
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\KeySwitchCameraManipulator
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\SetSceneViewVisitor
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\StateSetManipulator
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\TrackballManipulator
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\Export
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgGA\Version
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
\c

View File

@@ -0,0 +1,70 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_CAMERAMANIPULATOR
#define OSGGA_CAMERAMANIPULATOR 1
#include <osg/Camera>
#include <osg/Node>
#include <osgGA/Export>
#include <osgGA/GUIEventHandler>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIActionAdapter>
namespace osgGA{
class OSGGA_EXPORT CameraManipulator : public GUIEventHandler
{
public:
CameraManipulator();
virtual ~CameraManipulator();
/** attach a camera to the manipulator to be used for specifying view.*/
virtual void setCamera(osg::Camera*);
/** get the attached camera.*/
virtual const osg::Camera * getCamera() const;
/** get the attached camera.*/
virtual osg::Camera * getCamera();
/** Attach a node to the manipulator.
Automatically detaches previously attached node.
setNode(NULL) detaches previously nodes.
Is ignored by manipulators which do not require a reference model.*/
virtual void setNode(osg::Node*) {}
/** Return node if attached.*/
virtual const osg::Node* getNode() const { return NULL; }
/** Return node if attached.*/
virtual osg::Node* getNode() { return NULL; }
/** Move the camera to the default position.
May be ignored by manipulators if home functionality is not appropriate.*/
virtual void home(const GUIEventAdapter& ,GUIActionAdapter&) {}
/** Start/restart the manipulator.*/
virtual void init(const GUIEventAdapter& ,GUIActionAdapter&) {}
/** Handle events, return true if handled, false otherwise.*/
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** Handle visitations */
virtual void accept(GUIEventHandlerVisitor& v) { v.visit(*this); }
protected:
// Reference pointer to a camera
osg::ref_ptr<osg::Camera> _camera;
};
}
#endif

View File

@@ -0,0 +1,75 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_DRIVEMANIPULATOR
#define OSGGA_DRIVEMANIPULATOR 1
#include <osgGA/CameraManipulator>
namespace osgGA{
class OSGGA_EXPORT DriveManipulator : public CameraManipulator
{
public:
DriveManipulator();
virtual ~DriveManipulator();
/** Attach a node to the manipulator.
Automatically detaches previously attached node.
setNode(NULL) detaches previously nodes.
Is ignored by manipulators which do not require a reference model.*/
virtual void setNode(osg::Node*);
/** Return node if attached.*/
virtual const osg::Node* getNode() const;
/** Return node if attached.*/
virtual osg::Node* getNode();
/** Move the camera to the default position.
May be ignored by manipulators if home functionality is not appropriate.*/
virtual void home(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** Start/restart the manipulator.*/
virtual void init(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** handle events, return true if handled, false otherwise.*/
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us);
private:
/** Reset the internal GUIEvent stack.*/
void flushMouseEventStack();
/** Add the current mouse GUIEvent to internal stack.*/
void addMouseEvent(const GUIEventAdapter& ea);
/** For the give mouse movement calculate the movement of the camera.
Return true is camera has moved and a redraw is required.*/
bool calcMovement();
// Internal event stack comprising last three mouse events.
osg::ref_ptr<const GUIEventAdapter> _ga_t1;
osg::ref_ptr<const GUIEventAdapter> _ga_t0;
osg::ref_ptr<osg::Node> _node;
float _modelScale;
float _velocity;
float _height;
float _buffer;
enum SpeedControlMode {
USE_MOUSE_Y_FOR_SPEED,
USE_MOUSE_BUTTONS_FOR_SPEED
};
SpeedControlMode _speedMode;
};
}
#endif

53
include/osgGA/Export Normal file
View File

@@ -0,0 +1,53 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
// The following symbol has a underscore suffix for compatibility.
#ifndef OSGGA_EXPORT_
#define OSGGA_EXPORT_ 1
#if defined(WIN32) && !(defined(__CYGWIN__) || defined(__MINGW32__))
#pragma warning( disable : 4244 )
#pragma warning( disable : 4251 )
#pragma warning( disable : 4275 )
#pragma warning( disable : 4786 )
#endif
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
# ifdef OSGGA_LIBRARY
# define OSGGA_EXPORT __declspec(dllexport)
# else
# define OSGGA_EXPORT __declspec(dllimport)
#endif /* OSGUTIL_LIBRARY */
#else
#define OSGGA_EXPORT
#endif
#endif
/**
\namespace osgGA
The 'GA' in osgGA stands for 'GUI Abstraction'.
As the OpenSceneGraph is a cross-platform, window system-agnostic class library,
it has no direct ties to any given windowing environment. Viewers, however, must at
some level interact with a window system - where Window system may refer to a windowing
API, e.g. GLUT, Qt, FLTK, MFC, ...
There is much commonality in the implementation of Viewers for varying windowing
environments. E.g. most Viewers will update a Camera position in response to a mouse
event, and may request that a timer be started as a result of a model being 'spun'.
The purpose of the osgGA namespace is to centralise the common areas of this
functionality. With this centralised, the viewer writer needs only write a
GUIEventAdapter, a GUIActionAdapter, and assemble a collection of GUIEventHandlers
as appropriate for the viewer.
Events from the windowing environment are adpated, and then fed into the GUIEventHandlers.
The GUIEventHandlers analyse and take action, and make requests of the windowing
environemnt via the GUIActionAdapter. The viewer writer should honour these requests.
*/

View File

@@ -0,0 +1,76 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_FLIGHTMANIPULATOR
#define OSGGA_FLIGHTMANIPULATOR 1
#include <osgGA/CameraManipulator>
namespace osgGA{
class OSGGA_EXPORT FlightManipulator : public CameraManipulator
{
public:
FlightManipulator();
virtual ~FlightManipulator();
/** Attach a node to the manipulator.
Automatically detaches previously attached node.
setNode(NULL) detaches previously nodes.
Is ignored by manipulators which do not require a reference model.*/
virtual void setNode(osg::Node*);
/** Return node if attached.*/
virtual const osg::Node* getNode() const;
/** Return node if attached.*/
virtual osg::Node* getNode();
/** Move the camera to the default position.
May be ignored by manipulators if home functionality is not appropriate.*/
virtual void home(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** Start/restart the manipulator.*/
virtual void init(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** handle events, return true if handled, false otherwise.*/
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us);
enum YawControlMode {
YAW_AUTOMATICALLY_WHEN_BANKED,
NO_AUTOMATIC_YAW
};
/** Set the yaw control between no yaw and yawing when banked.*/
void setYawControlMode(YawControlMode ycm) { _yawMode = ycm; }
private:
/** Reset the internal GUIEvent stack.*/
void flushMouseEventStack();
/** Add the current mouse GUIEvent to internal stack.*/
void addMouseEvent(const GUIEventAdapter& ea);
/** For the give mouse movement calculate the movement of the camera.
Return true is camera has moved and a redraw is required.*/
bool calcMovement();
// Internal event stack comprising last three mouse events.
osg::ref_ptr<const GUIEventAdapter> _ga_t1;
osg::ref_ptr<const GUIEventAdapter> _ga_t0;
osg::ref_ptr<osg::Node> _node;
float _modelScale;
float _velocity;
YawControlMode _yawMode;
};
}
#endif

View File

@@ -0,0 +1,55 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_GUIACTIONADAPTER
#define OSGGA_GUIACTIONADAPTER 1
#include <osgGA/Export>
namespace osgGA{
/** Pure virtual base class for adapting the GUI actions requested by CameraManipulators
* into actions which are handled by the GUI toolkit of the users application.
*
* There are several was of using the ActionAdapter either inheriting it as
* done with osgGLUT::Viewer class or passing a simple struct to the camera
* manipulator then unpacking the results and working out what to do to respond
* to the requests.
*
* Also there are several ways to run your app and handle the updating of
* the window. osgGLUT::Viewer always has a idle callback registered which does a
* redraw all the time. osgGLUT::Viewer can safely ignore both requestRedraw() and
* requestContinousUpdate() as these are happening all the time anyway.
*
* Other apps will probably want to respond to the requestRedraw() and
* requestContinousUpdate(bool) and again there is more than one way to handle it.
* You can override requestRedraw() and implement to call your own window
* redraw straight away. Or you can implement so that a flag is set and
* then you then respond the flag being set in your own leisure.
*
* requestContinousUpdate(bool) is for enabling a throw or idle
* callback to be requested by the camera manipulator. Again you can respond
* to this immediately by registering a idle callback or a timed callback, or
* you can delay setting the callback and do at you own leisure.
*
* requestWarpPointer(int,int) is requesting a respositioning of a mouse pointer
* to a specified x,y location on the window. Used by some camera manipulators
* to initialize the mouse pointer when mouse position relative to a controls
* neutral mouse position is required, i.e when mimicking a aircrafts joystick.
*/
class GUIActionAdapter
{
public:
virtual void requestRedraw() = 0;
virtual void requestContinuousUpdate(bool needed=true) = 0;
virtual void requestWarpPointer(int x,int y) = 0;
};
}
#endif

View File

@@ -0,0 +1,89 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_GUIEVENTADAPTER
#define OSGGA_GUIEVENTADAPTER 1
#include <osg/Referenced>
#include <osgGA/Export>
namespace osgGA{
/** Pure virtual base class for adapting platform specific events into
* generic keyboard and mouse events.
*
* Used as GUI toolkit independent input into the osgUtil::CameraManipualor's.
* For an example of how GUIEventAdapter is specialised for a particular GUI
* Toolkit see osgGLUT::GLUTEventAdapter.
*/
class GUIEventAdapter : public osg::Referenced
{
public:
GUIEventAdapter() {}
enum MouseButtonMask {
LEFT_MOUSE_BUTTON=1,
MIDDLE_MOUSE_BUTTON=2,
RIGHT_MOUSE_BUTTON=4
};
enum EventType {
PUSH,
RELEASE,
DRAG,
MOVE,
KEYBOARD,
FRAME,
RESIZE,
NONE
};
/** Get the EventType of the GUI event.*/
virtual EventType getEventType() const = 0;
/** key pressed, return -1 if inappropriate for this event. */
virtual int getKey() const = 0;
/** button pressed/released, return -1 if inappropriate for this event.*/
virtual int getButton() const = 0;
/** window minimum x. */
virtual int getXmin() const = 0;
/** window maximum x. */
virtual int getXmax() const = 0;
/** window minimum y. */
virtual int getYmin() const = 0;
/** window maximum y. */
virtual int getYmax() const = 0;
/** current mouse x position.*/
virtual int getX() const = 0;
/** current mouse y position.*/
virtual int getY() const = 0;
/** current mouse button state */
virtual unsigned int getButtonMask() const = 0;
/** time in seconds of event. */
virtual float time() const = 0;
protected:
/** Force users to create on heap, so that multiple referencing is safe.*/
virtual ~GUIEventAdapter() {}
};
}
#endif

View File

@@ -0,0 +1,123 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_GUIEVENTHANDLER
#define OSGGA_GUIEVENTHANDLER 1
#include <vector>
#include <osg/Referenced>
#include <osgGA/Export>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventHandlerVisitor>
namespace osgGA{
class CompositeGUIEventHandler;
/**
GUIEventHandler provides a basic interface for any class which wants to handle
a GUI Events.
The GUIEvent is supplied by a GUIEventAdapter. Feedback resulting from the
handle method is supplied by a GUIActionAdapter, which allows the GUIEventHandler
to ask the GUI to take some action in response to an incoming event.
For example, consider a Trackball Viewer class which takes mouse events and
manipulates a scene camera in response. The Trackball Viewer is a GUIEventHandler,
and receives the events via the handle method. If the user 'throws' the model,
the Trackball Viewer class can detect this via the incoming events, and
request that the GUI set up a timer callback to continually redraw the view.
This request is made via the GUIActionAdapter class.
*/
class OSGGA_EXPORT GUIEventHandler : public osg::Referenced
{
public:
/** Handle events, return true if handled, false otherwise.*/
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us)=0;
/** Is this const GUIEventHandler a composite? */
virtual const CompositeGUIEventHandler* getComposite() const { return 0; }
/** Is this non-const GUIEventHandler a composite? */
virtual CompositeGUIEventHandler* getComposite() { return 0; }
/** Accept visits from GUIEventHandler visitors */
virtual void accept(GUIEventHandlerVisitor&) = 0;
//virtual void accept(GUIEventHandlerVisitor&) { }
};
/**
CompositeGUIEventHandler allows GUIEventHandlers to be composed into hierarchies.
*/
class OSGGA_EXPORT CompositeGUIEventHandler : public GUIEventHandler
{
public:
typedef std::vector< osg::ref_ptr<GUIEventHandler> > ChildList;
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& aa);
virtual const CompositeGUIEventHandler* getComposite() const { return this; }
virtual CompositeGUIEventHandler* getComposite() { return this; }
virtual void accept(GUIEventHandlerVisitor& v) { v.visit(*this); }
/* Composite-specific methods below */
virtual bool addChild(GUIEventHandler *geh);
virtual bool removeChild(GUIEventHandler *geh);
const int getNumChildren() const { return _children.size(); }
GUIEventHandler *getChild( int i) { return _children[i].get(); }
const GUIEventHandler *getChild( int i ) const { return _children[i].get(); }
bool containsNode( const GUIEventHandler* node ) const
{
for (ChildList::const_iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
if (itr->get()==node) return true;
}
return false;
}
ChildList::iterator findChild( const GUIEventHandler* node )
{
for (ChildList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
if (itr->get()==node) return itr;
}
return _children.end();
}
private:
ChildList _children;
};
}
#endif

View File

@@ -0,0 +1,55 @@
#ifndef OSGGA_GUIEVENTHANDLERVISITOR
#define OSGGA_GUIEVENTHANDLERVISITOR 1
#include <osg/ref_ptr>
#include <osgGA/Export>
#include <osgGA/GUIEventAdapter>
namespace osgGA{
// Some forward declarations
class GUIActionAdapter;
class CompositeGUIEventHandler;
class CameraManipulator;
class StateSetManipulator;
/** Base class primarily for visiting GUIEventHandlers.
A Default Visitor, (Might want to make it an Extrinsic Visitor at some point).
By default, it does nothing to the things it visits. Sub classes of this Visitor
need only override visit operations for the types of object they're interested in.
*/
class OSGGA_EXPORT GUIEventHandlerVisitor
{
public:
virtual void visit(CompositeGUIEventHandler&);
virtual void visit(CameraManipulator&) {};
virtual void visit(StateSetManipulator&) {};
// Accessors
/** Get the GUI EventAdapter associated with this GUIEventHandlerVisitor */
const GUIEventAdapter *getGUIEventAdapter() { return _gea.get(); }
/** Get the GUI Action Adapter associated with this GEH Visitor */
GUIActionAdapter *getGUIActionAdapter() { return _gaa; }
protected:
GUIEventHandlerVisitor(GUIEventAdapter* in, GUIActionAdapter* out):_gea(in),_gaa(out) {}
virtual ~GUIEventHandlerVisitor() {}
private:
osg::ref_ptr<GUIEventAdapter> _gea;
GUIActionAdapter* _gaa; // Just a pointer. NOT owned by this object.
};
};
#endif

View File

@@ -0,0 +1,70 @@
#ifndef OSGUTIL_KEYSWITCCAMERAMANIPULATORHER
#define OSGUTIL_KEYSWITCHCAMERAMANIPULATORER 1
#include <osgGA/Export>
#include <osgGA/CameraManipulator>
#include <osgGA/GUIEventHandler>
#include <osgGA/GUIEventHandlerVisitor>
//#include <osgUtil/CallbackList>
namespace osgGA{
class GUIEventAdapter;
class GUIActionAdapter;
class OSGGA_EXPORT KeySwitchCameraManipulator : public CameraManipulator
{
public:
// Local methods
void addCameraManipulator(int key, std::string name, CameraManipulator *cm);
//typedef void (* Callback)(KeySwitchCameraManipulator *);
// class Callback: public osgUtil::CallbackList<KeySwitchCameraManipulator>::Callback {
// public:
// virtual ~Callback() {};
// virtual void operator()(KeySwitchCameraManipulator *) = 0;
// };
//
// void addCallback(Callback*);
//
// void removeCallback(Callback*);
// Overrides from CameraManipulator...
virtual void setCamera(osg::Camera* c) { _current->setCamera(c); }
virtual const osg::Camera * getCamera() const { return _current->getCamera(); }
virtual osg::Camera * getCamera() { return _current->getCamera(); }
virtual void setNode(osg::Node* n) { _current->setNode(n); }
virtual const osg::Node* getNode() const { return _current->getNode(); }
virtual osg::Node* getNode() { return _current->getNode(); }
virtual void home(const GUIEventAdapter& ee,GUIActionAdapter& aa) { _current->home(ee,aa); }
virtual void init(const GUIEventAdapter& ee,GUIActionAdapter& aa) { _current->init(ee,aa); }
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us);
private:
typedef std::pair<std::string, osg::ref_ptr<CameraManipulator> > NamedManipulator;
typedef std::map<int, NamedManipulator> KeyManipMap;
KeyManipMap _manips;
osg::ref_ptr<CameraManipulator> _current;
// Callbacks
//CallbackList<KeySwitchCameraManipulator> _cameraManipChangeCallbacks;
};
};
#endif

View File

@@ -0,0 +1,40 @@
#ifndef OSGGA_SETSCENEVIEWGEHVISITOR
#define OSGGA_SETSCENEVIEWGEHVISITOR 1
#include <osgGA/GUIEventHandlerVisitor>
#include <osgUtil/SceneView>
namespace osgGA{
// Some forward declarations
class GUIEventHandler;
class CameraManipulator;
/** SetSceneViewGUIEventHandlerVisitor which visits various types of GUIEventHandler and
sets them up appropriately, given a new scene view.
. */
class OSGGA_EXPORT SetSceneViewVisitor: public GUIEventHandlerVisitor
{
public:
SetSceneViewVisitor(GUIEventAdapter* in,
GUIActionAdapter* out,
osgUtil::SceneView* sv):
GUIEventHandlerVisitor(in,out),
_sceneView(sv) {}
virtual ~SetSceneViewVisitor() {}
virtual void visit(CameraManipulator& cm);
virtual void visit(StateSetManipulator& cm);
private:
osg::ref_ptr<osgUtil::SceneView> _sceneView;
};
};
#endif

View File

@@ -0,0 +1,51 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_GEOSTATE_MANIPULATOR
#define OSGGA_GEOSTATE_MANIPULATOR 1
#include <osg/StateSet>
#include <osgGA/Export>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventHandler>
namespace osgGA{
class OSGGA_EXPORT StateSetManipulator : public GUIEventHandler
{
public:
StateSetManipulator();
virtual ~StateSetManipulator();
/** attach a geostate to the manipulator to be used for specifying view.*/
virtual void setStateSet(osg::StateSet*);
/** get the attached a geostate.*/
virtual osg::StateSet * getStateSet();
/** get the attached a geostate.*/
virtual const osg::StateSet * getStateSet() const;
/** Handle events, return true if handled, false otherwise.*/
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** Handle visitations */
virtual void accept(GUIEventHandlerVisitor&);
protected:
// Reference pointer to a geostate
osg::ref_ptr<osg::StateSet> _drawState;
bool _backface;
bool _lighting;
bool _texture;
};
}
#endif

View File

@@ -0,0 +1,77 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_TRACKBALLMANIPULATOR
#define OSGGA_TRACKBALLMANIPULATOR 1
#include <osgGA/CameraManipulator>
namespace osgGA{
class OSGGA_EXPORT TrackballManipulator : public CameraManipulator
{
public:
TrackballManipulator();
virtual ~TrackballManipulator();
/** Attach a node to the manipulator.
Automatically detaches previously attached node.
setNode(NULL) detaches previously nodes.
Is ignored by manipulators which do not require a reference model.*/
virtual void setNode(osg::Node*);
/** Return node if attached.*/
virtual const osg::Node* getNode() const;
/** Return node if attached.*/
virtual osg::Node* getNode();
/** Move the camera to the default position.
May be ignored by manipulators if home functionality is not appropriate.*/
virtual void home(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** Start/restart the manipulator.*/
virtual void init(const GUIEventAdapter& ea,GUIActionAdapter& us);
/** handle events, return true if handled, false otherwise.*/
virtual bool handle(const GUIEventAdapter& ea,GUIActionAdapter& us);
private:
/** Reset the internal GUIEvent stack.*/
void flushMouseEventStack();
/** Add the current mouse GUIEvent to internal stack.*/
void addMouseEvent(const GUIEventAdapter& ea);
/** For the give mouse movement calculate the movement of the camera.
Return true is camera has moved and a redraw is required.*/
bool calcMovement();
void trackball(osg::Vec3& axis,float& angle, float p1x, float p1y, float p2x, float p2y);
float tb_project_to_sphere(float r, float x, float y);
/** Check the speed at which the mouse is moving.
If speed is below a threshold then return false, otherwise return true.*/
bool isMouseMoving();
// Internal event stack comprising last three mouse events.
osg::ref_ptr<const GUIEventAdapter> _ga_t1;
osg::ref_ptr<const GUIEventAdapter> _ga_t0;
osg::ref_ptr<osg::Node> _node;
float _modelScale;
float _minimumZoomScale;
bool _thrown;
};
}
#endif

39
include/osgGA/Version Normal file
View File

@@ -0,0 +1,39 @@
//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSGGA_VERSION
#define OSGGA_VERSION 1
#include <osgGA/Export>
extern "C" {
/**
* getVersion_osgGA() returns the library version number.
* Numbering convention : osg_src-0.8-31 will return 0.8.31 from getVersion_osgGA.
*
* This C function can be also used to check for the existence of the OpenSceneGraph
* library using autoconf and its m4 macro AC_CHECK_LIB.
*
* Here is the code to add to your configure.in:
\verbatim
#
# Check for the OpenSceneGraph (OSG) utility library
#
AC_CHECK_LIB(osg, osgGAGetVersion, ,
[AC_MSG_ERROR(OpenSceneGraph utility library not found. See http://www.openscenegraph.org)],)
\endverbatim
*/
extern OSGGA_EXPORT const char* osgGAGetVersion();
/**
* getLibraryName_osgGA() returns the library name in human friendly form.
*/
extern OSGGA_EXPORT const char* osgGAGetLibraryName();
}
#endif

View File

@@ -0,0 +1,37 @@
#include <osg/GL>
#include <osg/Matrix>
#include <osgGA/CameraManipulator>
using namespace osg;
using namespace osgGA;
CameraManipulator::CameraManipulator(): _camera(NULL)
{
}
CameraManipulator::~CameraManipulator()
{
}
void CameraManipulator::setCamera(Camera *camera)
{
_camera=camera;
}
const Camera *CameraManipulator::getCamera() const
{
return _camera.get();
}
Camera *CameraManipulator::getCamera()
{
return _camera.get();
}
bool CameraManipulator::handle(const GUIEventAdapter&,GUIActionAdapter&)
{
return false;
}

View File

@@ -0,0 +1,565 @@
#if defined(_MSC_VER)
#pragma warning( disable : 4786 )
#endif
#include <osgGA/DriveManipulator>
#include <osgUtil/IntersectVisitor>
#include <osg/Notify>
using namespace osg;
using namespace osgGA;
DriveManipulator::DriveManipulator()
{
_modelScale = 0.01f;
_velocity = 0.0f;
//_speedMode = USE_MOUSE_Y_FOR_SPEED;
_speedMode = USE_MOUSE_BUTTONS_FOR_SPEED;
}
DriveManipulator::~DriveManipulator()
{
}
void DriveManipulator::setNode(osg::Node* node)
{
_node = node;
if (_node.get())
{
const osg::BoundingSphere& boundingSphere=_node->getBound();
_modelScale = boundingSphere._radius;
_height = sqrtf(_modelScale)*0.03f;
_buffer = sqrtf(_modelScale)*0.05f;
}
}
const osg::Node* DriveManipulator::getNode() const
{
return _node.get();
}
osg::Node* DriveManipulator::getNode()
{
return _node.get();
}
void DriveManipulator::home(const GUIEventAdapter& ea,GUIActionAdapter& us)
{
if(_node.get() && _camera.get())
{
const osg::BoundingSphere& boundingSphere=_node->getBound();
osg::Vec3 ep = boundingSphere._center;
osg::Vec3 bp = ep;
ep.z() -= _modelScale*0.0001f;
bp.z() -= _modelScale;
// check to see if any obstruction in front.
osgUtil::IntersectVisitor iv;
bool cameraSet = false;
osg::ref_ptr<osg::LineSegment> segDown = new osg::LineSegment;
segDown->set(ep,bp);
iv.addLineSegment(segDown.get());
_node->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segDown.get());
if (!hitList.empty())
{
// notify(INFO) << "Hit terrain ok"<< std::endl;
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
osg::Vec3 np = hitList.front().getWorldIntersectNormal();
osg::Vec3 uv;
if (np.z()>0.0f) uv = np;
else uv = -np;
float lookDistance = _modelScale*0.1f;
ep = ip;
ep.z() += _height;
osg::Vec3 lv = uv^osg::Vec3(1.0f,0.0f,0.0f);
osg::Vec3 cp = ep+lv*lookDistance;
_camera->setLookAt(ep,cp,uv);
cameraSet = true;
}
}
if (!cameraSet)
{
bp = ep;
bp.z() += _modelScale;
osg::ref_ptr<osg::LineSegment> segUp = new osg::LineSegment;
segUp->set(ep,bp);
iv.addLineSegment(segUp.get());
_node->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segUp.get());
if (!hitList.empty())
{
// notify(INFO) << "Hit terrain ok"<< std::endl;
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
osg::Vec3 np = hitList.front().getWorldIntersectNormal();
osg::Vec3 uv;
if (np.z()>0.0f) uv = np;
else uv = -np;
float lookDistance = _modelScale*0.1f;
ep = ip;
ep.z() += _height;
osg::Vec3 lv = uv^osg::Vec3(1.0f,0.0f,0.0f);
osg::Vec3 cp = ep+lv*lookDistance;
_camera->setLookAt(ep,cp,uv);
cameraSet = true;
}
}
}
if (!cameraSet)
{
// eye
_camera->setLookAt(boundingSphere._center+osg::Vec3( 0.0,-2.0f * boundingSphere._radius,0.0f),
// look
boundingSphere._center,
// up
osg::Vec3(0.0f,0.0f,1.0f));
}
}
_velocity = 0.0f;
us.requestRedraw();
us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2,(ea.getYmin()+ea.getYmax())/2);
flushMouseEventStack();
}
void DriveManipulator::init(const GUIEventAdapter& ea,GUIActionAdapter& us)
{
flushMouseEventStack();
us.requestContinuousUpdate(false);
_velocity = 0.0f;
osg::Vec3 ep = _camera->getEyePoint();
osg::Vec3 sv = _camera->getSideVector();
osg::Vec3 bp = ep;
bp.z() -= _modelScale;
// check to see if any obstruction in front.
osgUtil::IntersectVisitor iv;
bool cameraSet = false;
osg::ref_ptr<osg::LineSegment> segDown = new osg::LineSegment;
segDown->set(ep,bp);
iv.addLineSegment(segDown.get());
_node->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segDown.get());
if (!hitList.empty())
{
// notify(INFO) << "Hit terrain ok"<< std::endl;
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
osg::Vec3 np = hitList.front().getWorldIntersectNormal();
osg::Vec3 uv;
if (np.z()>0.0f) uv = np;
else uv = -np;
float lookDistance = _modelScale*0.1f;
ep = ip+uv*_height;
osg::Vec3 lv = uv^sv;
osg::Vec3 lp = ep+lv*lookDistance;
_camera->setLookAt(ep,lp,uv);
_camera->ensureOrthogonalUpVector();
cameraSet = true;
}
}
if (!cameraSet)
{
bp = ep;
bp.z() += _modelScale;
osg::ref_ptr<osg::LineSegment> segUp = new osg::LineSegment;
segUp->set(ep,bp);
iv.addLineSegment(segUp.get());
_node->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segUp.get());
if (!hitList.empty())
{
// notify(INFO) << "Hit terrain ok"<< std::endl;
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
osg::Vec3 np = hitList.front().getWorldIntersectNormal();
osg::Vec3 uv;
if (np.z()>0.0f) uv = np;
else uv = -np;
float lookDistance = _modelScale*0.1f;
ep = ip+uv*_height;
osg::Vec3 lv = uv^sv;
osg::Vec3 lp = ep+lv*lookDistance;
_camera->setLookAt(ep,lp,uv);
_camera->ensureOrthogonalUpVector();
cameraSet = true;
}
}
}
us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2,(ea.getYmin()+ea.getYmax())/2);
}
bool DriveManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
{
if(!_camera.get()) return false;
switch(ea.getEventType())
{
case(GUIEventAdapter::PUSH):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::RELEASE):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::DRAG):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::MOVE):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::KEYBOARD):
{
if (ea.getKey()==' ')
{
flushMouseEventStack();
home(ea,us);
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
}
else if (ea.getKey()=='q')
{
_speedMode = USE_MOUSE_Y_FOR_SPEED;
return true;
}
else if (ea.getKey()=='a')
{
_speedMode = USE_MOUSE_BUTTONS_FOR_SPEED;
return true;
}
else if (ea.getKey()=='+')
{
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()*1.25f);
return true;
}
else if (ea.getKey()=='-')
{
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()/1.25f);
return true;
}
return false;
}
case(GUIEventAdapter::FRAME):
{
addMouseEvent(ea);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::RESIZE):
{
init(ea,us);
us.requestRedraw();
return true;
}
default:
return false;
}
}
void DriveManipulator::flushMouseEventStack()
{
_ga_t1 = NULL;
_ga_t0 = NULL;
}
void DriveManipulator::addMouseEvent(const GUIEventAdapter& ea)
{
_ga_t1 = _ga_t0;
_ga_t0 = &ea;
}
bool DriveManipulator::calcMovement()
{
_camera->setFusionDistanceMode(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE);
// return if less then two events have been added.
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
float dt = _ga_t0->time()-_ga_t1->time();
if (dt<0.0f)
{
notify(WARN) << "warning dt = "<<dt<< std::endl;
dt = 0.0f;
}
switch(_speedMode)
{
case(USE_MOUSE_Y_FOR_SPEED):
{
float my = (_ga_t0->getYmin()+_ga_t0->getYmax())/2.0f;
float dy = _ga_t0->getY()-my;
_velocity = -_modelScale*0.0002f*dy;
break;
}
case(USE_MOUSE_BUTTONS_FOR_SPEED):
{
unsigned int buttonMask = _ga_t1->getButtonMask();
if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
{
// pan model.
_velocity += dt*_modelScale*0.02f;
}
else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
{
_velocity = 0.0f;
}
else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
{
_velocity -= dt*_modelScale*0.02f;
}
break;
}
}
// rotate the camera.
osg::Vec3 center = _camera->getEyePoint();
osg::Vec3 uv = _camera->getUpVector();
float mx = (_ga_t0->getXmin()+_ga_t0->getXmax())/2.0f;
float dx = _ga_t0->getX()-mx;
float yaw = -inDegrees(dx*0.1f*dt);
osg::Matrix mat;
mat.makeTranslate(-center.x(),-center.y(),-center.z());
mat *= Matrix::rotate(yaw,uv.x(),uv.y(),uv.z());
mat *= Matrix::translate(center.x(),center.y(),center.z());
center = _camera->getEyePoint();
uv = _camera->getUpVector();
_camera->transformLookAt(mat);
// get the new forward (look) vector.
osg::Vec3 sv = _camera->getSideVector();
osg::Vec3 lv = _camera->getCenterPoint()-_camera->getEyePoint();
float lookDistance = lv.length();
lv.normalize();
// movement is big enough the move the eye point along the look vector.
if (fabsf(_velocity*dt)>1e-8)
{
osg::Vec3 ep = _camera->getEyePoint();
float distanceToMove = _velocity*dt;
float signedBuffer;
if (distanceToMove>=0.0f) signedBuffer=_buffer;
else signedBuffer=-_buffer;
// check to see if any obstruction in front.
osgUtil::IntersectVisitor iv;
osg::ref_ptr<osg::LineSegment> segForward = new osg::LineSegment;
segForward->set(ep,ep+lv*(signedBuffer+distanceToMove));
iv.addLineSegment(segForward.get());
_node->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segForward.get());
if (!hitList.empty())
{
// notify(INFO) << "Hit obstruction"<< std::endl;
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
distanceToMove = (ip-ep).length()-_buffer;
_velocity = 0.0f;
}
}
// check to see if forward point is correct height above terrain.
osg::Vec3 fp = ep+lv*distanceToMove;
osg::Vec3 lfp = fp-uv*_height*5;
iv.reset();
osg::ref_ptr<osg::LineSegment> segNormal = new osg::LineSegment;
segNormal->set(fp,lfp);
iv.addLineSegment(segNormal.get());
_node->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segNormal.get());
if (!hitList.empty())
{
// notify(INFO) << "Hit terrain ok"<< std::endl;
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
osg::Vec3 np = hitList.front().getWorldIntersectNormal();
if (uv*np>0.0f) uv = np;
else uv = -np;
ep = ip+uv*_height;
lv = uv^sv;
osg::Vec3 lp = ep+lv*lookDistance;
_camera->setLookAt(ep,lp,uv);
_camera->ensureOrthogonalUpVector();
return true;
}
}
// no hit on the terrain found therefore resort to a fall under
// under the influence of gravity.
osg::Vec3 dp = lfp;
dp.z() -= 2*_modelScale;
iv.reset();
osg::ref_ptr<osg::LineSegment> segFall = new osg::LineSegment;
segFall->set(lfp,dp);
iv.addLineSegment(segFall.get());
_node->accept(iv);
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segFall.get());
if (!hitList.empty())
{
notify(INFO) << "Hit terrain on decent ok"<< std::endl;
osg::Vec3 ip = hitList.front().getWorldIntersectPoint();
osg::Vec3 np = hitList.front().getWorldIntersectNormal();
if (uv*np>0.0f) uv = np;
else uv = -np;
ep = ip+uv*_height;
lv = uv^sv;
osg::Vec3 lp = ep+lv*lookDistance;
_camera->setLookAt(ep,lp,uv);
_camera->ensureOrthogonalUpVector();
return true;
}
}
// no collision with terrain has been found therefore track horizontally.
lv *= (_velocity*dt);
ep += lv;
osg::Vec3 lp = _camera->getCenterPoint()+lv;
_camera->setLookAt(ep,lp,uv);
_camera->ensureOrthogonalUpVector();
}
return true;
}

View File

@@ -0,0 +1,245 @@
#include <osgGA/FlightManipulator>
#include <osg/Types>
#include <osg/Notify>
using namespace osg;
using namespace osgGA;
FlightManipulator::FlightManipulator()
{
_modelScale = 0.01f;
_velocity = 0.0f;
_yawMode = YAW_AUTOMATICALLY_WHEN_BANKED;
}
FlightManipulator::~FlightManipulator()
{
}
void FlightManipulator::setNode(osg::Node* node)
{
_node = node;
if (_node.get())
{
const osg::BoundingSphere& boundingSphere=_node->getBound();
_modelScale = boundingSphere._radius;
}
}
const osg::Node* FlightManipulator::getNode() const
{
return _node.get();
}
osg::Node* FlightManipulator::getNode()
{
return _node.get();
}
void FlightManipulator::home(const GUIEventAdapter& ea,GUIActionAdapter& us)
{
if(_node.get() && _camera.get())
{
const osg::BoundingSphere& boundingSphere=_node->getBound();
_camera->setLookAt(
boundingSphere._center+osg::Vec3( 0.0,-3.0f * boundingSphere._radius,0.0f),
boundingSphere._center,
osg::Vec3(0.0f,0.0f,1.0f));
_velocity = 0.0f;
us.requestRedraw();
us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2,(ea.getYmin()+ea.getYmax())/2);
flushMouseEventStack();
}
}
void FlightManipulator::init(const GUIEventAdapter& ea,GUIActionAdapter& us)
{
flushMouseEventStack();
us.requestContinuousUpdate(false);
_velocity = 0.0f;
us.requestWarpPointer((ea.getXmin()+ea.getXmax())/2,(ea.getYmin()+ea.getYmax())/2);
}
bool FlightManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
{
if(!_camera.get()) return false;
switch(ea.getEventType())
{
case(GUIEventAdapter::PUSH):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::RELEASE):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::DRAG):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::MOVE):
{
addMouseEvent(ea);
us.requestContinuousUpdate(true);
if (calcMovement()) us.requestRedraw();
return true;
}
case(GUIEventAdapter::KEYBOARD):
if (ea.getKey()==' ')
{
flushMouseEventStack();
home(ea,us);
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
}
else if (ea.getKey()=='+')
{
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()*1.25f);
return true;
}
else if (ea.getKey()=='-')
{
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()/1.25f);
return true;
}
return false;
case(GUIEventAdapter::FRAME):
addMouseEvent(ea);
if (calcMovement()) us.requestRedraw();
return true;
case(GUIEventAdapter::RESIZE):
init(ea,us);
us.requestRedraw();
return true;
default:
return false;
}
}
void FlightManipulator::flushMouseEventStack()
{
_ga_t1 = NULL;
_ga_t0 = NULL;
}
void FlightManipulator::addMouseEvent(const GUIEventAdapter& ea)
{
_ga_t1 = _ga_t0;
_ga_t0 = &ea;
}
bool FlightManipulator::calcMovement()
{
_camera->setFusionDistanceMode(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE);
// return if less then two events have been added.
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
float dt = _ga_t0->time()-_ga_t1->time();
if (dt<0.0f)
{
notify(WARN) << "warning dt = "<<dt<< std::endl;
dt = 0.0f;
}
unsigned int buttonMask = _ga_t1->getButtonMask();
if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
{
// pan model.
_velocity += dt*_modelScale*0.05f;
}
else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
{
_velocity = 0.0f;
}
else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
{
_velocity -= dt*_modelScale*0.05f;
}
float mx = (_ga_t0->getXmin()+_ga_t0->getXmax())/2.0f;
float my = (_ga_t0->getYmin()+_ga_t0->getYmax())/2.0f;
float dx = _ga_t0->getX()-mx;
float dy = _ga_t0->getY()-my;
osg::Vec3 center = _camera->getEyePoint();
osg::Vec3 sv = _camera->getSideVector();
osg::Vec3 lv = _camera->getLookVector();
float pitch = inDegrees(dy*0.15f*dt);
float roll = inDegrees(dx*0.1f*dt);
osg::Matrix mat;
mat.makeTranslate(-center);
mat *= Matrix::rotate(pitch,sv.x(),sv.y(),sv.z());
mat *= Matrix::rotate(roll,lv.x(),lv.y(),lv.z());
if (_yawMode==YAW_AUTOMATICALLY_WHEN_BANKED)
{
float bank = asinf(sv.z());
float yaw = inRadians(bank)*dt;
mat *= Matrix::rotate(yaw,0.0f,0.0f,1.0f);
}
lv *= (_velocity*dt);
mat *= Matrix::translate(center+lv);
_camera->transformLookAt(mat);
return true;
}

View File

@@ -0,0 +1,43 @@
#include <osgGA/GUIEventHandler>
using osgGA::CompositeGUIEventHandler;
bool CompositeGUIEventHandler::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
bool result=false;
for (ChildList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
{
result |= (*itr)->handle(ea,aa);
}
return result;
}
bool CompositeGUIEventHandler::addChild(GUIEventHandler *child)
{
if (child && !containsNode(child))
{
// note ref_ptr<> automatically handles incrementing child's reference count.
_children.push_back(child);
return true;
}
else return false;
}
bool CompositeGUIEventHandler::removeChild(GUIEventHandler *child)
{
ChildList::iterator itr = findChild(child);
if (itr!=_children.end())
{
// note ref_ptr<> automatically handles decrementing child's reference count.
_children.erase(itr);
return true;
}
else return false;
}

View File

@@ -0,0 +1,9 @@
#include <osgGA/GUIEventHandlerVisitor>
#include <osgGA/GUIEventHandler>
void osgGA::GUIEventHandlerVisitor::visit(osgGA::CompositeGUIEventHandler& cgeh)
{
for(int i=0; i<cgeh.getNumChildren(); i++){
cgeh.getChild(i)->accept(*this);
}
}

View File

@@ -0,0 +1,45 @@
#include <osgGA/KeySwitchCameraManipulator>
#include <osg/Notify>
using namespace osgGA;
void KeySwitchCameraManipulator::addCameraManipulator(int key, std::string name, CameraManipulator *cm)
{
if(!cm) return;
_manips[key]=std::make_pair(name,osg::ref_ptr<CameraManipulator>(cm));
if(!_current.valid()){
_current=cm;
}
}
bool KeySwitchCameraManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
if(ea.getEventType()==GUIEventAdapter::KEYBOARD){
KeyManipMap::iterator it=_manips.find(ea.getKey());
if(it != _manips.end()){
osg::notify(osg::INFO)<<"Switching to manipulator: "<<(*it).second.first<<endl;
cout<<"***Switching to manipulator: "<<(*it).second.first<<endl;
it->second.second->setNode(_current->getNode());
it->second.second->setCamera(_current->getCamera());
it->second.second->init(ea,aa);
_current = it->second.second;
//_cameraManipChangeCallbacks.notify(this);
}
}
return _current->handle(ea,aa);
}
// void KeySwitchCameraManipulator::addCallback(Callback* c)
// {
// _cameraManipChangeCallbacks.addCallback(c);
// }
//
// void KeySwitchCameraManipulator::removeCallback(Callback* c)
// {
// _cameraManipChangeCallbacks.removeCallback(c);
// }

24
src/osgGA/Makefile Normal file
View File

@@ -0,0 +1,24 @@
TOPDIR = ../..
include $(TOPDIR)/Make/makedefs
CXXFILES = \
CameraManipulator.cpp\
DriveManipulator.cpp\
FlightManipulator.cpp\
GUIEventHandler.cpp\
GUIEventHandlerVisitor.cpp\
KeySwitchCameraManipulator.cpp\
SetSceneViewVisitor.cpp\
StateSetManipulator.cpp\
TrackballManipulator.cpp\
Version.cpp\
DEF += -DOSGGA_LIBRARY
LIBS += -losgUtil -losg $(GL_LIBS) $(OTHER_LIBS)
TARGET_BASENAME = osgGA
LIB = $(LIB_PREFIX)$(TARGET_BASENAME).$(LIB_EXT)
include $(TOPDIR)/Make/makerules

View File

@@ -0,0 +1,16 @@
#include <osgGA/SetSceneViewVisitor>
#include <osgGA/CameraManipulator>
#include <osgGA/StateSetManipulator>
void osgGA::SetSceneViewVisitor::visit(osgGA::CameraManipulator& cm)
{
cm.setNode(_sceneView->getSceneData());
cm.setCamera(_sceneView->getCamera());
cm.init(*getGUIEventAdapter(),*getGUIActionAdapter());
cm.home(*getGUIEventAdapter(),*getGUIActionAdapter());
}
void osgGA::SetSceneViewVisitor::visit(osgGA::StateSetManipulator& ssm)
{
ssm.setStateSet(_sceneView->getGlobalStateSet());
}

View File

@@ -0,0 +1,73 @@
#include <osgGA/StateSetManipulator>
using namespace osg;
using namespace osgGA;
StateSetManipulator::StateSetManipulator(): _drawState(NULL)
{
}
StateSetManipulator::~StateSetManipulator()
{
}
void StateSetManipulator::setStateSet(StateSet *drawState)
{
_drawState=drawState;
if(!_drawState.valid()) return;
_backface = (_drawState->getMode(GL_CULL_FACE)==osg::StateAttribute::ON);
_lighting =(_drawState->getMode(GL_LIGHTING)==osg::StateAttribute::ON);
_texture =(_drawState->getMode(GL_TEXTURE_2D)==osg::StateAttribute::ON);
}
StateSet *StateSetManipulator::getStateSet()
{
return _drawState.get();
}
const StateSet *StateSetManipulator::getStateSet() const
{
return _drawState.get();
}
bool StateSetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
if(!_drawState.valid()) return false;
if(ea.getEventType()==GUIEventAdapter::KEYBOARD){
switch( ea.getKey() ){
case 'b' :
_backface = !_backface;
if( _backface ) _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
else _drawState->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE_OFF);
aa.requestRedraw();
return true;
break;
case 'l' :
_lighting = !_lighting ;
if( _lighting ) _drawState->setMode(GL_LIGHTING,osg::StateAttribute::ON);
else _drawState->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE_OFF);
aa.requestRedraw();
return true;
break;
case 't' :
_texture = !_texture;
if (_texture) _drawState->setMode(GL_TEXTURE_2D,osg::StateAttribute::INHERIT);
else _drawState->setMode(GL_TEXTURE_2D,osg::StateAttribute::OVERRIDE_OFF);
aa.requestRedraw();
return true;
break;
}
}
return false;
}
void StateSetManipulator::accept(GUIEventHandlerVisitor& gehv)
{
gehv.visit(*this);
}

View File

@@ -0,0 +1,397 @@
#include <osgGA/TrackballManipulator>
#include <osg/Types>
#include <osg/Notify>
using namespace osg;
using namespace osgGA;
TrackballManipulator::TrackballManipulator()
{
_modelScale = 0.01f;
_minimumZoomScale = 0.05f;
_thrown = false;
}
TrackballManipulator::~TrackballManipulator()
{
}
void TrackballManipulator::setNode(osg::Node* node)
{
_node = node;
if (_node.get())
{
const osg::BoundingSphere& boundingSphere=_node->getBound();
_modelScale = boundingSphere._radius;
}
}
const osg::Node* TrackballManipulator::getNode() const
{
return _node.get();
}
osg::Node* TrackballManipulator::getNode()
{
return _node.get();
}
/*ea*/
void TrackballManipulator::home(const GUIEventAdapter& ,GUIActionAdapter& us)
{
if(_node.get() && _camera.get())
{
const osg::BoundingSphere& boundingSphere=_node->getBound();
_camera->setView(boundingSphere._center+osg::Vec3( 0.0,-3.0f * boundingSphere._radius,0.0f),
boundingSphere._center,
osg::Vec3(0.0f,0.0f,1.0f));
us.requestRedraw();
}
}
void TrackballManipulator::init(const GUIEventAdapter& ,GUIActionAdapter& )
{
flushMouseEventStack();
}
bool TrackballManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
{
if(!_camera.get()) return false;
switch(ea.getEventType())
{
case(GUIEventAdapter::PUSH):
{
flushMouseEventStack();
addMouseEvent(ea);
if (calcMovement()) us.requestRedraw();
us.requestContinuousUpdate(false);
_thrown = false;
return true;
}
case(GUIEventAdapter::RELEASE):
{
if (ea.getButtonMask()==0)
{
if (isMouseMoving())
{
if (calcMovement())
{
us.requestRedraw();
us.requestContinuousUpdate(true);
_thrown = true;
}
}
else
{
flushMouseEventStack();
addMouseEvent(ea);
if (calcMovement()) us.requestRedraw();
us.requestContinuousUpdate(false);
_thrown = false;
}
}
else
{
flushMouseEventStack();
addMouseEvent(ea);
if (calcMovement()) us.requestRedraw();
us.requestContinuousUpdate(false);
_thrown = false;
}
return true;
}
case(GUIEventAdapter::DRAG):
{
addMouseEvent(ea);
if (calcMovement()) us.requestRedraw();
us.requestContinuousUpdate(false);
_thrown = false;
return true;
}
case(GUIEventAdapter::MOVE):
{
return false;
}
case(GUIEventAdapter::KEYBOARD):
if (ea.getKey()==' ')
{
flushMouseEventStack();
_thrown = false;
home(ea,us);
us.requestRedraw();
us.requestContinuousUpdate(false);
return true;
} else if (ea.getKey()=='+')
{
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()*1.25f);
return true;
}
else if (ea.getKey()=='-')
{
_camera->setFusionDistanceRatio(_camera->getFusionDistanceRatio()/1.25f);
return true;
}
return false;
case(GUIEventAdapter::FRAME):
_camera->setFusionDistanceMode(osg::Camera::PROPORTIONAL_TO_LOOK_DISTANCE);
if (_thrown)
{
if (calcMovement()) us.requestRedraw();
return true;
}
return false;
default:
return false;
}
}
bool TrackballManipulator::isMouseMoving()
{
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
static const float velocity = 100.0f;
float dx = _ga_t0->getX()-_ga_t1->getX();
float dy = _ga_t0->getY()-_ga_t1->getY();
float len = sqrtf(dx*dx+dy*dy);
float dt = _ga_t0->time()-_ga_t1->time();
return (len>dt*velocity);
}
void TrackballManipulator::flushMouseEventStack()
{
_ga_t1 = NULL;
_ga_t0 = NULL;
}
void TrackballManipulator::addMouseEvent(const GUIEventAdapter& ea)
{
_ga_t1 = _ga_t0;
_ga_t0 = &ea;
}
bool TrackballManipulator::calcMovement()
{
// return if less then two events have been added.
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
float dx = _ga_t0->getX()-_ga_t1->getX();
float dy = _ga_t0->getY()-_ga_t1->getY();
// return if there is no movement.
if (dx==0 && dy==0) return false;
float focalLength = (_camera->getCenterPoint()-_camera->getEyePoint()).length();
unsigned int buttonMask = _ga_t1->getButtonMask();
if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
{
// rotate camera.
osg::Vec3 center = _camera->getCenterPoint();
osg::Vec3 axis;
float angle;
float mx0 = (_ga_t0->getXmin()+_ga_t0->getXmax())/2.0f;
float rx0 = (_ga_t0->getXmax()-_ga_t0->getXmin())/2.0f;
float my0 = (_ga_t0->getYmin()+_ga_t0->getYmax())/2.0f;
float ry0 = (_ga_t0->getYmax()-_ga_t0->getYmin())/2.0f;
float mx1 = (_ga_t0->getXmin()+_ga_t1->getXmax())/2.0f;
float rx1 = (_ga_t0->getXmax()-_ga_t1->getXmin())/2.0f;
float my1 = (_ga_t1->getYmin()+_ga_t1->getYmax())/2.0f;
float ry1 = (_ga_t1->getYmax()-_ga_t1->getYmin())/2.0f;
float px0 = (_ga_t0->getX()-mx0)/rx0;
float py0 = (my0-_ga_t0->getY())/ry0;
float px1 = (_ga_t1->getX()-mx1)/rx1;
float py1 = (my1-_ga_t1->getY())/ry1;
trackball(axis,angle,px1,py1,px0,py0);
osg::Matrix mat;
mat.makeTranslate(-center.x(),-center.y(),-center.z());
mat *= Matrix::rotate(angle,axis.x(),axis.y(),axis.z());
mat *= Matrix::translate(center.x(),center.y(),center.z());
_camera->transformLookAt(mat);
return true;
}
else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
{
// pan model.
float scale = 0.0015f*focalLength;
osg::Vec3 uv = _camera->getUpVector();
osg::Vec3 sv = _camera->getSideVector();
osg::Vec3 dv = uv*(dy*scale)-sv*(dx*scale);
osg::Matrix mat;
mat.makeTranslate(dv.x(),dv.y(),dv.z());
_camera->transformLookAt(mat);
return true;
}
else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
{
// zoom model.
float fd = focalLength;
float scale = 1.0f-dy*0.001f;
if (fd*scale>_modelScale*_minimumZoomScale)
{
// zoom camera in.
osg::Vec3 center = _camera->getCenterPoint();
osg::Matrix mat;
mat.makeTranslate(-center.x(),-center.y(),-center.z());
mat *= Matrix::scale(scale,scale,scale);
mat *= Matrix::translate(center.x(),center.y(),center.z());
_camera->transformLookAt(mat);
}
else
{
// notify(DEBUG_INFO) << "Pushing forward"<<std::endl;
// push the camera forward.
float scale = 0.0015f*fd;
osg::Vec3 dv = _camera->getLookVector()*(dy*scale);
osg::Matrix mat;
mat.makeTranslate(dv.x(),dv.y(),dv.z());
_camera->transformLookAt(mat);
}
return true;
}
return false;
}
/*
* This size should really be based on the distance from the center of
* rotation to the point on the object underneath the mouse. That
* point would then track the mouse as closely as possible. This is a
* simple example, though, so that is left as an Exercise for the
* Programmer.
*/
const float TRACKBALLSIZE = 0.8f;
/*
* Ok, simulate a track-ball. Project the points onto the virtual
* trackball, then figure out the axis of rotation, which is the cross
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
* Note: This is a deformed trackball-- is a trackball in the center,
* but is deformed into a hyperbolic sheet of rotation away from the
* center. This particular function was chosen after trying out
* several variations.
*
* It is assumed that the arguments to this routine are in the range
* (-1.0 ... 1.0)
*/
void TrackballManipulator::trackball(osg::Vec3& axis,float& angle, float p1x, float p1y, float p2x, float p2y)
{
/*
* First, figure out z-coordinates for projection of P1 and P2 to
* deformed sphere
*/
osg::Vec3 uv = _camera->getUpVector();
osg::Vec3 sv = _camera->getSideVector();
osg::Vec3 lv = _camera->getLookVector();
osg::Vec3 p1 = sv*p1x+uv*p1y-lv*tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y);
osg::Vec3 p2 = sv*p2x+uv*p2y-lv*tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y);
/*
* Now, we want the cross product of P1 and P2
*/
// Robert,
//
// This was the quick 'n' dirty fix to get the trackball doing the right
// thing after fixing the Quat rotations to be right-handed. You may want
// to do something more elegant.
// axis = p1^p2;
axis = p2^p1;
axis.normalize();
/*
* Figure out how much to rotate around that axis.
*/
float t = (p2-p1).length() / (2.0*TRACKBALLSIZE);
/*
* Avoid problems with out-of-control values...
*/
if (t > 1.0) t = 1.0;
if (t < -1.0) t = -1.0;
angle = inRadians(asin(t));
}
/*
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
* if we are away from the center of the sphere.
*/
float TrackballManipulator::tb_project_to_sphere(float r, float x, float y)
{
float d, t, z;
d = sqrt(x*x + y*y);
/* Inside sphere */
if (d < r * 0.70710678118654752440)
{
z = sqrt(r*r - d*d);
} /* On hyperbola */
else
{
t = r / 1.41421356237309504880;
z = t*t / d;
}
return z;
}

12
src/osgGA/Version.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include <osgGA/Version>
const char* osgGAGetVersion()
{
return "0.8.45";
}
const char* osgGAGetLibraryName()
{
return "Open Scene Graph Gui Adapter Library";
}

View File

@@ -257,6 +257,12 @@ void SceneView::cull()
cullStage(projectionRight.get(),modelviewRight.get(),_cullVisitorRight.get(),_rendergraphRight.get(),_renderStageRight.get());
// if (_camera.valid())
// {
// // clamp the camera to the near/far computed in cull traversal.
// _camera->setNearFar(_cullVisitorRight->getCalculatedNearPlane(),_cullVisitorRight->getCalculatedFarPlane());
// }
}
else
{
@@ -278,8 +284,15 @@ void SceneView::cull()
_cullVisitor->setTraversalMask(_cullMask);
cullStage(projection.get(),modelview.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get());
// if (_camera.valid())
// {
// // clamp the camera to the near/far computed in cull traversal.
// _camera->setNearFar(_cullVisitor->getCalculatedNearPlane(),_cullVisitor->getCalculatedFarPlane());
// }
}
}
void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage)