hello
thanks kevin for the opengl example.
i have used his example to display a triangle which can be rotated in a 3D
space using the up down left right keys.
also added a button and a textbox, i have 2 question:
1- i can rotate the triangle by keys, until i click on the button to display
some text in the textbox, why is this behaviour, and how i can restore the
triangle rotating after clicking the button.
2- is it possible to make the opengl window smaller than the win32gui window
!!
best wishes
attached below the code, and for your convenience from here:
http://rapidshare.com/files/254072142/triangle.rar
peter
use strict;
use warnings;
#these constants are needed for SetPixelFormat() but aren't defined in
Win32::GUI
use constant {
PFD_TYPE_RGBA => 0,
PFD_DOUBLEBUFFER => 0x00000001,
PFD_DRAW_TO_WINDOW => 0x00000004,
PFD_SUPPORT_OPENGL => 0x00000020,
PFD_MAIN_PLANE => 0,
};
use OpenGL qw(:glfunctions :glconstants :glufunctions);
#use OpenGL qw(:all);
use Win32::API;
use Win32::GUI qw();
use Win32::GUI::Carp qw(warningsToDialog fatalsToDialog immediateWarnings
winwarn windie);
use Win32::GUI::Constants qw(IDI_APPLICATION WS_CLIPCHILDREN
WS_CLIPSIBLINGS
WM_CREATE WM_SIZE WM_CLOSE VK_ESCAPE CW_USEDEFAULT MB_OK
MB_ICONEXCLAMATION);
my $g_HDC; #global handle to device context
my $hRC; #handle to rendering context
my $rtri = 0.0;
my $xrot = 0;
my $yrot = 0;
#define PIXELFORMATDESCRIPTOR struct used for the SetPixelFormat function
#refer to the Windows SDK documentation for more info about this structure
Win32::API::Struct->typedef(
PIXELFORMATDESCRIPTOR => qw(
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
DWORD dwLayerMask;
DWORD dwVisibleMask;
DWORD dwDamageMask;
)
);
#needed for the wglMakeCurrent functions
Win32::API::Type->typedef('HGLRC', 'HANDLE');
#import some extra functions
#more info can be found in the Windows SDK documentation
#exchanges the front and back buffers of the current pixel format
Win32::API->Import('gdi32', 'BOOL SwapBuffers(HDC hdc);')
or windie "Win32::API->Import(SwapBuffers): $^E";
#attempts to match an appropriate pixel format supported by a device context
to
# a given pixel format specification.
Win32::API->Import('gdi32', 'int ChoosePixelFormat(HDC hdc,
PIXELFORMATDESCRIPTOR * ppfd);')
or windie "Win32::API->Import(ChoosePixelFormat): $^E";
#sets the pixel format of the specified device context to the format
specified
# by the iPixelFormat index returned from ChoosePixelFormat().
Win32::API->Import('gdi32', 'BOOL SetPixelFormat(HDC hdc, int
iPixelFormat, PIXELFORMATDESCRIPTOR * ppfd);')
or windie "Win32::API->Import(SetPixelFormat): $^E";
#creates a new OpenGL rendering context, which is suitable for drawing on
the
# device referenced by hdc.
Win32::API->Import('opengl32', 'HGLRC wglCreateContext(HDC hdc);')
or windie "Win32::API->Import(wglCreateContext): $^E";
#makes a specified OpenGL rendering context the calling thread's current
# rendering context.
Win32::API->Import('opengl32', 'BOOL wglMakeCurrent(HDC hdc, HGLRC
hglrc);')
or windie "Win32::API->Import(wglMakeCurrent): $^E";
#deletes a specified OpenGL rendering context.
Win32::API->Import('opengl32', 'BOOL wglDeleteContext(HGLRC hglrc);')
or windie "Win32::API->Import(wglDeleteContext): $^E";
#create main window
my $main = Win32::GUI::Window->new(
-name => "main",
-text => "OpenGL Example: Colour Cube",
-size => [640,480],
-left => CW_USEDEFAULT, #let system position window
-pushstyle =>
#Excludes the area occupied by child windows when drawing occurs
# within the parent window.
WS_CLIPCHILDREN |
#When a particular child window needs to be painted, all other overlapping
# child windows are clipped out of the region of the child window to be
updated.
WS_CLIPSIBLINGS,
-onTerminate => sub { #WM_CLOSE
wglMakeCurrent($g_HDC->Handle(), 0); #deselect rendering context from $hDC
wglDeleteContext($hRC); #delete rendering context $hRC
return -1; #exit main loop
},
-onResize => sub { #WM_SIZE
my $self = shift;
return 0 unless $self;
my $height = $self->Height(); #get height and width
my $width = $self->Width();
$height = 1 if $height == 0; #don't divide by 0
glViewport(0,0,$width,$height); #set viewport to new dimensions
glMatrixMode(GL_PROJECTION); #set matrix mode to projection matrix
glLoadIdentity(); #reset projection matrix
gluPerspective(54.0, $width / $height, 1.0, 1000.0); #calculate aspect
ratio of window
glMatrixMode(GL_MODELVIEW); #set modelview matrix
glLoadIdentity(); #reset modelview matrix
return 1;
},
-onKeyDown => sub { #WM_KEYDOWN
my ($self, $flags, $key) = @_;
return -1 if $key == VK_ESCAPE; #exit if escape key pressed
if ($key == 37) {
$yrot -= 3.0;
} elsif ($key == 39) {
$yrot += 3.0;
} elsif ($key == 38) {
$xrot += 3.0;
} elsif ($key == 40) {
$xrot -= 3.0;
}
else {
return;
}
#glutPostRedisplay();
return 1;
},
);
$main->AddButton(
-text => "Run",
-name => "Button1",
-left => 23,
-top => 10,
-width => 56,
-height => 36,
-foreground => 0,
);
my $textfield = $main->AddTextfield(
-text => "",
-name => "Textfield_1",
-left => 120,
-top => 10,
-width => 150,
-height => 100,
-multiline => 1,
-vscroll => 1,
);
unless($main){
windie("Cannot create window: $^E");
}
$main->SetIcon(Win32::GUI::Icon->new(IDI_APPLICATION)); #set window icon
#WM_CREATE
$g_HDC = $main->GetDC(); #set global device context to device context of
main window
unless(SetupPixelFormat($g_HDC->Handle())){ #setup pixel format for
device context
exit 1; #exit if setup fails
}
$hRC = wglCreateContext($g_HDC->Handle()); #create rendering context used
by OpenGL to draw
wglMakeCurrent($g_HDC->Handle(), $hRC); #select rendering context $hRC
into $g_HDC
#Initialize OpenGL
#my ($width, $height) = (300,200);
glClearColor(0.0, 0.0, 0.0, 0.0);
# Enables clearing of the Depth buffer
glClearDepth(1.0);
# The type of depth test to do
glDepthFunc(GL_LESS);
# Enables depth testing with that type
glEnable(GL_DEPTH_TEST);
# Enables smooth color shading
glShadeModel(GL_SMOOTH);
# Reset the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
# Calculate the aspect ratio of the Window
#gluPerspective(45.0, $width/$height, 0.1, 100.0);
# Reset the modelview matrix
$main->Show(); #show window
while(Win32::GUI::DoEvents() != -1){
Render();
}
#This function is used to set the pixel format for the device context.
# Accepts a handle to the device context of the window and returns true if
succeeds
# or false if fails.
#Adapted from code from OpenGL Game Programming (Premier Press, 2004)
sub SetupPixelFormat {
my $hDC = shift; #is a handle to DC
my $nPixelFormat;
my $pfd = Win32::API::Struct->new('PIXELFORMATDESCRIPTOR'); #create new
structure
$pfd->{nSize} = $pfd->sizeof(); #return sizeof structure
$pfd->{nVersion} = 1; #default version
$pfd->{dwFlags} = PFD_DRAW_TO_WINDOW | #window drawing support
PFD_SUPPORT_OPENGL | #OpenGL support
PFD_DOUBLEBUFFER; #double buffering support
$pfd->{iPixelType} = PFD_TYPE_RGBA; #rgba colour mode
$pfd->{cColorBits} = 32; #32 bit colour mode
$pfd->{cRedBits} = 0; #ignore colour bits
$pfd->{cRedShift} = 0; #
$pfd->{cGreenBits} = 0; #
$pfd->{cGreenShift} = 0; #
$pfd->{cBlueBits} = 0; #
$pfd->{cBlueShift} = 0; #
$pfd->{cAlphaBits} = 0; #not alpha buffer
$pfd->{cAlphaShift} = 0; #ignore alpha shift bit
$pfd->{cAccumBits} = 0; #no accumulation buffer
$pfd->{cAccumRedBits} = 0; #ignore accumulation bits
$pfd->{cAccumGreenBits} = 0; #
$pfd->{cAccumBlueBits} = 0; #
$pfd->{cAccumAlphaBits} = 0; #
$pfd->{cDepthBits} = 16; #16 bit z-buffer size
$pfd->{cStencilBits} = 0; #no stencil buffer
$pfd->{cAuxBuffers} = 0; #no auxiliary buffer
$pfd->{iLayerType} = PFD_MAIN_PLANE; #main drawing plane
$pfd->{bReserved} = 0; #reserved
$pfd->{dwLayerMask} = 0; #layer masks ignored
$pfd->{dwVisibleMask} = 0; #
$pfd->{dwDamageMask} = 0; #
# choose best matching pixel format
unless( $nPixelFormat = ChoosePixelFormat($hDC, $pfd) ){
winwarn("Can't find an appropriate pixel format");
return 0;
}
# set pixel format to device context
unless( SetPixelFormat($hDC, $nPixelFormat, $pfd) ){
winwarn("Unable to set pixel format");
return 0;
}
return 1;
}
#This function draws the cube of points. The colour of each point is based
on its position
#Adapted from code from OpenGL Game Programming (Premier Press, 2004)
sub DrawCube {
glRotatef( $yrot, 0.0, 1.0, 0.0 );
glRotatef( $xrot, 1.0, 0.0, 0.0 );
glPushMatrix();
#glBegin(GL_POINTS);
#glRotatef($rtri, 0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex3f( 0.0, 20.0, 0.0); # Top vertex
glColor3f(0.0, 1.0, 0.0); # Set The Color To Green
glVertex3f( 20.0, -20.0, 0.0); # Bottom right vertex
glColor3f(0.0, 0.0, 1.0); # Set The Color To Blue
glVertex3f(-20.0, -20.0, 0.0);
glEnd();
$rtri = $rtri + 3.0;
glPopMatrix();
}
#This function is used to draw the cube and is called every frame
#Adapted from code from OpenGL Game Programming (Premier Press, 2004)
sub Render {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #clear color and depth
buffer
glLoadIdentity(); #replaces the current matrix with the identity matrix.
glTranslatef(0.0, 0.0, -150.0); #move to 0,0,-150
glPushMatrix(); #save current matrix
DrawCube(); #draw cube
glPopMatrix(); #restore matrix
glFlush(); #clear buffers
SwapBuffers($g_HDC->Handle()); #exchange front and back buffers of device
context
}
#Conveniently, the Windows specific functions for setup of OpenGL accept and
return
# handles to windows or contexts, which are just numbers, and the handles to
# these are stored in the Window and DC objects created by Win32::GUI. This
method
# provides an easy access to this value. Placing the method in the
#Win32::GUI::DC
# package allows both Windows and DCs to use it.
sub Button1_Click {
$textfield->Append("OpenGL example : rotating triangle\r\n");
}
package Win32::GUI::DC;
sub Handle {
return shift->{-handle};
}
__END__
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Perl-Win32-GUI-Users mailing list
Perl-Win32-GUI-Users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users
http://perl-win32-gui.sourceforge.net/