wxGLCanvas is a small square

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
m0rr0w
In need of some credit
In need of some credit
Posts: 6
Joined: Wed Aug 16, 2017 4:25 pm

wxGLCanvas is a small square

Post by m0rr0w »

Hello I have a problem where wxGLCanvas is a small square in the upper left of my client area. I can change the color so I know thats the canvas but I can't figure out how to change the size. I tried creating the wxGLCanvas as child to a panel and setting the panel to a sizer, I tried setting the wxGLCanvas directly into a sizer, but it doesn't make the canvas any bigger. Take a look at this code:

Code: Select all

#include "wx/wx.h";
#include "wx/notebook.h";
#include <glew.h>
#include <wx/glcanvas.h>

// Declare the application class
class MyApp : public wxApp
{
public:
	bool render_loop_on;
	virtual bool OnInit();
};

// Implements MyApp& GetApp()
DECLARE_APP(MyApp)
// Give wxWidgets the means to create a MyApp object
IMPLEMENT_APP(MyApp)

// Declare our main frame class
class MyFrame : public wxFrame
{
public:
	/*wxNotebook* nbHierarchy = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));
	wxNotebook* nbScene = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(800, 600));
	wxNotebook* nbInspector = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));*/

	// Constructor
	MyFrame(const wxString& title);
	// Event handlers
	void OnQuit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);
	void OnSize(wxSizeEvent& event);
	void OnPaint(wxPaintEvent& event);
	wxGLContext* myContext;
	wxGLCanvas* myCanvas;
	wxPanel* panel;
private:
	// This class handles events
	DECLARE_EVENT_TABLE()
};

// Initialize the application
bool MyApp::OnInit()
{
	// Create the main application window
	MyFrame *frame = new MyFrame(wxT("War Engine Version 0"));
	// Show it
	frame->Show(true);
	return true;
}

// Event table for MyFrame
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
EVT_SIZE(MyFrame::OnSize)
EVT_PAINT(MyFrame::OnPaint)
wxEND_EVENT_TABLE()

void MyFrame::OnAbout(wxCommandEvent& event)
{
	wxString msg;
	msg.Printf(wxT("Hello and welcome to %s."),
		"War Engine Version 0");

	wxMessageBox(msg, wxT("About War Engine"),
		wxOK | wxICON_INFORMATION, this);
}

void MyFrame::OnQuit(wxCommandEvent& event)
{
	// Destroy the frame
	Close();
}

MyFrame::MyFrame(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title)
{
	// Create a menu bar
	wxMenu *fileMenu = new wxMenu;
	// The “About” item should be in the help menu
	wxMenu *helpMenu = new wxMenu;
	helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
		wxT("ABout this program."));
	fileMenu->Append(wxID_EXIT, wxT("E&xit\tAlt - X"),
		wxT("Quit this program"));
	// Now append the freshly created menu to the menu bar...
	wxMenuBar *menuBar = new wxMenuBar();
	menuBar->Append(fileMenu, wxT("&File"));
	menuBar->Append(helpMenu, wxT("&Help"));
	// ... and attach this menu bar to the frame
	SetMenuBar(menuBar);
	// Create a status bar just for fun
	CreateStatusBar(2);
	SetStatusText(wxT("Welcome to War Engine!"));

	panel = new wxPanel(this);

	wxGLAttributes vAttrs;
	// Defaults should be accepted
	vAttrs.PlatformDefaults().Defaults().EndList();
	bool accepted = wxGLCanvas::IsDisplaySupported(vAttrs);

	if (accepted)
	{
		myCanvas = new wxGLCanvas(panel, vAttrs);
	}

	wxGLContextAttrs ctxAttrs;
	ctxAttrs.PlatformDefaults().CoreProfile().OGLVersion(3, 2).EndList();
	myContext = new wxGLContext(myCanvas, NULL, &ctxAttrs);

	myCanvas->SetCurrent(*myContext);

	glewExperimental = true;

	GLenum err = glewInit();

	if (GLEW_OK != err)
	{
		wxMessageBox("GLEW not initialized");
	}

	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	sizer->Add(panel, 1, wxEXPAND);
	sizer->SetSizeHints(this);
	SetSizer(sizer);

	/*wxPanel* hierarchyWindow = new wxPanel(nbHierarchy, wxID_ANY);
	nbHierarchy->AddPage(hierarchyWindow, "Hierarchy", false);
	wxPanel* sceneWindow = new wxPanel(nbScene, wxID_ANY);
	nbScene->AddPage(sceneWindow, "Game", false);
	wxPanel* inspectorWindow = new wxPanel(nbInspector, wxID_ANY);
	nbInspector->AddPage(inspectorWindow, "Inspector", false);

	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	sizer->Add(nbHierarchy, 0, wxEXPAND, 0);
	sizer->Add(nbScene, 1, wxEXPAND, 0);
	sizer->Add(nbInspector, 0, wxEXPAND, 0);
	sizer->SetSizeHints(this);
	SetSizer(sizer);*/
}

void MyFrame::OnSize(wxSizeEvent& event)
{
	glViewport(0, 0, (GLsizei)event.GetSize().x, (GLsizei)event.GetSize().y);
}

void MyFrame::OnPaint(wxPaintEvent& event)
{
	glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	myCanvas->SwapBuffers();
}
So why can't I change the size of the canvas if I'm putting it in a sizer...

I don't see anything that helps me in the sample.
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxGLCanvas is a small square

Post by doublemax »

I don't see anything that helps me in the sample.
At the very least you should have seen that the samples are totally different from your code.

There are so many things wrong in your code that i don't even know where to start.
- you need to catch the paint event of the wxGLCanvas, not the wxFrame
- in the paint event handler you must create a wxPaintDC even if you don't use it
- you must catch the size event of the wxGLCanvas, not the wxFrame
- you didn't put wxGLCanvas into any sizer

I would suggest to take one of the OpenGL samples as base for your code.
Use the source, Luke!
m0rr0w
In need of some credit
In need of some credit
Posts: 6
Joined: Wed Aug 16, 2017 4:25 pm

Re: wxGLCanvas is a small square

Post by m0rr0w »

doublemax wrote:
I don't see anything that helps me in the sample.
At the very least you should have seen that the samples are totally different from your code.

There are so many things wrong in your code that i don't even know where to start.
- you need to catch the paint event of the wxGLCanvas, not the wxFrame
- in the paint event handler you must create a wxPaintDC even if you don't use it
- you must catch the size event of the wxGLCanvas, not the wxFrame
- you didn't put wxGLCanvas into any sizer

I would suggest to take one of the OpenGL samples as base for your code.
Thx alot I got it to work. I'm having so much problems because I'm trying to learn opengl and wxwidgets at the same time while being used to only coding in c# in Unity but I'm slowly getting it. The sample just kind of overwhelmed me but I will keep reading over it. #-o

Here is the code that shows a black triangle on a green background (atleast for me). I think you should make this a sample for ppl like me :lol: :

src.h

Code: Select all

#pragma once
#include <wx/glcanvas.h>

// Declare the application class
class MyApp : public wxApp
{
public:
	bool render_loop_on;
	virtual bool OnInit();
};

class MyGLCanvas;

// Declare our main frame class
class MyFrame : public wxFrame
{
public:
	/*wxNotebook* nbHierarchy = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));
	wxNotebook* nbScene = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(800, 600));
	wxNotebook* nbInspector = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));*/

	// Constructor
	MyFrame(const wxString& title);
	// Event handlers
	void OnQuit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);
private:
	MyGLCanvas* m_mycanvas;
	wxDECLARE_EVENT_TABLE();
};

class MyGLCanvas : public wxGLCanvas
{
public:
	MyGLCanvas(MyFrame* parent, const wxGLAttributes& canvasAttrs);
	~MyGLCanvas();

	void OnPaint(wxPaintEvent& event);
	void OnSize(wxSizeEvent& event);
	wxGLContext* myContext;

	wxDECLARE_EVENT_TABLE();
};


src.cpp

Code: Select all

#include "wx/wx.h"
#include "wx/notebook.h"
#include <glew.h>
#include <wx/glcanvas.h>
#include "src.h"

static const GLfloat g_vertex_buffer_data[] = {
	-1.0f, -1.0f, 0.0f,
	1.0f, -1.0f, 0.0f,
	0.0f,  1.0f, 0.0f,
};

GLuint vertexbuffer;

// Event table for MyFrame
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
wxEND_EVENT_TABLE()

// Implements MyApp& GetApp()
DECLARE_APP(MyApp)
// Give wxWidgets the means to create a MyApp object
IMPLEMENT_APP(MyApp)

// Initialize the application
bool MyApp::OnInit()
{
	// Create the main application window
	MyFrame *frame = new MyFrame(wxT("War Engine Version 0"));
	// Show it
	frame->Show(true);
	return true;
}

void MyFrame::OnAbout(wxCommandEvent& event)
{
	wxString msg;
	msg.Printf(wxT("Hello and welcome to %s."),
		"War Engine Version 0");

	wxMessageBox(msg, wxT("About War Engine"),
		wxOK | wxICON_INFORMATION, this);
}

void MyFrame::OnQuit(wxCommandEvent& event)
{
	// Destroy the frame
	Close();
}

MyFrame::MyFrame(const wxString& title)
	: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(800,600))
{
	// Create a menu bar
	wxMenu *fileMenu = new wxMenu;
	// The “About” item should be in the help menu
	wxMenu *helpMenu = new wxMenu;
	helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
		wxT("ABout this program."));
	fileMenu->Append(wxID_EXIT, wxT("E&xit\tAlt - X"),
		wxT("Quit this program"));
	// Now append the freshly created menu to the menu bar...
	wxMenuBar *menuBar = new wxMenuBar();
	menuBar->Append(fileMenu, wxT("&File"));
	menuBar->Append(helpMenu, wxT("&Help"));
	// ... and attach this menu bar to the frame
	SetMenuBar(menuBar);
	// Create a status bar just for fun
	CreateStatusBar(2);
	SetStatusText(wxT("Welcome to War Engine!"));

	wxGLAttributes vAttrs;

	vAttrs.PlatformDefaults().Defaults().EndList();
	bool accepted = wxGLCanvas::IsDisplaySupported(vAttrs);

	if (accepted)
	{
		m_mycanvas = new MyGLCanvas(this, vAttrs);
	}

	glewExperimental = true;
	m_mycanvas->SetCurrent(*m_mycanvas->myContext);

	GLenum err = glewInit();

	if (GLEW_OK != err)
	{
		wxMessageBox("GLEW not initialized");
	}

	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	sizer->Add(m_mycanvas, 1, wxEXPAND);
	sizer->SetSizeHints(m_mycanvas);
	SetSizer(sizer);

	GLuint VertexArrayID;
	glGenVertexArrays(1, &VertexArrayID);
	glBindVertexArray(VertexArrayID);

	// This will identify our vertex buffer
	
	// Generate 1 buffer, put the resulting identifier in vertexbuffer
	glGenBuffers(1, &vertexbuffer);
	// The following commands will talk about our 'vertexbuffer' buffer
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	// Give our vertices to OpenGL.
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);



	/*wxPanel* hierarchyWindow = new wxPanel(nbHierarchy, wxID_ANY);
	nbHierarchy->AddPage(hierarchyWindow, "Hierarchy", false);
	wxPanel* sceneWindow = new wxPanel(nbScene, wxID_ANY);
	nbScene->AddPage(sceneWindow, "Game", false);
	wxPanel* inspectorWindow = new wxPanel(nbInspector, wxID_ANY);
	nbInspector->AddPage(inspectorWindow, "Inspector", false);

	wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
	sizer->Add(nbHierarchy, 0, wxEXPAND, 0);
	sizer->Add(nbScene, 1, wxEXPAND, 0);
	sizer->Add(nbInspector, 0, wxEXPAND, 0);
	sizer->SetSizeHints(this);
	SetSizer(sizer);*/
}

wxBEGIN_EVENT_TABLE(MyGLCanvas, wxGLCanvas)
EVT_PAINT(MyGLCanvas::OnPaint)
EVT_SIZE(MyGLCanvas::OnSize)
wxEND_EVENT_TABLE()

MyGLCanvas::MyGLCanvas(MyFrame* parent, const wxGLAttributes& canvasAttribs) : wxGLCanvas(parent, canvasAttribs)
{
	wxGLContextAttrs ctxAttrs;
	ctxAttrs.PlatformDefaults().CoreProfile().OGLVersion(3, 2).EndList();

	myContext = new wxGLContext(this, NULL, &ctxAttrs);

	if (!myContext->IsOK())
	{
		wxMessageBox("Opengl 3.2 capable driver needed.");
	}
}

MyGLCanvas::~MyGLCanvas()
{
	if (myContext)
		SetCurrent(*myContext);

	if (myContext)
	{
		delete myContext;
		myContext = NULL;
	}
}

void MyGLCanvas::OnSize(wxSizeEvent& event)
{
	glViewport(0, 0, (GLsizei)event.GetSize().x, (GLsizei)event.GetSize().y);
}

void MyGLCanvas::OnPaint(wxPaintEvent& event)
{
	wxPaintDC dc(this);

	glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	// 1rst attribute buffer : vertices
	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
	glVertexAttribPointer(
		0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
		3,                  // size
		GL_FLOAT,           // type
		GL_FALSE,           // normalized?
		0,                  // stride
		(void*)0            // array buffer offset
	);
	// Draw the triangle !
	glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
	glDisableVertexAttribArray(0);

	SwapBuffers();
}
Post Reply