When you say "pan" and "zoom", I understand you want to "translate" and "scale".

But do you want to move the camera (GL_PROJECTION matrix) or the world (GL_MODELVIEW matrix)?

To set up the camera. First use glViewport(0, 0, w, h) to define the window limits, then tell OpenGL you are going to modify the camera with glMatrixMode(GL_PROJECTION). Now there are two types of camera: isometric (glOrtho) or perspective (gluPerspective). This functions create a initial GL_PROJECTION matrix for you, but you can apply other transformations by multipying.

Only a perspective camera lets you "zoom" (fov).
You are doing 2D, so probably you should start with isometric.

The code was to show you how a transformation matrix looks like. The matrix is 4x4 = 16 GLdouble.

A matrix transforms the geometry. Let [V] be the geometry.

The identity matrix [I] has no effect:
| 1 0 0 0 |
| 0 1 0 0 | * [V] = [V]
| 0 0 1 0 |
| 0 0 0 1 |
When you call glLoadIdentity, you are setting [I] as the current (GL_MODELVIEW or GL_PROJECTION) matrix. You can multiply the matrix by other matrix to translate, then multiply by other to rotate, and so on.
glMultMatrix([I]) obviously has no effect.

If now you want to translate the geometry to (tx, ty, tz), you need a matrix like this [T]:
|  1  0  0  0 |
|  0  1  0  0 | * [V] = [T] * [V] = [V translated]
|  0  0  1  0 |
| tx ty tz  1 |
Thit is what glTranslate(tx, ty, tx) does, multiply the current matrix by [T]: same as glMultMatrix([T])

glScale(sx, sy, sz) :
| sx  0  0  0 |
|  0 sy  0  0 | = [S]
|  0  0 sz  0 |
|  0  0  0  1 |

glRotate(0, 0, rz):
| cos(rz) -sin(rz) 0  0 |
| sin(rz) cos(rz)  0  0 | = [R]
|    0        0    1  1 |
|    0        0    0  1 |


One matrix [M]=[T]*[S]*[R] can apply translation, rotation and scale to your geometry in one step (one multiplication).
Remember that [T]*[R] is not [R]*[T]


Try this:

# About OpenGL Projections
#---------------------------------
from pyglet import window,image
from pyglet.window import key
from pyglet.gl import *

def opengl_init():
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    glDepthFunc(GL_LEQUAL)

def playground():

    # Test your code here
    glColor4f(1,1,1,1)
    glBegin(GL_LINES)
    glVertex3f(0,0,0)
    glVertex3f(640,480,0)

    glVertex3f(0,480,0)
    glVertex3f(640,0,0)
    glEnd()

class camera():
    mode=1
    x,y,z=0,0,512
    rx,ry,rz=30,-45,0
    w,h=640,480
    far=8192
    fov=60

    def view(self,width,height):
        self.w,self.h=width,height
        glViewport(0, 0, width, height)
        print "Viewport "+str(width)+"x"+str(height)
        if self.mode==2: self.isometric()
        elif self.mode==3: self.perspective()
        else: self.default()

    def default(self):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, self.w, 0, self.h, -1, 1)
        glMatrixMode(GL_MODELVIEW)

    def isometric(self):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
glOrtho(-self.w/2.,self.w/2.,-self.h/2.,self.h/2.,0,self.far)
        glMatrixMode(GL_MODELVIEW)

    def perspective(self):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(self.fov, float(self.w)/self.h, 0.1, self.far)
        glMatrixMode(GL_MODELVIEW)

    def key(self, symbol, modifiers):
        if symbol==key.F1:
            self.mode=1
            self.default()
            print "Projection: Pyglet default"
        elif symbol==key.F2:
            print "Projection: 3D Isometric"
            self.mode=2
            self.isometric()
        elif symbol==key.F3:
            print "Projection: 3D Perspective"
            self.mode=3
            self.perspective()
        elif self.mode==3 and symbol==key.NUM_SUBTRACT:
            self.fov-=1
            self.perspective()
        elif self.mode==3 and symbol==key.NUM_ADD:
            self.fov+=1
            self.perspective()
        else: print "KEY "+key.symbol_string(symbol)

    def drag(self, x, y, dx, dy, button, modifiers):
        if button==1:
            self.x-=dx*2
            self.y-=dy*2
        elif button==2:
            self.x-=dx*2
            self.z-=dy*2
        elif button==4:
            self.ry+=dx/4.
            self.rx-=dy/4.

    def apply(self):
        glLoadIdentity()
        if self.mode==1: return
        glTranslatef(-self.x,-self.y,-self.z)
        glRotatef(self.rx,1,0,0)
        glRotatef(self.ry,0,1,0)
        glRotatef(self.rz,0,0,1)

def x_array(list):
    return (GLfloat * len(list))(*list)

def axis(d=200):
    vertices,colors=[],[]
    #XZ RED
    vertices.extend([-d, 0,-d, d, 0,-d, d, 0, d,-d, 0, d])
    for i in range (0,4): colors.extend([1,0,0,0.5])
    #YZ GREEN
    vertices.extend([ 0,-d,-d, 0,-d, d, 0, d, d, 0, d,-d])
    for i in range (0,4): colors.extend([0,1,0,0.5])
    #XY BLUE
    vertices.extend([-d,-d, 0, d,-d, 0, d, d, 0,-d, d, 0])
    for i in range (0,4): colors.extend([0,0,1,0.5])
    return x_array(vertices),x_array(colors)
AXIS_VERTICES,AXIS_COLORS=axis()

def draw_vertex_array(vertices,colors,mode=GL_LINES):
    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_COLOR_ARRAY)
    glColorPointer(4, GL_FLOAT, 0, colors)
    glVertexPointer(3, GL_FLOAT, 0, vertices)
    glDrawArrays(GL_QUADS, 0, len(vertices)/3)
    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_COLOR_ARRAY)

def draw_axis():
    glEnable(GL_DEPTH_TEST)
    draw_vertex_array(AXIS_VERTICES,AXIS_COLORS,GL_QUADS)
    glDisable(GL_DEPTH_TEST)

print "OpenGL Projections"
print "---------------------------------"
print "Projection matrix -> F1, F2, F3"
print "Camera -> Drag LMB,CMB,RMB"
print ""
cam=camera()
win = window.Window(resizable=True)
win.on_resize=cam.view
win.on_key_press=cam.key
win.on_mouse_drag=cam.drag
opengl_init()

while not win.has_exit:
    win.dispatch_events()
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    cam.apply()
    draw_axis()
    playground()
    win.flip()


Question:


El 27/07/2012 20:41, Derek S. escribió:
Thank you for the example Txema. I'm going to need to become a little more educated to understand it. Is A,C the x,y of the bottom left corner of the window, and B,D the top right? What kind of data type is the matrix, some sort of special double precision tuple?
What do you use this bit of code for (zooming, panning, etc..)?

Txema Vicente wrote:

    I have some code that may help you, the math is in there.

    This is for a hierarchy of planes, and all matrices are calculated
    "manually".

    _tx, _ty, _tz : Translation
    _scale: (XY axis)
    _rotation: (Z axis)


    RADIANS=-0.01745

    class Plane(...):

         def matrix_update(self):
             a = self._scale*math.cos(RADIANS*self._rotation)
             b = self._scale*math.sin(RADIANS*self._rotation)
             if self.parent is None:
                 self.matrix=(gl.GLdouble * 16)(
                                 a, -b, 0, 0,
                                 b, a, 0, 0,
                                 0, 0, 1, 0,
                                 self._tx, self._ty, self._tz, 1)
             else:
                 c, d = -b, a
                 origin=self.parent.matrix
                 A,C = origin[0], origin[1] #C=-B
                 B,D = origin[4], origin[5] #D=A
                 X,Y,Z = origin[12], origin[13], origin[14]
                 self.matrix=(gl.GLdouble * 16)(
                                  A*a+B*c, C*a+D*c, 0, 0,
                                  A*b+B*d, C*b+D*d, 0, 0,
                                  0, 0, 1, 0,
                          X + A*self._tx + B*self._ty, Y + C*self._tx +
    D*self._ty,
                          Z + self._tz, 1)

             for plane in self.children: plane.matrix_update()


--
You received this message because you are subscribed to the Google Groups "pyglet-users" group. To view this discussion on the web visit https://groups.google.com/d/msg/pyglet-users/-/LGCPXGNx3EoJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/pyglet-users?hl=en.

--
You received this message because you are subscribed to the Google Groups 
"pyglet-users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/pyglet-users?hl=en.

Reply via email to