[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] PyOpenGL Screenshots



Here it is. I didn't spend any time making this code nice, but you can
just rip out the parts you need.

2008/5/8 Alistair Buxton <a.j.buxton@xxxxxxxxx>:
> I have a full example of doing exactly this task using python to
>  render to a series of png images (which you can load into something
>  like adobe premier), or a raw RV24 file (which you can transcode under
>  linux using... transcode). Will post it as soon as I've dug it out and
>  tested it still works. Includes examples of using transcode too.
>
>  2008/5/8 Ian Mallett <geometrian@xxxxxxxxx>:
>
>
> > I figured out a way to do it in my program--Animation Shop Pro.  It would
>  > still be cool to have examples of how to do this without Animation Shop.  I
>  > was thinking ffmpeg or pil for doing so.  I looked around, but couldn't find
>  > anything.
>  >  Thanks everyone,
>  > Ian
>  >
>
>
>
>  --
>  Alistair Buxton
>  a.j.buxton@xxxxxxxxx
>



-- 
Alistair Buxton
a.j.buxton@xxxxxxxxx
#!/usr/bin/env python

# Python OpenGL -> Video file
# (c) 2008 Alistair Buxton <a.j.buxton@xxxxxxxxx>
# Handy for doing procedural animations for compositing with other 
# videos in <your favourite video editing package.>

import os, random, math

from OpenGL.GL import *
from OpenGL.GLU import *
import pygame, pygame.image, pygame.key
from pygame.locals import *
from PIL import Image

######################################################################################

# render settings

# 1 = best
QUALITY = 16

# whether to actually write output files or just preview
render_on = True

# If you don't want to write separate png files, you can just dump the output 
# from glReadPixels() into one huge file and encode it with transcode:

# transcode --use_rgb -i whatever.rv24 -x raw=RGB,null -y xvid4 -o output.xvid.avi -k -z  -f 25
# (for xvid)

# But beware that whatever.rv24 will be HUGE as it is uncompressed (not even RLE). 
# the size will be width*height*numframes*3 bytes, that's 31mb/sec for standard PAL video.

# Also worth mentioning: RV24 export is RGB, but png export is RGBA - thus if you use
# RV24 method, you will loose the alpha channel of your video.

# render type
# if true, write one big RV24 raw video file
# if false, write a png sequence
render_rv24 = False

if render_on:
    # size of final render
    w = 720
    h = 576
else:
    # size for preview
    w = 720
    h = 576

# how many frames to render before exiting
max_frames = 25

# framerate of rendered video
fps = 25.0

if render_rv24:
    framefile = file("whatever.rv24", "wb")

######################################################################################

# the snowflake animation stuff

flakes = []

class SnowFlake(object):
    def __init__(self):
        self.x = random.randrange(0,720)
        self.y = random.randrange(0,576)
        
        self.z = 3 + (random.randrange(3,20) / random.randrange(3,25))
        
        self.dy = random.randrange(1,10)
        self.drift = random.randrange(1,100)/1000.0 
        self.rad = random.randrange(1,100)/100.0

    def draw(self):
        glColor4f(1.0,1.0,1.0,1.0)
        if self.z < 0:
            return
        glBegin(GL_POLYGON)
        r = math.floor(self.z * 4)
        for i in range(int(r)):
            glVertex2f( self.x+(self.z*math.sin(2*math.pi*(i/r))), self.y+(self.z*math.cos(2*math.pi*(i/r))) )
        glVertex2f( self.x, self.y+self.z )
        glEnd()

    
    def update(self, ftime):
    
        self.rad += ((ftime*0.5)+self.drift)
        self.x += math.sin(self.rad)
        
        self.y -= 0.7*ftime*(40.0+self.dy)*self.z;
        
        if (self.y < -10):
            self.y = 586
        
        if (self.x < -10):
            self.x = 730
            
        if (self.x > 730):
            self.x = -10

# standard opengl stuff init/draw/update/resize

def resize((width, height)):
    if height==0:
        height=1.0
    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluOrtho2D(0, 720, 0, 576)
#    gluOrtho2D(-(width/(2*height)), width/(2*height), 0, 1)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def init():
    glShadeModel(GL_SMOOTH)
    glClearColor(0.3,0.5,0.7,0.0)
    glClearDepth(1.0)
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
    glDisable(GL_DEPTH_TEST)    
    
    for i in range(100):
        flakes.append(SnowFlake())

def update(ftime):
    for f in flakes:
        f.update(ftime)

def draw():
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )

    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glDisable(GL_TEXTURE_2D)

    for f in flakes:
        f.draw()

#######################################################################################

# write a png file from GL framebuffer data

def png_file_write(name, number, data):
    im = Image.frombuffer("RGBA", (720,576), data, "raw", "RGBA", 0, 0)
    fnumber = "%05d" % number
    im.save(name + fnumber + ".png")

######################################################################################

# main

def main():

    video_flags = OPENGL|DOUBLEBUF#|FULLSCREEN
    
    pygame.init()
    surface = pygame.display.set_mode((w,h), video_flags)
    pygame.key.set_repeat(100,30)

    resize((w,h))
    init()
    
    frames = 0
    done = 0
    ftime = 0
    oldticks = newticks = ticks = pygame.time.get_ticks()
    while not done:
        while 1:
            event = pygame.event.poll()
            if event.type == NOEVENT:
                break
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    done = 1
            if event.type == QUIT:
                done = 1

        draw()

        ########### This is where the output gets written ###########
        # NOTE: the GL_RGB / GL_RGBA difference
        if render_on == 1:
            if render_rv24:
                framefile.write(glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE))
            else:
                png_file_write("snow", frames, glReadPixels( 0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE))

        pygame.display.flip()
        newticks = pygame.time.get_ticks()

        # if rendering then set the frame time to fixed amount
        if render_on == 1:
            thistime = 1.0 / fps # change this to the desired framerate of your video!
        # else if previewing, use varying frame length to approximate actual output
        else:
            thistime = (newticks - oldticks) / 1000.0

        oldticks = newticks
        ftime += thistime
        frames += 1

        update(thistime)

        print "frame %d : ftime %f" % (frames,ftime)
        if (frames) > max_frames:
            if render_on == 1:
                break
            else:
                pass



if __name__ == '__main__': main()