1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include "oglwindow.hxx"
11 #include <cppuhelper/supportsservice.hxx>
13 using namespace com::sun::star
;
14 using namespace libgltf
;
16 namespace avmedia
{ namespace ogl
{
18 OGLWindow::OGLWindow( glTFHandle
& rHandle
, const rtl::Reference
<OpenGLContext
> &rContext
, vcl::Window
& rEventHandlerParent
)
19 : m_rHandle( rHandle
)
20 , m_xContext( rContext
)
21 , m_rEventHandler( rEventHandlerParent
)
22 , m_bVisible ( false )
23 , m_aLastMousePos(Point(0,0))
24 , m_bIsOrbitMode( false )
28 OGLWindow::~OGLWindow()
33 void SAL_CALL
OGLWindow::update()
35 m_xContext
->makeCurrent();
36 int nRet
= gltf_prepare_renderer(&m_rHandle
);
39 SAL_WARN("avmedia.opengl", "Error occurred while preparing for rendering! Error code: " << nRet
);
42 gltf_renderer(&m_rHandle
);
43 gltf_complete_renderer(&m_rHandle
);
44 m_xContext
->swapBuffers();
47 sal_Bool SAL_CALL
OGLWindow::setZoomLevel( css::media::ZoomLevel
/*eZoomLevel*/ )
52 css::media::ZoomLevel SAL_CALL
OGLWindow::getZoomLevel()
54 return media::ZoomLevel_ORIGINAL
;
57 void SAL_CALL
OGLWindow::setPointerType( sal_Int32
)
61 OUString SAL_CALL
OGLWindow::getImplementationName()
63 return OUString("com.sun.star.comp.avmedia.Window_OpenGL");
66 sal_Bool SAL_CALL
OGLWindow::supportsService( const OUString
& rServiceName
)
68 return cppu::supportsService(this, rServiceName
);
71 uno::Sequence
< OUString
> SAL_CALL
OGLWindow::getSupportedServiceNames()
73 return { "com.sun.star.media.Window_OpenGL" };
76 void SAL_CALL
OGLWindow::dispose()
78 assert(m_rEventHandler
.GetParent());
79 m_rEventHandler
.GetParent()->RemoveEventListener( LINK(this, OGLWindow
, FocusGrabber
));
80 m_rEventHandler
.RemoveEventListener( LINK(this, OGLWindow
, CameraHandler
));
83 void SAL_CALL
OGLWindow::addEventListener( const uno::Reference
< lang::XEventListener
>& )
87 void SAL_CALL
OGLWindow::removeEventListener( const uno::Reference
< lang::XEventListener
>& )
91 void SAL_CALL
OGLWindow::setPosSize( sal_Int32 nX
, sal_Int32 nY
, sal_Int32 nWidth
, sal_Int32 nHeight
, sal_Int16
/*nFlags*/ )
93 if( m_rHandle
.viewport
.x
!= nX
|| m_rHandle
.viewport
.x
!= nY
||
94 m_rHandle
.viewport
.width
!= nWidth
|| m_rHandle
.viewport
.height
!= nHeight
)
96 m_xContext
->setWinSize(Size(nWidth
,nHeight
));
97 m_rHandle
.viewport
.x
= nX
;
98 m_rHandle
.viewport
.y
= nY
;
99 m_rHandle
.viewport
.width
= nWidth
;
100 m_rHandle
.viewport
.height
= nHeight
;
104 awt::Rectangle SAL_CALL
OGLWindow::getPosSize()
106 return awt::Rectangle(m_rHandle
.viewport
.x
, m_rHandle
.viewport
.y
,
107 m_rHandle
.viewport
.width
, m_rHandle
.viewport
.height
);
110 void SAL_CALL
OGLWindow::setVisible( sal_Bool bSet
)
112 assert(m_rEventHandler
.GetParent());
113 if( bSet
&& !m_bVisible
)
115 m_rEventHandler
.GetParent()->AddEventListener( LINK(this, OGLWindow
, FocusGrabber
));
116 m_rEventHandler
.AddEventListener( LINK(this, OGLWindow
, CameraHandler
));
117 m_rEventHandler
.GrabFocus();
121 m_rEventHandler
.GetParent()->RemoveEventListener( LINK(this, OGLWindow
, FocusGrabber
));
122 m_rEventHandler
.RemoveEventListener( LINK(this, OGLWindow
, CameraHandler
));
127 void SAL_CALL
OGLWindow::setEnable( sal_Bool
)
131 void SAL_CALL
OGLWindow::setFocus()
135 void SAL_CALL
OGLWindow::addWindowListener( const uno::Reference
< awt::XWindowListener
>& )
139 void SAL_CALL
OGLWindow::removeWindowListener( const uno::Reference
< awt::XWindowListener
>& )
143 void SAL_CALL
OGLWindow::addFocusListener( const uno::Reference
< awt::XFocusListener
>& )
147 void SAL_CALL
OGLWindow::removeFocusListener( const uno::Reference
< awt::XFocusListener
>& )
151 void SAL_CALL
OGLWindow::addKeyListener( const uno::Reference
< awt::XKeyListener
>& )
155 void SAL_CALL
OGLWindow::removeKeyListener( const uno::Reference
< awt::XKeyListener
>& )
159 void SAL_CALL
OGLWindow::addMouseListener( const uno::Reference
< awt::XMouseListener
>& )
163 void SAL_CALL
OGLWindow::removeMouseListener( const uno::Reference
< awt::XMouseListener
>& )
167 void SAL_CALL
OGLWindow::addMouseMotionListener( const uno::Reference
< awt::XMouseMotionListener
>& )
171 void SAL_CALL
OGLWindow::removeMouseMotionListener( const uno::Reference
< awt::XMouseMotionListener
>& )
175 void SAL_CALL
OGLWindow::addPaintListener( const uno::Reference
< awt::XPaintListener
>& )
179 void SAL_CALL
OGLWindow::removePaintListener( const uno::Reference
< awt::XPaintListener
>& )
183 IMPL_LINK(OGLWindow
, FocusGrabber
, VclWindowEvent
&, rEvent
, void)
185 if( rEvent
.GetId() == VclEventId::WindowMouseMove
)
187 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(rEvent
.GetData());
190 const Point
& rMousePos
= pMouseEvt
->GetPosPixel();
191 const tools::Rectangle
aWinRect(m_rEventHandler
.GetPosPixel(),m_rEventHandler
.GetSizePixel());
192 // Grab focus to the OpenGL window when mouse pointer is over it
193 if( aWinRect
.IsInside(rMousePos
) )
195 if ( !m_rEventHandler
.HasFocus() )
197 m_rEventHandler
.GrabFocus();
200 // Move focus to the document when mouse is not over the OpenGL window
201 else if ( m_rEventHandler
.HasFocus() )
203 m_rEventHandler
.GrabFocusToDocument();
209 IMPL_LINK(OGLWindow
, CameraHandler
, VclWindowEvent
&, rEvent
, void)
211 if( rEvent
.GetId() == VclEventId::WindowKeyInput
)
213 KeyEvent
* pKeyEvt
= static_cast<KeyEvent
*>(rEvent
.GetData());
216 const sal_uInt16 nCode
= pKeyEvt
->GetKeyCode().GetCode();
217 if (nCode
== KEY_Q
|| nCode
== KEY_E
||
218 nCode
== KEY_A
|| nCode
== KEY_D
||
219 nCode
== KEY_W
|| nCode
== KEY_S
)
221 // Calculate movement
227 gltf_get_camera_pos(&m_rHandle
, &vEye
,&vView
,&vUp
);
228 float fModelSize
=(float)gltf_get_model_size(&m_rHandle
);
230 glm::vec3 vMove
= vView
-vEye
;
231 vMove
= glm::normalize(vMove
);
233 glm::vec3 vStrafe
= glm::cross(vMove
, vUp
);
234 vStrafe
= glm::normalize(vStrafe
);
236 glm::vec3 vMup
= vUp
* 25.0f
;
238 if( !m_bIsOrbitMode
)
240 if(nCode
== KEY_E
)vMoveBy
+= vMup
*(0.0005f
*fModelSize
);
241 if(nCode
== KEY_Q
)vMoveBy
-= vMup
*(0.0005f
*fModelSize
);
242 if(nCode
== KEY_W
)vMoveBy
+= vMove
*(0.0005f
*fModelSize
);
243 if(nCode
== KEY_S
)vMoveBy
-= vMove
*(0.0005f
*fModelSize
);
244 if(nCode
== KEY_A
)vMoveBy
-= vStrafe
*(0.0005f
*fModelSize
);
245 if(nCode
== KEY_D
)vMoveBy
+= vStrafe
*(0.0005f
*fModelSize
);
249 bool bZoomIn
= false;
250 bool bZoomOut
= false;
253 vMoveBy
+= vMove
*(0.0005f
*fModelSize
);
258 vMoveBy
-= vMove
*(0.0005f
*fModelSize
);
262 // Limit zooming in orbit mode
263 float fCameraDistFromModelGlobe
= glm::length(vEye
+ vMoveBy
- vView
) - fModelSize
/ 2.0f
;
264 if ((fCameraDistFromModelGlobe
< 0.5 * fModelSize
&& bZoomIn
) ||
265 (fCameraDistFromModelGlobe
> 2 * fModelSize
&& bZoomOut
))
267 vMoveBy
= glm::vec3(0.0);
271 gltf_renderer_move_camera(&m_rHandle
, vMoveBy
.x
, vMoveBy
.y
, vMoveBy
.z
, 0.0001);
293 float fSensitivity
= 50.0;
294 gltf_renderer_rotate_model(&m_rHandle
, nDeltaX
*fSensitivity
, nDeltaY
*fSensitivity
, 0.0);
297 else if(nCode
== KEY_M
)
301 gltf_orbit_mode_stop(&m_rHandle
);
302 m_bIsOrbitMode
= false;
306 gltf_orbit_mode_start(&m_rHandle
);
307 m_bIsOrbitMode
= true;
310 else if(nCode
== KEY_F
)
312 gltf_render_FPS_enable(&m_rHandle
);
316 else if( rEvent
.GetId() == VclEventId::WindowMouseButtonDown
)
318 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(rEvent
.GetData());
319 if(pMouseEvt
&& pMouseEvt
->IsLeft() && pMouseEvt
->GetClicks() == 1)
321 m_aLastMousePos
= pMouseEvt
->GetPosPixel();
324 else if( rEvent
.GetId() == VclEventId::WindowMouseMove
)
326 if ( !m_rEventHandler
.HasFocus() )
328 m_rEventHandler
.GrabFocus();
330 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(rEvent
.GetData());
331 if(pMouseEvt
&& pMouseEvt
->IsLeft() && m_aLastMousePos
!= Point(0,0))
333 const Point
& aCurPos
= pMouseEvt
->GetPosPixel();
334 float fSensitivity
= std::min(m_rHandle
.viewport
.width
, m_rHandle
.viewport
.height
);
335 if (fSensitivity
== 0.0)
338 fSensitivity
= 540.0 / fSensitivity
;
341 long nDeltaX
= m_aLastMousePos
.X()-aCurPos
.X();
342 long nDeltaY
= m_aLastMousePos
.Y()-aCurPos
.Y();
346 gltf_renderer_rotate_model(&m_rHandle
, (float)nDeltaX
*fSensitivity
, (float)nDeltaY
*fSensitivity
, 0.0);
350 // Filter out too small deltas to avoid rewrite rotation parameter with 0
351 // before rotation is done
352 if( nDeltaX
!= 0 || nDeltaY
!= 0 )
353 gltf_renderer_rotate_camera(&m_rHandle
, (float)nDeltaX
*fSensitivity
, (float)nDeltaY
*fSensitivity
, 0.0);
355 m_aLastMousePos
= aCurPos
;
358 else if( rEvent
.GetId() == VclEventId::WindowMouseButtonUp
)
360 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(rEvent
.GetData());
361 if(pMouseEvt
&& pMouseEvt
->IsLeft() && pMouseEvt
->GetClicks() == 1)
363 m_aLastMousePos
= Point(0,0);
369 } // namespace avmedia
371 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */