40#include <wx/arrimpl.cpp>
43#include <wx/dcmemory.h>
44#include <wx/dynarray.h>
48#include <wx/glcanvas.h>
50#include <wx/jsonval.h>
53#include <wx/progdlg.h>
54#include <wx/stopwatch.h>
56#include <wx/tokenzr.h>
70#include "emboss_data.h"
72#include "glChartCanvas.h"
73#include "glTexCache.h"
77#include "mipmap/mipmap.h"
79#include "color_handler.h"
80#include "OCPNPlatform.h"
83#include "pluginmanager.h"
85#include "RolloverWin.h"
89#include "route_point_gui.h"
99#ifdef USE_ANDROID_GLES2
100#include <GLES2/gl2.h>
106#include "androidUTIL.h"
107#elif defined(__WXQT__) || defined(__WXGTK__)
111#ifndef GL_ETC1_RGB8_OES
112#define GL_ETC1_RGB8_OES 0x8D64
115#ifndef GL_DEPTH_STENCIL_ATTACHMENT
116#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
119#if defined(__UNIX__) && !defined(__WXOSX__)
124 void Reset() { clock_gettime(CLOCK_REALTIME, &tp); }
128 clock_gettime(CLOCK_REALTIME, &tp_end);
129 return (tp_end.tv_sec - tp.tv_sec) * 1.e3 +
130 (tp_end.tv_nsec - tp.tv_nsec) / 1.e6;
138#if defined(__OCPN__ANDROID__)
139#include "androidUTIL.h"
140#elif defined(__WXQT__) || defined(__WXGTK__) || defined(FLATPAK)
145#ifndef GL_ETC1_RGB8_OES
146#define GL_ETC1_RGB8_OES 0x8D64
152#ifdef __OCPN__ANDROID__
155extern "C" void glOrthof(
float left,
float right,
float bottom,
float top,
156 float near,
float far);
157#define glOrtho(a, b, c, d, e, f) \
159 glOrthof(a, b, c, d, e, f);
167#ifdef USE_ANDROID_GLES2
168#include <GLES2/gl2.h>
171#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
176extern bool GetMemoryStatus(
int *mem_total,
int *mem_used);
178extern s52plib *ps52plib;
179extern bool g_bopengl;
180extern bool g_bDebugOGL;
181extern bool g_bShowFPS;
182extern bool g_bSoftwareGL;
185extern bool g_bShowChartBar;
187extern bool b_inCompressAllCharts;
189GLenum g_texture_rectangle_format;
191extern int g_memCacheLimit;
192extern ColorScheme global_color_scheme;
193extern bool g_bquiting;
195extern int g_mipmap_max_level;
197extern int g_OwnShipIconType;
204extern RouteList *pRouteList;
205extern std::vector<Track*> g_TrackList;
206extern bool b_inCompressAllCharts;
207extern bool g_bGLexpert;
208extern bool g_bcompression_wait;
209extern float g_ShipScaleFactorExp;
211float g_GLMinSymbolLineWidth;
212float g_GLMinCartographicLineWidth;
214extern bool g_fog_overzoom;
215extern double g_overzoom_emphasis_base;
216extern bool g_oz_vector_scale;
218extern int g_nCPUCount;
219extern bool g_running;
221extern unsigned int g_canvasConfig;
228wxColor s_regionColor;
239#define APIENTRYP APIENTRY *
245#ifndef GL_COMPRESSED_RGB_FXT1_3DFX
246#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
249PFNGLGENFRAMEBUFFERSEXTPROC s_glGenFramebuffers;
250PFNGLGENRENDERBUFFERSEXTPROC s_glGenRenderbuffers;
251PFNGLFRAMEBUFFERTEXTURE2DEXTPROC s_glFramebufferTexture2D;
252PFNGLBINDFRAMEBUFFEREXTPROC s_glBindFramebuffer;
253PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC s_glFramebufferRenderbuffer;
254PFNGLRENDERBUFFERSTORAGEEXTPROC s_glRenderbufferStorage;
255PFNGLBINDRENDERBUFFEREXTPROC s_glBindRenderbuffer;
256PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC s_glCheckFramebufferStatus;
257PFNGLDELETEFRAMEBUFFERSEXTPROC s_glDeleteFramebuffers;
258PFNGLDELETERENDERBUFFERSEXTPROC s_glDeleteRenderbuffers;
260PFNGLCOMPRESSEDTEXIMAGE2DPROC s_glCompressedTexImage2D;
261PFNGLGETCOMPRESSEDTEXIMAGEPROC s_glGetCompressedTexImage;
264PFNGLGENBUFFERSPROC s_glGenBuffers;
265PFNGLBINDBUFFERPROC s_glBindBuffer;
266PFNGLBUFFERDATAPROC s_glBufferData;
267PFNGLDELETEBUFFERSPROC s_glDeleteBuffers;
269#ifndef USE_ANDROID_GLES2
274typedef void(APIENTRYP PFNGLGETBUFFERPARAMETERIV)(GLenum target, GLenum value,
276PFNGLGETBUFFERPARAMETERIV s_glGetBufferParameteriv;
278#include <wx/arrimpl.cpp>
281GLuint g_raster_format = GL_RGB;
285wxStopWatch g_glstopwatch;
286double g_gl_ms_per_frame;
289int g_uncompressed_tile_size;
291extern wxProgressDialog *pprog;
292extern bool b_skipout;
293extern wxSize pprog_size;
294extern int pprog_count;
295extern int pprog_threads;
296extern float g_ChartScaleFactorExp;
303bool glChartCanvas::s_b_useScissorTest;
304bool glChartCanvas::s_b_useStencil;
305bool glChartCanvas::s_b_useStencilAP;
306bool glChartCanvas::s_b_useFBO;
308#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
309static int s_tess_vertex_idx;
310static int s_tess_vertex_idx_this;
311static int s_tess_buf_len;
312static GLfloat *s_tess_work_buf;
315static vec4 s_tess_color;
325 while ( upd.HaveRects() )
327 wxRect rect = upd.GetRect();
328 printf(
"[(%d, %d) (%d, %d)] ", rect.x, rect.y, rect.width, rect.height);
334GLboolean QueryExtension(
const char *extName) {
345 extNameLen = strlen(extName);
347 p = (
char *)glGetString(GL_EXTENSIONS);
355 int n = strcspn(p,
" ");
356 if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
365int test_attribs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE,
366 16, WX_GL_STENCIL_SIZE, 8,
369glTestCanvas::glTestCanvas(wxWindow *parent)
370 : wxGLCanvas(parent, wxID_ANY, test_attribs, wxDefaultPosition,
374int attribs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE,
375 16, WX_GL_STENCIL_SIZE, 8,
378EVT_PAINT(glChartCanvas::OnPaint)
379EVT_ACTIVATE(glChartCanvas::OnActivate) EVT_SIZE(glChartCanvas::OnSize)
380 EVT_MOUSE_EVENTS(glChartCanvas::MouseEvent) END_EVENT_TABLE()
383 : wxGLCanvas(parent, wxID_ANY, attribs, wxDefaultPosition, wxSize(256, 256),
384 wxFULL_REPAINT_ON_RESIZE | wxBG_STYLE_CUSTOM, _T(""))
387 m_pParentCanvas =
dynamic_cast<ChartCanvas *
>(parent);
392void glChartCanvas::Init() {
397 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
399 m_cache_current_ch = NULL;
401 m_b_paint_enable =
true;
402 m_in_glpaint =
false;
404 m_cache_tex[0] = m_cache_tex[1] = 0;
407 m_b_BuiltFBO =
false;
408 m_b_DisableFBO =
false;
417 m_bpinchGuard =
false;
418 m_binGesture =
false;
421 m_last_render_time = -1;
428 m_gldc.SetGLCanvas(
this);
429 m_gldc.SetDPIFactor(g_BasePlatform->GetDisplayDIPMult(GetParent()));
431 m_displayScale = 1.0;
432#if defined(__WXOSX__) || defined(__WXGTK3__)
434 m_displayScale = GetContentScaleFactor();
437#ifdef __OCPN__ANDROID__
442 (wxObjectEventFunction)(wxEventFunction)&glChartCanvas::OnEvtPanGesture,
446 wxEVT_QT_PINCHGESTURE,
447 (wxObjectEventFunction)(wxEventFunction)&glChartCanvas::OnEvtPinchGesture,
450 Connect(GESTURE_EVENT_TIMER, wxEVT_TIMER,
451 (wxObjectEventFunction)(
452 wxEventFunction)&glChartCanvas::onGestureTimerEvent,
455 Connect(GESTURE_FINISH_TIMER, wxEVT_TIMER,
456 (wxObjectEventFunction)(
457 wxEventFunction)&glChartCanvas::onGestureFinishTimerEvent,
461 ZOOM_TIMER, wxEVT_TIMER,
462 (wxObjectEventFunction)(wxEventFunction)&glChartCanvas::onZoomTimerEvent,
465 m_gestureEeventTimer.SetOwner(
this, GESTURE_EVENT_TIMER);
466 m_gestureFinishTimer.SetOwner(
this, GESTURE_FINISH_TIMER);
467 zoomTimer.SetOwner(
this, ZOOM_TIMER);
469#ifdef USE_ANDROID_GLES2
477 m_bgestureGuard =
false;
482#ifdef HAVE_WX_GESTURE_EVENTS
483 if (!EnableTouchEvents(wxTOUCH_ZOOM_GESTURE |
484 wxTOUCH_PRESS_GESTURES)) {
485 wxLogError(
"Failed to enable touch events");
488 Bind(wxEVT_GESTURE_ZOOM, &ChartCanvas::OnZoom, m_pParentCanvas);
490 Bind(wxEVT_LONG_PRESS, &ChartCanvas::OnLongPress, m_pParentCanvas);
491 Bind(wxEVT_PRESS_AND_TAP, &ChartCanvas::OnPressAndTap, m_pParentCanvas);
493 Bind(wxEVT_RIGHT_UP, &ChartCanvas::OnRightUp, m_pParentCanvas);
494 Bind(wxEVT_RIGHT_DOWN, &ChartCanvas::OnRightDown, m_pParentCanvas);
496 Bind(wxEVT_LEFT_UP, &ChartCanvas::OnLeftUp, m_pParentCanvas);
497 Bind(wxEVT_LEFT_DOWN, &ChartCanvas::OnLeftDown, m_pParentCanvas);
499 Bind(wxEVT_MOUSEWHEEL, &ChartCanvas::OnWheel, m_pParentCanvas);
500 Bind(wxEVT_MOTION, &ChartCanvas::OnMotion, m_pParentCanvas);
507glChartCanvas::~glChartCanvas() {
508#ifdef __OCPN__ANDROID__
513void glChartCanvas::FlushFBO(
void) {
514 if (m_bsetup) BuildFBO();
517void glChartCanvas::OnActivate(wxActivateEvent &event) {
518 m_pParentCanvas->OnActivate(event);
521void glChartCanvas::OnSize(wxSizeEvent &event) {
523#ifdef __OCPN__ANDROID__
525 wxLogMessage(_T(
"Got OnSize event while NOT running"));
527 qDebug() <<
"OnSizeB";
534 if (!IsShown())
return;
536 SetCurrent(*m_pcontext);
539 SetSize(GetSize().x, GetSize().y);
547 if (m_bsetup && m_pcontext && IsShown()) {
548 SetCurrent(*m_pcontext);
554 wxLogMessage(_T(
"BuildFBO 3"));
560 ViewPort *vp = m_pParentCanvas->GetpVP();
563 mat4x4_scale_aniso((
float(*)[4])vp->vp_matrix_transform, m,
564 2.0 / (
float)vp->pix_width, -2.0 / (
float)vp->pix_height,
566 mat4x4_translate_in_place((
float(*)[4])vp->vp_matrix_transform, -vp->pix_width / 2,
567 -vp->pix_height / 2, 0);
570void glChartCanvas::MouseEvent(wxMouseEvent &event) {
571 if (m_pParentCanvas->MouseEventOverlayWindows(event))
return;
573#ifndef __OCPN__ANDROID__
577 bool obj_proc = m_pParentCanvas->MouseEventProcessObjects(event);
579 if (!obj_proc && !m_pParentCanvas->singleClickEventIsValid)
580 m_pParentCanvas->MouseEventProcessCanvas(event);
582 if (!g_btouch) m_pParentCanvas->SetCanvasCursor(event);
586 if (m_bgestureGuard) {
587 m_pParentCanvas->r_rband.x = 0;
597 if (event.LeftUp()) {
599 if ((abs(panx) > 2) || (abs(pany) > 2)) {
602 m_gestureEeventTimer.Start(10, wxTIMER_ONE_SHOT);
609 if (!event.LeftDClick()) {
614 if (m_binPan && event.RightDown()) {
615 qDebug() <<
"Skip right on pan";
618 bool obj_proc = m_pParentCanvas->MouseEventProcessObjects(event);
620 if (!obj_proc && !m_pParentCanvas->singleClickEventIsValid) {
621 if (!m_bgestureGuard)
622 m_pParentCanvas->MouseEventProcessCanvas(
631#ifndef GL_MAX_RENDERBUFFER_SIZE
632#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
635#ifndef USE_ANDROID_GLES2
636bool glChartCanvas::buildFBOSize(
int fboSize) {
638 if (IsShown()) SetCurrent(*m_pcontext);
641 glDeleteTextures(2, m_cache_tex);
642 glDeleteFramebuffers(1, &m_fb0);
643 glDeleteRenderbuffers(1, &m_renderbuffer);
644 m_b_BuiltFBO =
false;
647 if (m_b_DisableFBO)
return false;
649#ifdef __OCPN__ANDROID__
651 int rb_x = GetSize().x;
652 int rb_y = GetSize().y;
654 while (i < rb_x) i <<= 1;
658 while (i < rb_y) i <<= 1;
661 m_cache_tex_x = wxMax(rb_x, rb_y);
662 m_cache_tex_y = wxMax(rb_x, rb_y);
665 m_cache_tex_x = GetSize().x * m_displayScale;
666 m_cache_tex_y = GetSize().y * m_displayScale;
669 int err = GL_NO_ERROR;
671 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, ¶ms);
674 if (err == GL_INVALID_ENUM) {
675 glGetIntegerv(GL_MAX_TEXTURE_SIZE, ¶ms);
679 if (err == GL_NO_ERROR) {
680 if (fboSize > params) {
682 _T(
" OpenGL-> Requested Framebuffer size exceeds ")
683 _T(
"GL_MAX_RENDERBUFFER_SIZE"));
688 glGenFramebuffers(1, &m_fb0);
692 msg.Printf(_T(
" OpenGL-> Framebuffer GenFramebuffers error: %08X"),
698 glGenRenderbuffers(1, &m_renderbuffer);
702 msg.Printf(_T(
" OpenGL-> Framebuffer GenRenderbuffers error: %08X"),
708 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
712 msg.Printf(_T(
" OpenGL-> Framebuffer BindFramebuffers error: %08X"),
719 glGenTextures(2, m_cache_tex);
720 for (
int i = 0; i < 2; i++) {
721 glBindTexture(g_texture_rectangle_format, m_cache_tex[i]);
722 glTexParameterf(g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER,
724 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER,
726 glTexImage2D(g_texture_rectangle_format, 0, GL_RGBA, m_cache_tex_x,
727 m_cache_tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
730 glBindRenderbuffer(GL_RENDERBUFFER_EXT, m_renderbuffer);
732 if (m_b_useFBOStencil) {
734 glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
735 m_cache_tex_x, m_cache_tex_y);
737 int err = glGetError();
740 msg.Printf(_T(
" OpenGL-> glRenderbufferStorage error: %08X"), err);
744 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
745 GL_RENDERBUFFER_EXT, m_renderbuffer);
750 _T(
" OpenGL-> glFramebufferRenderbuffer depth error: %08X"), err);
754 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
755 GL_RENDERBUFFER_EXT, m_renderbuffer);
760 _T(
" OpenGL-> glFramebufferRenderbuffer stencil error: %08X"),
766 GLenum depth_format = GL_DEPTH_COMPONENT24;
771 if (!QueryExtension(
"GL_OES_depth24")) depth_format = GL_DEPTH_COMPONENT16;
775 glRenderbufferStorage(GL_RENDERBUFFER_EXT, depth_format, m_cache_tex_x,
777 int err = glGetError();
781 _T(
" OpenGL-> Framebuffer Depth Buffer Storage error: %08X"),
787 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
788 GL_RENDERBUFFER_EXT, m_renderbuffer);
794 _T(
" OpenGL-> Framebuffer Depth Buffer Attach error: %08X"), err);
800 glBindTexture(GL_TEXTURE_2D, 0);
801 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
804 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
806 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
807 g_texture_rectangle_format, m_cache_tex[0], 0);
809 GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
811 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
813 if (fb_status != GL_FRAMEBUFFER_COMPLETE_EXT) {
815 msg.Printf(_T(
" OpenGL-> buildFBOSize->Framebuffer Incomplete: %08X"),
825#ifdef USE_ANDROID_GLES2
826bool glChartCanvas::buildFBOSize(
int fboSize) {
830 int rb_x = GetSize().x;
831 int rb_y = GetSize().y;
833 while (i < rb_x) i <<= 1;
837 while (i < rb_y) i <<= 1;
840 m_cache_tex_x = wxMax(rb_x, rb_y);
841 m_cache_tex_y = wxMax(rb_x, rb_y);
845 int err = GL_NO_ERROR;
847 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, ¶ms);
850 if (err == GL_INVALID_ENUM) {
851 glGetIntegerv(GL_MAX_TEXTURE_SIZE, ¶ms);
855 if (err == GL_NO_ERROR) {
856 if (fboSize > params) {
858 _T(
" OpenGL-> Requested Framebuffer size exceeds ")
859 _T(
"GL_MAX_RENDERBUFFER_SIZE"));
864 glGenFramebuffers(1, &m_fb0);
868 msg.Printf(_T(
" OpenGL-> Framebuffer GenFramebuffers error: %08X"),
874 glGenRenderbuffers(1, &m_renderbuffer);
878 msg.Printf(_T(
" OpenGL-> Framebuffer GenRenderbuffers error: %08X"),
884 glBindFramebuffer(GL_FRAMEBUFFER, m_fb0);
888 msg.Printf(_T(
" OpenGL-> Framebuffer BindFramebuffers error: %08X"),
895 glGenTextures(2, m_cache_tex);
896 for (
int i = 0; i < 2; i++) {
897 glBindTexture(g_texture_rectangle_format, m_cache_tex[i]);
898 glTexParameterf(g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER,
900 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER,
902 glTexImage2D(g_texture_rectangle_format, 0, GL_RGBA, m_cache_tex_x,
903 m_cache_tex_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
906 glBindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
909 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, m_cache_tex_x,
915 msg.Printf(_T(
" OpenGL-> glRenderbufferStorage error: %08X"), err);
919 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
920 GL_RENDERBUFFER, m_renderbuffer);
924 msg.Printf(_T(
" OpenGL-> glFramebufferRenderbuffer depth error: %08X"),
929 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
930 GL_RENDERBUFFER, m_renderbuffer);
935 _T(
" OpenGL-> glFramebufferRenderbuffer stencil error: %08X"), err);
939 glBindTexture(GL_TEXTURE_2D, 0);
940 glBindFramebuffer(GL_FRAMEBUFFER, 0);
943 glBindFramebuffer(GL_FRAMEBUFFER, m_fb0);
945 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
946 g_texture_rectangle_format, m_cache_tex[0], 0);
948 GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
950 glBindFramebuffer(GL_FRAMEBUFFER, 0);
952 if (fb_status != GL_FRAMEBUFFER_COMPLETE) {
955 _T(
" OpenGL-> buildFBOSize->Framebuffer Incomplete: %08X %08X"),
965void glChartCanvas::BuildFBO() {
968 glDeleteTextures(2, m_cache_tex);
969 glDeleteFramebuffers(1, &m_fb0);
970 glDeleteRenderbuffers(1, &m_renderbuffer);
971 m_b_BuiltFBO =
false;
974 if (m_b_DisableFBO)
return;
977 int gl_width, gl_height;
978 m_pParentCanvas->GetClientSize(&gl_width, &gl_height);
979 int initialSize = NextPow2(gl_width * m_displayScale);
981#ifdef __OCPN__ANDROID__
984 wxString info = androidGetDeviceInfo();
986 if (wxNOT_FOUND != info.Find(_T(
"GT-S6312"))) initialSize = 1024;
989 if (!buildFBOSize(initialSize)) {
990 glDeleteTextures(2, m_cache_tex);
991 glDeleteFramebuffers(1, &m_fb0);
992 glDeleteRenderbuffers(1, &m_renderbuffer);
994 if (!buildFBOSize(1024)) {
995 wxLogMessage(_T(
"BuildFBO C"));
997 m_b_DisableFBO =
true;
998 wxLogMessage(_T(
"OpenGL-> FBO Framebuffer unavailable"));
999 m_b_BuiltFBO =
false;
1008 msg.Printf(_T(
"OpenGL-> Framebuffer OK, size = %d"), m_cache_tex_x);
1014 glClear(GL_COLOR_BUFFER_BIT);
1015 m_b_BuiltFBO =
true;
1020void glChartCanvas::SetupOpenGL() {
1021 SetCurrent(*m_pcontext);
1023 char *str = (
char *)glGetString(GL_RENDERER);
1026 wxLogMessage(_T(
"Failed to initialize OpenGL"));
1030 char render_string[80];
1031 strncpy(render_string, str, 79);
1032 m_renderer = wxString(render_string, wxConvUTF8);
1035 if (g_bSoftwareGL) msg.Printf(_T(
"OpenGL-> Software OpenGL"));
1036 msg.Printf(_T(
"OpenGL-> Renderer String: "));
1040 if (ps52plib) ps52plib->SetGLRendererString(m_renderer);
1042 char version_string[80];
1043 strncpy(version_string, (
char *)glGetString(GL_VERSION), 79);
1044 msg.Printf(_T(
"OpenGL-> Version reported: "));
1045 m_version = wxString(version_string, wxConvUTF8);
1049 char GLSL_version_string[80];
1050 strncpy(GLSL_version_string, (
char *)glGetString(GL_SHADING_LANGUAGE_VERSION), 79);
1051 msg.Printf(_T(
"OpenGL-> GLSL Version reported: "));
1052 m_GLSLversion = wxString(GLSL_version_string, wxConvUTF8);
1053 msg += m_GLSLversion;
1056#ifndef __OCPN__ANDROID__
1058 GLenum err = glewInit();
1059#ifdef GLEW_ERROR_NO_GLX_DISPLAY
1060 if (GLEW_OK != err && GLEW_ERROR_NO_GLX_DISPLAY != err)
1065 printf(
"GLEW init failed: %s\n", glewGetErrorString(err));
1070 printf(
"GLEW init success!n");
1075 const GLubyte *ext_str = glGetString(GL_EXTENSIONS);
1076 m_extensions = wxString((
const char *)ext_str, wxConvUTF8);
1080#ifndef USE_ANDROID_GLES2
1081 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
1083 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
1085 g_GLMinSymbolLineWidth = wxMax(parms[0], 1);
1086 g_GLMinCartographicLineWidth = wxMax(parms[0], 1);
1093 if (m_renderer.Upper().Find(_T(
"MESA")) != wxNOT_FOUND) {
1095 glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &parf);
1097 g_GLMinSymbolLineWidth = wxMax(((
float)parms[0] + parf), 1);
1100 s_b_useScissorTest =
true;
1102 if (GetRendererString().Find(_T(
"RADEON X600")) != wxNOT_FOUND)
1103 s_b_useScissorTest =
false;
1105 if (GetRendererString().Find(_T(
"GeForce")) !=
1107 s_b_useScissorTest =
false;
1109 bool bad_stencil_code =
false;
1112 if (GetRendererString().Find(_T(
"UniChrome")) != wxNOT_FOUND)
1113 bad_stencil_code =
true;
1116 if (GetRendererString().Find(_T(
"Mali")) != wxNOT_FOUND)
1117 bad_stencil_code =
true;
1120 glEnable(GL_STENCIL_TEST);
1121 GLboolean stencil = glIsEnabled(GL_STENCIL_TEST);
1123 glGetIntegerv(GL_STENCIL_BITS, &sb);
1126 glDisable(GL_STENCIL_TEST);
1128 s_b_useStencil =
false;
1129 if (stencil && (sb == 8)) s_b_useStencil =
true;
1131 if (QueryExtension(
"GL_ARB_texture_non_power_of_two"))
1132 g_texture_rectangle_format = GL_TEXTURE_2D;
1133 else if (QueryExtension(
"GL_OES_texture_npot"))
1134 g_texture_rectangle_format = GL_TEXTURE_2D;
1135 else if (QueryExtension(
"GL_ARB_texture_rectangle"))
1136 g_texture_rectangle_format = GL_TEXTURE_RECTANGLE_ARB;
1137 wxLogMessage(wxString::Format(_T(
"OpenGL-> Texture rectangle format: %x"),
1138 g_texture_rectangle_format));
1140#ifdef __OCPN__ANDROID__
1141 g_texture_rectangle_format = GL_TEXTURE_2D;
1145 g_b_EnableVBO =
true;
1147#ifdef __OCPN__ANDROID__
1148 g_b_EnableVBO =
false;
1152 wxLogMessage(_T(
"OpenGL-> Using Vertexbuffer Objects"));
1154 wxLogMessage(_T(
"OpenGL-> Vertexbuffer Objects unavailable"));
1158 m_b_useFBOStencil = QueryExtension(
"GL_OES_packed_depth_stencil");
1160 m_b_useFBOStencil = QueryExtension(
"GL_EXT_packed_depth_stencil") == GL_TRUE;
1163#ifndef USE_ANDROID_GLES2
1165 if (bad_stencil_code) s_b_useStencil =
false;
1168 g_GLOptions.m_bUseCanvasPanning =
false;
1181#ifndef __OCPN__ANDROID__
1185 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
1187 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
1188 g_texture_rectangle_format, m_cache_tex[0], 0);
1190 GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
1191 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
1193 if (fb_status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1195 msg.Printf(_T(
" OpenGL-> Framebuffer Incomplete: %08X"), fb_status);
1197 m_b_DisableFBO =
true;
1203 if (m_b_BuiltFBO && !m_b_useFBOStencil) s_b_useStencil =
false;
1207 s_b_useStencilAP = s_b_useStencil & !bad_stencil_code;
1209#ifdef USE_ANDROID_GLES2
1210 s_b_useStencilAP = s_b_useStencil;
1217 wxLogMessage(_T(
"OpenGL-> Using Framebuffer Objects"));
1219 if (m_b_useFBOStencil)
1220 wxLogMessage(_T(
"OpenGL-> Using FBO Stencil buffer"));
1222 wxLogMessage(_T(
"OpenGL-> FBO Stencil buffer unavailable"));
1224 wxLogMessage(_T(
"OpenGL-> Framebuffer Objects unavailable"));
1227 wxLogMessage(_T(
"OpenGL-> Using Stencil buffer clipping"));
1229 wxLogMessage(_T(
"OpenGL-> Using Depth buffer clipping"));
1231 if (s_b_useScissorTest && s_b_useStencil)
1232 wxLogMessage(_T(
"OpenGL-> Using Scissor Clipping"));
1235 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1237 MipMap_ResolveRoutines();
1241 lwmsg.Printf(_T(
"OpenGL-> Minimum cartographic line width: %4.1f"),
1242 g_GLMinCartographicLineWidth);
1243 wxLogMessage(lwmsg);
1244 lwmsg.Printf(_T(
"OpenGL-> Minimum symbol line width: %4.1f"),
1245 g_GLMinSymbolLineWidth);
1246 wxLogMessage(lwmsg);
1250 g_GLOptions.m_bUseAcceleratedPanning = !m_b_DisableFBO && m_b_BuiltFBO;
1252#ifdef USE_ANDROID_GLES2
1253 g_GLOptions.m_bUseAcceleratedPanning =
true;
1259 int tex_dim = g_GLOptions.m_iTextureDimension;
1260 for (
int dim = tex_dim; dim > 0; dim /= 2) max_level++;
1261 g_mipmap_max_level = max_level - 1;
1265#ifdef __OCPN__ANDROID__
1266 g_mipmap_max_level = 4;
1269 s_b_useFBO = m_b_BuiltFBO;
1273 ps52plib->SetGLOptions(s_b_useStencil, s_b_useStencilAP, s_b_useScissorTest,
1274 s_b_useFBO, g_b_EnableVBO,
1275 g_texture_rectangle_format,
1276 g_GLMinCartographicLineWidth,
1277 g_GLMinSymbolLineWidth );
1281 SendJSONConfigMessage();
1284void glChartCanvas::SendJSONConfigMessage() {
1287 v[_T(
"setupComplete")] = m_bsetup;
1288 v[_T(
"useStencil")] = s_b_useStencil;
1289 v[_T(
"useStencilAP")] = s_b_useStencilAP;
1290 v[_T(
"useScissorTest")] = s_b_useScissorTest;
1291 v[_T(
"useFBO")] = s_b_useFBO;
1292 v[_T(
"useVBO")] = g_b_EnableVBO;
1293 v[_T(
"TextureRectangleFormat")] = g_texture_rectangle_format;
1294 wxString msg_id(_T(
"OCPN_OPENGL_CONFIG"));
1295 g_pi_manager->SendJSONMessageToAllPlugins(msg_id, v);
1298void glChartCanvas::SetupCompression() {
1299 int dim = g_GLOptions.m_iTextureDimension;
1302 if (!::IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) {
1303 wxLogMessage(_T(
"OpenGL-> SSE2 Instruction set not available"));
1304 goto no_compression;
1308 g_uncompressed_tile_size = dim * dim * 4;
1309 if (!g_GLOptions.m_bTextureCompression)
goto no_compression;
1311 g_raster_format = GL_RGB;
1315 if (QueryExtension(
"GL_OES_compressed_ETC1_RGB8_texture")) {
1316 g_raster_format = GL_ETC1_RGB8_OES;
1318 wxLogMessage(_T(
"OpenGL-> Using oes etc1 compression"));
1322 if (GL_RGB == g_raster_format) {
1328 if ((QueryExtension(
"GL_EXT_texture_compression_s3tc") ||
1329 QueryExtension(
"GL_EXT_texture_compression_dxt1"))
1333 if (GetRendererString().Find(_T(
"Gallium")) != wxNOT_FOUND &&
1334 GetRendererString().Find(_T(
"NV")) != wxNOT_FOUND)
1335 g_raster_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1337 g_raster_format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1339 wxLogMessage(_T(
"OpenGL-> Using s3tc dxt1 compression"));
1340 }
else if (QueryExtension(
"GL_3DFX_texture_compression_FXT1")
1342 g_raster_format = GL_COMPRESSED_RGB_FXT1_3DFX;
1344 wxLogMessage(_T(
"OpenGL-> Using 3dfx fxt1 compression"));
1346 wxLogMessage(_T(
"OpenGL-> No Useable compression format found"));
1347 goto no_compression;
1352 g_tile_size = 512 * 512 / 2;
1356 glGenTextures(1, &texture);
1357 glBindTexture(GL_TEXTURE_2D, texture);
1358 glTexImage2D(GL_TEXTURE_2D, 0, g_raster_format, dim, dim, 0, GL_RGB,
1359 GL_UNSIGNED_BYTE, NULL);
1360 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
1362 glDeleteTextures(1, &texture);
1366 if (g_tile_size == 0)
goto no_compression;
1368 wxLogMessage(wxString::Format(
1369 _T(
"OpenGL-> Compressed tile size: %dkb (%d:1)"), g_tile_size / 1024,
1370 g_uncompressed_tile_size / g_tile_size));
1374 g_GLOptions.m_bTextureCompression =
false;
1376 g_tile_size = g_uncompressed_tile_size;
1377 wxLogMessage(wxString::Format(_T(
"OpenGL-> Not Using compression")));
1380void glChartCanvas::OnPaint(wxPaintEvent &event) {
1383 if (!m_pcontext)
return;
1391 SetCurrent(*m_pcontext);
1396 if (ps52plib) ps52plib->FlushSymbolCaches();
1404 if (!m_b_paint_enable)
return;
1407 if (m_in_glpaint)
return;
1410 m_pParentCanvas->UpdateCanvasS52PLIBConfig();
1433bool glChartCanvas::HasNormalizedViewPort(
const ViewPort &vp) {
1435#ifndef USE_ANDROID_GLES2
1436 return vp.m_projection_type == PROJECTION_MERCATOR ||
1437 vp.m_projection_type == PROJECTION_POLAR ||
1438 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1452#define NORM_FACTOR 4096.0
1453void glChartCanvas::MultMatrixViewPort(
ViewPort &vp,
float lat,
float lon) {
1454#ifndef USE_ANDROID_GLES2
1456 wxPoint2DDouble point;
1458 switch (vp.m_projection_type) {
1459 case PROJECTION_MERCATOR:
1460 case PROJECTION_EQUIRECTANGULAR:
1461 case PROJECTION_WEB_MERCATOR:
1463 point = vp.GetDoublePixFromLL(lat, lon);
1464 glTranslated(point.m_x, point.m_y, 0);
1465 glScaled(vp.view_scale_ppm / NORM_FACTOR, vp.view_scale_ppm / NORM_FACTOR,
1469 case PROJECTION_POLAR:
1472 point = vp.GetDoublePixFromLL(vp.clat > 0 ? 90 : -90, vp.clon);
1473 glTranslated(point.m_x, point.m_y, 0);
1474 glRotatef(vp.clon - lon, 0, 0, vp.clat);
1475 glScalef(vp.view_scale_ppm / NORM_FACTOR, vp.view_scale_ppm / NORM_FACTOR,
1477 glTranslatef(-vp.pix_width / 2, -vp.pix_height / 2, 0);
1481 printf(
"ERROR: Unhandled projection\n");
1484 double rotation = vp.rotation;
1486 if (rotation) glRotatef(rotation * 180 / PI, 0, 0, 1);
1494 switch (vp.m_projection_type) {
1495 case PROJECTION_MERCATOR:
1496 case PROJECTION_EQUIRECTANGULAR:
1497 case PROJECTION_WEB_MERCATOR:
1501 case PROJECTION_POLAR:
1502 cvp.clat = vp.clat > 0 ? 90 : -90;
1506 printf(
"ERROR: Unhandled projection\n");
1510 cvp.view_scale_ppm = NORM_FACTOR;
1511 cvp.rotation = cvp.skew = 0;
1515bool glChartCanvas::CanClipViewport(
const ViewPort &vp) {
1516 return vp.m_projection_type == PROJECTION_MERCATOR ||
1517 vp.m_projection_type == PROJECTION_WEB_MERCATOR ||
1518 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1522 const LLRegion ®ion) {
1523 if (!CanClipViewport(vp))
return vp;
1526 LLBBox bbox = region.GetBox();
1528 if (!bbox.GetValid())
return vp;
1536 if (bbox.GetMaxLon() < cvp.GetBBox().GetMinLon()) {
1537 bbox.Set(bbox.GetMinLat(), bbox.GetMinLon() + 360, bbox.GetMaxLat(),
1538 bbox.GetMaxLon() + 360);
1539 cvp.SetBBoxDirect(bbox);
1540 }
else if (bbox.GetMinLon() > cvp.GetBBox().GetMaxLon()) {
1541 bbox.Set(bbox.GetMinLat(), bbox.GetMinLon() - 360, bbox.GetMaxLat(),
1542 bbox.GetMaxLon() - 360);
1543 cvp.SetBBoxDirect(bbox);
1545 cvp.SetBBoxDirect(bbox);
1550void glChartCanvas::DrawStaticRoutesTracksAndWaypoints(
ViewPort &vp) {
1551 if (!m_pParentCanvas->m_bShowNavobjects)
return;
1554 for (
Track* pTrackDraw : g_TrackList) {
1557 if (pActiveTrack && pActiveTrack->IsRunning())
continue;
1559 TrackGui(*pTrackDraw).Draw(m_pParentCanvas, dc, vp, vp.GetBBox());
1562 for (wxRouteListNode *node = pRouteList->GetFirst(); node;
1563 node = node->GetNext()) {
1564 Route *pRouteDraw = node->GetData();
1566 if (!pRouteDraw)
continue;
1569 if (pRouteDraw->IsActive() || pRouteDraw->IsSelected())
continue;
1572 if (pRouteDraw->m_bIsBeingEdited)
continue;
1574 RouteGui(*pRouteDraw).DrawGL(vp, m_pParentCanvas, dc);
1579 if (vp.GetBBox().GetValid() && pWayPointMan) {
1580 for (wxRoutePointListNode *pnode =
1581 pWayPointMan->GetWaypointList()->GetFirst();
1582 pnode; pnode = pnode->GetNext()) {
1584 if (pWP && (!pWP->m_bRPIsBeingEdited) && (!pWP->m_bIsInRoute))
1585 if (vp.GetBBox().ContainsMarge(pWP->m_lat, pWP->m_lon, .5))
1592void glChartCanvas::DrawDynamicRoutesTracksAndWaypoints(
ViewPort &vp) {
1595 for (
Track* pTrackDraw : g_TrackList) {
1597 if (pActiveTrack && pActiveTrack->IsRunning())
1598 TrackGui(*pTrackDraw).Draw(m_pParentCanvas, dc, vp, vp.GetBBox());
1602 for (wxRouteListNode *node = pRouteList->GetFirst(); node;
1603 node = node->GetNext()) {
1604 Route *pRouteDraw = node->GetData();
1607 if (!pRouteDraw)
continue;
1610 if (pRouteDraw->IsActive() || pRouteDraw->IsSelected()) drawit++;
1613 if (pRouteDraw->m_bIsBeingEdited) drawit++;
1616 if (pRouteDraw->IsSelected()) drawit++;
1619 const LLBBox &vp_box = vp.GetBBox(), &test_box = pRouteDraw->GetBBox();
1620 if (!vp_box.IntersectOut(test_box))
1621 RouteGui(*pRouteDraw).DrawGL(vp, m_pParentCanvas, dc);
1627 if (vp.GetBBox().GetValid() && pWayPointMan) {
1628 for (wxRoutePointListNode *pnode =
1629 pWayPointMan->GetWaypointList()->GetFirst();
1630 pnode; pnode = pnode->GetNext()) {
1632 if (pWP && pWP->m_bRPIsBeingEdited && !pWP->m_bIsInRoute)
1639static void GetLatLonCurveDist(
const ViewPort &vp,
float &lat_dist,
1643 switch (vp.m_projection_type) {
1644 case PROJECTION_TRANSVERSE_MERCATOR:
1645 lat_dist = 4, lon_dist = 1;
1647 case PROJECTION_POLYCONIC:
1648 lat_dist = 2, lon_dist = 1;
1650 case PROJECTION_ORTHOGRAPHIC:
1651 lat_dist = 2, lon_dist = 2;
1653 case PROJECTION_POLAR:
1654 lat_dist = 180, lon_dist = 1;
1656 case PROJECTION_STEREOGRAPHIC:
1657 case PROJECTION_GNOMONIC:
1658 lat_dist = 2, lon_dist = 1;
1660 case PROJECTION_EQUIRECTANGULAR:
1663 lat_dist = 2, lon_dist = 360;
1666 lat_dist = 180, lon_dist = 360;
1670void glChartCanvas::RenderChartOutline(
ocpnDC &dc,
int dbIndex,
ViewPort &vp) {
1671 if (ChartData->GetDBChartType(dbIndex) == CHART_TYPE_PLUGIN &&
1672 !ChartData->IsChartAvailable(dbIndex))
1677 ChartData->GetDBBoundingBox(dbIndex, box);
1678 if (!box.GetValid())
return;
1682 if (box.GetLonRange() == 360)
return;
1684 LLBBox vpbox = vp.GetBBox();
1686 double lon_bias = 0;
1688 if (box.IntersectOutGetBias(vp.GetBBox(), lon_bias))
return;
1690 float plylat, plylon;
1694 if (ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93)
1695 color = GetGlobalColor(_T (
"YELO1" ));
1696 else if (ChartData->GetDBChartFamily(dbIndex) == CHART_FAMILY_VECTOR)
1697 color = GetGlobalColor(_T (
"GREEN2" ));
1699 color = GetGlobalColor(_T (
"UINFR" ));
1701#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1702 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
1704 glColor3ub(color.Red(), color.Green(), color.Blue());
1705 glLineWidth(g_GLMinSymbolLineWidth);
1707 float lat_dist, lon_dist;
1708 GetLatLonCurveDist(vp, lat_dist, lon_dist);
1711 int nAuxPlyEntries = ChartData->GetnAuxPlyEntries(dbIndex), nPly;
1715 nPly = ChartData->GetDBAuxPlyPoint(dbIndex, 0, j, 0, 0);
1717 nPly = ChartData->GetDBPlyPoint(dbIndex, 0, &plylat, &plylon);
1719 bool begin =
false, sml_valid =
false;
1721 float lastplylat = 0.0;
1722 float lastplylon = 0.0;
1724 int modulo = (nPly == 0) ? 1 : nPly;
1725 for (
int i = 0; i < nPly + 1; i++) {
1727 ChartData->GetDBAuxPlyPoint(dbIndex, i % modulo, j, &plylat, &plylon);
1729 ChartData->GetDBPlyPoint(dbIndex, i % modulo, &plylat, &plylon);
1733 if (lastplylon - plylon > 180)
1735 else if (lastplylon - plylon < -180)
1742 int lat_splits = floor(fabs(plylat - lastplylat) / lat_dist);
1743 int lon_splits = floor(fabs(plylon - lastplylon) / lon_dist);
1744 splits = wxMax(lat_splits, lon_splits) + 1;
1751 toSM(plylat, plylon, 0, 0, smj + 0, smj + 1);
1752 if (!sml_valid) toSM(lastplylat, lastplylon, 0, 0, sml + 0, sml + 1);
1755 for (
double c = 0; c < splits; c++) {
1757 if (c == splits - 1)
1758 lat = plylat, lon = plylon;
1760 double d = (double)(c + 1) / splits;
1761 fromSM(d * smj[0] + (1 - d) * sml[0], d * smj[1] + (1 - d) * sml[1],
1766 m_pParentCanvas->GetDoubleCanvasPointPix(lat, lon, &s);
1767 if (!std::isnan(s.m_x)) {
1770 glBegin(GL_LINE_STRIP);
1772 glVertex2f(s.m_x, s.m_y);
1778 if ((sml_valid = splits != 1)) memcpy(sml, smj,
sizeof smj);
1779 lastplylat = plylat, lastplylon = plylon;
1784 }
while (++j < nAuxPlyEntries);
1786 glDisable(GL_LINE_SMOOTH);
1790 double nominal_line_width_pix =
1791 wxMax(2.0, floor(m_pParentCanvas->GetPixPerMM() / 4));
1793 if (ChartData->GetDBChartType(dbIndex) == CHART_TYPE_CM93)
1794 dc.SetPen(wxPen(GetGlobalColor(_T (
"YELO1" )), nominal_line_width_pix,
1797 else if (ChartData->GetDBChartFamily(dbIndex) == CHART_FAMILY_VECTOR)
1798 dc.SetPen(wxPen(GetGlobalColor(_T (
"UINFG" )), nominal_line_width_pix,
1802 dc.SetPen(wxPen(GetGlobalColor(_T (
"UINFR" )), nominal_line_width_pix,
1805 float plylat1, plylon1;
1809 int nAuxPlyEntries = ChartData->GetnAuxPlyEntries(dbIndex);
1810 if (0 == nAuxPlyEntries)
1813 std::vector<int> points_vector;
1815 std::vector<float> vec = ChartData->GetReducedPlyPoints(dbIndex);
1816 int nPly = vec.size() / 2;
1818 if (nPly == 0)
return;
1820 for (
int i = 0; i < nPly; i++) {
1821 plylon1 = vec[i * 2];
1822 plylat1 = vec[i * 2 + 1];
1824 m_pParentCanvas->GetCanvasPointPix(plylat1, plylon1, &r1);
1828 points_vector.push_back(pixx1);
1829 points_vector.push_back(pixy1);
1832 ChartData->GetDBPlyPoint(dbIndex, 0, &plylat1, &plylon1);
1833 plylon1 += lon_bias;
1835 m_pParentCanvas->GetCanvasPointPix(vec[1], vec[0], &r1);
1839 points_vector.push_back(pixx1);
1840 points_vector.push_back(pixy1);
1842 if (points_vector.size()) {
1843 std::vector<int>::iterator it = points_vector.begin();
1844 dc.DrawLines(points_vector.size() / 2, (wxPoint *)&(*it), 0, 0,
true);
1852 for (
int j = 0; j < nAuxPlyEntries; j++) {
1853 std::vector<int> points_vector;
1855 std::vector<float> vec = ChartData->GetReducedAuxPlyPoints(dbIndex, j);
1856 int nAuxPly = vec.size() / 2;
1858 if (nAuxPly == 0)
continue;
1860 for (
int i = 0; i < nAuxPly; i++) {
1861 plylon1 = vec[i * 2];
1862 plylat1 = vec[i * 2 + 1];
1864 m_pParentCanvas->GetCanvasPointPix(plylat1, plylon1, &r1);
1868 points_vector.push_back(pixx1);
1869 points_vector.push_back(pixy1);
1872 m_pParentCanvas->GetCanvasPointPix(vec[1], vec[0], &r1);
1876 points_vector.push_back(pixx1);
1877 points_vector.push_back(pixy1);
1879 if (points_vector.size()) {
1880 std::vector<int>::iterator it = points_vector.begin();
1881 dc.DrawLines(points_vector.size() / 2, (wxPoint *)&(*it), 0, 0,
true);
1889extern void CalcGridSpacing(
float WindowDegrees,
float &MajorSpacing,
1890 float &MinorSpacing);
1891extern wxString CalcGridText(
float latlon,
float spacing,
bool bPostfix);
1892void glChartCanvas::GridDraw() {
1893 if (!m_pParentCanvas->m_bDisplayGrid)
return;
1895 ViewPort &vp = m_pParentCanvas->GetVP();
1897 if (!vp.IsValid() || !vp.GetBBox().GetValid())
return;
1901 fabs(vp.rotation) < 0.0001 && vp.m_projection_type == PROJECTION_MERCATOR;
1903 double nlat, elon, slat, wlon;
1905 float gridlatMajor, gridlatMinor, gridlonMajor, gridlonMinor;
1908 wxColour GridColor = GetGlobalColor(_T (
"SNDG1" ));
1910 if (!m_gridfont.IsBuilt()) {
1911 double dpi_factor = g_BasePlatform->GetDisplayDIPMult(
this);
1912 wxFont *dFont = FontMgr::Get().GetFont(_(
"GridText"), 0);
1913 wxFont font = *dFont;
1914 int font_size = wxMax(10, dFont->GetPointSize());
1915 font.SetPointSize(font_size * m_displayScale);
1916 font.SetWeight(wxFONTWEIGHT_NORMAL);
1918 m_gridfont.SetContentScaleFactor(OCPN_GetDisplayContentScaleFactor());
1919 m_gridfont.Build(font, 1, dpi_factor);
1921 m_gridfont.SetColor(GridColor);
1926 LLBBox llbbox = vp.GetBBox();
1927 nlat = llbbox.GetMaxLat();
1928 slat = llbbox.GetMinLat();
1929 elon = llbbox.GetMaxLon();
1930 wlon = llbbox.GetMinLon();
1933 CalcGridSpacing(vp.view_scale_ppm, gridlatMajor, gridlatMinor);
1934 CalcGridSpacing(vp.view_scale_ppm, gridlonMajor, gridlonMinor);
1937 bool straight_latitudes = vp.m_projection_type == PROJECTION_MERCATOR ||
1938 vp.m_projection_type == PROJECTION_WEB_MERCATOR ||
1939 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1940 bool straight_longitudes = vp.m_projection_type == PROJECTION_MERCATOR ||
1941 vp.m_projection_type == PROJECTION_WEB_MERCATOR ||
1942 vp.m_projection_type == PROJECTION_POLAR ||
1943 vp.m_projection_type == PROJECTION_EQUIRECTANGULAR;
1946 if (straight_latitudes)
1949 latmargin = gridlatMajor / 2;
1951 slat = wxMax(slat, -90 + latmargin);
1952 nlat = wxMin(nlat, 90 - latmargin);
1954 float startlat = ceil(slat / gridlatMajor) * gridlatMajor;
1955 float startlon = ceil(wlon / gridlonMajor) * gridlonMajor;
1956 float curved_step = wxMin(sqrt(5e-3 / vp.view_scale_ppm), 3);
1959 wxPen *pen = wxThePenList->FindOrCreatePen(GridColor, g_GLMinSymbolLineWidth,
1966 float lon_step = elon - wlon;
1967 if (!straight_latitudes) lon_step /= ceil(lon_step / curved_step);
1969 for (lat = startlat; lat < nlat; lat += gridlatMajor) {
1970 wxPoint2DDouble r, s;
1973 for (lon = wlon; lon < elon + lon_step / 2; lon += lon_step) {
1974 m_pParentCanvas->GetDoubleCanvasPointPix(lat, lon, &r);
1975 if (!std::isnan(s.m_x) && !std::isnan(r.m_x)) {
1976 gldc.DrawLine(s.m_x, s.m_y, r.m_x, r.m_y,
false);
1984 for (lat = ceil(slat / gridlatMinor) * gridlatMinor; lat < nlat;
1985 lat += gridlatMinor) {
1987 m_pParentCanvas->GetCanvasPointPix(lat, (elon + wlon) / 2, &r);
1988 gldc.DrawLine(0, r.y, 10, r.y,
true);
1989 gldc.DrawLine(w - 10, r.y, w, r.y,
false);
1991 lat = lat + gridlatMinor;
1996 float lat_step = nlat - slat;
1997 if (!straight_longitudes) lat_step /= ceil(lat_step / curved_step);
1999 for (lon = startlon; lon < elon; lon += gridlonMajor) {
2000 wxPoint2DDouble r, s;
2002 for (lat = slat; lat < nlat + lat_step / 2; lat += lat_step) {
2003 m_pParentCanvas->GetDoubleCanvasPointPix(lat, lon, &r);
2005 if (!std::isnan(s.m_x) && !std::isnan(r.m_x)) {
2006 gldc.DrawLine(s.m_x, s.m_y, r.m_x, r.m_y,
false);
2014 for (lon = ceil(wlon / gridlonMinor) * gridlonMinor; lon < elon;
2015 lon += gridlonMinor) {
2017 m_pParentCanvas->GetCanvasPointPix((nlat + slat) / 2, lon, &r);
2018 gldc.DrawLine(r.x, 0, r.x, 10,
false);
2019 gldc.DrawLine(r.x, h - 10, r.x, h,
false);
2024 if( abs(vp.rotation) < .1){
2025 glEnable(GL_TEXTURE_2D);
2027 for (lat = startlat; lat < nlat; lat += gridlatMajor) {
2028 if (fabs(lat - wxRound(lat)) < 1e-5) lat = wxRound(lat);
2031 CalcGridText(lat, gridlatMajor,
true);
2033 m_gridfont.GetTextExtent(st, 0, &iy);
2035 if (straight_latitudes) {
2037 m_pParentCanvas->GetCanvasPointPix(lat, elon, &r);
2038 m_pParentCanvas->GetCanvasPointPix(lat, wlon, &s);
2040 float x = 0, y = -1;
2041 y = (float)(r.y * s.x - s.y * r.x) / (s.x - r.x);
2042 if (y < 0 || y > h) {
2044 x = (float)(r.x * s.y - s.x * r.y + (s.x - r.x) * y) / (s.y - r.y);
2047 m_gridfont.RenderString(st, x, y);
2051 double y1, y2, lat1, lon1, lat2, lon2;
2053 y1 = 0, y2 = vp.pix_height;
2054 double error = vp.pix_width, lasterror;
2057 m_pParentCanvas->GetCanvasPixPoint(0, y1, lat1, lon1);
2058 m_pParentCanvas->GetCanvasPixPoint(0, y2, lat2, lon2);
2060 double y = y1 + (lat1 - lat) * (y2 - y1) / (lat1 - lat2);
2062 m_pParentCanvas->GetDoubleCanvasPointPix(
2063 lat, lon1 + (y1 - y) * (lon2 - lon1) / (y1 - y2), &r);
2065 if (fabs(y - y1) < fabs(y - y2))
2071 error = fabs(r.m_x);
2072 if (--maxiters == 0)
break;
2073 }
while (error > 1 && error < lasterror);
2075 if (error < 1 && r.m_y >= 0 && r.m_y <= vp.pix_height - iy)
2079 m_pParentCanvas->GetDoubleCanvasPointPix(lat, vp.clon, &r);
2081 m_gridfont.RenderString(st, r.m_x, r.m_y);
2085 for (lon = startlon; lon < elon; lon += gridlonMajor) {
2086 if (fabs(lon - wxRound(lon)) < 1e-5) lon = wxRound(lon);
2089 m_pParentCanvas->GetCanvasPointPix(nlat, lon, &r);
2090 m_pParentCanvas->GetCanvasPointPix(slat, lon, &s);
2095 else if (xlon <= -180.0)
2098 wxString st = CalcGridText(xlon, gridlonMajor,
false);
2100 m_gridfont.GetTextExtent(st, &ix, 0);
2102 if (straight_longitudes) {
2103 float x = -1, y = 0;
2104 x = (float)(r.x * s.y - s.x * r.y) / (s.y - r.y);
2105 if (x < 0 || x > w) {
2107 y = (float)(r.y * s.x - s.y * r.x + (s.y - r.y) * x) / (s.x - r.x);
2110 m_gridfont.RenderString(st, x, y);
2114 double x1, x2, lat1, lon1, lat2, lon2;
2116 x1 = 0, x2 = vp.pix_width;
2117 double error = vp.pix_height, lasterror;
2119 m_pParentCanvas->GetCanvasPixPoint(x1, 0, lat1, lon1);
2120 m_pParentCanvas->GetCanvasPixPoint(x2, 0, lat2, lon2);
2122 double x = x1 + (lon1 - lon) * (x2 - x1) / (lon1 - lon2);
2124 m_pParentCanvas->GetDoubleCanvasPointPix(
2125 lat1 + (x1 - x) * (lat2 - lat1) / (x1 - x2), lon, &r);
2127 if (fabs(x - x1) < fabs(x - x2))
2133 error = fabs(r.m_y);
2134 }
while (error > 1 && error < lasterror);
2136 if (error < 1 && r.m_x >= 0 && r.m_x <= vp.pix_width - ix)
2140 m_pParentCanvas->GetDoubleCanvasPointPix(
2141 wxMin(wxMax(vp.clat, slat), nlat), lon, &r);
2143 m_gridfont.RenderString(st, r.m_x, r.m_y);
2147 glDisable(GL_TEXTURE_2D);
2148 glDisable(GL_BLEND);
2153 if (!emboss)
return;
2155 int w = emboss->width, h = emboss->height;
2157 glEnable(GL_TEXTURE_2D);
2160 if (!emboss->gltexind) {
2162 emboss->glwidth = NextPow2(emboss->width);
2163 emboss->glheight = NextPow2(emboss->height);
2166 int size = emboss->glwidth * emboss->glheight;
2167 char *data =
new char[2 * size];
2168 for (
int i = 0; i < h; i++) {
2169 for (
int j = 0; j < emboss->glwidth; j++) {
2171 data[2 * ((i * emboss->glwidth) + j)] =
2172 (char)(emboss->pmap[(i * w) + j] > 0 ? 0 : 255);
2173 data[2 * ((i * emboss->glwidth) + j) + 1] =
2174 (char)abs((emboss->pmap[(i * w) + j]));
2179 glGenTextures(1, &emboss->gltexind);
2180 glBindTexture(GL_TEXTURE_2D, emboss->gltexind);
2181 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, emboss->glwidth,
2182 emboss->glheight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
2184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2190 glBindTexture(GL_TEXTURE_2D, emboss->gltexind);
2194 int x = emboss->x, y = emboss->y;
2196 float wp = (float)w / emboss->glwidth;
2197 float hp = (
float)h / emboss->glheight;
2223 RenderSingleTexture(dc, coords, uv, m_pParentCanvas->GetpVP(), x, y, 0);
2225 glDisable(GL_BLEND);
2226 glDisable(GL_TEXTURE_2D);
2229void glChartCanvas::ShipDraw(
ocpnDC &dc) {
2230 if (!m_pParentCanvas->GetVP().IsValid())
return;
2231 wxPoint lGPSPoint, lShipMidPoint, GPSOffsetPixels(0, 0);
2234 float pCog = std::isnan(gCog) ? 0 : gCog;
2235 float pSog = std::isnan(gSog) ? 0 : gSog;
2237 m_pParentCanvas->GetCanvasPointPix(gLat, gLon, &lGPSPoint);
2238 lShipMidPoint = lGPSPoint;
2242 float icon_hdt = pCog;
2243 if (!std::isnan(gHdt)) icon_hdt = gHdt;
2246 if (std::isnan(icon_hdt)) icon_hdt = 0.0;
2250 double osd_head_lat, osd_head_lon;
2251 wxPoint osd_head_point;
2253 ll_gc_ll(gLat, gLon, icon_hdt, pSog * 10. / 60., &osd_head_lat,
2256 m_pParentCanvas->GetCanvasPointPix(osd_head_lat, osd_head_lon,
2259 float icon_rad = atan2f((
float)(osd_head_point.y - lShipMidPoint.y),
2260 (
float)(osd_head_point.x - lShipMidPoint.x));
2261 icon_rad += (float)PI;
2265 ((icon_hdt + 90.) * PI / 180.) + m_pParentCanvas->GetVP().rotation;
2269 BoundingBox bb_screen(0, 0, m_pParentCanvas->GetVP().pix_width,
2270 m_pParentCanvas->GetVP().pix_height);
2275 if (bb_screen.PointInBox(lShipMidPoint, 20)) {
2276 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
2277 if (g_GLOptions.m_GLPolygonSmoothing) glEnable(GL_POLYGON_SMOOTH);
2279 if (m_pParentCanvas->GetVP().chart_scale >
2282 float scale_factor = 1.0;
2284 if ((g_ChartScaleFactorExp > 1.0) && (g_OwnShipIconType == 0))
2285 scale_factor = (log(g_ChartScaleFactorExp) + 1.0) * 1.1;
2287 float nominal_ownship_size_mm = m_pParentCanvas->m_display_size_mm / 44.0;
2288 nominal_ownship_size_mm = wxMin(nominal_ownship_size_mm, 15.0);
2289 nominal_ownship_size_mm = wxMax(nominal_ownship_size_mm, 7.0);
2291 float nominal_ownship_size_pixels =
2292 wxMax(20.0, m_pParentCanvas->GetPixPerMM() *
2293 nominal_ownship_size_mm);
2295 float v = (nominal_ownship_size_pixels * scale_factor) / 3;
2297 wxPen ppSmallScaleShip;
2298 if (SHIP_NORMAL == m_pParentCanvas->m_ownship_state)
2299 ppSmallScaleShip = wxPen(GetGlobalColor(_T (
"URED" )), v / 5, wxPENSTYLE_SOLID);
2301 ppSmallScaleShip = wxPen(GetGlobalColor(_T (
"YELO1" )), v / 5, wxPENSTYLE_SOLID);
2302 dc.SetPen(ppSmallScaleShip);
2304 dc.SetBrush(wxBrush(GetGlobalColor(_T (
"URED" )), wxBRUSHSTYLE_TRANSPARENT));
2307 dc.DrawLine((-v * 1.2) + lShipMidPoint.x, lShipMidPoint.y,
2308 (v * 1.2) + lShipMidPoint.x, lShipMidPoint.y);
2309 dc.DrawLine(lShipMidPoint.x, (-v * 1.2) + lShipMidPoint.y,
2310 lShipMidPoint.x, (v * 1.2) + lShipMidPoint.y);
2313 dc.StrokeCircle(lShipMidPoint.x, lShipMidPoint.y, v);
2314 dc.StrokeCircle(lShipMidPoint.x, lShipMidPoint.y, 0.6 * v);
2317 int draw_color = SHIP_INVALID;
2318 if (SHIP_NORMAL == m_pParentCanvas->m_ownship_state)
2319 draw_color = SHIP_NORMAL;
2320 else if (SHIP_LOWACCURACY == m_pParentCanvas->m_ownship_state)
2321 draw_color = SHIP_LOWACCURACY;
2329 ownship_color = draw_color;
2331 if (ownship_tex) glDeleteTextures(1, &ownship_tex);
2333 glGenTextures(1, &ownship_tex);
2334 glBindTexture(GL_TEXTURE_2D, ownship_tex);
2336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2340 if (m_pParentCanvas->m_pos_image_user) {
2341 switch (draw_color) {
2343 image = *m_pParentCanvas->m_pos_image_user_grey;
2346 image = *m_pParentCanvas->m_pos_image_user;
2348 case SHIP_LOWACCURACY:
2349 image = *m_pParentCanvas->m_pos_image_user_yellow;
2353 switch (draw_color) {
2355 image = *m_pParentCanvas->m_pos_image_grey;
2358 image = *m_pParentCanvas->m_pos_image_red;
2360 case SHIP_LOWACCURACY:
2361 image = *m_pParentCanvas->m_pos_image_yellow;
2366 int w = image.GetWidth(), h = image.GetHeight();
2367 int glw = NextPow2(w), glh = NextPow2(h);
2368 ownship_size = wxSize(w, h);
2369 ownship_tex_size = wxSize(glw, glh);
2371 unsigned char *d = image.GetData();
2372 unsigned char *a = image.GetAlpha();
2373 unsigned char *e =
new unsigned char[4 * w * h];
2376 for (
int p = 0; p < w * h; p++) {
2377 e[4 * p + 0] = d[3 * p + 0];
2378 e[4 * p + 1] = d[3 * p + 1];
2379 e[4 * p + 2] = d[3 * p + 2];
2380 e[4 * p + 3] = a[p];
2383 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glw, glh, 0, GL_RGBA,
2384 GL_UNSIGNED_BYTE, 0);
2386 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
2392#ifndef USE_ANDROID_GLES2
2393 if (m_pParentCanvas->m_pos_image_user)
2394 glColor4ub(255, 255, 255, 255);
2395 else if (SHIP_NORMAL == m_pParentCanvas->m_ownship_state)
2396 glColor4ub(255, 0, 0, 255);
2397 else if (SHIP_LOWACCURACY == m_pParentCanvas->m_ownship_state)
2398 glColor4ub(255, 255, 0, 255);
2400 glColor4ub(128, 128, 128, 255);
2402 float scale_factor_y = 1.0;
2403 float scale_factor_x = 1.0;
2405 int ownShipWidth = 22;
2406 int ownShipLength = 84;
2407 lShipMidPoint = lGPSPoint;
2410 if (g_OwnShipIconType != 0)
2411 m_pParentCanvas->ComputeShipScaleFactor(
2412 icon_hdt, ownShipWidth, ownShipLength, lShipMidPoint,
2413 GPSOffsetPixels, lGPSPoint, scale_factor_x, scale_factor_y);
2417 int x = lShipMidPoint.x, y = lShipMidPoint.y;
2420 if ((g_ShipScaleFactorExp > 1.0) && (g_OwnShipIconType == 0)) {
2421 scale_factor_x = (log(g_ShipScaleFactorExp) + 1.0) * 1.1;
2422 scale_factor_y = (log(g_ShipScaleFactorExp) + 1.0) * 1.1;
2427 float gps_circle_radius = 3.0;
2429 if (g_OwnShipIconType == 0) {
2431 glEnable(GL_TEXTURE_2D);
2432 glBindTexture(GL_TEXTURE_2D, ownship_tex);
2441 int image_height_bitmap = m_pParentCanvas->m_pos_image_red->GetHeight();
2442 if (m_pParentCanvas->m_pos_image_user)
2443 image_height_bitmap = m_pParentCanvas->m_pos_image_user->GetHeight();
2445 float nominal_ownship_size_mm =
2446 image_height_bitmap / m_pParentCanvas->GetPixPerMM();
2448 nominal_ownship_size_mm = wxMin(nominal_ownship_size_mm, 15.0);
2449 nominal_ownship_size_mm = wxMax(nominal_ownship_size_mm, 7.0);
2451 float nominal_ownship_size_pixels =
2452 wxMax(20.0, m_pParentCanvas->GetPixPerMM() *
2453 nominal_ownship_size_mm);
2455 float h = nominal_ownship_size_pixels * scale_factor_y;
2456 float w = nominal_ownship_size_pixels * scale_factor_x *
2457 ownship_size.x / ownship_size.y;
2458 float glw = ownship_tex_size.x, glh = ownship_tex_size.y;
2459 float u = ownship_size.x / glw, v = ownship_size.y / glh;
2465 gps_circle_radius = w / 5;
2467 float uv[8], coords[8];
2486 RenderSingleTexture(dc, coords, uv, m_pParentCanvas->GetpVP(), x, y,
2489 glDisable(GL_TEXTURE_2D);
2490 }
else if (g_OwnShipIconType == 1) {
2492 glEnable(GL_TEXTURE_2D);
2493 glBindTexture(GL_TEXTURE_2D, ownship_tex);
2495 float nominal_ownship_size_pixels_y = 84;
2496 float nominal_ownship_size_pixels_x = 22;
2498 float h = nominal_ownship_size_pixels_y * scale_factor_y;
2499 float w = nominal_ownship_size_pixels_x * scale_factor_x;
2501 float u = (float)ownship_size.x / ownship_tex_size.x,
2502 v = (
float)ownship_size.y / ownship_tex_size.y;
2505 gps_circle_radius = w / 5;
2507 float uv[8], coords[8];
2526 RenderSingleTexture(dc, coords, uv, m_pParentCanvas->GetpVP(), x, y,
2529 glDisable(GL_TEXTURE_2D);
2530 }
else if (g_OwnShipIconType == 2) {
2538 wxPoint shipPoints[6];
2540 wxColour colour = m_pParentCanvas->ShipColor();
2541 wxPen ppPen(*wxBLACK, 1);
2542 wxBrush ppBrush(colour);
2544 dc.SetBrush(ppBrush);
2546 shipPoints[0].x = 0 * scale_factor_x;
2547 shipPoints[0].y = -28 * scale_factor_y;
2548 shipPoints[1].x = 11 * scale_factor_x;
2549 shipPoints[1].y = -28 * scale_factor_y;
2550 shipPoints[2].x = 11 * scale_factor_x;
2551 shipPoints[2].y = 42 * scale_factor_y;
2552 shipPoints[3].x = 0 * scale_factor_x;
2553 shipPoints[3].y = 42 * scale_factor_y;
2554 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2557 shipPoints[0].x = 0 * scale_factor_x;
2558 shipPoints[0].y = -42 * scale_factor_y;
2559 shipPoints[1].x = 5 * scale_factor_x;
2560 shipPoints[1].y = -42 * scale_factor_y;
2561 shipPoints[2].x = 11 * scale_factor_x;
2562 shipPoints[2].y = -28 * scale_factor_y;
2563 shipPoints[3].x = 0 * scale_factor_x;
2564 shipPoints[3].y = -28 * scale_factor_y;
2565 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2568 shipPoints[0].x = 0 * scale_factor_x;
2569 shipPoints[0].y = -28 * scale_factor_y;
2570 shipPoints[1].x = -11 * scale_factor_x;
2571 shipPoints[1].y = -28 * scale_factor_y;
2572 shipPoints[2].x = -11 * scale_factor_x;
2573 shipPoints[2].y = 42 * scale_factor_y;
2574 shipPoints[3].x = 0 * scale_factor_x;
2575 shipPoints[3].y = 42 * scale_factor_y;
2576 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2579 shipPoints[0].x = 0 * scale_factor_x;
2580 shipPoints[0].y = -42 * scale_factor_y;
2581 shipPoints[1].x = -5 * scale_factor_x;
2582 shipPoints[1].y = -42 * scale_factor_y;
2583 shipPoints[2].x = -11 * scale_factor_x;
2584 shipPoints[2].y = -28 * scale_factor_y;
2585 shipPoints[3].x = 0 * scale_factor_x;
2586 shipPoints[3].y = -28 * scale_factor_y;
2587 dc.DrawPolygon(4, shipPoints, lShipMidPoint.x, lShipMidPoint.y, 1,
2591 double p1x = -11 * scale_factor_x;
2592 double p2x = 11 * scale_factor_x;
2596 ((p1x)*cos(icon_rad - PI / 2)) - ((p1y)*sin(icon_rad - PI / 2));
2598 ((p2x)*cos(icon_rad - PI / 2)) - ((p2y)*sin(icon_rad - PI / 2));
2600 ((p1y)*cos(icon_rad - PI / 2)) + ((p1x)*sin(icon_rad - PI / 2));
2602 ((p2y)*cos(icon_rad - PI / 2)) + ((p2x)*sin(icon_rad - PI / 2));
2603 dc.DrawLine(p1xr + lShipMidPoint.x, p1yr + lShipMidPoint.y,
2604 p2xr + lShipMidPoint.x, p2yr + lShipMidPoint.y);
2608 p1y = -42 * scale_factor_y;
2609 p2y = 42 * scale_factor_y;
2610 p1xr = ((p1x)*cos(icon_rad - PI / 2)) - ((p1y)*sin(icon_rad - PI / 2));
2611 p2xr = ((p2x)*cos(icon_rad - PI / 2)) - ((p2y)*sin(icon_rad - PI / 2));
2612 p1yr = ((p1y)*cos(icon_rad - PI / 2)) + ((p1x)*sin(icon_rad - PI / 2));
2613 p2yr = ((p2y)*cos(icon_rad - PI / 2)) + ((p2x)*sin(icon_rad - PI / 2));
2614 dc.DrawLine(p1xr + lShipMidPoint.x, p1yr + lShipMidPoint.y,
2615 p2xr + lShipMidPoint.x, p2yr + lShipMidPoint.y);
2618 img_height = ownShipLength * scale_factor_y;
2621 if (m_pParentCanvas->m_pos_image_user) gps_circle_radius = 1;
2623 float cx = lGPSPoint.x, cy = lGPSPoint.y;
2624 wxPen ppPen1(GetGlobalColor(_T (
"UBLCK" )), 1, wxPENSTYLE_SOLID);
2626 dc.SetBrush(wxBrush(GetGlobalColor(_T (
"CHWHT" ))));
2628 dc.StrokeCircle(cx, cy, gps_circle_radius);
2632 glDisable(GL_LINE_SMOOTH);
2633 glDisable(GL_POLYGON_SMOOTH);
2634 glDisable(GL_BLEND);
2637 m_pParentCanvas->ShipIndicatorsDraw(dc, img_height, GPSOffsetPixels,
2641void glChartCanvas::DrawFloatingOverlayObjects(
ocpnDC &dc) {
2642 ViewPort &vp = m_pParentCanvas->GetVP();
2647 Route *active_route = g_pRouteMan->GetpActiveRoute();
2656 g_overlayCanvas = m_pParentCanvas;
2658 g_pi_manager->SendViewPortToRequestingPlugIns(vp);
2659 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
2660 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_LEGACY);
2665 AISDrawAreaNotices(dc, m_pParentCanvas->GetVP(), m_pParentCanvas);
2667 m_pParentCanvas->DrawAnchorWatchPoints(dc);
2668 AISDraw(dc, m_pParentCanvas->GetVP(), m_pParentCanvas);
2670 m_pParentCanvas->AlertDraw(dc);
2672 m_pParentCanvas->RenderVisibleSectorLights(dc);
2674 m_pParentCanvas->RenderRouteLegs(dc);
2675 m_pParentCanvas->RenderShipToActive(dc,
true);
2676 m_pParentCanvas->ScaleBarDraw(dc);
2677 s57_DrawExtendedLightSectorsGL(dc, m_pParentCanvas->VPoint,
2678 m_pParentCanvas->extendedSectorLegs);
2680 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
2681 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_OVER_SHIPS);
2685void glChartCanvas::DrawChartBar(
ocpnDC &dc) {
2686 if (m_pParentCanvas->GetPiano()){
2688 int canvas_height = GetClientSize().y;
2689 canvas_height *= m_displayScale;
2691 m_pParentCanvas->GetPiano()->DrawGL(
2693 m_pParentCanvas->GetPiano()->GetHeight());
2697void glChartCanvas::DrawQuiting() {
2698#ifndef USE_ANDROID_GLES2
2699 GLubyte pattern[8][8];
2700 for (
int y = 0; y < 8; y++)
2701 for (
int x = 0; x < 8; x++) pattern[y][x] = (y == x) * 255;
2704 glEnable(GL_TEXTURE_2D);
2705 glBindTexture(GL_TEXTURE_2D, 0);
2707 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2711 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 8, 8, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
2715 float x = GetSize().x, y = GetSize().y;
2716 float u = x / 8, v = y / 8;
2729 glDisable(GL_TEXTURE_2D);
2730 glDisable(GL_BLEND);
2734void glChartCanvas::DrawCloseMessage(wxString msg) {
2735#ifndef USE_ANDROID_GLES2
2738 wxFont *pfont = FontMgr::Get().FindOrCreateFont(
2739 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
2743 texfont.Build(*pfont, 1, 1);
2745 texfont.GetTextExtent(msg, &w, &h);
2747 int yp = m_pParentCanvas->GetVP().pix_height / 2;
2748 int xp = (m_pParentCanvas->GetVP().pix_width - w) / 2;
2750 glColor3ub(243, 229, 47);
2754 glVertex2i(xp + w, yp);
2755 glVertex2i(xp + w, yp + h);
2756 glVertex2i(xp, yp + h);
2761 glColor3ub(0, 0, 0);
2762 glEnable(GL_TEXTURE_2D);
2763 texfont.RenderString(msg, xp, yp);
2764 glDisable(GL_TEXTURE_2D);
2765 glDisable(GL_BLEND);
2772static std::list<double *> combine_work_data;
2773static void combineCallbackD(GLdouble coords[3], GLdouble *vertex_data[4],
2774 GLfloat weight[4], GLdouble **dataOut) {
2775 double *vertex =
new double[3];
2776 combine_work_data.push_back(vertex);
2777 memcpy(vertex, coords, 3 * (
sizeof *coords));
2781#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
2782void vertexCallbackD_GLSL(GLvoid *vertex) {
2784 if (s_tess_vertex_idx > s_tess_buf_len - 8) {
2785 int new_buf_len = s_tess_buf_len + 100;
2786 GLfloat *tmp = s_tess_work_buf;
2789 (GLfloat *)realloc(s_tess_work_buf, new_buf_len *
sizeof(GLfloat));
2790 if (NULL == s_tess_work_buf) {
2794 s_tess_buf_len = new_buf_len;
2797 GLdouble *pointer = (GLdouble *)vertex;
2799 s_tess_work_buf[s_tess_vertex_idx++] = (float)pointer[0];
2800 s_tess_work_buf[s_tess_vertex_idx++] = (float)pointer[1];
2805void beginCallbackD_GLSL(GLenum mode) {
2806 s_tess_vertex_idx_this = s_tess_vertex_idx;
2811void endCallbackD_GLSL() {
2815 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)s_tessVP.vp_matrix_transform);
2817 mat4x4 identityMatrix;
2818 mat4x4_identity(identityMatrix);
2819 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)identityMatrix);
2823 colorv[0] = s_regionColor.Red() / float(256);
2824 colorv[1] = s_regionColor.Green() / float(256);
2825 colorv[2] = s_regionColor.Blue() / float(256);
2826 colorv[3] = s_regionColor.Alpha() / float(256);
2827 shader->SetUniform4fv(
"color", colorv);
2829 float *bufPt = &s_tess_work_buf[s_tess_vertex_idx_this];
2830 shader->SetAttributePointerf(
"position", bufPt);
2832 glDrawArrays(s_tess_mode, 0, s_nvertex);
2838void vertexCallbackD(GLvoid *vertex)
2840 glVertex3dv( (GLdouble *)vertex);
2843void beginCallbackD( GLenum mode)
2855void glChartCanvas::DrawRegion(
ViewPort &vp,
const LLRegion ®ion) {
2856 float lat_dist, lon_dist;
2857 GetLatLonCurveDist(vp, lat_dist, lon_dist);
2859 GLUtesselator *tobj = gluNewTess();
2861 pStaticShader = GetStaticTriShader();
2864#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
2865 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&vertexCallbackD_GLSL);
2866 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&beginCallbackD_GLSL);
2867 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&endCallbackD_GLSL);
2868 gluTessCallback(tobj, GLU_TESS_COMBINE, (_GLUfuncptr)&combineCallbackD);
2872 gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&vertexCallbackD);
2873 gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr)&beginCallbackD);
2874 gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr)&endCallbackD);
2875 gluTessCallback(tobj, GLU_TESS_COMBINE, (_GLUfuncptr)&combineCallbackD);
2878 gluTessNormal(tobj, 0, 0, 1);
2880 gluTessBeginPolygon(tobj, NULL);
2881 for (std::list<poly_contour>::const_iterator i = region.contours.begin();
2882 i != region.contours.end(); i++) {
2883 gluTessBeginContour(tobj);
2884 contour_pt l = *i->rbegin();
2886 bool sml_valid =
false;
2887 for (poly_contour::const_iterator j = i->begin(); j != i->end(); j++) {
2888 int lat_splits = floor(fabs(j->y - l.y) / lat_dist);
2889 int lon_splits = floor(fabs(j->x - l.x) / lon_dist);
2890 int splits = wxMax(lat_splits, lon_splits) + 1;
2896 toSM(j->y, j->x, 0, 0, smj + 0, smj + 1);
2897 if (!sml_valid) toSM(l.y, l.x, 0, 0, sml + 0, sml + 1);
2900 for (
int i = 0; i < splits; i++) {
2902 if (i == splits - 1)
2903 lat = j->y, lon = j->x;
2905 double d = (double)(i + 1) / splits;
2906 fromSM(d * smj[0] + (1 - d) * sml[0], d * smj[1] + (1 - d) * sml[1],
2909 wxPoint2DDouble q = vp.GetDoublePixFromLL(lat, lon);
2910 if (std::isnan(q.m_x))
continue;
2912 double *p =
new double[6];
2917 p[0] = wxRound(q.m_x), p[1] = wxRound(q.m_y), p[2] = 0;
2922 gluTessVertex(tobj, p, p);
2923 combine_work_data.push_back(p);
2927 if ((sml_valid = splits != 1)) memcpy(sml, smj,
sizeof smj);
2929 gluTessEndContour(tobj);
2931 gluTessEndPolygon(tobj);
2933 gluDeleteTess(tobj);
2935 for (std::list<double *>::iterator i = combine_work_data.begin();
2936 i != combine_work_data.end(); i++)
2938 combine_work_data.clear();
2943void glChartCanvas::SetClipRegion(
ViewPort &vp,
const LLRegion ®ion) {
2944 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2946 if (s_b_useStencil) {
2948 glEnable(GL_STENCIL_TEST);
2950 glClear(GL_STENCIL_BUFFER_BIT);
2954 glStencilFunc(GL_ALWAYS, 1, 1);
2955 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
2958#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
2962 glEnable(GL_DEPTH_TEST);
2963 glDepthFunc(GL_ALWAYS);
2964 glDepthMask(GL_TRUE);
2966 glClear(GL_DEPTH_BUFFER_BIT);
2979 glTranslatef(0, 0, .5);
2983 s_regionColor = wxColor(0,0,0,255);
2984 DrawRegion(vp, region);
2986 if (s_b_useStencil) {
2989 glStencilFunc(GL_EQUAL, 1, 1);
2990 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2993#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
2995 glDepthFunc(GL_GREATER);
2996 glDepthMask(GL_FALSE);
2997 glTranslatef(0, 0, -.5);
3000 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3003void glChartCanvas::SetClipRect(
const ViewPort &vp,
const wxRect &rect,
3007 if (s_b_useStencil && s_b_useScissorTest) {
3008 wxRect vp_rect(0, 0, vp.pix_width, vp.pix_height);
3009 if (rect != vp_rect) {
3010 glEnable(GL_SCISSOR_TEST);
3011 glScissor(rect.x, vp.pix_height - rect.height - rect.y, rect.width,
3014#ifndef USE_ANDROID_GLES2
3020void glChartCanvas::DisableClipRegion() {
3021 glDisable(GL_SCISSOR_TEST);
3022 glDisable(GL_STENCIL_TEST);
3023 glDisable(GL_DEPTH_TEST);
3026void glChartCanvas::Invalidate() {
3028 m_cache_vp.Invalidate();
3034 if (!pBSBChart)
return;
3036 if (b_inCompressAllCharts)
3040 wxString key = chart->GetHashKey();
3043 ChartPathHashTexfactType &hash = g_glTextureManager->m_chart_texfactory_hash;
3044 ChartPathHashTexfactType::iterator ittf = hash.find(key);
3047 if (ittf == hash.end()) {
3049 hash[key]->SetHashKey(key);
3052 pTexFact = hash[key];
3053 pTexFact->SetLRUTime(++m_LRUtime);
3058 glChartCanvas::HasNormalizedViewPort(vp) && pBSBChart->GetPPM() < 1;
3059 pTexFact->PrepareTiles(vp, use_norm_vp, pBSBChart);
3066 if (vp.m_projection_type == PROJECTION_MERCATOR &&
3067 chart->GetChartProjectionType() == PROJECTION_MERCATOR) {
3068 double scalefactor = pBSBChart->GetRasterScaleFactor(vp);
3069 base_level = log(scalefactor) / log(2.0);
3073 if (base_level > g_mipmap_max_level) base_level = g_mipmap_max_level;
3078 glEnable(GL_TEXTURE_2D);
3079#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3080 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3082 glEnableClientState(GL_VERTEX_ARRAY);
3083 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3088 pTexFact->GetCenter(lat, lon);
3089 MultMatrixViewPort(vp, lat, lon);
3093 LLBBox box = region.GetBox();
3096 if (g_memCacheLimit > 0) {
3098 GetMemoryStatus(0, &mem_used);
3101 glTexTile **tiles = pTexFact->GetTiles(numtiles);
3102 for (
int i = 0; i < numtiles; i++) {
3104 if (region.IntersectOut(tile->box)) {
3107 g_tex_mem_used > g_GLOptions.m_iTextureMemorySize * 1024 * 1024;
3108 if (bGLMemCrunch) pTexFact->DeleteTexture(tile->rect);
3110 bool texture = pTexFact->PrepareTexture(base_level, tile->rect,
3111 global_color_scheme, mem_used);
3115 coords = tile->m_coords;
3117 coords =
new float[2 * tile->m_ncoords];
3118 for (
int i = 0; i < tile->m_ncoords; i++) {
3119 wxPoint2DDouble p = vp.GetDoublePixFromLL(tile->m_coords[2 * i + 0],
3120 tile->m_coords[2 * i + 1]);
3121 coords[2 * i + 0] = p.m_x;
3122 coords[2 * i + 1] = p.m_y;
3126#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
3127 RenderTextures(m_gldc, coords, tile->m_texcoords, 4, m_pParentCanvas->GetpVP());
3130 glDisable(GL_TEXTURE_2D);
3134 glTexCoordPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), tile->m_texcoords);
3135 glVertexPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), coords);
3136 glDrawArrays(GL_QUADS, 0, tile->m_ncoords);
3138 if (!texture) glEnable(GL_TEXTURE_2D);
3140 if (!use_norm_vp)
delete[] coords;
3144 glDisable(GL_TEXTURE_2D);
3146#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3147 if (use_norm_vp) glPopMatrix();
3149 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3150 glDisableClientState(GL_VERTEX_ARRAY);
3154void glChartCanvas::RenderQuiltViewGL(
ViewPort &vp,
3156 if (!m_pParentCanvas->m_pQuilt->GetnCharts() ||
3157 m_pParentCanvas->m_pQuilt->IsBusy())
3161 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetFirstChart();
3170 LLRegion region = vp.GetLLRegion(rect_region);
3172 LLRegion rendered_region;
3178 if (chart->GetChartFamily() != CHART_FAMILY_RASTER) {
3186 QuiltPatch *pqp = m_pParentCanvas->m_pQuilt->GetCurrentPatch();
3188 LLRegion get_region = pqp->ActiveRegion;
3189 bool b_rendered =
false;
3191 if (!pqp->b_overlay) {
3192 get_region.Intersect(region);
3193 if (!get_region.Empty()) {
3194 if (chart->GetChartFamily() == CHART_FAMILY_RASTER) {
3196 if (Patch_Ch_BSB ) {
3198 SetClipRegion(vp, get_region );
3199 RenderRasterChartRegionGL(chart, vp, pqp->ActiveRegion);
3200 DisableClipRegion();
3203 }
else if (chart->GetChartType() == CHART_TYPE_MBTILES) {
3204 SetClipRegion(vp, pqp->ActiveRegion );
3205 chart->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3207 DisableClipRegion();
3210 }
else if (chart->GetChartFamily() == CHART_FAMILY_VECTOR) {
3211 if (chart->GetChartType() == CHART_TYPE_CM93COMP) {
3212 RenderNoDTA(vp, get_region);
3213 chart->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3218 if (Chs57->m_RAZBuilt) {
3219 RenderNoDTA(vp, get_region);
3220 Chs57->RenderRegionViewOnGLNoText(*m_pcontext, vp,
3221 rect_region, get_region);
3222 DisableClipRegion();
3227 const LLRegion &oregion = get_region;
3228 LLBBox box = oregion.GetBox();
3231 vp.GetPixFromLL(box.GetMaxLat(), box.GetMinLon());
3233 vp.GetPixFromLL(box.GetMaxLat(), box.GetMaxLon());
3235 vp.GetPixFromLL(box.GetMinLat(), box.GetMaxLon());
3237 vp.GetPixFromLL(box.GetMinLat(), box.GetMinLon());
3239 wxRect srect(p1.x, p1.y, p3.x - p1.x, p4.y - p2.y);
3242 ViewPort cvp = ClippedViewport(vp, get_region);
3243 if (m_pParentCanvas->GetWorldBackgroundChart()) {
3244 SetClipRegion(cvp, get_region);
3245 m_pParentCanvas->GetWorldBackgroundChart()->SetColorsDirect(
3246 GetGlobalColor(_T (
"LANDA" )),
3247 GetGlobalColor(_T (
"DEPMS" )));
3248 RenderWorldChart(gldc, cvp, srect, world);
3249 m_pParentCanvas->GetWorldBackgroundChart()->SetColorScheme(
3250 global_color_scheme);
3251 DisableClipRegion();
3258 RenderNoDTA(vp, get_region);
3259 ChPI->RenderRegionViewOnGLNoText(*m_pcontext, vp, rect_region,
3262 RenderNoDTA(vp, get_region);
3263 chart->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3280 chart = m_pParentCanvas->m_pQuilt->GetNextChart();
3284 if (m_pParentCanvas->m_pQuilt->HasOverlays()) {
3285 ChartBase *pch = m_pParentCanvas->m_pQuilt->GetFirstChart();
3287 QuiltPatch *pqp = m_pParentCanvas->m_pQuilt->GetCurrentPatch();
3288 if (pqp->b_Valid && pqp->b_overlay &&
3289 pch->GetChartFamily() == CHART_FAMILY_VECTOR) {
3290 LLRegion get_region = pqp->ActiveRegion;
3292 get_region.Intersect(region);
3293 if (!get_region.Empty()) {
3296 Chs57->RenderOverlayRegionViewOnGL(*m_pcontext, vp, rect_region,
3301 ChPI->RenderRegionViewOnGL(*m_pcontext, vp, rect_region,
3308 pch = m_pParentCanvas->m_pQuilt->GetNextChart();
3313 LLRegion hiregion = m_pParentCanvas->m_pQuilt->GetHiliteRegion();
3315 if (!hiregion.Empty()) {
3319 switch (global_color_scheme) {
3320 case GLOBAL_COLOR_SCHEME_DAY:
3323 case GLOBAL_COLOR_SCHEME_DUSK:
3326 case GLOBAL_COLOR_SCHEME_NIGHT:
3335#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3337 glColor4f((
float).8, (
float).4, (
float).4, (
float)hitrans);
3339 s_regionColor = wxColor(204, 102, 102, hitrans * 256);
3342 DrawRegion(vp, hiregion);
3344 glDisable(GL_BLEND);
3346 m_pParentCanvas->m_pQuilt->SetRenderedVP(vp);
3349void glChartCanvas::RenderQuiltViewGLText(
ViewPort &vp,
3351 if (!m_pParentCanvas->m_pQuilt->GetnCharts() ||
3352 m_pParentCanvas->m_pQuilt->IsBusy())
3356 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetLargestScaleChart();
3358 LLRegion region = vp.GetLLRegion(rect_region);
3360 LLRegion rendered_region;
3362 QuiltPatch *pqp = m_pParentCanvas->m_pQuilt->GetCurrentPatch();
3364 LLRegion get_region = pqp->ActiveRegion;
3366 if (!pqp->b_overlay) {
3367 if (chart->GetChartFamily() == CHART_FAMILY_VECTOR) {
3370 Chs57->RenderViewOnGLTextOnly(*m_pcontext, vp);
3375 ChPI->RenderRegionViewOnGLTextOnly(*m_pcontext, vp, rect_region);
3382 chart = m_pParentCanvas->m_pQuilt->GetNextSmallerScaleChart();
3410void glChartCanvas::RenderCharts(
ocpnDC &dc,
const OCPNRegion &rect_region) {
3411 ViewPort &vp = m_pParentCanvas->VPoint;
3419 m_pParentCanvas->m_singleChart->GetChartType() == CHART_TYPE_CM93COMP)
3420 static_cast<cm93compchart *
>(m_pParentCanvas->m_singleChart)
3423 LLRegion chart_region;
3425 (m_pParentCanvas->m_singleChart->GetChartType() == CHART_TYPE_PLUGIN)) {
3426 if (m_pParentCanvas->m_singleChart->GetChartFamily() ==
3427 CHART_FAMILY_RASTER) {
3435 cpw->chartpix_to_latlong(0, 0, ll + 0, ll + 1);
3436 cpw->chartpix_to_latlong(0, cpw->GetSize_Y(), ll + 2, ll + 3);
3437 cpw->chartpix_to_latlong(cpw->GetSize_X(), cpw->GetSize_Y(), ll + 4,
3439 cpw->chartpix_to_latlong(cpw->GetSize_X(), 0, ll + 6, ll + 7);
3443 for (
int i = 1; i < 6; i += 2)
3444 if (fabs(ll[i] - ll[i + 2]) > 180) {
3446 for (
int i = 1; i < 8; i += 2)
3447 if (ll[i] < 0) ll[i] += 360;
3451 chart_region = LLRegion(4, ll);
3454 m_pParentCanvas->m_singleChart->GetChartExtent(&ext);
3456 double ll[8] = {ext.SLAT, ext.WLON, ext.SLAT, ext.ELON,
3457 ext.NLAT, ext.ELON, ext.NLAT, ext.WLON};
3458 chart_region = LLRegion(4, ll);
3461 chart_region = vp.b_quilt
3462 ? m_pParentCanvas->m_pQuilt->GetFullQuiltRegion()
3463 : m_pParentCanvas->m_singleChart->GetValidRegion();
3465 bool world_view =
false;
3467 wxRect rect = upd.GetRect();
3468 LLRegion background_region = vp.GetLLRegion(rect);
3471 background_region.Subtract(chart_region);
3473 if (!background_region.Empty()) {
3474 ViewPort cvp = ClippedViewport(vp, background_region);
3475 RenderWorldChart(dc, cvp, rect, world_view);
3480 RenderQuiltViewGL(vp, rect_region);
3482 LLRegion region = vp.GetLLRegion(rect_region);
3483 if (m_pParentCanvas->m_singleChart->GetChartFamily() ==
3484 CHART_FAMILY_RASTER) {
3485 if (m_pParentCanvas->m_singleChart->GetChartType() == CHART_TYPE_MBTILES)
3486 m_pParentCanvas->m_singleChart->RenderRegionViewOnGL(
3487 *m_pcontext, vp, rect_region, region);
3489 RenderRasterChartRegionGL(m_pParentCanvas->m_singleChart, vp, region);
3490 }
else if (m_pParentCanvas->m_singleChart->GetChartFamily() ==
3491 CHART_FAMILY_VECTOR) {
3492 chart_region.Intersect(region);
3493 RenderNoDTA(vp, chart_region);
3494 m_pParentCanvas->m_singleChart->RenderRegionViewOnGL(*m_pcontext, vp,
3495 rect_region, region);
3501void glChartCanvas::RenderNoDTA(
ViewPort &vp,
const LLRegion ®ion,
3503 wxColour color = GetGlobalColor(_T (
"NODTA" ));
3504#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3506 glColor4ub(color.Red(), color.Green(), color.Blue(), transparency);
3508 glColor4ub(163, 180, 183, transparency);
3511 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3515 s_regionColor = color;
3518 DrawRegion(vp, region);
3523void glChartCanvas::RenderWorldChart(
ocpnDC &dc,
ViewPort &vp, wxRect &rect,
3526 wxColour water = m_pParentCanvas->pWorldBackgroundChart->water;
3528 glEnable(GL_SCISSOR_TEST);
3529 glScissor(rect.x, vp.pix_height - rect.height - rect.y, rect.width,
3535 int x1 = rect.x, y1 = rect.y, x2 = x1 + rect.width, y2 = y1 + rect.height;
3536#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
3538 GLShaderProgram *shader = pcolor_tri_shader_program[GetCanvasIndex()];
3542 colorv[0] = water.Red() / float(256);
3543 colorv[1] = water.Green() / float(256);
3544 colorv[2] = water.Blue() / float(256);
3546 shader->SetUniform4fv(
"color", colorv);
3557 shader->SetAttributePointerf(
"position", pf);
3559 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3568 m_pParentCanvas->pWorldBackgroundChart->RenderViewOnDC(dc, vp);
3570 glDisable(GL_SCISSOR_TEST);
3579void glChartCanvas::DrawGroundedOverlayObjects(
ocpnDC &dc,
ViewPort &vp) {
3580 m_pParentCanvas->RenderAllChartOutlines(dc, vp);
3582 DrawStaticRoutesTracksAndWaypoints(vp);
3584 DisableClipRegion();
3587void glChartCanvas::DrawGLTidesInBBox(
ocpnDC &dc, LLBBox &BBox) {
3589 if (m_pParentCanvas->GetVP().chart_scale > 500000) {
3593 wxBitmap bmp = m_pParentCanvas->GetTideBitmap();
3594 if (!bmp.Ok())
return;
3596 wxImage image = bmp.ConvertToImage();
3597 int w = image.GetWidth(), h = image.GetHeight();
3600 if (g_texture_rectangle_format == GL_TEXTURE_2D)
3601 tex_w = w, tex_h = h;
3603 tex_w = NextPow2(w), tex_h = NextPow2(h);
3605 m_tideTexWidth = tex_w;
3606 m_tideTexHeight = tex_h;
3608 unsigned char *d = image.GetData();
3609 unsigned char *a = image.GetAlpha();
3611 unsigned char mr, mg, mb;
3612 if (!a) image.GetOrFindMaskColour(&mr, &mg, &mb);
3614 unsigned char *e =
new unsigned char[4 * w * h];
3616 for (
int y = 0; y < h; y++)
3617 for (
int x = 0; x < w; x++) {
3618 unsigned char r, g, b;
3619 int off = (y * w + x);
3629 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
3633 glGenTextures(1, &m_tideTex);
3635 glBindTexture(GL_TEXTURE_2D, m_tideTex);
3636 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3637 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3639 if (g_texture_rectangle_format == GL_TEXTURE_2D)
3640 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
3641 GL_UNSIGNED_BYTE, e);
3643 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA,
3644 GL_UNSIGNED_BYTE, 0);
3645 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
3654 glBindTexture(GL_TEXTURE_2D, m_tideTex);
3655 glEnable(GL_TEXTURE_2D);
3658#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
3660 for (
int i = 1; i < ptcmgr->Get_max_IDX() + 1; i++) {
3661 const IDX_entry *pIDX = ptcmgr->GetIDX_entry(i);
3663 char type = pIDX->IDX_type;
3664 if ((type ==
't') || (type ==
'T'))
3666 double lon = pIDX->IDX_lon;
3667 double lat = pIDX->IDX_lat;
3669 if (BBox.Contains(lat, lon)) {
3671 m_pParentCanvas->GetCanvasPointPix(lat, lon, &r);
3677#ifdef __OCPN__ANDROID__
3678 scale *= getAndroidDisplayDensity();
3680 double width2 =
scale * m_tideTexWidth / 2;
3681 double height2 =
scale * m_tideTexHeight / 2;
3696 coords[0] = xp - width2;
3697 coords[1] = yp - height2;
3698 coords[2] = xp - width2;
3699 coords[3] = yp + height2;
3700 coords[4] = xp + width2;
3701 coords[5] = yp + height2;
3702 coords[6] = xp + width2;
3703 coords[7] = yp - height2;
3705 RenderTextures(dc, coords, uv, 4, m_pParentCanvas->GetpVP());
3712 glDisable(GL_TEXTURE_2D);
3713 glDisable(GL_BLEND);
3714 glBindTexture(GL_TEXTURE_2D, 0);
3716 m_pParentCanvas->DrawAllTidesInBBox(dc, BBox);
3719void glChartCanvas::DrawGLCurrentsInBBox(
ocpnDC &dc, LLBBox &BBox) {
3720 m_pParentCanvas->DrawAllCurrentsInBBox(dc, BBox);
3723void glChartCanvas::SetColorScheme(ColorScheme cs) {
3724 if (!m_bsetup)
return;
3726 glDeleteTextures(1, &m_tideTex);
3727 glDeleteTextures(1, &m_currentTex);
3733void glChartCanvas::RenderGLAlertMessage() {
3734 if (!m_pParentCanvas->GetAlertString().IsEmpty()) {
3735 wxString msg = m_pParentCanvas->GetAlertString();
3737 wxFont *pfont = GetOCPNScaledFont(_(
"Dialog"));
3738 m_gldc.SetFont(*pfont);
3742 sdc.GetTextExtent(msg, &w, &h, NULL, NULL, pfont);
3747 m_pParentCanvas->VPoint.pix_height - GetChartbarHeight() - h - (h / 4);
3749 wxRect sbr = m_pParentCanvas->GetScaleBarRect();
3750 int xp = sbr.x + sbr.width + 5;
3752 wxPen ppPen1(GetGlobalColor(_T (
"UBLCK" )), 1, wxPENSTYLE_SOLID);
3753 m_gldc.SetPen(ppPen1);
3754 m_gldc.SetBrush(wxBrush(GetGlobalColor(_T (
"YELO1" ))));
3756 m_gldc.DrawRectangle(xp, yp, w, h);
3758 m_gldc.DrawText(msg, xp, yp);
3762unsigned long quiltHash;
3766void glChartCanvas::Render() {
3767 if (!m_bsetup || !m_pParentCanvas->m_pQuilt ||
3768 (m_pParentCanvas->VPoint.b_quilt && !m_pParentCanvas->m_pQuilt) ||
3769 (!m_pParentCanvas->VPoint.b_quilt && !m_pParentCanvas->m_singleChart)) {
3777#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
3778 loadShaders(GetCanvasIndex());
3779 configureShaders(m_pParentCanvas->VPoint);
3783#ifdef USE_ANDROID_GLES2
3787 if (m_binPinch)
return;
3796 bool recompose =
false;
3797 if (m_pParentCanvas->VPoint.b_quilt && m_pParentCanvas->m_pQuilt &&
3798 !m_pParentCanvas->m_pQuilt->IsComposed()) {
3799 if (m_pParentCanvas->VPoint.IsValid()) {
3800 m_pParentCanvas->m_pQuilt->
Compose(m_pParentCanvas->VPoint);
3801 m_pParentCanvas->UpdateCanvasControlBar();
3810 if (sw.GetTime() > 2000) {
3811 m_pParentCanvas->ZoomCanvas(1.0001,
false);
3816 s_tess_vertex_idx = 0;
3817 quiltHash = m_pParentCanvas->m_pQuilt->GetXStackHash();
3818 refChartIndex = m_pParentCanvas->m_pQuilt->GetRefChartdbIndex();
3822 m_last_render_time = wxDateTime::Now().GetTicks();
3826 if (g_GLOptions.m_bTextureCompression &&
3827 !g_GLOptions.m_bTextureCompressionCaching)
3828 g_glTextureManager->ClearJobList();
3830 if (b_timeGL && g_bShowFPS) {
3831 if (n_render % 10) {
3833 g_glstopwatch.Start();
3840 int gl_width, gl_height;
3841 gl_width = m_pParentCanvas->VPoint.pix_width;
3842 gl_height = m_pParentCanvas->VPoint.pix_height;
3845 m_glcanvas_width = gl_width;
3846 m_glcanvas_height = gl_height;
3852 ViewPort *vp = m_pParentCanvas->GetpVP();
3853 vp->pix_height = gl_height;
3859 mat4x4_scale_aniso((
float(*)[4])vp->vp_matrix_transform, m,
3860 2.0 / (
float)vp->pix_width, -2.0 / (
float)vp->pix_height,
3862 mat4x4_translate_in_place((
float(*)[4])vp->vp_matrix_transform, -vp->pix_width / 2,
3863 -vp->pix_height / 2, 0);
3867 ViewPort VPoint = m_pParentCanvas->VPoint;
3869 OCPNRegion screen_region(wxRect(0, 0, gl_width, gl_height));
3870 glViewport(0, 0, (GLint)gl_width, (GLint)gl_height);
3873#if !defined(USE_ANDROID_GLES2)
3874 glMatrixMode(GL_PROJECTION);
3877 glOrtho(0, (GLint)gl_width, (GLint)gl_height, 0, -1, 1);
3878 glMatrixMode(GL_MODELVIEW);
3882 if (s_b_useStencil) {
3883 glEnable(GL_STENCIL_TEST);
3884 glStencilMask(0xff);
3885 glClear(GL_STENCIL_BUFFER_BIT);
3886 glDisable(GL_STENCIL_TEST);
3892 if (g_GLOptions.m_GLLineSmoothing) glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
3893 if (g_GLOptions.m_GLPolygonSmoothing)
3894 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
3895 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3902 g_glTextureManager->TextureCrunch(0.8);
3905 double scale_factor = VPoint.ref_scale / VPoint.chart_scale;
3908 bool bpost_hilite = !m_pParentCanvas->m_pQuilt->GetHiliteRegion().Empty();
3909 bool useFBO =
false;
3915 if (m_b_BuiltFBO && !bpost_hilite
3920 bool b_newview =
true;
3921 bool b_full =
false;
3925 if (m_cache_vp.view_scale_ppm == VPoint.view_scale_ppm &&
3926 m_cache_vp.rotation == VPoint.rotation &&
3927 m_cache_vp.clat == VPoint.clat && m_cache_vp.clon == VPoint.clon &&
3928 m_cache_vp.IsValid() && m_cache_vp.pix_height == VPoint.pix_height &&
3929 m_cache_current_ch == m_pParentCanvas->m_singleChart) {
3933#ifdef USE_ANDROID_GLES2
3934 if (recompose) b_newview =
true;
3946 if (VPoint.b_quilt) {
3947 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetFirstChart();
3948 if (!chart) b_full =
true;
3955 if (VPoint.b_quilt && m_pParentCanvas->m_pQuilt->IsQuiltVector() &&
3956 (m_cache_vp.view_scale_ppm != VPoint.view_scale_ppm ||
3957 m_cache_vp.rotation != VPoint.rotation)) {
3958 OCPNPlatform::ShowBusySpinner();
3965 bool accelerated_pan =
false;
3966 if (g_GLOptions.m_bUseAcceleratedPanning && m_cache_vp.IsValid() &&
3967 (VPoint.m_projection_type == PROJECTION_MERCATOR ||
3968 VPoint.m_projection_type == PROJECTION_EQUIRECTANGULAR) &&
3969 m_cache_vp.pix_height == VPoint.pix_height) {
3970 wxPoint2DDouble c_old =
3971 VPoint.GetDoublePixFromLL(VPoint.clat, VPoint.clon) *
3973 wxPoint2DDouble c_new =
3974 m_cache_vp.GetDoublePixFromLL(VPoint.clat, VPoint.clon) *
3977 dy = wxRound(c_new.m_y - c_old.m_y);
3978 dx = wxRound(c_new.m_x - c_old.m_x);
3988 double deltax = c_new.m_x - c_old.m_x;
3989 double deltay = c_new.m_y - c_old.m_y;
3991 bool b_whole_pixel =
true;
3992 if ((fabs(deltax - dx) > 1e-2) || (fabs(deltay - dy) > 1e-2))
3993 b_whole_pixel =
false;
3996 b_whole_pixel && abs(dx) < m_cache_tex_x && abs(dy) < m_cache_tex_y
3997 && (abs(dx) > 0 || (abs(dy) > 0));
4002 if (m_displayScale > 1)
4003 accelerated_pan =
false;
4007 if(fabs(VPoint.rotation) > 0)
4008 accelerated_pan =
false;
4011#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4014 glBindFramebuffer(GL_FRAMEBUFFER, m_fb0);
4016 if (VPoint.chart_scale < 5000) b_full =
true;
4018 if (VPoint.chart_scale > 5e7) b_full =
true;
4020 if (b_full) accelerated_pan =
false;
4023 if (accelerated_pan) {
4024 if ((dx != 0) || (dy != 0))
4035 if (VPoint.chart_scale < 10000) fluff = 8;
4037 if (dy > 0 && dy < gl_height)
4038 update_region.Union(wxRect(0, gl_height - (dy + fluff),
4039 gl_width, dy + fluff));
4041 update_region.Union(wxRect(0, 0, gl_width, -dy + fluff));
4043 if (dx > 0 && dx < gl_width)
4044 update_region.Union(wxRect(gl_width - (dx + fluff), 0,
4045 dx + fluff, gl_height));
4047 update_region.Union(wxRect(0, 0, -dx + fluff, gl_height));
4049 m_cache_page = !m_cache_page;
4052 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4054 m_cache_tex[m_cache_page], 0);
4064 RenderCharts(m_gldc, update_region);
4065 glDisable(g_texture_rectangle_format);
4070 glBindTexture(GL_TEXTURE_2D, m_cache_tex[!m_cache_page]);
4071 glEnable(GL_TEXTURE_2D);
4074 float x1, x2, y1, y2;
4087 float tx1, tx2, ty1, ty2;
4093 tx2 = sx / (float)m_cache_tex_x;
4095 ty2 = sy / (float)m_cache_tex_y;
4112 coords[2] = -dx + sx;
4114 coords[4] = -dx + sx;
4115 coords[5] = dy + sy;
4117 coords[7] = dy + sy;
4119 GLShaderProgram *shader = ptexture_2D_shader_program[GetCanvasIndex()];
4123 shader->SetUniform1i(
"uTex", 0);
4127 mat4x4_scale_aniso(mvp, m, 2.0 / (
float)sx, 2.0 / (
float)sy, 1.0);
4128 mat4x4_translate_in_place(mvp, -(
float)sx / 2, -(
float)sy / 2, 0);
4129 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)mvp);
4131 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
4153 shader->SetAttributePointerf(
"aPos", co1);
4154 shader->SetAttributePointerf(
"aUV", tco1);
4156 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4159 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)VPoint.vp_matrix_transform);
4162 glBindTexture(g_texture_rectangle_format, 0);
4165 glDisable(g_texture_rectangle_format);
4173 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
4174 g_texture_rectangle_format,
4175 m_cache_tex[!m_cache_page], 0);
4186 wxColour color = GetGlobalColor( _T (
"NODTA" ) );
4187 glClearColor( color.Red() / 256., color.Green() / 256. ,
4188 color.Blue()/ 256. ,1.0 );
4189 glClear(GL_COLOR_BUFFER_BIT);
4192 RenderCharts(m_gldc, rscreen_region);
4194 m_cache_page = !m_cache_page;
4199 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4203 if (busy) OCPNPlatform::HideBusySpinner();
4210#ifndef __OCPN__ANDROID__
4212 glMatrixMode(GL_PROJECTION);
4215 gluPerspective(2 * 180 / PI * atan2((
double)gl_height, (
double)gl_width),
4216 (GLfloat)gl_width / (GLfloat)gl_height, 1, gl_width);
4218 glMatrixMode(GL_MODELVIEW);
4222 glTranslatef(-gl_width / 2, -gl_height / 2, -gl_width / 2);
4223 glRotated(VPoint.tilt * 180 / PI, 1, 0, 0);
4225 glGetIntegerv(GL_VIEWPORT, viewport);
4226 glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
4227 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
4233 glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fb0);
4234 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4235 glBlitFramebuffer(0, 0, sx, sy, 0, 0, sx*2, sy*2, GL_COLOR_BUFFER_BIT, GL_LINEAR);
4237 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4241 glBindTexture(g_texture_rectangle_format, m_cache_tex[m_cache_page]);
4242 glEnable(g_texture_rectangle_format);
4244 float tx, ty, tx0, ty0, divx, divy;
4247 if (GL_TEXTURE_RECTANGLE_ARB == g_texture_rectangle_format) {
4250 divx = m_cache_tex_x;
4251 divy = m_cache_tex_y;
4254 tx0 = m_fbo_offsetx / divx;
4255 ty0 = m_fbo_offsety / divy;
4256 tx = (m_fbo_offsetx + m_fbo_swidth) / divx;
4257 ty = (m_fbo_offsety + m_fbo_sheight) / divy;
4282 RenderTextures(gldc, coords, uv, 4, m_pParentCanvas->GetpVP());
4285 glDisable(g_texture_rectangle_format);
4287 m_cache_vp = VPoint;
4288 m_cache_current_ch = m_pParentCanvas->m_singleChart;
4290 if (VPoint.b_quilt) m_pParentCanvas->m_pQuilt->SetRenderedVP(VPoint);
4294 RenderCharts(m_gldc, screen_region);
4300 RenderS57TextOverlay(VPoint);
4301 RenderMBTilesOverlay(VPoint);
4305 wxRect rt = upd.GetRect();
4306 LLRegion region = VPoint.GetLLRegion(rt);
4307 ViewPort cvp = ClippedViewport(VPoint, region);
4308 DrawGroundedOverlayObjects(gldc, cvp);
4311 if (m_pParentCanvas->m_bShowTide || m_pParentCanvas->m_bShowCurrent) {
4312 LLRegion screenLLRegion = VPoint.GetLLRegion(screen_region);
4313 LLBBox screenBox = screenLLRegion.GetBox();
4315 screenBox.EnLarge(screenBox.GetLonRange() * 0.05);
4318 if (m_pParentCanvas->m_bShowTide) {
4319 m_pParentCanvas->RebuildTideSelectList(screenBox);
4320 DrawGLTidesInBBox(gldc, VPoint.GetBBox());
4323 if (m_pParentCanvas->m_bShowCurrent) {
4324 m_pParentCanvas->RebuildCurrentSelectList(screenBox);
4325 DrawGLCurrentsInBBox(gldc, VPoint.GetBBox());
4331 if (g_canvasConfig != 0) {
4332 if (m_pParentCanvas == wxWindow::FindFocus()) {
4333 g_focusCanvas = m_pParentCanvas;
4335 wxColour colour = GetGlobalColor(_T(
"BLUE4"));
4336 wxPen ppBlue(colour, 1);
4337 wxBrush ppBrush(colour);
4338 gldc.SetPen(ppBlue);
4339 gldc.SetBrush(ppBrush);
4340 int xw = m_pParentCanvas->GetClientSize().x * m_displayScale;
4341 float rect_pix = m_pParentCanvas->m_focus_indicator_pix
4343 wxPoint barPoints[4];
4346 barPoints[1].x = xw;
4348 barPoints[2].x = xw;
4349 barPoints[2].y = rect_pix;
4351 barPoints[3].y = rect_pix;
4353 gldc.DrawPolygon(4, barPoints, 0, 0, 1, 0);
4357 DrawDynamicRoutesTracksAndWaypoints(VPoint);
4361 DrawFloatingOverlayObjects(m_gldc);
4363#ifndef USE_ANDROID_GLES2
4366 glMatrixMode(GL_PROJECTION);
4369 glOrtho(0, (GLint)gl_width, (GLint)gl_height, 0, -1, 1);
4370 glMatrixMode(GL_MODELVIEW);
4375 DrawEmboss(m_gldc, m_pParentCanvas->EmbossDepthScale());
4376 DrawEmboss(m_gldc, m_pParentCanvas->EmbossOverzoomIndicator(gldc));
4379 ViewPort &vp = m_pParentCanvas->GetVP();
4380 g_pi_manager->SendViewPortToRequestingPlugIns(vp);
4381 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
4382 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_OVER_EMBOSS);
4385 if (m_pParentCanvas->m_pTrackRolloverWin)
4386 m_pParentCanvas->m_pTrackRolloverWin->Draw(gldc);
4388 if (m_pParentCanvas->m_pRouteRolloverWin)
4389 m_pParentCanvas->m_pRouteRolloverWin->Draw(gldc);
4391 if (m_pParentCanvas->m_pAISRolloverWin)
4392 m_pParentCanvas->m_pAISRolloverWin->Draw(gldc);
4399 if (m_pParentCanvas->m_pCIWin && m_pParentCanvas->m_pCIWin->IsShown()) {
4400 int x, y, width, height;
4401 m_pParentCanvas->m_pCIWin->GetClientSize(&width, &height);
4402 m_pParentCanvas->m_pCIWin->GetPosition(&x, &y);
4403 wxBitmap bmp(width, height, -1);
4406 dc.SetBackground(wxBrush(GetGlobalColor(_T (
"UIBCK" ))));
4409 dc.SetTextBackground(GetGlobalColor(_T (
"UIBCK" )));
4410 dc.SetTextForeground(GetGlobalColor(_T (
"UITX1" )));
4414 wxString s = m_pParentCanvas->m_pCIWin->GetString();
4415 int h = m_pParentCanvas->m_pCIWin->GetCharHeight();
4417 wxStringTokenizer tkz(s, _T(
"\n"));
4420 while (tkz.HasMoreTokens()) {
4421 token = tkz.GetNextToken();
4422 dc.DrawText(token, xt, yt);
4425 dc.SelectObject(wxNullBitmap);
4427 m_gldc.DrawBitmap(bmp, x, y,
false);
4431 if (pthumbwin && pthumbwin->IsShown()) {
4433 pthumbwin->GetPosition(&thumbx, &thumby);
4434 if (pthumbwin->GetBitmap().IsOk())
4435 m_gldc.DrawBitmap(pthumbwin->GetBitmap(), thumbx, thumby,
false);
4438 if (g_MainToolbar && g_MainToolbar->m_pRecoverwin) {
4439 int recoverx, recovery;
4440 g_MainToolbar->m_pRecoverwin->GetPosition(&recoverx, &recovery);
4441 if (g_MainToolbar->m_pRecoverwin->GetBitmap().IsOk())
4442 m_gldc.DrawBitmap(g_MainToolbar->m_pRecoverwin->GetBitmap(), recoverx,
4448 if (g_bShowChartBar) DrawChartBar(m_gldc);
4450 if (m_pParentCanvas->m_Compass) m_pParentCanvas->m_Compass->Paint(gldc);
4452 RenderGLAlertMessage();
4456 ViewPort &vp = m_pParentCanvas->GetVP();
4457 g_pi_manager->SendViewPortToRequestingPlugIns(vp);
4458 g_pi_manager->RenderAllGLCanvasOverlayPlugIns(
4459 m_pcontext, vp, m_pParentCanvas->m_canvasIndex, OVERLAY_OVER_UI);
4463 if (g_bquiting) DrawQuiting();
4464 if (g_bcompression_wait)
4465 DrawCloseMessage(_(
"Waiting for raster chart compression thread exit."));
4470 if (g_b_needFinish) glFinish();
4473 if (b_timeGL && g_bShowFPS) {
4474 if (n_render % 10) {
4477 double filter = .05;
4480 g_gl_ms_per_frame = g_gl_ms_per_frame * (1. - filter) +
4481 ((
double)(g_glstopwatch.Time()) * filter);
4482 if(g_gl_ms_per_frame > 0)
4483 printf(
" OpenGL frame time: %3.0f ms--> %3.0fFPS\n",
4484 g_gl_ms_per_frame, 1000./ g_gl_ms_per_frame);
4488 g_glTextureManager->TextureCrunch(0.8);
4489 g_glTextureManager->FactoryCrunch(0.6);
4491 m_pParentCanvas->PaintCleanup();
4493 m_bforcefull =
false;
4498void glChartCanvas::RenderS57TextOverlay(
ViewPort &VPoint) {
4501 if (VPoint.b_quilt) {
4502 if (m_pParentCanvas->m_pQuilt->IsQuiltVector() && ps52plib &&
4503 ps52plib->GetShowS57Text()) {
4504 ChartBase *chart = m_pParentCanvas->m_pQuilt->GetRefChart();
4505 if (chart && (chart->GetChartType() != CHART_TYPE_CM93COMP)) {
4510 ChPI->ClearPLIBTextList();
4512 ps52plib->ClearTextList();
4518 vpx.BuildExpandedVP(VPoint.pix_width * 12 / 10, VPoint.pix_height);
4521 wxRect(0, 0, VPoint.pix_width, VPoint.pix_height));
4522 RenderQuiltViewGLText(vpx, screen_region);
4528void glChartCanvas::RenderMBTilesOverlay(
ViewPort &VPoint) {
4530 std::vector<int> stackIndexArray =
4531 m_pParentCanvas->m_pQuilt->GetExtendedStackIndexArray();
4532 unsigned int im = stackIndexArray.size();
4535 if (VPoint.b_quilt && im > 0) {
4536 bool regionVPBuilt =
false;
4538 LLRegion screenLLRegion;
4542 std::vector<int> tiles_to_show;
4543 for (
unsigned int is = 0; is < im; is++) {
4545 ChartData->GetChartTableEntry(stackIndexArray[is]);
4546 if (cte.GetChartType() == CHART_TYPE_MBTILES) {
4547 if (m_pParentCanvas->IsTileOverlayIndexInNoShow(stackIndexArray[is])) {
4549 std::vector<int> piano_active_array_tiles =
4550 m_pParentCanvas->m_Piano->GetActiveKeyArray();
4551 bool bfound =
false;
4553 for (
unsigned int i = 0; i < piano_active_array_tiles.size(); i++) {
4554 if (piano_active_array_tiles[i] == stackIndexArray[is]) {
4555 piano_active_array_tiles.erase(piano_active_array_tiles.begin() +
4563 m_pParentCanvas->m_Piano->SetActiveKeyArray(
4564 piano_active_array_tiles);
4569 tiles_to_show.push_back(stackIndexArray[is]);
4570 if (!regionVPBuilt) {
4572 OCPNRegion(wxRect(0, 0, VPoint.pix_width, VPoint.pix_height));
4573 screenLLRegion = VPoint.GetLLRegion(screen_region);
4574 screenBox = screenLLRegion.GetBox();
4578 p.x = VPoint.pix_width / 2;
4579 p.y = VPoint.pix_height / 2;
4580 VPoint.GetLLFromPix(p, &vp.clat, &vp.clon);
4582 regionVPBuilt =
true;
4589 for (std::vector<int>::reverse_iterator rit = tiles_to_show.rbegin();
4590 rit != tiles_to_show.rend(); ++rit) {
4591 ChartBase *chart = ChartData->OpenChartFromDBAndLock(*rit, FULL_INIT);
4595 if (chart == NULL)
continue;
4597 wxFileName tileFile(chart->GetFullPath());
4599 wxULongLong tileSizeMB = tileFile.GetSize() >> 20;
4601 if (!ChartData->CheckAnyCanvasExclusiveTileGroup() ||
4602 (tileSizeMB.GetLo() > 5000)) {
4605 if (!m_pParentCanvas->IsTileOverlayIndexInYesShow(*rit)) {
4606 if (!m_pParentCanvas->IsTileOverlayIndexInNoShow(*rit)) {
4607 m_pParentCanvas->m_tile_noshow_index_array.push_back(*rit);
4614 if (m_pParentCanvas->IsTileOverlayIndexInNoShow(*rit)) {
4620 pcmbt->RenderRegionViewOnGL(*m_pcontext, vp, screen_region,
4624 std::vector<int> piano_active_array_tiles =
4625 m_pParentCanvas->m_Piano->GetActiveKeyArray();
4626 bool bfound =
false;
4628 if (std::find(piano_active_array_tiles.begin(),
4629 piano_active_array_tiles.end(),
4630 *rit) != piano_active_array_tiles.end()) {
4635 piano_active_array_tiles.push_back(*rit);
4636 m_pParentCanvas->m_Piano->SetActiveKeyArray(piano_active_array_tiles);
4642 LLRegion hiregion = m_pParentCanvas->m_pQuilt->GetHiliteRegion();
4644 if (!hiregion.Empty()) {
4648 switch (global_color_scheme) {
4649 case GLOBAL_COLOR_SCHEME_DAY:
4652 case GLOBAL_COLOR_SCHEME_DUSK:
4655 case GLOBAL_COLOR_SCHEME_NIGHT:
4663#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4664 glColor4f((
float).8, (
float).4, (
float).4, (
float)hitrans);
4666 s_regionColor = wxColor(204, 102, 102, hitrans * 256);
4669 DrawRegion(VPoint, hiregion);
4671 glDisable(GL_BLEND);
4676void glChartCanvas::RenderCanvasBackingChart(
ocpnDC &dc,
4680 GetClientSize(&w, &h);
4682 glViewport(0, 0, (GLint)m_cache_tex_x, (GLint)m_cache_tex_y);
4683#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4684 glMatrixMode(GL_PROJECTION);
4687 glOrtho(0, m_cache_tex_x, m_cache_tex_y, 0, -1, 1);
4688 glMatrixMode(GL_MODELVIEW);
4692 wxRect rtex(0, 0, m_cache_tex_x, m_cache_tex_y);
4694 m_pParentCanvas->GetVP().BuildExpandedVP(m_cache_tex_x, m_cache_tex_y);
4696 bool world_view =
false;
4697 RenderWorldChart(dc, cvp, rtex, world_view);
4703 glViewport(0, 0, (GLint)w, (GLint)h);
4704#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4705 glMatrixMode(GL_PROJECTION);
4708 glOrtho(0, (GLint)w, (GLint)h, 0, -1, 1);
4709 glMatrixMode(GL_MODELVIEW);
4714void glChartCanvas::FastPan(
int dx,
int dy) {
4715#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
4719void glChartCanvas::ZoomProject(
float offset_x,
float offset_y,
float swidth,
4721 SetCurrent(*m_pcontext);
4723 float sx = GetSize().x;
4724 float sy = GetSize().y;
4726 float tx, ty, tx0, ty0;
4736 tx = offset_x + swidth;
4737 ty = offset_y + sheight;
4740 GetClientSize(&w, &h);
4741 glViewport(0, 0, (GLint)w, (GLint)h);
4743 if (s_b_useStencil) {
4744 glEnable(GL_STENCIL_TEST);
4745 glStencilMask(0xff);
4746 glClear(GL_STENCIL_BUFFER_BIT);
4747 glDisable(GL_STENCIL_TEST);
4755 glBindTexture(g_texture_rectangle_format, 0);
4758 glBindTexture(g_texture_rectangle_format, m_cache_tex[m_cache_page]);
4759 glEnable(g_texture_rectangle_format);
4766 uv[0] = tx0 / m_cache_tex_x;
4767 uv[1] = ty / m_cache_tex_y;
4768 uv[2] = tx / m_cache_tex_x;
4769 uv[3] = ty / m_cache_tex_y;
4770 uv[4] = tx / m_cache_tex_x;
4771 uv[5] = ty0 / m_cache_tex_y;
4772 uv[6] = tx0 / m_cache_tex_x;
4773 uv[7] = ty0 / m_cache_tex_y;
4785 RenderTextures(m_gldc, coords, uv, 4, m_pParentCanvas->GetpVP());
4787 glDisable(g_texture_rectangle_format);
4788 glBindTexture(g_texture_rectangle_format, 0);
4793 wxColour color = GetGlobalColor(_T(
"GREY1"));
4794 float ht = -offset_y * (sy / sheight);
4795 wxRect r(0, sy - ht, w, ht);
4796 RenderColorRect(r, color);
4799 wxRect rt(0, 0, w, sy - (ht + (sy * sy / sheight)));
4800 RenderColorRect(rt, color);
4803 float w1 = -offset_x * sx / swidth;
4804 wxRect rl(0, 0, w1, sy);
4805 RenderColorRect(rl, color);
4808 float px = w1 + sx * sx / swidth;
4809 wxRect rr(px, 0, sx - px, sy);
4810 RenderColorRect(rr, color);
4820void glChartCanvas::onZoomTimerEvent(wxTimerEvent &event) {
4823 if ((m_nRun < m_nTotal) && !m_zoomFinal) {
4824 m_runoffsetx += m_offsetxStep;
4825 if (m_offsetxStep > 0)
4826 m_runoffsetx = wxMin(m_runoffsetx, m_fbo_offsetx);
4828 m_runoffsetx = wxMax(m_runoffsetx, m_fbo_offsetx);
4830 m_runoffsety += m_offsetyStep;
4831 if (m_offsetyStep > 0)
4832 m_runoffsety = wxMin(m_runoffsety, m_fbo_offsety);
4834 m_runoffsety = wxMax(m_runoffsety, m_fbo_offsety);
4836 m_runswidth += m_swidthStep;
4837 if (m_swidthStep > 0)
4838 m_runswidth = wxMin(m_runswidth, m_fbo_swidth);
4840 m_runswidth = wxMax(m_runswidth, m_fbo_swidth);
4842 m_runsheight += m_sheightStep;
4843 if (m_sheightStep > 0)
4844 m_runsheight = wxMin(m_runsheight, m_fbo_sheight);
4846 m_runsheight = wxMax(m_runsheight, m_fbo_sheight);
4851 ZoomProject(m_runoffsetx, m_runoffsety, m_runswidth, m_runsheight);
4860 m_pParentCanvas->ZoomCanvas(m_zoomFinalZoom,
false);
4862 if (m_zoomFinaldx || m_zoomFinaldy) {
4863 m_pParentCanvas->PanCanvas(m_zoomFinaldx, m_zoomFinaldy);
4866 m_zoomFinal =
false;
4870void glChartCanvas::FastZoom(
float factor,
float cp_x,
float cp_y,
float post_x,
4874 int sx = GetSize().x;
4875 int sy = GetSize().y;
4877 m_lastfbo_offsetx = m_fbo_offsetx;
4878 m_lastfbo_offsety = m_fbo_offsety;
4879 m_lastfbo_swidth = m_fbo_swidth;
4880 m_lastfbo_sheight = m_fbo_sheight;
4882 float curr_fbo_offset_x = m_fbo_offsetx;
4883 float curr_fbo_offset_y = m_fbo_offsety;
4884 float curr_fbo_swidth = m_fbo_swidth;
4885 float curr_fbo_sheight = m_fbo_sheight;
4887 float fx = (float)cp_x / sx;
4888 float fy = 1.0 - (float)cp_y / sy;
4889 if (factor < 1.0f) {
4894 float fbo_ctr_x = curr_fbo_offset_x + (curr_fbo_swidth * fx);
4895 float fbo_ctr_y = curr_fbo_offset_y + (curr_fbo_sheight * fy);
4897 m_fbo_swidth = curr_fbo_swidth / factor;
4898 m_fbo_sheight = curr_fbo_sheight / factor;
4900 m_fbo_offsetx = fbo_ctr_x - (m_fbo_swidth * fx);
4901 m_fbo_offsety = fbo_ctr_y - (m_fbo_sheight * fy);
4903 m_fbo_offsetx += post_x;
4904 m_fbo_offsety += post_y;
4920 float perStep = m_nStep / m_nTotal;
4922 if (zoomTimer.IsRunning()) {
4923 m_offsetxStep = (m_fbo_offsetx - m_runoffsetx) * perStep;
4924 m_offsetyStep = (m_fbo_offsety - m_runoffsety) * perStep;
4925 m_swidthStep = (m_fbo_swidth - m_runswidth) * perStep;
4926 m_sheightStep = (m_fbo_sheight - m_runsheight) * perStep;
4929 m_offsetxStep = (m_fbo_offsetx - m_lastfbo_offsetx) * perStep;
4930 m_offsetyStep = (m_fbo_offsety - m_lastfbo_offsety) * perStep;
4931 m_swidthStep = (m_fbo_swidth - m_lastfbo_swidth) * perStep;
4932 m_sheightStep = (m_fbo_sheight - m_lastfbo_sheight) * perStep;
4934 m_runoffsetx = m_lastfbo_offsetx;
4935 m_runoffsety = m_lastfbo_offsety;
4936 m_runswidth = m_lastfbo_swidth;
4937 m_runsheight = m_lastfbo_sheight;
4940 if (!zoomTimer.IsRunning()) zoomTimer.Start(m_nStep);
4941 m_zoomFinal =
false;
4945#ifdef __OCPN__ANDROID__
4947void glChartCanvas::OnEvtPanGesture(wxQT_PanGestureEvent &event) {
4951 if (m_pParentCanvas->isRouteEditing() || m_pParentCanvas->isMarkEditing())
4954 if (m_binPinch)
return;
4955 if (m_bpinchGuard)
return;
4957 int x =
event.GetOffset().x;
4958 int y =
event.GetOffset().y;
4960 int lx =
event.GetLastOffset().x;
4961 int ly =
event.GetLastOffset().y;
4966 switch (event.GetState()) {
4967 case GestureStarted:
4968 if (m_binPan)
break;
4972 m_binGesture =
true;
4976 case GestureUpdated:
4978 if (!g_GLOptions.m_bUseCanvasPanning) {
4981 m_pParentCanvas->FreezePiano();
4982 m_pParentCanvas->PanCanvas(dx, -dy);
4983 m_pParentCanvas->ThawPiano();
4994 case GestureFinished:
4997 m_pParentCanvas->UpdateCanvasControlBar();
5000 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5004 case GestureCanceled:
5006 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5013 m_bgestureGuard =
true;
5014 m_gestureEeventTimer.Start(500, wxTIMER_ONE_SHOT);
5015 m_bforcefull =
false;
5020float zoom_inc = 1.0;
5021bool first_zout =
false;
5023void glChartCanvas::OnEvtPinchGesture(wxQT_PinchGestureEvent &event) {
5024 float zoom_gain = 1.0;
5025 float zout_gain = 1.0;
5028 float total_zoom_val;
5030 float max_zoom_scale = 1000.;
5031 float min_zoom_scale = 2e8;
5033 if (event.GetScaleFactor() > 1)
5034 zoom_val = ((
event.GetScaleFactor() - 1.0) * zoom_gain) + 1.0;
5036 zoom_val = 1.0 - ((1.0 -
event.GetScaleFactor()) * zout_gain);
5038 if (event.GetTotalScaleFactor() > 1)
5039 total_zoom_val = ((event.GetTotalScaleFactor() - 1.0) * zoom_gain) + 1.0;
5042 total_zoom_val = 1.0 - ((1.0 -
event.GetTotalScaleFactor()) * zout_gain);
5044 double projected_scale = cc1->GetVP().chart_scale / total_zoom_val;
5047 float max_zoom_scale = 1000.;
5048 if( cc1->GetVP().b_quilt) {
5049 int ref_index = cc1->GetQuiltRefChartdbIndex();
5056 float min_zoom_scale = 2e8;
5062 1.0 - ((1.0 -
event.GetTotalScaleFactor()) * zoom_gain);
5064 double projected_scale =
5065 m_pParentCanvas->GetVP().chart_scale / total_zoom_val;
5067 switch (event.GetState()) {
5068 case GestureStarted:
5073 m_binGesture =
true;
5075 m_pinchStart =
event.GetCenterPoint();
5076 m_lpinchPoint = m_pinchStart;
5078 m_pParentCanvas->GetCanvasPixPoint(event.GetCenterPoint().x,
5079 event.GetCenterPoint().y, m_pinchlat,
5084 m_cc_x = m_fbo_offsetx + (m_fbo_swidth / 2);
5085 m_cc_y = m_fbo_offsety + (m_fbo_sheight / 2);
5088 SetCurrent(*m_pcontext);
5094 case GestureUpdated:
5095 if (g_GLOptions.m_bUseCanvasPanning) {
5096 if (projected_scale < min_zoom_scale) {
5097 wxPoint pinchPoint =
event.GetCenterPoint();
5099 float dx = pinchPoint.x - m_lpinchPoint.x;
5100 float dy = pinchPoint.y - m_lpinchPoint.y;
5102 FastZoom(zoom_val, m_pinchStart.x, m_pinchStart.y,
5103 -dx / total_zoom_val, dy / total_zoom_val);
5105 m_lpinchPoint = pinchPoint;
5109 if (1 || ((total_zoom_val > 1) && !first_zout)) {
5110 wxPoint pinchPoint =
event.GetCenterPoint();
5112 float dx = pinchPoint.x - m_lpinchPoint.x;
5113 float dy = pinchPoint.y - m_lpinchPoint.y;
5115 if ((projected_scale > max_zoom_scale) &&
5116 (projected_scale < min_zoom_scale))
5117 FastZoom(zoom_val, m_pinchStart.x, m_pinchStart.y,
5118 -dx / total_zoom_val, dy / total_zoom_val);
5120 m_lpinchPoint = pinchPoint;
5124 zoom_inc *= zoom_val;
5125 if ((zoom_inc < 0.9) || (zoom_inc > 1.1)) {
5126 m_pParentCanvas->ZoomCanvas(zoom_inc,
false);
5130 wxPoint pinchPoint =
event.GetCenterPoint();
5131 float dx = pinchPoint.x - m_lpinchPoint.x;
5132 float dy = pinchPoint.y - m_lpinchPoint.y;
5133 m_pParentCanvas->PanCanvas(-dx, -dy);
5134 m_lpinchPoint = pinchPoint;
5145 case GestureFinished: {
5149 float cc_x = m_fbo_offsetx + (m_fbo_swidth / 2);
5150 float cc_y = m_fbo_offsety + (m_fbo_sheight / 2);
5154 float tzoom = total_zoom_val;
5156 if (projected_scale >= min_zoom_scale)
5157 tzoom = m_pParentCanvas->GetVP().chart_scale / min_zoom_scale;
5159 if (projected_scale < max_zoom_scale)
5160 tzoom = m_pParentCanvas->GetVP().chart_scale / max_zoom_scale;
5162 dx = (cc_x - m_cc_x) * tzoom;
5163 dy = -(cc_y - m_cc_y) * tzoom;
5166 if (zoomTimer.IsRunning()) {
5169 m_zoomFinalZoom = tzoom;
5175 double final_projected_scale =
5176 m_pParentCanvas->GetVP().chart_scale / tzoom;
5179 if (final_projected_scale < min_zoom_scale) {
5181 m_pParentCanvas->ZoomCanvas(tzoom,
false);
5182 m_pParentCanvas->PanCanvas(dx, dy);
5183 m_pParentCanvas->m_pQuilt->Invalidate();
5184 m_bforcefull =
true;
5188 m_pParentCanvas->GetCanvasScaleFactor() / min_zoom_scale;
5190 m_pParentCanvas->SetVPScale(new_scale);
5191 m_pParentCanvas->m_pQuilt->Invalidate();
5192 m_bforcefull =
true;
5204 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5208 case GestureCanceled:
5210 m_gestureFinishTimer.Start(500, wxTIMER_ONE_SHOT);
5217 m_bgestureGuard =
true;
5219 m_gestureEeventTimer.Start(500, wxTIMER_ONE_SHOT);
5222void glChartCanvas::onGestureTimerEvent(wxTimerEvent &event) {
5232 m_bgestureGuard =
false;
5233 m_bpinchGuard =
false;
5234 m_binGesture =
false;
5235 m_bforcefull =
false;
5238void glChartCanvas::onGestureFinishTimerEvent(wxTimerEvent &event) {
5242 m_binGesture =
false;
5243 m_bforcefull =
false;
5248void glChartCanvas::configureShaders(
ViewPort & vp) {
5249#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5255 GLShaderProgram *shader = pcolor_tri_shader_program[GetCanvasIndex()];
5257 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5258 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5278 shader = ptexture_2D_shader_program[GetCanvasIndex()];
5280 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5281 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5292 shader = pcircle_filled_shader_program[GetCanvasIndex()];
5294 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5295 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5307 shader = ptexture_2DA_shader_program[GetCanvasIndex()];
5309 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5310 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5318 shader = pAALine_shader_program[GetCanvasIndex()];
5320 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5323 shader = pring_shader_program[GetCanvasIndex()];
5325 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)pvp->vp_matrix_transform);
5326 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)I);
5329 m_gldc.m_texfont.PrepareShader(vp.pix_width, vp.pix_height, vp.rotation);
5335void glChartCanvas::RenderTextures(
ocpnDC &dc,
float *coords,
float *uvCoords,
5338#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5339 int nl = nVertex / 4;
5341 float *luv = uvCoords;
5344 RenderSingleTexture(dc, lc, luv, vp, 0, 0, 0);
5352 glEnableClientState(GL_VERTEX_ARRAY);
5353 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
5355 glTexCoordPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), uvCoords);
5356 glVertexPointer(2, GL_FLOAT, 2 *
sizeof(GLfloat), coords);
5357 glDrawArrays(GL_QUADS, 0, 4);
5364void glChartCanvas::RenderSingleTexture(
ocpnDC &dc,
float *coords,
float *uvCoords,
5367#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5369 GLShaderProgram *shader = ptexture_2D_shader_program[dc.m_canvasIndex];
5375 shader->SetUniform1i(
"uTex", 0);
5380 mat4x4_rotate_Z(Q, I, angle_rad);
5387 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)Q);
5392 shader->SetAttributePointerf(
"aPos", co1);
5393 shader->SetAttributePointerf(
"aUV", tco1);
5401 GLushort indices1[] = {0,1,3,2};
5402 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices1);
5414 tco1[0] = uvCoords[0];
5415 tco1[1] = uvCoords[1];
5416 tco1[2] = uvCoords[2];
5417 tco1[3] = uvCoords[3];
5418 tco1[4] = uvCoords[6];
5419 tco1[5] = uvCoords[7];
5420 tco1[6] = uvCoords[4];
5421 tco1[7] = uvCoords[5];
5426 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5438void glChartCanvas::RenderColorRect(wxRect r, wxColor & color) {
5439#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5441 GLShaderProgram *shader = pcolor_tri_shader_program[GetCanvasIndex()];
5444 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_pParentCanvas->GetpVP()->vp_matrix_transform);
5447 colorv[0] = color.Red() / float(256);
5448 colorv[1] = color.Green() / float(256);
5449 colorv[2] = color.Blue() / float(256);
5451 shader->SetUniform4fv(
"color", colorv);
5454 pf[0] = r.x + r.width;
5458 pf[4] = r.x + r.width;
5459 pf[5] = r.y + r.height;
5461 pf[7] = r.y + r.height;
5462 shader->SetAttributePointerf(
"position", pf);
5464 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5472void glChartCanvas::RenderScene(
bool bRenderCharts,
bool bRenderOverlays) {
5474#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
5476 ViewPort VPoint = m_pParentCanvas->VPoint;
5480 GetClientSize(&w, &h);
5481 int sx = GetSize().x;
5482 int sy = GetSize().y;
5484 OCPNRegion screen_region(wxRect(0, 0, VPoint.pix_width, VPoint.pix_height));
5486 glViewport(0, 0, (GLint)w, (GLint)h);
5488 if (s_b_useStencil) {
5489 glEnable(GL_STENCIL_TEST);
5490 glStencilMask(0xff);
5491 glClear(GL_STENCIL_BUFFER_BIT);
5492 glDisable(GL_STENCIL_TEST);
5496 m_pParentCanvas->m_pQuilt->
Compose(m_pParentCanvas->VPoint);
5501 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
5502 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
5503 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5506 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fb0);
5508 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
5509 g_texture_rectangle_format,
5510 m_cache_tex[m_cache_page], 0);
5517 if (bRenderCharts) RenderCharts(gldc, screen_region);
5519 if (bRenderOverlays) {
5520 RenderS57TextOverlay(m_pParentCanvas->VPoint);
5521 RenderMBTilesOverlay(m_pParentCanvas->VPoint);
5522 DrawStaticRoutesTracksAndWaypoints(m_pParentCanvas->VPoint);
5523 DrawDynamicRoutesTracksAndWaypoints(VPoint);
5524 DrawFloatingOverlayObjects(m_gldc);
5528 glBindFramebuffer(GL_FRAMEBUFFER, 0);
bool MouseEventSetup(wxMouseEvent &event, bool b_handle_dclick=true)
bool Compose(const ViewPort &vp)