Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : */
9 :
10 : #include "oglwindow.hxx"
11 : #include <cppuhelper/supportsservice.hxx>
12 :
13 : using namespace com::sun::star;
14 : using namespace libgltf;
15 :
16 : namespace avmedia { namespace ogl {
17 :
18 0 : OGLWindow::OGLWindow( glTFHandle& rHandle, OpenGLContext& rContext, vcl::Window& rEventHandlerParent )
19 : : m_rHandle( rHandle )
20 : , m_rContext( rContext )
21 : , m_rEventHandler( rEventHandlerParent )
22 : , m_bVisible ( false )
23 : , m_aLastMousePos(Point(0,0))
24 0 : , m_bIsOrbitMode( false )
25 : {
26 0 : }
27 :
28 0 : OGLWindow::~OGLWindow()
29 : {
30 0 : dispose();
31 0 : }
32 :
33 0 : void SAL_CALL OGLWindow::update() throw (css::uno::RuntimeException, std::exception)
34 : {
35 0 : m_rContext.makeCurrent();
36 0 : int nRet = gltf_prepare_renderer(&m_rHandle);
37 0 : if( nRet != 0 )
38 : {
39 : SAL_WARN("avmedia.opengl", "Error occurred while preparing for rendering! Error code: " << nRet);
40 0 : return;
41 : }
42 0 : gltf_renderer(&m_rHandle);
43 0 : gltf_complete_renderer(&m_rHandle);
44 0 : m_rContext.swapBuffers();
45 : }
46 :
47 0 : sal_Bool SAL_CALL OGLWindow::setZoomLevel( css::media::ZoomLevel /*eZoomLevel*/ ) throw (css::uno::RuntimeException, std::exception)
48 : {
49 0 : return false;
50 : }
51 :
52 0 : css::media::ZoomLevel SAL_CALL OGLWindow::getZoomLevel() throw (css::uno::RuntimeException, std::exception)
53 : {
54 0 : return media::ZoomLevel_ORIGINAL;
55 : }
56 :
57 0 : void SAL_CALL OGLWindow::setPointerType( sal_Int32 ) throw (css::uno::RuntimeException, std::exception)
58 : {
59 0 : }
60 :
61 0 : OUString SAL_CALL OGLWindow::getImplementationName() throw (css::uno::RuntimeException, std::exception)
62 : {
63 0 : return OUString("com.sun.star.comp.avmedia.Window_OpenGL");
64 : }
65 :
66 0 : sal_Bool SAL_CALL OGLWindow::supportsService( const OUString& rServiceName ) throw (css::uno::RuntimeException, std::exception)
67 : {
68 0 : return cppu::supportsService(this, rServiceName);
69 : }
70 :
71 0 : uno::Sequence< OUString > SAL_CALL OGLWindow::getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception)
72 : {
73 0 : uno::Sequence< OUString > aRet(1);
74 0 : aRet[0] = "com.sun.star.media.Window_OpenGL";
75 0 : return aRet;
76 : }
77 :
78 0 : void SAL_CALL OGLWindow::dispose() throw (uno::RuntimeException, std::exception)
79 : {
80 : assert(m_rEventHandler.GetParent());
81 0 : m_rEventHandler.GetParent()->RemoveEventListener( LINK(this, OGLWindow, FocusGrabber));
82 0 : m_rEventHandler.RemoveEventListener( LINK(this, OGLWindow, CameraHandler));
83 0 : }
84 :
85 0 : void SAL_CALL OGLWindow::addEventListener( const uno::Reference< lang::XEventListener >& )
86 : throw (uno::RuntimeException, std::exception)
87 : {
88 0 : }
89 :
90 0 : void SAL_CALL OGLWindow::removeEventListener( const uno::Reference< lang::XEventListener >& )
91 : throw (uno::RuntimeException, std::exception)
92 : {
93 0 : }
94 :
95 0 : void SAL_CALL OGLWindow::setPosSize( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int16 /*nFlags*/ )
96 : throw (uno::RuntimeException, std::exception)
97 : {
98 0 : if( m_rHandle.viewport.x != nX || m_rHandle.viewport.x != nY ||
99 0 : m_rHandle.viewport.width != nWidth || m_rHandle.viewport.height != nHeight )
100 : {
101 0 : m_rContext.setWinSize(Size(nWidth,nHeight));
102 0 : m_rHandle.viewport.x = nX;
103 0 : m_rHandle.viewport.y = nY;
104 0 : m_rHandle.viewport.width = nWidth;
105 0 : m_rHandle.viewport.height = nHeight;
106 : }
107 0 : }
108 :
109 0 : awt::Rectangle SAL_CALL OGLWindow::getPosSize()
110 : throw (uno::RuntimeException, std::exception)
111 : {
112 : return awt::Rectangle(m_rHandle.viewport.x, m_rHandle.viewport.y,
113 0 : m_rHandle.viewport.width, m_rHandle.viewport.height);
114 : }
115 :
116 0 : void SAL_CALL OGLWindow::setVisible( sal_Bool bSet )
117 : throw (uno::RuntimeException, std::exception)
118 : {
119 : assert(m_rEventHandler.GetParent());
120 0 : if( bSet && !m_bVisible )
121 : {
122 0 : m_rEventHandler.GetParent()->AddEventListener( LINK(this, OGLWindow, FocusGrabber));
123 0 : m_rEventHandler.AddEventListener( LINK(this, OGLWindow, CameraHandler));
124 0 : m_rEventHandler.GrabFocus();
125 : }
126 0 : else if( !bSet )
127 : {
128 0 : m_rEventHandler.GetParent()->RemoveEventListener( LINK(this, OGLWindow, FocusGrabber));
129 0 : m_rEventHandler.RemoveEventListener( LINK(this, OGLWindow, CameraHandler));
130 : }
131 0 : m_bVisible = bSet;
132 0 : }
133 :
134 0 : void SAL_CALL OGLWindow::setEnable( sal_Bool )
135 : throw (uno::RuntimeException, std::exception)
136 : {
137 0 : }
138 :
139 0 : void SAL_CALL OGLWindow::setFocus()
140 : throw (uno::RuntimeException, std::exception)
141 : {
142 0 : }
143 :
144 0 : void SAL_CALL OGLWindow::addWindowListener( const uno::Reference< awt::XWindowListener >& )
145 : throw (uno::RuntimeException, std::exception)
146 : {
147 0 : }
148 :
149 0 : void SAL_CALL OGLWindow::removeWindowListener( const uno::Reference< awt::XWindowListener >& )
150 : throw (uno::RuntimeException, std::exception)
151 : {
152 0 : }
153 :
154 0 : void SAL_CALL OGLWindow::addFocusListener( const uno::Reference< awt::XFocusListener >& )
155 : throw (uno::RuntimeException, std::exception)
156 : {
157 0 : }
158 :
159 0 : void SAL_CALL OGLWindow::removeFocusListener( const uno::Reference< awt::XFocusListener >& )
160 : throw (uno::RuntimeException, std::exception)
161 : {
162 0 : }
163 :
164 0 : void SAL_CALL OGLWindow::addKeyListener( const uno::Reference< awt::XKeyListener >& )
165 : throw (uno::RuntimeException, std::exception)
166 : {
167 0 : }
168 :
169 0 : void SAL_CALL OGLWindow::removeKeyListener( const uno::Reference< awt::XKeyListener >& )
170 : throw (uno::RuntimeException, std::exception)
171 : {
172 0 : }
173 :
174 0 : void SAL_CALL OGLWindow::addMouseListener( const uno::Reference< awt::XMouseListener >& )
175 : throw (uno::RuntimeException, std::exception)
176 : {
177 0 : }
178 :
179 0 : void SAL_CALL OGLWindow::removeMouseListener( const uno::Reference< awt::XMouseListener >& )
180 : throw (uno::RuntimeException, std::exception)
181 : {
182 0 : }
183 :
184 0 : void SAL_CALL OGLWindow::addMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& )
185 : throw (uno::RuntimeException, std::exception)
186 : {
187 0 : }
188 :
189 0 : void SAL_CALL OGLWindow::removeMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& )
190 : throw (uno::RuntimeException, std::exception)
191 : {
192 0 : }
193 :
194 0 : void SAL_CALL OGLWindow::addPaintListener( const uno::Reference< awt::XPaintListener >& )
195 : throw (uno::RuntimeException, std::exception)
196 : {
197 0 : }
198 :
199 0 : void SAL_CALL OGLWindow::removePaintListener( const uno::Reference< awt::XPaintListener >& )
200 : throw (uno::RuntimeException, std::exception)
201 : {
202 0 : }
203 :
204 0 : IMPL_LINK(OGLWindow, FocusGrabber, VclWindowEvent*, pEvent)
205 : {
206 0 : if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE )
207 : {
208 0 : MouseEvent* pMouseEvt = static_cast<MouseEvent*>(pEvent->GetData());
209 0 : if(pMouseEvt)
210 : {
211 0 : const Point& rMousePos = pMouseEvt->GetPosPixel();
212 0 : const Rectangle aWinRect(m_rEventHandler.GetPosPixel(),m_rEventHandler.GetSizePixel());
213 : // Grab focus to the OpenGL window when mouse pointer is over it
214 0 : if( aWinRect.IsInside(rMousePos) )
215 : {
216 0 : if ( !m_rEventHandler.HasFocus() )
217 : {
218 0 : m_rEventHandler.GrabFocus();
219 : }
220 : }
221 : // Move focus to the document when mouse is not over the OpenGL window
222 0 : else if ( m_rEventHandler.HasFocus() )
223 : {
224 0 : m_rEventHandler.GrabFocusToDocument();
225 : }
226 : }
227 : }
228 :
229 0 : return 0;
230 : }
231 :
232 0 : IMPL_LINK(OGLWindow, CameraHandler, VclWindowEvent*, pEvent)
233 : {
234 0 : if( pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT )
235 : {
236 0 : KeyEvent* pKeyEvt = static_cast<KeyEvent*>(pEvent->GetData());
237 0 : if(pKeyEvt)
238 : {
239 0 : const sal_uInt16 nCode = pKeyEvt->GetKeyCode().GetCode();
240 0 : if (nCode == KEY_Q || nCode == KEY_E ||
241 0 : nCode == KEY_A || nCode == KEY_D ||
242 0 : nCode == KEY_W || nCode == KEY_S )
243 : {
244 : // Calculate movement
245 0 : glm::vec3 vMoveBy;
246 : {
247 0 : glm::vec3 vEye;
248 0 : glm::vec3 vView;
249 0 : glm::vec3 vUp;
250 0 : gltf_get_camera_pos(&m_rHandle, &vEye,&vView,&vUp);
251 0 : float fModelSize =(float)gltf_get_model_size(&m_rHandle);
252 :
253 0 : glm::vec3 vMove = vView-vEye;
254 0 : vMove = glm::normalize(vMove);
255 0 : vMove *= 25.0f;
256 0 : glm::vec3 vStrafe = glm::cross(vMove, vUp);
257 0 : vStrafe = glm::normalize(vStrafe);
258 0 : vStrafe *= 25.0f;
259 0 : glm::vec3 vMup = vUp * 25.0f;
260 :
261 0 : if( !m_bIsOrbitMode )
262 : {
263 0 : if(nCode == KEY_E)vMoveBy += vMup*(0.0005f*fModelSize);
264 0 : if(nCode == KEY_Q)vMoveBy -= vMup*(0.0005f*fModelSize);
265 0 : if(nCode == KEY_W)vMoveBy += vMove*(0.0005f*fModelSize);
266 0 : if(nCode == KEY_S)vMoveBy -= vMove*(0.0005f*fModelSize);
267 0 : if(nCode == KEY_A)vMoveBy -= vStrafe*(0.0005f*fModelSize);
268 0 : if(nCode == KEY_D)vMoveBy += vStrafe*(0.0005f*fModelSize);
269 : }
270 : else
271 : {
272 0 : bool bZoomIn = false;
273 0 : bool bZoomOut = false;
274 0 : if(nCode == KEY_E)
275 : {
276 0 : vMoveBy += vMove*(0.0005f*fModelSize);
277 0 : bZoomIn = true;
278 : }
279 0 : if(nCode == KEY_Q)
280 : {
281 0 : vMoveBy -= vMove*(0.0005f*fModelSize);
282 0 : bZoomOut = true;
283 : }
284 :
285 : // Limit zooming in orbit mode
286 0 : float fCameraDistFromModelGlobe = glm::length(vEye + vMoveBy - vView) - fModelSize / 2.0f;
287 0 : if ((fCameraDistFromModelGlobe < 0.5 * fModelSize && bZoomIn ) ||
288 0 : (fCameraDistFromModelGlobe > 2 * fModelSize && bZoomOut ))
289 : {
290 0 : vMoveBy = glm::vec3(0.0);
291 : }
292 : }
293 : }
294 0 : gltf_renderer_move_camera(&m_rHandle, vMoveBy.x, vMoveBy.y, vMoveBy.z, 0.0001);
295 :
296 0 : if( m_bIsOrbitMode )
297 : {
298 0 : long nDeltaX = 0;
299 0 : long nDeltaY = 0;
300 0 : if (nCode == KEY_W)
301 : {
302 0 : nDeltaY -= 1;
303 : }
304 0 : if (nCode == KEY_S)
305 : {
306 0 : nDeltaY += 1;
307 : }
308 0 : if (nCode == KEY_A)
309 : {
310 0 : nDeltaX -= 1;
311 : }
312 0 : if (nCode == KEY_D)
313 : {
314 0 : nDeltaX += 1;
315 : }
316 0 : float fSensitivity = 50.0;
317 0 : gltf_renderer_rotate_model(&m_rHandle, nDeltaX*fSensitivity, nDeltaY*fSensitivity, 0.0);
318 0 : }
319 : }
320 0 : else if(nCode == KEY_M)
321 : {
322 0 : if(m_bIsOrbitMode)
323 : {
324 0 : gltf_orbit_mode_stop(&m_rHandle);
325 0 : m_bIsOrbitMode = false;
326 : }
327 : else
328 : {
329 0 : gltf_orbit_mode_start(&m_rHandle);
330 0 : m_bIsOrbitMode = true;
331 : }
332 : }
333 0 : else if(nCode == KEY_F)
334 : {
335 0 : gltf_render_FPS_enable(&m_rHandle);
336 : }
337 : }
338 : }
339 0 : else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONDOWN )
340 : {
341 0 : MouseEvent* pMouseEvt = static_cast<MouseEvent*>(pEvent->GetData());
342 0 : if(pMouseEvt && pMouseEvt->IsLeft() && pMouseEvt->GetClicks() == 1)
343 : {
344 0 : m_aLastMousePos = pMouseEvt->GetPosPixel();
345 : }
346 : }
347 0 : else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE )
348 : {
349 0 : if ( !m_rEventHandler.HasFocus() )
350 : {
351 0 : m_rEventHandler.GrabFocus();
352 : }
353 0 : MouseEvent* pMouseEvt = static_cast<MouseEvent*>(pEvent->GetData());
354 0 : if(pMouseEvt && pMouseEvt->IsLeft() && m_aLastMousePos != Point(0,0))
355 : {
356 0 : const Point& aCurPos = pMouseEvt->GetPosPixel();
357 0 : float fSensitivity = std::min(m_rHandle.viewport.width, m_rHandle.viewport.height);
358 0 : if (fSensitivity == 0.0)
359 0 : fSensitivity = 1.0;
360 : else
361 0 : fSensitivity = 540.0 / fSensitivity;
362 :
363 :
364 0 : long nDeltaX = m_aLastMousePos.X()-aCurPos.X();
365 0 : long nDeltaY = m_aLastMousePos.Y()-aCurPos.Y();
366 0 : if( m_bIsOrbitMode )
367 : {
368 0 : fSensitivity *= 5;
369 0 : gltf_renderer_rotate_model(&m_rHandle, (float)nDeltaX*fSensitivity, (float)nDeltaY*fSensitivity, 0.0);
370 : }
371 : else
372 : {
373 : // Filter out too small deltas to avoid rewrite rotation parameter with 0
374 : // before rotation is done
375 0 : if( nDeltaX != 0 || nDeltaY != 0 )
376 0 : gltf_renderer_rotate_camera(&m_rHandle, (float)nDeltaX*fSensitivity, (float)nDeltaY*fSensitivity, 0.0);
377 : }
378 0 : m_aLastMousePos = aCurPos;
379 : }
380 : }
381 0 : else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONUP )
382 : {
383 0 : MouseEvent* pMouseEvt = static_cast<MouseEvent*>(pEvent->GetData());
384 0 : if(pMouseEvt && pMouseEvt->IsLeft() && pMouseEvt->GetClicks() == 1)
385 : {
386 0 : m_aLastMousePos = Point(0,0);
387 : }
388 : }
389 0 : return 0;
390 : }
391 :
392 : } // namespace ogl
393 : } // namespace avmedia
394 :
395 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|