This sample is based on the XPLM300 window sample. It demonstrates the use of the modelview, viewport, and projection matrix datarefs (new to X-Plane 11.10) for applying scissoring to new-style plugin-created windows.
If you build the plugin, but comment out the call the glScissor()
, you’ll see the fill pattern goes all the way to the edge of the green rectangle.
- Download as a project for Xcode 14 or newer (64-bit Intel)
- Download as a project for Microsoft Visual Studio 2017 (64-bit; requires Windows 8.1 SDK)
- Download as a project for GCC 4.x/Linux (64-bit)
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"
#include "XPLMDataAccess.h"
#include <string.h>
#include <stdio.h>
#if IBM
#include <windows.h>
#endif
#if LIN
#include <GL/gl.h>
#elif __GNUC__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#endif
#ifndef XPLM300
#error This is made to be compiled against the XPLM300 SDK
#endif
static XPLMWindowID g_window;
void draw(XPLMWindowID in_window_id, void * in_refcon);
int dummy_mouse_handler(XPLMWindowID in_window_id, int x, int y, int is_down, void * in_refcon) { return 0; }
XPLMCursorStatus dummy_cursor_status_handler(XPLMWindowID in_window_id, int x, int y, void * in_refcon) { return xplm_CursorDefault; }
int dummy_wheel_handler(XPLMWindowID in_window_id, int x, int y, int wheel, int clicks, void * in_refcon) { return 0; }
void dummy_key_handler(XPLMWindowID in_window_id, char key, XPLMKeyFlags flags, char virtual_key, void * in_refcon, int losing_focus) { }
PLUGIN_API int XPluginStart(
char * outName,
char * outSig,
char * outDesc)
{
strcpy(outName, "ScissorsSamplePlugin");
strcpy(outSig, "xpsdk.examples.scissorsampleplugin");
strcpy(outDesc, "A test plug-in that demonstrates using GL scissors within an X-Plane 11 GUI window.");
// We're not guaranteed that the main monitor's lower left is at (0, 0)... we'll need to query for the global desktop bounds!
int global_desktop_bounds[4]; // left, bottom, right, top
XPLMGetScreenBoundsGlobal(&global_desktop_bounds[0], &global_desktop_bounds[3], &global_desktop_bounds[2], &global_desktop_bounds[1]);
XPLMCreateWindow_t params;
params.structSize = sizeof(params);
params.left = global_desktop_bounds[0] + 50;
params.bottom = global_desktop_bounds[1] + 150;
params.right = global_desktop_bounds[0] + 350;
params.top = global_desktop_bounds[1] + 450;
params.visible = 1;
params.drawWindowFunc = draw;
params.handleMouseClickFunc = dummy_mouse_handler;
params.handleRightClickFunc = dummy_mouse_handler;
params.handleMouseWheelFunc = dummy_wheel_handler;
params.handleKeyFunc = dummy_key_handler;
params.handleCursorFunc = dummy_cursor_status_handler;
params.refcon = NULL;
params.layer = xplm_WindowLayerFloatingWindows;
params.decorateAsFloatingWindow = 1;
g_window = XPLMCreateWindowEx(¶ms);
XPLMSetWindowTitle(g_window, "Sample Window");
return (g_window != NULL);
}
PLUGIN_API void XPluginStop(void)
{
// Since we created the window, we'll be good citizens and clean it up
XPLMDestroyWindow(g_window);
g_window = NULL;
}
PLUGIN_API void XPluginDisable(void) { }
PLUGIN_API int XPluginEnable(void) { return 1; }
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void * inParam) { }
static void multMatrixVec4f(GLfloat dst[4], const GLfloat m[16], const GLfloat v[4])
{
dst[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12];
dst[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13];
dst[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14];
dst[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15];
}
static void modelview_to_window_coords(int out_w[2], const GLfloat in_mv[4], const GLfloat mv[16], const GLfloat pr[16], const GLint viewport[4])
{
GLfloat eye[4], ndc[4];
multMatrixVec4f(eye, mv, in_mv);
multMatrixVec4f(ndc, pr, eye);
ndc[3] = 1.0f / ndc[3];
ndc[0] *= ndc[3];
ndc[1] *= ndc[3];
out_w[0] = (ndc[0] * 0.5f + 0.5f) * viewport[2] + viewport[0];
out_w[1] = (ndc[1] * 0.5f + 0.5f) * viewport[3] + viewport[1];
}
void draw(XPLMWindowID in_window_id, void * in_refcon)
{
XPLMSetGraphicsState(
0 /* no fog */,
0 /* 0 texture units */,
0 /* no lighting */,
0 /* no alpha testing */,
1 /* do alpha blend */,
1 /* do depth testing */,
0 /* no depth writing */
);
int l, t, r, b;
XPLMGetWindowGeometry(in_window_id, &l, &t, &r, &b);
// First, draw a green box at the edges of the window to illustrate the *full* bounds.
glColor4f(0, 1, 0, 1);
glBegin(GL_LINE_LOOP);
{
glVertex2f(l, b);
glVertex2f(l, t);
glVertex2f(r, t);
glVertex2f(r, b);
}
glEnd();
static XPLMDataRef mv_dref = XPLMFindDataRef("sim/graphics/view/modelview_matrix");
static XPLMDataRef vp_dref = XPLMFindDataRef("sim/graphics/view/viewport");
static XPLMDataRef pr_dref = XPLMFindDataRef("sim/graphics/view/projection_matrix");
// Get the current modelview matrix, viewport, and projection matrix from X-Plane
float mv[16], pr[16];
int vp[4];
XPLMGetDatavf(mv_dref, mv, 0, 16);
XPLMGetDatavf(pr_dref, pr, 0, 16);
XPLMGetDatavi(vp_dref, vp, 0, 4);
// Our new modelview bounds: we'll bring the window in by 10 bx on all sides
GLfloat top_right_modelview[4] = { r - 10, t - 10, 0, 1 };
GLfloat btm_left_modelview[4] = { l + 10, b + 10, 0, 1 };
// Get our top-right and bottom-left window coordinates
int top_right_window[2], btm_left_window[2];
modelview_to_window_coords(top_right_window, top_right_modelview, mv, pr, vp);
modelview_to_window_coords(btm_left_window, btm_left_modelview, mv, pr, vp);
glEnable(GL_SCISSOR_TEST);
glScissor(btm_left_window[0], btm_left_window[1], top_right_window[0] - btm_left_window[0], top_right_window[1] - btm_left_window[1]);
{
// Draw a fill pattern
// If the scissors were disabled, this would fill the entire window, not just a subsection.
glColor4f(1, 1, 1, 0.2);
int x, y;
glBegin(GL_LINES);
for(x = l; x < r; x += 3)
{
glVertex2f(x, b);
glVertex2f(x, t);
}
for(y = b; y < t; y += 3)
{
glVertex2f(l, y);
glVertex2f(r, y);
}
glEnd();
}
glDisable(GL_SCISSOR_TEST);
}
i couldnt download this plugin for all releases. Can you help me for download? whats the problem ?
Doh! Looks like I broke the download links in the reorganization we did yesterday. Give it a try now!
I used this sample, however i am keep getting identity matrix for modelview matrix. Can you please help me?
That sounds normal! On a 2-D monitor (i.e., not in VR), drawing in 2-D, the scaling to the display is all in the projection matrix, so the modelview matrix will be identity. If you launch in VR, you’ll get a different modelview matrix.
Hi, I am new to using OpenGL, I am trying to using the glBegin glVertex glEnd to draw a procedural aircraft panel but I heard that this method is deprecated for OpenGL 3, what would recommend as a suitable solution for drawing a large amount of lines and text? Thank you very much.