git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@51630 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			324 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			324 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/////////////////////////////////////////////////////////////////////////////
 | 
						|
// Name:        penguin.cpp
 | 
						|
// Purpose:     wxGLCanvas demo program
 | 
						|
// Author:      Robert Roebling
 | 
						|
// Modified by: Sandro Sigala
 | 
						|
// Created:     04/01/98
 | 
						|
// RCS-ID:      $Id$
 | 
						|
// Copyright:   (c) Robert Roebling
 | 
						|
// Licence:     wxWindows licence
 | 
						|
/////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// 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
 | 
						|
 | 
						|
#if !wxUSE_GLCANVAS
 | 
						|
    #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
 | 
						|
#endif
 | 
						|
 | 
						|
#include "penguin.h"
 | 
						|
#ifdef __DARWIN__
 | 
						|
    #include <OpenGL/glu.h>
 | 
						|
#else
 | 
						|
    #include <GL/glu.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "../../sample.xpm"
 | 
						|
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
// MyApp
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
 | 
						|
// `Main program' equivalent, creating windows and returning main app frame
 | 
						|
bool MyApp::OnInit()
 | 
						|
{
 | 
						|
    if ( !wxApp::OnInit() )
 | 
						|
        return false;
 | 
						|
 | 
						|
    // Create the main frame window
 | 
						|
    MyFrame *frame = new MyFrame(NULL, wxT("wxWidgets Penguin Sample"),
 | 
						|
        wxDefaultPosition, wxDefaultSize);
 | 
						|
 | 
						|
#if wxUSE_ZLIB
 | 
						|
    if (wxFileExists(wxT("penguin.dxf.gz")))
 | 
						|
        frame->GetCanvas()->LoadDXF(wxT("penguin.dxf.gz"));
 | 
						|
#else
 | 
						|
    if (wxFileExists(wxT("penguin.dxf")))
 | 
						|
        frame->GetCanvas()->LoadDXF(wxT("penguin.dxf"));
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Show the frame */
 | 
						|
    frame->Show(true);
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
IMPLEMENT_APP(MyApp)
 | 
						|
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
// MyFrame
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
 | 
						|
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
 | 
						|
    EVT_MENU(wxID_OPEN, MyFrame::OnMenuFileOpen)
 | 
						|
    EVT_MENU(wxID_EXIT, MyFrame::OnMenuFileExit)
 | 
						|
    EVT_MENU(wxID_HELP, MyFrame::OnMenuHelpAbout)
 | 
						|
END_EVENT_TABLE()
 | 
						|
 | 
						|
// MyFrame constructor
 | 
						|
MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
 | 
						|
    const wxSize& size, long style)
 | 
						|
    : wxFrame(frame, wxID_ANY, title, pos, size, style)
 | 
						|
{
 | 
						|
    SetIcon(wxIcon(sample_xpm));
 | 
						|
 | 
						|
    // Make the "File" menu
 | 
						|
    wxMenu *fileMenu = new wxMenu;
 | 
						|
    fileMenu->Append(wxID_OPEN, wxT("&Open..."));
 | 
						|
    fileMenu->AppendSeparator();
 | 
						|
    fileMenu->Append(wxID_EXIT, wxT("E&xit\tALT-X"));
 | 
						|
    // Make the "Help" menu
 | 
						|
    wxMenu *helpMenu = new wxMenu;
 | 
						|
    helpMenu->Append(wxID_HELP, wxT("&About..."));
 | 
						|
 | 
						|
    wxMenuBar *menuBar = new wxMenuBar;
 | 
						|
    menuBar->Append(fileMenu, wxT("&File"));
 | 
						|
    menuBar->Append(helpMenu, wxT("&Help"));
 | 
						|
    SetMenuBar(menuBar);
 | 
						|
 | 
						|
    Show(true);
 | 
						|
 | 
						|
    m_canvas = new TestGLCanvas(this, wxID_ANY, wxDefaultPosition,
 | 
						|
        GetClientSize(), wxSUNKEN_BORDER);
 | 
						|
}
 | 
						|
 | 
						|
// File|Open... command
 | 
						|
void MyFrame::OnMenuFileOpen( wxCommandEvent& WXUNUSED(event) )
 | 
						|
{
 | 
						|
    wxString filename = wxFileSelector(wxT("Choose DXF Model"), wxT(""), wxT(""), wxT(""),
 | 
						|
#if wxUSE_ZLIB
 | 
						|
        wxT("DXF Drawing (*.dxf;*.dxf.gz)|*.dxf;*.dxf.gz|All files (*.*)|*.*"),
 | 
						|
#else
 | 
						|
        wxT("DXF Drawing (*.dxf)|*.dxf)|All files (*.*)|*.*"),
 | 
						|
#endif
 | 
						|
        wxFD_OPEN);
 | 
						|
    if (!filename.IsEmpty())
 | 
						|
    {
 | 
						|
        m_canvas->LoadDXF(filename);
 | 
						|
        m_canvas->Refresh(false);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// File|Exit command
 | 
						|
void MyFrame::OnMenuFileExit( wxCommandEvent& WXUNUSED(event) )
 | 
						|
{
 | 
						|
    // true is to force the frame to close
 | 
						|
    Close(true);
 | 
						|
}
 | 
						|
 | 
						|
// Help|About... command
 | 
						|
void MyFrame::OnMenuHelpAbout( wxCommandEvent& WXUNUSED(event) )
 | 
						|
{
 | 
						|
    wxMessageBox(wxT("OpenGL Penguin Sample (c) Robert Roebling, Sandro Sigala et al"));
 | 
						|
}
 | 
						|
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
// TestGLCanvas
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
 | 
						|
BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
 | 
						|
    EVT_SIZE(TestGLCanvas::OnSize)
 | 
						|
    EVT_PAINT(TestGLCanvas::OnPaint)
 | 
						|
    EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
 | 
						|
    EVT_MOUSE_EVENTS(TestGLCanvas::OnMouse)
 | 
						|
END_EVENT_TABLE()
 | 
						|
 | 
						|
TestGLCanvas::TestGLCanvas(wxWindow *parent,
 | 
						|
                           wxWindowID id,
 | 
						|
                           const wxPoint& pos,
 | 
						|
                           const wxSize& size,
 | 
						|
                           long style,
 | 
						|
                           const wxString& name)
 | 
						|
    : wxGLCanvas(parent, id, NULL, pos, size,
 | 
						|
                 style | wxFULL_REPAINT_ON_RESIZE, name)
 | 
						|
{
 | 
						|
    // Explicitly create a new rendering context instance for this canvas.
 | 
						|
    m_glRC = new wxGLContext(this);
 | 
						|
 | 
						|
    // Make the new context current (activate it for use) with this canvas.
 | 
						|
    SetCurrent(*m_glRC);
 | 
						|
 | 
						|
    m_gldata.initialized = false;
 | 
						|
 | 
						|
    // initialize view matrix
 | 
						|
    m_gldata.beginx = 0.0f;
 | 
						|
    m_gldata.beginy = 0.0f;
 | 
						|
    m_gldata.zoom   = 45.0f;
 | 
						|
    trackball(m_gldata.quat, 0.0f, 0.0f, 0.0f, 0.0f);
 | 
						|
}
 | 
						|
 | 
						|
TestGLCanvas::~TestGLCanvas()
 | 
						|
{
 | 
						|
    delete m_glRC;
 | 
						|
}
 | 
						|
 | 
						|
void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
 | 
						|
{
 | 
						|
    // must always be here
 | 
						|
    wxPaintDC dc(this);
 | 
						|
 | 
						|
    SetCurrent(*m_glRC);
 | 
						|
 | 
						|
    // Initialize OpenGL
 | 
						|
    if (!m_gldata.initialized)
 | 
						|
    {
 | 
						|
        InitGL();
 | 
						|
        ResetProjectionMode();
 | 
						|
        m_gldata.initialized = true;
 | 
						|
    }
 | 
						|
 | 
						|
    // Clear
 | 
						|
    glClearColor( 0.3f, 0.4f, 0.6f, 1.0f );
 | 
						|
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 | 
						|
 | 
						|
    // Transformations
 | 
						|
    glLoadIdentity();
 | 
						|
    glTranslatef( 0.0f, 0.0f, -20.0f );
 | 
						|
    GLfloat m[4][4];
 | 
						|
    build_rotmatrix( m, m_gldata.quat );
 | 
						|
    glMultMatrixf( &m[0][0] );
 | 
						|
 | 
						|
    m_renderer.Render();
 | 
						|
 | 
						|
    // Flush
 | 
						|
    glFlush();
 | 
						|
 | 
						|
    // Swap
 | 
						|
    SwapBuffers();
 | 
						|
}
 | 
						|
 | 
						|
void TestGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
 | 
						|
{
 | 
						|
    // Reset the OpenGL view aspect.
 | 
						|
    // This is OK only because there is only one canvas that uses the context.
 | 
						|
    // See the cube sample for that case that multiple canvases are made current with one context.
 | 
						|
    ResetProjectionMode();
 | 
						|
}
 | 
						|
 | 
						|
void TestGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
 | 
						|
{
 | 
						|
    // Do nothing, to avoid flashing on MSW
 | 
						|
}
 | 
						|
 | 
						|
// Load the DXF file.  If the zlib support is compiled in wxWidgets,
 | 
						|
// supports also the ".dxf.gz" gzip compressed files.
 | 
						|
void TestGLCanvas::LoadDXF(const wxString& filename)
 | 
						|
{
 | 
						|
    wxFileInputStream stream(filename);
 | 
						|
    if (stream.Ok())
 | 
						|
#if wxUSE_ZLIB
 | 
						|
    {
 | 
						|
        if (filename.Right(3).Lower() == wxT(".gz"))
 | 
						|
        {
 | 
						|
            wxZlibInputStream zstream(stream);
 | 
						|
            m_renderer.Load(zstream);
 | 
						|
        } else
 | 
						|
        {
 | 
						|
            m_renderer.Load(stream);
 | 
						|
        }
 | 
						|
    }
 | 
						|
#else
 | 
						|
    {
 | 
						|
        m_renderer.Load(stream);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void TestGLCanvas::OnMouse(wxMouseEvent& event)
 | 
						|
{
 | 
						|
    if (event.Dragging())
 | 
						|
    {
 | 
						|
        wxSize sz(GetClientSize());
 | 
						|
 | 
						|
        /* drag in progress, simulate trackball */
 | 
						|
        float spin_quat[4];
 | 
						|
        trackball(spin_quat,
 | 
						|
            (2.0*m_gldata.beginx - sz.x) / sz.x,
 | 
						|
            (sz.y - 2.0*m_gldata.beginy) / sz.y,
 | 
						|
            (2.0*event.GetX() - sz.x)    / sz.x,
 | 
						|
            (sz.y - 2.0*event.GetY())    / sz.y);
 | 
						|
 | 
						|
        add_quats(spin_quat, m_gldata.quat, m_gldata.quat);
 | 
						|
 | 
						|
        /* orientation has changed, redraw mesh */
 | 
						|
        Refresh(false);
 | 
						|
    }
 | 
						|
 | 
						|
    m_gldata.beginx = event.GetX();
 | 
						|
    m_gldata.beginy = event.GetY();
 | 
						|
}
 | 
						|
 | 
						|
void TestGLCanvas::InitGL()
 | 
						|
{
 | 
						|
    static const GLfloat light0_pos[4]   = { -50.0f, 50.0f, 0.0f, 0.0f };
 | 
						|
 | 
						|
    // white light
 | 
						|
    static const GLfloat light0_color[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
 | 
						|
 | 
						|
    static const GLfloat light1_pos[4]   = {  50.0f, 50.0f, 0.0f, 0.0f };
 | 
						|
 | 
						|
    // cold blue light
 | 
						|
    static const GLfloat light1_color[4] = { 0.4f, 0.4f, 1.0f, 1.0f };
 | 
						|
 | 
						|
    /* remove back faces */
 | 
						|
    glDisable(GL_CULL_FACE);
 | 
						|
    glEnable(GL_DEPTH_TEST);
 | 
						|
 | 
						|
    /* speedups */
 | 
						|
    glEnable(GL_DITHER);
 | 
						|
    glShadeModel(GL_SMOOTH);
 | 
						|
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
 | 
						|
    glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
 | 
						|
 | 
						|
    /* light */
 | 
						|
    glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
 | 
						|
    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light0_color);
 | 
						|
    glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
 | 
						|
    glLightfv(GL_LIGHT1, GL_DIFFUSE,  light1_color);
 | 
						|
    glEnable(GL_LIGHT0);
 | 
						|
    glEnable(GL_LIGHT1);
 | 
						|
    glEnable(GL_LIGHTING);
 | 
						|
 | 
						|
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
 | 
						|
    glEnable(GL_COLOR_MATERIAL);
 | 
						|
}
 | 
						|
 | 
						|
void TestGLCanvas::ResetProjectionMode()
 | 
						|
{
 | 
						|
    // This is normally only necessary if there is more than one wxGLCanvas
 | 
						|
    // or more than one wxGLContext in the application.
 | 
						|
    SetCurrent(*m_glRC);
 | 
						|
 | 
						|
    int w, h;
 | 
						|
    GetClientSize(&w, &h);
 | 
						|
 | 
						|
    // It's up to the application code to update the OpenGL viewport settings.
 | 
						|
    // In order to avoid extensive context switching, consider doing this in
 | 
						|
    // OnPaint() rather than here, though.
 | 
						|
    glViewport(0, 0, (GLint) w, (GLint) h);
 | 
						|
 | 
						|
    glMatrixMode(GL_PROJECTION);
 | 
						|
    glLoadIdentity();
 | 
						|
    gluPerspective(45.0f, (GLfloat)w/h, 1.0, 100.0);
 | 
						|
    glMatrixMode(GL_MODELVIEW);
 | 
						|
    glLoadIdentity();
 | 
						|
}
 |