2 #include "GVORenderer.h"
3 #include "GVOWorldMap.h"
5 #include "GVOTexture.h"
6 #include "GVOShipRouteList.h"
7 #include "GVOShipRoute.h"
12 const double k_scaleStep = 0.125; // 12.5%
13 const double k_minScale = 0.125; // 12.5%
14 const double k_maxScale = 4.00; // 400%
16 // Google
\90æ
\90¶
\9eH
\82
\81u
\92n
\8b\85\82Ì
\8aO
\8eü
\82Í40,075km
\81v
\81u1
\83m
\83b
\83g
\82Í1.85200km
\81v
17 // 1
\90¢
\8aE
\8dÀ
\95W
\82Í40,075km/16384points
18 //
\8eÀ
\8e\9e\8aÔ1
\95b
\82Å
\83Q
\81[
\83\80\93à0.4
\8e\9e\8aÔ
20 //
\92n
\8b\85\8aO
\8eü
\82ð
\90Ô
\93¹
\94¼
\8ca
\82©
\82ç
\8eZ
\8fo
\82·
\82é
\81B
21 //
\90Ô
\93¹
\94¼
\8ca
\82Í6378.137
\82È
\82Ì
\82Å
\8aO
\8eü
\82Í2*M_PI_*6378.137
22 inline double s_velocityByKnot( const double velocity )
24 static const double k_knotFactor = (2 * M_PI * 6378.137) / 16384.0 / 0.4 / 1.852;
25 return velocity * k_knotFactor;
30 void GVORenderer::setup( const GVOConfig * config, HDC hdcPrimary, const GVOWorldMap * worldMap )
32 m_hdcPrimary = hdcPrimary;
35 setWorldMap( worldMap );
39 void GVORenderer::teardown()
41 delete m_worldMapTexture;
42 m_worldMapTexture = NULL;
44 ::wglMakeCurrent( NULL, NULL );
45 ::wglDeleteContext( m_hglrc );
51 void GVORenderer::setConfig( const GVOConfig * config )
53 m_focusPointInWorldCoord = config->m_initialSurveyCoord;
54 m_shipPointInWorld.x = -1;
55 m_shipPointInWorld.y = -1;
56 m_shipVectorLineEnabled = config->m_shipVectorLineEnabled;
57 m_speedMeterEnabled = config->m_speedMeterEnabled;
58 m_traceShipEnabled = config->m_traceShipPositionEnabled;
62 void GVORenderer::setupGL()
64 PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd) };
66 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
67 pfd.iPixelType = PFD_TYPE_RGBA;
71 pfd.iLayerType = PFD_MAIN_PLANE;
72 ::SetPixelFormat( m_hdcPrimary, ::ChoosePixelFormat( m_hdcPrimary, &pfd ), &pfd );
73 m_hglrc = ::wglCreateContext( m_hdcPrimary );
74 ::wglMakeCurrent( m_hdcPrimary, m_hglrc );
75 ::glDisable( GL_DEPTH_TEST );
76 ::glDisable( GL_LIGHTING );
77 ::glEnable( GL_CULL_FACE );
78 ::glCullFace( GL_BACK );
82 void GVORenderer::setWorldMap( const GVOWorldMap * worldMap )
84 m_worldMap = worldMap;
85 m_worldMapTexture = new GVOTexture();
86 m_worldMapTexture->setImage( worldMap->image() );
90 void GVORenderer::setViewSize( const SIZE& viewSize )
92 m_viewSize = viewSize;
93 ::wglMakeCurrent( m_hdcPrimary, m_hglrc );
94 ::glMatrixMode( GL_PROJECTION );
96 ::glViewport( 0, 0, m_viewSize.cx, m_viewSize.cy );
97 ::gluOrtho2D( 0, m_viewSize.cx, m_viewSize.cy, 0 );
101 SIZE GVORenderer::scaledMapSize() const
104 LONG( m_worldMap->image().width() * m_viewScale ),
105 LONG( m_worldMap->image().height() * m_viewScale )
111 POINT GVORenderer::mapOriginInView() const
113 const POINT viewCenter = viewCenterPoint();
114 const SIZE mapSize = scaledMapSize();
115 const POINT worldPosInView = drawOffsetFromWorldCoord( m_focusPointInWorldCoord );
118 viewCenter.x - worldPosInView.x,
119 viewCenter.y - worldPosInView.y
121 if ( m_viewSize.cx < mapSize.cx ) {
122 while ( 0 < mapTopLeft.x ) {
123 mapTopLeft.x -= mapSize.cx;
131 void GVORenderer::offsetFocusInViewCoord( const POINT& offset )
133 const double dx = ((double)offset.x / m_viewScale) / m_worldMap->image().width();
134 const double dy = ((double)offset.y / m_viewScale) / m_worldMap->image().height();
136 LONG x = m_focusPointInWorldCoord.x + LONG( dx * k_worldWidth );
137 LONG y = m_focusPointInWorldCoord.y + LONG( dy * k_worldHeight );
138 y = std::max<LONG>( 0, std::min<LONG>( y, k_worldHeight ) );
142 while ( k_worldWidth < x ) {
146 m_focusPointInWorldCoord.x = x;
147 m_focusPointInWorldCoord.y = y;
151 bool GVORenderer::zoomIn()
153 double scale = m_viewScale;
154 double step = k_scaleStep;
156 scale = m_viewScale + step;
157 if ( k_maxScale < scale ) {
160 if ( m_viewScale != scale ) {
168 bool GVORenderer::zoomOut()
170 double scale = m_viewScale;
171 double step = k_scaleStep;
173 scale = m_viewScale - step;
174 if ( scale < k_minScale ) {
177 if ( m_viewScale != scale ) {
185 void GVORenderer::resetViewScale()
191 POINT GVORenderer::drawOffsetFromWorldCoord( const POINT&worldCoord ) const
193 const POINT worldPosInImage = m_worldMap->imageCoordFromWorldCoord( worldCoord );
194 const POINT drawOffset = {
195 LONG( worldPosInImage.x * m_viewScale ),
196 LONG( worldPosInImage.y * m_viewScale )
202 void GVORenderer::setShipPositionInWorld( const POINT& shipPositionInWorld )
204 if ( m_traceShipEnabled ) {
205 m_focusPointInWorldCoord = shipPositionInWorld;
207 m_shipPointInWorld = shipPositionInWorld;
211 void GVORenderer::render( const GVOVector& shipVector, double shipVelocity, GVOTexture * shipTexture, const GVOShipRouteList * shipRouteList )
213 ::wglMakeCurrent( m_hdcPrimary, m_hglrc );
214 ::glClearColor( 0.2f, 0.2f, 0.3f, 0.0f );
215 ::glClear( GL_COLOR_BUFFER_BIT );
216 ::glDisable( GL_BLEND );
218 renderMap( shipVector, shipTexture, shipRouteList );
220 if ( m_speedMeterEnabled ) {
221 renderSpeedMeter( shipVelocity );
225 ::SwapBuffers( m_hdcPrimary );
226 ::wglMakeCurrent( NULL, NULL );
230 void GVORenderer::renderMap( const GVOVector& shipVector, GVOTexture * shipTexture, const GVOShipRouteList * shipRouteList )
232 _ASSERT( m_worldMapTexture != NULL );
234 const SIZE mapSize = scaledMapSize();
236 const POINT mapTopLeft = mapOriginInView();
237 int xDrawOrigin, yDrawOrigin;
238 xDrawOrigin = mapTopLeft.x;
239 yDrawOrigin = mapTopLeft.y;
240 if ( 0 < xDrawOrigin ) {
241 xDrawOrigin = (xDrawOrigin % mapSize.cx) - mapSize.cx;
243 const int xInitial = xDrawOrigin; //
\8d¶
\92[
\82Ì
\95`
\89æ
\8aJ
\8enx
\8dÀ
\95W
244 int drawn = xInitial;
246 //
\90¢
\8aE
\92n
\90}
\82ð
\89¡
\82É
\95À
\82×
\82Ä
\95`
\89æ
247 //
\81i
\95`
\89æ
\8dÅ
\93K
\89»
\82Í
\8fÈ
\97ª
\81j
248 ::glMatrixMode( GL_MODELVIEW );
250 ::glTranslatef( (float)xDrawOrigin, (float)yDrawOrigin, 0 );
251 while ( drawn < m_viewSize.cx ) {
252 //
\92n
\90}
\82ð1
\96\87\95`
\89æ
253 renderTexture( *m_worldMapTexture, (float)mapSize.cx, (float)mapSize.cy );
255 //
\8dq
\98H
\82ð1
\96\87\95ª
\95`
\89æ
256 renderShipRouteList( mapSize.cx, mapSize.cy, shipRouteList );
258 xDrawOrigin += mapSize.cx;
260 ::glTranslatef( (float)mapSize.cx, 0.0f, 0.0f );
264 //
\95s
\90³
\82È
\8e©
\91D
\88Ê
\92u
\82È
\82ç
\82±
\82ê
\88È
\8d~
\82Ì
\95`
\89æ
\82Í
\82µ
\82È
\82¢
\81B
265 if ( m_shipPointInWorld.x < 0 || m_shipPointInWorld.y < 0 ) {
269 const POINT shipPointOffset = drawOffsetFromWorldCoord( m_shipPointInWorld );
271 //
\90j
\98H
\97\
\91ª
\90ü
\82ð
\95`
\89æ
272 if ( shipVector.length() != 0.0 && m_shipVectorLineEnabled ) {
273 const float lineWidth = max<float>( 1, float( 1 * m_viewScale ) );
274 ::glLineWidth( lineWidth );
275 ::glColor3f( 255, 0, 255 );
277 const LONG k_lineLength = k_worldHeight;
278 const POINT reachPointOffset = drawOffsetFromWorldCoord(
279 shipVector.pointFromOriginWithLength( m_shipPointInWorld, k_lineLength )
282 //
\8c©
\82¦
\82Ä
\82é
\92n
\90}
\89æ
\91\9c\82Ì
\95ª
\82¾
\82¯
\95`
\89æ
\82·
\82é
284 xDrawOrigin = xInitial;
285 ::glMatrixMode( GL_MODELVIEW );
287 ::glTranslatef( (float)xDrawOrigin, (float)yDrawOrigin, 0 );
288 while ( drawn < m_viewSize.cx ) {
289 ::glBegin( GL_LINES );
290 ::glVertex2i( shipPointOffset.x, shipPointOffset.y );
291 ::glVertex2i( reachPointOffset.x, reachPointOffset.y );
294 xDrawOrigin += mapSize.cx;
296 ::glTranslatef( (float)mapSize.cx, 0.0f, 0.0f );
301 //
\8e©
\91D
\82Ì
\88Ê
\92u
\82ð
\95`
\89æ
303 const float shipMarkSize = 16.0f;
305 //
\8c©
\82¦
\82Ä
\82é
\92n
\90}
\89æ
\91\9c\82Ì
\95ª
\82¾
\82¯
\95`
\89æ
\82·
\82é
307 xDrawOrigin = xInitial;
308 ::glMatrixMode( GL_MODELVIEW );
310 ::glLineWidth( 1.0f );
311 ::glTranslatef( (float)xDrawOrigin, (float)yDrawOrigin, 0 );
312 while ( drawn < m_viewSize.cx ) {
313 const float x = shipPointOffset.x - shipTexture->width() / 2.0f;
314 const float y = shipPointOffset.y - shipTexture->height() / 2.0f;
316 ::glEnable( GL_BLEND );
317 ::glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
318 ::glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
319 renderTexture( *shipTexture, x, y, shipMarkSize, shipMarkSize );
320 ::glDisable( GL_BLEND );
322 xDrawOrigin += mapSize.cx;
324 ::glTranslatef( (float)mapSize.cx, 0.0f, 0.0f );
330 void GVORenderer::renderShipRouteList( int width, int height, const GVOShipRouteList * shipRouteList )
332 _ASSERT( 0 <= width );
333 _ASSERT( 0 <= height );
334 _ASSERT(shipRouteList != NULL);
336 const float lineWidth = max<float>( 1, float( 1 * m_viewScale ) );
337 ::glLineWidth( lineWidth );
338 //
\8dÅ
\90V
\8dq
\98H
\88È
\8aO
\82ð
\94¼
\93§
\96¾
\82Å
\95`
\89æ
339 if ( 1 < shipRouteList->getList().size() ) {
340 ::glEnable( GL_BLEND );
341 ::glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
342 ::glColor4f( 1.0f, 1.0f, 1.0f, 0.5f );
345 for ( const GVOShipRoute *route : shipRouteList->getList() ) {
346 //
\8dÅ
\90V
\8dq
\98H
\82¾
\82¯
\82ð
\95s
\93§
\96¾
\82Å
\95`
\89æ
347 if ( shipRouteList->getList().back() == route ) {
348 ::glLineWidth( lineWidth );
349 ::glColor3f( 1.0f, 1.0f, 1.0f );
350 ::glDisable( GL_BLEND );
353 if ( route->isFavorite() ) {
354 ::glColor4f( 1.0f, 1.0f, 0.0f, 0.75f );
355 if ( route->isHilight() ) {
356 ::glLineWidth( lineWidth * 2 );
360 if ( route->isHilight() ) {
361 ::glLineWidth( lineWidth * 2 );
362 ::glColor4f( 0.5f, 1.0f, 1.0f, 0.75f );
365 ::glLineWidth( lineWidth );
366 ::glColor4f( 1.0f, 1.0f, 1.0f, 0.5f );
370 for ( const GVOShipRoute::Line & line : route->getLines() ) {
371 if ( line.size() < 2 ) {
372 // 2
\93_
\96¢
\96\9e\82Å
\82Í
\90ü
\82ð
\88ø
\82¯
\82È
\82¢
375 ::glBegin( GL_LINE_STRIP );
376 for ( const GVONormalizedPoint & point : line ) {
377 const float x = point.x() * width;
378 const float y = point.y() * height;
379 ::glVertex2f( x, y );
384 ::glDisable( GL_BLEND );
388 void GVORenderer::renderSpeedMeter( double shipVelocity )
390 // THE
\8eè
\94²
\82«
\95¶
\8e\9a\83e
\83N
\83X
\83`
\83\83\81[
\8dì
\90¬
392 HDC hdcMem = ::CreateCompatibleDC( m_hdcPrimary );
395 const double velocity = s_velocityByKnot( shipVelocity );
396 wchar_t buf[4096] = { 0 };
397 swprintf( buf, _countof( buf ), L"%.2f kt", velocity );
400 ::DrawText( hdcMem, buf, -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_TOP | DT_CALCRECT );
401 const int width = rc.right - rc.left;
402 const int stride = width + (4 - width % 4) % 4;
403 const int height = rc.bottom - rc.top;
405 workImage.createImage( stride, height );
406 ::SelectObject( hdcMem, workImage.bitmapHandle() );
407 ::DrawText( hdcMem, buf, -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_TOP );
408 ::RestoreDC( hdcMem, -1 );
409 ::DeleteDC( hdcMem );
411 GVOTexture workTexture;
412 workTexture.setImage( workImage );
414 ::glMatrixMode( GL_MODELVIEW );
416 renderTexture( workTexture, float( m_viewSize.cx - stride ), 0.0f, (float)stride, (float)height );
420 void GVORenderer::renderTexture( GVOTexture & texture, float w, float h )
422 renderTexture( texture, 0, 0, w, h );
425 void GVORenderer::renderTexture( GVOTexture & texture, float x, float y, float w, float h )
429 ::glBegin( GL_QUADS );
431 ::glTexCoord2d( 0, 0 );
432 ::glVertex2d( x, y );
434 ::glTexCoord2d( 0, 1 );
435 ::glVertex2d( x, y + h );
437 ::glTexCoord2d( 1, 1 );
438 ::glVertex2d( x + w, y + h );
440 ::glTexCoord2d( 1, 0 );
441 ::glVertex2d( x + w, y );
449 GVOTexture * GVORenderer::createTextureFromImage( const GVOImage & image )
451 ::wglMakeCurrent( m_hdcPrimary, m_hglrc );
452 std::auto_ptr<GVOTexture> texture( new GVOTexture() );
453 texture->setImage( image );
454 ::wglMakeCurrent( NULL, NULL );
456 return texture.release();