28 #include <wx/wxprec.h>
40 #include <wx/arrimpl.cpp>
42 #include <wx/colour.h>
43 #include <wx/dcmemory.h>
44 #include <wx/dynarray.h>
47 #include <wx/gdicmn.h>
48 #include <wx/glcanvas.h>
50 #include <wx/jsonval.h>
53 #include <wx/progdlg.h>
54 #include <wx/stopwatch.h>
55 #include <wx/string.h>
56 #include <wx/tokenzr.h>
58 #include <wx/window.h>
60 #include "model/own_ship.h"
61 #include "model/route.h"
62 #include "model/routeman.h"
63 #include "model/track.h"
66 #include "chartbase.h"
67 #include "chart_ctx_factory.h"
71 #include "ChInfoWin.h"
73 #include "color_handler.h"
76 #include "emboss_data.h"
78 #include "glChartCanvas.h"
79 #include "glTexCache.h"
83 #include "mipmap/mipmap.h"
85 #include "OCPNPlatform.h"
87 #include "pluginmanager.h"
89 #include "RolloverWin.h"
90 #include "route_gui.h"
91 #include "route_point_gui.h"
98 #include "track_gui.h"
100 #include "iENCToolbar.h"
101 #include "shapefile_basemap.h"
103 #ifdef USE_ANDROID_GLES2
104 #include <GLES2/gl2.h>
110 #include "androidUTIL.h"
111 #elif defined(__WXQT__) || defined(__WXGTK__)
115 #ifndef GL_ETC1_RGB8_OES
116 #define GL_ETC1_RGB8_OES 0x8D64
119 #ifndef GL_DEPTH_STENCIL_ATTACHMENT
120 #define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
123 #if defined(__UNIX__) && !defined(__WXOSX__)
128 void Reset() { clock_gettime(CLOCK_REALTIME, &tp); }
132 clock_gettime(CLOCK_REALTIME, &tp_end);
133 return (tp_end.tv_sec - tp.tv_sec) * 1.e3 +
134 (tp_end.tv_nsec - tp.tv_nsec) / 1.e6;
142 #if defined(__ANDROID__)
143 #include "androidUTIL.h"
144 #elif defined(__WXQT__) || defined(__WXGTK__) || defined(FLATPAK)
149 #ifndef GL_ETC1_RGB8_OES
150 #define GL_ETC1_RGB8_OES 0x8D64
159 extern "C" void glOrthof(
float left,
float right,
float bottom,
float top,
160 float near,
float far);
161 #define glOrtho(a, b, c, d, e, f) \
163 glOrthof(a, b, c, d, e, f);
168 #include "s57chart.h"
171 #ifdef USE_ANDROID_GLES2
172 #include <GLES2/gl2.h>
175 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
180 extern bool GetMemoryStatus(
int *mem_total,
int *mem_used);
182 extern s52plib *ps52plib;
183 extern bool g_bopengl;
184 extern bool g_bDebugOGL;
185 extern bool g_bSoftwareGL;
188 extern bool g_bShowChartBar;
190 extern bool b_inCompressAllCharts;
192 extern GLenum g_texture_rectangle_format;
194 extern int g_memCacheLimit;
195 extern ColorScheme global_color_scheme;
196 extern bool g_bquiting;
198 extern int g_mipmap_max_level;
200 extern int g_OwnShipIconType;
206 extern RouteList *pRouteList;
207 extern std::vector<Track*> g_TrackList;
208 extern bool b_inCompressAllCharts;
209 extern bool g_bGLexpert;
210 extern bool g_bcompression_wait;
211 extern float g_ShipScaleFactorExp;
213 float g_GLMinCartographicLineWidth;
215 extern bool g_fog_overzoom;
216 extern double g_overzoom_emphasis_base;
217 extern bool g_oz_vector_scale;
218 extern TCMgr *ptcmgr;
219 extern int g_nCPUCount;
220 extern bool g_running;
222 extern unsigned int g_canvasConfig;
226 extern bool g_PrintingInProgress;
230 wxColor s_regionColor;
242 #define APIENTRYP APIENTRY *
248 #ifndef GL_COMPRESSED_RGB_FXT1_3DFX
249 #define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
252 PFNGLGENFRAMEBUFFERSEXTPROC s_glGenFramebuffers;
253 PFNGLGENRENDERBUFFERSEXTPROC s_glGenRenderbuffers;
254 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC s_glFramebufferTexture2D;
255 PFNGLBINDFRAMEBUFFEREXTPROC s_glBindFramebuffer;
256 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC s_glFramebufferRenderbuffer;
257 PFNGLRENDERBUFFERSTORAGEEXTPROC s_glRenderbufferStorage;
258 PFNGLBINDRENDERBUFFEREXTPROC s_glBindRenderbuffer;
259 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC s_glCheckFramebufferStatus;
260 PFNGLDELETEFRAMEBUFFERSEXTPROC s_glDeleteFramebuffers;
261 PFNGLDELETERENDERBUFFERSEXTPROC s_glDeleteRenderbuffers;
263 PFNGLCOMPRESSEDTEXIMAGE2DPROC s_glCompressedTexImage2D;
264 PFNGLGETCOMPRESSEDTEXIMAGEPROC s_glGetCompressedTexImage;
267 PFNGLGENBUFFERSPROC s_glGenBuffers;
268 PFNGLBINDBUFFERPROC s_glBindBuffer;
269 PFNGLBUFFERDATAPROC s_glBufferData;
270 PFNGLDELETEBUFFERSPROC s_glDeleteBuffers;
272 #ifndef USE_ANDROID_GLES2
277 typedef void(APIENTRYP PFNGLGETBUFFERPARAMETERIV)(GLenum target, GLenum value,
279 PFNGLGETBUFFERPARAMETERIV s_glGetBufferParameteriv;
281 #include <wx/arrimpl.cpp>
284 GLuint g_raster_format = GL_RGB;
288 wxStopWatch g_glstopwatch;
289 double g_gl_ms_per_frame;
292 int g_uncompressed_tile_size;
294 extern wxProgressDialog *pprog;
295 extern bool b_skipout;
296 extern wxSize pprog_size;
297 extern int pprog_count;
298 extern int pprog_threads;
305 bool glChartCanvas::s_b_useScissorTest;
306 bool glChartCanvas::s_b_useStencil;
307 bool glChartCanvas::s_b_useStencilAP;
308 bool glChartCanvas::s_b_useFBO;
310 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
311 static int s_tess_vertex_idx;
312 static int s_tess_vertex_idx_this;
313 static int s_tess_buf_len;
314 static GLfloat *s_tess_work_buf;
316 static int s_nvertex;
317 static vec4 s_tess_color;
327 while ( upd.HaveRects() )
329 wxRect rect = upd.GetRect();
330 printf(
"[(%d, %d) (%d, %d)] ", rect.x, rect.y, rect.width, rect.height);
337 GLboolean QueryExtension(
const char *extName) {
348 extNameLen = strlen(extName);
350 p = (
char *)glGetString(GL_EXTENSIONS);
358 int n = strcspn(p,
" ");
359 if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
368 int test_attribs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE,
369 16, WX_GL_STENCIL_SIZE, 8,
372 glTestCanvas::glTestCanvas(wxWindow *parent)
373 : wxGLCanvas(parent, wxID_ANY, test_attribs, wxDefaultPosition,
377 int attribs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE,
378 16, WX_GL_STENCIL_SIZE, 8,
381 EVT_PAINT(glChartCanvas::OnPaint)
382 EVT_ACTIVATE(glChartCanvas::OnActivate) EVT_SIZE(glChartCanvas::OnSize)
383 EVT_MOUSE_EVENTS(glChartCanvas::MouseEvent) END_EVENT_TABLE()
386 : wxGLCanvas(parent, wxID_ANY, attribs, wxDefaultPosition, wxSize(256, 256),
387 wxFULL_REPAINT_ON_RESIZE | wxBG_STYLE_CUSTOM, _T(""))
390 m_pParentCanvas =
dynamic_cast<ChartCanvas *
>(parent);
395 std::unordered_map<wxPenStyle, std::array<wxDash, 2>> glChartCanvas::dash_map = {
396 {wxPENSTYLE_DOT, {1, 1}},
397 {wxPENSTYLE_LONG_DASH, {5, 5}},
398 {wxPENSTYLE_SHORT_DASH, {1, 5}},
399 {wxPENSTYLE_DOT_DASH, {5, 1}},
402 void glChartCanvas::Init() {
407 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
409 m_cache_current_ch = NULL;
411 m_b_paint_enable =
true;
412 m_in_glpaint =
false;
414 m_cache_tex[0] = m_cache_tex[1] = 0;
417 m_b_BuiltFBO =
false;
418 m_b_DisableFBO =
false;
427 m_bpinchGuard =
false;
428 m_binGesture =
false;
431 m_last_render_time = -1;
438 m_gldc.SetGLCanvas(
this);
439 m_gldc.SetDPIFactor(g_BasePlatform->GetDisplayDIPMult(GetParent()));
441 m_displayScale = 1.0;
442 #if defined(__WXOSX__) || defined(__WXGTK3__)
444 m_displayScale = GetContentScaleFactor();
452 (wxObjectEventFunction)(wxEventFunction)&glChartCanvas::OnEvtPanGesture,
456 wxEVT_QT_PINCHGESTURE,
457 (wxObjectEventFunction)(wxEventFunction)&glChartCanvas::OnEvtPinchGesture,
460 Connect(GESTURE_EVENT_TIMER, wxEVT_TIMER,
461 (wxObjectEventFunction)(
462 wxEventFunction)&glChartCanvas::onGestureTimerEvent,
465 Connect(GESTURE_FINISH_TIMER, wxEVT_TIMER,
466 (wxObjectEventFunction)(
467 wxEventFunction)&glChartCanvas::onGestureFinishTimerEvent,
471 ZOOM_TIMER, wxEVT_TIMER,
472 (wxObjectEventFunction)(wxEventFunction)&glChartCanvas::onZoomTimerEvent,
475 m_gestureEeventTimer.SetOwner(
this, GESTURE_EVENT_TIMER);
476 m_gestureFinishTimer.SetOwner(
this, GESTURE_FINISH_TIMER);
477 zoomTimer.SetOwner(
this, ZOOM_TIMER);
479 #ifdef USE_ANDROID_GLES2
487 m_bgestureGuard =
false;
492 #ifdef HAVE_WX_GESTURE_EVENTS
493 if (!EnableTouchEvents(wxTOUCH_ZOOM_GESTURE |
494 wxTOUCH_PRESS_GESTURES)) {
495 wxLogError(
"Failed to enable touch events");
498 Bind(wxEVT_GESTURE_ZOOM, &ChartCanvas::OnZoom, m_pParentCanvas);
500 Bind(wxEVT_LONG_PRESS, &ChartCanvas::OnLongPress, m_pParentCanvas);
501 Bind(wxEVT_PRESS_AND_TAP, &ChartCanvas::OnPressAndTap, m_pParentCanvas);
503 Bind(wxEVT_RIGHT_UP, &ChartCanvas::OnRightUp, m_pParentCanvas);
504 Bind(wxEVT_RIGHT_DOWN, &ChartCanvas::OnRightDown, m_pParentCanvas);
506 Bind(wxEVT_LEFT_UP, &ChartCanvas::OnLeftUp, m_pParentCanvas);
507 Bind(wxEVT_LEFT_DOWN, &ChartCanvas::OnLeftDown, m_pParentCanvas);
509 Bind(wxEVT_MOUSEWHEEL, &ChartCanvas::OnWheel, m_pParentCanvas);
510 Bind(wxEVT_MOTION, &ChartCanvas::OnMotion, m_pParentCanvas);
517 glChartCanvas::~glChartCanvas() {
523 void glChartCanvas::FlushFBO(
void) {
524 if (m_bsetup) BuildFBO();
527 void glChartCanvas::OnActivate(wxActivateEvent &event) {
528 m_pParentCanvas->OnActivate(event);
531 void glChartCanvas::OnSize(wxSizeEvent &event) {
535 wxLogMessage(_T(
"Got OnSize event while NOT running"));
537 qDebug() <<
"OnSizeB";
544 if (!IsShown())
return;
546 SetCurrent(*m_pcontext);
549 SetSize(GetSize().x, GetSize().y);
557 if (m_bsetup && m_pcontext && IsShown()) {
558 SetCurrent(*m_pcontext);
564 wxLogMessage(_T(
"BuildFBO 3"));
570 ViewPort *vp = m_pParentCanvas->GetpVP();
573 mat4x4_scale_aniso((
float(*)[4])vp->vp_matrix_transform, m,
574 2.0 / (
float)vp->pix_width, -2.0 / (
float)vp->pix_height,
576 mat4x4_translate_in_place((
float(*)[4])vp->vp_matrix_transform, -vp->pix_width / 2,
577 -vp->pix_height / 2, 0);
580 void glChartCanvas::MouseEvent(wxMouseEvent &event) {
581 if (m_pParentCanvas->MouseEventOverlayWindows(event))
return;
587 bool obj_proc = m_pParentCanvas->MouseEventProcessObjects(event);
589 if (!obj_proc && !m_pParentCanvas->singleClickEventIsValid)
590 m_pParentCanvas->MouseEventProcessCanvas(event);
592 if (!g_btouch) m_pParentCanvas->SetCanvasCursor(event);
596 if (m_bgestureGuard) {
597 m_pParentCanvas->r_rband.x = 0;
607 if (event.LeftUp()) {
609 if ((abs(panx) > 2) || (abs(pany) > 2)) {
612 m_gestureEeventTimer.Start(10, wxTIMER_ONE_SHOT);
619 if (!event.LeftDClick()) {
624 if (m_binPan && event.RightDown()) {
625 qDebug() <<
"Skip right on pan";
628 bool obj_proc = m_pParentCanvas->MouseEventProcessObjects(event);
630 if (!obj_proc && !m_pParentCanvas->singleClickEventIsValid) {
631 if (!m_bgestureGuard)
632 m_pParentCanvas->MouseEventProcessCanvas(
641 #ifndef GL_MAX_RENDERBUFFER_SIZE
642 #define GL_MAX_RENDERBUFFER_SIZE 0x84E8
645 #ifndef USE_ANDROID_GLES2
646 bool glChartCanvas::buildFBOSize(
int fboSize) {
648 if (IsShown()) SetCurrent(*m_pcontext);
651 glDeleteTextures(2, m_cache_tex);
652 glDeleteFramebuffers(1, &m_fb0);
653 glDeleteRenderbuffers(1, &m_renderbuffer);
654 m_b_BuiltFBO =
false;
657 if (m_b_DisableFBO)
return false;
661 int rb_x = GetSize().x;
662 int rb_y = GetSize().y;
664 while (i < rb_x) i <<= 1;
668 while (i < rb_y) i <<= 1;
671 m_cache_tex_x = wxMax(rb_x, rb_y);
672 m_cache_tex_y = wxMax(rb_x, rb_y);
675 m_cache_tex_x = GetSize().x * m_displayScale;
676 m_cache_tex_y = GetSize().y * m_displayScale;
679 int err = GL_NO_ERROR;
681 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, ¶ms);
684 if (err == GL_INVALID_ENUM) {
685 glGetIntegerv(GL_MAX_TEXTURE_SIZE, ¶ms);
689 if (err == GL_NO_ERROR) {
690 if (fboSize > params) {
692 _T(
" OpenGL-> Requested Framebuffer size exceeds ")
693 _T(
"GL_MAX_RENDERBUFFER_SIZE"));
698 glGenFramebuffers(1, &m_fb0);
702 msg.Printf(_T(
" OpenGL-> Framebuffer GenFramebuffers error: %08X"),
708 glGenRenderbuffers(1, &m_renderbuffer);
712 msg.Printf(_T(
" OpenGL-> Framebuffer GenRenderbuffers error: %08X"),
718 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
722 msg.Printf(_T(
" OpenGL-> Framebuffer BindFramebuffers error: %08X"),
729 glGenTextures(2, m_cache_tex);
730 for (
int i = 0; i < 2; i++) {
731 glBindTexture(g_texture_rectangle_format, m_cache_tex[i]);
732 glTexParameterf(g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER,
734 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER,
736 glTexImage2D(g_texture_rectangle_format, 0, GL_RGBA, m_cache_tex_x,
737 m_cache_tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
740 glBindRenderbuffer(GL_RENDERBUFFER_EXT, m_renderbuffer);
742 if (m_b_useFBOStencil) {
744 glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
745 m_cache_tex_x, m_cache_tex_y);
747 int err = glGetError();
750 msg.Printf(_T(
" OpenGL-> glRenderbufferStorage error: %08X"), err);
754 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
755 GL_RENDERBUFFER_EXT, m_renderbuffer);
760 _T(
" OpenGL-> glFramebufferRenderbuffer depth error: %08X"), err);
764 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
765 GL_RENDERBUFFER_EXT, m_renderbuffer);
770 _T(
" OpenGL-> glFramebufferRenderbuffer stencil error: %08X"),
776 GLenum depth_format = GL_DEPTH_COMPONENT24;
781 if (!QueryExtension(
"GL_OES_depth24")) depth_format = GL_DEPTH_COMPONENT16;
785 glRenderbufferStorage(GL_RENDERBUFFER_EXT, depth_format, m_cache_tex_x,
787 int err = glGetError();
791 _T(
" OpenGL-> Framebuffer Depth Buffer Storage error: %08X"),
797 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
798 GL_RENDERBUFFER_EXT, m_renderbuffer);
804 _T(
" OpenGL-> Framebuffer Depth Buffer Attach error: %08X"), err);
810 glBindTexture(GL_TEXTURE_2D, 0);
811 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
814 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
816 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
817 g_texture_rectangle_format, m_cache_tex[0], 0);
819 GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
821 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
823 if (fb_status != GL_FRAMEBUFFER_COMPLETE_EXT) {
825 msg.Printf(_T(
" OpenGL-> buildFBOSize->Framebuffer Incomplete: %08X"),
835 #ifdef USE_ANDROID_GLES2
836 bool glChartCanvas::buildFBOSize(
int fboSize) {
840 int rb_x = GetSize().x;
841 int rb_y = GetSize().y;
843 while (i < rb_x) i <<= 1;
847 while (i < rb_y) i <<= 1;
850 m_cache_tex_x = wxMax(rb_x, rb_y);
851 m_cache_tex_y = wxMax(rb_x, rb_y);
855 int err = GL_NO_ERROR;
857 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, ¶ms);
860 if (err == GL_INVALID_ENUM) {
861 glGetIntegerv(GL_MAX_TEXTURE_SIZE, ¶ms);
865 if (err == GL_NO_ERROR) {
866 if (fboSize > params) {
868 _T(
" OpenGL-> Requested Framebuffer size exceeds ")
869 _T(
"GL_MAX_RENDERBUFFER_SIZE"));
874 glGenFramebuffers(1, &m_fb0);
878 msg.Printf(_T(
" OpenGL-> Framebuffer GenFramebuffers error: %08X"),
884 glGenRenderbuffers(1, &m_renderbuffer);
888 msg.Printf(_T(
" OpenGL-> Framebuffer GenRenderbuffers error: %08X"),
894 glBindFramebuffer(GL_FRAMEBUFFER, m_fb0);
898 msg.Printf(_T(
" OpenGL-> Framebuffer BindFramebuffers error: %08X"),
905 glGenTextures(2, m_cache_tex);
906 for (
int i = 0; i < 2; i++) {
907 glBindTexture(g_texture_rectangle_format, m_cache_tex[i]);
908 glTexParameterf(g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER,
910 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER,
912 glTexImage2D(g_texture_rectangle_format, 0, GL_RGBA, m_cache_tex_x,
913 m_cache_tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
916 glBindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
919 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, m_cache_tex_x,
925 msg.Printf(_T(
" OpenGL-> glRenderbufferStorage error: %08X"), err);
929 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
930 GL_RENDERBUFFER, m_renderbuffer);
934 msg.Printf(_T(
" OpenGL-> glFramebufferRenderbuffer depth error: %08X"),
939 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
940 GL_RENDERBUFFER, m_renderbuffer);
945 _T(
" OpenGL-> glFramebufferRenderbuffer stencil error: %08X"), err);
949 glBindTexture(GL_TEXTURE_2D, 0);
950 glBindFramebuffer(GL_FRAMEBUFFER, 0);
953 glBindFramebuffer(GL_FRAMEBUFFER, m_fb0);
955 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
956 g_texture_rectangle_format, m_cache_tex[0], 0);
958 GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
960 glBindFramebuffer(GL_FRAMEBUFFER, 0);
962 if (fb_status != GL_FRAMEBUFFER_COMPLETE) {
965 _T(
" OpenGL-> buildFBOSize->Framebuffer Incomplete: %08X %08X"),
975 void glChartCanvas::BuildFBO() {
978 glDeleteTextures(2, m_cache_tex);
979 glDeleteFramebuffers(1, &m_fb0);
980 glDeleteRenderbuffers(1, &m_renderbuffer);
981 m_b_BuiltFBO =
false;
984 if (m_b_DisableFBO)
return;
987 int gl_width, gl_height;
988 m_pParentCanvas->GetClientSize(&gl_width, &gl_height);
989 int initialSize = NextPow2(gl_width * m_displayScale);
994 wxString info = androidGetDeviceInfo();
996 if (wxNOT_FOUND != info.Find(_T(
"GT-S6312"))) initialSize = 1024;
999 if (!buildFBOSize(initialSize)) {
1000 glDeleteTextures(2, m_cache_tex);
1001 glDeleteFramebuffers(1, &m_fb0);
1002 glDeleteRenderbuffers(1, &m_renderbuffer);
1004 if (!buildFBOSize(1024)) {
1005 wxLogMessage(_T(
"BuildFBO C"));
1007 m_b_DisableFBO =
true;
1008 wxLogMessage(_T(
"OpenGL-> FBO Framebuffer unavailable"));
1009 m_b_BuiltFBO =
false;
1018 msg.Printf(_T(
"OpenGL-> Framebuffer OK, size = %d"), m_cache_tex_x);
1024 glClear(GL_COLOR_BUFFER_BIT);
1025 m_b_BuiltFBO =
true;
1030 void glChartCanvas::SetupOpenGL() {
1031 SetCurrent(*m_pcontext);
1033 char *str = (
char *)glGetString(GL_RENDERER);
1036 wxLogMessage(_T(
"Failed to initialize OpenGL"));
1040 char render_string[80];
1041 strncpy(render_string, str, 79);
1042 m_renderer = wxString(render_string, wxConvUTF8);
1045 if (g_bSoftwareGL) msg.Printf(_T(
"OpenGL-> Software OpenGL"));
1046 msg.Printf(_T(
"OpenGL-> Renderer String: "));
1050 if (ps52plib) ps52plib->SetGLRendererString(m_renderer);
1052 char version_string[80];
1053 strncpy(version_string, (
char *)glGetString(GL_VERSION), 79);
1054 msg.Printf(_T(
"OpenGL-> Version reported: "));
1055 m_version = wxString(version_string, wxConvUTF8);
1059 char GLSL_version_string[80];
1060 strncpy(GLSL_version_string, (
char *)glGetString(GL_SHADING_LANGUAGE_VERSION), 79);
1061 msg.Printf(_T(
"OpenGL-> GLSL Version reported: "));
1062 m_GLSLversion = wxString(GLSL_version_string, wxConvUTF8);
1063 msg += m_GLSLversion;
1068 GLenum err = glewInit();
1069 #ifdef GLEW_ERROR_NO_GLX_DISPLAY
1070 if (GLEW_OK != err && GLEW_ERROR_NO_GLX_DISPLAY != err)
1075 printf(
"GLEW init failed: %s\n", glewGetErrorString(err));
1080 wxLogMessage(
"GLEW init success!n");
1085 const GLubyte *ext_str = glGetString(GL_EXTENSIONS);
1086 m_extensions = wxString((
const char *)ext_str, wxConvUTF8);
1090 #ifndef USE_ANDROID_GLES2
1091 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
1093 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
1095 g_GLMinSymbolLineWidth = wxMax(parms[0], 1);
1096 g_GLMinCartographicLineWidth = wxMax(parms[0], 1);
1103 if (m_renderer.Upper().Find(_T(
"MESA")) != wxNOT_FOUND) {
1105 glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &parf);
1107 g_GLMinSymbolLineWidth = wxMax(((
float)parms[0] + parf), 1);
1110 s_b_useScissorTest =
true;
1112 if (GetRendererString().Find(_T(
"RADEON X600")) != wxNOT_FOUND)
1113 s_b_useScissorTest =
false;
1115 if (GetRendererString().Find(_T(
"GeForce")) !=
1117 s_b_useScissorTest =
false;
1119 bool bad_stencil_code =
false;
1122 if (GetRendererString().Find(_T(
"UniChrome")) != wxNOT_FOUND)
1123 bad_stencil_code =
true;
1126 if (GetRendererString().Find(_T(
"Mali")) != wxNOT_FOUND)
1127 bad_stencil_code =
true;
1130 glEnable(GL_STENCIL_TEST);
1131 GLboolean stencil = glIsEnabled(GL_STENCIL_TEST);
1133 glGetIntegerv(GL_STENCIL_BITS, &sb);
1136 glDisable(GL_STENCIL_TEST);
1138 s_b_useStencil =
false;
1139 if (stencil && (sb == 8)) s_b_useStencil =
true;
1141 if (QueryExtension(
"GL_ARB_texture_non_power_of_two"))
1142 g_texture_rectangle_format = GL_TEXTURE_2D;
1143 else if (QueryExtension(
"GL_OES_texture_npot"))
1144 g_texture_rectangle_format = GL_TEXTURE_2D;
1145 else if (QueryExtension(
"GL_ARB_texture_rectangle"))
1146 g_texture_rectangle_format = GL_TEXTURE_RECTANGLE_ARB;
1147 wxLogMessage(wxString::Format(_T(
"OpenGL-> Texture rectangle format: %x"),
1148 g_texture_rectangle_format));
1151 g_texture_rectangle_format = GL_TEXTURE_2D;
1155 g_b_EnableVBO =
true;
1158 g_b_EnableVBO =
false;
1162 wxLogMessage(_T(
"OpenGL-> Using Vertexbuffer Objects"));
1164 wxLogMessage(_T(
"OpenGL-> Vertexbuffer Objects unavailable"));
1168 m_b_useFBOStencil = QueryExtension(
"GL_OES_packed_depth_stencil");
1170 m_b_useFBOStencil = QueryExtension(
"GL_EXT_packed_depth_stencil") == GL_TRUE;
1173 #ifndef USE_ANDROID_GLES2
1175 if (bad_stencil_code) s_b_useStencil =
false;
1178 g_GLOptions.m_bUseCanvasPanning =
false;
1188 if (m_displayScale > 1)
1189 m_b_DisableFBO =
true;
1198 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
1200 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
1201 g_texture_rectangle_format, m_cache_tex[0], 0);
1203 GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
1204 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
1206 if (fb_status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1208 msg.Printf(_T(
" OpenGL-> Framebuffer Incomplete: %08X"), fb_status);
1210 m_b_DisableFBO =
true;
1216 if (m_b_BuiltFBO && !m_b_useFBOStencil) s_b_useStencil =
false;
1220 s_b_useStencilAP = s_b_useStencil & !bad_stencil_code;
1222 #ifdef USE_ANDROID_GLES2
1223 s_b_useStencilAP = s_b_useStencil;
1230 wxLogMessage(_T(
"OpenGL-> Using Framebuffer Objects"));
1232 if (m_b_useFBOStencil)
1233 wxLogMessage(_T(
"OpenGL-> Using FBO Stencil buffer"));
1235 wxLogMessage(_T(
"OpenGL-> FBO Stencil buffer unavailable"));
1237 wxLogMessage(_T(
"OpenGL-> Framebuffer Objects unavailable"));
1240 wxLogMessage(_T(
"OpenGL-> Using Stencil buffer clipping"));
1242 wxLogMessage(_T(
"OpenGL-> Using Depth buffer clipping"));
1244 if (s_b_useScissorTest && s_b_useStencil)
1245 wxLogMessage(_T(
"OpenGL-> Using Scissor Clipping"));
1248 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1250 MipMap_ResolveRoutines();
1254 lwmsg.Printf(_T(
"OpenGL-> Minimum cartographic line width: %4.1f"),
1255 g_GLMinCartographicLineWidth);
1256 wxLogMessage(lwmsg);
1257 lwmsg.Printf(_T(
"OpenGL-> Minimum symbol line width: %4.1f"),
1258 g_GLMinSymbolLineWidth);
1259 wxLogMessage(lwmsg);
1263 g_GLOptions.m_bUseAcceleratedPanning = !m_b_DisableFBO && m_b_BuiltFBO;
1265 #ifdef USE_ANDROID_GLES2
1266 g_GLOptions.m_bUseAcceleratedPanning =
true;
1272 int tex_dim = g_GLOptions.m_iTextureDimension;
1273 for (
int dim = tex_dim; dim > 0; dim /= 2) max_level++;
1274 g_mipmap_max_level = max_level - 1;
1279 g_mipmap_max_level = 4;
1282 s_b_useFBO = m_b_BuiltFBO;
1286 ps52plib->SetGLOptions(s_b_useStencil, s_b_useStencilAP, s_b_useScissorTest,
1287 s_b_useFBO, g_b_EnableVBO,
1288 g_texture_rectangle_format,
1289 g_GLMinCartographicLineWidth,
1290 g_GLMinSymbolLineWidth );
1294 SendJSONConfigMessage();
1297 void glChartCanvas::SendJSONConfigMessage() {
1300 v[_T(
"setupComplete")] = m_bsetup;
1301 v[_T(
"useStencil")] = s_b_useStencil;
1302 v[_T(
"useStencilAP")] = s_b_useStencilAP;
1303 v[_T(
"useScissorTest")] = s_b_useScissorTest;
1304 v[_T(
"useFBO")] = s_b_useFBO;
1305 v[_T(
"useVBO")] = g_b_EnableVBO;
1306 v[_T(
"TextureRectangleFormat")] = g_texture_rectangle_format;
1307 wxString msg_id(_T(
"OCPN_OPENGL_CONFIG"));
1308 g_pi_manager->SendJSONMessageToAllPlugins(msg_id, v);
1311 void glChartCanvas::SetupCompression() {
1312 int dim = g_GLOptions.m_iTextureDimension;
1315 if (!::IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
1316 wxLogMessage(_T(
"OpenGL-> SSE2 Instruction set not available"));
1317 goto no_compression;
1321 g_uncompressed_tile_size = dim * dim * 4;
1322 if (!g_GLOptions.m_bTextureCompression)
goto no_compression;
1324 g_raster_format = GL_RGB;
1328 if (QueryExtension(
"GL_OES_compressed_ETC1_RGB8_texture")) {
1329 g_raster_format = GL_ETC1_RGB8_OES;
1331 wxLogMessage(_T(
"OpenGL-> Using oes etc1 compression"));
1335 if (GL_RGB == g_raster_format) {
1341 if ((QueryExtension(
"GL_EXT_texture_compression_s3tc") ||
1342 QueryExtension(
"GL_EXT_texture_compression_dxt1"))
1346 if (GetRendererString().Find(_T(
"Gallium")) != wxNOT_FOUND &&
1347 GetRendererString().Find(_T(
"NV")) != wxNOT_FOUND)
1348 g_raster_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1350 g_raster_format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1352 wxLogMessage(_T(
"OpenGL-> Using s3tc dxt1 compression"));
1353 }
else if (QueryExtension(
"GL_3DFX_texture_compression_FXT1")
1355 g_raster_format = GL_COMPRESSED_RGB_FXT1_3DFX;
1357 wxLogMessage(_T(
"OpenGL-> Using 3dfx fxt1 compression"));
1359 wxLogMessage(_T(
"OpenGL-> No Useable compression format found"));
1360 goto no_compression;
1365 g_tile_size = 512 * 512 / 2;
1369 glGenTextures(1, &texture);
1370 glBindTexture(GL_TEXTURE_2D, texture);
1371 glTexImage2D(GL_TEXTURE_2D, 0, g_raster_format, dim, dim, 0, GL_RGB,
1372 GL_UNSIGNED_BYTE, NULL);
1373 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
1375 glDeleteTextures(1, &texture);
1379 if (g_tile_size == 0)
goto no_compression;
1381 wxLogMessage(wxString::Format(
1382 _T(
"OpenGL-> Compressed tile size: %dkb (%d:1)"), g_tile_size / 1024,
1383 g_uncompressed_tile_size / g_tile_size));
1387 g_GLOptions.m_bTextureCompression =
false;
1389 g_tile_size = g_uncompressed_tile_size;
1390 wxLogMessage(wxString::Format(_T(
"OpenGL-> Not Using compression")));
1393 void glChartCanvas::OnPaint(wxPaintEvent &event) {
1396 if (!m_pcontext)
return;
1404 SetCurrent(*m_pcontext);
1409 if (ps52plib) ps52plib->FlushSymbolCaches(ChartCtxFactory());
1417 if (!m_b_paint_enable)
return;
1420 if (m_in_glpaint)
return;
1423 m_pParentCanvas->UpdateCanvasS52PLIBConfig();
1446 bool glChartCanvas::HasNormalizedViewPort(
const ViewPort &vp) {
1448 #ifndef USE_ANDROID_GLES2
1449 return vp.m_projection_type == PROJECTION_MERCATOR ||
1450 vp.m_projection_type == PROJECTION_POLAR ||
1451 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1465 #define NORM_FACTOR 4096.0
1466 void glChartCanvas::MultMatrixViewPort(
ViewPort &vp,
float lat,
float lon) {
1467 #ifndef USE_ANDROID_GLES2
1469 wxPoint2DDouble point;
1471 switch (vp.m_projection_type) {
1472 case PROJECTION_MERCATOR:
1473 case PROJECTION_EQUIRECTANGULAR:
1474 case PROJECTION_WEB_MERCATOR:
1476 point = vp.GetDoublePixFromLL(lat, lon);
1477 glTranslated(point.m_x, point.m_y, 0);
1478 glScaled(vp.view_scale_ppm / NORM_FACTOR, vp.view_scale_ppm / NORM_FACTOR,
1482 case PROJECTION_POLAR:
1485 point = vp.GetDoublePixFromLL(vp.clat > 0 ? 90 : -90, vp.clon);
1486 glTranslated(point.m_x, point.m_y, 0);
1487 glRotatef(vp.clon - lon, 0, 0, vp.clat);
1488 glScalef(vp.view_scale_ppm / NORM_FACTOR, vp.view_scale_ppm / NORM_FACTOR,
1490 glTranslatef(-vp.pix_width / 2, -vp.pix_height / 2, 0);
1494 printf(
"ERROR: Unhandled projection\n");
1497 double rotation = vp.rotation;
1499 if (rotation) glRotatef(rotation * 180 / PI, 0, 0, 1);
1507 switch (vp.m_projection_type) {
1508 case PROJECTION_MERCATOR:
1509 case PROJECTION_EQUIRECTANGULAR:
1510 case PROJECTION_WEB_MERCATOR:
1514 case PROJECTION_POLAR:
1515 cvp.clat = vp.clat > 0 ? 90 : -90;
1519 printf(
"ERROR: Unhandled projection\n");
1523 cvp.view_scale_ppm = NORM_FACTOR;
1524 cvp.rotation = cvp.skew = 0;
1528 bool glChartCanvas::CanClipViewport(
const ViewPort &vp) {
1529 return vp.m_projection_type == PROJECTION_MERCATOR ||
1530 vp.m_projection_type == PROJECTION_WEB_MERCATOR ||
1531 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1535 const LLRegion ®ion) {
1536 if (!CanClipViewport(vp))
return vp;
1539 LLBBox bbox = region.GetBox();
1541 if (!bbox.GetValid())
return vp;
1549 if (bbox.GetMaxLon() < cvp.GetBBox().GetMinLon()) {
1550 bbox.Set(bbox.GetMinLat(), bbox.GetMinLon() + 360, bbox.GetMaxLat(),
1551 bbox.GetMaxLon() + 360);
1552 cvp.SetBBoxDirect(bbox);
1553 }
else if (bbox.GetMinLon() > cvp.GetBBox().GetMaxLon()) {
1554 bbox.Set(bbox.GetMinLat(), bbox.GetMinLon() - 360, bbox.GetMaxLat(),
1555 bbox.GetMaxLon() - 360);
1556 cvp.SetBBoxDirect(bbox);
1558 cvp.SetBBoxDirect(bbox);
1563 void glChartCanvas::DrawStaticRoutesTracksAndWaypoints(
ViewPort &vp) {
1564 if (!m_pParentCanvas->m_bShowNavobjects)
return;
1567 for (
Track* pTrackDraw : g_TrackList) {
1570 if (pActiveTrack && pActiveTrack->IsRunning())
continue;
1572 TrackGui(*pTrackDraw).Draw(m_pParentCanvas, dc, vp, vp.GetBBox());
1575 for (wxRouteListNode *node = pRouteList->GetFirst(); node;
1576 node = node->GetNext()) {
1577 Route *pRouteDraw = node->GetData();
1579 if (!pRouteDraw)
continue;
1582 if (pRouteDraw->IsActive() || pRouteDraw->IsSelected())
continue;
1585 if (pRouteDraw->m_bIsBeingEdited)
continue;
1587 RouteGui(*pRouteDraw).DrawGL(vp, m_pParentCanvas, dc);
1592 if (vp.GetBBox().GetValid() && pWayPointMan) {
1593 for (wxRoutePointListNode *pnode =
1594 pWayPointMan->GetWaypointList()->GetFirst();
1595 pnode; pnode = pnode->GetNext()) {
1597 if (pWP && (!pWP->m_bRPIsBeingEdited) && (!pWP->m_bIsInRoute))
1598 if (vp.GetBBox().ContainsMarge(pWP->m_lat, pWP->m_lon, .5))
1605 void glChartCanvas::DrawDynamicRoutesTracksAndWaypoints(
ViewPort &vp) {
1608 for (
Track* pTrackDraw : g_TrackList) {
1610 if (pActiveTrack && pActiveTrack->IsRunning())
1611 TrackGui(*pTrackDraw).Draw(m_pParentCanvas, dc, vp, vp.GetBBox());
1615 for (wxRouteListNode *node = pRouteList->GetFirst(); node;
1616 node = node->GetNext()) {
1617 Route *pRouteDraw = node->GetData();
1620 if (!pRouteDraw)
continue;
1623 if (pRouteDraw->IsActive() || pRouteDraw->IsSelected()) drawit++;
1626 if (pRouteDraw->m_bIsBeingEdited) drawit++;
1629 if (pRouteDraw->IsSelected()) drawit++;
1632 const LLBBox &vp_box = vp.GetBBox(), &test_box = pRouteDraw->GetBBox();
1633 if (!vp_box.IntersectOut(test_box))
1634 RouteGui(*pRouteDraw).DrawGL(vp, m_pParentCanvas, dc);
1640 if (vp.GetBBox().GetValid() && pWayPointMan) {
1641 for (wxRoutePointListNode *pnode =
1642 pWayPointMan->GetWaypointList()->GetFirst();
1643 pnode; pnode = pnode->GetNext()) {
1645 if (pWP && pWP->m_bRPIsBeingEdited && !pWP->m_bIsInRoute)
1652 static void GetLatLonCurveDist(
const ViewPort &vp,
float &lat_dist,
1656 switch (vp.m_projection_type) {
1657 case PROJECTION_TRANSVERSE_MERCATOR:
1658 lat_dist = 4, lon_dist = 1;
1660 case PROJECTION_POLYCONIC:
1661 lat_dist = 2, lon_dist = 1;
1663 case PROJECTION_ORTHOGRAPHIC:
1664 lat_dist = 2, lon_dist = 2;
1666 case PROJECTION_POLAR:
1667 lat_dist = 180, lon_dist = 1;
1669 case PROJECTION_STEREOGRAPHIC:
1670 case PROJECTION_GNOMONIC:
1671 lat_dist = 2, lon_dist = 1;
1673 case PROJECTION_EQUIRECTANGULAR:
1676 lat_dist = 2, lon_dist = 360;
1679 lat_dist = 180, lon_dist = 360;
1683 void glChartCanvas::RenderChartOutline(
ocpnDC &dc,
int dbIndex,
ViewPort &vp) {
1684 if (ChartData->GetDBChartType(dbIndex) == CHART_TYPE_PLUGIN &&
1685 !ChartData->IsChartAvailable(dbIndex))
1690 ChartData->GetDBBoundingBox(dbIndex, box);
1691 if (!box.GetValid())
return;
1695 if (box.GetLonRange() == 360)
return;
1697 LLBBox vpbox = vp.GetBBox();
1699 double lon_bias = 0;
1701 if (box.IntersectOutGetBias(vp.GetBBox(), lon_bias))
return;
1705 if (ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93)
1706 color = GetGlobalColor(_T (
"YELO1" ));
1707 else if (ChartData->GetDBChartFamily(dbIndex) == CHART_FAMILY_VECTOR)
1708 color = GetGlobalColor(_T (
"GREEN2" ));
1710 color = GetGlobalColor(_T (
"UINFR" ));
1712 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1713 float plylat, plylon;
1715 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
1717 glColor3ub(color.Red(), color.Green(), color.Blue());
1718 glLineWidth(g_GLMinSymbolLineWidth);
1720 float lat_dist, lon_dist;
1721 GetLatLonCurveDist(vp, lat_dist, lon_dist);
1724 int nAuxPlyEntries = ChartData->GetnAuxPlyEntries(dbIndex), nPly;
1728 nPly = ChartData->GetDBAuxPlyPoint(dbIndex, 0, j, 0, 0);
1730 nPly = ChartData->GetDBPlyPoint(dbIndex, 0, &plylat, &plylon);
1732 bool begin =
false, sml_valid =
false;
1734 float lastplylat = 0.0;
1735 float lastplylon = 0.0;
1737 int modulo = (nPly == 0) ? 1 : nPly;
1738 for (
int i = 0; i < nPly + 1; i++) {
1740 ChartData->GetDBAuxPlyPoint(dbIndex, i % modulo, j, &plylat, &plylon);
1742 ChartData->GetDBPlyPoint(dbIndex, i % modulo, &plylat, &plylon);
1746 if (lastplylon - plylon > 180)
1748 else if (lastplylon - plylon < -180)
1755 int lat_splits = floor(fabs(plylat - lastplylat) / lat_dist);
1756 int lon_splits = floor(fabs(plylon - lastplylon) / lon_dist);
1757 splits = wxMax(lat_splits, lon_splits) + 1;
1764 toSM(plylat, plylon, 0, 0, smj + 0, smj + 1);
1765 if (!sml_valid) toSM(lastplylat, lastplylon, 0, 0, sml + 0, sml + 1);
1768 for (
double c = 0; c < splits; c++) {
1770 if (c == splits - 1)
1771 lat = plylat, lon = plylon;
1773 double d = (double)(c + 1) / splits;
1774 fromSM(d * smj[0] + (1 - d) * sml[0], d * smj[1] + (1 - d) * sml[1],
1779 m_pParentCanvas->GetDoubleCanvasPointPix(lat, lon, &s);
1780 if (!std::isnan(s.m_x)) {
1783 glBegin(GL_LINE_STRIP);
1785 glVertex2f(s.m_x, s.m_y);
1791 if ((sml_valid = splits != 1)) memcpy(sml, smj,
sizeof smj);
1792 lastplylat = plylat, lastplylon = plylon;
1797 }
while (++j < nAuxPlyEntries);
1799 glDisable(GL_LINE_SMOOTH);
1803 double nominal_line_width_pix =
1804 wxMax(2.0, floor(m_pParentCanvas->GetPixPerMM() / 4));
1806 if (ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93)
1807 dc.SetPen(wxPen(GetGlobalColor(_T (
"YELO1" )), nominal_line_width_pix,
1810 else if (ChartData->GetDBChartFamily(dbIndex) == CHART_FAMILY_VECTOR)
1811 dc.SetPen(wxPen(GetGlobalColor(_T (
"UINFG" )), nominal_line_width_pix,
1815 dc.SetPen(wxPen(GetGlobalColor(_T (
"UINFR" )), nominal_line_width_pix,
1818 float plylat1, plylon1;
1822 int nAuxPlyEntries = ChartData->GetnAuxPlyEntries(dbIndex);
1823 if (0 == nAuxPlyEntries)
1826 std::vector<int> points_vector;
1828 std::vector<float> vec = ChartData->GetReducedPlyPoints(dbIndex);
1829 int nPly = vec.size() / 2;
1831 if (nPly == 0)
return;
1833 for (
int i = 0; i < nPly; i++) {
1834 plylon1 = vec[i * 2];
1835 plylat1 = vec[i * 2 + 1];
1837 m_pParentCanvas->GetCanvasPointPix(plylat1, plylon1, &r1);
1841 points_vector.push_back(pixx1);
1842 points_vector.push_back(pixy1);
1845 ChartData->GetDBPlyPoint(dbIndex, 0, &plylat1, &plylon1);
1846 plylon1 += lon_bias;
1848 m_pParentCanvas->GetCanvasPointPix(vec[1], vec[0], &r1);
1852 points_vector.push_back(pixx1);
1853 points_vector.push_back(pixy1);
1855 if (points_vector.size()) {
1856 std::vector<int>::iterator it = points_vector.begin();
1857 dc.DrawLines(points_vector.size() / 2, (wxPoint *)&(*it), 0, 0,
true);
1865 for (
int j = 0; j < nAuxPlyEntries; j++) {
1866 std::vector<int> points_vector;
1868 std::vector<float> vec = ChartData->GetReducedAuxPlyPoints(dbIndex, j);
1869 int nAuxPly = vec.size() / 2;
1871 if (nAuxPly == 0)
continue;
1873 for (
int i = 0; i < nAuxPly; i++) {
1874 plylon1 = vec[i * 2];
1875 plylat1 = vec[i * 2 + 1];
1877 m_pParentCanvas->GetCanvasPointPix(plylat1, plylon1, &r1);
1881 points_vector.push_back(pixx1);
1882 points_vector.push_back(pixy1);
1885 m_pParentCanvas->GetCanvasPointPix(vec[1], vec[0], &r1);
1889 points_vector.push_back(pixx1);
1890 points_vector.push_back(pixy1);
1892 if (points_vector.size()) {
1893 std::vector<int>::iterator it = points_vector.begin();
1894 dc.DrawLines(points_vector.size() / 2, (wxPoint *)&(*it), 0, 0,
true);
1902 extern void CalcGridSpacing(
float WindowDegrees,
float &MajorSpacing,
1903 float &MinorSpacing);
1904 extern wxString CalcGridText(
float latlon,
float spacing,
bool bPostfix);
1905 void glChartCanvas::GridDraw() {
1906 if (!m_pParentCanvas->m_bDisplayGrid)
return;
1908 ViewPort &vp = m_pParentCanvas->GetVP();
1910 if (!vp.IsValid() || !vp.GetBBox().GetValid())
return;
1914 fabs(vp.rotation) < 0.0001 && vp.m_projection_type == PROJECTION_MERCATOR;
1916 double nlat, elon, slat, wlon;
1918 float gridlatMajor, gridlatMinor, gridlonMajor, gridlonMinor;
1921 wxColour GridColor = GetGlobalColor(_T (
"SNDG1" ));
1923 if (!m_gridfont.IsBuilt()) {
1924 double dpi_factor = g_BasePlatform->GetDisplayDIPMult(
this);
1925 wxFont *dFont = FontMgr::Get().GetFont(_(
"GridText"), 0);
1926 wxFont font = *dFont;
1927 int font_size = wxMax(10, dFont->GetPointSize());
1928 font.SetPointSize(font_size * m_displayScale);
1929 font.SetWeight(wxFONTWEIGHT_NORMAL);
1931 m_gridfont.SetContentScaleFactor(OCPN_GetDisplayContentScaleFactor());
1932 m_gridfont.Build(font, 1, dpi_factor);
1934 m_gridfont.SetColor(GridColor);
1939 LLBBox llbbox = vp.GetBBox();
1940 nlat = llbbox.GetMaxLat();
1941 slat = llbbox.GetMinLat();
1942 elon = llbbox.GetMaxLon();
1943 wlon = llbbox.GetMinLon();
1946 CalcGridSpacing(vp.view_scale_ppm, gridlatMajor, gridlatMinor);
1947 CalcGridSpacing(vp.view_scale_ppm, gridlonMajor, gridlonMinor);
1950 bool straight_latitudes = vp.m_projection_type == PROJECTION_MERCATOR ||
1951 vp.m_projection_type == PROJECTION_WEB_MERCATOR ||
1952 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1953 bool straight_longitudes = vp.m_projection_type == PROJECTION_MERCATOR ||
1954 vp.m_projection_type == PROJECTION_WEB_MERCATOR ||
1955 vp.m_projection_type == PROJECTION_POLAR ||
1956 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1959 if (straight_latitudes)
1962 latmargin = gridlatMajor / 2;
1964 slat = wxMax(slat, -90 + latmargin);
1965 nlat = wxMin(nlat, 90 - latmargin);
1967 float startlat = ceil(slat / gridlatMajor) * gridlatMajor;
1968 float startlon = ceil(wlon / gridlonMajor) * gridlonMajor;
1969 float curved_step = wxMin(sqrt(5e-3 / vp.view_scale_ppm), 3);
1972 wxPen *pen = wxThePenList->FindOrCreatePen(GridColor, g_GLMinSymbolLineWidth,
1979 float lon_step = elon - wlon;
1980 if (!straight_latitudes) lon_step /= ceil(lon_step / curved_step);
1982 for (lat = startlat; lat < nlat; lat += gridlatMajor) {
1983 wxPoint2DDouble r, s;
1986 for (lon = wlon; lon < elon + lon_step / 2; lon += lon_step) {
1987 m_pParentCanvas->GetDoubleCanvasPointPix(lat, lon, &r);
1988 if (!std::isnan(s.m_x) && !std::isnan(r.m_x)) {
1989 gldc.DrawLine(s.m_x, s.m_y, r.m_x, r.m_y,
false);
1997 for (lat = ceil(slat / gridlatMinor) * gridlatMinor; lat < nlat;
1998 lat += gridlatMinor) {
2000 m_pParentCanvas->GetCanvasPointPix(lat, (elon + wlon) / 2, &r);
2001 gldc.DrawLine(0, r.y, 10, r.y,
true);
2002 gldc.DrawLine(w - 10, r.y, w, r.y,
false);
2004 lat = lat + gridlatMinor;
2009 float lat_step = nlat - slat;
2010 if (!straight_longitudes) lat_step /= ceil(lat_step / curved_step);
2012 for (lon = startlon; lon < elon; lon += gridlonMajor) {
2013 wxPoint2DDouble r, s;
2015 for (lat = slat; lat < nlat + lat_step / 2; lat += lat_step) {
2016 m_pParentCanvas->GetDoubleCanvasPointPix(lat, lon, &r);
2018 if (!std::isnan(s.m_x) && !std::isnan(r.m_x)) {
2019 gldc.DrawLine(s.m_x, s.m_y, r.m_x, r.m_y,
false);
2027 for (lon = ceil(wlon / gridlonMinor) * gridlonMinor; lon < elon;
2028 lon += gridlonMinor) {
2030 m_pParentCanvas->GetCanvasPointPix((nlat + slat) / 2, lon, &r);
2031 gldc.DrawLine(r.x, 0, r.x, 10,
false);
2032 gldc.DrawLine(r.x, h - 10, r.x, h,
false);
2037 if( abs(vp.rotation) < .1){
2038 glEnable(GL_TEXTURE_2D);
2040 for (lat = startlat; lat < nlat; lat += gridlatMajor) {
2041 if (fabs(lat - wxRound(lat)) < 1e-5) lat = wxRound(lat);
2044 CalcGridText(lat, gridlatMajor,
true);
2046 m_gridfont.GetTextExtent(st, 0, &iy);
2048 if (straight_latitudes) {
2050 m_pParentCanvas->GetCanvasPointPix(lat, elon, &r);
2051 m_pParentCanvas->GetCanvasPointPix(lat, wlon, &s);
2053 float x = 0, y = -1;
2054 y = (float)(r.y * s.x - s.y * r.x) / (s.x - r.x);
2055 if (y < 0 || y > h) {
2057 x = (float)(r.x * s.y - s.x * r.y + (s.x - r.x) * y) / (s.y - r.y);
2060 m_gridfont.RenderString(st, x, y);
2064 double y1, y2, lat1, lon1, lat2, lon2;
2066 y1 = 0, y2 = vp.pix_height;
2067 double error = vp.pix_width, lasterror;
2070 m_pParentCanvas->GetCanvasPixPoint(0, y1, lat1, lon1);
2071 m_pParentCanvas->GetCanvasPixPoint(0, y2, lat2, lon2);
2073 double y = y1 + (lat1 - lat) * (y2 - y1) / (lat1 - lat2);
2075 m_pParentCanvas->GetDoubleCanvasPointPix(
2076 lat, lon1 + (y1 - y) * (lon2 - lon1) / (y1 - y2), &r);
2078 if (fabs(y - y1) < fabs(y - y2))
2084 error = fabs(r.m_x);
2085 if (--maxiters == 0)
break;
2086 }
while (error > 1 && error < lasterror);
2088 if (error < 1 && r.m_y >= 0 && r.m_y <= vp.pix_height - iy)
2092 m_pParentCanvas->GetDoubleCanvasPointPix(lat, vp.clon, &r);
2094 m_gridfont.RenderString(st, r.m_x, r.m_y);
2098 for (lon = startlon; lon < elon; lon += gridlonMajor) {
2099 if (fabs(lon - wxRound(lon)) < 1e-5) lon = wxRound(lon);
2102 m_pParentCanvas->GetCanvasPointPix(nlat, lon, &r);
2103 m_pParentCanvas->GetCanvasPointPix(slat, lon, &s);
2108 else if (xlon <= -180.0)
2111 wxString st = CalcGridText(xlon, gridlonMajor,
false);
2113 m_gridfont.GetTextExtent(st, &ix, 0);
2115 if (straight_longitudes) {
2116 float x = -1, y = 0;
2117 x = (float)(r.x * s.y - s.x * r.y) / (s.y - r.y);
2118 if (x < 0 || x > w) {
2120 y = (float)(r.y * s.x - s.y * r.x + (s.y - r.y) * x) / (s.x - r.x);
2123 m_gridfont.RenderString(st, x, y);
2127 double x1, x2, lat1, lon1, lat2, lon2;
2129 x1 = 0, x2 = vp.pix_width;
2130 double error = vp.pix_height, lasterror;
2132 m_pParentCanvas->GetCanvasPixPoint(x1, 0, lat1, lon1);
2133 m_pParentCanvas->GetCanvasPixPoint(x2, 0, lat2, lon2);
2135 double x = x1 + (lon1 - lon) * (x2 - x1) / (lon1 - lon2);
2137 m_pParentCanvas->GetDoubleCanvasPointPix(
2138 lat1 + (x1 - x) * (lat2 - lat1) / (x1 - x2), lon, &r);
2140 if (fabs(x - x1) < fabs(x - x2))
2146 error = fabs(r.m_y);
2147 }
while (error > 1 && error < lasterror);
2149 if (error < 1 && r.m_x >= 0 && r.m_x <= vp.pix_width - ix)
2153 m_pParentCanvas->GetDoubleCanvasPointPix(
2154 wxMin(wxMax(vp.clat, slat), nlat), lon, &r);
2156 m_gridfont.RenderString(st, r.m_x, r.m_y);
2160 glDisable(GL_TEXTURE_2D);
2161 glDisable(GL_BLEND);
2166 if (!emboss)
return;
2168 int w = emboss->width, h = emboss->height;
2170 glEnable(GL_TEXTURE_2D);
2173 if (!emboss->gltexind) {
2175 emboss->glwidth = NextPow2(emboss->width);
2176 emboss->glheight = NextPow2(emboss->height);
2179 int size = emboss->glwidth * emboss->glheight;
2180 char *data =
new char[2 * size];
2181 for (
int i = 0; i < h; i++) {
2182 for (
int j = 0; j < emboss->glwidth; j++) {
2184 data[2 * ((i * emboss->glwidth) + j)] =
2185 (char)(emboss->pmap[(i * w) + j] > 0 ? 0 : 255);
2186 data[2 * ((i * emboss->glwidth) + j) + 1] =
2187 (char)abs((emboss->pmap[(i * w) + j]));
2192 glGenTextures(1, &emboss->gltexind);
2193 glBindTexture(GL_TEXTURE_2D, emboss->gltexind);
2194 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, emboss->glwidth,
2195 emboss->glheight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
2197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2198 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2203 glBindTexture(GL_TEXTURE_2D, emboss->gltexind);
2207 int x = emboss->x, y = emboss->y;
2209 float wp = (float)w / emboss->glwidth;
2210 float hp = (
float)h / emboss->glheight;
2236 RenderSingleTexture(dc, coords, uv, m_pParentCanvas->GetpVP(), x, y, 0);
2238 glDisable(GL_BLEND);
2239 glDisable(GL_TEXTURE_2D);
2242 void glChartCanvas::ShipDraw(
ocpnDC &dc) {
2243 if (!m_pParentCanvas->GetVP().IsValid())
return;
2244 wxPoint lGPSPoint, lShipMidPoint, GPSOffsetPixels(0, 0);
2247 float pCog = std::isnan(gCog) ? 0 : gCog;
2248 float pSog = std::isnan(gSog) ? 0 : gSog;
2250 m_pParentCanvas->GetCanvasPointPix(gLat, gLon, &lGPSPoint);
2251 lShipMidPoint = lGPSPoint;
2255 float icon_hdt = pCog;
2256 if (!std::isnan(gHdt)) icon_hdt = gHdt;
2259 if (std::isnan(icon_hdt)) icon_hdt = 0.0;
2263 double osd_head_lat, osd_head_lon;
2264 wxPoint osd_head_point;
2266 ll_gc_ll(gLat, gLon, icon_hdt, pSog * 10. / 60., &osd_head_lat,
2269 m_pParentCanvas->GetCanvasPointPix(osd_head_lat, osd_head_lon,
2272 float icon_rad = atan2f((
float)(osd_head_point.y - lShipMidPoint.y),
2273 (
float)(osd_head_point.x - lShipMidPoint.x));
2274 icon_rad += (float)PI;
2278 ((icon_hdt + 90.) * PI / 180.) + m_pParentCanvas->GetVP().rotation;
2282 BoundingBox bb_screen(0, 0, m_pParentCanvas->GetVP().pix_width,
2283 m_pParentCanvas->GetVP().pix_height);
2288 if (bb_screen.PointInBox(lShipMidPoint, 20)) {
2289 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
2290 if (g_GLOptions.m_GLPolygonSmoothing) glEnable(GL_POLYGON_SMOOTH);
2292 if (m_pParentCanvas->GetVP().chart_scale >
2295 float scale_factor = 1.0;
2297 if ((g_ChartScaleFactorExp > 1.0) && (g_OwnShipIconType == 0))
2298 scale_factor = (log(g_ChartScaleFactorExp) + 1.0) * 1.1;
2300 float nominal_ownship_size_mm = m_pParentCanvas->m_display_size_mm / 44.0;
2301 nominal_ownship_size_mm = wxMin(nominal_ownship_size_mm, 15.0);
2302 nominal_ownship_size_mm = wxMax(nominal_ownship_size_mm, 7.0);
2304 scale_factor *= m_pParentCanvas->GetContentScaleFactor();
2306 float nominal_ownship_size_pixels =
2307 wxMax(20.0, m_pParentCanvas->GetPixPerMM() *
2308 nominal_ownship_size_mm);
2310 float v = (nominal_ownship_size_pixels * scale_factor) / 3;
2312 wxPen ppSmallScaleShip;
2313 if (SHIP_NORMAL == m_pParentCanvas->m_ownship_state)
2314 ppSmallScaleShip = wxPen(GetGlobalColor(_T (
"URED" )), v / 5, wxPENSTYLE_SOLID);
2316 ppSmallScaleShip = wxPen(GetGlobalColor(_T (
"YELO1" )), v / 5, wxPENSTYLE_SOLID);
2317 dc.SetPen(ppSmallScaleShip);
2319 dc.SetBrush(wxBrush(GetGlobalColor(_T (
"URED" )), wxBRUSHSTYLE_TRANSPARENT));
2322 dc.DrawLine((-v * 1.2) + lShipMidPoint.x, lShipMidPoint.y,
2323 (v * 1.2) + lShipMidPoint.x, lShipMidPoint.y);
2324 dc.DrawLine(lShipMidPoint.x, (-v * 1.2) + lShipMidPoint.y,
2325 lShipMidPoint.x, (v * 1.2) + lShipMidPoint.y);
2328 dc.StrokeCircle(lShipMidPoint.x, lShipMidPoint.y, v);
2329 dc.StrokeCircle(lShipMidPoint.x, lShipMidPoint.y, 0.6 * v);
2332 int draw_color = SHIP_INVALID;
2333 if (SHIP_NORMAL == m_pParentCanvas->m_ownship_state)
2334 draw_color = SHIP_NORMAL;
2335 else if (SHIP_LOWACCURACY == m_pParentCanvas->m_ownship_state)
2336 draw_color = SHIP_LOWACCURACY;
2344 ownship_color = draw_color;
2346 if (ownship_tex) glDeleteTextures(1, &ownship_tex);
2348 glGenTextures(1, &ownship_tex);
2349 glBindTexture(GL_TEXTURE_2D, ownship_tex);
2351 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2352 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2355 if (m_pParentCanvas->m_pos_image_user) {
2356 switch (draw_color) {
2358 image = *m_pParentCanvas->m_pos_image_user_grey;
2361 image = *m_pParentCanvas->m_pos_image_user;
2363 case SHIP_LOWACCURACY:
2364 image = *m_pParentCanvas->m_pos_image_user_yellow;
2368 switch (draw_color) {
2370 image = *m_pParentCanvas->m_pos_image_grey;
2373 image = *m_pParentCanvas->m_pos_image_red;
2375 case SHIP_LOWACCURACY:
2376 image = *m_pParentCanvas->m_pos_image_yellow;
2381 int w = image.GetWidth(), h = image.GetHeight();
2382 int glw = NextPow2(w), glh = NextPow2(h);
2383 ownship_size = wxSize(w, h);
2384 ownship_tex_size = wxSize(glw, glh);
2386 unsigned char *d = image.GetData();
2387 unsigned char *a = image.GetAlpha();
2388 unsigned char *e =
new unsigned char[4 * w * h];
2391 for (
int p = 0; p < w * h; p++) {
2392 e[4 * p + 0] = d[3 * p + 0];
2393 e[4 * p + 1] = d[3 * p + 1];
2394 e[4 * p + 2] = d[3 * p + 2];
2395 e[4 * p + 3] = a[p];
2398 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glw, glh, 0, GL_RGBA,
2399 GL_UNSIGNED_BYTE, 0);
2401 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
2407 #ifndef USE_ANDROID_GLES2
2408 if (m_pParentCanvas->m_pos_image_user)
2409 glColor4ub(255, 255, 255, 255);
2410 else if (SHIP_NORMAL == m_pParentCanvas->m_ownship_state)
2411 glColor4ub(255, 0, 0, 255);
2412 else if (SHIP_LOWACCURACY == m_pParentCanvas->m_ownship_state)
2413 glColor4ub(255, 255, 0, 255);
2415 glColor4ub(128, 128, 128, 255);
2417 float scale_factor_y = 1.0;
2418 float scale_factor_x = 1.0;
2420 int ownShipWidth = 22;
2421 int ownShipLength = 84;
2422 lShipMidPoint = lGPSPoint;
2425 if (g_OwnShipIconType != 0)
2426 m_pParentCanvas->ComputeShipScaleFactor(
2427 icon_hdt, ownShipWidth, ownShipLength, lShipMidPoint,
2428 GPSOffsetPixels, lGPSPoint, scale_factor_x, scale_factor_y);
2432 int x = lShipMidPoint.x, y = lShipMidPoint.y;
2435 if ((g_ShipScaleFactorExp > 1.0) && (g_OwnShipIconType == 0)) {
2436 scale_factor_x = (log(g_ShipScaleFactorExp) + 1.0) * 1.1;
2437 scale_factor_y = (log(g_ShipScaleFactorExp) + 1.0) * 1.1;
2441 scale_factor_x *= m_pParentCanvas->GetContentScaleFactor();
2442 scale_factor_y *= m_pParentCanvas->GetContentScaleFactor();
2446 float gps_circle_radius = 3.0;
2448 if (g_OwnShipIconType == 0) {
2450 glEnable(GL_TEXTURE_2D);
2451 glBindTexture(GL_TEXTURE_2D, ownship_tex);
2460 int image_height_bitmap = m_pParentCanvas->m_pos_image_red->GetHeight();
2461 if (m_pParentCanvas->m_pos_image_user)
2462 image_height_bitmap = m_pParentCanvas->m_pos_image_user->GetHeight();
2464 float nominal_ownship_size_mm =
2465 image_height_bitmap / m_pParentCanvas->GetPixPerMM();
2467 nominal_ownship_size_mm = wxMin(nominal_ownship_size_mm, 15.0);
2468 nominal_ownship_size_mm = wxMax(nominal_ownship_size_mm, 7.0);
2470 float nominal_ownship_size_pixels =
2471 m_pParentCanvas->GetPixPerMM() * nominal_ownship_size_mm;
2474 if (m_pParentCanvas->GetContentScaleFactor() == 1.0) {
2475 nominal_ownship_size_pixels = wxMax(
2476 20.0, nominal_ownship_size_pixels);
2479 float h = nominal_ownship_size_pixels * scale_factor_y;
2480 float w = nominal_ownship_size_pixels * scale_factor_x *
2481 ownship_size.x / ownship_size.y;
2482 float glw = ownship_tex_size.x, glh = ownship_tex_size.y;
2483 float u = ownship_size.x / glw, v = ownship_size.y / glh;
2489 gps_circle_radius = w / 5;
2491 float uv[8], coords[8];
2510 RenderSingleTexture(dc, coords, uv, m_pParentCanvas->GetpVP(), x, y,
2513 glDisable(GL_TEXTURE_2D);
2514 }
else if (g_OwnShipIconType == 1) {
2516 glEnable(GL_TEXTURE_2D);
2517 glBindTexture(GL_TEXTURE_2D, ownship_tex);
2519 float nominal_ownship_size_pixels_y = 84;
2520 float nominal_ownship_size_pixels_x = 22;
2522 float h = nominal_ownship_size_pixels_y * scale_factor_y;
2523 float w = nominal_ownship_size_pixels_x * scale_factor_x;
2525 float u = (float)ownship_size.x / ownship_tex_size.x,
2526 v = (
float)ownship_size.y / ownship_tex_size.y;
2529 gps_circle_radius = w / 5;
2531 float uv[8], coords[8];
2550 RenderSingleTexture(dc, coords, uv, m_pParentCanvas->GetpVP(), x, y,
2553 glDisable(GL_TEXTURE_2D);
2554 }
else if (g_OwnShipIconType == 2) {
2562 wxPoint shipPoints[6];
2564 wxColour colour = m_pParentCanvas->ShipColor();
2565 wxPen ppPen(*wxBLACK, 1);
2566 wxBrush ppBrush(colour);
2568 dc.SetBrush(ppBrush);
2570 shipPoints[0].x = 0 * scale_factor_x;
2571 shipPoints[0].y = -28 * scale_factor_y;
2572 shipPoints[1].x = 11 * scale_factor_x;
2573 shipPoints[1].y = -28 * scale_factor_y;
2574 shipPoints[2].x = 11 * scale_factor_x;
2575 shipPoints[2].y = 42 * scale_factor_y;
2576 shipPoints[3].x = 0 * scale_factor_x;
2577 shipPoints[3].y = 42 * scale_factor_y;
2578 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2581 shipPoints[0].x = 0 * scale_factor_x;
2582 shipPoints[0].y = -42 * scale_factor_y;
2583 shipPoints[1].x = 5 * scale_factor_x;
2584 shipPoints[1].y = -42 * scale_factor_y;
2585 shipPoints[2].x = 11 * scale_factor_x;
2586 shipPoints[2].y = -28 * scale_factor_y;
2587 shipPoints[3].x = 0 * scale_factor_x;
2588 shipPoints[3].y = -28 * scale_factor_y;
2589 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2592 shipPoints[0].x = 0 * scale_factor_x;
2593 shipPoints[0].y = -28 * scale_factor_y;
2594 shipPoints[1].x = -11 * scale_factor_x;
2595 shipPoints[1].y = -28 * scale_factor_y;
2596 shipPoints[2].x = -11 * scale_factor_x;
2597 shipPoints[2].y = 42 * scale_factor_y;
2598 shipPoints[3].x = 0 * scale_factor_x;
2599 shipPoints[3].y = 42 * scale_factor_y;
2600 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2603 shipPoints[0].x = 0 * scale_factor_x;
2604 shipPoints[0].y = -42 * scale_factor_y;
2605 shipPoints[1].x = -5 * scale_factor_x;
2606 shipPoints[1].y = -42 * scale_factor_y;
2607 shipPoints[2].x = -11 * scale_factor_x;
2608 shipPoints[2].y = -28 * scale_factor_y;
2609 shipPoints[3].x = 0 * scale_factor_x;
2610 shipPoints[3].y = -28 * scale_factor_y;
2611 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2615 double p1x = -11 * scale_factor_x;
2616 double p2x = 11 * scale_factor_x;
2620 ((p1x)*cos(icon_rad - PI / 2)) - ((p1y)*sin(icon_rad - PI / 2));
2622 ((p2x)*cos(icon_rad - PI / 2)) - ((p2y)*sin(icon_rad - PI / 2));
2624 ((p1y)*cos(icon_rad - PI / 2)) + ((p1x)*sin(icon_rad - PI / 2));
2626 ((p2y)*cos(icon_rad - PI / 2)) + ((p2x)*sin(icon_rad - PI / 2));
2627 dc.DrawLine(p1xr + lShipMidPoint.x, p1yr + lShipMidPoint.y,
2628 p2xr + lShipMidPoint.x, p2yr + lShipMidPoint.y);
2632 p1y = -42 * scale_factor_y;
2633 p2y = 42 * scale_factor_y;
2634 p1xr = ((p1x)*cos(icon_rad - PI / 2)) - ((p1y)*sin(icon_rad - PI / 2));
2635 p2xr = ((p2x)*cos(icon_rad - PI / 2)) - ((p2y)*sin(icon_rad - PI / 2));
2636 p1yr = ((p1y)*cos(icon_rad - PI / 2)) + ((p1x)*sin(icon_rad - PI / 2));
2637 p2yr = ((p2y)*cos(icon_rad - PI / 2)) + ((p2x)*sin(icon_rad - PI / 2));
2638 dc.DrawLine(p1xr + lShipMidPoint.x, p1yr + lShipMidPoint.y,
2639 p2xr + lShipMidPoint.x, p2yr + lShipMidPoint.y);
2642 img_height = ownShipLength * scale_factor_y;
2645 if (m_pParentCanvas->m_pos_image_user) gps_circle_radius = 1;
2647 float cx = lGPSPoint.x, cy = lGPSPoint.y;
2648 wxPen ppPen1(GetGlobalColor(_T (
"UBLCK" )), 1, wxPENSTYLE_SOLID);
2650 dc.SetBrush(wxBrush(GetGlobalColor(_T (
"CHWHT" ))));
2652 dc.StrokeCircle(cx, cy, gps_circle_radius);
2656 glDisable(GL_LINE_SMOOTH);
2657 glDisable(GL_POLYGON_SMOOTH);
2658 glDisable(GL_BLEND);
2661 m_pParentCanvas->ShipIndicatorsDraw(dc, img_height, GPSOffsetPixels,
2665 void glChartCanvas::DrawFloatingOverlayObjects(
ocpnDC &dc) {
2666 ViewPort &vp = m_pParentCanvas->GetVP();
2671 Route *active_route = g_pRouteMan->GetpActiveRoute();
2680 g_overlayCanvas = m_pParentCanvas;
2682 g_pi_manager->SendViewPortToRequestingPlugIns(vp);
2683 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
2684 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_LEGACY);
2689 AISDrawAreaNotices(dc, m_pParentCanvas->GetVP(), m_pParentCanvas);
2691 m_pParentCanvas->DrawAnchorWatchPoints(dc);
2692 AISDraw(dc, m_pParentCanvas->GetVP(), m_pParentCanvas);
2694 m_pParentCanvas->AlertDraw(dc);
2696 m_pParentCanvas->RenderVisibleSectorLights(dc);
2698 m_pParentCanvas->RenderRouteLegs(dc);
2699 m_pParentCanvas->RenderShipToActive(dc,
true);
2700 m_pParentCanvas->ScaleBarDraw(dc);
2701 s57_DrawExtendedLightSectorsGL(dc, m_pParentCanvas->VPoint,
2702 m_pParentCanvas->extendedSectorLegs);
2704 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
2705 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_OVER_SHIPS);
2709 void glChartCanvas::DrawChartBar(
ocpnDC &dc) {
2710 if (m_pParentCanvas->GetPiano()){
2712 int canvas_height = GetClientSize().y;
2713 canvas_height *= m_displayScale;
2715 m_pParentCanvas->GetPiano()->DrawGL(
2717 m_pParentCanvas->GetPiano()->GetHeight());
2721 void glChartCanvas::DrawQuiting() {
2722 #ifndef USE_ANDROID_GLES2
2723 GLubyte pattern[8][8];
2724 for (
int y = 0; y < 8; y++)
2725 for (
int x = 0; x < 8; x++) pattern[y][x] = (y == x) * 255;
2728 glEnable(GL_TEXTURE_2D);
2729 glBindTexture(GL_TEXTURE_2D, 0);
2731 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2732 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2733 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2735 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 8, 8, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
2739 float x = GetSize().x, y = GetSize().y;
2740 float u = x / 8, v = y / 8;
2753 glDisable(GL_TEXTURE_2D);
2754 glDisable(GL_BLEND);
2758 void glChartCanvas::DrawCloseMessage(wxString msg) {
2759 #ifndef USE_ANDROID_GLES2
2762 wxFont *pfont = FontMgr::Get().FindOrCreateFont(
2763 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
2767 texfont.Build(*pfont, 1, 1);
2769 texfont.GetTextExtent(msg, &w, &h);
2771 int yp = m_pParentCanvas->GetVP().pix_height / 2;
2772 int xp = (m_pParentCanvas->GetVP().pix_width - w) / 2;
2774 glColor3ub(243, 229, 47);
2778 glVertex2i(xp + w, yp);
2779 glVertex2i(xp + w, yp + h);
2780 glVertex2i(xp, yp + h);
2785 glColor3ub(0, 0, 0);
2786 glEnable(GL_TEXTURE_2D);
2787 texfont.RenderString(msg, xp, yp);
2788 glDisable(GL_TEXTURE_2D);
2789 glDisable(GL_BLEND);
2796 static std::list<double *> combine_work_data;
2797 static void combineCallbackD(GLdouble coords[3], GLdouble *vertex_data[4],
2798 GLfloat weight[4], GLdouble **dataOut) {
2799 double *vertex =
new double[3];
2800 combine_work_data.push_back(vertex);
2801 memcpy(vertex, coords, 3 * (
sizeof *coords));
2805 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
2806 void vertexCallbackD_GLSL(GLvoid *vertex) {
2808 if (s_tess_vertex_idx > s_tess_buf_len - 8) {
2809 int new_buf_len = s_tess_buf_len + 100;
2810 GLfloat *tmp = s_tess_work_buf;
2813 (GLfloat *)realloc(s_tess_work_buf, new_buf_len *
sizeof(GLfloat));
2814 if (NULL == s_tess_work_buf) {
2818 s_tess_buf_len = new_buf_len;
2821 GLdouble *pointer = (GLdouble *)vertex;
2823 s_tess_work_buf[s_tess_vertex_idx++] = (float)pointer[0];
2824 s_tess_work_buf[s_tess_vertex_idx++] = (float)pointer[1];
2829 void beginCallbackD_GLSL(GLenum mode) {
2830 s_tess_vertex_idx_this = s_tess_vertex_idx;
2835 void endCallbackD_GLSL() {
2839 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)s_tessVP.vp_matrix_transform);
2841 mat4x4 identityMatrix;
2842 mat4x4_identity(identityMatrix);
2843 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)identityMatrix);
2847 colorv[0] = s_regionColor.Red() / float(256);
2848 colorv[1] = s_regionColor.Green() / float(256);
2849 colorv[2] = s_regionColor.Blue() / float(256);
2850 colorv[3] = s_regionColor.Alpha() / float(256);
2851 shader->SetUniform4fv(
"color", colorv);
2853 float *bufPt = &s_tess_work_buf[s_tess_vertex_idx_this];
2854 shader->SetAttributePointerf(
"position", bufPt);
2856 glDrawArrays(s_tess_mode, 0, s_nvertex);
2862 void vertexCallbackD(GLvoid *vertex)
2864 glVertex3dv( (GLdouble *)vertex);
2867 void beginCallbackD( GLenum mode)
2879 void glChartCanvas::DrawRegion(
ViewPort &vp,
const LLRegion ®ion) {
2880 float lat_dist, lon_dist;
2881 GetLatLonCurveDist(vp, lat_dist, lon_dist);
2883 GLUtesselator *tobj = gluNewTess();
2885 pStaticShader = GetStaticTriShader();
2888 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
2889 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&vertexCallbackD_GLSL);
2890 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&beginCallbackD_GLSL);
2891 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&endCallbackD_GLSL);
2892 gluTessCallback(tobj, GLU_TESS_COMBINE, (_GLUfuncptr)&combineCallbackD);
2896 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&vertexCallbackD);
2897 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&beginCallbackD);
2898 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&endCallbackD);
2899 gluTessCallback(tobj, GLU_TESS_COMBINE, (_GLUfuncptr)&combineCallbackD);
2902 gluTessNormal(tobj, 0, 0, 1);
2904 gluTessBeginPolygon(tobj, NULL);
2905 for (std::list<poly_contour>::const_iterator i = region.contours.begin();
2906 i != region.contours.end(); i++) {
2907 gluTessBeginContour(tobj);
2908 contour_pt l = *i->rbegin();
2910 bool sml_valid =
false;
2911 for (poly_contour::const_iterator j = i->begin(); j != i->end(); j++) {
2912 int lat_splits = floor(fabs(j->y - l.y) / lat_dist);
2913 int lon_splits = floor(fabs(j->x - l.x) / lon_dist);
2914 int splits = wxMax(lat_splits, lon_splits) + 1;
2920 toSM(j->y, j->x, 0, 0, smj + 0, smj + 1);
2921 if (!sml_valid) toSM(l.y, l.x, 0, 0, sml + 0, sml + 1);
2924 for (
int i = 0; i < splits; i++) {
2926 if (i == splits - 1)
2927 lat = j->y, lon = j->x;
2929 double d = (double)(i + 1) / splits;
2930 fromSM(d * smj[0] + (1 - d) * sml[0], d * smj[1] + (1 - d) * sml[1],
2933 wxPoint2DDouble q = vp.GetDoublePixFromLL(lat, lon);
2934 if (std::isnan(q.m_x))
continue;
2936 double *p =
new double[6];
2941 p[0] = wxRound(q.m_x), p[1] = wxRound(q.m_y), p[2] = 0;
2946 gluTessVertex(tobj, p, p);
2947 combine_work_data.push_back(p);
2951 if ((sml_valid = splits != 1)) memcpy(sml, smj,
sizeof smj);
2953 gluTessEndContour(tobj);
2955 gluTessEndPolygon(tobj);
2957 gluDeleteTess(tobj);
2959 for (std::list<double *>::iterator i = combine_work_data.begin();
2960 i != combine_work_data.end(); i++)
2962 combine_work_data.clear();
2967 void glChartCanvas::SetClipRegion(
ViewPort &vp,
const LLRegion ®ion) {
2968 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2970 if (s_b_useStencil) {
2972 glEnable(GL_STENCIL_TEST);
2974 glClear(GL_STENCIL_BUFFER_BIT);
2978 glStencilFunc(GL_ALWAYS, 1, 1);
2979 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
2982 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
2986 glEnable(GL_DEPTH_TEST);
2987 glDepthFunc(GL_ALWAYS);
2988 glDepthMask(GL_TRUE);
2990 glClear(GL_DEPTH_BUFFER_BIT);
3003 glTranslatef(0, 0, .5);
3007 s_regionColor = wxColor(0,0,0,255);
3008 DrawRegion(vp, region);
3010 if (s_b_useStencil) {
3013 glStencilFunc(GL_EQUAL, 1, 1);
3014 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3017 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3019 glDepthFunc(GL_GREATER);
3020 glDepthMask(GL_FALSE);
3021 glTranslatef(0, 0, -.5);
3024 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3027 void glChartCanvas::SetClipRect(
const ViewPort &vp,
const wxRect &rect,
3031 if (s_b_useStencil && s_b_useScissorTest) {
3032 wxRect vp_rect(0, 0, vp.pix_width, vp.pix_height);
3033 if (rect != vp_rect) {
3034 glEnable(GL_SCISSOR_TEST);
3035 glScissor(rect.x, vp.pix_height - rect.height - rect.y, rect.width,
3038 #ifndef USE_ANDROID_GLES2
3044 void glChartCanvas::DisableClipRegion() {
3045 glDisable(GL_SCISSOR_TEST);
3046 glDisable(GL_STENCIL_TEST);
3047 glDisable(GL_DEPTH_TEST);
3050 void glChartCanvas::Invalidate() {
3052 m_cache_vp.Invalidate();
3058 if (!pBSBChart)
return;
3060 if (b_inCompressAllCharts)
3064 wxString key = chart->GetHashKey();
3067 ChartPathHashTexfactType &hash = g_glTextureManager->m_chart_texfactory_hash;
3068 ChartPathHashTexfactType::iterator ittf = hash.find(key);
3071 if (ittf == hash.end()) {
3073 hash[key]->SetHashKey(key);
3076 pTexFact = hash[key];
3077 pTexFact->SetLRUTime(++m_LRUtime);
3082 glChartCanvas::HasNormalizedViewPort(vp) && pBSBChart->GetPPM() < 1;
3083 pTexFact->PrepareTiles(vp, use_norm_vp, pBSBChart);
3090 if (vp.m_projection_type == PROJECTION_MERCATOR &&
3091 chart->GetChartProjectionType() == PROJECTION_MERCATOR) {
3092 double scalefactor = pBSBChart->GetRasterScaleFactor(vp);
3093 base_level = log(scalefactor) / log(2.0);
3097 if (base_level > g_mipmap_max_level) base_level = g_mipmap_max_level;
3102 glEnable(GL_TEXTURE_2D);
3103 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3104 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3106 glEnableClientState(GL_VERTEX_ARRAY);
3107 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3112 pTexFact->GetCenter(lat, lon);
3113 MultMatrixViewPort(vp, lat, lon);
3117 LLBBox box = region.GetBox();
3120 if (g_memCacheLimit > 0) {
3122 GetMemoryStatus(0, &mem_used);
3125 glTexTile **tiles = pTexFact->GetTiles(numtiles);
3126 for (
int i = 0; i < numtiles; i++) {
3128 if (region.IntersectOut(tile->box)) {
3131 g_tex_mem_used > g_GLOptions.m_iTextureMemorySize * 1024 * 1024;
3132 if (bGLMemCrunch) pTexFact->DeleteTexture(tile->rect);
3134 bool texture = pTexFact->PrepareTexture(base_level, tile->rect,
3135 global_color_scheme, mem_used);
3139 coords = tile->m_coords;
3141 coords =
new float[2 * tile->m_ncoords];
3142 for (
int i = 0; i < tile->m_ncoords; i++) {
3143 wxPoint2DDouble p = vp.GetDoublePixFromLL(tile->m_coords[2 * i + 0],
3144 tile->m_coords[2 * i + 1]);
3145 coords[2 * i + 0] = p.m_x;
3146 coords[2 * i + 1] = p.m_y;
3150 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
3151 RenderTextures(m_gldc, coords, tile->m_texcoords, 4, m_pParentCanvas->GetpVP());
3154 glDisable(GL_TEXTURE_2D);
3158 glTexCoordPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), tile->m_texcoords);
3159 glVertexPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), coords);
3160 glDrawArrays(GL_QUADS, 0, tile->m_ncoords);
3162 if (!texture) glEnable(GL_TEXTURE_2D);
3164 if (!use_norm_vp)
delete[] coords;
3168 glDisable(GL_TEXTURE_2D);
3170 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3171 if (use_norm_vp) glPopMatrix();
3173 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3174 glDisableClientState(GL_VERTEX_ARRAY);
3178 void glChartCanvas::RenderQuiltViewGL(
ViewPort &vp,
3180 if (!m_pParentCanvas->m_pQuilt->GetnCharts() ||
3181 m_pParentCanvas->m_pQuilt->IsBusy())
3185 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetFirstChart();
3194 LLRegion region = vp.GetLLRegion(rect_region);
3196 LLRegion rendered_region;
3202 if (chart->GetChartFamily() != CHART_FAMILY_RASTER) {
3210 QuiltPatch *pqp = m_pParentCanvas->m_pQuilt->GetCurrentPatch();
3212 LLRegion get_region = pqp->ActiveRegion;
3213 bool b_rendered =
false;
3215 if (!pqp->b_overlay) {
3216 get_region.Intersect(region);
3217 if (!get_region.Empty()) {
3218 if (chart->GetChartFamily() == CHART_FAMILY_RASTER) {
3220 if (Patch_Ch_BSB ) {
3222 SetClipRegion(vp, get_region );
3223 RenderRasterChartRegionGL(chart, vp, pqp->ActiveRegion);
3224 DisableClipRegion();
3227 }
else if (chart->GetChartType() == CHART_TYPE_MBTILES) {
3228 SetClipRegion(vp, pqp->ActiveRegion );
3229 chart->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3231 DisableClipRegion();
3234 }
else if (chart->GetChartFamily() == CHART_FAMILY_VECTOR) {
3235 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
3236 RenderNoDTA(vp, get_region);
3237 chart->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3242 if (Chs57->m_RAZBuilt) {
3243 RenderNoDTA(vp, get_region);
3244 Chs57->RenderRegionViewOnGLNoText(*m_pcontext, vp,
3245 rect_region, get_region);
3246 DisableClipRegion();
3251 const LLRegion &oregion = get_region;
3252 LLBBox box = oregion.GetBox();
3255 vp.GetPixFromLL(box.GetMaxLat(), box.GetMinLon());
3257 vp.GetPixFromLL(box.GetMaxLat(), box.GetMaxLon());
3259 vp.GetPixFromLL(box.GetMinLat(), box.GetMaxLon());
3261 vp.GetPixFromLL(box.GetMinLat(), box.GetMinLon());
3263 wxRect srect(p1.x, p1.y, p3.x - p1.x, p4.y - p2.y);
3266 ViewPort cvp = ClippedViewport(vp, get_region);
3267 if (m_pParentCanvas->GetWorldBackgroundChart()) {
3268 SetClipRegion(cvp, get_region);
3269 m_pParentCanvas->GetWorldBackgroundChart()->SetColorsDirect(
3270 GetGlobalColor(_T (
"LANDA" )),
3271 GetGlobalColor(_T (
"DEPMS" )));
3272 RenderWorldChart(gldc, cvp, srect, world);
3273 m_pParentCanvas->GetWorldBackgroundChart()->SetColorScheme(
3274 global_color_scheme);
3275 DisableClipRegion();
3282 SetClipRegion(vp, get_region);
3283 RenderNoDTA(vp, get_region);
3284 ChPI->RenderRegionViewOnGLNoText(*m_pcontext, vp, rect_region,
3286 DisableClipRegion();
3289 SetClipRegion(vp, get_region);
3290 RenderNoDTA(vp, get_region);
3291 chart->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3293 DisableClipRegion();
3309 chart = m_pParentCanvas->m_pQuilt->GetNextChart();
3313 if (m_pParentCanvas->m_pQuilt->HasOverlays()) {
3314 ChartBase *pch = m_pParentCanvas->m_pQuilt->GetFirstChart();
3316 QuiltPatch *pqp = m_pParentCanvas->m_pQuilt->GetCurrentPatch();
3317 if (pqp->b_Valid && pqp->b_overlay &&
3318 pch->GetChartFamily() == CHART_FAMILY_VECTOR) {
3319 LLRegion get_region = pqp->ActiveRegion;
3321 get_region.Intersect(region);
3322 if (!get_region.Empty()) {
3325 Chs57->RenderOverlayRegionViewOnGL(*m_pcontext, vp, rect_region,
3330 ChPI->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3337 pch = m_pParentCanvas->m_pQuilt->GetNextChart();
3342 ViewPort vph = m_pParentCanvas->GetVP();
3343 for (
auto &index : m_pParentCanvas->m_pQuilt->GetHiLiteIndexArray()) {
3345 LLRegion hiregion = m_pParentCanvas->m_pQuilt->GetChartQuiltRegion(cte, vph);
3347 if (!hiregion.Empty()) {
3351 switch (global_color_scheme) {
3352 case GLOBAL_COLOR_SCHEME_DAY:
3355 case GLOBAL_COLOR_SCHEME_DUSK:
3358 case GLOBAL_COLOR_SCHEME_NIGHT:
3366 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3368 glColor4f((
float).8, (
float).4, (
float).4, (
float)hitrans);
3370 s_regionColor = wxColor(204, 102, 102, hitrans * 256);
3373 DrawRegion(vp, hiregion);
3375 glDisable(GL_BLEND);
3380 LLRegion hiregion = m_pParentCanvas->m_pQuilt->GetHiliteRegion();
3382 if (!hiregion.Empty()) {
3386 switch (global_color_scheme) {
3387 case GLOBAL_COLOR_SCHEME_DAY:
3390 case GLOBAL_COLOR_SCHEME_DUSK:
3393 case GLOBAL_COLOR_SCHEME_NIGHT:
3402 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3404 glColor4f((
float).8, (
float).4, (
float).4, (
float)hitrans);
3406 s_regionColor = wxColor(204, 102, 102, hitrans * 256);
3409 DrawRegion(vp, hiregion);
3411 glDisable(GL_BLEND);
3415 m_pParentCanvas->m_pQuilt->SetRenderedVP(vp);
3418 void glChartCanvas::RenderQuiltViewGLText(
ViewPort &vp,
3420 if (!m_pParentCanvas->m_pQuilt->GetnCharts() ||
3421 m_pParentCanvas->m_pQuilt->IsBusy())
3425 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetLargestScaleChart();
3427 LLRegion region = vp.GetLLRegion(rect_region);
3429 LLRegion rendered_region;
3431 QuiltPatch *pqp = m_pParentCanvas->m_pQuilt->GetCurrentPatch();
3433 LLRegion get_region = pqp->ActiveRegion;
3435 if (!pqp->b_overlay) {
3436 if (chart->GetChartFamily() == CHART_FAMILY_VECTOR) {
3439 Chs57->RenderViewOnGLTextOnly(*m_pcontext, vp);
3444 ChPI->RenderRegionViewOnGLTextOnly(*m_pcontext, vp, rect_region);
3451 chart = m_pParentCanvas->m_pQuilt->GetNextSmallerScaleChart();
3479 void glChartCanvas::RenderCharts(
ocpnDC &dc,
const OCPNRegion &rect_region) {
3480 ViewPort &vp = m_pParentCanvas->VPoint;
3488 m_pParentCanvas->m_singleChart->GetChartType() == CHART_TYPE_CM93COMP)
3489 static_cast<cm93compchart *
>(m_pParentCanvas->m_singleChart)
3492 LLRegion chart_region;
3494 (m_pParentCanvas->m_singleChart->GetChartType() == CHART_TYPE_PLUGIN)) {
3495 if (m_pParentCanvas->m_singleChart->GetChartFamily() ==
3496 CHART_FAMILY_RASTER) {
3504 cpw->chartpix_to_latlong(0, 0, ll + 0, ll + 1);
3505 cpw->chartpix_to_latlong(0, cpw->GetSize_Y(), ll + 2, ll + 3);
3506 cpw->chartpix_to_latlong(cpw->GetSize_X(), cpw->GetSize_Y(), ll + 4,
3508 cpw->chartpix_to_latlong(cpw->GetSize_X(), 0, ll + 6, ll + 7);
3512 for (
int i = 1; i < 6; i += 2)
3513 if (fabs(ll[i] - ll[i + 2]) > 180) {
3515 for (
int i = 1; i < 8; i += 2)
3516 if (ll[i] < 0) ll[i] += 360;
3520 chart_region = LLRegion(4, ll);
3523 m_pParentCanvas->m_singleChart->GetChartExtent(&ext);
3525 double ll[8] = {ext.SLAT, ext.WLON, ext.SLAT, ext.ELON,
3526 ext.NLAT, ext.ELON, ext.NLAT, ext.WLON};
3527 chart_region = LLRegion(4, ll);
3530 chart_region = vp.b_quilt
3531 ? m_pParentCanvas->m_pQuilt->GetFullQuiltRegion()
3532 : m_pParentCanvas->m_singleChart->GetValidRegion();
3534 bool world_view =
false;
3536 wxRect rect = upd.GetRect();
3537 LLRegion background_region = vp.GetLLRegion(rect);
3540 background_region.Subtract(chart_region);
3542 if (!background_region.Empty()) {
3543 ViewPort cvp = ClippedViewport(vp, background_region);
3544 SetClipRect(cvp, rect,
false);
3545 RenderWorldChart(dc, cvp, rect, world_view);
3546 DisableClipRegion();
3551 RenderQuiltViewGL(vp, rect_region);
3553 LLRegion region = vp.GetLLRegion(rect_region);
3554 if (m_pParentCanvas->m_singleChart->GetChartFamily() ==
3555 CHART_FAMILY_RASTER) {
3556 if (m_pParentCanvas->m_singleChart->GetChartType() == CHART_TYPE_MBTILES)
3557 m_pParentCanvas->m_singleChart->RenderRegionViewOnGL(
3558 *m_pcontext, vp, rect_region, region);
3560 RenderRasterChartRegionGL(m_pParentCanvas->m_singleChart, vp, region);
3561 }
else if (m_pParentCanvas->m_singleChart->GetChartFamily() ==
3562 CHART_FAMILY_VECTOR) {
3563 chart_region.Intersect(region);
3564 RenderNoDTA(vp, chart_region);
3565 m_pParentCanvas->m_singleChart->RenderRegionViewOnGL(*m_pcontext, vp,
3566 rect_region, region);
3572 void glChartCanvas::RenderNoDTA(
ViewPort &vp,
const LLRegion ®ion,
3574 wxColour color = GetGlobalColor(_T (
"NODTA" ));
3575 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3577 glColor4ub(color.Red(), color.Green(), color.Blue(), transparency);
3579 glColor4ub(163, 180, 183, transparency);
3582 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3586 s_regionColor = color;
3589 DrawRegion(vp, region);
3594 void glChartCanvas::RenderWorldChart(
ocpnDC &dc,
ViewPort &vp, wxRect &rect,
3597 wxColour water = m_pParentCanvas->pWorldBackgroundChart->water;
3599 glEnable(GL_SCISSOR_TEST);
3600 glScissor(rect.x, vp.pix_height - rect.height - rect.y, rect.width,
3606 int x1 = rect.x, y1 = rect.y, x2 = x1 + rect.width, y2 = y1 + rect.height;
3607 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
3609 GLShaderProgram *shader = pcolor_tri_shader_program[GetCanvasIndex()];
3613 colorv[0] = water.Red() / float(256);
3614 colorv[1] = water.Green() / float(256);
3615 colorv[2] = water.Blue() / float(256);
3617 shader->SetUniform4fv(
"color", colorv);
3628 shader->SetAttributePointerf(
"position", pf);
3630 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3640 gShapeBasemap.RenderViewOnDC(dc, vp);
3642 glDisable(GL_SCISSOR_TEST);
3651 void glChartCanvas::DrawGroundedOverlayObjects(
ocpnDC &dc,
ViewPort &vp) {
3652 m_pParentCanvas->RenderAllChartOutlines(dc, vp);
3654 DrawStaticRoutesTracksAndWaypoints(vp);
3656 DisableClipRegion();
3659 void glChartCanvas::DrawGLTidesInBBox(
ocpnDC &dc, LLBBox &BBox) {
3661 if (m_pParentCanvas->GetVP().chart_scale > 500000) {
3665 wxBitmap bmp = m_pParentCanvas->GetTideBitmap();
3666 if (!bmp.Ok())
return;
3668 wxImage image = bmp.ConvertToImage();
3669 int w = image.GetWidth(), h = image.GetHeight();
3672 if (g_texture_rectangle_format == GL_TEXTURE_2D)
3673 tex_w = w, tex_h = h;
3675 tex_w = NextPow2(w), tex_h = NextPow2(h);
3677 m_tideTexWidth = tex_w;
3678 m_tideTexHeight = tex_h;
3680 unsigned char *d = image.GetData();
3681 unsigned char *a = image.GetAlpha();
3683 unsigned char mr, mg, mb;
3684 if (!a) image.GetOrFindMaskColour(&mr, &mg, &mb);
3686 unsigned char *e =
new unsigned char[4 * w * h];
3688 for (
int y = 0; y < h; y++)
3689 for (
int x = 0; x < w; x++) {
3690 unsigned char r, g, b;
3691 int off = (y * w + x);
3701 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
3705 glGenTextures(1, &m_tideTex);
3707 glBindTexture(GL_TEXTURE_2D, m_tideTex);
3708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3711 if (g_texture_rectangle_format == GL_TEXTURE_2D)
3712 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
3713 GL_UNSIGNED_BYTE, e);
3715 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA,
3716 GL_UNSIGNED_BYTE, 0);
3717 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
3726 glBindTexture(GL_TEXTURE_2D, m_tideTex);
3727 glEnable(GL_TEXTURE_2D);
3730 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3732 for (
int i = 1; i < ptcmgr->Get_max_IDX() + 1; i++) {
3733 const IDX_entry *pIDX = ptcmgr->GetIDX_entry(i);
3735 char type = pIDX->IDX_type;
3736 if ((type ==
't') || (type ==
'T'))
3738 double lon = pIDX->IDX_lon;
3739 double lat = pIDX->IDX_lat;
3741 if (BBox.Contains(lat, lon)) {
3743 m_pParentCanvas->GetCanvasPointPix(lat, lon, &r);
3750 scale *= getAndroidDisplayDensity();
3752 double width2 =
scale * m_tideTexWidth / 2;
3753 double height2 =
scale * m_tideTexHeight / 2;
3768 coords[0] = xp - width2;
3769 coords[1] = yp - height2;
3770 coords[2] = xp - width2;
3771 coords[3] = yp + height2;
3772 coords[4] = xp + width2;
3773 coords[5] = yp + height2;
3774 coords[6] = xp + width2;
3775 coords[7] = yp - height2;
3777 RenderTextures(dc, coords, uv, 4, m_pParentCanvas->GetpVP());
3784 glDisable(GL_TEXTURE_2D);
3785 glDisable(GL_BLEND);
3786 glBindTexture(GL_TEXTURE_2D, 0);
3788 m_pParentCanvas->DrawAllTidesInBBox(dc, BBox);
3791 void glChartCanvas::DrawGLCurrentsInBBox(
ocpnDC &dc, LLBBox &BBox) {
3792 m_pParentCanvas->DrawAllCurrentsInBBox(dc, BBox);
3795 void glChartCanvas::SetColorScheme(ColorScheme cs) {
3796 if (!m_bsetup)
return;
3798 glDeleteTextures(1, &m_tideTex);
3799 glDeleteTextures(1, &m_currentTex);
3805 void glChartCanvas::RenderGLAlertMessage() {
3806 if (!m_pParentCanvas->GetAlertString().IsEmpty()) {
3807 wxString msg = m_pParentCanvas->GetAlertString();
3809 wxFont *pfont = GetOCPNScaledFont(_(
"Dialog"));
3810 m_gldc.SetFont(*pfont);
3814 sdc.GetTextExtent(msg, &w, &h, NULL, NULL, pfont);
3819 m_pParentCanvas->VPoint.pix_height - GetChartbarHeight() - h - (h / 4);
3821 wxRect sbr = m_pParentCanvas->GetScaleBarRect();
3822 int xp = sbr.x + sbr.width + 5;
3824 wxPen ppPen1(GetGlobalColor(_T (
"UBLCK" )), 1, wxPENSTYLE_SOLID);
3825 m_gldc.SetPen(ppPen1);
3826 m_gldc.SetBrush(wxBrush(GetGlobalColor(_T (
"YELO1" ))));
3828 m_gldc.DrawRectangle(xp, yp, w, h);
3830 m_gldc.DrawText(msg, xp, yp);
3834 unsigned long quiltHash;
3838 void glChartCanvas::Render() {
3839 if (!m_bsetup || !m_pParentCanvas->m_pQuilt ||
3840 (m_pParentCanvas->VPoint.b_quilt && !m_pParentCanvas->m_pQuilt) ||
3841 (!m_pParentCanvas->VPoint.b_quilt && !m_pParentCanvas->m_singleChart)) {
3846 if(!g_PrintingInProgress)
return;
3849 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
3850 loadShaders(GetCanvasIndex());
3851 configureShaders(m_pParentCanvas->VPoint);
3854 #ifdef USE_ANDROID_GLES2
3858 if (m_binPinch)
return;
3867 bool recompose =
false;
3868 if (m_pParentCanvas->VPoint.b_quilt && m_pParentCanvas->m_pQuilt &&
3869 !m_pParentCanvas->m_pQuilt->IsComposed()) {
3870 if (m_pParentCanvas->VPoint.IsValid()) {
3871 m_pParentCanvas->m_pQuilt->
Compose(m_pParentCanvas->VPoint);
3872 m_pParentCanvas->UpdateCanvasControlBar();
3881 if (sw.GetTime() > 2000) {
3882 m_pParentCanvas->ZoomCanvas(1.0001,
false);
3887 s_tess_vertex_idx = 0;
3888 quiltHash = m_pParentCanvas->m_pQuilt->GetXStackHash();
3889 refChartIndex = m_pParentCanvas->m_pQuilt->GetRefChartdbIndex();
3895 m_displayScale = GetContentScaleFactor();
3898 m_last_render_time = wxDateTime::Now().GetTicks();
3902 if (g_GLOptions.m_bTextureCompression &&
3903 !g_GLOptions.m_bTextureCompressionCaching)
3904 g_glTextureManager->ClearJobList();
3910 int gl_width, gl_height;
3911 gl_width = m_pParentCanvas->VPoint.pix_width;
3912 gl_height = m_pParentCanvas->VPoint.pix_height;
3915 m_glcanvas_width = gl_width;
3916 m_glcanvas_height = gl_height;
3920 if (gl_height & 1) {
3922 ViewPort *vp = m_pParentCanvas->GetpVP();
3923 vp->pix_height = gl_height;
3929 ViewPort *vp = m_pParentCanvas->GetpVP();
3930 vp->pix_width = gl_width;
3937 ViewPort *vp = m_pParentCanvas->GetpVP();
3940 mat4x4_scale_aniso((
float(*)[4])vp->vp_matrix_transform, m,
3941 2.0 / (
float)vp->pix_width, -2.0 / (
float)vp->pix_height,
3943 mat4x4_translate_in_place((
float(*)[4])vp->vp_matrix_transform,
3944 -vp->pix_width / 2, -vp->pix_height / 2, 0);
3947 ViewPort VPoint = m_pParentCanvas->VPoint;
3949 OCPNRegion screen_region(wxRect(0, 0, gl_width, gl_height));
3950 glViewport(0, 0, (GLint)gl_width, (GLint)gl_height);
3953 #if !defined(USE_ANDROID_GLES2)
3954 glMatrixMode(GL_PROJECTION);
3957 glOrtho(0, (GLint)gl_width, (GLint)gl_height, 0, -1, 1);
3958 glMatrixMode(GL_MODELVIEW);
3962 if (s_b_useStencil) {
3963 glEnable(GL_STENCIL_TEST);
3964 glStencilMask(0xff);
3965 glClear(GL_STENCIL_BUFFER_BIT);
3966 glDisable(GL_STENCIL_TEST);
3972 if (g_GLOptions.m_GLLineSmoothing) glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
3973 if (g_GLOptions.m_GLPolygonSmoothing)
3974 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
3975 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3982 g_glTextureManager->TextureCrunch(0.8);
3985 double scale_factor = VPoint.ref_scale / VPoint.chart_scale;
3987 bool bpost_hilite = !m_pParentCanvas->m_pQuilt->GetHiliteRegion().Empty();
3988 bool useFBO =
false;
3994 if (m_b_BuiltFBO && !bpost_hilite
3999 bool b_newview =
true;
4000 bool b_full =
false;
4004 if (m_cache_vp.view_scale_ppm == VPoint.view_scale_ppm &&
4005 m_cache_vp.rotation == VPoint.rotation &&
4006 m_cache_vp.clat == VPoint.clat && m_cache_vp.clon == VPoint.clon &&
4007 m_cache_vp.IsValid() && m_cache_vp.pix_height == VPoint.pix_height &&
4008 m_cache_current_ch == m_pParentCanvas->m_singleChart) {
4012 #ifdef USE_ANDROID_GLES2
4013 if (recompose) b_newview =
true;
4025 if (VPoint.b_quilt) {
4026 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetFirstChart();
4027 if (!chart) b_full =
true;
4036 bool accelerated_pan =
false;
4037 if (g_GLOptions.m_bUseAcceleratedPanning && m_cache_vp.IsValid() &&
4038 (VPoint.m_projection_type == PROJECTION_MERCATOR ||
4039 VPoint.m_projection_type == PROJECTION_EQUIRECTANGULAR) &&
4040 m_cache_vp.pix_height == VPoint.pix_height) {
4041 wxPoint2DDouble c_old =
4042 VPoint.GetDoublePixFromLL(VPoint.clat, VPoint.clon) *
4044 wxPoint2DDouble c_new =
4045 m_cache_vp.GetDoublePixFromLL(VPoint.clat, VPoint.clon) *
4048 dy = wxRound(c_new.m_y - c_old.m_y);
4049 dx = wxRound(c_new.m_x - c_old.m_x);
4059 double deltax = c_new.m_x - c_old.m_x;
4060 double deltay = c_new.m_y - c_old.m_y;
4062 bool b_whole_pixel =
true;
4063 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
4064 b_whole_pixel =
false;
4066 accelerated_pan = b_whole_pixel && abs(dx) < m_cache_tex_x &&
4067 abs(dy) < m_cache_tex_y &&
4068 (abs(dx) > 0 || (abs(dy) > 0));
4073 if (m_displayScale > 1) accelerated_pan =
false;
4077 if (fabs(VPoint.rotation) > 0) accelerated_pan =
false;
4080 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4083 glBindFramebuffer(GL_FRAMEBUFFER, m_fb0);
4085 if (VPoint.chart_scale < 5000) b_full =
true;
4087 if (VPoint.chart_scale > 5e7) b_full =
true;
4089 if (b_full) accelerated_pan =
false;
4091 if (accelerated_pan) {
4092 if ((dx != 0) || (dy != 0)) {
4102 if (VPoint.chart_scale < 10000) fluff = 8;
4104 if (dy > 0 && dy < gl_height)
4105 update_region.Union(
4106 wxRect(0, gl_height - (dy + fluff), gl_width, dy + fluff));
4108 update_region.Union(wxRect(0, 0, gl_width, -dy + fluff));
4110 if (dx > 0 && dx < gl_width)
4111 update_region.Union(
4112 wxRect(gl_width - (dx + fluff), 0, dx + fluff, gl_height));
4114 update_region.Union(wxRect(0, 0, -dx + fluff, gl_height));
4116 m_cache_page = !m_cache_page;
4119 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4120 GL_TEXTURE_2D, m_cache_tex[m_cache_page], 0);
4129 RenderCharts(m_gldc, update_region);
4130 glDisable(g_texture_rectangle_format);
4134 glBindTexture(GL_TEXTURE_2D, m_cache_tex[!m_cache_page]);
4135 glEnable(GL_TEXTURE_2D);
4138 float x1, x2, y1, y2;
4151 float tx1, tx2, ty1, ty2;
4157 tx2 = sx / (float)m_cache_tex_x;
4159 ty2 = sy / (float)m_cache_tex_y;
4176 coords[2] = -dx + sx;
4178 coords[4] = -dx + sx;
4179 coords[5] = dy + sy;
4181 coords[7] = dy + sy;
4184 ptexture_2D_shader_program[GetCanvasIndex()];
4188 shader->SetUniform1i(
"uTex", 0);
4192 mat4x4_scale_aniso(mvp, m, 2.0 / (
float)sx, 2.0 / (
float)sy, 1.0);
4193 mat4x4_translate_in_place(mvp, -(
float)sx / 2, -(
float)sy / 2, 0);
4194 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)mvp);
4196 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
4218 shader->SetAttributePointerf(
"aPos", co1);
4219 shader->SetAttributePointerf(
"aUV", tco1);
4221 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4224 shader->SetUniformMatrix4fv(
"MVMatrix",
4225 (GLfloat *)VPoint.vp_matrix_transform);
4228 glBindTexture(g_texture_rectangle_format, 0);
4230 glDisable(g_texture_rectangle_format);
4238 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
4239 g_texture_rectangle_format,
4240 m_cache_tex[!m_cache_page], 0);
4251 wxColour color = GetGlobalColor(_T (
"NODTA" ));
4252 glClearColor(color.Red() / 256., color.Green() / 256.,
4253 color.Blue() / 256., 1.0);
4254 glClear(GL_COLOR_BUFFER_BIT);
4257 RenderCharts(m_gldc, rscreen_region);
4259 m_cache_page = !m_cache_page;
4264 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4275 glMatrixMode(GL_PROJECTION);
4278 gluPerspective(2 * 180 / PI * atan2((
double)gl_height, (
double)gl_width),
4279 (GLfloat)gl_width / (GLfloat)gl_height, 1, gl_width);
4281 glMatrixMode(GL_MODELVIEW);
4285 glTranslatef(-gl_width / 2, -gl_height / 2, -gl_width / 2);
4286 glRotated(VPoint.tilt * 180 / PI, 1, 0, 0);
4288 glGetIntegerv(GL_VIEWPORT, viewport);
4289 glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
4290 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
4296 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fb0);
4297 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4298 glBlitFramebuffer(0, 0, sx, sy, 0, 0, sx*2, sy*2, GL_COLOR_BUFFER_BIT, GL_LINEAR);
4300 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4304 glBindTexture(g_texture_rectangle_format, m_cache_tex[m_cache_page]);
4305 glEnable(g_texture_rectangle_format);
4307 float tx, ty, tx0, ty0, divx, divy;
4310 if (GL_TEXTURE_RECTANGLE_ARB == g_texture_rectangle_format) {
4313 divx = m_cache_tex_x;
4314 divy = m_cache_tex_y;
4317 tx0 = m_fbo_offsetx / divx;
4318 ty0 = m_fbo_offsety / divy;
4319 tx = (m_fbo_offsetx + m_fbo_swidth) / divx;
4320 ty = (m_fbo_offsety + m_fbo_sheight) / divy;
4345 wxColour color = GetGlobalColor(_T (
"NODTA" ));
4346 glClearColor(color.Red() / 256., color.Green() / 256., color.Blue() / 256.,
4348 glClear(GL_COLOR_BUFFER_BIT);
4350 RenderTextures(gldc, coords, uv, 4, m_pParentCanvas->GetpVP());
4353 glDisable(g_texture_rectangle_format);
4355 m_cache_vp = VPoint;
4356 m_cache_current_ch = m_pParentCanvas->m_singleChart;
4358 if (VPoint.b_quilt) m_pParentCanvas->m_pQuilt->SetRenderedVP(VPoint);
4362 RenderCharts(m_gldc, screen_region);
4368 RenderS57TextOverlay(VPoint);
4369 RenderMBTilesOverlay(VPoint);
4373 wxRect rt = upd.GetRect();
4374 LLRegion region = VPoint.GetLLRegion(rt);
4375 ViewPort cvp = ClippedViewport(VPoint, region);
4376 DrawGroundedOverlayObjects(gldc, cvp);
4379 if (m_pParentCanvas->m_bShowTide || m_pParentCanvas->m_bShowCurrent) {
4380 LLRegion screenLLRegion = VPoint.GetLLRegion(screen_region);
4381 LLBBox screenBox = screenLLRegion.GetBox();
4383 screenBox.EnLarge(screenBox.GetLonRange() * 0.05);
4386 if (m_pParentCanvas->m_bShowTide) {
4387 m_pParentCanvas->RebuildTideSelectList(screenBox);
4388 DrawGLTidesInBBox(gldc, VPoint.GetBBox());
4391 if (m_pParentCanvas->m_bShowCurrent) {
4392 m_pParentCanvas->RebuildCurrentSelectList(screenBox);
4393 DrawGLCurrentsInBBox(gldc, VPoint.GetBBox());
4399 if (g_canvasConfig != 0) {
4400 if (m_pParentCanvas == wxWindow::FindFocus()) {
4401 g_focusCanvas = m_pParentCanvas;
4403 wxColour colour = GetGlobalColor(_T(
"BLUE4"));
4404 wxPen ppBlue(colour, 1);
4405 wxBrush ppBrush(colour);
4406 gldc.SetPen(ppBlue);
4407 gldc.SetBrush(ppBrush);
4408 int xw = m_pParentCanvas->GetClientSize().x * m_displayScale;
4409 float rect_pix = m_pParentCanvas->m_focus_indicator_pix * m_displayScale;
4410 wxPoint barPoints[4];
4413 barPoints[1].x = xw;
4415 barPoints[2].x = xw;
4416 barPoints[2].y = rect_pix;
4418 barPoints[3].y = rect_pix;
4420 gldc.DrawPolygon(4, barPoints, 0, 0, 1, 0);
4424 DrawDynamicRoutesTracksAndWaypoints(VPoint);
4428 DrawFloatingOverlayObjects(m_gldc);
4430 #ifndef USE_ANDROID_GLES2
4433 glMatrixMode(GL_PROJECTION);
4436 glOrtho(0, (GLint)gl_width, (GLint)gl_height, 0, -1, 1);
4437 glMatrixMode(GL_MODELVIEW);
4442 DrawEmboss(m_gldc, m_pParentCanvas->EmbossDepthScale());
4443 DrawEmboss(m_gldc, m_pParentCanvas->EmbossOverzoomIndicator(gldc));
4446 ViewPort &vp = m_pParentCanvas->GetVP();
4447 g_pi_manager->SendViewPortToRequestingPlugIns(vp);
4448 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
4449 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_OVER_EMBOSS);
4451 if(!g_PrintingInProgress){
4452 if (m_pParentCanvas->m_pTrackRolloverWin)
4453 m_pParentCanvas->m_pTrackRolloverWin->Draw(gldc);
4455 if (m_pParentCanvas->m_pRouteRolloverWin)
4456 m_pParentCanvas->m_pRouteRolloverWin->Draw(gldc);
4458 if (m_pParentCanvas->m_pAISRolloverWin)
4459 m_pParentCanvas->m_pAISRolloverWin->Draw(gldc);
4462 if (m_pParentCanvas->GetMUIBar())
4463 m_pParentCanvas->GetMUIBar()->DrawGL(gldc, m_displayScale);
4465 if (g_MainToolbar && m_pParentCanvas->IsPrimaryCanvas())
4466 g_MainToolbar->DrawGL(gldc, m_displayScale);
4468 if (g_iENCToolbar && m_pParentCanvas->IsPrimaryCanvas())
4469 g_iENCToolbar->DrawGL(gldc, m_displayScale);
4477 if (m_pParentCanvas->m_pCIWin && m_pParentCanvas->m_pCIWin->IsShown()) {
4478 int x, y, width, height;
4479 m_pParentCanvas->m_pCIWin->GetClientSize(&width, &height);
4480 m_pParentCanvas->m_pCIWin->GetPosition(&x, &y);
4481 wxBitmap bmp(width, height, -1);
4484 dc.SetBackground(wxBrush(GetGlobalColor(_T (
"UIBCK" ))));
4487 dc.SetTextBackground(GetGlobalColor(_T (
"UIBCK" )));
4488 dc.SetTextForeground(GetGlobalColor(_T (
"UITX1" )));
4492 wxString s = m_pParentCanvas->m_pCIWin->GetString();
4493 int h = m_pParentCanvas->m_pCIWin->GetCharHeight();
4495 wxStringTokenizer tkz(s, _T(
"\n"));
4498 while (tkz.HasMoreTokens()) {
4499 token = tkz.GetNextToken();
4500 dc.DrawText(token, xt, yt);
4503 dc.SelectObject(wxNullBitmap);
4505 m_gldc.DrawBitmap(bmp, x, y,
false);
4511 if (g_bShowChartBar) DrawChartBar(m_gldc);
4513 if (m_pParentCanvas->m_Compass) m_pParentCanvas->m_Compass->Paint(gldc);
4515 RenderGLAlertMessage();
4519 ViewPort &vp = m_pParentCanvas->GetVP();
4520 g_pi_manager->SendViewPortToRequestingPlugIns(vp);
4521 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
4522 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_OVER_UI);
4526 if (g_bquiting) DrawQuiting();
4527 if (g_bcompression_wait)
4528 DrawCloseMessage(_(
"Waiting for raster chart compression thread exit."));
4533 if (g_b_needFinish) glFinish();
4537 g_glTextureManager->TextureCrunch(0.8);
4538 g_glTextureManager->FactoryCrunch(0.6);
4540 m_pParentCanvas->PaintCleanup();
4542 m_bforcefull =
false;
4547 void glChartCanvas::RenderS57TextOverlay(
ViewPort &VPoint) {
4550 if (VPoint.b_quilt) {
4551 if (m_pParentCanvas->m_pQuilt->IsQuiltVector() && ps52plib &&
4552 ps52plib->GetShowS57Text()) {
4553 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetRefChart();
4554 if (chart && (chart->GetChartType() != CHART_TYPE_CM93COMP)) {
4559 ChPI->ClearPLIBTextList();
4561 ps52plib->ClearTextList();
4567 vpx.BuildExpandedVP(VPoint.pix_width * 12 / 10, VPoint.pix_height);
4570 wxRect(0, 0, VPoint.pix_width, VPoint.pix_height));
4571 RenderQuiltViewGLText(vpx, screen_region);
4577 void glChartCanvas::RenderMBTilesOverlay(
ViewPort &VPoint) {
4579 std::vector<int> stackIndexArray =
4580 m_pParentCanvas->m_pQuilt->GetExtendedStackIndexArray();
4581 unsigned int im = stackIndexArray.size();
4584 if (VPoint.b_quilt && im > 0) {
4585 bool regionVPBuilt =
false;
4587 LLRegion screenLLRegion;
4591 std::vector<int> tiles_to_show;
4592 for (
unsigned int is = 0; is < im; is++) {
4594 ChartData->GetChartTableEntry(stackIndexArray[is]);
4595 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
4596 if (m_pParentCanvas->IsTileOverlayIndexInNoShow(stackIndexArray[is])) {
4598 std::vector<int> piano_active_array_tiles =
4599 m_pParentCanvas->m_Piano->GetActiveKeyArray();
4600 bool bfound =
false;
4602 for (
unsigned int i = 0; i < piano_active_array_tiles.size(); i++) {
4603 if (piano_active_array_tiles[i] == stackIndexArray[is]) {
4604 piano_active_array_tiles.erase(piano_active_array_tiles.begin() +
4612 m_pParentCanvas->m_Piano->SetActiveKeyArray(
4613 piano_active_array_tiles);
4618 tiles_to_show.push_back(stackIndexArray[is]);
4619 if (!regionVPBuilt) {
4621 OCPNRegion(wxRect(0, 0, VPoint.pix_width, VPoint.pix_height));
4622 screenLLRegion = VPoint.GetLLRegion(screen_region);
4623 screenBox = screenLLRegion.GetBox();
4627 p.x = VPoint.pix_width / 2;
4628 p.y = VPoint.pix_height / 2;
4629 VPoint.GetLLFromPix(p, &vp.clat, &vp.clon);
4631 regionVPBuilt =
true;
4638 for (std::vector<int>::reverse_iterator rit = tiles_to_show.rbegin();
4639 rit != tiles_to_show.rend(); ++rit) {
4640 ChartBase *chart = ChartData->OpenChartFromDBAndLock(*rit, FULL_INIT);
4644 if (chart == NULL)
continue;
4646 wxFileName tileFile(chart->GetFullPath());
4648 wxULongLong tileSizeMB = tileFile.GetSize() >> 20;
4650 if (!ChartData->CheckAnyCanvasExclusiveTileGroup() ||
4651 (tileSizeMB.GetLo() > 5000)) {
4654 if (!m_pParentCanvas->IsTileOverlayIndexInYesShow(*rit)) {
4655 if (!m_pParentCanvas->IsTileOverlayIndexInNoShow(*rit)) {
4656 m_pParentCanvas->m_tile_noshow_index_array.push_back(*rit);
4663 if (m_pParentCanvas->IsTileOverlayIndexInNoShow(*rit)) {
4669 pcmbt->RenderRegionViewOnGL(*m_pcontext, vp, screen_region,
4673 std::vector<int> piano_active_array_tiles =
4674 m_pParentCanvas->m_Piano->GetActiveKeyArray();
4675 bool bfound =
false;
4677 if (std::find(piano_active_array_tiles.begin(),
4678 piano_active_array_tiles.end(),
4679 *rit) != piano_active_array_tiles.end()) {
4684 piano_active_array_tiles.push_back(*rit);
4685 m_pParentCanvas->m_Piano->SetActiveKeyArray(piano_active_array_tiles);
4691 LLRegion hiregion = m_pParentCanvas->m_pQuilt->GetHiliteRegion();
4693 if (!hiregion.Empty()) {
4697 switch (global_color_scheme) {
4698 case GLOBAL_COLOR_SCHEME_DAY:
4701 case GLOBAL_COLOR_SCHEME_DUSK:
4704 case GLOBAL_COLOR_SCHEME_NIGHT:
4712 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4713 glColor4f((
float).8, (
float).4, (
float).4, (
float)hitrans);
4715 s_regionColor = wxColor(204, 102, 102, hitrans * 256);
4718 DrawRegion(VPoint, hiregion);
4720 glDisable(GL_BLEND);
4725 void glChartCanvas::RenderCanvasBackingChart(
ocpnDC &dc,
4729 GetClientSize(&w, &h);
4731 glViewport(0, 0, (GLint)m_cache_tex_x, (GLint)m_cache_tex_y);
4732 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4733 glMatrixMode(GL_PROJECTION);
4736 glOrtho(0, m_cache_tex_x, m_cache_tex_y, 0, -1, 1);
4737 glMatrixMode(GL_MODELVIEW);
4741 wxRect rtex(0, 0, m_cache_tex_x, m_cache_tex_y);
4743 m_pParentCanvas->GetVP().BuildExpandedVP(m_cache_tex_x, m_cache_tex_y);
4745 bool world_view =
false;
4746 RenderWorldChart(dc, cvp, rtex, world_view);
4747 gShapeBasemap.RenderViewOnDC(dc, cvp);
4753 glViewport(0, 0, (GLint)w, (GLint)h);
4754 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4755 glMatrixMode(GL_PROJECTION);
4758 glOrtho(0, (GLint)w, (GLint)h, 0, -1, 1);
4759 glMatrixMode(GL_MODELVIEW);
4764 void glChartCanvas::FastPan(
int dx,
int dy) {
4765 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4769 void glChartCanvas::ZoomProject(
float offset_x,
float offset_y,
float swidth,
4771 SetCurrent(*m_pcontext);
4773 float sx = GetSize().x;
4774 float sy = GetSize().y;
4776 float tx, ty, tx0, ty0;
4786 tx = offset_x + swidth;
4787 ty = offset_y + sheight;
4790 GetClientSize(&w, &h);
4791 glViewport(0, 0, (GLint)w, (GLint)h);
4793 if (s_b_useStencil) {
4794 glEnable(GL_STENCIL_TEST);
4795 glStencilMask(0xff);
4796 glClear(GL_STENCIL_BUFFER_BIT);
4797 glDisable(GL_STENCIL_TEST);
4805 glBindTexture(g_texture_rectangle_format, 0);
4808 glBindTexture(g_texture_rectangle_format, m_cache_tex[m_cache_page]);
4809 glEnable(g_texture_rectangle_format);
4816 uv[0] = tx0 / m_cache_tex_x;
4817 uv[1] = ty / m_cache_tex_y;
4818 uv[2] = tx / m_cache_tex_x;
4819 uv[3] = ty / m_cache_tex_y;
4820 uv[4] = tx / m_cache_tex_x;
4821 uv[5] = ty0 / m_cache_tex_y;
4822 uv[6] = tx0 / m_cache_tex_x;
4823 uv[7] = ty0 / m_cache_tex_y;
4835 RenderTextures(m_gldc, coords, uv, 4, m_pParentCanvas->GetpVP());
4837 glDisable(g_texture_rectangle_format);
4838 glBindTexture(g_texture_rectangle_format, 0);
4843 wxColour color = GetGlobalColor(_T(
"GREY1"));
4844 float ht = -offset_y * (sy / sheight);
4845 wxRect r(0, sy - ht, w, ht);
4846 RenderColorRect(r, color);
4849 wxRect rt(0, 0, w, sy - (ht + (sy * sy / sheight)));
4850 RenderColorRect(rt, color);
4853 float w1 = -offset_x * sx / swidth;
4854 wxRect rl(0, 0, w1, sy);
4855 RenderColorRect(rl, color);
4858 float px = w1 + sx * sx / swidth;
4859 wxRect rr(px, 0, sx - px, sy);
4860 RenderColorRect(rr, color);
4870 void glChartCanvas::onZoomTimerEvent(wxTimerEvent &event) {
4873 if ((m_nRun < m_nTotal) && !m_zoomFinal) {
4874 m_runoffsetx += m_offsetxStep;
4875 if (m_offsetxStep > 0)
4876 m_runoffsetx = wxMin(m_runoffsetx, m_fbo_offsetx);
4878 m_runoffsetx = wxMax(m_runoffsetx, m_fbo_offsetx);
4880 m_runoffsety += m_offsetyStep;
4881 if (m_offsetyStep > 0)
4882 m_runoffsety = wxMin(m_runoffsety, m_fbo_offsety);
4884 m_runoffsety = wxMax(m_runoffsety, m_fbo_offsety);
4886 m_runswidth += m_swidthStep;
4887 if (m_swidthStep > 0)
4888 m_runswidth = wxMin(m_runswidth, m_fbo_swidth);
4890 m_runswidth = wxMax(m_runswidth, m_fbo_swidth);
4892 m_runsheight += m_sheightStep;
4893 if (m_sheightStep > 0)
4894 m_runsheight = wxMin(m_runsheight, m_fbo_sheight);
4896 m_runsheight = wxMax(m_runsheight, m_fbo_sheight);
4901 ZoomProject(m_runoffsetx, m_runoffsety, m_runswidth, m_runsheight);
4910 m_pParentCanvas->ZoomCanvas(m_zoomFinalZoom,
false);
4912 if (m_zoomFinaldx || m_zoomFinaldy) {
4913 m_pParentCanvas->PanCanvas(m_zoomFinaldx, m_zoomFinaldy);
4916 m_zoomFinal =
false;
4920 void glChartCanvas::FastZoom(
float factor,
float cp_x,
float cp_y,
float post_x,
4924 int sx = GetSize().x;
4925 int sy = GetSize().y;
4927 m_lastfbo_offsetx = m_fbo_offsetx;
4928 m_lastfbo_offsety = m_fbo_offsety;
4929 m_lastfbo_swidth = m_fbo_swidth;
4930 m_lastfbo_sheight = m_fbo_sheight;
4932 float curr_fbo_offset_x = m_fbo_offsetx;
4933 float curr_fbo_offset_y = m_fbo_offsety;
4934 float curr_fbo_swidth = m_fbo_swidth;
4935 float curr_fbo_sheight = m_fbo_sheight;
4937 float fx = (float)cp_x / sx;
4938 float fy = 1.0 - (float)cp_y / sy;
4939 if (factor < 1.0f) {
4944 float fbo_ctr_x = curr_fbo_offset_x + (curr_fbo_swidth * fx);
4945 float fbo_ctr_y = curr_fbo_offset_y + (curr_fbo_sheight * fy);
4947 m_fbo_swidth = curr_fbo_swidth / factor;
4948 m_fbo_sheight = curr_fbo_sheight / factor;
4950 m_fbo_offsetx = fbo_ctr_x - (m_fbo_swidth * fx);
4951 m_fbo_offsety = fbo_ctr_y - (m_fbo_sheight * fy);
4953 m_fbo_offsetx += post_x;
4954 m_fbo_offsety += post_y;
4970 float perStep = m_nStep / m_nTotal;
4972 if (zoomTimer.IsRunning()) {
4973 m_offsetxStep = (m_fbo_offsetx - m_runoffsetx) * perStep;
4974 m_offsetyStep = (m_fbo_offsety - m_runoffsety) * perStep;
4975 m_swidthStep = (m_fbo_swidth - m_runswidth) * perStep;
4976 m_sheightStep = (m_fbo_sheight - m_runsheight) * perStep;
4979 m_offsetxStep = (m_fbo_offsetx - m_lastfbo_offsetx) * perStep;
4980 m_offsetyStep = (m_fbo_offsety - m_lastfbo_offsety) * perStep;
4981 m_swidthStep = (m_fbo_swidth - m_lastfbo_swidth) * perStep;
4982 m_sheightStep = (m_fbo_sheight - m_lastfbo_sheight) * perStep;
4984 m_runoffsetx = m_lastfbo_offsetx;
4985 m_runoffsety = m_lastfbo_offsety;
4986 m_runswidth = m_lastfbo_swidth;
4987 m_runsheight = m_lastfbo_sheight;
4990 if (!zoomTimer.IsRunning()) zoomTimer.Start(m_nStep);
4991 m_zoomFinal =
false;
4997 void glChartCanvas::OnEvtPanGesture(wxQT_PanGestureEvent &event) {
5001 if (m_pParentCanvas->isRouteEditing() || m_pParentCanvas->isMarkEditing())
5004 if (m_binPinch)
return;
5005 if (m_bpinchGuard)
return;
5007 int x =
event.GetOffset().x;
5008 int y =
event.GetOffset().y;
5010 int lx =
event.GetLastOffset().x;
5011 int ly =
event.GetLastOffset().y;
5016 switch (event.GetState()) {
5017 case GestureStarted:
5018 if (m_binPan)
break;
5022 m_binGesture =
true;
5026 case GestureUpdated:
5028 if (!g_GLOptions.m_bUseCanvasPanning) {
5031 m_pParentCanvas->FreezePiano();
5032 m_pParentCanvas->PanCanvas(dx, -dy);
5033 m_pParentCanvas->ThawPiano();
5044 case GestureFinished:
5047 m_pParentCanvas->UpdateCanvasControlBar();
5050 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5054 case GestureCanceled:
5056 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5063 m_bgestureGuard =
true;
5064 m_gestureEeventTimer.Start(500, wxTIMER_ONE_SHOT);
5065 m_bforcefull =
false;
5070 float zoom_inc = 1.0;
5071 bool first_zout =
false;
5073 void glChartCanvas::OnEvtPinchGesture(wxQT_PinchGestureEvent &event) {
5074 float zoom_gain = 1.0;
5075 float zout_gain = 1.0;
5078 float total_zoom_val;
5080 float max_zoom_scale = 1000.;
5081 float min_zoom_scale = 2e8;
5083 if (event.GetScaleFactor() > 1)
5084 zoom_val = ((
event.GetScaleFactor() - 1.0) * zoom_gain) + 1.0;
5086 zoom_val = 1.0 - ((1.0 -
event.GetScaleFactor()) * zout_gain);
5088 if (event.GetTotalScaleFactor() > 1)
5089 total_zoom_val = ((event.GetTotalScaleFactor() - 1.0) * zoom_gain) + 1.0;
5092 total_zoom_val = 1.0 - ((1.0 -
event.GetTotalScaleFactor()) * zout_gain);
5094 double projected_scale = cc1->GetVP().chart_scale / total_zoom_val;
5097 float max_zoom_scale = 1000.;
5098 if( cc1->GetVP().b_quilt) {
5099 int ref_index = cc1->GetQuiltRefChartdbIndex();
5106 float min_zoom_scale = 2e8;
5111 1.0 - ((1.0 -
event.GetTotalScaleFactor()) * zoom_gain);
5113 double projected_scale =
5114 m_pParentCanvas->GetVP().chart_scale / total_zoom_val;
5116 switch (event.GetState()) {
5117 case GestureStarted:
5122 m_binGesture =
true;
5124 m_pinchStart =
event.GetCenterPoint();
5125 m_lpinchPoint = m_pinchStart;
5127 m_pParentCanvas->GetCanvasPixPoint(event.GetCenterPoint().x,
5128 event.GetCenterPoint().y, m_pinchlat,
5133 m_cc_x = m_fbo_offsetx + (m_fbo_swidth / 2);
5134 m_cc_y = m_fbo_offsety + (m_fbo_sheight / 2);
5137 SetCurrent(*m_pcontext);
5143 case GestureUpdated:
5144 if (g_GLOptions.m_bUseCanvasPanning) {
5145 if (projected_scale < min_zoom_scale) {
5146 wxPoint pinchPoint =
event.GetCenterPoint();
5148 float dx = pinchPoint.x - m_lpinchPoint.x;
5149 float dy = pinchPoint.y - m_lpinchPoint.y;
5151 FastZoom(zoom_val, m_pinchStart.x, m_pinchStart.y,
5152 -dx / total_zoom_val, dy / total_zoom_val);
5154 m_lpinchPoint = pinchPoint;
5158 if (1 || ((total_zoom_val > 1) && !first_zout)) {
5159 wxPoint pinchPoint =
event.GetCenterPoint();
5161 float dx = pinchPoint.x - m_lpinchPoint.x;
5162 float dy = pinchPoint.y - m_lpinchPoint.y;
5164 if ((projected_scale > max_zoom_scale) &&
5165 (projected_scale < min_zoom_scale))
5166 FastZoom(zoom_val, m_pinchStart.x, m_pinchStart.y,
5167 -dx / total_zoom_val, dy / total_zoom_val);
5169 m_lpinchPoint = pinchPoint;
5173 zoom_inc *= zoom_val;
5174 if ((zoom_inc < 0.9) || (zoom_inc > 1.1)) {
5175 m_pParentCanvas->ZoomCanvas(zoom_inc,
false);
5179 wxPoint pinchPoint =
event.GetCenterPoint();
5180 float dx = pinchPoint.x - m_lpinchPoint.x;
5181 float dy = pinchPoint.y - m_lpinchPoint.y;
5182 m_pParentCanvas->PanCanvas(-dx, -dy);
5183 m_lpinchPoint = pinchPoint;
5194 case GestureFinished: {
5198 float cc_x = m_fbo_offsetx + (m_fbo_swidth / 2);
5199 float cc_y = m_fbo_offsety + (m_fbo_sheight / 2);
5203 float tzoom = total_zoom_val;
5205 if (projected_scale >= min_zoom_scale)
5206 tzoom = m_pParentCanvas->GetVP().chart_scale / min_zoom_scale;
5208 if (projected_scale < max_zoom_scale)
5209 tzoom = m_pParentCanvas->GetVP().chart_scale / max_zoom_scale;
5211 dx = (cc_x - m_cc_x) * tzoom;
5212 dy = -(cc_y - m_cc_y) * tzoom;
5215 if (zoomTimer.IsRunning()) {
5218 m_zoomFinalZoom = tzoom;
5224 double final_projected_scale =
5225 m_pParentCanvas->GetVP().chart_scale / tzoom;
5228 if (final_projected_scale < min_zoom_scale) {
5230 m_pParentCanvas->ZoomCanvas(tzoom,
false);
5231 m_pParentCanvas->PanCanvas(dx, dy);
5232 m_pParentCanvas->m_pQuilt->Invalidate();
5233 m_bforcefull =
true;
5237 m_pParentCanvas->GetCanvasScaleFactor() / min_zoom_scale;
5239 m_pParentCanvas->SetVPScale(new_scale);
5240 m_pParentCanvas->m_pQuilt->Invalidate();
5241 m_bforcefull =
true;
5253 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5257 case GestureCanceled:
5259 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5266 m_bgestureGuard =
true;
5268 m_gestureEeventTimer.Start(500, wxTIMER_ONE_SHOT);
5271 void glChartCanvas::onGestureTimerEvent(wxTimerEvent &event) {
5281 m_bgestureGuard =
false;
5282 m_bpinchGuard =
false;
5283 m_binGesture =
false;
5284 m_bforcefull =
false;
5287 void glChartCanvas::onGestureFinishTimerEvent(wxTimerEvent &event) {
5291 m_binGesture =
false;
5292 m_bforcefull =
false;
5297 void glChartCanvas::configureShaders(
ViewPort & vp) {
5298 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5304 GLShaderProgram *shader = pcolor_tri_shader_program[GetCanvasIndex()];
5306 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5307 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5327 shader = ptexture_2D_shader_program[GetCanvasIndex()];
5329 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5330 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5341 shader = pcircle_filled_shader_program[GetCanvasIndex()];
5343 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5344 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5348 shader = ptexture_2DA_shader_program[GetCanvasIndex()];
5350 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5351 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5359 shader = pAALine_shader_program[GetCanvasIndex()];
5361 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5364 shader = pring_shader_program[GetCanvasIndex()];
5366 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5367 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5371 if (texture_2DA_shader_program){
5372 glUseProgram(texture_2DA_shader_program);
5373 GLint matloc = glGetUniformLocation(texture_2DA_shader_program,
"MVMatrix");
5374 glUniformMatrix4fv(matloc, 1, GL_FALSE,
5375 (
const GLfloat *)pvp->vp_matrix_transform);
5377 glGetUniformLocation(texture_2DA_shader_program,
"TransformMatrix");
5378 glUniformMatrix4fv(transloc, 1, GL_FALSE, (
const GLfloat *)I);
5381 m_gldc.m_texfont.PrepareShader(vp.pix_width, vp.pix_height, vp.rotation);
5387 void glChartCanvas::RenderTextures(
ocpnDC &dc,
float *coords,
float *uvCoords,
5390 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5391 int nl = nVertex / 4;
5393 float *luv = uvCoords;
5396 RenderSingleTexture(dc, lc, luv, vp, 0, 0, 0);
5404 glEnableClientState(GL_VERTEX_ARRAY);
5405 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
5407 glTexCoordPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), uvCoords);
5408 glVertexPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), coords);
5409 glDrawArrays(GL_QUADS, 0, 4);
5416 void glChartCanvas::RenderSingleTexture(
ocpnDC &dc,
float *coords,
float *uvCoords,
5419 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5421 GLShaderProgram *shader = ptexture_2D_shader_program[dc.m_canvasIndex];
5427 shader->SetUniform1i(
"uTex", 0);
5432 mat4x4_rotate_Z(Q, I, angle_rad);
5439 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)Q);
5444 shader->SetAttributePointerf(
"aPos", co1);
5445 shader->SetAttributePointerf(
"aUV", tco1);
5453 GLushort indices1[] = {0,1,3,2};
5454 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices1);
5466 tco1[0] = uvCoords[0];
5467 tco1[1] = uvCoords[1];
5468 tco1[2] = uvCoords[2];
5469 tco1[3] = uvCoords[3];
5470 tco1[4] = uvCoords[6];
5471 tco1[5] = uvCoords[7];
5472 tco1[6] = uvCoords[4];
5473 tco1[7] = uvCoords[5];
5478 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5490 void glChartCanvas::RenderColorRect(wxRect r, wxColor & color) {
5491 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5493 GLShaderProgram *shader = pcolor_tri_shader_program[GetCanvasIndex()];
5496 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_pParentCanvas->GetpVP()->vp_matrix_transform);
5499 colorv[0] = color.Red() / float(256);
5500 colorv[1] = color.Green() / float(256);
5501 colorv[2] = color.Blue() / float(256);
5503 shader->SetUniform4fv(
"color", colorv);
5506 pf[0] = r.x + r.width;
5510 pf[4] = r.x + r.width;
5511 pf[5] = r.y + r.height;
5513 pf[7] = r.y + r.height;
5514 shader->SetAttributePointerf(
"position", pf);
5516 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5524 void glChartCanvas::RenderScene(
bool bRenderCharts,
bool bRenderOverlays) {
5526 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5528 ViewPort VPoint = m_pParentCanvas->VPoint;
5532 GetClientSize(&w, &h);
5533 int sx = GetSize().x;
5534 int sy = GetSize().y;
5536 OCPNRegion screen_region(wxRect(0, 0, VPoint.pix_width, VPoint.pix_height));
5538 glViewport(0, 0, (GLint)w, (GLint)h);
5540 if (s_b_useStencil) {
5541 glEnable(GL_STENCIL_TEST);
5542 glStencilMask(0xff);
5543 glClear(GL_STENCIL_BUFFER_BIT);
5544 glDisable(GL_STENCIL_TEST);
5548 m_pParentCanvas->m_pQuilt->
Compose(m_pParentCanvas->VPoint);
5553 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
5554 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
5555 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5558 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
5560 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
5561 g_texture_rectangle_format,
5562 m_cache_tex[m_cache_page], 0);
5569 if (bRenderCharts) RenderCharts(gldc, screen_region);
5571 if (bRenderOverlays) {
5572 RenderS57TextOverlay(m_pParentCanvas->VPoint);
5573 RenderMBTilesOverlay(m_pParentCanvas->VPoint);
5574 DrawStaticRoutesTracksAndWaypoints(m_pParentCanvas->VPoint);
5575 DrawDynamicRoutesTracksAndWaypoints(VPoint);
5576 DrawFloatingOverlayObjects(m_gldc);
5580 glBindFramebuffer(GL_FRAMEBUFFER, 0);
bool MouseEventSetup(wxMouseEvent &event, bool b_handle_dclick=true)
bool Compose(const ViewPort &vp)
Set of basemaps at different resolutions.