jonsmith1982 has asked for the wisdom of the Perl Monks concerning the following question:

Sorry if this is a repost, but after 10 mins of waiting my first post didnt turn up...

Bellow is a script i have been messing around with that uses OpenGL, i have got to a point where i want to be able to zoom in on a certain position on the display and only display what can be seen within the window/screen.

at present it zooms in/out and scales/crops its self but it only zooms in/out to the top left corner.

Could you please give me some suggestions on the best way to go about this.

#! /usr/bin/perl -w use strict; use OpenGL qw(:all); use OpenGL::Image; use Time::HiRes qw( gettimeofday ); use constant ESCAPE => 27; use constant FRAME_RATE_SAMPLES => 60; my ($width, $height) = (640,480); my ($FrameCount, $FrameRate, $last) = (0, 0, 0); my ($now, $window) = (gettimeofday(), ); my ($Depth,$Top,$Bot,$Width) = (3.0,0.0,0.0,0.0); DepthCalc(); my @hours = (13..24); my @channels = (1..25); sub InitGL { glClearColor(0.0, 0.0, 0.0, 1.0); glClearDepth(1.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_SMOOTH); glMatrixMode(GL_PROJECTION); glLoadIdentity; gluPerspective(90.0, $width/$height, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); } sub ReSizeGLScene { ($width, $height) = @_; if ($width < 640) {$width = 640;} if ($height < 480) {$height = 480;} glViewport(0, 0, $width, $height); glMatrixMode(GL_PROJECTION); glLoadIdentity; gluPerspective(90.0, $width/$height, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); DepthCalc(); } sub DepthCalc { $Top = $Depth-($Depth / 7.5); $Bot = $Depth-($Depth / 7.5); $Width = (($width/$height)*$Depth)-($Depth / 100); return 1; } sub keyPressed { my ($key, $x, $y) = @_; if ($key == ord('q')) {glutDestroyWindow($window);exit(0);} elsif ($key == ESCAPE) {glutDestroyWindow($window);exit(0);} else {} } sub DrawGLScene { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); $FrameCount++; if ($FrameCount == FRAME_RATE_SAMPLES / 2) {FPS_calc();} elsif ($FrameCount == 0) {FPS_calc();} elsif ($FrameCount == FRAME_RATE_SAMPLES) {$FrameCount = 0;} glLoadIdentity(); glTranslatef(0.0, 0.0,-2.075); glColor4f(1.0,1.0,1.0,0.7); my $buf = sprintf("FPS: %f D: %2d F: %2d",$FrameRate,$Depth,$FrameCo +unt); glRasterPos2i(-1.8,-2.5); ourPrintString(GLUT_BITMAP_TIMES_ROMAN_24, +$buf); glLoadIdentity(); glTranslatef(0.0, 0.0,-($Depth+0.1)); glBegin(GL_QUADS); glColor4f(0.0,0.0,0.0,0.7); glVertex3f( $Width, $Depth, 0.0); glVertex3f( $Width, $Depth-($Depth/7.5), 0.0); glVertex3f(-$Width, $Depth-($Depth/7.5), 0.0); glVertex3f(-$Width, $Depth, 0.0); glEnd; my ($left_width, $right_width) = (-($Width-0.05), -($Width-5.95)); glLoadIdentity(); glTranslatef(0.0, 0.0,-($Depth)); glBegin(GL_QUADS); glColor4f(1.0,1.0,1.0,0.7); foreach my $hour (@hours) { my ($top_half, $bot_half) = ($Top-0.05, ($Top-4.0)); my $width_repl = $right_width; if ($right_width >= $Width) {$width_repl = ($Width-0.05);} foreach my $channel (@channels) { my $bot_repl = $bot_half; if ($bot_half <= -$Bot) {$bot_repl = -($Bot-0.05);} glVertex3f($left_width , $top_half , 0.0); glVertex3f($left_width , $bot_repl, 0.0); glVertex3f($width_repl, $bot_repl, 0.0); glVertex3f($width_repl, $top_half , 0.0); last if ($bot_half <= -$Bot); $top_half -= 4.0; $bot_half -= 4.0; } last if ($right_width >= $Width); $right_width += 5.95; $left_width += 5.95; } glEnd; glColor4f(1.0,1.0,0.8,1.0); glBegin(GL_QUADS); glVertex3f( $Width, $Top, 0.0); glVertex3f( $Width,-$Bot, 0.0); glVertex3f(-$Width,-$Bot, 0.0); glVertex3f(-$Width, $Top, 0.0); glEnd; glutSwapBuffers; } sub ourPrintString { my ($font, $str) = @_; my @c = split '', $str; for(@c) { glutBitmapCharacter($font, ord $_); } } sub FPS_calc { $now = gettimeofday(); my $delta = ($now - $last); $last = $now; $FrameRate = FRAME_RATE_SAMPLES / ($delta or 1); $FrameRate = substr($FrameRate, 0, 11); } sub MousePressed { my ($button, $state, $x, $y) = @_; return if ($state == 1); $Depth-- and DepthCalc() and return if ($button == 3 and $state == 0 + and !($Depth <= 2)); $Depth++ and DepthCalc() and return if ($button == 4 and $state == 0 + and !($Depth >= 27)); print (join(" ",@_)."\n"); #print $width." ".$height." ".$Width."/".$Depth. #"=".$Width / $Depth."\n" if $state == 0; } glutInit; glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize($width, $height); $window = glutCreateWindow("OpenGL Project"); glutReshapeFunc(\&ReSizeGLScene); glutDisplayFunc(\&DrawGLScene); glutIdleFunc(\&DrawGLScene); glutKeyboardFunc(\&keyPressed); glutMouseFunc(\&MousePressed); InitGL(); glutMainLoop(); return 1;

Replies are listed 'Best First'.
Re: POGL Zooming to a certain point
by chromatic (Archbishop) on Apr 18, 2008 at 21:43 UTC

    Assuming you want to move the camera (and you probably do), you need to make some sort of glTranslate() call to move the camera into the scene while leaving all of the other objects at fixed locations and orientations relative to the origin. If the camera appears to move toward the upper left (and it does for me), you probably need to move the camera along the X and Y axes as well -- I suspect you're drawing in the fourth quadrant, where the origin is at the upper left of your image.

      i dont want to move the camera, i want to move the background and only draw what would be visible by the camera.

      what i was thinking is...

      add feature for cropping left and top (to stop drawing of any excess OGL code) - right and bottom cropping already present
      find an equation to figure out each blocks x,y boundaries
      take mouses x,y and center using $Width

        Your other option then is to use glViewport() to change the viewport. This may be easier than changing the camera position. You should be able to rely on OpenGL doing any culling for you, so you don't have to do the math to figure out which blocks to display.