diff --git a/Make/makedirdefs b/Make/makedirdefs index 8d8eef874..9555990cc 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -22,7 +22,8 @@ SRC_DIRS = \ osgParticle \ osgFX \ osgShadow \ - osgSim + osgSim \ + osgManipulator ifeq ($(PRODUCER_INSTALLED),yes) SRC_DIRS += osgProducer @@ -272,6 +273,7 @@ EXAMPLE_DIRS = \ osgvertexprogram \ osgvolume \ osgwindows \ + osgmanipulator \ ifeq ($(COMPILE_INTROSPECTION),yes) diff --git a/VisualStudio/OpenSceneGraph.dsw b/VisualStudio/OpenSceneGraph.dsw index 6d8f020a9..929c95b21 100644 --- a/VisualStudio/OpenSceneGraph.dsw +++ b/VisualStudio/OpenSceneGraph.dsw @@ -99,6 +99,27 @@ Package=<4> ############################################################################### +Project: "Core osgManipulator"=.\osgManipulator\osgManipulator.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 + Begin Project Dependency + Project_Dep_Name Core osgGA + End Project Dependency +}}} + +############################################################################### + Project: "Core osgShadow"=.\osgShadow\osgShadow.dsp - Package Owner=<4> Package=<5> @@ -1302,6 +1323,36 @@ Package=<4> ############################################################################### +Project: "Example osgparticle"=.\examples\osgmanipulator\osgmanipulatordemo.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 osgDB + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgGA + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgManipulator + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgProducer + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgUtil + End Project Dependency +}}} + +############################################################################### + Project: "Example osgmovie"=.\examples\osgmovie\osgmovie.dsp - Package Owner=<4> Package=<5> diff --git a/VisualStudio/examples/osgmanipulator/osgmanipulatordemo.dsp b/VisualStudio/examples/osgmanipulator/osgmanipulatordemo.dsp new file mode 100644 index 000000000..f6b7a602b --- /dev/null +++ b/VisualStudio/examples/osgmanipulator/osgmanipulatordemo.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="Example osgmanipulator" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Example osgmanipulator - 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 "osgmanipulatordemo.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 "osgmanipulatordemo.mak" CFG="Example osgmanipulator - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Example osgmanipulator - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Example osgmanipulator - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Example osgmanipulator - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../bin/$(PlatformName)" +# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /I "../../../../OpenThreads/include" /I "../../../../Producer/include" /I "../../../../3rdParty/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /Zm200 /c +# 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 /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 OpenThreadsWin32.lib Producer.lib /nologo /subsystem:console /debug /machine:I386 /opt:ref /opt:icf /out:"$(OutDir)/osgmanipulator.exe" /libpath:"../../../lib/$(PlatformName)" /libpath:"../../../../OpenThreads/lib/$(PlatformName)" /libpath:"../../../../Producer/lib/$(PlatformName)" /libpath:"../../../../3rdParty/lib/$(PlatformName)" /libpath:"../../../../3rdParty/lib" + +!ELSEIF "$(CFG)" == "Example osgmanipulator - 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 "../../../bin/$(PlatformName)" +# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "../../../include" /I "../../../../OpenThreads/include" /I "../../../../Producer/include" /I "../../../../3rdParty/include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /D "_CRT_SECURE_NO_DEPRECATE" /FR /YX /FD /Zm200 /c +# 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 /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 OpenThreadsWin32d.lib Produced.lib glu32.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"$(OutDir)/osgmanipulatord.exe" /pdbtype:sept /libpath:"../../../lib/$(PlatformName)" /libpath:"../../../../OpenThreads/lib/$(PlatformName)" /libpath:"../../../../Producer/lib/$(PlatformName)"/libpath:"../../../../3rdParty/lib/$(PlatformName)" /libpath:"../../../../3rdParty/lib" +# SUBTRACT LINK32 /incremental:no + +!ENDIF + +# Begin Target + +# Name "Example osgmanipulator - Win32 Release" +# Name "Example osgmanipulator - Win32 Debug" +# Begin Source File + +SOURCE=..\..\..\examples\osgmanipulator\osgmanipulator.cpp +# End Source File +# End Target +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=..\..\icons\osg_icon.rc +# End Source File +# End Group +# End Project diff --git a/VisualStudio/osgManipulator/osgManipulator.dsp b/VisualStudio/osgManipulator/osgManipulator.dsp new file mode 100644 index 000000000..0aa99f895 --- /dev/null +++ b/VisualStudio/osgManipulator/osgManipulator.dsp @@ -0,0 +1,329 @@ +# Microsoft Developer Studio Project File - Name="Core osgManipulator" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=Core osgManipulator - 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 "osgManipulator.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 "osgManipulator.mak" CFG="Core osgManipulator - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Core osgManipulator - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Core osgManipulator - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Core osgManipulator - Win32 Release Static" (based on "Win32 (x86) Static Library") +!MESSAGE "Core osgManipulator - Win32 Debug Static" (based on "Win32 (x86) Static 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 osgManipulator - 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 "../../bin/$(PlatformName)" +# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +F90=df.exe +# 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" /I "../../../OpenThreads/include" /I "../../../Producer/include" /I "../../../3rdParty/include" /D "NDEBUG" /D "_MBCS" /D "_USRDLL" /D "OSGMANIPULATOR_LIBRARY" /D "_WINDOWS" /D "WIN32" /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /Zm200 /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 /debug /machine:I386 /pdbtype:sept +# ADD LINK32 OpenThreadsWin32.lib opengl32.lib glu32.lib /nologo /dll /debug /machine:I386 /opt:ref /opt:icf /out:"$(OutDir)/osgManipulator.dll" /implib:"../../lib/$(PlatformName)/osgManipulator.lib" /libpath:"../../lib/$(PlatformName)" /libpath:"../../../OpenThreads/lib/$(PlatformName)" /libpath:"../../../Producer/lib/$(PlatformName)" /libpath:"../../../3rdParty/lib/$(PlatformName)" /libpath:"../../../3rdParty/lib" + +!ELSEIF "$(CFG)" == "Core osgManipulator - 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 "../../bin/$(PlatformName)" +# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +F90=df.exe +# 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 /GR /GX /Zi /Od /I "../../include" /I "../../../OpenThreads/include" /I "../../../Producer/include" /I "../../../3rdParty/include" /D "_DEBUG" /D "OSGMANIPULATOR_LIBRARY" /D "_WINDOWS" /D "WIN32" /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /GZ /Zm200 /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 OpenThreadsWin32d.lib opengl32.lib glu32.lib /nologo /dll /debug /machine:I386 /out:"$(OutDir)/osgManipulatord.dll" /pdbtype:sept /implib:"../../lib/$(PlatformName)/osgManipulatord.lib" /libpath:"../../lib/$(PlatformName)" /libpath:"../../../OpenThreads/lib/$(PlatformName)" /libpath:"../../../Producer/lib/$(PlatformName)" /libpath:"../../../3rdParty/lib/$(PlatformName)" /libpath:"../../../3rdParty/lib" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Core osgManipulator - Win32 Release Static" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "../../lib" +# PROP BASE Intermediate_Dir "Release_Static" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../lib/$(PlatformName)" +# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)_Static" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +F90=df.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "OSG_LIBRARY_STATIC" /D "OT_LIBRARY_STATIC" /D "PR_LIBRARY_STATIC" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "../../include" /I "../../../OpenThreads/include" /I "../../../Producer/include" /I "../../../3rdParty/include" /D "NDEBUG" /D "_MBCS" /D "OSG_LIBRARY_STATIC" /D "OT_LIBRARY_STATIC" /D "PR_LIBRARY_STATIC" /D "_WINDOWS" /D "WIN32" /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /Zm200 /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 +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nodefaultlib /nologo /out:"$(OutDir)/osgManipulator_s.lib" + +!ELSEIF "$(CFG)" == "Core osgManipulator - Win32 Debug Static" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "../../lib" +# PROP BASE Intermediate_Dir "Debug_Static" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../lib/$(PlatformName)" +# PROP Intermediate_Dir "$(PlatformName)/$(ConfigurationName)_Static" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +F90=df.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "OSG_LIBRARY_STATIC" /D "OT_LIBRARY_STATIC" /D "PR_LIBRARY_STATIC" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /vmg /GR /GX /Z7 /Od /I "../../include" /I "../../../OpenThreads/include" /I "../../../Producer/include" /I "../../../3rdParty/include" /D "_DEBUG" /D "OSG_LIBRARY_STATIC" /D "OT_LIBRARY_STATIC" /D "PR_LIBRARY_STATIC" /D "_WINDOWS" /D "WIN32" /D "_CRT_SECURE_NO_DEPRECATE" /YX /FD /GZ /Zm200 /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 +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nodefaultlib /nologo /out:"$(OutDir)/osgManipulatord_s.lib" +# SUBTRACT LIB32 /pdb:none +!ENDIF + +# Begin Target + +# Name "Core osgManipulator - Win32 Release" +# Name "Core osgManipulator - Win32 Debug" +# Name "Core osgManipulator - Win32 Release Static" +# Name "Core osgManipulator - Win32 Debug Static" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\src\osgManipulator\AntiSquish.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Command.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\CommandManager.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Constraint.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Dragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Projector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\RotateCylinderDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\RotateSphereDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Scale1DDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Scale2DDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\ScaleAxisDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Selection.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\TabBoxDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\TabPlaneDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\TabPlaneTrackballDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\TrackballDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Translate1DDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\Translate2DDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\TranslateAxisDragger.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\osgManipulator\TranslatePlaneDragger.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter ";h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\include\osgManipulator\AntiSquish +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Command +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\CommandManager +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Constraint +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Dragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Export +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Projector +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\RotateCylinderDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\RotateSphereDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Scale1DDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Scale2DDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\ScaleAxisDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Selection +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\TabBoxDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\TabPlaneDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\TabPlaneTrackballDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\TrackballDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Translate1DDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\Translate2DDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\TranslateAxisDragger +# End Source File +# Begin Source File + +SOURCE=..\..\include\osgManipulator\TranslatePlaneDragger +# 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 diff --git a/examples/osgmanipulator/GNUmakefile b/examples/osgmanipulator/GNUmakefile new file mode 100644 index 000000000..045b385b8 --- /dev/null +++ b/examples/osgmanipulator/GNUmakefile @@ -0,0 +1,18 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgmanipulator.cpp\ + +LIBS += -losgProducer -lProducer -losgManipulator -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + GNUmakefile.inst=GNUmakefile + +EXEC = osgmanipulator + +INC += $(X_INC) + +include $(TOPDIR)/Make/makerules + diff --git a/examples/osgmanipulator/GNUmakefile.inst b/examples/osgmanipulator/GNUmakefile.inst new file mode 100644 index 000000000..d6d08a661 --- /dev/null +++ b/examples/osgmanipulator/GNUmakefile.inst @@ -0,0 +1,13 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgmanipulator.cpp\ + +LIBS += -losgProducer -lProducer -losgManipulator -losgDB -losgText -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgmanipulator + +INC += $(X_INC) + +include $(TOPDIR)/Make/makerules diff --git a/examples/osgmanipulator/osgmanipulator.cpp b/examples/osgmanipulator/osgmanipulator.cpp new file mode 100644 index 000000000..9aa111e75 --- /dev/null +++ b/examples/osgmanipulator/osgmanipulator.cpp @@ -0,0 +1,394 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +osgManipulator::Dragger* createDragger(const std::string& name) +{ + osgManipulator::Dragger* dragger = 0; + if ("TabPlaneDragger" == name) + { + osgManipulator::TabPlaneDragger* d = new osgManipulator::TabPlaneDragger(); + d->setupDefaultGeometry(); + dragger = d; + } + else if ("TabPlaneTrackballDragger" == name) + { + osgManipulator::TabPlaneTrackballDragger* d = new osgManipulator::TabPlaneTrackballDragger(); + d->setupDefaultGeometry(); + dragger = d; + } + else if ("TrackballDragger" == name) + { + osgManipulator::TrackballDragger* d = new osgManipulator::TrackballDragger(); + d->setupDefaultGeometry(); + dragger = d; + } + else if ("Translate1DDragger" == name) + { + osgManipulator::Translate1DDragger* d = new osgManipulator::Translate1DDragger(); + d->setupDefaultGeometry(); + dragger = d; + } + else if ("Translate2DDragger" == name) + { + osgManipulator::Translate2DDragger* d = new osgManipulator::Translate2DDragger(); + d->setupDefaultGeometry(); + dragger = d; + } + else if ("TranslateAxisDragger" == name) + { + osgManipulator::TranslateAxisDragger* d = new osgManipulator::TranslateAxisDragger(); + d->setupDefaultGeometry(); + dragger = d; + } + else + { + osgManipulator::TabBoxDragger* d = new osgManipulator::TabBoxDragger(); + d->setupDefaultGeometry(); + dragger = d; + } + + return dragger; +} + +osg::Node* createHUD() +{ + osg::Geode* geode = new osg::Geode(); + + std::string timesFont("fonts/arial.ttf"); + + osg::StateSet* stateset = geode->getOrCreateStateSet(); + stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + osgText::Text* text = new osgText::Text; + geode->addDrawable( text ); + + osg::Vec3 position(50.0f,50.0f,0.0f); + text->setPosition(position); + text->setText("Use the Tab key to switch between the trackball and pick modes."); + text->setFont(timesFont); + + osg::Camera* camera = new osg::Camera; + + // set the projection matrix + camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); + + // set the view matrix + camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); + camera->setViewMatrix(osg::Matrix::identity()); + + // only clear the depth buffer + camera->setClearMask(GL_DEPTH_BUFFER_BIT); + + // draw subgraph after main camera view. + camera->setRenderOrder(osg::Camera::POST_RENDER); + + camera->addChild(geode); + + return camera; +} + + +bool computePixelCoords(osgProducer::Viewer* viewer,float x,float y,unsigned int cameraNum,float& pixel_x,float& pixel_y) +{ + Producer::KeyboardMouse* km = viewer->getKeyboardMouse(); + if (!km) return false; + + if (cameraNum>=viewer->getNumberOfCameras()) return false; + + Producer::Camera* camera=viewer->getCamera(cameraNum); + Producer::RenderSurface* rs = camera->getRenderSurface(); + + Producer::InputArea* inputArea = km->getInputArea(); + if( inputArea != NULL ) + { + // first locate which InputRectange is appropriate for specified RenderSurface. + unsigned int i; + for(i=0;igetNumRenderSurfaces();++i) + { + if (inputArea->getRenderSurface(i)==rs) break; + } + + // the RenderSurface isn't in the InputArea list.. therefore cannot make mouse coords to it. + if (i==inputArea->getNumRenderSurfaces()) return false; + + // we have a valid InputRectangle + Producer::RenderSurface::InputRectangle ir = inputArea->getRenderSurface(i)->getInputRectangle(); + + float rx = (x-ir.left())/ir.width(); + float ry = (y-ir.bottom())/ir.height(); + + int wx, wy; + unsigned int w, h; + rs->getWindowRectangle( wx, wy, w, h ); + + pixel_x = ((float)w)* rx; + pixel_y = ((float)h)* ry; + } + else + { + float rx = (x+1.0f)*0.5f; + float ry = (y+1.0f)*0.5f; + + int wx, wy; + unsigned int w, h; + rs->getWindowRectangle( wx, wy, w, h ); + + pixel_x = ((float)w)* rx; + pixel_y = ((float)h)* ry; + } + return true; +} + +osg::Node* addDraggerToScene(osg::Node* scene, osgManipulator::CommandManager* cmdMgr, const std::string& name) +{ + scene->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); + + osgManipulator::Selection* selection = new osgManipulator::Selection; + selection->addChild(scene); + + osgManipulator::Dragger* dragger = createDragger(name); + + osg::Group* root = new osg::Group; + root->addChild(dragger); + root->addChild(selection); + root->addChild(createHUD()); + + float scale = scene->getBound().radius() * 1.6; + dragger->setMatrix(osg::Matrix::scale(scale, scale, scale) * + osg::Matrix::translate(scene->getBound().center())); + cmdMgr->connect(*dragger, *selection); + + return root; +} + +class PickModeHandler : public osgGA::GUIEventHandler +{ + public: + enum Modes + { + VIEW = 0, + PICK + }; + + PickModeHandler(osgProducer::Viewer *viewer) : osgGA::GUIEventHandler(), + _viewer(viewer), _mode(VIEW), _activeDragger(0) + { + } + + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, + osg::Object*, osg::NodeVisitor*) + { + if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Tab && + ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN && + _activeDragger == 0) + { + _mode = ! _mode; + } + + if (VIEW == _mode) return false; + + for(unsigned int i=0;i<_viewer->getNumberOfCameras();++i) + { + if ((ea.getEventType() == osgGA::GUIEventAdapter::PUSH) && + _viewer->computeIntersections(ea.getX(), ea.getY(), i, hitList)) + { + float pixel_x,pixel_y; + if (computePixelCoords(_viewer,ea.getX(),ea.getY(),i,pixel_x,pixel_y)) + { + Producer::Camera* camera=_viewer->getCamera(i); + + osgProducer::OsgSceneHandler* sh = dynamic_cast(camera->getSceneHandler()); + osgUtil::SceneView* sv = sh ? sh->getSceneView() : 0; + if (! sv) continue; + + for (osg::NodePath::iterator itr = hitList.front().getNodePath().begin(); + itr != hitList.front().getNodePath().end(); + ++itr) + { + osgManipulator::Dragger* dragger = dynamic_cast(*itr); + if (dragger) + { + dragger->handle(int(pixel_x+0.5), int(pixel_y+0.5), *sv, + hitList, hitList.begin(), + ea, aa); + _activeDragger = dragger; + break; + } + } + } + } + + switch (ea.getEventType()) + { + case osgGA::GUIEventAdapter::DRAG: + case osgGA::GUIEventAdapter::RELEASE: + if (_activeDragger) + { + float pixel_x,pixel_y; + if (computePixelCoords(_viewer,ea.getX(),ea.getY(),i,pixel_x,pixel_y)) + { + Producer::Camera* camera=_viewer->getCamera(i); + + osgProducer::OsgSceneHandler* sh = dynamic_cast(camera->getSceneHandler()); + osgUtil::SceneView* sv = sh ? sh->getSceneView() : 0; + if (_activeDragger && sv) + _activeDragger->handle(int(pixel_x+0.5), int(pixel_y+0.5), *sv, + hitList, hitList.begin(), + ea, aa); + } + } + break; + + default: + break; + } + if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) + { + _activeDragger = 0; + hitList.clear(); + } + } + return true; + } + + private: + osgProducer::Viewer* _viewer; + unsigned int _mode; + osgManipulator::Dragger* _activeDragger; + osgUtil::IntersectVisitor::HitList hitList; +}; + +int main( int argc, char **argv ) +{ + + // use an ArgumentParser object to manage the program arguments. + osg::ArgumentParser arguments(&argc,argv); + + // set up the usage document, in case we need to print out how to use this program. + arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName()); + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models."); + arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); + arguments.getApplicationUsage()->addCommandLineOption("--image ","Load an image and render it on a quad"); + arguments.getApplicationUsage()->addCommandLineOption("--dem ","Load an image/DEM and render it on a HeightField"); + arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters"); + arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available"); + arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available"); + arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings."); + + arguments.getApplicationUsage()->addCommandLineOption("--dragger ","Use the specified dragger for manipulation"); + + + // construct the viewer. + osgProducer::Viewer viewer(arguments); + + // set up the value with sensible default event handlers. + viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); + + // get details on keyboard and mouse bindings used by the viewer. + viewer.getUsage(*arguments.getApplicationUsage()); + + // if user request help write it out to cout. + bool helpAll = arguments.read("--help-all"); + unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) | + ((helpAll || arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) | + ((helpAll || arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 ); + if (helpType) + { + arguments.getApplicationUsage()->write(std::cout, helpType); + return 1; + } + + // report any errors if they have occurred when parsing the program arguments. + if (arguments.errors()) + { + arguments.writeErrorMessages(std::cout); + return 1; + } + + if (arguments.argc()<=1) + { + arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); + return 1; + } + + std::string dragger_name = "TabBoxDragger"; + arguments.read("--dragger", dragger_name); + + osg::Timer_t start_tick = osg::Timer::instance()->tick(); + + // read the scene from the list of file specified command line args. + osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); + + // if no model has been successfully loaded report failure. + if (!loadedModel) + { + std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl; + return 1; + } + + // any option left unread are converted into errors to write out later. + arguments.reportRemainingOptionsAsUnrecognized(); + + // report any errors if they have occurred when parsing the program arguments. + if (arguments.errors()) + { + arguments.writeErrorMessages(std::cout); + } + + osg::Timer_t end_tick = osg::Timer::instance()->tick(); + + std::cout << "Time to load = "<delta_s(start_tick,end_tick)< cmdMgr = new osgManipulator::CommandManager; + + // pass the loaded scene graph to the viewer. + viewer.setSceneData(addDraggerToScene(loadedModel.get(), cmdMgr.get(), dragger_name)); + + viewer.getEventHandlerList().push_front(new PickModeHandler(&viewer)); + + // create the windows and run the threads. + viewer.realize(); + + while( !viewer.done() ) + { + // wait for all cull and draw threads to complete. + viewer.sync(); + + // update the scene by traversing it with the the update visitor which will + // call all node update callbacks and animations. + viewer.update(); + + // fire off the cull and draw traversals of the scene. + viewer.frame(); + + } + + // wait for all cull and draw threads to complete. + viewer.sync(); + + // run a clean up frame to delete all OpenGL objects. + viewer.cleanup_frame(); + + // wait for all the clean up frame to complete. + viewer.sync(); + + return 0; +} + diff --git a/include/osgManipulator/AntiSquish b/include/osgManipulator/AntiSquish new file mode 100644 index 000000000..350279549 --- /dev/null +++ b/include/osgManipulator/AntiSquish @@ -0,0 +1,84 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgDragger - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef _OSG_ANTISQUISH_ +#define _OSG_ANTISQUISH_ 1 + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace osgManipulator { + +/** + * Class that performs the Anti Squish by making the scaling uniform along all axes. + */ +class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform +{ + public : + AntiSquish(); + AntiSquish(const osg::Vec3& pivot); + AntiSquish(const osg::Vec3& pivot, const osg::Vec3& position); + AntiSquish(const AntiSquish& pat, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + virtual osg::Object* cloneType() const { return new AntiSquish(); } + + virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new AntiSquish (*this,copyop); } + + virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } + + void setPivot(const osg::Vec3& pvt) + { + _pivot = pvt; + _usePivot = true; + _dirty = true; + } + + const osg::Vec3& getPivot() { return _pivot; } + + void setPosition(const osg::Vec3& pos) + { + _position = pos; + _usePosition = true; + _dirty = true; + } + + const osg::Vec3& getPosition() { return _position; } + + virtual ~AntiSquish(); + + osg::Matrix computeUnSquishedMatrix(const osg::Matrix&, bool& flag); + + protected: + + osg::NodeCallback* _asqCallback; + + osg::Vec3 _pivot; + bool _usePivot; + + osg::Vec3 _position; + bool _usePosition; + + bool _dirty; + osg::Matrix _cachedLocalToWorld; +}; + +} +#endif diff --git a/include/osgManipulator/Command b/include/osgManipulator/Command new file mode 100644 index 000000000..90a717b08 --- /dev/null +++ b/include/osgManipulator/Command @@ -0,0 +1,352 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_COMMAND +#define OSGMANIPULATOR_COMMAND 1 + +#include +#include + +#include +#include +#include + +#include + +namespace osgManipulator { + +class Constraint; + +/** Base class for motion commands that are generated by draggers. */ +class OSGMANIPULATOR_EXPORT MotionCommand : public osg::Referenced +{ + public: + + /** + * Motion command are based on click-drag-release actions. So each + * command needs to indicate which stage of the motion the command + * represents. + */ + enum Stage + { + NONE, + /** Click or pick start. */ + START, + /** Drag or pick move. */ + MOVE, + /** Release or pick finish. */ + FINISH + }; + + MotionCommand(); + + /** Execute the command. */ + virtual bool execute() = 0; + + /** Undo the command. The inverse of this command is executed. */ + virtual bool unexecute() = 0; + + /** Apply a constraint to the command. */ + virtual void applyConstraint(const Constraint*) = 0; + + /** + * Add Selection (receiver) to the command. The command will be + * executed on all the selections. + */ + void addSelection(Selection*); + + /** Remove Selection (receiver) from the command. */ + void removeSelection(Selection*); + + /** + * Gets the matrix for transforming the Selection. This matrix is in the + * command's coordinate systems. + */ + virtual osg::Matrix getMotionMatrix() const = 0; + + /** + * Sets the matrix for transforming the command's local coordinate + * system to the world/object coordinate system. + */ + void setLocalToWorldAndWorldToLocal(const osg::Matrix& localToWorld, const osg::Matrix& worldToLocal) + { + _localToWorld = localToWorld; + _worldToLocal = worldToLocal; + } + + /** + * Gets the matrix for transforming the command's local coordinate + * system to the world/object coordinate system. + */ + inline const osg::Matrix& getLocalToWorld() const { return _localToWorld; } + + /** + * Gets the matrix for transforming the command's world/object + * coordinate system to the command's local coordinate system. + */ + inline const osg::Matrix& getWorldToLocal() const { return _worldToLocal; } + + void setStage(const Stage s) { _stage = s; } + Stage getStage() const { return _stage; } + + protected: + + virtual ~MotionCommand(); + typedef std::vector< osg::ref_ptr > SelectionList; + + SelectionList& getSelectionList() { return _selectionList; } + const SelectionList& getSelectionList() const { return _selectionList; } + + private: + osg::Matrix _localToWorld; + osg::Matrix _worldToLocal; + + Stage _stage; + + SelectionList _selectionList; +}; + + +/** + * Command for translating in a line. + */ +class OSGMANIPULATOR_EXPORT TranslateInLineCommand : public MotionCommand +{ + public: + + TranslateInLineCommand(); + + TranslateInLineCommand(const osg::Vec3& s, const osg::Vec3& e); + + virtual bool execute(); + virtual bool unexecute(); + virtual void applyConstraint(const Constraint*); + + inline void setLine(const osg::Vec3& s, const osg::Vec3& e) { _line->start() = s; _line->end() = e; } + inline const osg::Vec3& getLineStart() const { return _line->start(); } + inline const osg::Vec3& getLineEnd() const { return _line->end(); } + + inline void setTranslation(const osg::Vec3& t) { _translation = t; } + inline const osg::Vec3& getTranslation() const { return _translation; } + + virtual osg::Matrix getMotionMatrix() const + { + return osg::Matrix::translate(_translation); + } + + protected: + + virtual ~TranslateInLineCommand(); + + private: + osg::ref_ptr _line; + osg::Vec3 _translation; +}; + +/** + * Command for translating in a plane. + */ +class OSGMANIPULATOR_EXPORT TranslateInPlaneCommand : public MotionCommand +{ + public: + + TranslateInPlaneCommand(); + + TranslateInPlaneCommand(const osg::Plane& plane); + + virtual bool execute(); + virtual bool unexecute(); + virtual void applyConstraint(const Constraint*); + + inline void setPlane(const osg::Plane& plane) { _plane = plane; } + inline const osg::Plane& getPlane() const { return _plane; } + + inline void setTranslation(const osg::Vec3& t) { _translation = t; } + inline const osg::Vec3& getTranslation() const { return _translation; } + + /** ReferencePoint is used only for snapping. */ + inline void setReferencePoint(const osg::Vec3& rp) { _referencePoint = rp; } + inline const osg::Vec3& getReferencePoint() const { return _referencePoint; } + + virtual osg::Matrix getMotionMatrix() const + { + return osg::Matrix::translate(_translation); + } + + protected: + + virtual ~TranslateInPlaneCommand(); + + private: + osg::Plane _plane; + osg::Vec3 _translation; + osg::Vec3 _referencePoint; +}; + +/** + * Command for 1D scaling. + */ +class OSGMANIPULATOR_EXPORT Scale1DCommand : public MotionCommand +{ + public: + + Scale1DCommand(); + + virtual bool execute(); + virtual bool unexecute(); + virtual void applyConstraint(const Constraint*); + + inline void setScale(float s) { _scale = s; } + inline float getScale() const { return _scale; } + + inline void setScaleCenter(float center) { _scaleCenter = center; } + inline float getScaleCenter() const { return _scaleCenter; } + + /** ReferencePoint is used only for snapping. */ + inline void setReferencePoint(float rp) { _referencePoint = rp; } + inline float getReferencePoint() const { return _referencePoint; } + + inline void setMinScale(float min) { _minScale = min; } + inline float getMinScale() const { return _minScale; } + + virtual osg::Matrix getMotionMatrix() const + { + return (osg::Matrix::translate(-_scaleCenter,0.0,0.0) + * osg::Matrix::scale(_scale,1.0,1.0) + * osg::Matrix::translate(_scaleCenter,0.0,0.0)); + } + + protected: + + virtual ~Scale1DCommand(); + + private: + float _scale; + float _scaleCenter; + float _referencePoint; + float _minScale; +}; + +/** + * Command for 2D scaling. + */ +class OSGMANIPULATOR_EXPORT Scale2DCommand : public MotionCommand +{ + public: + + Scale2DCommand(); + + virtual bool execute(); + virtual bool unexecute(); + virtual void applyConstraint(const Constraint*); + + inline void setScale(const osg::Vec2& s) { _scale = s; } + inline const osg::Vec2& getScale() const { return _scale; } + + inline void setScaleCenter(const osg::Vec2& center) { _scaleCenter = center; } + inline const osg::Vec2& getScaleCenter() const { return _scaleCenter; } + + /** ReferencePoint is used only for snapping. */ + inline void setReferencePoint(const osg::Vec2& rp) { _referencePoint = rp; } + inline const osg::Vec2& getReferencePoint() const { return _referencePoint; } + + inline void setMinScale(const osg::Vec2& min) { _minScale = min; } + inline const osg::Vec2& getMinScale() const { return _minScale; } + + virtual osg::Matrix getMotionMatrix() const + { + return (osg::Matrix::translate(-_scaleCenter[0],0.0,-_scaleCenter[1]) + * osg::Matrix::scale(_scale[0],1.0,_scale[1]) + * osg::Matrix::translate(_scaleCenter[0],0.0,_scaleCenter[1])); + } + + protected: + + virtual ~Scale2DCommand(); + + private: + osg::Vec2 _scale; + osg::Vec2 _scaleCenter; + osg::Vec2 _referencePoint; + osg::Vec2 _minScale; +}; + +/** + * Command for uniform 3D scaling. + */ +class OSGMANIPULATOR_EXPORT ScaleUniformCommand : public MotionCommand +{ + public: + + ScaleUniformCommand(); + + virtual bool execute(); + virtual bool unexecute(); + virtual void applyConstraint(const Constraint*); + + inline void setScale(float s) { _scale = s; } + inline float getScale() const { return _scale; } + + inline void setScaleCenter(const osg::Vec3& center) { _scaleCenter = center; } + inline const osg::Vec3& getScaleCenter() const { return _scaleCenter; } + + virtual osg::Matrix getMotionMatrix() const + { + return (osg::Matrix::translate(-_scaleCenter) + * osg::Matrix::scale(_scale,_scale,_scale) + * osg::Matrix::translate(_scaleCenter)); + } + + protected: + + virtual ~ScaleUniformCommand(); + + private: + float _scale; + osg::Vec3 _scaleCenter; +}; + +/** + * Command for rotation in 3D. + */ +class OSGMANIPULATOR_EXPORT Rotate3DCommand : public MotionCommand +{ + public: + + Rotate3DCommand(); + + virtual bool execute(); + virtual bool unexecute(); + virtual void applyConstraint(const Constraint*); + + inline void setRotation(const osg::Quat& rotation) { _rotation = rotation; } + inline const osg::Quat& getRotation() const { return _rotation; } + + virtual osg::Matrix getMotionMatrix() const + { + return osg::Matrix::rotate(_rotation); + } + + protected: + + virtual ~Rotate3DCommand(); + + private: + osg::Quat _rotation; +}; + + +} + +#endif diff --git a/include/osgManipulator/CommandManager b/include/osgManipulator/CommandManager new file mode 100644 index 000000000..de7c2b756 --- /dev/null +++ b/include/osgManipulator/CommandManager @@ -0,0 +1,64 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_COMMANDMANAGER +#define OSGMANIPULATOR_COMMANDMANAGER 1 + +#include +#include +#include + +namespace osgManipulator { + +/** + * Command manager receives commands from draggers and dispatches them to selections. + */ +class OSGMANIPULATOR_EXPORT CommandManager : public osg::Referenced +{ + public: + + CommandManager(); + + /** + * Connect a dragger to a selection. The selection will begin listening + * to commands generated by the dragger. This can be called multiple + * times to connect many selections to a dragger. + */ + virtual bool connect(Dragger& dragger, Selection& selection); + + virtual bool connect(Dragger& dragger, Constraint& constrain); + + /** Disconnect the selections from a dragger. */ + virtual bool disconnect(Dragger& dragger); + + /** Dispatches a command. Usually called from a dragger. */ + virtual void dispatch(MotionCommand& command); + + /** Add all selections connected to the dragger to the command. */ + void addSelectionsToCommand(MotionCommand& command, Dragger& dragger); + + protected: + + virtual ~CommandManager(); + + typedef std::multimap< osg::ref_ptr, osg::ref_ptr > DraggerSelectionMap; + DraggerSelectionMap _draggerSelectionMap; + + typedef std::multimap< osg::ref_ptr, osg::ref_ptr > DraggerConstraintMap; + DraggerConstraintMap _draggerConstraintMap; +}; + +} + +#endif diff --git a/include/osgManipulator/Constraint b/include/osgManipulator/Constraint new file mode 100644 index 000000000..0c66413bb --- /dev/null +++ b/include/osgManipulator/Constraint @@ -0,0 +1,95 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_CONSTRAINT +#define OSGMANIPULATOR_CONSTRAINT 1 + +#include + +#include +#include + +namespace osgManipulator { + +class MotionCommand; +class TranslateInLineCommand; +class TranslateInPlaneCommand; +class Scale1DCommand; +class Scale2DCommand; +class ScaleUniformCommand; + +class OSGMANIPULATOR_EXPORT Constraint : public osg::Referenced +{ + public: + + virtual bool constrain(MotionCommand&) const { return false; } + virtual bool constrain(TranslateInLineCommand& command) const { return constrain((MotionCommand&)command); } + virtual bool constrain(TranslateInPlaneCommand& command) const { return constrain((MotionCommand&)command); } + virtual bool constrain(Scale1DCommand& command) const { return constrain((MotionCommand&)command); } + virtual bool constrain(Scale2DCommand& command) const { return constrain((MotionCommand&)command); } + virtual bool constrain(ScaleUniformCommand& command) const { return constrain((MotionCommand&)command); } + + protected: + + Constraint(osg::Node& refNode) : _refNode(&refNode) {} + virtual ~Constraint() {} + + osg::Node& getReferenceNode() { return *_refNode; } + const osg::Node& getReferenceNode() const { return *_refNode; } + + const osg::Matrix& getLocalToWorld() const { return _localToWorld; } + const osg::Matrix& getWorldToLocal() const { return _worldToLocal; } + + void computeLocalToWorldAndWorldToLocal() const; + + private: + + osg::ref_ptr _refNode; + mutable osg::Matrix _localToWorld; + mutable osg::Matrix _worldToLocal; +}; + +/** + * Constraint to snap motion commands to a sugar cube grid. + */ +class OSGMANIPULATOR_EXPORT GridConstraint : public Constraint +{ + public: + + GridConstraint(osg::Node& refNode, const osg::Vec3d& origin, const osg::Vec3d& spacing); + + void setOrigin(const osg::Vec3d origin) { _origin = origin; } + void setSpacing(const osg::Vec3d spacing) { _spacing = spacing; } + + virtual bool constrain(TranslateInLineCommand& command) const; + virtual bool constrain(TranslateInPlaneCommand& command) const; + virtual bool constrain(Scale1DCommand& command) const; + virtual bool constrain(Scale2DCommand& command) const; + virtual bool constrain(ScaleUniformCommand& command) const; + + protected: + + virtual ~GridConstraint() {} + + private: + + osg::Vec3d _origin; + osg::Vec3d _spacing; + mutable osg::Matrix _startMatrix; + mutable osg::Matrix _matrix; +}; + +} + +#endif diff --git a/include/osgManipulator/Dragger b/include/osgManipulator/Dragger new file mode 100644 index 000000000..2af569cd6 --- /dev/null +++ b/include/osgManipulator/Dragger @@ -0,0 +1,134 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_DRAGGER +#define OSGMANIPULATOR_DRAGGER 1 + +#include + +#include +#include +#include +#include +#include + +namespace osgManipulator +{ + +class CommandManager; +class CompositeDragger; + +/** + * Base class for draggers. Concrete draggers implement the pick event handler + * and generate motion commands (translate, rotate, ...) and sends these + * command to the CommandManager. The CommandManager dispatches the commands + * to all the Selections that are connected to the Dragger that generates the + * commands. + */ +class OSGMANIPULATOR_EXPORT Dragger : public Selection +{ + public: + + /** Set/Get the CommandManager. Draggers use CommandManager to dispatch commands. */ + virtual void setCommandManager(CommandManager* cm) { _commandManager = cm; } + CommandManager* getCommandManager() { return _commandManager; } + const CommandManager* getCommandManager() const { return _commandManager; } + + /** + * Set/Get parent dragger. For simple draggers parent points to itself. + * For composite draggers parent points to the parent dragger that uses + * this dragger. + */ + virtual void setParentDragger(Dragger* parent) { _parentDragger = parent; } + Dragger* getParentDragger() { return _parentDragger; } + const Dragger* getParentDragger() const { return _parentDragger; } + + /** Returns 0 if this Dragger is not a CompositeDragger. */ + virtual const CompositeDragger* getComposite() const { return 0; } + + /** Returns 0 if this Dragger is not a CompositeDragger. */ + virtual CompositeDragger* getComposite() { return 0; } + + virtual bool handle(int, int, const osgUtil::SceneView&, + const osgUtil::IntersectVisitor::HitList&, + const osgUtil::IntersectVisitor::HitList::iterator&, + const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&) { return false; } + + protected: + + Dragger(); + virtual ~Dragger(); + + CommandManager* _commandManager; + + Dragger* _parentDragger; + +}; + + +/** + * CompositeDragger allows to create complex draggers that are composed of a + * hierarchy of Draggers. + */ +class OSGMANIPULATOR_EXPORT CompositeDragger : public Dragger +{ + public: + + typedef std::vector< osg::ref_ptr > DraggerList; + + virtual const CompositeDragger* getComposite() const { return this; } + virtual CompositeDragger* getComposite() { return this; } + + virtual void setCommandManager(CommandManager* cm); + + virtual void setParentDragger(Dragger* parent); + + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa); + + // Composite-specific methods below + virtual bool addDragger(Dragger* dragger); + virtual bool removeDragger(Dragger* dragger); + unsigned int getNumDraggers() const { return _draggerList.size(); } + Dragger* getDragger(unsigned int i) { return _draggerList[i].get(); } + const Dragger* getDragger(unsigned int i) const { return _draggerList[i].get(); } + bool containsDragger(const Dragger* dragger) const; + DraggerList::iterator findDragger(const Dragger* dragger); + + protected: + + CompositeDragger() {} + virtual ~CompositeDragger() {} + + DraggerList _draggerList; +}; + +/** + * Culls the drawable all the time. Used by draggers to have invisible geometry + * around lines and points so that they can be picked. For example, a dragger + * could have a line with an invisible cylinder around it to enable picking on + * that line. + */ +void setDrawableToAlwaysCull(osg::Drawable& drawable); + +/** + * Convenience function for setting the material color on a node. + */ +void setMaterialColor(const osg::Vec4& color, osg::Node& node); + +} + +#endif diff --git a/include/osgManipulator/Export b/include/osgManipulator/Export new file mode 100644 index 000000000..1ffee7632 --- /dev/null +++ b/include/osgManipulator/Export @@ -0,0 +1,28 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_EXPORT_ +#define OSGMANIPULATOR_EXPORT_ 1 + +#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__) + # ifdef OSGMANIPULATOR_LIBRARY + # define OSGMANIPULATOR_EXPORT __declspec(dllexport) + # else + # define OSGMANIPULATOR_EXPORT __declspec(dllimport) + # endif /* OSGMANIPULATOR_LIBRARY */ +#else + # define OSGMANIPULATOR_EXPORT +#endif + +#endif diff --git a/include/osgManipulator/Projector b/include/osgManipulator/Projector new file mode 100644 index 000000000..cd2b67b6a --- /dev/null +++ b/include/osgManipulator/Projector @@ -0,0 +1,298 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_PROJECTOR +#define OSGMANIPULATOR_PROJECTOR 1 + +#include + +#include +#include + +namespace osgManipulator { + +/** + * Base class for Projectors. Projectors maps 2D cursor motions to 3D motions. + */ +class OSGMANIPULATOR_EXPORT Projector : public osg::Referenced +{ + public: + + Projector(); + + /** + * Calculates the object/world coordinates (projectedPoint) of a window + * coordinate (pointToProject) when projected onto some shape or + * geometry (implemented in derived classes). SceneView in used for i + * projecting window coordinates into object coordinates and vice versa. + * Returns true on successful projection. + */ + virtual bool project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const = 0; + + /** + * Sets the matrix for transforming the projector's local coordinate + * system to the world/object coordinate system. + */ + void setLocalToWorld(const osg::Matrix& localToWorld) + { + _localToWorld = localToWorld; + _worldToLocalDirty = true; + } + + /** + * Gets the matrix for transforming the projector's local coordinate + * system to the world/object coordinate system. + */ + inline const osg::Matrix& getLocalToWorld() const { return _localToWorld; } + + /** + * Gets the matrix for transforming the world/object coordinate + * system to the command's local coordinate system. + */ + inline const osg::Matrix& getWorldToLocal() const + { + if (_worldToLocalDirty) + { + _worldToLocal.invert(_localToWorld); + _worldToLocalDirty = false; + } + return _worldToLocal; + } + + protected: + + virtual ~Projector(); + + osg::Matrix _localToWorld; + mutable osg::Matrix _worldToLocal; + + mutable bool _worldToLocalDirty; +}; + + +/** + * LineProjector projects points onto the closest point on the given line. + */ +class OSGMANIPULATOR_EXPORT LineProjector : public Projector +{ + public: + + LineProjector(); + + LineProjector(const osg::Vec3& s, const osg::Vec3& e); + + inline void setLine(const osg::Vec3& s, const osg::Vec3& e) { _line->start() = s; _line->end() = e; } + inline const osg::Vec3& getLineStart() const { return _line->start(); } + inline osg::Vec3& getLineStart() { return _line->start(); } + inline const osg::Vec3& getLineEnd() const { return _line->end(); } + inline osg::Vec3& getLineEnd() { return _line->end(); } + + /** + * Calculates the object coordinates (projectedPoint) of a window + * coordinate (pointToProject) when projected onto the given line. + * Returns true on successful projection. + */ + virtual bool project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const; + + protected: + + virtual ~LineProjector(); + + osg::ref_ptr _line; +}; + +/** + * PlaneProjector projects points onto the given line. + */ +class OSGMANIPULATOR_EXPORT PlaneProjector : public Projector +{ + public: + + PlaneProjector(); + + PlaneProjector(const osg::Plane& plane); + + inline void setPlane(const osg::Plane& plane) { _plane = plane; } + inline const osg::Plane& getPlane() const { return _plane; } + + /** + * Calculates the object coordinates (projectedPoint) of a window + * coordinate (pointToProject) when projected onto the given plane. + * Returns true on successful projection. + */ + virtual bool project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const; + + protected: + + virtual ~PlaneProjector(); + + osg::Plane _plane; +}; + +/** + * SphereProjector projects points onto the given sphere. + */ +class OSGMANIPULATOR_EXPORT SphereProjector : public Projector +{ + public: + + SphereProjector(); + + SphereProjector(osg::Sphere& sphere); + + inline void setSphere(osg::Sphere& sphere) { _sphere = &sphere; } + inline const osg::Sphere& getSphere() const { return *_sphere; } + + /** + * Calculates the object coordinates (projectedPoint) of a window + * coordinate (pointToProject) when projected onto the given sphere. + * Returns true on successful projection. + */ + virtual bool project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const; + + /** + * Returns true is the point is in front of the cylinder given the eye + * direction. + */ + bool isPointInFront(const osg::Vec3& point, const osgUtil::SceneView& sv, const osg::Matrix& localToWorld) const; + + void setFront(bool front) { _front = front; } + + protected: + + virtual ~SphereProjector(); + + osg::ref_ptr _sphere; + bool _front; +}; + +/** + * SpherePlaneProjector projects points onto a sphere, failing which it project + * onto a plane oriented to the viewing direction. + */ +class OSGMANIPULATOR_EXPORT SpherePlaneProjector : public SphereProjector +{ + public: + + SpherePlaneProjector(); + + SpherePlaneProjector(osg::Sphere& sphere); + + /** + * Calculates the object coordinates (projectedPoint) of a window + * coordinate (pointToProject) when projected onto the given sphere. + * Returns true on successful projection. + */ + virtual bool project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const; + + /** + * Returns true if the previous projection was on the sphere and false + * if the projection was on the plane. + */ + bool isProjectionOnSphere() const { return _onSphere; } + + osg::Quat getRotation(const osg::Vec3& p1, bool p1OnSphere, + const osg::Vec3& p2, bool p2OnSphere, + float radialFactor = 0.0f) const; + + protected: + + virtual ~SpherePlaneProjector(); + + mutable osg::Plane _plane; + mutable bool _onSphere; +}; + +/** + * CylinderProjector projects points onto the given cylinder. + */ +class OSGMANIPULATOR_EXPORT CylinderProjector : public Projector +{ + public: + + CylinderProjector(); + + CylinderProjector(osg::Cylinder& cylinder); + + inline void setCylinder(osg::Cylinder& cylinder) + { + _cylinder = &cylinder; + _cylinderAxis = osg::Vec3(0.0,0.0,1.0) * osg::Matrix(cylinder.getRotation()); + _cylinderAxis.normalize(); + } + inline const osg::Cylinder& getCylinder() const { return *_cylinder; } + + /** + * Calculates the object coordinates (projectedPoint) of a window + * coordinate (pointToProject) when projected onto the given plane. + * Returns true on successful projection. + */ + virtual bool project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const; + + + /** + * Returns true is the point is in front of the cylinder given the eye + * direction. + */ + bool isPointInFront(const osg::Vec3& point, const osgUtil::SceneView& sv, const osg::Matrix& localToWorld) const; + + void setFront(bool front) { _front = front; } + + protected: + + virtual ~CylinderProjector(); + + osg::ref_ptr _cylinder; + osg::Vec3 _cylinderAxis; + bool _front; +}; + +/** + * CylinderPlaneProjector projects points onto the given cylinder. + */ +class OSGMANIPULATOR_EXPORT CylinderPlaneProjector : public CylinderProjector +{ + public: + + CylinderPlaneProjector(); + + CylinderPlaneProjector(osg::Cylinder& cylinder); + + /** + * Calculates the object coordinates (projectedPoint) of a window + * coordinate (pointToProject) when projected onto the given plane. + * Returns true on successful projection. + */ + virtual bool project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const; + + /** + * Returns true if the previous projection was on the cylinder and + * false if the projection was on the plane. + */ + bool isProjectionOnCylinder() const { return _onCylinder; } + + osg::Quat getRotation(const osg::Vec3& p1, bool p1OnCyl, const osg::Vec3& p2, bool p2OnCyl) const; + + protected: + + virtual ~CylinderPlaneProjector(); + + mutable osg::Plane _plane; + mutable bool _onCylinder; + mutable osg::Vec3 _planeLineStart, _planeLineEnd; +}; + +} + +#endif diff --git a/include/osgManipulator/RotateCylinderDragger b/include/osgManipulator/RotateCylinderDragger new file mode 100644 index 000000000..1a412ac0a --- /dev/null +++ b/include/osgManipulator/RotateCylinderDragger @@ -0,0 +1,74 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_ROTATECYLINDERDRAGGER +#define OSGMANIPULATOR_ROTATECYLINDERDRAGGER 1 + +#include +#include + +namespace osgManipulator { + +/** + * Dragger for performing 3D rotation on a cylinder. + */ +class OSGMANIPULATOR_EXPORT RotateCylinderDragger : public Dragger +{ + public: + + RotateCylinderDragger(); + + /** + * Handle pick events on dragger and generate TranslateInLine commands. + */ + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + /** Set/Get color for dragger. */ + inline void setColor(const osg::Vec4& color) { _color = color; setMaterialColor(_color,*this); } + inline const osg::Vec4 getColor() const { return _color; } + + /** + * Set/Get pick color for dragger. Pick color is color of the dragger + * when picked. It gives a visual feedback to show that the dragger has + * been picked. + */ + inline void setPickColor(const osg::Vec4& color) { _pickColor = color; } + inline const osg::Vec4 getPickColor() const { return _pickColor; } + + + protected: + + virtual ~RotateCylinderDragger(); + + osg::ref_ptr _projector; + + osg::Vec3 _prevWorldProjPt; + bool _prevPtOnCylinder; + osg::Matrix _startLocalToWorld, _startWorldToLocal; + osg::Quat _prevRotation; + + osg::Vec4 _color; + osg::Vec4 _pickColor; +}; + + +} + +#endif diff --git a/include/osgManipulator/RotateSphereDragger b/include/osgManipulator/RotateSphereDragger new file mode 100644 index 000000000..199d93730 --- /dev/null +++ b/include/osgManipulator/RotateSphereDragger @@ -0,0 +1,73 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_ROTATESPHEREDRAGGER +#define OSGMANIPULATOR_ROTATESPHEREDRAGGER 1 + +#include +#include + +namespace osgManipulator { + +/** + * Dragger for performing 3D rotation on a sphere. + */ +class OSGMANIPULATOR_EXPORT RotateSphereDragger : public Dragger +{ + public: + + RotateSphereDragger(); + + /** + * Handle pick events on dragger and generate TranslateInLine commands. + */ + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + /** Set/Get color for dragger. */ + inline void setColor(const osg::Vec4& color) { _color = color; setMaterialColor(_color,*this); } + inline const osg::Vec4 getColor() const { return _color; } + + /** + * Set/Get pick color for dragger. Pick color is color of the dragger + * when picked. It gives a visual feedback to show that the dragger has + * been picked. + */ + inline void setPickColor(const osg::Vec4& color) { _pickColor = color; } + inline const osg::Vec4 getPickColor() const { return _pickColor; } + + protected: + + virtual ~RotateSphereDragger(); + + osg::ref_ptr _projector; + + osg::Vec3 _prevWorldProjPt; + bool _prevPtOnSphere; + osg::Matrix _startLocalToWorld, _startWorldToLocal; + osg::Quat _prevRotation; + + osg::Vec4 _color; + osg::Vec4 _pickColor; +}; + + +} + +#endif diff --git a/include/osgManipulator/Scale1DDragger b/include/osgManipulator/Scale1DDragger new file mode 100644 index 000000000..6cb403dc9 --- /dev/null +++ b/include/osgManipulator/Scale1DDragger @@ -0,0 +1,98 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_SCALE1DDRAGGER +#define OSGMANIPULATOR_SCALE1DDRAGGER 1 + +#include +#include + +namespace osgManipulator { + +/** + * Dragger for performing 1D scaling. + */ +class OSGMANIPULATOR_EXPORT Scale1DDragger : public Dragger +{ + public: + + enum ScaleMode + { + SCALE_WITH_ORIGIN_AS_PIVOT = 0, + SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT + }; + + Scale1DDragger(ScaleMode scaleMode=SCALE_WITH_ORIGIN_AS_PIVOT); + + /** + * Handle pick events on dragger and generate TranslateInLine commands. + */ + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + /** Set/Get min scale for dragger. */ + inline void setMinScale(float min) { _minScale = min; } + inline float getMinScale() const { return _minScale; } + + /** Set/Get color for dragger. */ + inline void setColor(const osg::Vec4& color) { _color = color; setMaterialColor(_color,*this); } + inline const osg::Vec4 getColor() const { return _color; } + + /** + * Set/Get pick color for dragger. Pick color is color of the dragger + * when picked. It gives a visual feedback to show that the dragger has + * been picked. + */ + inline void setPickColor(const osg::Vec4& color) { _pickColor = color; } + inline const osg::Vec4 getPickColor() const { return _pickColor; } + + /** Set/Get left and right handle nodes for dragger. */ + inline void setLeftHandleNode (osg::Node& node) { _leftHandleNode = &node; } + inline void setRightHandleNode(osg::Node& node) { _rightHandleNode = &node; } + inline osg::Node* getLeftHandleNode() { return _leftHandleNode.get(); } + inline osg::Node* getRightHandleNode() { return _rightHandleNode.get(); } + + /** Set left/right handle position. */ + inline void setLeftHandlePosition(float pos) { _projector->getLineStart() = osg::Vec3(pos,0.0,0.0); } + inline float getLeftHandlePosition() const { return _projector->getLineStart()[0]; } + inline void setRightHandlePosition(float pos) { _projector->getLineEnd() = osg::Vec3(pos,0.0,0.0); } + inline float getRightHandlePosition() { return _projector->getLineEnd()[0]; } + + protected: + + virtual ~Scale1DDragger(); + + osg::ref_ptr< LineProjector > _projector; + osg::Vec3 _startProjectedPoint; + float _scaleCenter; + float _minScale; + + osg::ref_ptr< osg::Node > _leftHandleNode; + osg::ref_ptr< osg::Node > _rightHandleNode; + + osg::Vec4 _color; + osg::Vec4 _pickColor; + + ScaleMode _scaleMode; +}; + + +} + +#endif diff --git a/include/osgManipulator/Scale2DDragger b/include/osgManipulator/Scale2DDragger new file mode 100644 index 000000000..9d956de22 --- /dev/null +++ b/include/osgManipulator/Scale2DDragger @@ -0,0 +1,114 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_SCALE2DDRAGGER +#define OSGMANIPULATOR_SCALE2DDRAGGER 1 + +#include +#include + +namespace osgManipulator { + +/** + * Dragger for performing 2D scaling. + */ +class OSGMANIPULATOR_EXPORT Scale2DDragger : public Dragger +{ + public: + + enum ScaleMode + { + SCALE_WITH_ORIGIN_AS_PIVOT = 0, + SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT + }; + + Scale2DDragger(ScaleMode scaleMode=SCALE_WITH_ORIGIN_AS_PIVOT); + + /** + * Handle pick events on dragger and generate TranslateInLine commands. + */ + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + /** Set/Get min scale for dragger. */ + inline void setMinScale(const osg::Vec2& min) { _minScale = min; } + inline const osg::Vec2& getMinScale() const { return _minScale; } + + /** Set/Get color for dragger. */ + inline void setColor(const osg::Vec4& color) { _color = color; setMaterialColor(_color,*this); } + inline const osg::Vec4 getColor() const { return _color; } + + /** + * Set/Get pick color for dragger. Pick color is color of the dragger + * when picked. It gives a visual feedback to show that the dragger has + * been picked. + */ + inline void setPickColor(const osg::Vec4& color) { _pickColor = color; } + inline const osg::Vec4 getPickColor() const { return _pickColor; } + + /** Set/Get the handle nodes for dragger. */ + inline void setTopLeftHandleNode (osg::Node& node) { _topLeftHandleNode = &node; } + inline osg::Node* getTopLeftHandleNode() { return _topLeftHandleNode.get(); } + inline void setBottomLeftHandleNode (osg::Node& node) { _bottomLeftHandleNode = &node; } + inline osg::Node* getBottomLeftHandleNode() { return _bottomLeftHandleNode.get(); } + inline void setTopRightHandleNode(osg::Node& node) { _topRightHandleNode = &node; } + inline osg::Node* getTopRightHandleNode() { return _topRightHandleNode.get(); } + inline void setBottomRightHandleNode(osg::Node& node) { _bottomRightHandleNode = &node; } + inline osg::Node* getBottomRightHandleNode() { return _bottomRightHandleNode.get(); } + + /** Set/Get the handle nodes postion for dragger. */ + inline void setTopLeftHandlePosition(const osg::Vec2& pos) { _topLeftHandlePosition = pos; } + const osg::Vec2& getTopLeftHandlePosition() { return _topLeftHandlePosition; } + inline void setBottomLeftHandlePosition(const osg::Vec2& pos) { _bottomLeftHandlePosition = pos; } + const osg::Vec2& getBottomLeftHandlePosition() { return _bottomLeftHandlePosition; } + inline void setTopRightHandlePosition(const osg::Vec2& pos) { _topRightHandlePosition = pos; } + const osg::Vec2& getTopRightHandlePosition() { return _topRightHandlePosition; } + inline void setBottomRightHandlePosition(const osg::Vec2& pos){ _bottomRightHandlePosition = pos; } + const osg::Vec2& getBottomRightHandlePosition() { return _bottomRightHandlePosition; } + + protected: + + virtual ~Scale2DDragger(); + + osg::ref_ptr< PlaneProjector > _projector; + osg::Vec3 _startProjectedPoint; + osg::Vec2 _scaleCenter; + osg::Vec2 _referencePoint; + osg::Vec2 _minScale; + + osg::ref_ptr< osg::Node > _topLeftHandleNode; + osg::ref_ptr< osg::Node > _bottomLeftHandleNode; + osg::ref_ptr< osg::Node > _topRightHandleNode; + osg::ref_ptr< osg::Node > _bottomRightHandleNode; + + osg::Vec2 _topLeftHandlePosition; + osg::Vec2 _bottomLeftHandlePosition; + osg::Vec2 _topRightHandlePosition; + osg::Vec2 _bottomRightHandlePosition; + + osg::Vec4 _color; + osg::Vec4 _pickColor; + + ScaleMode _scaleMode; +}; + + +} + +#endif diff --git a/include/osgManipulator/ScaleAxisDragger b/include/osgManipulator/ScaleAxisDragger new file mode 100644 index 000000000..b5acd4303 --- /dev/null +++ b/include/osgManipulator/ScaleAxisDragger @@ -0,0 +1,46 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_SCALEAXISDRAGGER +#define OSGMANIPULATOR_SCALEAXISDRAGGER 1 + +#include + +namespace osgManipulator { + +/** + * Dragger for performing scaling on all 3 axes. + */ +class OSGMANIPULATOR_EXPORT ScaleAxisDragger : public CompositeDragger +{ + public: + + ScaleAxisDragger(); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + protected: + + virtual ~ScaleAxisDragger(); + + osg::ref_ptr< Scale1DDragger > _xDragger; + osg::ref_ptr< Scale1DDragger > _yDragger; + osg::ref_ptr< Scale1DDragger > _zDragger; +}; + + +} + +#endif diff --git a/include/osgManipulator/Selection b/include/osgManipulator/Selection new file mode 100644 index 000000000..3e13027b8 --- /dev/null +++ b/include/osgManipulator/Selection @@ -0,0 +1,68 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_SELECTION +#define OSGMANIPULATOR_SELECTION 1 + +#include +#include + +namespace osgManipulator { + +class MotionCommand; +class TranslateInLineCommand; +class TranslateInPlaneCommand; +class Scale1DCommand; +class Scale2DCommand; +class ScaleUniformCommand; +class Rotate3DCommand; + +/** Computes the nodepath from the given node all the way upto the root. */ +extern OSGMANIPULATOR_EXPORT void computeNodePathToRoot(osg::Node& node, osg::NodePath& np); + +/** + * Selection listens to motion commands generated by draggers. + */ +class OSGMANIPULATOR_EXPORT Selection : public osg::MatrixTransform +{ + public: + + Selection(); + + /** + * Receive motion commands and set the MatrixTransform accordingly to + * transform selections. Returns true on success. + */ + virtual bool receive(const MotionCommand&); + virtual bool receive(const TranslateInLineCommand& command) { return receive((MotionCommand&)command); } + virtual bool receive(const TranslateInPlaneCommand& command) { return receive((MotionCommand&)command); } + virtual bool receive(const Scale1DCommand& command) { return receive((MotionCommand&)command); } + virtual bool receive(const Scale2DCommand& command) { return receive((MotionCommand&)command); } + virtual bool receive(const ScaleUniformCommand& command) { return receive((MotionCommand&)command); } + virtual bool receive(const Rotate3DCommand& command) { return receive((MotionCommand&)command); } + + protected: + + virtual ~Selection(); + + osg::Matrix _startMotionMatrix; + + osg::Matrix _localToWorld; + osg::Matrix _worldToLocal; +}; + + +} + +#endif diff --git a/include/osgManipulator/TabBoxDragger b/include/osgManipulator/TabBoxDragger new file mode 100644 index 000000000..98e0e7e5e --- /dev/null +++ b/include/osgManipulator/TabBoxDragger @@ -0,0 +1,47 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TABBOXDRAGGER +#define OSGMANIPULATOR_TABBOXDRAGGER 1 + +#include + +namespace osgManipulator { + +/** + * TabBoxDragger consists of 6 TabPlaneDraggers to form a box dragger that + * performs translation and scaling. + */ +class OSGMANIPULATOR_EXPORT TabBoxDragger : public CompositeDragger +{ + public: + + TabBoxDragger(); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + void setPlaneColor(const osg::Vec4& color); + + protected: + + virtual ~TabBoxDragger(); + + std::vector< osg::ref_ptr< TabPlaneDragger > > _planeDraggers; +}; + + +} + +#endif diff --git a/include/osgManipulator/TabPlaneDragger b/include/osgManipulator/TabPlaneDragger new file mode 100644 index 000000000..f9c0eeeb3 --- /dev/null +++ b/include/osgManipulator/TabPlaneDragger @@ -0,0 +1,59 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TABPLANEDRAGGER +#define OSGMANIPULATOR_TABPLANEDRAGGER 1 + +#include +#include +#include + +namespace osgManipulator { + +/** + * Tab plane dragger consists of a plane with tabs on it's corners and edges + * for scaling. And the plane is used as a 2D translate dragger. + */ +class OSGMANIPULATOR_EXPORT TabPlaneDragger : public CompositeDragger +{ + public: + + TabPlaneDragger(); + + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hit, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(bool twoSidedHandle = true); + + void setPlaneColor(const osg::Vec4& color) { _translateDragger->setColor(color); } + + protected: + + virtual ~TabPlaneDragger(); + + osg::ref_ptr< TranslatePlaneDragger > _translateDragger; + osg::ref_ptr< Scale2DDragger > _cornerScaleDragger; + osg::ref_ptr< Scale1DDragger > _horzEdgeScaleDragger; + osg::ref_ptr< Scale1DDragger > _vertEdgeScaleDragger; + + float _handleScaleFactor; +}; + + +} + +#endif diff --git a/include/osgManipulator/TabPlaneTrackballDragger b/include/osgManipulator/TabPlaneTrackballDragger new file mode 100644 index 000000000..6b96d4389 --- /dev/null +++ b/include/osgManipulator/TabPlaneTrackballDragger @@ -0,0 +1,48 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TABPLANETRACKBALLDRAGGER +#define OSGMANIPULATOR_TABPLANETRACKBALLDRAGGER 1 + +#include +#include + +namespace osgManipulator { + +/** + * Dragger for performing rotation in all axes. + */ +class OSGMANIPULATOR_EXPORT TabPlaneTrackballDragger : public CompositeDragger +{ + public: + + TabPlaneTrackballDragger(); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + void setPlaneColor(const osg::Vec4& color) { _tabPlaneDragger->setPlaneColor(color); } + + protected: + + virtual ~TabPlaneTrackballDragger(); + + osg::ref_ptr _trackballDragger; + osg::ref_ptr _tabPlaneDragger; +}; + + +} + +#endif diff --git a/include/osgManipulator/TrackballDragger b/include/osgManipulator/TrackballDragger new file mode 100644 index 000000000..4854da038 --- /dev/null +++ b/include/osgManipulator/TrackballDragger @@ -0,0 +1,48 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TRACKBALLDRAGGER +#define OSGMANIPULATOR_TRACKBALLDRAGGER 1 + +#include +#include + +namespace osgManipulator { + +/** + * Dragger for performing rotation in all axes. + */ +class OSGMANIPULATOR_EXPORT TrackballDragger : public CompositeDragger +{ + public: + + TrackballDragger(bool useAutoTransform=false); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + protected: + + virtual ~TrackballDragger(); + + osg::ref_ptr _xDragger; + osg::ref_ptr _yDragger; + osg::ref_ptr _zDragger; + osg::ref_ptr _xyzDragger; +}; + + +} + +#endif diff --git a/include/osgManipulator/Translate1DDragger b/include/osgManipulator/Translate1DDragger new file mode 100644 index 000000000..913d42d40 --- /dev/null +++ b/include/osgManipulator/Translate1DDragger @@ -0,0 +1,71 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TRANSLATE1DDRAGGER +#define OSGMANIPULATOR_TRANSLATE1DDRAGGER 1 + +#include +#include + +namespace osgManipulator { + + +/** + * Dragger for performing 1D translation. + */ +class OSGMANIPULATOR_EXPORT Translate1DDragger : public Dragger +{ + public: + + Translate1DDragger(); + + Translate1DDragger(const osg::Vec3& s, const osg::Vec3& e); + + /** Handle pick events on dragger and generate TranslateInLine commands. */ + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hit, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + /** Set/Get color for dragger. */ + inline void setColor(const osg::Vec4& color) { _color = color; setMaterialColor(_color,*this); } + inline const osg::Vec4 getColor() const { return _color; } + + /** Set/Get pick color for dragger. Pick color is color of the dragger when picked. + It gives a visual feedback to show that the dragger has been picked. */ + inline void setPickColor(const osg::Vec4& color) { _pickColor = color; } + inline const osg::Vec4 getPickColor() const { return _pickColor; } + + inline void setCheckForNodeInNodePath(bool onOff) { _checkForNodeInNodePath = onOff; } + + protected: + + virtual ~Translate1DDragger(); + + osg::ref_ptr< LineProjector > _projector; + osg::Vec3 _startProjectedPoint; + + osg::Vec4 _color; + osg::Vec4 _pickColor; + + bool _checkForNodeInNodePath; +}; + + +} + +#endif diff --git a/include/osgManipulator/Translate2DDragger b/include/osgManipulator/Translate2DDragger new file mode 100644 index 000000000..7b0f01e34 --- /dev/null +++ b/include/osgManipulator/Translate2DDragger @@ -0,0 +1,69 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TRANSLATE2DDRAGGER +#define OSGMANIPULATOR_TRANSLATE2DDRAGGER 1 + +#include +#include + +#include + +namespace osgManipulator { + +/** + * Dragger for performing 2D translation. + */ +class OSGMANIPULATOR_EXPORT Translate2DDragger : public Dragger +{ + public: + + Translate2DDragger(); + + Translate2DDragger(const osg::Plane& plane); + + /** Handle pick events on dragger and generate TranslateInLine commands. */ + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hit, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + /** Set/Get color for dragger. */ + inline void setColor(const osg::Vec4& color) { _color = color; setMaterialColor(_color,*this); } + inline const osg::Vec4 getColor() const { return _color; } + + /** Set/Get pick color for dragger. Pick color is color of the dragger when picked. + It gives a visual feedback to show that the dragger has been picked. */ + inline void setPickColor(const osg::Vec4& color) { _pickColor = color; } + inline const osg::Vec4 getPickColor() const { return _pickColor; } + + protected: + + virtual ~Translate2DDragger(); + + osg::ref_ptr< PlaneProjector > _projector; + osg::Vec3 _startProjectedPoint; + + osg::Vec4 _color; + osg::Vec4 _pickColor; + osg::ref_ptr _polygonOffset; +}; + + +} + +#endif diff --git a/include/osgManipulator/TranslateAxisDragger b/include/osgManipulator/TranslateAxisDragger new file mode 100644 index 000000000..90b3422d6 --- /dev/null +++ b/include/osgManipulator/TranslateAxisDragger @@ -0,0 +1,46 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TRANSLATEAXISDRAGGER +#define OSGMANIPULATOR_TRANSLATEAXISDRAGGER 1 + +#include + +namespace osgManipulator { + +/** + * Dragger for performing translation in all three axes. + */ +class OSGMANIPULATOR_EXPORT TranslateAxisDragger : public CompositeDragger +{ + public: + + TranslateAxisDragger(); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + protected: + + virtual ~TranslateAxisDragger(); + + osg::ref_ptr< Translate1DDragger > _xDragger; + osg::ref_ptr< Translate1DDragger > _yDragger; + osg::ref_ptr< Translate1DDragger > _zDragger; +}; + + +} + +#endif diff --git a/include/osgManipulator/TranslatePlaneDragger b/include/osgManipulator/TranslatePlaneDragger new file mode 100644 index 000000000..99be0888b --- /dev/null +++ b/include/osgManipulator/TranslatePlaneDragger @@ -0,0 +1,58 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#ifndef OSGMANIPULATOR_TRANSLATEPLANEDRAGGER +#define OSGMANIPULATOR_TRANSLATEPLANEDRAGGER 1 + +#include +#include + +namespace osgManipulator { + +/** + * Tab plane dragger consists of a plane with tabs on it's corners and edges + * for scaling. And the plane is used as a 2D translate dragger. + */ +class OSGMANIPULATOR_EXPORT TranslatePlaneDragger : public CompositeDragger +{ + public: + + TranslatePlaneDragger(); + + virtual bool handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hitList, + const osgUtil::IntersectVisitor::HitList::iterator& hit, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); + + /** Setup default geometry for dragger. */ + void setupDefaultGeometry(); + + inline void setColor(const osg::Vec4& color) { if (_translate2DDragger.valid()) _translate2DDragger->setColor(color); } + + Translate1DDragger* getTranslate1DDragger() { return _translate1DDragger.get(); } + Translate2DDragger* getTranslate2DDragger() { return _translate2DDragger.get(); } + + protected: + + virtual ~TranslatePlaneDragger(); + + osg::ref_ptr< Translate2DDragger > _translate2DDragger; + osg::ref_ptr< Translate1DDragger > _translate1DDragger; + bool _usingTranslate1DDragger; +}; + + +} + +#endif diff --git a/src/osgManipulator/AntiSquish.cpp b/src/osgManipulator/AntiSquish.cpp new file mode 100644 index 000000000..67ece3fd7 --- /dev/null +++ b/src/osgManipulator/AntiSquish.cpp @@ -0,0 +1,192 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include + +using namespace osgManipulator; + +namespace +{ + class AntiSquishCallback: public osg::NodeCallback + { + public: + AntiSquishCallback(AntiSquish* asq) : osg::NodeCallback(), _antiSquish(asq) {} + virtual ~AntiSquishCallback() {}; + + virtual void operator() (osg::Node*, osg::NodeVisitor* nv) + { + // Get the node path. + osg::NodePath np = nv->getNodePath(); + + // Remove the last node which is the anti squish node itself. + np.pop_back(); + + // Get the accumulated modeling matrix. + osg::Matrix localToWorld = computeLocalToWorld(np); + + // compute the unsquished matrix. + bool flag = false; + osg::Matrix _unsquishedMatrix = _antiSquish->computeUnSquishedMatrix(localToWorld, flag); + if (flag) + _antiSquish->setMatrix(_unsquishedMatrix); + } + + protected: + AntiSquish* _antiSquish; + }; + +} + +AntiSquish::AntiSquish() : _usePivot(true), _usePosition(false) +{ + _asqCallback = new AntiSquishCallback(this); + setUpdateCallback(_asqCallback); +} + +AntiSquish::AntiSquish(const osg::Vec3& pivot) : _pivot(pivot), _usePivot(true), _usePosition(false) +{ + _asqCallback = new AntiSquishCallback(this); + setUpdateCallback(_asqCallback); +} + +AntiSquish::AntiSquish(const osg::Vec3& pivot, const osg::Vec3& pos) + : _pivot(pivot), _usePivot(true), _position(pos), _usePosition(true) +{ + _asqCallback = new AntiSquishCallback(this); + setUpdateCallback(_asqCallback); +} + + +AntiSquish::AntiSquish(const AntiSquish& pat,const osg::CopyOp& copyop) : + MatrixTransform(pat,copyop), + _asqCallback(pat._asqCallback), + _pivot(pat._pivot), + _usePivot(pat._usePivot), + _position(pat._position), + _usePosition(pat._usePosition), + _cachedLocalToWorld(pat._cachedLocalToWorld) +{ +} + +AntiSquish::~AntiSquish() +{ +} + +osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& flag) +{ + osg::Vec3d t, s; + osg::Quat r, so; + + if (LTW == _cachedLocalToWorld && _dirty == false) + { + flag = false; + return osg::Matrix::identity(); + } + + _cachedLocalToWorld = LTW; + + LTW.decompose(t, r, s, so); + + // Let's take an average of the scale. + double av = (s[0] + s[1] + s[2])/3.0; + s[0] = av; s[1] = av; s[2]=av; + + if (av == 0) + { + flag = false; + return osg::Matrix::identity(); + } + + osg::Matrix unsquished; + + // + // Final Matrix: [-Pivot][SO]^[S][SO][R][T][Pivot][LOCALTOWORLD]^[position] + // OR [SO]^[S][SO][R][T][LOCALTOWORLD]^ + // + if (_usePivot) + { + osg::Matrix tmpPivot; + tmpPivot.setTrans(-_pivot); + unsquished.postMult(tmpPivot); + + osg::Matrix tmps, invtmps; + so.get(tmps); + invtmps = osg::Matrix::inverse(tmps); + if (invtmps.isNaN()) + { + flag = false; + return osg::Matrix::identity(); + } + + //SO^ + unsquished.postMult(invtmps); + //S + unsquished.postMult(osg::Matrix::scale(s[0], s[1], s[2])); + //SO + unsquished.postMult(tmps); + tmpPivot.makeIdentity(); + osg::Matrix tmpr; + r.get(tmpr); + //R + unsquished.postMult(tmpr); + //T + unsquished.postMult(osg::Matrix::translate(t[0],t[1],t[2])); + + osg::Matrix invltw; + invltw = osg::Matrix::inverse(LTW); + if (invltw.isNaN()) + { + flag =false; + return osg::Matrix::identity(); + } + // LTW^ + unsquished.postMult( invltw ); + + // Position + tmpPivot.makeIdentity(); + if (_usePosition) + tmpPivot.setTrans(_position); + else + tmpPivot.setTrans(_pivot); + + unsquished.postMult(tmpPivot); + } + else + { + osg::Matrix tmps, invtmps; + so.get(tmps); + invtmps = osg::Matrix::inverse(tmps); + unsquished.postMult(invtmps); + unsquished.postMult(osg::Matrix::scale(s[0], s[1], s[2])); + unsquished.postMult(tmps); + osg::Matrix tmpr; + r.get(tmpr); + unsquished.postMult(tmpr); + unsquished.postMult(osg::Matrix::translate(t[0],t[1],t[2])); + unsquished.postMult( osg::Matrix::inverse(LTW) ); + } + + if (unsquished.isNaN()) + { + flag = false; + return osg::Matrix::identity(); + } + + flag = true; + _dirty = false; + return unsquished; +} + + + diff --git a/src/osgManipulator/Command.cpp b/src/osgManipulator/Command.cpp new file mode 100644 index 000000000..4ed41e6a5 --- /dev/null +++ b/src/osgManipulator/Command.cpp @@ -0,0 +1,321 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include + +using namespace osgManipulator; + +/////////////////////////////////////////////////////////////////////////////// +// +// Motion Command base class. +// + +MotionCommand::MotionCommand() : _stage(NONE) +{ +} + +MotionCommand::~MotionCommand() +{ +} + +void MotionCommand::addSelection(Selection* selection) +{ + _selectionList.push_back(selection); +} + +void MotionCommand::removeSelection(Selection* selection) +{ + _selectionList.erase(std::remove(_selectionList.begin(), _selectionList.end(), selection), + _selectionList.end()); +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Translate in line command. +// + +TranslateInLineCommand::TranslateInLineCommand() +{ + _line = new osg::LineSegment; +} + +TranslateInLineCommand::TranslateInLineCommand(const osg::Vec3& s, const osg::Vec3& e) +{ + _line = new osg::LineSegment(s,e); +} + +TranslateInLineCommand::~TranslateInLineCommand() +{ +} + +bool TranslateInLineCommand::execute() +{ + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*this); + } + return true; +} + +bool TranslateInLineCommand::unexecute() +{ + osg::ref_ptr inverse = new TranslateInLineCommand(); + *inverse = *this; + inverse->setTranslation(-_translation); + + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*inverse); + } + return true; +} + +void TranslateInLineCommand::applyConstraint(const Constraint* constraint) +{ + if (constraint) constraint->constrain(*this); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Translate in plane command. +// + +TranslateInPlaneCommand::TranslateInPlaneCommand() +{ +} + +TranslateInPlaneCommand::TranslateInPlaneCommand(const osg::Plane& plane) : _plane(plane) +{ +} + +TranslateInPlaneCommand::~TranslateInPlaneCommand() +{ +} + +bool TranslateInPlaneCommand::execute() +{ + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*this); + } + return true; +} + +bool TranslateInPlaneCommand::unexecute() +{ + osg::ref_ptr inverse = new TranslateInPlaneCommand(); + *inverse = *this; + inverse->setTranslation(-_translation); + + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*inverse); + } + return true; +} + +void TranslateInPlaneCommand::applyConstraint(const Constraint* constraint) +{ + if (constraint) constraint->constrain(*this); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Scale 1D command. +// + +Scale1DCommand::Scale1DCommand() : _scale(1.0f) +{ +} + +Scale1DCommand::~Scale1DCommand() +{ +} + +bool Scale1DCommand::execute() +{ + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*this); + } + return true; +} + +bool Scale1DCommand::unexecute() +{ + osg::ref_ptr inverse = new Scale1DCommand(); + *inverse = *this; + if (_scale) inverse->setScale(1.0/_scale); + + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*inverse); + } + return true; +} + +void Scale1DCommand::applyConstraint(const Constraint* constraint) +{ + if (constraint) constraint->constrain(*this); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Scale 2D command. +// + +Scale2DCommand::Scale2DCommand() : _scale(1.0,1.0) +{ +} + +Scale2DCommand::~Scale2DCommand() +{ +} + +bool Scale2DCommand::execute() +{ + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*this); + } + return true; +} + +bool Scale2DCommand::unexecute() +{ + osg::ref_ptr inverse = new Scale2DCommand(); + *inverse = *this; + if (_scale[0] && _scale[1]) + inverse->setScale(osg::Vec2(1.0/_scale[0],1.0/_scale[1])); + + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*inverse); + } + return true; +} + +void Scale2DCommand::applyConstraint(const Constraint* constraint) +{ + if (constraint) constraint->constrain(*this); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Scale uniform command. +// + +ScaleUniformCommand::ScaleUniformCommand() : _scale(1.0f) +{ +} + +ScaleUniformCommand::~ScaleUniformCommand() +{ +} + +bool ScaleUniformCommand::execute() +{ + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*this); + } + return true; +} + +bool ScaleUniformCommand::unexecute() +{ + osg::ref_ptr inverse = new ScaleUniformCommand(); + *inverse = *this; + if (_scale) inverse->setScale(1.0/_scale); + + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*inverse); + } + return true; +} + +void ScaleUniformCommand::applyConstraint(const Constraint* constraint) +{ + if (constraint) constraint->constrain(*this); +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Rotate 3D command. +// + +Rotate3DCommand::Rotate3DCommand() +{ +} + +Rotate3DCommand::~Rotate3DCommand() +{ +} + +bool Rotate3DCommand::execute() +{ + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*this); + } + return true; +} + +bool Rotate3DCommand::unexecute() +{ + osg::ref_ptr inverse = new Rotate3DCommand(); + *inverse = *this; + inverse->setRotation(_rotation.inverse()); + + for (SelectionList::iterator iter = getSelectionList().begin(); + iter != getSelectionList().end(); + ++iter) + { + (*iter)->receive(*inverse); + } + return true; +} + +void Rotate3DCommand::applyConstraint(const Constraint* constraint) +{ + if (constraint) constraint->constrain(*this); +} diff --git a/src/osgManipulator/CommandManager.cpp b/src/osgManipulator/CommandManager.cpp new file mode 100644 index 000000000..b71b271b8 --- /dev/null +++ b/src/osgManipulator/CommandManager.cpp @@ -0,0 +1,124 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include + +using namespace osgManipulator; + +CommandManager::CommandManager() +{ +} + +CommandManager::~CommandManager() +{ +} + +bool CommandManager::connect(Dragger& dragger, Selection& selection) +{ + dragger.setCommandManager(this); + + // Check to see if the selection is already associated with the dragger. + if (_draggerSelectionMap.count(&dragger) > 0) + { + std::pair s; + s = _draggerSelectionMap.equal_range(&dragger); + + for (DraggerSelectionMap::iterator iter = s.first; iter != s.second; ++iter) + { + if (iter->second == &selection) + return false; + } + } + + // Associate selection with dragger + _draggerSelectionMap.insert(DraggerSelectionMap::value_type(&dragger,&selection)); + + return true; +} + +bool CommandManager::connect(Dragger& dragger, Constraint& constraint) +{ + dragger.setCommandManager(this); + + // Check to see if the selection is already associated with the dragger. + if (_draggerConstraintMap.count(&dragger) > 0) + { + std::pair s; + s = _draggerConstraintMap.equal_range(&dragger); + + for (DraggerConstraintMap::iterator iter = s.first; iter != s.second; ++iter) + { + if (iter->second == &constraint) + return false; + } + } + + // Associate selection with dragger + _draggerConstraintMap.insert(DraggerConstraintMap::value_type(&dragger,&constraint)); + + return true; +} + +bool CommandManager::disconnect(Dragger& dragger) +{ + _draggerSelectionMap.erase(&dragger); + _draggerConstraintMap.erase(&dragger); + return true; +} + +void CommandManager::dispatch(MotionCommand& command) +{ + command.execute(); +} + +void CommandManager::addSelectionsToCommand(MotionCommand& command, Dragger& dragger) +{ + // Apply constraints to the command. + if (_draggerConstraintMap.count(&dragger) > 0) + { + // Get all the selections assoicated with this dragger. + std::pair s; + s = _draggerConstraintMap.equal_range(&dragger); + + for (DraggerConstraintMap::iterator iter = s.first; iter != s.second; ++iter) + { + // Add the selection to the command. + if (iter->second.valid()) + { + command.applyConstraint(iter->second.get()); + } + } + } + + // Add the dragger to the selection list first. + command.addSelection(&dragger); + + // Add the remaining selections. + if (_draggerSelectionMap.count(&dragger) > 0) + { + // Get all the selections assoicated with this dragger. + std::pair s; + s = _draggerSelectionMap.equal_range(&dragger); + + for (DraggerSelectionMap::iterator iter = s.first; iter != s.second; ++iter) + { + // Add the selection to the command. + if (iter->second.valid()) + { + command.addSelection(iter->second.get()); + } + } + } +} diff --git a/src/osgManipulator/Constraint.cpp b/src/osgManipulator/Constraint.cpp new file mode 100644 index 000000000..4ec9cc048 --- /dev/null +++ b/src/osgManipulator/Constraint.cpp @@ -0,0 +1,165 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include + +using namespace osgManipulator; + +namespace +{ + +double round_to_nearest_int(double x) { return floor(x+0.5); } + +osg::Vec3d snap_point_to_grid(const osg::Vec3d& point, const osg::Vec3d& origin, const osg::Vec3d& spacing) +{ + osg::Vec3d scale; + scale[0] = spacing[0] ? round_to_nearest_int((point[0] - origin[0]) / spacing[0]) : 1.0; + scale[1] = spacing[1] ? round_to_nearest_int((point[1] - origin[1]) / spacing[1]) : 1.0; + scale[2] = spacing[2] ? round_to_nearest_int((point[2] - origin[2]) / spacing[2]) : 1.0; + osg::Vec3d snappedPoint = origin; + snappedPoint += osg::Vec3(scale[0]*spacing[0],scale[1]*spacing[1],scale[2]*spacing[2]); + return snappedPoint; +} + +} + + +void Constraint::computeLocalToWorldAndWorldToLocal() const +{ + osg::NodePath pathToRoot; + computeNodePathToRoot(const_cast(getReferenceNode()),pathToRoot); + _localToWorld = osg::computeLocalToWorld(pathToRoot); + _worldToLocal = osg::computeWorldToLocal(pathToRoot); +} + +GridConstraint::GridConstraint(osg::Node& refNode, const osg::Vec3d& origin, const osg::Vec3d& spacing) + : Constraint(refNode), _origin(origin), _spacing(spacing) +{ +} + +bool GridConstraint::constrain(TranslateInLineCommand& command) const +{ + if (command.getStage() == osgManipulator::MotionCommand::START) + computeLocalToWorldAndWorldToLocal(); + else if (command.getStage() == osgManipulator::MotionCommand::FINISH) + return true; + + osg::Vec3 translatedPoint = command.getLineStart() + command.getTranslation(); + osg::Vec3d localTranslatedPoint = (osg::Vec3d(translatedPoint) + * command.getLocalToWorld() * getWorldToLocal()); + osg::Vec3d newLocalTranslatedPoint = snap_point_to_grid(localTranslatedPoint, + _origin, + _spacing); + command.setTranslation(newLocalTranslatedPoint * getLocalToWorld() * command.getWorldToLocal() - command.getLineStart()); + + return true; +} + +bool GridConstraint::constrain(TranslateInPlaneCommand& command) const +{ + if (command.getStage() == osgManipulator::MotionCommand::START) + computeLocalToWorldAndWorldToLocal(); + else if (command.getStage() == osgManipulator::MotionCommand::FINISH) + return true; + + osg::Matrix commandToConstraint = command.getLocalToWorld() * getWorldToLocal(); + osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal(); + + // Snap the reference point to grid. + osg::Vec3d localRefPoint = command.getReferencePoint() * commandToConstraint; + osg::Vec3d snappedLocalRefPoint = snap_point_to_grid(localRefPoint, _origin, _spacing); + osg::Vec3d snappedCmdRefPoint = snappedLocalRefPoint * constraintToCommand; + + // Snap the translated point to grid. + osg::Vec3 translatedPoint = snappedCmdRefPoint + command.getTranslation(); + osg::Vec3d localTranslatedPoint = osg::Vec3d(translatedPoint) * commandToConstraint; + osg::Vec3d newLocalTranslatedPoint = snap_point_to_grid(localTranslatedPoint, _origin, _spacing); + + // Set the snapped translation. + command.setTranslation(newLocalTranslatedPoint * constraintToCommand - snappedCmdRefPoint); + + return true; +} + +bool GridConstraint::constrain(Scale1DCommand& command) const +{ + if (command.getStage() == osgManipulator::MotionCommand::START) + computeLocalToWorldAndWorldToLocal(); + else if (command.getStage() == osgManipulator::MotionCommand::FINISH) + return true; + + double scaledPoint = (command.getReferencePoint() - command.getScaleCenter()) * command.getScale() + command.getScaleCenter(); + + osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal(); + osg::Vec3d commandOrigin = _origin * constraintToCommand; + osg::Vec3d commandSpacing = (_origin + _spacing) * constraintToCommand - commandOrigin; + + double spacingFactor = commandSpacing[0] ? round_to_nearest_int((scaledPoint-commandOrigin[0])/commandSpacing[0]) : 1.0; + + double snappedScaledPoint = commandOrigin[0] + commandSpacing[0] * spacingFactor; + + double denom = (command.getReferencePoint() - command.getScaleCenter()); + double snappedScale = (denom) ? (snappedScaledPoint - command.getScaleCenter()) / denom : 1.0; + if (snappedScale < command.getMinScale()) snappedScale = command.getMinScale(); + + command.setScale(snappedScale); + return true; +} + +bool GridConstraint::constrain(Scale2DCommand& command) const +{ + if (command.getStage() == osgManipulator::MotionCommand::START) + computeLocalToWorldAndWorldToLocal(); + else if (command.getStage() == osgManipulator::MotionCommand::FINISH) + return true; + + osg::Vec2d scaledPoint = command.getReferencePoint() - command.getScaleCenter(); + scaledPoint[0] *= command.getScale()[0]; + scaledPoint[1] *= command.getScale()[1]; + scaledPoint += command.getScaleCenter(); + + osg::Matrix constraintToCommand = getLocalToWorld() * command.getWorldToLocal(); + osg::Vec3d commandOrigin = _origin * constraintToCommand; + osg::Vec3d commandSpacing = (_origin + _spacing) * constraintToCommand - commandOrigin; + + osg::Vec2d spacingFactor; + spacingFactor[0] = commandSpacing[0] ? round_to_nearest_int((scaledPoint[0] - commandOrigin[0])/commandSpacing[0]) : 1.0; + spacingFactor[1] = commandSpacing[2] ? round_to_nearest_int((scaledPoint[1] - commandOrigin[2])/commandSpacing[2]) : 1.0; + + osg::Vec2d snappedScaledPoint = (osg::Vec2d(commandOrigin[0],commandOrigin[2]) + + osg::Vec2d(commandSpacing[0]*spacingFactor[0], + commandSpacing[2]*spacingFactor[1])); + + osg::Vec2d denom = command.getReferencePoint() - command.getScaleCenter(); + osg::Vec2 snappedScale; + snappedScale[0] = denom[0] ? (snappedScaledPoint[0] - command.getScaleCenter()[0]) / denom[0] : 1.0; + snappedScale[1] = denom[1] ? (snappedScaledPoint[1] - command.getScaleCenter()[1]) / denom[1] : 1.0; + + if (snappedScale[0] < command.getMinScale()[0]) snappedScale[0] = command.getMinScale()[0]; + if (snappedScale[1] < command.getMinScale()[1]) snappedScale[1] = command.getMinScale()[1]; + + command.setScale(snappedScale); + return true; +} + +bool GridConstraint::constrain(ScaleUniformCommand&) const +{ + // Can you correctly snap a ScaleUniformCommand using a Grid constraint that has + // different spacings in the three axis?? + return false; +} diff --git a/src/osgManipulator/Dragger.cpp b/src/osgManipulator/Dragger.cpp new file mode 100644 index 000000000..ddd7bd273 --- /dev/null +++ b/src/osgManipulator/Dragger.cpp @@ -0,0 +1,127 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include + +using namespace osgManipulator; + +Dragger::Dragger() : _commandManager(0) +{ + _parentDragger = this; +} + +Dragger::~Dragger() +{ +} + +bool CompositeDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hl, const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + for (DraggerList::iterator itr=_draggerList.begin(); itr!=_draggerList.end(); ++itr) + { + if ((*itr)->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa)) + return true; + } + return false; +} + +bool CompositeDragger::containsDragger( const Dragger* dragger ) const +{ + for (DraggerList::const_iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) + { + if (itr->get() == dragger) return true; + } + return false; +} + +CompositeDragger::DraggerList::iterator CompositeDragger::findDragger( const Dragger* dragger ) +{ + for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) + { + if (itr->get() == dragger) return itr; + } + return _draggerList.end(); +} + +bool CompositeDragger::addDragger(Dragger *dragger) +{ + if (dragger && !containsDragger(dragger)) + { + _draggerList.push_back(dragger); + return true; + } + else return false; + +} + +bool CompositeDragger::removeDragger(Dragger *dragger) +{ + DraggerList::iterator itr = findDragger(dragger); + if (itr != _draggerList.end()) + { + _draggerList.erase(itr); + return true; + } + else return false; + +} +void CompositeDragger::setCommandManager(CommandManager* cm) +{ + for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) + { + (*itr)->setCommandManager(cm); + } + Dragger::setCommandManager(cm); +} + +void CompositeDragger::setParentDragger(Dragger* dragger) +{ + for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr) + { + (*itr)->setParentDragger(dragger); + } + Dragger::setParentDragger(dragger); +} + +class ForceCullCallback : public osg::Drawable::CullCallback +{ + public: + virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const + { + return true; + } +}; + +void osgManipulator::setDrawableToAlwaysCull(osg::Drawable& drawable) +{ + ForceCullCallback* cullCB = new ForceCullCallback; + drawable.setCullCallback (cullCB); +} + +void osgManipulator::setMaterialColor(const osg::Vec4& color, osg::Node& node) +{ + osg::Material* mat = dynamic_cast(node.getOrCreateStateSet()->getAttribute(osg::StateAttribute::MATERIAL)); + if (! mat) + { + mat = new osg::Material; + node.getOrCreateStateSet()->setAttribute(mat); + } + mat->setDiffuse(osg::Material::FRONT_AND_BACK, color); +} diff --git a/src/osgManipulator/GNUmakefile b/src/osgManipulator/GNUmakefile new file mode 100644 index 000000000..a17c628d5 --- /dev/null +++ b/src/osgManipulator/GNUmakefile @@ -0,0 +1,37 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + + +CXXFILES = \ + AntiSquish.cpp \ + Command.cpp \ + CommandManager.cpp \ + Constraint.cpp \ + Dragger.cpp \ + Projector.cpp \ + RotateCylinderDragger.cpp \ + RotateSphereDragger.cpp \ + Scale1DDragger.cpp \ + Scale2DDragger.cpp \ + ScaleAxisDragger.cpp \ + Selection.cpp \ + TabBoxDragger.cpp \ + TabPlaneDragger.cpp \ + TabPlaneTrackballDragger.cpp \ + TrackballDragger.cpp \ + Translate1DDragger.cpp \ + Translate2DDragger.cpp \ + TranslateAxisDragger.cpp \ + TranslatePlaneDragger.cpp + +DEF += -DOSGMANIPULATOR_LIBRARY + +INC += +LIBS += -losgGA -losgUtil -losg $(GL_LIBS) $(OTHER_LIBS) + +TARGET_BASENAME = osgManipulator + +LIB = $(LIB_PREFIX)$(TARGET_BASENAME).$(LIB_EXT) + +include $(TOPDIR)/Make/makerules + diff --git a/src/osgManipulator/Projector.cpp b/src/osgManipulator/Projector.cpp new file mode 100644 index 000000000..2552450e6 --- /dev/null +++ b/src/osgManipulator/Projector.cpp @@ -0,0 +1,711 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include + +using namespace osgManipulator; + +namespace +{ + +bool computeClosestPoints(const osg::LineSegment& l1, const osg::LineSegment& l2, + osg::Vec3& p1, osg::Vec3& p2) +{ + // Computes the closest points (p1 and p2 on line l1 and l2 respectively) between the two lines + // An explanation of the algorithm can be found at + // http://www.geometryalgorithms.com/Archive/algorithm_0106/algorithm_0106.htm + + osg::Vec3 u = l1.end() - l1.start(); u.normalize(); + osg::Vec3 v = l2.end() - l2.start(); v.normalize(); + + osg::Vec3 w0 = l1.start() - l2.start(); + + float a = u * u; + float b = u * v; + float c = v * v; + float d = u * w0; + float e = v * w0; + + float denominator = a*c - b*b; + + // Test if lines are parallel + if (denominator == 0.0) return false; + + float sc = (b*e - c*d)/denominator; + float tc = (a*e - b*d)/denominator; + + p1 = l1.start() + u * sc; + p2 = l2.start() + v * tc; + + return true; +} + +bool computeClosestPointOnLine(const osg::Vec3& lineStart, const osg::Vec3& lineEnd, + const osg::Vec3& fromPoint, osg::Vec3& closestPoint) +{ + osg::Vec3 v = lineEnd - lineStart; + osg::Vec3 w = fromPoint - lineStart; + + float c1 = w * v; + float c2 = v * v; + + float almostZero = 0.000001; + if (c2 < almostZero) return false; + + float b = c1 / c2; + closestPoint = lineStart + v * b; + + return true; +} + +bool getPlaneLineIntersection(const osg::Vec4& plane, + const osg::Vec3& lineStart, const osg::Vec3& lineEnd, + osg::Vec3& isect) +{ + const double deltaX = lineEnd.x() - lineStart.x(); + const double deltaY = lineEnd.y() - lineStart.y(); + const double deltaZ = lineEnd.z() - lineStart.z(); + + const double denominator = (plane[0]*deltaX + plane[1]*deltaY + plane[2]*deltaZ); + if (! denominator) return false; + + const double C = (plane[0]*lineStart.x() + plane[1]*lineStart.y() + plane[2]*lineStart.z() + plane[3]) / denominator; + + isect.x() = lineStart.x() - deltaX * C; + isect.y() = lineStart.y() - deltaY * C; + isect.z() = lineStart.z() - deltaZ * C; + + return true; +} + +bool getSphereLineIntersection(const osg::Sphere& sphere, + const osg::Vec3& lineStart, const osg::Vec3& lineEnd, + osg::Vec3& frontISect, osg::Vec3& backISect) +{ + osg::Vec3 lineDirection = lineEnd - lineStart; + lineDirection.normalize(); + + osg::Vec3 v = lineStart - sphere.getCenter(); + float B = 2.0f * (lineDirection * v); + float C = v * v - sphere.getRadius() * sphere.getRadius(); + + float discriminant = B * B - 4.0f * C; + + if (discriminant < 0.0f) // Line and sphere don't intersect. + return false; + + float discriminantSqroot = sqrtf(discriminant); + float t0 = (-B - discriminantSqroot) * 0.5f; + frontISect = lineStart + lineDirection * t0; + + float t1 = (-B + discriminantSqroot) * 0.5f; + backISect = lineStart + lineDirection * t1; + + return true; +} + +bool getUnitCylinderLineIntersection(const osg::Vec3& lineStart, const osg::Vec3& lineEnd, + osg::Vec3& isectFront, osg::Vec3& isectBack) +{ + osg::Vec3 dir = lineEnd - lineStart; + dir.normalize(); + + float a = dir[0] * dir[0] + dir[1] * dir[1]; + float b = 2.0f * (lineStart[0] * dir[0] + lineStart[1] * dir[1]); + float c = lineStart[0] * lineStart[0] + lineStart[1] * lineStart[1] - 1; + + float d = b*b - 4*a*c; + if (d < 0.0f) return false; + + float dSqroot = sqrtf(d); + float t0, t1; + if (b > 0.0f) + { + t0 = -(2.0f * c) / (dSqroot + b); + t1 = -(dSqroot + b) / (2.0 * a); + } + else + { + t0 = (2.0f * c) / (dSqroot - b); + t1 = (dSqroot - b) / (2.0 * a); + } + + isectFront = lineStart + dir * t0; + isectBack = lineStart + dir * t1; + return true; +} + +bool getCylinderLineIntersection(const osg::Cylinder& cylinder, + const osg::Vec3& lineStart, const osg::Vec3& lineEnd, + osg::Vec3& isectFront, osg::Vec3& isectBack) +{ + // Compute matrix transformation that takes the cylinder to a unit cylinder with Z-axis as it's axis and + // (0,0,0) as it's center. + float oneOverRadius = 1.0f / cylinder.getRadius(); + osg::Matrix toUnitCylInZ = osg::Matrix::translate(-cylinder.getCenter()) + * osg::Matrix::scale(oneOverRadius, oneOverRadius, oneOverRadius) + * osg::Matrix(cylinder.getRotation().inverse()); + + // Transform the lineStart and lineEnd into the unit cylinder space. + osg::Vec3 unitCylLineStart = lineStart * toUnitCylInZ; + osg::Vec3 unitCylLineEnd = lineEnd * toUnitCylInZ; + + // Intersect line with unit cylinder. + osg::Vec3 unitCylIsectFront, unitCylIsectBack; + if (! getUnitCylinderLineIntersection(unitCylLineStart, unitCylLineEnd, unitCylIsectFront, unitCylIsectBack)) + return false; + + // Transform back from unit cylinder space. + osg::Matrix invToUnitCylInZ(osg::Matrix::inverse(toUnitCylInZ)); + isectFront = unitCylIsectFront * invToUnitCylInZ; + isectBack = unitCylIsectBack * invToUnitCylInZ; + + return true; +} + +osg::Vec3 getEyeDirection(const osg::Matrix& viewingMatrix, const osg::Matrix& localToWorld) +{ + osg::Vec3 eye, center, up; + viewingMatrix.getLookAt(eye, center, up); + osg::Vec3 eyeDir = eye - center; + + // To take a normal from world to local you need to transform it by the transpose of the inverse of the + // world to local matrix. Pre-multipling is equivalent to doing a post-multiplication of the transpose. + osg::Vec3 localEyeDir = localToWorld * eyeDir; + localEyeDir.normalize(); + return localEyeDir; +} + +osg::Plane computePlaneThruPointAndOrientedToEye(const osg::Matrix& viewingMatrix, const osg::Matrix& localToWorld, + const osg::Vec3& point, bool front) +{ + osg::Vec3 planeNormal = getEyeDirection(viewingMatrix, localToWorld); + if (! front) planeNormal = -planeNormal; + + osg::Plane plane; + plane.set(planeNormal, point); + return plane; +} + +osg::Plane computePlaneParallelToAxisAndOrientedToEye(const osg::Matrix& viewingMatrix, const osg::Matrix& localToWorld, + const osg::Vec3& axisDir, float radius, + osg::Vec3& planeLineStart, osg::Vec3& planeLineEnd, + bool front) +{ + osg::Vec3 perpDir = axisDir ^ getEyeDirection(viewingMatrix, localToWorld); + osg::Vec3 planeDir = perpDir ^ axisDir; + planeDir.normalize(); + if (! front) + planeDir = -planeDir; + + osg::Vec3 planePoint = planeDir * radius + axisDir; + osg::Plane plane; + plane.set(planeDir, planePoint); + + planeLineStart = planePoint; + planeLineEnd = planePoint + axisDir; + return plane; +} + +} + + +Projector::Projector() : _worldToLocalDirty(false) +{ +} + +Projector::~Projector() +{ +} + +LineProjector::LineProjector() +{ + _line = new osg::LineSegment(osg::Vec3(0.0,0.0,0.0), osg::Vec3(1.0,0.0,0.0)); +} + +LineProjector::LineProjector(const osg::Vec3& s, const osg::Vec3& e) +{ + _line = new osg::LineSegment(s,e); +} + +LineProjector::~LineProjector() +{ +} + +bool LineProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const +{ + if (!_line->valid()) + { + osg::notify(osg::WARN) << "Warning: Invalid line set. LineProjector::project() failed."< objectLine = new osg::LineSegment; + objectLine->mult(*_line, getLocalToWorld()); + + // Project the objectLine onto the window. + osg::ref_ptr windowLine = new osg::LineSegment; + sv.projectObjectIntoWindow(objectLine->start(), windowLine->start()); + sv.projectObjectIntoWindow(objectLine->end(), windowLine->end()); + + windowLine->start().z() = windowLine->end().z() = 0.0f; + + // Can't project if the line is straight into the screen. + if (!windowLine->valid()) + return false; + + // Compute projection of the point on the windowLine by computing the dot product. + osg::Vec2 windowLineStart(windowLine->start().x(),windowLine->start().y()); + osg::Vec2 windowLineEnd(windowLine->end().x(),windowLine->end().y()); + osg::Vec2 windowLineDirection = windowLineEnd - windowLineStart; + windowLineDirection.normalize(); + float dotProduct = (windowLineDirection) * (pointToProject - windowLineStart); + + // Get the closest point on the windowLine from (x,y). + osg::Vec2 closestWindowPt = windowLineStart + windowLineDirection * dotProduct; + + // Project the closest point back into the scene and into local space. + osg::ref_ptr projectedLocalLine = new osg::LineSegment; + sv.projectWindowXYIntoObject((int)closestWindowPt.x(), (int)closestWindowPt.y(), projectedLocalLine->start(), projectedLocalLine->end()); + projectedLocalLine->mult(*projectedLocalLine, getWorldToLocal()); + + // Find the closest point between _line and projectedLocalLine on _line and that's the result. + osg::Vec3 closestPtLine, closestPtProjWorkingLine; + if (! computeClosestPoints(*_line, *projectedLocalLine, closestPtLine, closestPtProjWorkingLine)) + return false; + + projectedPoint = closestPtLine; + + return true; +} + +PlaneProjector::PlaneProjector() +{ +} + +PlaneProjector::PlaneProjector(const osg::Plane& plane) +{ + _plane = plane; +} + + +PlaneProjector::~PlaneProjector() +{ +} + +bool PlaneProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const +{ + if (!_plane.valid()) + { + osg::notify(osg::WARN) << "Warning: Invalid plane set. PlaneProjector::project() failed."<< std::endl; + return false; + } + + // Get the near and far points for the mouse point. + osg::Vec3 nearPoint, farPoint; + sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint); + + // Transform these points into local coordinates. + osg::Vec3 objectNearPoint, objectFarPoint; + objectNearPoint = nearPoint * getWorldToLocal(); + objectFarPoint = farPoint * getWorldToLocal(); + + // Find the intersection of the plane with the line (formed by the near and far points in local coordinates). + return getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, projectedPoint); +} + + +SphereProjector::SphereProjector() : _sphere(new osg::Sphere), _front(true) +{ +} + +SphereProjector::SphereProjector(osg::Sphere& sphere) : _sphere(&sphere), _front(true) +{ +} + + +SphereProjector::~SphereProjector() +{ +} + +bool SphereProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const +{ + if (!_sphere->valid()) + { + osg::notify(osg::WARN) << "Warning: Invalid sphere. SphereProjector::project() failed." << std::endl; + return false; + } + + // Get the near and far points for the mouse point. + osg::Vec3 nearPoint, farPoint; + sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint); + + // Transform these points into local coordinates. + osg::Vec3 objectNearPoint, objectFarPoint; + objectNearPoint = nearPoint * getWorldToLocal(); + objectFarPoint = farPoint * getWorldToLocal(); + + // Find the intersection of the sphere with the line. + osg::Vec3 dontCare; + if (_front) + return getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, projectedPoint, dontCare); + return getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, dontCare, projectedPoint); +} + +bool SphereProjector::isPointInFront(const osg::Vec3& point, const osgUtil::SceneView& sv, const osg::Matrix& localToWorld) const +{ + osg::Vec3 centerToPoint = getSphere().getCenter() - point; + if (centerToPoint * getEyeDirection(sv.getViewMatrix(), localToWorld) < 0.0) + return false; + return true; +} + + +SpherePlaneProjector::SpherePlaneProjector() +{ +} + +SpherePlaneProjector::SpherePlaneProjector(osg::Sphere& sphere) : SphereProjector(sphere) +{ +} + + +SpherePlaneProjector::~SpherePlaneProjector() +{ +} + +osg::Quat SpherePlaneProjector::getRotation(const osg::Vec3& p1, bool p1OnSphere, const osg::Vec3& p2, bool p2OnSphere, + float radialFactor) const +{ + if (p1OnSphere && p2OnSphere) + { + osg::Quat rotation; + if (_front) + rotation.makeRotate(p1 - getSphere().getCenter(), p2 - getSphere().getCenter()); + else + rotation.makeRotate(p2 - getSphere().getCenter(), p1 - getSphere().getCenter()); + return rotation; + } + else if (!p1OnSphere && !p2OnSphere) + { + osg::Quat rotation; + rotation.makeRotate(p1 - getSphere().getCenter(), p2 - getSphere().getCenter()); + + osg::Vec3 axis; double angle; + rotation.getRotate(angle, axis); + + osg::Vec3 realAxis; + if (axis * _plane.getNormal() > 0.0f) + realAxis = _plane.getNormal(); + else + realAxis = - _plane.getNormal(); + + osg::Quat rollRotation(angle, realAxis); + + osg::Vec3 diff1 = p1 - getSphere().getCenter(); + osg::Vec3 diff2 = p2 - getSphere().getCenter(); + float d = diff2.length() - diff1.length(); + + float theta = d / getSphere().getRadius(); + if (fabs(theta) < 0.000001 || fabs(theta) > 1.0) + return rollRotation; + + diff1.normalize(); + osg::Vec3 pullAxis = diff1 ^ _plane.getNormal(); + pullAxis.normalize(); + osg::Quat pullRotation(radialFactor * theta, pullAxis); + + osg::Quat totalRotation = pullRotation * rollRotation; + return totalRotation; + } + else + { + const osg::Vec3& planePoint = getSphere().getCenter(); + + osg::Vec3 intersection, dontCare; + if (p1OnSphere) + getSphereLineIntersection(getSphere(), p2, planePoint, intersection, dontCare); + else + getSphereLineIntersection(getSphere(), p1, planePoint, intersection, dontCare); + + osg::Quat rotation; + if (p1OnSphere) + rotation.makeRotate(p1 - getSphere().getCenter(), intersection - getSphere().getCenter()); + else + rotation.makeRotate(intersection - getSphere().getCenter(), p2 - getSphere().getCenter()); + return rotation; + } +} + +bool SpherePlaneProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const +{ + if (!_sphere->valid()) + { + osg::notify(osg::WARN) << "Warning: Invalid sphere. SpherePlaneProjector::project() failed." << std::endl; + return false; + } + + // Get the near and far points for the mouse point. + osg::Vec3 nearPoint, farPoint; + sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint); + + // Transform these points into local coordinates. + osg::Vec3 objectNearPoint, objectFarPoint; + objectNearPoint = nearPoint * getWorldToLocal(); + objectFarPoint = farPoint * getWorldToLocal(); + + // Find the intersection of the sphere with the line. + osg::Vec3 sphereIntersection, dontCare; + bool hitSphere = false; + if (_front) + hitSphere = getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, sphereIntersection, dontCare); + else + hitSphere = getSphereLineIntersection(*_sphere, objectNearPoint, objectFarPoint, dontCare, sphereIntersection); + + // Compute plane oriented to the eye. + _plane = computePlaneThruPointAndOrientedToEye(sv.getViewMatrix(), getLocalToWorld(), getSphere().getCenter(), _front); + + // Find the intersection on the plane. + osg::Vec3 planeIntersection; + if (hitSphere) + { + if (! getPlaneLineIntersection(_plane.asVec4(), sphereIntersection, sphereIntersection + _plane.getNormal(), planeIntersection)) + return false; + } + else + { + if (! getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, planeIntersection)) + return false; + } + + // Distance from the plane intersection point to the center of the sphere. + float dist = (planeIntersection - getSphere().getCenter()).length(); + + // If the distance is less that the sphere radius choose the sphere intersection else choose + // the plane intersection. + if (dist < getSphere().getRadius()) + { + if (! hitSphere) return false; + projectedPoint = sphereIntersection; + _onSphere = true; + } + else + { + projectedPoint = planeIntersection; + _onSphere = false; + } + return true; +} + +CylinderProjector::CylinderProjector() : _cylinder(new osg::Cylinder()), _cylinderAxis(0.0,0.0,1.0), _front(true) +{ +} + +CylinderProjector::CylinderProjector(osg::Cylinder& cylinder) : _front(true) +{ + setCylinder(cylinder); +} + +CylinderProjector::~CylinderProjector() +{ +} + +bool CylinderProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const +{ + if (!_cylinder.valid()) + { + osg::notify(osg::WARN) << "Warning: Invalid cylinder. CylinderProjector::project() failed." + << std::endl; + return false; + } + + // Get the near and far points for the mouse point. + osg::Vec3 nearPoint, farPoint; + sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint); + + // Transform these points into local coordinates. + osg::Vec3 objectNearPoint, objectFarPoint; + objectNearPoint = nearPoint * getWorldToLocal(); + objectFarPoint = farPoint * getWorldToLocal(); + + // Find the intersection of the sphere with the line. + osg::Vec3 dontCare; + return getCylinderLineIntersection(*_cylinder, objectNearPoint, objectFarPoint, projectedPoint, dontCare); +} + +bool CylinderProjector::isPointInFront(const osg::Vec3& point, const osgUtil::SceneView& sv, const osg::Matrix& localToWorld) const +{ + osg::Vec3 closestPointOnAxis; + computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis, + point, closestPointOnAxis); + + osg::Vec3 perpPoint = point - closestPointOnAxis; + if (perpPoint * getEyeDirection(sv.getViewMatrix(), localToWorld) < 0.0) + return false; + return true; +} + +CylinderPlaneProjector::CylinderPlaneProjector() +{ +} + +CylinderPlaneProjector::CylinderPlaneProjector(osg::Cylinder& cylinder) : CylinderProjector(cylinder) +{ +} + +CylinderPlaneProjector::~CylinderPlaneProjector() +{ +} + +bool CylinderPlaneProjector::project(const osg::Vec2& pointToProject, const osgUtil::SceneView& sv, osg::Vec3& projectedPoint) const +{ + if (!_cylinder.valid()) + { + osg::notify(osg::WARN) << "Warning: Invalid cylinder. CylinderProjector::project() failed." + << std::endl; + return false; + } + + // Get the near and far points for the mouse point. + osg::Vec3 nearPoint, farPoint; + sv.projectWindowXYIntoObject((int)pointToProject[0],(int)pointToProject[1],nearPoint,farPoint); + + // Transform these points into local coordinates. + osg::Vec3 objectNearPoint, objectFarPoint; + objectNearPoint = nearPoint * getWorldToLocal(); + objectFarPoint = farPoint * getWorldToLocal(); + + // Find the intersection of the sphere with the line. + osg::Vec3 cylIntersection; + bool hitCylinder = false; + if (_front) + { + osg::Vec3 dontCare; + hitCylinder = getCylinderLineIntersection(*_cylinder, objectNearPoint, objectFarPoint, cylIntersection, dontCare); + } + else + { + osg::Vec3 dontCare; + hitCylinder = getCylinderLineIntersection(*_cylinder, objectNearPoint, objectFarPoint, dontCare, cylIntersection); + } + + // Compute plane oriented to the eye. + _plane = computePlaneParallelToAxisAndOrientedToEye(sv.getViewMatrix(), getLocalToWorld(), _cylinderAxis, + getCylinder().getRadius(), _planeLineStart, _planeLineEnd, + _front); + + // Find the intersection on the plane. + osg::Vec3 planeIntersection; + getPlaneLineIntersection(_plane.asVec4(), objectNearPoint, objectFarPoint, planeIntersection); + + if (hitCylinder) + { + osg::Vec3 projectIntersection; + getPlaneLineIntersection(_plane.asVec4(), cylIntersection, cylIntersection + _plane.getNormal(), projectIntersection); + + osg::Vec3 closestPointToCylAxis; + computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis, + projectIntersection, closestPointToCylAxis); + + // Distance from the plane intersection point to the closest point on the cylinder axis. + float dist = (projectIntersection - closestPointToCylAxis).length(); + + if (dist < getCylinder().getRadius()) + { + if (!hitCylinder) return false; + projectedPoint = cylIntersection; + _onCylinder = true; + } + else + { + projectedPoint = planeIntersection; + _onCylinder = false; + } + } + else + { + projectedPoint = planeIntersection; + _onCylinder = false; + } + + return true; +} + +osg::Quat CylinderPlaneProjector::getRotation(const osg::Vec3& p1, bool p1OnCyl, const osg::Vec3& p2, bool p2OnCyl) const +{ + if (p1OnCyl && p2OnCyl) + { + osg::Vec3 closestPointToCylAxis1, closestPointToCylAxis2; + computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis * getCylinder().getHeight(), + p1, closestPointToCylAxis1); + computeClosestPointOnLine(getCylinder().getCenter(), getCylinder().getCenter() + _cylinderAxis * getCylinder().getHeight(), + p2, closestPointToCylAxis2); + + osg::Vec3 v1 = p1 - closestPointToCylAxis1; + osg::Vec3 v2 = p2 - closestPointToCylAxis2; + + float cosAngle = v1 * v2 / (v1.length() * v2.length()); + + if (cosAngle > 1.0 || cosAngle < -1.0) + return osg::Quat(); + + float angle = acosf(cosAngle); + osg::Vec3 rotAxis = v1 ^ v2; + + return osg::Quat(angle, rotAxis); + } + else if (!p1OnCyl && !p2OnCyl) + { + osg::Vec3 closestPointToPlaneLine1, closestPointToPlaneLine2; + computeClosestPointOnLine(_planeLineStart, _planeLineEnd, + p1, closestPointToPlaneLine1); + computeClosestPointOnLine(_planeLineStart, _planeLineEnd, + p2, closestPointToPlaneLine2); + + osg::Vec3 v1 = p1 - closestPointToPlaneLine1; + osg::Vec3 v2 = p2 - closestPointToPlaneLine2; + + osg::Vec3 diff = v2 - v1; + float d = diff.length(); + + float angle = (getCylinder().getRadius() == 0.0) ? 0.0 : (d / getCylinder().getRadius()); + osg::Vec3 rotAxis = _plane.getNormal() ^ v1; + + if (v2.length() > v1.length()) + return osg::Quat(angle, rotAxis); + else + return osg::Quat(-angle, rotAxis); + + } + else + { + osg::Vec3 offCylinderPt = (p1OnCyl) ? p2 : p1; + + osg::Vec3 linePtNearest; + computeClosestPointOnLine(_planeLineStart, _planeLineEnd, + offCylinderPt, linePtNearest); + osg::Vec3 dirToOffCylinderPt = offCylinderPt - linePtNearest; + dirToOffCylinderPt.normalize(); + + osg::Vec3 ptOnCylinder = linePtNearest + dirToOffCylinderPt * getCylinder().getRadius(); + + if (p1OnCyl) + return (getRotation(p1, true, ptOnCylinder, true) * + getRotation(ptOnCylinder, false, p2, false)); + else + return (getRotation(p1, false, ptOnCylinder, false) * + getRotation(ptOnCylinder, true, p2, true)); + } +} diff --git a/src/osgManipulator/RotateCylinderDragger.cpp b/src/osgManipulator/RotateCylinderDragger.cpp new file mode 100644 index 000000000..473eb2892 --- /dev/null +++ b/src/osgManipulator/RotateCylinderDragger.cpp @@ -0,0 +1,160 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include +#include +#include + + +using namespace osgManipulator; + +RotateCylinderDragger::RotateCylinderDragger() +{ + _projector = new CylinderPlaneProjector(); + setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); +} + +RotateCylinderDragger::~RotateCylinderDragger() +{ +} + +bool RotateCylinderDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + switch (ea.getEventType()) + { + // Pick start. + case (osgGA::GUIEventAdapter::PUSH): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::NodePath nodePathToRoot; + computeNodePathToRoot(*this,nodePathToRoot); + osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); + _projector->setLocalToWorld(localToWorld); + + _startLocalToWorld = _projector->getLocalToWorld(); + _startWorldToLocal = _projector->getWorldToLocal(); + + if (_projector->isPointInFront(hitIter->getLocalIntersectPoint(), sv, _startLocalToWorld)) + _projector->setFront(true); + else + _projector->setFront(false); + + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + // Generate the motion command. + osg::ref_ptr cmd = new Rotate3DCommand(); + cmd->setStage(MotionCommand::START); + cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Set color to pick color. + setMaterialColor(_pickColor,*this); + + _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); + _prevRotation = osg::Quat(); + _prevPtOnCylinder = _projector->isProjectionOnCylinder(); + + aa.requestRedraw(); + } + return true; + } + + // Pick move. + case (osgGA::GUIEventAdapter::DRAG): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::Matrix localToWorld = osg::Matrix(_prevRotation) * _startLocalToWorld; + _projector->setLocalToWorld(localToWorld); + + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + osg::Vec3 prevProjectedPoint = _prevWorldProjPt * _projector->getWorldToLocal(); + osg::Quat deltaRotation = _projector->getRotation(prevProjectedPoint, _prevPtOnCylinder, + projectedPoint, _projector->isProjectionOnCylinder()); + osg::Quat rotation = deltaRotation * _prevRotation; + + // Generate the motion command. + osg::ref_ptr cmd = new Rotate3DCommand(); + cmd->setStage(MotionCommand::MOVE); + cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); + cmd->setRotation(rotation); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); + _prevRotation = rotation; + _prevPtOnCylinder = _projector->isProjectionOnCylinder(); + aa.requestRedraw(); + } + return true; + } + + // Pick finish. + case (osgGA::GUIEventAdapter::RELEASE): + { + osg::ref_ptr cmd = new Rotate3DCommand(); + + cmd->setStage(MotionCommand::FINISH); + cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Reset color. + setMaterialColor(_color,*this); + + aa.requestRedraw(); + + return true; + } + default: + return false; + } + return false; +} + +void RotateCylinderDragger::setupDefaultGeometry() +{ + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(const_cast(&_projector->getCylinder()))); + addChild(geode); +} diff --git a/src/osgManipulator/RotateSphereDragger.cpp b/src/osgManipulator/RotateSphereDragger.cpp new file mode 100644 index 000000000..1ea8e0386 --- /dev/null +++ b/src/osgManipulator/RotateSphereDragger.cpp @@ -0,0 +1,162 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include +#include +#include + +#include + +using namespace osgManipulator; + +RotateSphereDragger::RotateSphereDragger() : _prevPtOnSphere(true) +{ + _projector = new SpherePlaneProjector(); + setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); +} + +RotateSphereDragger::~RotateSphereDragger() +{ +} + +bool RotateSphereDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + switch (ea.getEventType()) + { + // Pick start. + case (osgGA::GUIEventAdapter::PUSH): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::NodePath nodePathToRoot; + computeNodePathToRoot(*this,nodePathToRoot); + osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); + _projector->setLocalToWorld(localToWorld); + + _startLocalToWorld = _projector->getLocalToWorld(); + _startWorldToLocal = _projector->getWorldToLocal(); + + if (_projector->isPointInFront(hitIter->getLocalIntersectPoint(), sv, _startLocalToWorld)) + _projector->setFront(true); + else + _projector->setFront(false); + + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + // Generate the motion command. + osg::ref_ptr cmd = new Rotate3DCommand(); + cmd->setStage(MotionCommand::START); + cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Set color to pick color. + setMaterialColor(_pickColor,*this); + + _prevRotation = osg::Quat(); + _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); + _prevPtOnSphere = _projector->isProjectionOnSphere(); + + aa.requestRedraw(); + } + + return true; + } + + // Pick move. + case (osgGA::GUIEventAdapter::DRAG): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::Matrix localToWorld = osg::Matrix(_prevRotation) * _startLocalToWorld; + _projector->setLocalToWorld(localToWorld); + + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + osg::Vec3 prevProjectedPoint = _prevWorldProjPt * _projector->getWorldToLocal(); + osg::Quat deltaRotation = _projector->getRotation(prevProjectedPoint, _prevPtOnSphere, + projectedPoint, _projector->isProjectionOnSphere(),1.0f); + osg::Quat rotation = deltaRotation * _prevRotation; + + // Generate the motion command. + osg::ref_ptr cmd = new Rotate3DCommand(); + cmd->setStage(MotionCommand::MOVE); + cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); + cmd->setRotation(rotation); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + _prevWorldProjPt = projectedPoint * _projector->getLocalToWorld(); + _prevRotation = rotation; + _prevPtOnSphere = _projector->isProjectionOnSphere(); + aa.requestRedraw(); + } + return true; + } + + // Pick finish. + case (osgGA::GUIEventAdapter::RELEASE): + { + osg::ref_ptr cmd = new Rotate3DCommand(); + + cmd->setStage(MotionCommand::FINISH); + cmd->setLocalToWorldAndWorldToLocal(_startLocalToWorld,_startWorldToLocal); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Reset color. + setMaterialColor(_color,*this); + + aa.requestRedraw(); + + return true; + } + default: + return false; + } + return false; +} + +void RotateSphereDragger::setupDefaultGeometry() +{ + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(const_cast(&_projector->getSphere()))); + addChild(geode); +} diff --git a/src/osgManipulator/Scale1DDragger.cpp b/src/osgManipulator/Scale1DDragger.cpp new file mode 100644 index 000000000..68e4cf8a4 --- /dev/null +++ b/src/osgManipulator/Scale1DDragger.cpp @@ -0,0 +1,216 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include +#include +#include +#include + +using namespace osgManipulator; + +namespace +{ + +float computeScale(const osg::Vec3& startProjectedPoint, + const osg::Vec3& projectedPoint, float scaleCenter) +{ + float denom = startProjectedPoint[0] - scaleCenter; + float scale = denom ? (projectedPoint[0] - scaleCenter)/denom : 1.0; + return scale; +} + +} + +Scale1DDragger::Scale1DDragger(ScaleMode scaleMode) : Dragger(), _minScale(0.001), _scaleMode(scaleMode) +{ + _projector = new LineProjector(osg::Vec3(-0.5f,0.0f,0.0f),osg::Vec3(0.5f,0.0f,0.0f)); + setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); +} + +Scale1DDragger::~Scale1DDragger() +{ +} + +bool Scale1DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + switch (ea.getEventType()) + { + // Pick start. + case (osgGA::GUIEventAdapter::PUSH): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::NodePath nodePathToRoot; + computeNodePathToRoot(*this,nodePathToRoot); + osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); + _projector->setLocalToWorld(localToWorld); + + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, _startProjectedPoint)) + { + _scaleCenter = 0.0f; + if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) + { + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _leftHandleNode.get()) + != (*hitIter)._nodePath.end()) + _scaleCenter = _projector->getLineEnd()[0]; + else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _rightHandleNode.get()) + != (*hitIter)._nodePath.end()) + _scaleCenter = _projector->getLineStart()[0]; + } + + // Generate the motion command. + osg::ref_ptr cmd = new Scale1DCommand(); + cmd->setStage(MotionCommand::START); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Set color to pick color. + setMaterialColor(_pickColor,*this); + + aa.requestRedraw(); + } + return true; + } + + // Pick move. + case (osgGA::GUIEventAdapter::DRAG): + { + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + // Generate the motion command. + osg::ref_ptr cmd = new Scale1DCommand(); + + // Compute scale. + float scale = computeScale(_startProjectedPoint,projectedPoint,_scaleCenter); + if (scale < getMinScale()) scale = getMinScale(); + + // Snap the referencePoint to the line start or line end depending on which is closer. + float referencePoint = _startProjectedPoint[0]; + if (fabs(_projector->getLineStart()[0] - referencePoint) < + fabs(_projector->getLineEnd()[0] - referencePoint)) + referencePoint = _projector->getLineStart()[0]; + else + referencePoint = _projector->getLineEnd()[0]; + + cmd->setStage(MotionCommand::MOVE); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + cmd->setScale(scale); + cmd->setScaleCenter(_scaleCenter); + cmd->setReferencePoint(referencePoint); + cmd->setMinScale(getMinScale()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + aa.requestRedraw(); + } + return true; + } + + // Pick finish. + case (osgGA::GUIEventAdapter::RELEASE): + { + osg::ref_ptr cmd = new Scale1DCommand(); + + cmd->setStage(MotionCommand::FINISH); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Reset color. + setMaterialColor(_color,*this); + + aa.requestRedraw(); + + return true; + } + default: + return false; + } + return false; +} + +void Scale1DDragger::setupDefaultGeometry() +{ + // Get the line length and direction. + osg::Vec3 lineDir = _projector->getLineEnd()-_projector->getLineStart(); + float lineLength = lineDir.length(); + lineDir.normalize(); + + osg::Geode* lineGeode = new osg::Geode; + // Create a line. + { + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(2); + (*vertices)[0] = _projector->getLineStart(); + (*vertices)[1] = _projector->getLineEnd(); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); + + lineGeode->addDrawable(geometry); + } + + // Turn of lighting for line and set line width. + lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + osg::LineWidth* linewidth = new osg::LineWidth(); + linewidth->setWidth(2.0f); + lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); + + // Add line and cones to the scene. + addChild(lineGeode); + + // Create a left box. + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(new osg::Box(_projector->getLineStart(), 0.05 * lineLength))); + addChild(geode); + setLeftHandleNode(*geode); + } + + // Create a right box. + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(new osg::Box(_projector->getLineEnd(), 0.05 * lineLength))); + addChild(geode); + setRightHandleNode(*geode); + } +} diff --git a/src/osgManipulator/Scale2DDragger.cpp b/src/osgManipulator/Scale2DDragger.cpp new file mode 100644 index 000000000..450003b20 --- /dev/null +++ b/src/osgManipulator/Scale2DDragger.cpp @@ -0,0 +1,258 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include +#include +#include +#include + +using namespace osgManipulator; + +namespace +{ + +osg::Vec2 computeScale(const osg::Vec3& startProjectedPoint, + const osg::Vec3& projectedPoint, + const osg::Vec2& scaleCenter) +{ + osg::Vec2 scale(1.0,1.0); + if ((startProjectedPoint[0] - scaleCenter[0]) != 0.0) + scale[0] = (projectedPoint[0] - scaleCenter[0])/(startProjectedPoint[0] - scaleCenter[0]); + if ((startProjectedPoint[2] - scaleCenter[1]) != 0.0) + scale[1] = (projectedPoint[2] - scaleCenter[1])/(startProjectedPoint[2] - scaleCenter[1]); + return scale; +} + +} + +Scale2DDragger::Scale2DDragger(ScaleMode scaleMode) : Dragger(), _minScale(0.001,0.001), _scaleMode(scaleMode) +{ + _projector = new PlaneProjector(osg::Plane(0.0,1.0,0.0,0.0)); + setColor(osg::Vec4(0.0, 1.0, 0.0, 1.0)); + setPickColor(osg::Vec4(1.0, 1.0, 0.0, 1.0)); + + _topLeftHandlePosition.set (-0.5,0.5); + _bottomLeftHandlePosition.set (-0.5,-0.5); + _bottomRightHandlePosition.set(0.5,-0.5); + _topRightHandlePosition.set (0.5,0.5); +} + +Scale2DDragger::~Scale2DDragger() +{ +} + +bool Scale2DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + switch (ea.getEventType()) + { + // Pick start. + case (osgGA::GUIEventAdapter::PUSH): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::NodePath nodePathToRoot; + computeNodePathToRoot(*this,nodePathToRoot); + osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); + _projector->setLocalToWorld(localToWorld); + + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, _startProjectedPoint)) + { + _scaleCenter.set(0.0,0.0); + + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _topLeftHandleNode.get()) + != (*hitIter)._nodePath.end()) + { + _referencePoint = _topLeftHandlePosition; + if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) + _scaleCenter = _bottomRightHandlePosition; + } + else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _bottomLeftHandleNode.get()) + != (*hitIter)._nodePath.end()) + { + _referencePoint = _bottomLeftHandlePosition; + if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) + _scaleCenter = _topRightHandlePosition; + } + else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _bottomRightHandleNode.get()) + != (*hitIter)._nodePath.end()) + { + _referencePoint = _bottomRightHandlePosition; + if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) + _scaleCenter = _topLeftHandlePosition; + } + else if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), _topRightHandleNode.get()) + != (*hitIter)._nodePath.end()) + { + _referencePoint = _topRightHandlePosition; + if (_scaleMode == SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT) + _scaleCenter = _bottomLeftHandlePosition; + + } + + // Generate the motion command. + osg::ref_ptr cmd = new Scale2DCommand(); + cmd->setStage(MotionCommand::START); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + cmd->setReferencePoint(_referencePoint); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Set color to pick color. + setMaterialColor(_pickColor,*this); + + aa.requestRedraw(); + } + return true; + } + + // Pick move. + case (osgGA::GUIEventAdapter::DRAG): + { + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + // Compute scale. + osg::Vec2 scale = computeScale(_startProjectedPoint,projectedPoint,_scaleCenter); + + if (scale[0] < getMinScale()[0]) scale[0] = getMinScale()[0]; + if (scale[1] < getMinScale()[1]) scale[1] = getMinScale()[1]; + + // Generate the motion command. + osg::ref_ptr cmd = new Scale2DCommand(); + cmd->setStage(MotionCommand::MOVE); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + cmd->setScale(scale); + cmd->setScaleCenter(_scaleCenter); + cmd->setReferencePoint(_referencePoint); + cmd->setMinScale(getMinScale()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + aa.requestRedraw(); + } + return true; + } + + // Pick finish. + case (osgGA::GUIEventAdapter::RELEASE): + { + osg::ref_ptr cmd = new Scale2DCommand(); + + cmd->setStage(MotionCommand::FINISH); + cmd->setReferencePoint(_referencePoint); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Reset color. + setMaterialColor(_color,*this); + + aa.requestRedraw(); + + return true; + } + default: + return false; + } + return false; +} + +void Scale2DDragger::setupDefaultGeometry() +{ + osg::Geode* lineGeode = new osg::Geode; + // Create a line. + { + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(4); + (*vertices)[0].set(_topLeftHandlePosition[0],0.0,_topLeftHandlePosition[1]); + (*vertices)[1].set(_bottomLeftHandlePosition[0],0.0,_bottomLeftHandlePosition[1]); + (*vertices)[2].set(_bottomRightHandlePosition[0],0.0,_bottomRightHandlePosition[1]); + (*vertices)[3].set(_topRightHandlePosition[0],0.0,_topRightHandlePosition[1]); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,vertices->size())); + + lineGeode->addDrawable(geometry); + } + + // Turn of lighting for line and set line width. + lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + osg::LineWidth* linewidth = new osg::LineWidth(); + linewidth->setWidth(2.0); + lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); + + // Add line and cones to the scene. + addChild(lineGeode); + + // Create a top left box. + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_topLeftHandlePosition[0], + 0.0,_topLeftHandlePosition[1]), 0.05))); + addChild(geode); + setTopLeftHandleNode(*geode); + } + + // Create a bottom left box. + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_bottomLeftHandlePosition[0], + 0.0,_bottomLeftHandlePosition[1]), 0.05))); + addChild(geode); + setBottomLeftHandleNode(*geode); + } + + // Create a bottom right box. + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_bottomRightHandlePosition[0], + 0.0,_bottomRightHandlePosition[1]), 0.05))); + addChild(geode); + setBottomRightHandleNode(*geode); + } + + // Create a top right box. + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(_topRightHandlePosition[0], + 0.0,_topRightHandlePosition[1]), 0.05))); + addChild(geode); + setTopRightHandleNode(*geode); + } +} diff --git a/src/osgManipulator/ScaleAxisDragger.cpp b/src/osgManipulator/ScaleAxisDragger.cpp new file mode 100644 index 000000000..5e19fc476 --- /dev/null +++ b/src/osgManipulator/ScaleAxisDragger.cpp @@ -0,0 +1,101 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include + +#include +#include +#include +#include + +using namespace osgManipulator; + +ScaleAxisDragger::ScaleAxisDragger() +{ + _xDragger = new osgManipulator::Scale1DDragger(); + addChild(_xDragger.get()); + addDragger(_xDragger.get()); + + _yDragger = new osgManipulator::Scale1DDragger(); + addChild(_yDragger.get()); + addDragger(_yDragger.get()); + + _zDragger = new osgManipulator::Scale1DDragger(); + addChild(_zDragger.get()); + addDragger(_zDragger.get()); + + setParentDragger(getParentDragger()); +} + +ScaleAxisDragger::~ScaleAxisDragger() +{ +} + +void ScaleAxisDragger::setupDefaultGeometry() +{ + // Create a line. + osg::Geode* lineGeode = new osg::Geode; + { + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(2); + (*vertices)[0] = osg::Vec3(0.0f,0.0f,0.0f); + (*vertices)[1] = osg::Vec3(1.0f,0.0f,0.0f); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); + + lineGeode->addDrawable(geometry); + } + + // Turn of lighting for line and set line width. + { + osg::LineWidth* linewidth = new osg::LineWidth(); + linewidth->setWidth(2.0f); + lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); + lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + } + + // Add line to all the individual 1D draggers. + _xDragger->addChild(lineGeode); + _yDragger->addChild(lineGeode); + _zDragger->addChild(lineGeode); + + osg::Geode* geode = new osg::Geode; + + // Create a box. + geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(1.0f,0.0f,0.0f), 0.05))); + + // Add geode to all 1D draggers. + _xDragger->addChild(geode); + _yDragger->addChild(geode); + _zDragger->addChild(geode); + + // Rotate Z-axis dragger appropriately. + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); + _zDragger->setMatrix(osg::Matrix(rotation)); + } + + // Rotate Y-axis dragger appropriately. + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); + _yDragger->setMatrix(osg::Matrix(rotation)); + } + + // Send different colors for each dragger. + _xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); + _yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); + _zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); +} diff --git a/src/osgManipulator/Selection.cpp b/src/osgManipulator/Selection.cpp new file mode 100644 index 000000000..6472c1133 --- /dev/null +++ b/src/osgManipulator/Selection.cpp @@ -0,0 +1,95 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include + +#include + +using namespace osgManipulator; + +class FindNodePathToRootVisitor : public osg::NodeVisitor +{ + public: + + osg::NodePath& _nodePathToRoot; + + FindNodePathToRootVisitor(osg::NodePath& np) + : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS), + _nodePathToRoot(np) + {} + + virtual void apply(osg::Node& node) + { + _nodePathToRoot.push_back(&node); + traverse(node); + } +}; + +void osgManipulator::computeNodePathToRoot(osg::Node& node, osg::NodePath& np) +{ + np.clear(); + osg::ref_ptr visitor = new FindNodePathToRootVisitor(np); + node.accept(*visitor); + np.pop_back(); + std::reverse(np.begin(), np.end()); +} + +Selection::Selection() +{ +} + +Selection::~Selection() +{ +} + +bool Selection::receive(const MotionCommand& command) +{ + switch (command.getStage()) + { + case MotionCommand::START: + { + // Save the current matrix + _startMotionMatrix = getMatrix(); + + // Get the LocalToWorld and WorldToLocal matrix for this node. + osg::NodePath nodePathToRoot; + computeNodePathToRoot(*this,nodePathToRoot); + _localToWorld = osg::computeLocalToWorld(nodePathToRoot); + _worldToLocal = osg::Matrix::inverse(_localToWorld); + + return true; + } + case MotionCommand::MOVE: + { + // Transform the command's motion matrix into local motion matrix. + osg::Matrix localMotionMatrix = _localToWorld * command.getWorldToLocal() + * command.getMotionMatrix() + * command.getLocalToWorld() * _worldToLocal; + + // Transform by the localMotionMatrix + setMatrix(localMotionMatrix * _startMotionMatrix); + + return true; + } + case MotionCommand::FINISH: + { + return true; + } + case MotionCommand::NONE: + default: + return false; + } +} + diff --git a/src/osgManipulator/TabBoxDragger.cpp b/src/osgManipulator/TabBoxDragger.cpp new file mode 100644 index 000000000..88b1ef14b --- /dev/null +++ b/src/osgManipulator/TabBoxDragger.cpp @@ -0,0 +1,77 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include + +#include +#include +#include +#include + +using namespace osgManipulator; + +TabBoxDragger::TabBoxDragger() +{ + for (int i=0; i<6; ++i) + { + _planeDraggers.push_back(new TabPlaneDragger()); + addChild(_planeDraggers[i].get()); + addDragger(_planeDraggers[i].get()); + } + + { + _planeDraggers[0]->setMatrix(osg::Matrix::translate(osg::Vec3(0.0,0.5,0.0))); + } + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, -1.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); + _planeDraggers[1]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,-0.5,0.0))); + } + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); + _planeDraggers[2]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,0.0,-0.5))); + } + + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); + _planeDraggers[3]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.0,0.0,0.5))); + } + + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); + _planeDraggers[4]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(-0.5,0.0,0.0))); + } + + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); + _planeDraggers[5]->setMatrix(osg::Matrix(rotation)*osg::Matrix::translate(osg::Vec3(0.5,0.0,0.0))); + } + + setParentDragger(getParentDragger()); +} + +TabBoxDragger::~TabBoxDragger() +{ +} + +void TabBoxDragger::setupDefaultGeometry() +{ + for (unsigned int i=0; i<_planeDraggers.size(); ++i) + _planeDraggers[i]->setupDefaultGeometry(false); +} + +void TabBoxDragger::setPlaneColor(const osg::Vec4& color) +{ + for (unsigned int i=0; i<_planeDraggers.size(); ++i) + _planeDraggers[i]->setPlaneColor(color); +} diff --git a/src/osgManipulator/TabPlaneDragger.cpp b/src/osgManipulator/TabPlaneDragger.cpp new file mode 100644 index 000000000..738056d8c --- /dev/null +++ b/src/osgManipulator/TabPlaneDragger.cpp @@ -0,0 +1,267 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace osgManipulator; + +namespace +{ + +osg::Node* createHandleNode(Scale2DDragger* cornerScaleDragger, float handleScaleFactor, bool twosided) +{ + osg::Vec3Array* vertices = new osg::Vec3Array(4); + (*vertices)[0] = osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0],0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]) * handleScaleFactor; + (*vertices)[1] = osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0],0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]) * handleScaleFactor; + (*vertices)[2] = osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0],0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]) * handleScaleFactor; + (*vertices)[3] = osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0],0.0,cornerScaleDragger->getTopRightHandlePosition()[1]) * handleScaleFactor; + + osg::Geometry* geometry = new osg::Geometry(); + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size())); + + osg::Vec3Array* normals = new osg::Vec3Array; + normals->push_back(osg::Vec3(0.0,1.0,0.0)); + geometry->setNormalArray(normals); + geometry->setNormalBinding(osg::Geometry::BIND_OVERALL); + + osg::Geode* geode = new osg::Geode; + geode->setName("Dragger Handle"); + geode->addDrawable(geometry); + + if (!twosided) + { + osg::CullFace* cullface = new osg::CullFace; + cullface->setMode(osg::CullFace::FRONT); + geode->getOrCreateStateSet()->setAttribute(cullface, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); + geode->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); + } + + geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + return geode; +} + +osg::Node* createHandleScene(const osg::Vec3& pos, osg::Node* handleNode, float handleScaleFactor) +{ + osg::AutoTransform *at = new osg::AutoTransform; + at->setPosition(pos); + at->setPivotPoint(pos * handleScaleFactor); + at->setAutoScaleToScreen(true); + at->addChild(handleNode); + + AntiSquish* as = new AntiSquish; + as->setPivot(pos); + as->addChild(at); + + return as; +} + +void createCornerScaleDraggerGeometry(Scale2DDragger* cornerScaleDragger, osg::Node* handleNode, float handleScaleFactor) +{ + // Create a top left box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0], + 0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]), + handleNode, handleScaleFactor); + cornerScaleDragger->addChild(handleScene); + cornerScaleDragger->setTopLeftHandleNode(*handleScene); + } + + // Create a bottom left box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0], + 0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]), + handleNode, handleScaleFactor); + cornerScaleDragger->addChild(handleScene); + cornerScaleDragger->setBottomLeftHandleNode(*handleScene); + } + + // Create a bottom right box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0], + 0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]), + handleNode, handleScaleFactor); + cornerScaleDragger->addChild(handleScene); + cornerScaleDragger->setBottomRightHandleNode(*handleScene); + } + + // Create a top right box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0], + 0.0,cornerScaleDragger->getTopRightHandlePosition()[1]), + handleNode, handleScaleFactor); + cornerScaleDragger->addChild(handleScene); + cornerScaleDragger->setTopRightHandleNode(*handleScene); + } +} + +void createEdgeScaleDraggerGeometry(Scale1DDragger* horzEdgeScaleDragger, Scale1DDragger* vertEdgeScaleDragger, + osg::Node* handleNode, float handleScaleFactor) +{ + // Create a left box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(horzEdgeScaleDragger->getLeftHandlePosition(),0.0,0.0), + handleNode, handleScaleFactor); + horzEdgeScaleDragger->addChild(handleScene); + horzEdgeScaleDragger->setLeftHandleNode(*handleScene); + } + + // Create a right box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(horzEdgeScaleDragger->getRightHandlePosition(),0.0,0.0), + handleNode, handleScaleFactor); + horzEdgeScaleDragger->addChild(handleScene); + horzEdgeScaleDragger->setRightHandleNode(*handleScene); + } + + // Create a top box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(vertEdgeScaleDragger->getLeftHandlePosition(),0.0,0.0), + handleNode, handleScaleFactor); + vertEdgeScaleDragger->addChild(handleScene); + vertEdgeScaleDragger->setLeftHandleNode(*handleScene); + } + + // Create a bottom box. + { + osg::Node* handleScene = createHandleScene(osg::Vec3(vertEdgeScaleDragger->getRightHandlePosition(),0.0,0.0), + handleNode, handleScaleFactor); + vertEdgeScaleDragger->addChild(handleScene); + vertEdgeScaleDragger->setRightHandleNode(*handleScene); + } + + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); + vertEdgeScaleDragger->setMatrix(osg::Matrix(rotation)); +} + +void createTranslateDraggerGeometry(Scale2DDragger* cornerScaleDragger, TranslatePlaneDragger* translateDragger) +{ + // Create a polygon. + { + osg::Geode* geode = new osg::Geode; + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(4); + (*vertices)[0] = osg::Vec3(cornerScaleDragger->getTopLeftHandlePosition()[0],0.0,cornerScaleDragger->getTopLeftHandlePosition()[1]); + (*vertices)[1] = osg::Vec3(cornerScaleDragger->getBottomLeftHandlePosition()[0],0.0,cornerScaleDragger->getBottomLeftHandlePosition()[1]); + (*vertices)[2] = osg::Vec3(cornerScaleDragger->getBottomRightHandlePosition()[0],0.0,cornerScaleDragger->getBottomRightHandlePosition()[1]); + (*vertices)[3] = osg::Vec3(cornerScaleDragger->getTopRightHandlePosition()[0],0.0,cornerScaleDragger->getTopRightHandlePosition()[1]); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size())); + + osg::Vec3Array* normals = new osg::Vec3Array; + normals->push_back(osg::Vec3(0.0,1.0,0.0)); + geometry->setNormalArray(normals); + geometry->setNormalBinding(osg::Geometry::BIND_OVERALL); + + geode->addDrawable(geometry); + + osg::PolygonMode* polymode = new osg::PolygonMode; + polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); + geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); + + geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + translateDragger->getTranslate2DDragger()->addChild(geode); + } + +} + +} + +TabPlaneDragger::TabPlaneDragger() : _handleScaleFactor(20.0) +{ + _cornerScaleDragger = new Scale2DDragger(Scale2DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT); + addChild(_cornerScaleDragger.get()); + addDragger(_cornerScaleDragger.get()); + + _horzEdgeScaleDragger = new Scale1DDragger(Scale1DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT); + addChild(_horzEdgeScaleDragger.get()); + addDragger(_horzEdgeScaleDragger.get()); + + _vertEdgeScaleDragger = new Scale1DDragger(Scale1DDragger::SCALE_WITH_OPPOSITE_HANDLE_AS_PIVOT); + addChild(_vertEdgeScaleDragger.get()); + addDragger(_vertEdgeScaleDragger.get()); + + _translateDragger = new TranslatePlaneDragger(); + _translateDragger->setColor(osg::Vec4(0.7f, 0.7f, 0.7f, 1.0f)); + addChild(_translateDragger.get()); + addDragger(_translateDragger.get()); + + setParentDragger(getParentDragger()); +} + +TabPlaneDragger::~TabPlaneDragger() +{ +} + +bool TabPlaneDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hl, const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + if (ea.getButtonMask() & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) return false; + + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + // Since the translate plane and the handleNode lie on the same plane the hit could've been on either one. But we + // need to handle the scaling draggers before the translation. Check if the node path has the scaling nodes else + // check for the scaling nodes in next hit. + if (_cornerScaleDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa)) + return true; + if (_horzEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa)) + return true; + if (_vertEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa)) + return true; + + osgUtil::IntersectVisitor::HitList::iterator nextHit = hitIter + 1; + while (nextHit != hl.end()) + { + if (_cornerScaleDragger->handle(pixel_x, pixel_y, sv, hl, nextHit, ea, aa)) + return true; + if (_horzEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, nextHit, ea, aa)) + return true; + if (_vertEdgeScaleDragger->handle(pixel_x, pixel_y, sv, hl, nextHit, ea, aa)) + return true; + ++nextHit; + } + + if (_translateDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa)) + return true; + + return false; +} + +void TabPlaneDragger::setupDefaultGeometry(bool twoSidedHandle) +{ + osg::ref_ptr handleNode = createHandleNode(_cornerScaleDragger.get(), _handleScaleFactor, twoSidedHandle); + + createCornerScaleDraggerGeometry(_cornerScaleDragger.get(), handleNode.get(), _handleScaleFactor); + createEdgeScaleDraggerGeometry(_horzEdgeScaleDragger.get(),_vertEdgeScaleDragger.get(),handleNode.get(),_handleScaleFactor); + createTranslateDraggerGeometry(_cornerScaleDragger.get(), _translateDragger.get()); +} + + diff --git a/src/osgManipulator/TabPlaneTrackballDragger.cpp b/src/osgManipulator/TabPlaneTrackballDragger.cpp new file mode 100644 index 000000000..6df75af33 --- /dev/null +++ b/src/osgManipulator/TabPlaneTrackballDragger.cpp @@ -0,0 +1,48 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace osgManipulator; + +TabPlaneTrackballDragger::TabPlaneTrackballDragger() +{ + _trackballDragger = new TrackballDragger(true); + addChild(_trackballDragger.get()); + addDragger(_trackballDragger.get()); + + _tabPlaneDragger = new TabPlaneDragger(); + addChild(_tabPlaneDragger.get()); + addDragger(_tabPlaneDragger.get()); + + setParentDragger(getParentDragger()); +} + +TabPlaneTrackballDragger::~TabPlaneTrackballDragger() +{ +} + +void TabPlaneTrackballDragger::setupDefaultGeometry() +{ + _trackballDragger->setupDefaultGeometry(); + _tabPlaneDragger->setupDefaultGeometry(); +} diff --git a/src/osgManipulator/TrackballDragger.cpp b/src/osgManipulator/TrackballDragger.cpp new file mode 100644 index 000000000..40a0f80d1 --- /dev/null +++ b/src/osgManipulator/TrackballDragger.cpp @@ -0,0 +1,171 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace osgManipulator; + +namespace +{ + +osg::Geometry* createCircleGeometry(float radius, unsigned int numSegments) +{ + const float angleDelta = 2.0f*osg::PI/(float)numSegments; + const float r = radius; + float angle = 0.0f; + osg::Vec3Array* vertexArray = new osg::Vec3Array(numSegments); + osg::Vec3Array* normalArray = new osg::Vec3Array(numSegments); + for(unsigned int i = 0; i < numSegments; ++i,angle+=angleDelta) + { + float c = cosf(angle); + float s = sinf(angle); + (*vertexArray)[i].set(c*r,s*r,0.0f); + (*normalArray)[i].set(c,s,0.0f); + } + osg::Geometry* geometry = new osg::Geometry(); + geometry->setVertexArray(vertexArray); + geometry->setNormalArray(normalArray); + geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,vertexArray->size())); + return geometry; +} + +} + +TrackballDragger::TrackballDragger(bool useAutoTransform) +{ + if (useAutoTransform) + { + float pixelSize = 50.0f; + osg::MatrixTransform* scaler = new osg::MatrixTransform; + scaler->setMatrix(osg::Matrix::scale(pixelSize, pixelSize, pixelSize)); + + osg::AutoTransform *at = new osg::AutoTransform; + at->setAutoScaleToScreen(true); + at->addChild(scaler); + + AntiSquish* as = new AntiSquish; + as->addChild(at); + addChild(as); + + _xDragger = new RotateCylinderDragger(); + scaler->addChild(_xDragger.get()); + addDragger(_xDragger.get()); + + _yDragger = new RotateCylinderDragger(); + scaler->addChild(_yDragger.get()); + addDragger(_yDragger.get()); + + _zDragger = new RotateCylinderDragger(); + scaler->addChild(_zDragger.get()); + addDragger(_zDragger.get()); + + _xyzDragger = new RotateSphereDragger(); + scaler->addChild(_xyzDragger.get()); + addDragger(_xyzDragger.get()); + } + else + { + _xDragger = new RotateCylinderDragger(); + addChild(_xDragger.get()); + addDragger(_xDragger.get()); + + _yDragger = new RotateCylinderDragger(); + addChild(_yDragger.get()); + addDragger(_yDragger.get()); + + _zDragger = new RotateCylinderDragger(); + addChild(_zDragger.get()); + addDragger(_zDragger.get()); + + _xyzDragger = new RotateSphereDragger(); + addChild(_xyzDragger.get()); + addDragger(_xyzDragger.get()); + } + + setParentDragger(getParentDragger()); +} + +TrackballDragger::~TrackballDragger() +{ +} + +void TrackballDragger::setupDefaultGeometry() +{ + osg::Geode* geode = new osg::Geode; + { + osg::TessellationHints* hints = new osg::TessellationHints; + hints->setCreateTop(false); + hints->setCreateBottom(false); + hints->setCreateBackFace(false); + + osg::Cylinder* cylinder = new osg::Cylinder; + cylinder->setHeight(0.15f); + osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder,hints); + geode->addDrawable(cylinderDrawable); + setDrawableToAlwaysCull(*cylinderDrawable); + geode->addDrawable(createCircleGeometry(1.0f, 25)); + } + + // Draw in line mode. + { + osg::PolygonMode* polymode = new osg::PolygonMode; + polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); + geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); + geode->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); + geode->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(2.0f),osg::StateAttribute::ON); + } + + // Add line to all the individual 1D draggers. + _xDragger->addChild(geode); + _yDragger->addChild(geode); + _zDragger->addChild(geode); + + + // Rotate X-axis dragger appropriately. + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); + _xDragger->setMatrix(osg::Matrix(rotation)); + } + + // Rotate Y-axis dragger appropriately. + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); + _yDragger->setMatrix(osg::Matrix(rotation)); + } + + // Send different colors for each dragger. + _xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); + _yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); + _zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); + + // Add invisible sphere for pick the spherical dragger. + { + osg::Drawable* sphereDrawable = new osg::ShapeDrawable(new osg::Sphere()); + setDrawableToAlwaysCull(*sphereDrawable); + osg::Geode* sphereGeode = new osg::Geode; + sphereGeode->addDrawable(sphereDrawable); + + _xyzDragger->addChild(sphereGeode); + } +} diff --git a/src/osgManipulator/Translate1DDragger.cpp b/src/osgManipulator/Translate1DDragger.cpp new file mode 100644 index 000000000..db6f9a792 --- /dev/null +++ b/src/osgManipulator/Translate1DDragger.cpp @@ -0,0 +1,212 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include +#include +#include +#include + +using namespace osgManipulator; + +Translate1DDragger::Translate1DDragger() : Dragger(), _checkForNodeInNodePath(true) +{ + _projector = new LineProjector; + setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); +} + +Translate1DDragger::Translate1DDragger(const osg::Vec3& s, const osg::Vec3& e) : Dragger(), _checkForNodeInNodePath(true) +{ + _projector = new LineProjector(s,e); + setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); +} + +Translate1DDragger::~Translate1DDragger() +{ +} + +bool Translate1DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList&, const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (_checkForNodeInNodePath) + { + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + } + + switch (ea.getEventType()) + { + // Pick start. + case (osgGA::GUIEventAdapter::PUSH): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::NodePath nodePathToRoot; + computeNodePathToRoot(*this,nodePathToRoot); + osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); + _projector->setLocalToWorld(localToWorld); + + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, _startProjectedPoint)) + { + // Generate the motion command. + osg::ref_ptr cmd = new TranslateInLineCommand(_projector->getLineStart(), + _projector->getLineEnd()); + cmd->setStage(MotionCommand::START); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Set color to pick color. + setMaterialColor(_pickColor,*this); + + aa.requestRedraw(); + } + return true; + } + + // Pick move. + case (osgGA::GUIEventAdapter::DRAG): + { + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + // Generate the motion command. + osg::ref_ptr cmd = new TranslateInLineCommand(_projector->getLineStart(), + _projector->getLineEnd()); + cmd->setStage(MotionCommand::MOVE); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + cmd->setTranslation(projectedPoint - _startProjectedPoint); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + aa.requestRedraw(); + } + return true; + } + + // Pick finish. + case (osgGA::GUIEventAdapter::RELEASE): + { + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + osg::ref_ptr cmd = new TranslateInLineCommand(_projector->getLineStart(), + _projector->getLineEnd()); + + cmd->setStage(MotionCommand::FINISH); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Reset color. + setMaterialColor(_color,*this); + + aa.requestRedraw(); + } + + return true; + } + default: + return false; + } + return false; +} + +void Translate1DDragger::setupDefaultGeometry() +{ + // Get the line length and direction. + osg::Vec3 lineDir = _projector->getLineEnd()-_projector->getLineStart(); + float lineLength = lineDir.length(); + lineDir.normalize(); + + osg::Geode* geode = new osg::Geode; + // Create a left cone. + { + osg::Cone* cone = new osg::Cone (_projector->getLineStart(), 0.025f * lineLength, 0.10f * lineLength); + osg::Quat rotation; + rotation.makeRotate(lineDir, osg::Vec3(0.0f, 0.0f, 1.0f)); + cone->setRotation(rotation); + + geode->addDrawable(new osg::ShapeDrawable(cone)); + } + + // Create a right cone. + { + osg::Cone* cone = new osg::Cone (_projector->getLineEnd(), 0.025f * lineLength, 0.10f * lineLength); + osg::Quat rotation; + rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), lineDir); + cone->setRotation(rotation); + + geode->addDrawable(new osg::ShapeDrawable(cone)); + } + + // Create an invisible cylinder for picking the line. + { + osg::Cylinder* cylinder = new osg::Cylinder ((_projector->getLineStart()+_projector->getLineEnd())/2, 0.015f * lineLength, lineLength); + osg::Quat rotation; + rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), lineDir); + cylinder->setRotation(rotation); + osg::Drawable* cylinderGeom = new osg::ShapeDrawable(cylinder); + + setDrawableToAlwaysCull(*cylinderGeom); + + geode->addDrawable(cylinderGeom); + } + + osg::Geode* lineGeode = new osg::Geode; + // Create a line. + { + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(2); + (*vertices)[0] = _projector->getLineStart(); + (*vertices)[1] = _projector->getLineEnd(); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); + + lineGeode->addDrawable(geometry); + } + + // Turn of lighting for line and set line width. + lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + osg::LineWidth* linewidth = new osg::LineWidth(); + linewidth->setWidth(2.0f); + lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); + + // Add line and cones to the scene. + addChild(lineGeode); + addChild(geode); +} diff --git a/src/osgManipulator/Translate2DDragger.cpp b/src/osgManipulator/Translate2DDragger.cpp new file mode 100644 index 000000000..1a312749e --- /dev/null +++ b/src/osgManipulator/Translate2DDragger.cpp @@ -0,0 +1,227 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include +#include +#include + +#include +#include +#include +#include + +using namespace osgManipulator; + +Translate2DDragger::Translate2DDragger() +{ + _projector = new PlaneProjector(osg::Plane(0.0,1.0,0.0,0.0)); + _polygonOffset = new osg::PolygonOffset(-1.0f,-1.0f); + setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); +} + +Translate2DDragger::Translate2DDragger(const osg::Plane& plane) +{ + _projector = new PlaneProjector(plane); + _polygonOffset = new osg::PolygonOffset(-1.0f,-1.0f); + setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + setPickColor(osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f)); +} + +Translate2DDragger::~Translate2DDragger() +{ +} + +bool Translate2DDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList&, + const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + switch (ea.getEventType()) + { + // Pick start. + case (osgGA::GUIEventAdapter::PUSH): + { + // Get the LocalToWorld matrix for this node and set it for the projector. + osg::NodePath nodePathToRoot; + computeNodePathToRoot(*this,nodePathToRoot); + osg::Matrix localToWorld = osg::computeLocalToWorld(nodePathToRoot); + _projector->setLocalToWorld(localToWorld); + + if (_projector->project(osg::Vec2((float)pixel_x, (float)pixel_y), sv, _startProjectedPoint)) + { + // Generate the motion command. + osg::ref_ptr cmd = new TranslateInPlaneCommand(_projector->getPlane()); + + cmd->setStage(MotionCommand::START); + cmd->setReferencePoint(_startProjectedPoint); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Set color to pick color. + setMaterialColor(_pickColor,*this); + getOrCreateStateSet()->setAttributeAndModes(_polygonOffset.get(), osg::StateAttribute::ON); + + aa.requestRedraw(); + } + return true; + } + + // Pick move. + case (osgGA::GUIEventAdapter::DRAG): + { + osg::Vec3 projectedPoint; + if (_projector->project(osg::Vec2(pixel_x, pixel_y), sv, projectedPoint)) + { + // Generate the motion command. + osg::ref_ptr cmd = new TranslateInPlaneCommand(_projector->getPlane()); + + cmd->setStage(MotionCommand::MOVE); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + cmd->setTranslation(projectedPoint - _startProjectedPoint); + cmd->setReferencePoint(_startProjectedPoint); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + aa.requestRedraw(); + } + return true; + } + + // Pick finish. + case (osgGA::GUIEventAdapter::RELEASE): + { + osg::ref_ptr cmd = new TranslateInPlaneCommand(_projector->getPlane()); + + cmd->setStage(MotionCommand::FINISH); + cmd->setReferencePoint(_startProjectedPoint); + cmd->setLocalToWorldAndWorldToLocal(_projector->getLocalToWorld(),_projector->getWorldToLocal()); + + // Dispatch command. + if (_commandManager) + { + _commandManager->addSelectionsToCommand(*cmd, *getParentDragger()); + _commandManager->dispatch(*cmd); + } + + // Reset color. + setMaterialColor(_color,*this); + getOrCreateStateSet()->removeAttribute(_polygonOffset.get()); + + aa.requestRedraw(); + + return true; + } + default: + return false; + } + return false; +} + +void Translate2DDragger::setupDefaultGeometry() +{ + // Create a line. + osg::Geode* lineGeode = new osg::Geode; + { + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(2); + (*vertices)[0] = osg::Vec3(0.0f,0.0f,-0.5f); + (*vertices)[1] = osg::Vec3(0.0f,0.0f,0.5f); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); + + lineGeode->addDrawable(geometry); + } + + // Turn of lighting for line and set line width. + osg::LineWidth* linewidth = new osg::LineWidth(); + linewidth->setWidth(2.0f); + lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); + lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + osg::Geode* geode = new osg::Geode; + + // Create left cone. + { + osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, -0.5f), 0.025f, 0.10f); + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f,0.0f,-1.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); + cone->setRotation(rotation); + geode->addDrawable(new osg::ShapeDrawable(cone)); + } + + // Create right cone. + { + osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, 0.5f), 0.025f, 0.10f); + geode->addDrawable(new osg::ShapeDrawable(cone)); + } + + // Create an invisible cylinder for picking the line. + { + osg::Cylinder* cylinder = new osg::Cylinder (osg::Vec3(0.0f,0.0f,0.0f), 0.015f, 1.0f); + osg::Drawable* drawable = new osg::ShapeDrawable(cylinder); + setDrawableToAlwaysCull(*drawable); + geode->addDrawable(drawable); + } + + // MatrixTransform to rotate the geometry according to the normal of the plane. + osg::MatrixTransform* xform = new osg::MatrixTransform; + + // Create an arrow in the X axis. + { + osg::MatrixTransform* arrow = new osg::MatrixTransform; + arrow->addChild(lineGeode); + arrow->addChild(geode); + + // Rotate X-axis arrow appropriately. + osg::Quat rotation; rotation.makeRotate(osg::Vec3(1.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 1.0f)); + arrow->setMatrix(osg::Matrix(rotation)); + + xform->addChild(arrow); + } + + // Create an arrow in the Z axis. + { + osg::Group* arrow = new osg::Group; + arrow->addChild(lineGeode); + arrow->addChild(geode); + + xform->addChild(arrow); + } + + // Rotate the xform so that the geometry lies on the plane. + { + osg::Vec3 normal = _projector->getPlane().getNormal(); normal.normalize(); + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 1.0f, 0.0f), normal); + xform->setMatrix(osg::Matrix(rotation)); + } + + addChild(xform); +} diff --git a/src/osgManipulator/TranslateAxisDragger.cpp b/src/osgManipulator/TranslateAxisDragger.cpp new file mode 100644 index 000000000..83ba064b3 --- /dev/null +++ b/src/osgManipulator/TranslateAxisDragger.cpp @@ -0,0 +1,112 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include + +#include +#include +#include +#include + +using namespace osgManipulator; + +TranslateAxisDragger::TranslateAxisDragger() +{ + _xDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0)); + addChild(_xDragger.get()); + addDragger(_xDragger.get()); + + _yDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0)); + addChild(_yDragger.get()); + addDragger(_yDragger.get()); + + _zDragger = new Translate1DDragger(osg::Vec3(0.0,0.0,0.0), osg::Vec3(0.0,0.0,1.0)); + addChild(_zDragger.get()); + addDragger(_zDragger.get()); + + setParentDragger(getParentDragger()); +} + +TranslateAxisDragger::~TranslateAxisDragger() +{ +} + +void TranslateAxisDragger::setupDefaultGeometry() +{ + // Create a line. + osg::Geode* lineGeode = new osg::Geode; + { + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(2); + (*vertices)[0] = osg::Vec3(0.0f,0.0f,0.0f); + (*vertices)[1] = osg::Vec3(0.0f,0.0f,1.0f); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); + + lineGeode->addDrawable(geometry); + } + + // Turn of lighting for line and set line width. + { + osg::LineWidth* linewidth = new osg::LineWidth(); + linewidth->setWidth(2.0f); + lineGeode->getOrCreateStateSet()->setAttributeAndModes(linewidth, osg::StateAttribute::ON); + lineGeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + } + + // Add line to all the individual 1D draggers. + _xDragger->addChild(lineGeode); + _yDragger->addChild(lineGeode); + _zDragger->addChild(lineGeode); + + osg::Geode* geode = new osg::Geode; + + // Create a cone. + { + osg::Cone* cone = new osg::Cone (osg::Vec3(0.0f, 0.0f, 1.0f), 0.025f, 0.10f); + geode->addDrawable(new osg::ShapeDrawable(cone)); + } + + // Create an invisible cylinder for picking the line. + { + osg::Cylinder* cylinder = new osg::Cylinder (osg::Vec3(0.0f,0.0f,0.5f), 0.015f, 1.0f); + osg::Drawable* geometry = new osg::ShapeDrawable(cylinder); + setDrawableToAlwaysCull(*geometry); + geode->addDrawable(geometry); + } + + // Add geode to all 1D draggers. + _xDragger->addChild(geode); + _yDragger->addChild(geode); + _zDragger->addChild(geode); + + // Rotate X-axis dragger appropriately. + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(1.0f, 0.0f, 0.0f)); + _xDragger->setMatrix(osg::Matrix(rotation)); + } + + // Rotate Y-axis dragger appropriately. + { + osg::Quat rotation; rotation.makeRotate(osg::Vec3(0.0f, 0.0f, 1.0f), osg::Vec3(0.0f, 1.0f, 0.0f)); + _yDragger->setMatrix(osg::Matrix(rotation)); + } + + // Send different colors for each dragger. + _xDragger->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); + _yDragger->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); + _zDragger->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); +} diff --git a/src/osgManipulator/TranslatePlaneDragger.cpp b/src/osgManipulator/TranslatePlaneDragger.cpp new file mode 100644 index 000000000..b324ba796 --- /dev/null +++ b/src/osgManipulator/TranslatePlaneDragger.cpp @@ -0,0 +1,108 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace osgManipulator; + +TranslatePlaneDragger::TranslatePlaneDragger() : _usingTranslate1DDragger(false) +{ + _translate2DDragger = new Translate2DDragger(); + _translate2DDragger->setColor(osg::Vec4(0.7f, 0.7f, 0.7f, 1.0f)); + addChild(_translate2DDragger.get()); + addDragger(_translate2DDragger.get()); + + _translate1DDragger = new Translate1DDragger(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(0.0f,1.0f,0.0f)); + _translate1DDragger->setCheckForNodeInNodePath(false); + addChild(_translate1DDragger.get()); + addDragger(_translate1DDragger.get()); + + setParentDragger(getParentDragger()); +} + +TranslatePlaneDragger::~TranslatePlaneDragger() +{ +} + +bool TranslatePlaneDragger::handle(int pixel_x, int pixel_y, const osgUtil::SceneView& sv, + const osgUtil::IntersectVisitor::HitList& hl, + const osgUtil::IntersectVisitor::HitList::iterator& hitIter, + const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) +{ + // Check if the dragger node is in the nodepath. + if (std::find((*hitIter)._nodePath.begin(), (*hitIter)._nodePath.end(), this) == (*hitIter)._nodePath.end()) + return false; + + if ((ea.getButtonMask() & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) && + ea.getEventType() == osgGA::GUIEventAdapter::PUSH) + _usingTranslate1DDragger = true; + + bool handled = false; + if (_usingTranslate1DDragger) + { + if (_translate1DDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa)) + handled = true; + } + else + { + if (_translate2DDragger->handle(pixel_x, pixel_y, sv, hl, hitIter, ea, aa)) + handled = true; + } + + if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) + _usingTranslate1DDragger = false; + + return handled; +} + +void TranslatePlaneDragger::setupDefaultGeometry() +{ + // Create a polygon. + { + osg::Geode* geode = new osg::Geode; + osg::Geometry* geometry = new osg::Geometry(); + + osg::Vec3Array* vertices = new osg::Vec3Array(4); + (*vertices)[0] = osg::Vec3(-0.5,0.0,0.5); + (*vertices)[1] = osg::Vec3(-0.5,0.0,-0.5); + (*vertices)[2] = osg::Vec3(0.5,0.0,-0.5); + (*vertices)[3] = osg::Vec3(0.5,0.0,0.5); + + geometry->setVertexArray(vertices); + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size())); + + osg::Vec3Array* normals = new osg::Vec3Array; + normals->push_back(osg::Vec3(0.0,1.0,0.0)); + geometry->setNormalArray(normals); + geometry->setNormalBinding(osg::Geometry::BIND_OVERALL); + + geode->addDrawable(geometry); + + osg::PolygonMode* polymode = new osg::PolygonMode; + polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); + geode->getOrCreateStateSet()->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); + + geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + _translate2DDragger->addChild(geode); + } +}