diff --git a/asset.py b/asset.py new file mode 100755 index 0000000..a65eb41 --- /dev/null +++ b/asset.py @@ -0,0 +1,13 @@ + +from gameobj import gameobj + +class asset_manager(object): + def __init__(self): + self.renderable_cache = {} + def get_obj(self, name): + go = gameobj() + go.set_renderable(self.renderable_cache[name]) + return go + + +mgr = asset_manager() \ No newline at end of file diff --git a/data/tex/black.png b/data/tex/black.png new file mode 100755 index 0000000..31d8067 Binary files /dev/null and b/data/tex/black.png differ diff --git a/data/tex/nm_flat.png b/data/tex/nm_flat.png new file mode 100755 index 0000000..1b82345 Binary files /dev/null and b/data/tex/nm_flat.png differ diff --git a/data/tex/plasma1.png b/data/tex/plasma1.png new file mode 100755 index 0000000..70c2ad0 Binary files /dev/null and b/data/tex/plasma1.png differ diff --git a/data/tex/plasma2.png b/data/tex/plasma2.png new file mode 100755 index 0000000..b41ed62 Binary files /dev/null and b/data/tex/plasma2.png differ diff --git a/data/tex/test1.png b/data/tex/test1.png new file mode 100755 index 0000000..6cdfb48 Binary files /dev/null and b/data/tex/test1.png differ diff --git a/data/tex/white.png b/data/tex/white.png new file mode 100755 index 0000000..3380fbb Binary files /dev/null and b/data/tex/white.png differ diff --git a/data/xml/def/sprites.xml b/data/xml/def/sprites.xml new file mode 100755 index 0000000..5f08046 --- /dev/null +++ b/data/xml/def/sprites.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/xml/sprites.xml b/data/xml/sprites.xml new file mode 100755 index 0000000..fe02b6b --- /dev/null +++ b/data/xml/sprites.xml @@ -0,0 +1,5 @@ + + + tex/test1.png + + \ No newline at end of file diff --git a/deprecate.py b/deprecate.py new file mode 100755 index 0000000..cce8950 --- /dev/null +++ b/deprecate.py @@ -0,0 +1,20 @@ +import warnings +import functools + + +def deprecated(func): + """This is a decorator which can be used to mark functions + as deprecated. It will result in a warning being emitted + when the function is used.""" + + @functools.wraps(func) + def new_func(*args, **kwargs): + warnings.warn( + "Call to deprecated function %(funcname)s." % { + 'funcname': func.__name__, + }, + category=DeprecationWarning, + stacklevel=2 + ) + return func(*args, **kwargs) + return new_func diff --git a/enums.py b/enums.py index 8e6b649..e00ecb3 100755 --- a/enums.py +++ b/enums.py @@ -49,3 +49,10 @@ pl.particle = 4 pl.sprite = 5 pl.composite1 = 6 pl.composite2 = 7 + +tt = enum() +tt.diffuse = 0 # the diffuse texture sets the colors and general brightness of the texture. if the same texture is used as the emissive texture, the model is effectively "fullbright" +tt.emissive = 1 # this texture is blended with the diffuse texture as the light level drops (this can be used to add running lights or glow to a ship, or light up the dark side of a planet, otherwise pure "black" is a good choice) +tt.specular = 2 # adding a specular map allows you to add areas of low or high reflectivity to your texture +tt.normal = 3 # normal maps allow bump mapping and other tweaks, with each channel representing the direction of the normal (red = -1x to 1x, green = -1y to 1y, blue = 0z to 1z) + diff --git a/gamedata.py b/gamedata.py index 638e76c..b086eb0 100755 --- a/gamedata.py +++ b/gamedata.py @@ -6,6 +6,7 @@ except ImportError: from elementtree.ElementTree import parse import files import shader +from deprecate import deprecated class MissingNode(object): def __init__(self): @@ -221,7 +222,24 @@ def load_xml_files(binfile, xmlfile): return XMLGameDataReader(bintree, xmltree) +def get(dataname): + if dataname in get.cache: + return get.cache[dataname] + + bin = files.mgr.path("xml/def", "%s.xml" % (dataname,)) + xml = files.mgr.path("xml", "%s.xml" % (dataname,)) + + if not os.path.exists(bin) or not os.path.exists(xml): + raise OSError("XML data file does not exist") + + dataobj = load_xml_files(bin, xml) + + get.cache[dataname] = dataobj + return dataobj + +get.cache = {} +@deprecated def load_gamedata(): bins = glob.glob(files.mgr.path("xml/def", "*.xml")) xmls = glob.glob(files.mgr.path("xml", "*.xml")) @@ -235,7 +253,6 @@ def load_gamedata(): dataobjs = {} for fn in ffns: - print fn #DELME binfile = files.mgr.path("xml/def", fn) xmlfile = files.mgr.path("xml", fn) dataobj = load_xml_files(binfile, xmlfile) diff --git a/gameobj.py b/gameobj.py new file mode 100755 index 0000000..c57501b --- /dev/null +++ b/gameobj.py @@ -0,0 +1,5 @@ + +class gameobj(object): + def __init__(self): + pass + diff --git a/lesson6.py b/lesson6.py new file mode 100755 index 0000000..72e97c6 --- /dev/null +++ b/lesson6.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python + +# +# This code was created by Richard Campbell '99 (ported to Python/PyOpenGL by John Ferguson 2000) +# +# The port was based on the lesson5 tutorial module by Tony Colston (tonetheman@hotmail.com). +# +# If you've found this code useful, please let me know (email John Ferguson at hakuin@voicenet.com). +# +# See original source and C based tutorial at http:#nehe.gamedev.net +# +# Note: +# ----- +# Now, I assume you've read the prior tutorial notes and know the deal here. The one major, new requirement +# is to have a working version of PIL (Python Image Library) on your machine. +# +# General Users: +# -------------- +# I think to use textures at all you need Nunmeric Python, I tried without it and BAM Python didn't "like" the texture API. +# +# Win32 Users: +# ------------ +# Well, here's the install I used to get it working: +# [1] py152.exe - include the TCL install! +# [2] PyOpenGL.EXE - probably the latest, the Vaults notes should give you a clue. +# [3] Distutils-0.9.win32.exe for step #4 +# [4] Numerical-15.3.tgz - run the setup.py (need VC++ on your machine, otherwise, have fun with #3, it looks fixable to use gCC). +# +# Win98 users (yes Win98, I have Mandrake on the other partition okay?), you need to the Tcl bin directory in your PATH, not PYTHONPATH, +# just the DOS PATH. +# +# BTW, since this is Python make sure you use tabs or spaces to indent, I had numerous problems since I +# was using editors that were not sensitive to Python. +# +from OpenGL.GL import * +from OpenGL.GLUT import * +from OpenGL.GLU import * +from Image import * + +# Some api in the chain is translating the keystrokes to this octal string +# so instead of saying: ESCAPE = 27, we use the following. +ESCAPE = '\033' + +# Number of the glut window. +window = 0 + +# Rotations for cube. +xrot = yrot = zrot = 0.0 + +texture = 0 + +def LoadTextures(): + #global texture + image = open("NeHe.bmp") + + ix = image.size[0] + iy = image.size[1] + image = image.tostring("raw", "RGBX", 0, -1) + + # Create Texture + # There does not seem to be support for this call or the version of PyOGL I have is broken. + #glGenTextures(1, texture) + #glBindTexture(GL_TEXTURE_2D, texture) # 2d texture (x and y size) + + glPixelStorei(GL_UNPACK_ALIGNMENT,1) + glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) + +# A general OpenGL initialization function. Sets all of the initial parameters. +def InitGL(Width, Height): # We call this right after our OpenGL window is created. + LoadTextures() + glEnable(GL_TEXTURE_2D) + glClearColor(0.0, 0.0, 0.0, 0.0) # This Will Clear The Background Color To Black + glClearDepth(1.0) # Enables Clearing Of The Depth Buffer + glDepthFunc(GL_LESS) # The Type Of Depth Test To Do + glEnable(GL_DEPTH_TEST) # Enables Depth Testing + glShadeModel(GL_SMOOTH) # Enables Smooth Color Shading + + glMatrixMode(GL_PROJECTION) + glLoadIdentity() # Reset The Projection Matrix + # Calculate The Aspect Ratio Of The Window + gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0) + + glMatrixMode(GL_MODELVIEW) + +# The function called when our window is resized (which shouldn't happen if you enable fullscreen, below) +def ReSizeGLScene(Width, Height): + if Height == 0: # Prevent A Divide By Zero If The Window Is Too Small + Height = 1 + + glViewport(0, 0, Width, Height) # Reset The Current Viewport And Perspective Transformation + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0) + glMatrixMode(GL_MODELVIEW) + +# The main drawing function. +def DrawGLScene(): + global xrot, yrot, zrot, texture + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Clear The Screen And The Depth Buffer + glLoadIdentity() # Reset The View + glTranslatef(0.0,0.0,-5.0) # Move Into The Screen + + glRotatef(xrot,1.0,0.0,0.0) # Rotate The Cube On It's X Axis + glRotatef(yrot,0.0,1.0,0.0) # Rotate The Cube On It's Y Axis + glRotatef(zrot,0.0,0.0,1.0) # Rotate The Cube On It's Z Axis + + # Note there does not seem to be support for this call. + #glBindTexture(GL_TEXTURE_2D,texture) # Rotate The Pyramid On It's Y Axis + + glBegin(GL_QUADS) # Start Drawing The Cube + + # Front Face (note that the texture's corners have to match the quad's corners) + glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0) # Top Left Of The Texture and Quad + + # Back Face + glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0) # Bottom Left Of The Texture and Quad + + # Top Face + glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) # Top Right Of The Texture and Quad + + # Bottom Face + glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) # Bottom Right Of The Texture and Quad + + # Right face + glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, 1.0) # Top Left Of The Texture and Quad + glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) # Bottom Left Of The Texture and Quad + + # Left Face + glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0) # Bottom Left Of The Texture and Quad + glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) # Bottom Right Of The Texture and Quad + glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0) # Top Right Of The Texture and Quad + glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) # Top Left Of The Texture and Quad + + glEnd(); # Done Drawing The Cube + + xrot = xrot + 0.2 # X rotation + yrot = yrot + 0.2 # Y rotation + zrot = zrot + 0.2 # Z rotation + + # since this is double buffered, swap the buffers to display what just got drawn. + glutSwapBuffers() + +# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y) +def keyPressed(*args): + # If escape is pressed, kill everything. + if args[0] == ESCAPE: + glutDestroyWindow(window) + sys.exit() + +def main(): + global window + # For now we just pass glutInit one empty argument. I wasn't sure what should or could be passed in (tuple, list, ...) + # Once I find out the right stuff based on reading the PyOpenGL source, I'll address this. + glutInit("") + + # Select type of Display mode: + # Double buffer + # RGBA color + # Alpha components supported + # Depth buffer + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH) + + # get a 640 x 480 window + glutInitWindowSize(640, 480) + + # the window starts at the upper left corner of the screen + glutInitWindowPosition(0, 0) + + # Okay, like the C version we retain the window id to use when closing, but for those of you new + # to Python (like myself), remember this assignment would make the variable local and not global + # if it weren't for the global declaration at the start of main. + window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99") + + # Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to + # set the function pointer and invoke a function to actually register the callback, otherwise it + # would be very much like the C version of the code. + glutSetDisplayFuncCallback(DrawGLScene) + glutDisplayFunc() + + # Uncomment this line to get full screen. + # glutFullScreen() + + # When we are doing nothing, redraw the scene. + glutSetIdleFuncCallback(DrawGLScene) + glutIdleFunc() + + # Register the function called when our window is resized. + glutSetReshapeFuncCallback(ReSizeGLScene) + glutReshapeFunc() + + # Register the function called when the keyboard is pressed. + glutSetKeyboardFuncCallback(keyPressed) + glutKeyboardFunc() + + # Initialize our window. + InitGL(640, 480) + + # Start Event Processing Engine + glutMainLoop() + +# Print message to console, and kick off the main to get it rolling. +print "Hit ESC key to quit." +main() + diff --git a/looprun.bat b/looprun.bat old mode 100644 new mode 100755 index c24d6b9..9f601e3 --- a/looprun.bat +++ b/looprun.bat @@ -2,4 +2,5 @@ :restart roc_test.py pause +echo Starting... goto restart diff --git a/models.py b/models.py new file mode 100755 index 0000000..bb04bf1 --- /dev/null +++ b/models.py @@ -0,0 +1,146 @@ +import enums + +class Vertex(object): + __slots__ = [ + 'v', # vertex coordinates + 'n', # normal + 't', # texture coordinates + 'c', # color + ] + +class Model_Manager(object): + def __init__(self): + self.load_textypes() + self.load_textures() + self.load_materials() + self.load_models() + + def load_textypes(): + self.textypes = {} + self.textypes[enums.tt.diffuse] = TextureType(GL_TEXTURE0, GL_TEXTURE_2D, GL_CLAMP, GL_CLAMP, GL_NEAREST, GL_NEAREST) + self.textypes[enums.tt.dark] = TextureType(GL_TEXTURE1, GL_TEXTURE_2D) + self.textypes[enums.tt.specular] = TextureType(GL_TEXTURE2, GL_TEXTURE_2D) + self.textypes[enums.tt.normal] = TextureType(GL_TEXTURE3, GL_TEXTURE_2D) + + def get_textype(self, textype): + if isinstance(textype, TextureType): + return textype + return self.textypes[textype] + + def load_textures(self): + gamedata.get('textures') + + def load_textures(self): + gamedata.get('materials') + + def load_textures(self): + gamedata.get('models') + +mgr = Model_Manager() + +class TextureType(object): + def __init__(self, texunit, texdim, wrap_s=GL_CLAMP, wrap_t=GL_CLAMP, mag=GL_LINEAR, min=GL_LINEAR) + self.texunit = texunit + self.texdim = texdim + self.wrap_s = wrap_s + self.wrap_t = wrap_t + self.mag = mag + self.min = min + + def initialize(self): + glActiveTexture(self.texunit) + glTexParameterf(self.texdim, GL_TEXTURE_WRAP_S, self.wrap_s) + glTexParameterf(self.texdim, GL_TEXTURE_WRAP_T, self.wrap_t) + glTexParameterf(self.texdim, GL_TEXTURE_MAG_FILTER, self.mag) + glTexParameterf(self.texdim, GL_TEXTURE_MIN_FILTER, self.min) + + def get_dimension(self): + return self.texdim + + def activate(self): + glActiveTexture(self.texunit) + + + + +class Material(object): + + def __init__(self): + pass + def attach_texture(self, textype, texid): + textype = mgr.get_textype(textype) + textype.activate() + + self.texid + +class Texture(object): + def __init__(self): + pass + def load(self, file): + img = files.mgr.png(file) + texid, = glGenTextures(1) + + self.id = texid + + imgdata = pygame.image.tostring(img, "RGBA") + imgr = img.get_rect() + + glBindTexture(textype.get_dimension(), texid) + glTexImage2D(textype.get_dimension(), 0, GL_RGBA8, imgr.w, imgr.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgdata) + glBindTexture(textype.get_dimension(), 0) + +class Model(object): + def __init__(self): + self.vertexes = [] + + + def set_rotation(self): + glPushMatrix() + glMultMatrixf(self.rot.get_matrix()) + + def unset_rotation(self): + glPopMatrix() + + def bind_textures(self): + glBindTexture(GL_TEXTURE_2D + def unbind_textures(self): + + def draw(self): + self.bind_textures() + glBegin(GL_TRIANGLES) + for v in self.vertexes: + self.draw_vertex(v) + glEnd(GL_TRIANGLES) + self.unbind_textures() + + def draw_vertex(self, v): + glColor3f(v.c[0], v.c[1], v.c[2]) + glNormal3f(v.n.x, v.n.y, v.n.z) + glTexCoord2f(v.t[0], v.t[1]) + glVertex3f(v.v.x, v.v.y, v.v.z) + + + + +class Sprite(object): + def __init__(self): + Model.__init__(self) + vl = [Vertex() for x in xrange(4)] + + normal = vect(0.0, 0.0, 1.0) + white = (1.0, 1.0, 1.0) + for v in vl: + v.n = normal + v.c = white + + tl, bl, tr, br = vl + + tl.v = vect(-0.5, -0.5, 0.0); tl.t = (0.0, 0.0) + bl.v = vect(-0.5, 0.5, 0.0); bl.t = (0.0, 1.0) + tr.v = vect( 0.5, -0.5, 0.0); tr.t = (1.0, 0.0) + br.v = vect( 0.5, 0.5, 0.0); br.t = (1.0, 1.0) + + self.corners = vl + self.vertexes = [tl, bl, tr, bl, tr, br] + + def set_texture( \ No newline at end of file diff --git a/roc.py b/roc.py new file mode 100755 index 0000000..f713ce4 --- /dev/null +++ b/roc.py @@ -0,0 +1,86 @@ +import pygame +from pygame.locals import * +import gamedata +import gametimer +import video +import shader +import inputs +from OpenGL.GL import * + + +def init2d(): + init(videoinit=video.init2d) + +def init3d(): + init(videoinit=video.init3d) + +def init(videoinit): + pygame.init() + + size = width, height = (1600,1200) + size = width, height = (1024,768) + + video.set_res(size) + videoinit() + video.enable_vsync() + +def test_frame(): + from PIL import Image + + # pink triangle + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(0.0, 0.0, 1.0) + glColor4f(1.0, 0.0, 0.5, 1.0) + glVertex3f( 20.0, 50.0, 1.0) + glVertex3f( 20.0, 600.0, 1.0) + glVertex3f( 400.0, 50.0, 1.0) + glEnd() + + # yellow square + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(0.0, 0.0, 1.0) + glColor4f(1.0, 1.0, 0.0, 1.0) + glVertex3f( 150.0, 20.0, -50.0) + glVertex3f( 150.0, 400.0, -50.0) + glVertex3f( 360.0, 20.0, -50.0) + glVertex3f( 360.0, 400.0, -50.0) + glEnd() + + # texture test + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(0.0, 0.0, 1.0) + glColor4f(1.0, 1.0, 1.0, 1.0) + glVertex3f( 500.0, 300.0, 5.0) + glVertex3f( 500.0, 500.0, 5.0) + glVertex3f( 700.0, 300.0, 5.0) + glVertex3f( 700.0, 500.0, 5.0) + glEnd() + + +def main(): + gametimer.start_loop() + while True: + events = pygame.event.get() + gametimer.next_frame() + pygame.event.pump() + for ev in events: + if ev.type == QUIT: + inputs.add_command('exit') + break + elif ev.type == KEYUP: + inputs.keyup(ev.key) + elif ev.type == KEYDOWN: + inputs.keydown(ev.key) + #elif ev.type == VIDEOEXPOSE: + # video.force_redraw() + elif ev.type in (MOUSEBUTTONDOWN, MOUSEBUTTONUP): + pass + + if 'exit' in inputs.commands: + break + + video.predraw() + + test_frame() + + video.next_frame() diff --git a/roc_test.py b/roc_test.py index 9f39b7e..d61fffc 100755 --- a/roc_test.py +++ b/roc_test.py @@ -1,19 +1,4 @@ -import pygame -from pygame.locals import * -import gamedata -import gametimer -import video -import shader +import roc -pygame.init() -gamedata.load_gamedata() - -size = width, height = (1600,1200) -size = width, height = (1024,768) - -video.set_res(size) -video.init() -video.enable_vsync() -gametimer.start_loop() - -print shader.mgr.detect() +roc.init2d() +roc.main() \ No newline at end of file diff --git a/shader.py b/shader.py index a0ab67f..56443a3 100755 --- a/shader.py +++ b/shader.py @@ -7,13 +7,19 @@ except ImportError: pass from OpenGL.arrays import GLintArray, GLcharArray, GLsizeiArray, GLcharARBArray import sys +import gamedata + class shader_manager(object): def __init__(self): # Fixed Pipeline is always zero self.shaderlib = {'ffp': 0} self.shaderprograms = {} - self.shadersources = [] + + self.initshadersources = [] + self.initmode = 'auto' + self.initialized = False + def use_gl2_shaders(self): self.funcs = { 'create': glCreateShader, @@ -74,6 +80,10 @@ class shader_manager(object): } def init_gl(self): + if self.initialized: + return + + self.initialized = True import files #print glGetString(GL_EXTENSIONS) if True: @@ -82,7 +92,7 @@ class shader_manager(object): self.use_arb_shaders() #self.use_gl2_shaders() - for name, vertex, fragment in self.shadersources: + for name, vertex, fragment in self.initshadersources: vf = files.mgr.open('shaders/%s.vert' % (vertex,)) ff = files.mgr.open('shaders/%s.frag' % (fragment,)) vs = self.funcs['create'](GL_VERTEX_SHADER) @@ -129,6 +139,13 @@ class shader_manager(object): return workable_shaders + def autoinit(self): + shadertypes = self.detect() + + if not shadertypes: + raise ValueError, "No working shaders detected" + + self.init_shadertype(shadertypes[0]) def init_shadertype(self, shadertype): if shadertype == "GL2": @@ -143,9 +160,9 @@ class shader_manager(object): def select(self, shader): - if self.shadersources: + if self.initshadersources: self.init_gl() - self.shadersources = [] + self.initshadersources = [] if not shader in self.shaderlib: self.funcs['use'](0) return True @@ -187,8 +204,12 @@ class shader_manager(object): return True + def load(self): + shader_data = gamedata.get('shaders') + self.load_shaders(shader_data) + def load_shaders(self, shaders): for shader in shaders.shader: - self.shadersources.append((shader['id'], shader['vertex'], shader['fragment'])) + self.initshadersources.append((shader['id'], shader['vertex'], shader['fragment'])) mgr = shader_manager() diff --git a/sprite.py b/sprite.py new file mode 100755 index 0000000..1f36a08 --- /dev/null +++ b/sprite.py @@ -0,0 +1,69 @@ +import files +import os +from OpenGL.GL import * +from py3ds.example.gltexture import Texture + +class renderable_sprite(object): + """ + Internal class to create a textured quad for a sprite to live on. + Multiple sprites can use the same sprite_tex if the graphic they want to + display is the same. + """ + def __init__(self): + self.gltex = None + self.gllist = None + self.texfile = None + self.scale = 1.0 + def load_name(self, name): + self.texfile = files.mgr.open(os.path.join('sprite', name + '.png')) + def set_file(self, fileobj): + self.texfile = fileobj + def update(self): + pass + def render(self): + if self.gltex == None: + self.gltex = Texture(self.texfile) + self.texfile.close() + self.texfile = None + if self.gllist == None: + glPushMatrix() + #glLoadIdentity() + dl = glGenLists(1) + if dl == 0: + raise GLError, "cannot allocate display list" + glNewList(dl, GL_COMPILE) + glEnable(GL_BLEND) + glEnable(GL_DEPTH_TEST) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + self.gltex.enable() + self.gltex.bind() + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) + glBegin(GL_TRIANGLE_STRIP) + glNormal3f(1.0, 0.0, 0.0) + glTexCoord2f(1.0, 1.0); glVertex3f( 0.0, 1.0, 1.0) + glTexCoord2f(0.0, 1.0); glVertex3f( 0.0, 1.0, -1.0) + glTexCoord2f(1.0, 0.0); glVertex3f(-0.0, -1.0, 1.0) + glTexCoord2f(0.0, 0.0); glVertex3f(-0.0, -1.0, -1.0) + glEnd() + + self.gltex.disable() + glDisable(GL_BLEND) + glEndList() + self.gllist = dl + glPopMatrix() + glCallList(self.gllist) + + +class sprite_manager(object): + def __init__(self): + self.sprite_cache = {} + def get(self, name): + if name in self.sprite_cache: + return self.sprite_cache[name] + + s = renderable_sprite() + s.load_name(name) + self.sprite_cache[name] = s + return s + +mgr = sprite_manager() \ No newline at end of file diff --git a/texture.py b/texture.py new file mode 100755 index 0000000..57d9eab --- /dev/null +++ b/texture.py @@ -0,0 +1,21 @@ + +class texture_wrapper(object): + def __init__(self): + pass + + def load_name(self, name): + pass + +class texture_manager(object): + def __init__(self): + self.texture_cache = {} + def get(self, name): + if name in self.texture_cache: + return self.texture_cache[name] + + t = texture_wrapper() + t.load_name(name) + self.texture_cache[name] = t + return t + +mgr = texture_manager() \ No newline at end of file diff --git a/video.py b/video.py index d04334a..58eb880 100755 --- a/video.py +++ b/video.py @@ -6,6 +6,10 @@ from OpenGL.arrays import GLcharArray import pygame from pygame.locals import * import sys +import shader + +height=None +width=None def enable_vsync(): if sys.platform != 'darwin': @@ -20,13 +24,60 @@ def enable_vsync(): print "Unable to set vsync mode, using driver defaults" def skipping_next_frame(): return False -def set_res((width, height)): +def set_res((width_in, height_in)): + global height, width + + height = height_in + width = width_in + if height==0: height=1 - pygame.display.gl_set_attribute(GL_DEPTH_SIZE, 24) + if width==0: + width=1 + #pygame.display.gl_set_attribute(GL_DEPTH_SIZE, 24) video_flags = OPENGL|DOUBLEBUF #video_flags = OPENGL|DOUBLEBUF|FULLSCREEN pygame.display.set_mode((width, height), video_flags) + +def get_res(): + return (height, width) + +def get_height(): + return height + +def get_width(): + return width + + +def init2d(): + #print pygame.display.gl_get_attribute(GL_DEPTH_SIZE) + glViewport(0, 0, width, height) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + glOrtho(-0.5, float(width)-0.5, float(height)-0.5, -0.5, 256.0, -256.0) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + #glRotatef(120.0, 1.0, 0.0, 0.0) + + + glClearColor(0.0, 0.0, 0.0, 0.0) + glClearDepth(-256.0) + + glShadeModel(GL_SMOOTH) + glEnable(GL_DEPTH_TEST) + glEnable(GL_CULL_FACE) + glEnable(GL_TEXTURE_2D) + glDepthFunc(GL_GEQUAL) + glEnable(GL_BLEND) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) + + shader.mgr.load() + shader.mgr.init_gl() + shader.mgr.select("ffp") + glDisable(GL_LIGHTING) + + +def init3d(): #print pygame.display.gl_get_attribute(GL_DEPTH_SIZE) glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) @@ -35,8 +86,6 @@ def set_res((width, height)): glMatrixMode(GL_MODELVIEW) glLoadIdentity() -def init(): - import shader glShadeModel(GL_SMOOTH) glClearColor(0.0, 0.0, 0.0, 0.0) glClearDepth(1.0) @@ -60,16 +109,20 @@ def init(): glEnable( GL_LIGHT1 ) """ """ + + shader.mgr.load() + shader.mgr.init_gl() shader.mgr.select("standard") glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (0.3, 0.3, 0.3, 1.0)) #glEnable(GL_AUTO_NORMAL) + def predraw(): glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glLoadIdentity() #glTranslatef(-1.0, 0.0, -9.0) - glRotatef(270.0, 1.0, 0.0, 0.0) + #glRotatef(270.0, 1.0, 0.0, 0.0) def next_frame(): pygame.display.flip()