Today, I was able to load 3D Object Model with OpenSceneGraph on wxWidgets. This project used OpenSceneGraph-3.0, wxWidget 2.8.12, Windows 10 and Visual Studio 2010. It was really fun. The code consist of wxOsgHello.cpp and wxOsgHello.h. Here is the code shown as below:
Filename: wxOsgHello.cpp
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// For wxCURSOR_BLANK below, but isn't used a.t.m.
//#ifdef WIN32
//#include "wx/msw/wx.rc"
//#endif
#include "wxOsgHello.h"
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgDB/ReadFile>
#include <wx/image.h>
#include <wx/menu.h>
#include <iostream>
// `Main program' equivalent, creating windows and returning main app frame
bool wxOsgApp::OnInit()
{
if (argc<2)
{
std::cout << wxString(argv[0]).mb_str() <<": requires filename argument." << std::endl;
return false;
}
int width = 800;
int height = 600;
// Create the main frame window
MainFrame *frame = new MainFrame(NULL, wxT("wxWidgets OSG Sample"),
wxDefaultPosition, wxSize(width, height));
// create osg canvas
// - initialize
int attributes[7];
attributes[0] = int(WX_GL_DOUBLEBUFFER);
attributes[1] = WX_GL_RGBA;
attributes[2] = WX_GL_DEPTH_SIZE;
attributes[3] = 8;
attributes[4] = WX_GL_STENCIL_SIZE;
attributes[5] = 8;
attributes[6] = 0;
OSGCanvas *canvas = new OSGCanvas(frame, wxID_ANY, wxDefaultPosition,
wxSize(width, height), wxSUNKEN_BORDER, wxT("osgviewerWX"), attributes);
GraphicsWindowWX* gw = new GraphicsWindowWX(canvas);
canvas->SetGraphicsWindow(gw);
osgViewer::Viewer *viewer = new osgViewer::Viewer;
viewer->getCamera()->setGraphicsContext(gw);
viewer->getCamera()->setViewport(0,0,width,height);
viewer->addEventHandler(new osgViewer::StatsHandler);
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
// load the scene.
wxString fname(argv[1]);
osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(std::string(fname.mb_str()));
if (!loadedModel)
{
std::cout << argv[0] <<": No data loaded." << std::endl;
return false;
}
viewer->setSceneData(loadedModel.get());
viewer->setCameraManipulator(new osgGA::TrackballManipulator);
frame->SetViewer(viewer);
/* Show the frame */
frame->Show(true);
return true;
}
IMPLEMENT_APP(wxOsgApp)
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
EVT_IDLE(MainFrame::OnIdle)
END_EVENT_TABLE()
/* My frame constructor */
MainFrame::MainFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
const wxSize& size, long style)
: wxFrame(frame, wxID_ANY, title, pos, size, style)
{
}
void MainFrame::SetViewer(osgViewer::Viewer *viewer)
{
_viewer = viewer;
}
void MainFrame::OnIdle(wxIdleEvent &event)
{
if (!_viewer->isRealized())
return;
_viewer->frame();
event.RequestMore();
}
BEGIN_EVENT_TABLE(OSGCanvas, wxGLCanvas)
EVT_SIZE (OSGCanvas::OnSize)
EVT_PAINT (OSGCanvas::OnPaint)
EVT_ERASE_BACKGROUND (OSGCanvas::OnEraseBackground)
EVT_CHAR (OSGCanvas::OnChar)
EVT_KEY_UP (OSGCanvas::OnKeyUp)
EVT_ENTER_WINDOW (OSGCanvas::OnMouseEnter)
EVT_LEFT_DOWN (OSGCanvas::OnMouseDown)
EVT_MIDDLE_DOWN (OSGCanvas::OnMouseDown)
EVT_RIGHT_DOWN (OSGCanvas::OnMouseDown)
EVT_LEFT_UP (OSGCanvas::OnMouseUp)
EVT_MIDDLE_UP (OSGCanvas::OnMouseUp)
EVT_RIGHT_UP (OSGCanvas::OnMouseUp)
EVT_MOTION (OSGCanvas::OnMouseMotion)
EVT_MOUSEWHEEL (OSGCanvas::OnMouseWheel)
END_EVENT_TABLE()
OSGCanvas::OSGCanvas(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size, long style, const wxString& name, int *attributes)
: wxGLCanvas(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name, attributes)
{
// default cursor to standard
_oldCursor = *wxSTANDARD_CURSOR;
}
OSGCanvas::~OSGCanvas()
{
}
void OSGCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
{
/* must always be here */
wxPaintDC dc(this);
}
void OSGCanvas::OnSize(wxSizeEvent& event)
{
// this is also necessary to update the context on some platforms
wxGLCanvas::OnSize(event);
// set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
int width, height;
GetClientSize(&width, &height);
if (_graphics_window.valid())
{
// update the window dimensions, in case the window has been resized.
_graphics_window->getEventQueue()->windowResize(0, 0, width, height);
_graphics_window->resized(0,0,width,height);
}
}
void OSGCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
/* Do nothing, to avoid flashing on MSW */
}
void OSGCanvas::OnChar(wxKeyEvent &event)
{
#if wxUSE_UNICODE
int key = event.GetUnicodeKey();
#else
int key = event.GetKeyCode();
#endif
if (_graphics_window.valid())
_graphics_window->getEventQueue()->keyPress(key);
// If this key event is not processed here, we should call
// event.Skip() to allow processing to continue.
}
void OSGCanvas::OnKeyUp(wxKeyEvent &event)
{
#if wxUSE_UNICODE
int key = event.GetUnicodeKey();
#else
int key = event.GetKeyCode();
#endif
if (_graphics_window.valid())
_graphics_window->getEventQueue()->keyRelease(key);
// If this key event is not processed here, we should call
// event.Skip() to allow processing to continue.
}
void OSGCanvas::OnMouseEnter(wxMouseEvent &event)
{
// Set focus to ourselves, so keyboard events get directed to us
SetFocus();
}
void OSGCanvas::OnMouseDown(wxMouseEvent &event)
{
if (_graphics_window.valid())
{
_graphics_window->getEventQueue()->mouseButtonPress(event.GetX(), event.GetY(),
event.GetButton());
}
}
void OSGCanvas::OnMouseUp(wxMouseEvent &event)
{
if (_graphics_window.valid())
{
_graphics_window->getEventQueue()->mouseButtonRelease(event.GetX(), event.GetY(),
event.GetButton());
}
}
void OSGCanvas::OnMouseMotion(wxMouseEvent &event)
{
if (_graphics_window.valid())
_graphics_window->getEventQueue()->mouseMotion(event.GetX(), event.GetY());
}
void OSGCanvas::OnMouseWheel(wxMouseEvent &event)
{
int delta = event.GetWheelRotation() / event.GetWheelDelta() * event.GetLinesPerAction();
if (_graphics_window.valid()) {
_graphics_window->getEventQueue()->mouseScroll(
delta>0 ?
osgGA::GUIEventAdapter::SCROLL_UP :
osgGA::GUIEventAdapter::SCROLL_DOWN);
}
}
void OSGCanvas::UseCursor(bool value)
{
if (value)
{
// show the old cursor
SetCursor(_oldCursor);
}
else
{
// remember the old cursor
_oldCursor = GetCursor();
// hide the cursor
// - can't find a way to do this neatly, so create a 1x1, transparent image
wxImage image(1,1);
image.SetMask(true);
image.SetMaskColour(0, 0, 0);
wxCursor cursor(image);
SetCursor(cursor);
// On wxGTK, only works as of version 2.7.0
// (http://trac.wxwidgets.org/ticket/2946)
// SetCursor( wxStockCursor( wxCURSOR_BLANK ) );
}
}
GraphicsWindowWX::GraphicsWindowWX(OSGCanvas *canvas)
{
_canvas = canvas;
_traits = new GraphicsContext::Traits;
wxPoint pos = _canvas->GetPosition();
wxSize size = _canvas->GetSize();
_traits->x = pos.x;
_traits->y = pos.y;
_traits->width = size.x;
_traits->height = size.y;
init();
}
GraphicsWindowWX::~GraphicsWindowWX()
{
}
void GraphicsWindowWX::init()
{
if (valid())
{
setState( new osg::State );
getState()->setGraphicsContext(this);
if (_traits.valid() && _traits->sharedContext)
{
getState()->setContextID( _traits->sharedContext->getState()->getContextID() );
incrementContextIDUsageCount( getState()->getContextID() );
}
else
{
getState()->setContextID( osg::GraphicsContext::createNewContextID() );
}
}
}
void GraphicsWindowWX::grabFocus()
{
// focus the canvas
//_canvas->SetFocus();
}
void GraphicsWindowWX::grabFocusIfPointerInWindow()
{
// focus this window, if the pointer is in the window
/* wxPoint pos = wxGetMousePosition();
if (wxFindWindowAtPoint(pos) == _canvas)
_canvas->SetFocus();*/
}
void GraphicsWindowWX::useCursor(bool cursorOn)
{
_canvas->UseCursor(cursorOn);
}
bool GraphicsWindowWX::makeCurrentImplementation()
{
_canvas->SetCurrent();
return true;
}
void GraphicsWindowWX::swapBuffersImplementation()
{
_canvas->SwapBuffers();
}
Filename: wxOsgHello.h
#ifndef _WXSIMPLEVIEWERWX_H_
#define _WXSIMPLEVIEWERWX_H_
#include "wx/defs.h"
#include "wx/app.h"
#include "wx/cursor.h"
#include "wx/glcanvas.h"
#include <osgViewer/Viewer>
#include <string>
class GraphicsWindowWX;
class OSGCanvas : public wxGLCanvas
{
public:
OSGCanvas(wxWindow *parent, wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, long style = 0,
const wxString& name = wxT("TestGLCanvas"),
int *attributes = 0);
virtual ~OSGCanvas();
void SetGraphicsWindow(osgViewer::GraphicsWindow *gw) { _graphics_window = gw; }
void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event);
void OnEraseBackground(wxEraseEvent& event);
void OnChar(wxKeyEvent &event);
void OnKeyUp(wxKeyEvent &event);
void OnMouseEnter(wxMouseEvent &event);
void OnMouseDown(wxMouseEvent &event);
void OnMouseUp(wxMouseEvent &event);
void OnMouseMotion(wxMouseEvent &event);
void OnMouseWheel(wxMouseEvent &event);
void UseCursor(bool value);
private:
DECLARE_EVENT_TABLE()
osg::ref_ptr<osgViewer::GraphicsWindow> _graphics_window;
wxCursor _oldCursor;
};
class GraphicsWindowWX : public osgViewer::GraphicsWindow
{
public:
GraphicsWindowWX(OSGCanvas *canvas);
~GraphicsWindowWX();
void init();
//
// GraphicsWindow interface
//
void grabFocus();
void grabFocusIfPointerInWindow();
void useCursor(bool cursorOn);
bool makeCurrentImplementation();
void swapBuffersImplementation();
// not implemented yet...just use dummy implementation to get working.
virtual bool valid() const { return true; }
virtual bool realizeImplementation() { return true; }
virtual bool isRealizedImplementation() const { return _canvas->IsShownOnScreen(); }
virtual void closeImplementation() {}
virtual bool releaseContextImplementation() { return true; }
private:
// XXX need to set _canvas to NULL when the canvas is deleted by
// its parent. for this, need to add event handler in OSGCanvas
OSGCanvas* _canvas;
};
class MainFrame : public wxFrame
{
public:
MainFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
const wxSize& size, long style = wxDEFAULT_FRAME_STYLE);
void SetViewer(osgViewer::Viewer *viewer);
void OnIdle(wxIdleEvent& event);
private:
osg::ref_ptr<osgViewer::Viewer> _viewer;
DECLARE_EVENT_TABLE()
};
/* Define a new application type */
class wxOsgApp : public wxApp
{
public:
bool OnInit();
};
#endif // _WXSIMPLEVIEWERWX_H_
Project Configuration
Under Visual Studio 2010, open your project properties
Tab Debugging:
Command Arguments:
E:/osg/OpenSceneGraph_Data/dumptruck.osg
Tab C/C++:
Additional Include Directories:
E:\osg\3rdParty-x64-Release\include;E:\osg\3rdParty-x64-Release\lib\mswu
Preprocessor:
WIN32;NDEBUG;__WXMSW__;_WINDOWS;_WINSOCKAPI_
Tab Linker:
Additional Libraries Directories:
E:\osg\3rdParty-x64-Release\lib\
Input:
opengl32.lib;OpenThreads.lib;osg.lib;osgDB.lib;osgUtil.lib;osgGA.lib;osgFX.lib;osgViewer.lib;osgText.lib;osgManipulator.lib;osgSim.lib;osgParticle.lib;osgShadow.lib;wxtiff.lib;wxjpeg.lib;wxpng.lib;wxzlib.lib;wxexpat.lib;wxregexu.lib;wxbase28u.lib;wxmsw28u_core.lib;wxmsw28u_adv.lib;wxcode_msw28u_propgrid.lib;wxbase28u_xml.lib;wxmsw28u_xrc.lib;wxbase28u_net.lib;wxmsw28u_aui.lib;wxmsw28u_gl.lib;wxmsw28u_html.lib;wxmsw28u_media.lib;wxmsw28u_qa.lib;
Compile and run, if you are successfully then you will get result as below
Other Topics:
How to build NGINX RTMP module, Setup Live Streaming with NGINX RTMP module, Publishing Stream with Open Broadcaster Software (OBS), Create Adaptive Streaming with NGINX RTMP, Implementing Filtergraph in Streaming with NGINX RTMP, How to Implement Running Text in Streaming with NGINX RTMP, How to build OpenSceneGraph with Code::Blocks, How to build OpenSceneGraph with Visual Studio 2010, Building Geometry Model, How to run OpenSceneGraph with Netbean IDE 8.2 C++, Rendering Basic Shapes, Using OSG Node to Load 3D Object Model, Rendering 3D Simulator with OpenSceneGraph, How to compile wxWidgets with Visual Studio 2010, How to Setup Debugging in Golang with Visual Code, How to Load 3D Object Model with OpenSceneGraph on wxWidgets
great
ReplyDeleteThank you
Delete