commit e4ad38cd566dbc01ad8b46267c1606d3c25c86a1 Author: cecilkorik Date: Sun Apr 24 18:30:40 2011 -0600 first add of roc diff --git a/camera.py b/camera.py new file mode 100644 index 0000000..184c183 --- /dev/null +++ b/camera.py @@ -0,0 +1,190 @@ +from gameobj import game_object +import math +from quat import * +from py3dutil import vect +from OpenGL.GL import * +import files + +class game_camera(game_object): + def __init__(self): + self.tracking = None + game_object.__init__(self) + self.target_pos = self.pos.copy() + self.target_rot = self.rot.copy() + self.real_pos = self.pos.copy() + self.real_rot = self.rot.copy() + self.starbox = None + self.starboxes = [] + + def track(self, obj): + self.tracking = obj + self.target_at(obj, immediate=True) + + def target_at(self, obj, immediate=False): + self.target_pos = obj.pos.copy() + desired_v = -self.get_camera_vector(obj.rot) + self.target_rot = quat(desired_v.x, desired_v.y, desired_v.z, 0.0) + self.target_rot = obj.rot.copy() + if immediate: + self.pos = obj.pos.copy() + self.rot = obj.rot.copy() + self.real_pos = obj.pos.copy() + self.real_rot = obj.rot.copy() + else: + self.camera_slew() + + + # apply translation vector to current position! + #print "Realrot: %s" % (self.real_rot,) #DELME + self.rot = self.real_rot + self.pos = self.real_pos + self.get_camera_vector(self.rot) + + def get_camera_vector(self, rot): + camera_pitch = 15.0 + camera_dist = 16.0 + camera_pitch_axis = rot.get_conjugate() * vect(0.0, 1.0, 0.0) + camera_pitch_axis.normalize() + #print "Rot: %s" % (rot,) #DELME + + # find the direction we want to be pointing (looking forward) + camera_v = (rot.get_conjugate() * vect(1.0, 0.0, 0.0)) + # find the angle at which the camera should be pitched + camera_q = get_angle(camera_pitch, camera_pitch_axis) + # rotate the direction to include the pitch component + camera_v = camera_q * camera_v + # apply the distance to turn our unit vector into a translation vector + camera_v = camera_v.normalize() * -camera_dist + #print camera_v + return camera_v + + def draw_starbox(self): + return + starbox = 'plain' + #starbox = 'test' + if starbox != self.starbox: + import sprite + self.starbox = starbox + self.starboxes = [] + for i in range(6): + fn = 'img/starbox/starbox_%s_%d.png' % (starbox, i + 1) + f = files.mgr.open(fn) + self.starboxes.append(sprite.sprite_tex()) + self.starboxes[i].set_file(f) + starbox_locs = [ + (90.0, 1.0, 0.0, 0.0), + (0.0, 0.0, 0.0, 1.0), + (270.0, 0.0, 0.0, 1.0), + (180.0, 0.0, 0.0, 1.0), + (90.0, 0.0, 0.0, 1.0), + (270.0, 1.0, 0.0, 0.0) + ] + + clr = (1.0, 1.0, 1.0, 1.0) + glDisable(GL_LIGHTING) + glDepthMask(0) + glMaterialfv(GL_FRONT, GL_AMBIENT, clr) + glMaterialfv(GL_FRONT, GL_DIFFUSE, clr) + glMaterialfv(GL_FRONT, GL_SPECULAR, clr) + glColor4f(*clr) + glMatrixMode(GL_PROJECTION) + glPushMatrix() + glLoadIdentity() + fsize = 0.8 + wsize = 1.1 + fardist = 100.0 + glFrustum(-wsize, wsize, -fsize, fsize, 2.0, fardist * 10.0) + #glOrtho(-1.0, 1.0, -1.0, 1.0, 0.1, fardist * 10.0) + glMatrixMode(GL_MODELVIEW) + + for i in range(6): + glPushMatrix() + glRotatef(*starbox_locs[i]) + if i == 0: + glRotatef(270.0, 0.0, 1.0, 0.0) + if i == 5: + glRotatef(90.0, 0.0, 1.0, 0.0) + glTranslatef(0.0, fardist, 0.0) + glScalef(fardist, fardist, fardist) + #glTranslatef(0.0, 100.0, 0.0) + #glScalef(100.0, 100.0, 100.0) + self.starboxes[i].render() + glPopMatrix() + glDepthMask(1) + glEnable(GL_LIGHTING) + + glMatrixMode(GL_PROJECTION) + glPopMatrix() + glMatrixMode(GL_MODELVIEW) + + def calc_render_pos(self): + self.render_pos = vect(0.0, 0.0, 0.0) + + def clear_render_pos(self): + self.render_pos = None + + def render(self): + glPushMatrix() + glRotatef(90.0, 0.0, 0.0, 1.0) + glMultMatrixf(self.rot.get_conjugate().get_matrix()) + self.draw_starbox() + #glTranslatef(*[-x for x in self.pos]) + + + def update(self): + #return + if self.tracking != None: + self.target_at(self.tracking) + + def camera_slew(self): + #return + currv = self.get_camera_vector(self.real_rot) + targv = self.get_camera_vector(self.target_rot) + currpos = self.real_pos + currv + targpos = self.target_pos + targv + + currv.normalize() + targv.normalize() + + rotdiff = currv.dot(targv) + + if rotdiff != 0.0: + rotspeed = (math.sqrt(1.0 + rotdiff) - 1.0) / 10.0 + maxrot = 25.0 + if rotdiff > maxrot: + rotspeed += (rotdiff - maxrot) + amt = abs(rotspeed / rotdiff) + if amt >= 1.0: + self.real_rot = self.target_rot.copy() + elif amt < 1e-7: + self.real_rot = self.rot.copy() + else: + self.real_rot = self.rot.slerp(self.target_rot, amt) + + d = currpos.dist(targpos) + if d != 0.0: + maxdist = 3.0 + followspeed = (math.sqrt(1.0 + d) - 1.0) + #followspeed = 0.000001 + if d > maxdist: + followspeed += d - maxdist + amt = abs(followspeed / d) + #print "%s, %s, %s" % (d, amt, followspeed) + if amt > 1.0 or amt < 1e-7: + self.real_pos = self.target_pos.copy() + else: + self.real_pos = self.real_pos.slerp(self.target_pos, amt) + + #self.real_rot = self.real_rot * get_angle(90.0, vect(0.0, 0.0, 1.0)) + + + def get_forward_vector(self): + return (self.rot * vect(1.0, 0.0, 0.0)).normalize() + + + + def done(self): + glPopMatrix() + + + + diff --git a/data/shaders/shadow_pass1.frag b/data/shaders/shadow_pass1.frag new file mode 100644 index 0000000..f4a2ab7 --- /dev/null +++ b/data/shaders/shadow_pass1.frag @@ -0,0 +1,13 @@ +uniform sampler2D TextureMap; + +varying float CameraDepth; +varying vec2 TexCoord; + +void main() +{ + // draw the typical textured output to visual framebuffer + gl_FragData[0] = texture2D(TextureMap, TexCoord); + + // write "normaliized vertex depth" to the depthmap's alpha. + gl_FragData[1] = vec4(vec3(0.0), CameraDepth); +} \ No newline at end of file diff --git a/data/shaders/shadow_pass1.vert b/data/shaders/shadow_pass1.vert new file mode 100644 index 0000000..377efc0 --- /dev/null +++ b/data/shaders/shadow_pass1.vert @@ -0,0 +1,24 @@ +uniform vec3 CameraPos; +uniform vec3 CameraDir; +uniform float DepthNear; +uniform float DepthFar; + +varying float CameraDepth; // normalized camera depth +varying vec2 TexCoord; + +void main() +{ + // offset = vector to vertex from camera's position + vec3 offset = (gl_Vertex.xyz / gl_Vertex.w) - CameraPos; + + // z = distance from vertex to camera plane + float z = -dot(offset, CameraDir); + + // Depth from vertex to camera, mapped to [0,1] + CameraDepth = (z - DepthNear) / (DepthFar - DepthNear); + + // typical interpolated coordinate for texture lookup + TexCoord = gl_MultiTexCoord0.xy; + + gl_Position = ftransform(); +} \ No newline at end of file diff --git a/data/shaders/shadow_pass2.frag b/data/shaders/shadow_pass2.frag new file mode 100644 index 0000000..ab181e9 --- /dev/null +++ b/data/shaders/shadow_pass2.frag @@ -0,0 +1,25 @@ +uniform sampler2D DepthTexture; +uniform sampler2D ShadowTexture; + +varying vec2 DepthTexCoord; +varying vec3 ShadowNear; +varying vec3 ShadowDir; + +const vec3 shadowColor = vec3(0.0); + +void main() +{ + // read from DepthTexture + // (depth is stored in texture's alpha component) + float cameraDepth = texture2D(DepthTexture, DepthTexCoord).a; + + vec3 shadowPos = (cameraDepth * ShadowDir) + ShadowNear; + float l = dot(shadowPos.yz, shadowPos.yz); + float d = shadowPos.x; + + // k = shadow density: 0=opaque, 1=transparent + // (use texture's red component as the density) + float k = texture2D(ShadowTexture, vec2(l, d)).r; + + gl_FragColor = vec4(shadowColor, k); +} \ No newline at end of file diff --git a/data/shaders/shadow_pass2.vert b/data/shaders/shadow_pass2.vert new file mode 100644 index 0000000..52e01e3 --- /dev/null +++ b/data/shaders/shadow_pass2.vert @@ -0,0 +1,49 @@ +uniform mat3 WorldToShadow; +uniform vec3 SphereOrigin; + +uniform vec3 CameraPos; +uniform vec3 CameraDir; +uniform float DepthNear; +uniform float DepthFar; + +varying vec2 DepthTexCoord; +varying vec3 ShadowNear; +varying vec3 ShadowDir; + +void main() +{ + vec4 tmp1 = ftransform(); + gl_Position = tmp1; + + // Predivide out w to avoid perspective-correct interpolation. + // The quantities being interpolated are screen-space texture + // coordinates and vectors to the near and far shadow plane, + // all of which have to be bilinearly interpolated. + // This could potentially be done by setting glHint, + // but it wouldn't be guaranteed to work on all hardware. + + gl_Position.xyz /= gl_Position.w; + gl_Position.w = 1.0; + + // Grab the transformed vertex's XY components as a texcoord + // for sampling from the depth texture from pass 1. + // Normalize them from [0,0] to [1,1] + + DepthTexCoord = gl_Position.xy * 0.5 + 0.5; + + // offset = vector to vertex from camera's position + vec3 offset = (gl_Vertex.xyz / gl_Vertex.w) - CameraPos; + + // z = distance from vertex to camera plane + float z = -dot(offset, CameraDir); + + vec3 shadowOffsetNear = offset * DepthNear / z; + vec3 shadowOffsetFar = offset * DepthFar / z; + + vec3 worldPositionNear = CameraPos + shadowOffsetNear; + vec3 worldPositionFar = CameraPos + shadowOffsetFar; + + vec3 shadowFar = WorldToShadow * (worldPositionFar - SphereOrigin); + ShadowNear = WorldToShadow * (worldPositionNear - SphereOrigin); + ShadowDir = shadowFar - ShadowNear; +} \ No newline at end of file diff --git a/data/shaders/sprite.frag b/data/shaders/sprite.frag new file mode 100644 index 0000000..fb132e5 --- /dev/null +++ b/data/shaders/sprite.frag @@ -0,0 +1,17 @@ +varying vec4 ambientGlobal/*,ambientA[8],diffuseA[8]*/; +varying vec4 pixelpos; +uniform sampler2D tex; + +void main() +{ + vec4 color = ambientGlobal; + vec4 white = vec4(1.0, 1.0, 1.5, 1.0); + //color = white; + + vec4 texcolor = texture2D(tex, gl_TexCoord[0].st); + color = clamp(texcolor * color, 0.0, 1.0); + //color = color * vec4(1.0, 1.0, 1.0, 0.5); + gl_FragColor = color; + // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + +} \ No newline at end of file diff --git a/data/shaders/sprite.vert b/data/shaders/sprite.vert new file mode 100644 index 0000000..e43949b --- /dev/null +++ b/data/shaders/sprite.vert @@ -0,0 +1,15 @@ +varying vec4 ambientGlobal/*,ambientA[8],diffuseA[8]*/; +varying vec3 normal/*,lightDirA[8],halfVectorA[8]*/; +/*varying float distA[8];*/ +varying vec4 pixelpos; + +void main() +{ + normal = normalize(gl_NormalMatrix * gl_Normal); + + pixelpos = gl_ModelViewMatrix * gl_Vertex; + ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient; + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_Position = ftransform(); +} diff --git a/data/shaders/standard.frag b/data/shaders/standard.frag new file mode 100644 index 0000000..3aec6dd --- /dev/null +++ b/data/shaders/standard.frag @@ -0,0 +1,141 @@ +varying vec4 ambientGlobal/*,ambientA[8],diffuseA[8]*/; +varying vec4 pixelpos; +uniform sampler2D tex; +varying vec3 normal/*,lightDirA[8],halfVectorA[8]*/; +/*varying float distA[8];*/ + + +vec4 overlay_blend(vec4 base, vec4 blend) +{ + vec4 lumCoeff = vec4(0.2125, 0.7154, 0.0721, 1.0); + vec4 white = vec4(1.0, 1.0, 1.0, 1.0); + vec4 result; + float luminance = dot(base, lumCoeff); + + if (luminance < 0.45) + result = 2.0 * blend * base; + else if (luminance > 0.55) + result = white - 2.0 * (white - blend) * (white - base); + else + { + vec4 result1 = 2.0 * blend * base; + vec4 result2 = white - 2.0 * (white - blend) * (white - base); + result = mix(result1, result2, (luminance - 0.45) * 10.0); + } + return result; +} + +vec4 process_lightsource(gl_LightSourceParameters light, vec4 incolor) +{ + vec3 n,halfV,viewV,lightDir,halfVector; + float NdotL,NdotHV,dist; + vec4 color = vec4(0.0, 0.0, 0.0, 1.0); + vec4 spec = vec4(0.0, 0.0, 0.0, 1.0); + vec4 white = vec4(1.0, 1.0, 1.0, 1.0); + float att; + + /* a fragment shader can't write a varying variable, hence we need + a new variable to store the normalized interpolated normal */ + n = normalize(normal); + + vec3 aux, ldir; + vec4 d,a; + if (light.position[3] == 1.0) + { + aux = vec3(light.position-pixelpos); + ldir = normalize(aux); + dist = length(aux); + } + else + { + ldir = normalize(vec3(light.position)); + dist = 0.0; + } + + halfVector = normalize(light.halfVector.xyz); + + /* Compute the diffuse, ambient and globalAmbient terms */ + d = gl_FrontMaterial.diffuse * light.diffuse; + + /* The ambient terms have been separated since one of them */ + /* suffers attenuation */ + a = gl_FrontMaterial.ambient * light.ambient; + + /* compute the dot product between normal and normalized lightdir */ + NdotL = dot(n,ldir); + +#define SHADOW_FUZZ 0.1 + + if (NdotL > 0.0) { + NdotL = ((1.0 - SHADOW_FUZZ) * NdotL) + SHADOW_FUZZ; + + att = 1.0 / (light.constantAttenuation + + light.linearAttenuation * dist + + light.quadraticAttenuation * dist * dist); + color = att * (d * NdotL + a); + + + halfV = normalize(halfVector); + NdotHV = max(dot(n,halfV),0.0); + + //spec = att * gl_FrontMaterial.specular * light.specular * pow(NdotHV,gl_FrontMaterial.shininess); + spec = att * white * light.specular * pow(NdotHV,10.0); + + } + else if (NdotL > (-1.0 * SHADOW_FUZZ)) { + float fraction; + NdotL = (NdotL+SHADOW_FUZZ); + fraction = NdotL / SHADOW_FUZZ; + + att = 1.0 / (light.constantAttenuation + + light.linearAttenuation * dist + + light.quadraticAttenuation * dist * dist); + color = att * fraction * (d * NdotL + a); + + halfV = normalize(halfVector); + NdotHV = max(dot(n,halfV),0.0); + + //spec = att * fraction * gl_FrontMaterial.specular * light.specular * pow(NdotHV,gl_FrontMaterial.shininess); + spec = att * white * light.specular * pow(NdotHV,10.0); + + } + + + // blend mode SCREEN + color = white - ((white - color) * (white - incolor)); + // blend mode AVG + //color = (color + incolor) * 0.5; + // blend mode LIGHTEN + //color = max(color, incolor); + // blend mode OVERLAY + //color = overlay_blend(incolor, color); + // blend mode DODGE + //color = incolor / (white - color); + // blend mode MULTIPLY + //color = color * incolor; + + color += clamp(spec, 0.0, 1.0); + return clamp(color, 0.0, 1.0); + +} + +void main() +{ + vec4 color = ambientGlobal; + vec4 white = vec4(1.0, 1.0, 1.0, 1.0); + //color = white; + + color = process_lightsource(gl_LightSource[0], color); + color = process_lightsource(gl_LightSource[1], color); + color = process_lightsource(gl_LightSource[2], color); + color = process_lightsource(gl_LightSource[3], color); + color = process_lightsource(gl_LightSource[4], color); + color = process_lightsource(gl_LightSource[5], color); + color = process_lightsource(gl_LightSource[6], color); + color = process_lightsource(gl_LightSource[7], color); + + vec4 texcolor = texture2D(tex, gl_TexCoord[0].st); + gl_FragColor = clamp(texcolor * color, 0.0, 1.0); + // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + +} \ No newline at end of file diff --git a/data/shaders/standard.vert b/data/shaders/standard.vert new file mode 100644 index 0000000..9d75179 --- /dev/null +++ b/data/shaders/standard.vert @@ -0,0 +1,15 @@ +varying vec4 ambientGlobal/*,ambientA[8],diffuseA[8]*/; +varying vec3 normal/*,lightDirA[8],halfVectorA[8]*/; +/*varying float distA[8];*/ +varying vec4 pixelpos; + +void main() +{ + normal = normalize(gl_NormalMatrix * gl_Normal); + + pixelpos = gl_ModelViewMatrix * gl_Vertex; + ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient; + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_Position = ftransform(); +} diff --git a/data/shaders/test.frag b/data/shaders/test.frag new file mode 100644 index 0000000..03f0e92 --- /dev/null +++ b/data/shaders/test.frag @@ -0,0 +1,12 @@ +varying vec3 normal; +varying vec3 lightdir; +uniform sampler2D tex; + +void main() +{ + float intensity; + intensity = dot(lightdir, normalize(normal)); + + var; + gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * vec4(intensity, intensity, intensity, 1.0); +} \ No newline at end of file diff --git a/data/shaders/test.vert b/data/shaders/test.vert new file mode 100644 index 0000000..5cdab5e --- /dev/null +++ b/data/shaders/test.vert @@ -0,0 +1,13 @@ +varying vec3 normal; +varying vec3 lightdir; + +void main() +{ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + normal = gl_NormalMatrix * gl_Normal; + vec4 newpos = ftransform(); + gl_Position = newpos; + + lightdir = normalize(vec3(gl_LightSource[0].position) - vec3(gl_ModelViewMatrix * gl_Vertex)); +} \ No newline at end of file diff --git a/data/sprite/bluelight_static.png b/data/sprite/bluelight_static.png new file mode 100644 index 0000000..d7197da Binary files /dev/null and b/data/sprite/bluelight_static.png differ diff --git a/data/sprite/fuzzy_particle.png b/data/sprite/fuzzy_particle.png new file mode 100644 index 0000000..b27b654 Binary files /dev/null and b/data/sprite/fuzzy_particle.png differ diff --git a/data/sprite/hard_particle.png b/data/sprite/hard_particle.png new file mode 100644 index 0000000..630fbec Binary files /dev/null and b/data/sprite/hard_particle.png differ diff --git a/data/sprite/medium_particle.png b/data/sprite/medium_particle.png new file mode 100644 index 0000000..ebfb3bb Binary files /dev/null and b/data/sprite/medium_particle.png differ diff --git a/data/sprite/redlight_static.png b/data/sprite/redlight_static.png new file mode 100644 index 0000000..abdd029 Binary files /dev/null and b/data/sprite/redlight_static.png differ diff --git a/data/sprite/soft_particle.png b/data/sprite/soft_particle.png new file mode 100644 index 0000000..09c5643 Binary files /dev/null and b/data/sprite/soft_particle.png differ diff --git a/data/sprite/star_sprite_inner.png b/data/sprite/star_sprite_inner.png new file mode 100644 index 0000000..a2d66b1 Binary files /dev/null and b/data/sprite/star_sprite_inner.png differ diff --git a/data/sprite/star_sprite_main.png b/data/sprite/star_sprite_main.png new file mode 100644 index 0000000..a9b4f77 Binary files /dev/null and b/data/sprite/star_sprite_main.png differ diff --git a/data/sprite/star_sprite_washout.png b/data/sprite/star_sprite_washout.png new file mode 100644 index 0000000..412fc27 Binary files /dev/null and b/data/sprite/star_sprite_washout.png differ diff --git a/data/sprite/whitelight_static.png b/data/sprite/whitelight_static.png new file mode 100644 index 0000000..b15444a Binary files /dev/null and b/data/sprite/whitelight_static.png differ diff --git a/data/sprite/yellowlight_static.png b/data/sprite/yellowlight_static.png new file mode 100644 index 0000000..78331a7 Binary files /dev/null and b/data/sprite/yellowlight_static.png differ diff --git a/data/xml/constants.xml b/data/xml/constants.xml new file mode 100644 index 0000000..4b97529 --- /dev/null +++ b/data/xml/constants.xml @@ -0,0 +1,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/xml/def/commodities.xml b/data/xml/def/commodities.xml new file mode 100644 index 0000000..d5a4c91 --- /dev/null +++ b/data/xml/def/commodities.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/data/xml/def/components.xml b/data/xml/def/components.xml new file mode 100644 index 0000000..44c7278 --- /dev/null +++ b/data/xml/def/components.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/xml/def/engines.xml b/data/xml/def/engines.xml new file mode 100644 index 0000000..b75e3c2 --- /dev/null +++ b/data/xml/def/engines.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/xml/def/factions.xml b/data/xml/def/factions.xml new file mode 100644 index 0000000..7b4dae9 --- /dev/null +++ b/data/xml/def/factions.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/data/xml/def/models.xml b/data/xml/def/models.xml new file mode 100644 index 0000000..42935d0 --- /dev/null +++ b/data/xml/def/models.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/xml/def/shaders.xml b/data/xml/def/shaders.xml new file mode 100644 index 0000000..87c9135 --- /dev/null +++ b/data/xml/def/shaders.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/data/xml/def/ships.xml b/data/xml/def/ships.xml new file mode 100644 index 0000000..5f0d76e --- /dev/null +++ b/data/xml/def/ships.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/xml/def/stellars.xml b/data/xml/def/stellars.xml new file mode 100644 index 0000000..15cf568 --- /dev/null +++ b/data/xml/def/stellars.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/xml/def/systems.xml b/data/xml/def/systems.xml new file mode 100644 index 0000000..df6d0af --- /dev/null +++ b/data/xml/def/systems.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/data/xml/def/weapons.xml b/data/xml/def/weapons.xml new file mode 100644 index 0000000..7b23f39 --- /dev/null +++ b/data/xml/def/weapons.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/xml/engines.xml b/data/xml/engines.xml new file mode 100644 index 0000000..5efd993 --- /dev/null +++ b/data/xml/engines.xml @@ -0,0 +1,20 @@ + + + LX-20 Light Freighter Engine + The LX-20 is one of the cheapest, simplest, and least effective engine designs available. It is commonly found equipped on the cheapest freighters, where its general reliability and the ease of finding replacement parts for it serves well. No reputable dealer would ever stock an engine this decrepit, but you can probably find a servicable one littering any spaceport since most people consider them useless. + 18000 + 0 + 150 + 3800 + eng_large + + + Plasma Vector Drive + This is the engine equipped as standard on the Kestrel fighter. Top-of-the-line by any account, there is no downside except the price. It's small and lightweight, and it provides tremendous speed and agility with a minimal fuel cost. + 0.05 + 25 + 22000 + 550000 + eng_advanced + + diff --git a/data/xml/factions.xml b/data/xml/factions.xml new file mode 100644 index 0000000..e93b0a7 --- /dev/null +++ b/data/xml/factions.xml @@ -0,0 +1,54 @@ + + + Government FactionGroup + -1 + + + Neutral FactionGroup + -1 + + + Criminal FactionGroup + -1 + + + Colonial Alliance Navy + 10000 + + + Colonial Alliance Police + 10000 + + + Associated Worlds Navy + 10000 + + + Associated Worlds Police + 10000 + + + Evon Naval Forces + 10000 + + + Evon Police Forces + 10000 + + + Royal Victorian Navy + 10000 + + + Victorian Police Forces + 10000 + + + Independent Defense Fleet + 10001 + + + Corsair Navy + 10002 + + diff --git a/data/xml/models.xml b/data/xml/models.xml new file mode 100644 index 0000000..3d49092 --- /dev/null +++ b/data/xml/models.xml @@ -0,0 +1,101 @@ + + + + star_sprite_washout + + 1.0,1.0,0.5,1.0 + + + star_sprite_main + + 1.0,1.0,0.7,1.0 + + + star_sprite_inner + + 1.0,1.0,1.0,1.0 + + + + + 1.0 + + + + + kestrel + kestrel + + + + + thor + + + + 0.5 + + + + + + navbuoy + + + + 1.0 + + + + + + + navbuoy + + + + 2.5 + + + + + + planet1 + 100.0 + + + + + soft_particle + + + + + + + hard_particle + + + + + + + medium_particle + + + + + + + kestrel + kestrel + + + + + planet1 + planet1_earthy + 1000.0 + + + diff --git a/data/xml/shaders.xml b/data/xml/shaders.xml new file mode 100644 index 0000000..be9262d --- /dev/null +++ b/data/xml/shaders.xml @@ -0,0 +1,22 @@ + + + standard + standard + + + test + test + + + sprite + sprite + + + shadow_pass1 + shadow_pass1 + + + shadow_pass2 + shadow_pass2 + + \ No newline at end of file diff --git a/data/xml/ships.xml b/data/xml/ships.xml new file mode 100644 index 0000000..d2f65dc --- /dev/null +++ b/data/xml/ships.xml @@ -0,0 +1,83 @@ + + + Spacetruck + m_fr_spacetruck + 55 + 64 + 35 + 15000 + 15000 + 2450 + 0 + 1 + The commercial backbone of the colonies, the Space Truck carries a lot of cargo and does it very cheaply. They are perfect for trading in heavily patrolled sectors, but in rougher areas their lack of defensive systems and voluminous cargo hold makes them an obvious target. + + + Kestrel + m_fi_kestrel + Graceful lines and top-end equipment make this fighter a favourite of civilian pilots. + 215 + 120 + 200 + 480 + 5 + 28 + 6 + 1 + + + Thor Class Battlestation + m_bs_thor + Massive and bristling with armaments and defenses, the Thor class battlestations are the Colonial Alliance's most powerful line of defense against any aggressor. Indeed, simulations show that in a best case scenario one of thsese battlestations could potentially defeat an entire foreign Navy single-handedly. + 451000000 + 6000000 + 140000 + 28 + + + Nav Buoy + m_misc_navbuoy0 + 1500 + + + Nav Buoy Test + m_misc_navbuoy_test + 1500 + + + Bob + m_pl_bob + 4.5e22 + + + + Starter Pack - Not for Resale + + + New pilots get this ship with this equipment + + + Thor Class Battlestation + + Massive and bristling with armaments and defenses, the Thor class battlestations are the Colonial Alliance's most powerful line of defense against any aggressor. Indeed, simulations show that in a best case scenario one of thsese battlestations could potentially defeat an entire foreign Navy single-handedly. + + + Bob + + A planet + + + + Nav Buoy + Navigation buoys are typically used to mark a route or a specific point in space. + + + + + Nav Buoy + Navigation buoys are typically used to mark a route or a specific point in space. + + + + + diff --git a/data/xml/stellars.xml b/data/xml/stellars.xml new file mode 100644 index 0000000..60def60 --- /dev/null +++ b/data/xml/stellars.xml @@ -0,0 +1,9 @@ + + + Bob + earthy + Bob is a rich agricultural planet, with a moderate industrial sector, large population centers, and a stable ecosystem. It's a pleasant place, with a little something for everyone, but is otherwise fairly nondescript. + 7.4e24 + 8552.3 + + \ No newline at end of file diff --git a/data/xml/weapons.xml b/data/xml/weapons.xml new file mode 100644 index 0000000..22bba03 --- /dev/null +++ b/data/xml/weapons.xml @@ -0,0 +1,22 @@ + + + Light Blaster + The staggering ubiquity of the blaster class weapons is due to their simplicity and reliability. This particular model is one of the smallest blaster models, and it is more of a mild deterrant than an actual combat weapon. Against any moderately capable fighter it would prove almost ineffective even in large numbers, and it would be absolutely laughable to suggest that it would be of any use at all against a larger ship. Still, they are often found on shuttles and small freighters hoping that any agressor will see that numerous guns are mounted without bothering to scan too closely. + 250 + 0.2 + 2 + w_lightblaster + + + 250 + wp_lightblaster + 1000 + + + hard_particle + + 400 + 20 + 20 + + \ No newline at end of file diff --git a/enums.py b/enums.py new file mode 100644 index 0000000..8e6b649 --- /dev/null +++ b/enums.py @@ -0,0 +1,51 @@ + +class enum(object): + pass + +def reverse(enumobj, value): + for name in dir(enumobj): + if name[0] == '_': + continue + if value == eval("enumobj.%s" % (name,)): + return name + + return None + + +# render types (for model.renderable_layer) +rt = enum() +rt.model = 0 # a 3d model made out of triangles, go figure! +rt.sprite = 1 # a 2d texture applied to a 2d plane. +rt.beam = 2 # a 2d plane between two points, similar to a sprite + +# rendering billboard modes (for model.renderable_layer) +rtbb = enum() +rtbb.none = 0 # not billboarded, has its own independent rotation +rtbb.full = 1 # the sprite always squarely faces the camera with no rotation, only its position is relevant +rtbb.yaxis = 2 # pitch and yaw axes are available for rotation, but rotation around the roll axis is always fixed to face the camera. + +# coordinate mode +cm = enum() +cm.universe = 0 +cm.camera = 1 +cm.relative = 2 +cm.aa_relative = 3 + +# log level +logl = enum() +logl.debug = 9 +logl.info = 8 +logl.warn = 4 +logl.err = 2 +logl.crit = 0 + +# pipelines +pl = enum() +pl.camera = 0 +pl.player = 1 +pl.model = 2 +pl.shadow = 3 +pl.particle = 4 +pl.sprite = 5 +pl.composite1 = 6 +pl.composite2 = 7 diff --git a/files.py b/files.py new file mode 100644 index 0000000..ceb6549 --- /dev/null +++ b/files.py @@ -0,0 +1,28 @@ +import os +import sys +import pygame + +def get_basedir(): + execpath = sys.argv[0] + execpath = os.path.split(execpath)[0] + if not execpath: + return '.' + return execpath + +class filemanager(object): + def __init__(self): + self.basepath = get_basedir() + self.datapath = "data" + + def path(self, *args): + return os.path.join(self.basepath, self.datapath, *args) + + def open(self, *args): + filename = self.path(*args) + return open(filename, 'rb') + + def png(self, *args): + filename = self.path(*args) + return pygame.image.load(filename) + +mgr = filemanager() diff --git a/files.pyc b/files.pyc new file mode 100755 index 0000000..f3a61b9 Binary files /dev/null and b/files.pyc differ diff --git a/gamedata.py b/gamedata.py new file mode 100644 index 0000000..638e76c --- /dev/null +++ b/gamedata.py @@ -0,0 +1,248 @@ +import glob +import os +try: + from xml.etree.cElementTree import parse +except ImportError: + from elementtree.ElementTree import parse +import files +import shader + +class MissingNode(object): + def __init__(self): + self.text = None + def get(self, name): + return None + +class GameDataTagDef(object): + def __init__(self): + self.multi = False + self.opt = False + self.type = None + self.default = None + +class GameDataNode(object): + def __init__(self): + self.dict = {} + def __setitem__(self, name, val): + self.dict[name] = val + def __getitem__(self, name): + return self.dict[name]._value + def __getattr__(self, name): + if name == 'dict': + raise AttributeError, name + try: + return self.dict[name] + except KeyError: + if name == '_value': + return None + raise AttributeError, name + def __setattr__(self, name, val): + if name == 'dict': + return object.__setattr__(self, name, val) + try: + self.dict[name] = val + except KeyError: + object.__setattr__(self, name, val) + def add_multi(self, key, value): + if not self.dict.has_key(key): + self.dict[key] = [] + self.dict[key].append(value) + def add_single(self, key, value): + self.dict[key] = value + def __repr__(self): + return """""" % (self.dict['_name'],) + def has_key(self, key): + return self.dict.has_key(key) + +class XMLGameDataReader(object): + def __init__(self, bin, xml): + self._bin = bin + self._xml = xml + self._tree = self.construct() + self._name = xml.tag + + + def value_as_type(self, value, type): + if type == 'string': + return value + elif type == 'bool': + if value and value[0].lower() in ('y', 't', '1'): + return True + else: + return False + elif type == 'int': + return int(value) + elif type == 'float': + return float(value) + elif type == 'csvarray': + # csvarrays are always ints... + return [int(x.strip()) for x in value.split(',')] + else: + raise TypeError, type + + def create_datatag_def(self, tag): + d = GameDataTagDef() + if tag.get('multiple') != None and tag.get('multiple')[0].lower() == 'y': + d.multi = True + if tag.get('optional') != None and tag.get('optional')[0].lower() == 'y': + d.opt = True + if tag.get('data') != None: + d.type = tag.get('data') + if tag.get('default') != None: + d.default = self.value_as_type(tag.get('default'), d.type) + d.opt = True + return d + + def create_attribute_def(self, tag): + return self.create_datatag_def(tag) + + def construct_node(self, bin, xml): + node = GameDataNode() + value = None + if bin.tag == 'datatag': + df = self.create_datatag_def(bin) + if df.type: + value = xml.text + if type(xml) == MissingNode and df.opt: + value = df.default + elif type(xml) == MissingNode: + raise ValueError, "Missing value for mandatory tag %s" % (bin.get('name'),) + elif df.type == 'bool': + # tag exists, and since it is a bool, that means it's True + value = True + else: + value = self.value_as_type(value, df.type) + + node['_value'] = value + elif bin.tag == 'attribute': + df = self.create_attribute_def(bin) + if df.type: + value = xml.get(bin.get('name')) + if value == None and df.opt: + value = df.default + elif not value: + raise ValueError, "Missing value for mandatory tag %s" % (bin.get('name'),) + else: + value = self.value_as_type(value, df.type) + + node['_value'] = value + + node['_def'] = df + node['_name'] = bin.get('name') + return node + + + def construct_recurse(self, bin, xml): + xmldict = {} + tagdict = {} + attrdict = {} + + if bin.tag == 'xml_binary_packing': + node = GameDataNode() + else: + node = self.construct_node(bin, xml) + + for child in bin.getchildren(): + if child.tag == 'datatag': + tagdict[child.get('name')] = child + elif child.tag == 'attribute': + attrdict[child.get('name')] = child + else: + raise ValueError + + xmlattrdict = {} + for k, v in xml.items(): + if not k in attrdict: + raise ValueError, "Key %s not a valid attribute: %s" % (k, attrdict.keys()) + continue + binchild = attrdict[k] + xmlchild = xml + xmlattrdict[k] = 0 + subnode = self.construct_node(binchild, xml) + if subnode._def.multi: + node.add_multi(k, subnode) + else: + node.add_single(k, subnode) + + xmltagdict = {} + for child in xml.getchildren(): + if not child.tag in tagdict: + raise ValueError + continue + binchild = tagdict[child.tag] + xmlchild = child + xmltagdict[child.tag] = 0 + subnode = self.construct_recurse(binchild, xmlchild) + if subnode._def.multi: + node.add_multi(child.tag, subnode) + else: + node.add_single(child.tag, subnode) + + missing = MissingNode() + for k in tagdict.keys(): + if not k in xmltagdict: + # Missing datatag + subnode = self.construct_node(tagdict[k], missing) + if not subnode._def.multi: + node.add_single(k, subnode) + else: + node.add_single(k, []) + + for k in attrdict.keys(): + if not k in xmlattrdict: + # Missing attribute + subnode = self.construct_node(attrdict[k], missing) + if not subnode._def.multi: + node.add_single(k, subnode) + else: + node.add_single(k, []) + + + + return node + + def construct(self): + rootname = self._bin.get('name') + assert rootname == self._xml.tag + + return self.construct_recurse(self._bin, self._xml) + + def __getattr__(self, name): + if name == 'tree': + raise AttributeError, name + return self._tree.__getattr__(name) + def __getitem__(self, name): + return self._tree.__getitem__(name) + + +def load_xml_files(binfile, xmlfile): + bintree = parse(binfile).getroot() + xmltree = parse(xmlfile).getroot() + + return XMLGameDataReader(bintree, xmltree) + + +def load_gamedata(): + bins = glob.glob(files.mgr.path("xml/def", "*.xml")) + xmls = glob.glob(files.mgr.path("xml", "*.xml")) + + binfns = [os.path.split(x)[1] for x in bins] + xmlfns = [os.path.split(x)[1] for x in xmls] + ffns = [] + for bfn in binfns: + if bfn in xmlfns: + ffns.append(bfn) + + 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) + dataobjs[dataobj._name] = dataobj + + shader.mgr.load_shaders(dataobjs['shaders']) + return dataobjs + + + diff --git a/gamedata.pyc b/gamedata.pyc new file mode 100755 index 0000000..4900692 Binary files /dev/null and b/gamedata.pyc differ diff --git a/gametimer.py b/gametimer.py new file mode 100644 index 0000000..f642d6c --- /dev/null +++ b/gametimer.py @@ -0,0 +1,41 @@ +import pygame + +def start_loop(): + global g_timer, g_elapsed + g_elapsed = 0 + g_elapsed_sec = 0.0 + g_timer = pygame.time.get_ticks() + +def next_frame(skipping=False): + global g_timer, g_elapsed, g_elapsed_sec + + newticks = pygame.time.get_ticks() + #if skipping: + # # reset g_timer to it's value from the previous frame + # g_timer -= g_elapsed + g_elapsed = newticks - g_timer + g_timer = newticks + g_elapsed_sec = float(g_elapsed) / 1000.0 + +def elapsed(): + """ + get the amount of time in milliseconds passed since the last frame was displayed + """ + return g_elapsed + +def elapsed_sec(): + """ + get the amount of time in seconds passed since the last frame was displayed + """ + return g_elapsed_sec + +def num_frames(delay, offset=0): + """ + if you want something to occur every "delay" milliseconds, + this will return the number of times you should make it happen + """ + global g_elapsed, g_timer + return int((g_timer - offset) / delay) - int((g_timer - g_elapsed - offset) / delay) + +def get_timer(): + return g_timer diff --git a/gametimer.pyc b/gametimer.pyc new file mode 100755 index 0000000..8d5adf6 Binary files /dev/null and b/gametimer.pyc differ diff --git a/inputs.py b/inputs.py new file mode 100644 index 0000000..61680b3 --- /dev/null +++ b/inputs.py @@ -0,0 +1,77 @@ +from pygame.locals import * +import video + +state = {} +commands = {} +bindings = { + K_LEFT: '+left', + K_RIGHT: '+right', + K_UP: '+up', + K_DOWN: '+down', + K_RETURN: 'select', + K_COMMA: '+leanleft', + K_PERIOD: '+leanright', + K_q: 'exit', + K_d: 'debug', + K_TAB: '+accel', + K_BACKSPACE: '+brake', +} +aliases = {} +keys = {} + +def keyup(key): + global commands, keys, bindings, aliases + if not key in keys: + return + del keys[key] + if key in bindings: + bind = bindings[key] + if bind in commands: + del commands[bind] + if bind and bind[1:] in state: + del state[bind[1:]] +def keydown(key): + global commands, keys, bindings, aliases + keys[key] = 0 + if key in bindings: + bind = bindings[key] + if bind in aliases: + "execute alias TODO" + elif bind and bind[0] == '+': + state[bind[1:]] = 0 + add_command(bind[1:]) + elif bind: + add_command(bind) + +def add_command(cmd): + global commands + + if not cmd in commands: + commands[cmd] = 1 + return + else: + commands[cmd] += 1 + +def received_command(cmd): + if cmd in commands: + if commands[cmd] > 0: + commands[cmd] -= 1 + return True + return False + +def received_command_multi(cmd): + if cmd in commands: + if commands[cmd] > 0: + commands[cmd] = 0 + return True + return False + +def next_frame(): + global commands + if video.skipping_next_frame(): + return + + commands = {} + + + diff --git a/looprun.bat b/looprun.bat new file mode 100644 index 0000000..c24d6b9 --- /dev/null +++ b/looprun.bat @@ -0,0 +1,5 @@ +@echo off +:restart +roc_test.py +pause +goto restart diff --git a/pipeline.py b/pipeline.py new file mode 100644 index 0000000..d4e860c --- /dev/null +++ b/pipeline.py @@ -0,0 +1,167 @@ +from OpenGL.GL import * +import shader +import physics +from py3dutil import * +from enums import * + +class pipeline_manager(object): + def __init__(self): + self.phase = 'move' + self.updates = [] + self.renders = [] + self.phases = [ + ('handle_input', {}), + ('ai', {}), + ('animate', {}), + ('move', {}), + ('collide', {'func': physics.mgr.postcollide}), + ('prerender', {}) + ] + self.pipelines = [ + ('camera', {}), + ('player', {'lighting': False, 'shader': 'standard'}), + ('model', {'lighting': False, 'shader': 'standard'}), +# ('shadow', {}), +# ('particle', {'lighting': False, 'depthsort': obarr(), 'nodepthbuffer': True, 'shader': 'sprite'}), +# ('sprite', {'lighting': False, 'depthsort': obarr(), 'nodepthbuffer': True, 'shader': 'sprite'}), + ('composite1', {}), + ('composite2', {}), + + ] + self.phase_index = {} + for i, phase in enumerate(self.phases): + self.phase_index[phase[0]] = i + self.updates.append(obarr()) + + self.pipeline_index = {} + for i, pipe in enumerate(self.pipelines): + self.pipeline_index[pipe[0]] = i + self.renders.append(obarr()) + + + def update(self): + for i, updarr in enumerate(self.updates): + phase = self.phases[i] + self.phase = phase[0] + retval = False + repeat_count = 1 + if 'repeat' in phase and phase[1]['repeat']: + repeat_count = phase[1]['repeat'] + while repeat_count > 0: + if 'func' in phase: + retval = phase['func']() + else: + for o in updarr: + c = eval("o.%s" % (phase[0],)) + if callable(c): + rv = c() + if rv: + retval = rv + + if not ('repeat' in phase and phase[1]['repeat']) or retval: + repeat_count -= 1 + else: + if 'fail_func' in phase[1]: + phase[1]['fail_func']() + break + + physics.mgr.postcollide() + + def render(self): + for i, renarr in enumerate(self.renders): + for ren in renarr: + ren.owner.calc_render_pos() + for i, renarr in enumerate(self.renders): + type, typedata = self.pipelines[i] + if 'depthsort' in typedata: + depthsort = typedata['depthsort'] + depthsort.resize(len(renarr)) + for i in range(len(renarr)): + depthsort[i] = renarr[i].owner.render_pos.mag() + renarr.sort(depthsort) + + + + lighting_on = 'lighting' in typedata and typedata['lighting'] + shader_on = 'shader' in typedata + depth_off = 'nodepthbuffer' in typedata and typedata['nodepthbuffer'] + if lighting_on: + glEnable(GL_LIGHTING) + if shader_on: + shader.mgr.select(typedata['shader']) + if depth_off: + glDepthMask(GL_FALSE) + + for o in renarr: + if lighting_on: + o.owner.illuminate() + o.owner.render(o.layer) + + if depth_off: + glDepthMask(GL_TRUE) + if lighting_on: + glDisable(GL_LIGHTING) + if shader_on: + shader.mgr.select("ffp") + for i, renarr in enumerate(self.renders): + for ren in renarr: + ren.owner.clear_render_pos() + + + +mgr = pipeline_manager() + +def register_ship(obj): + render_pipes = ('model',) + update_pipes = ('ai', 'move', 'collide') + register(obj, update_pipes) + +def register_player(obj): + render_pipes = ('model',) + update_pipes = ('handle_input', 'move', 'collide') + register(obj, update_pipes) + +def register_particles(obj): + render_pipes = ('particle',) + update_pipes = ('move',) + register(obj, update_pipes) + +def register_direct(obj, update_pipes, render_pipes): + assert False + obj._pipeline_update = tuple(update_pipes) + obj._pipeline_render = tuple(render_pipes) + + for phase in update_pipes: + i = mgr.phase_index[phase] + mgr.updates[i].append(obj) + + for pipe in render_pipes: + i = mgr.pipeline_index[pipe] + mgr.renders[i].append(obj) + +def register(obj, update_pipes): + obj._pipeline_update = tuple(update_pipes) + + for phase in update_pipes: + i = mgr.phase_index[phase] + mgr.updates[i].append(obj) + + for lc in obj.layers: + i = lc.layer.pipeline + mgr.renders[i].append(lc) + + +def unregister(obj): + update = obj._pipeline_update + + del obj._pipeline_update + + for lc in obj.layers: + ir = lc.layer.pipeline + mgr.renders[ir].remove(lc) + + for u in update: + iu = mgr.phase_index[u] + mgr.updates[iu].remove(obj) + + diff --git a/refuge.py b/refuge.py new file mode 100755 index 0000000..44ab9e8 --- /dev/null +++ b/refuge.py @@ -0,0 +1,97 @@ +#!/usr/local/bin/python2.4 + +import pygame +from pygame.locals import * +import os +import sys +import math +import random +import inputs +import gamedata +import gametimer +import video +import glwrapper +import init_universe +import universe +import time +import components +try: + from PIL import PngImagePlugin +except: + import PngImagePlugin +from gameobj import * +from player import * +from particles import * +from ai import * + +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() +init_universe.init() +view = None +skipping = False +while True: + events = pygame.event.get() + #if skipping: + # print "SKIPPING! Forced? %s" % (video.get_forced_redraw(),) + gametimer.next_frame(skipping) + """ + if guiscreen != None or guidlg != None: + video.force_redraw() # irrelevant right now, but when we exit the gui, we'll need a full redraw! + for ev in events: + if ev.type == QUIT: + inputs.add_command('exit') + break + if 'exit' in inputs.commands: + break + if guiscreen: + guiscreen.distribute_events(*events) + continue + """ + 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 + + #map.handle_keys(keys) + #units.mgr.update() + #view.update() + + #if video.get_forced_redraw(): + # video.get_scr().fill((0,0,0)) + + #skipping = video.skipping_next_frame() + + + if not skipping: + universe.next_frame() + video.predraw() + universe.render() + + if not skipping: + video.next_frame() + inputs.next_frame() + else: + video.reset_skipping() + + + diff --git a/roc_test.py b/roc_test.py new file mode 100644 index 0000000..9f39b7e --- /dev/null +++ b/roc_test.py @@ -0,0 +1,19 @@ +import pygame +from pygame.locals import * +import gamedata +import gametimer +import video +import shader + +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() diff --git a/shader.py b/shader.py new file mode 100644 index 0000000..a0ab67f --- /dev/null +++ b/shader.py @@ -0,0 +1,194 @@ +import ctypes +from OpenGL.GL import * +try: + import OpenGL.raw.GL + raw = OpenGL.raw +except ImportError: + pass +from OpenGL.arrays import GLintArray, GLcharArray, GLsizeiArray, GLcharARBArray +import sys + +class shader_manager(object): + def __init__(self): + # Fixed Pipeline is always zero + self.shaderlib = {'ffp': 0} + self.shaderprograms = {} + self.shadersources = [] + def use_gl2_shaders(self): + self.funcs = { + 'create': glCreateShader, + 'source': glShaderSource, + 'compile': glCompileShader, + 'program': glCreateProgram, + 'attach': glAttachShader, + 'link': glLinkProgram, + 'use': glUseProgram, + 'param': glGetShaderiv, + 'uniform': glUniform4f, + 'arraytype': GLcharArray + } + def use_raw_shaders(self): + self.funcs = { + 'create': raw.GL.glCreateShader, + 'source': raw.GL.glShaderSource, + 'compile': raw.GL.glCompileShader, + 'program': raw.GL.glCreateProgram, + 'attach': raw.GL.glAttachShader, + 'link': raw.GL.glLinkProgram, + 'use': raw.GL.glUseProgram, + 'param': raw.GL.glGetShaderiv + } + + def use_arb_shaders(self): + from OpenGL.GL.ARB import shader_objects + if not shader_objects.glInitShaderObjectsARB(): + raise RuntimeError("ARB Shaders failed to initialize") + + self.funcs = { + 'create': shader_objects.glCreateShaderObjectARB, + 'source': shader_objects.glShaderSourceARB, + 'compile': shader_objects.glCompileShaderARB, + 'program': shader_objects.glCreateProgramObjectARB, + 'attach': shader_objects.glAttachObjectARB, + 'link': shader_objects.glLinkProgramARB, + 'use': shader_objects.glUseProgramObjectARB, + 'uniform': shader_objects.glUniform4fARB, + 'param': shader_objects.glGetObjectParameterivARB + } + def use_arb_new_shaders(self): + from OpenGL.GL.ARB import shader_objects_new + shader_objects = shader_objects_new + if not shader_objects.glInitShaderObjectsARB(): + raise RuntimeError("ARB New Shaders failed to initialize") + + self.funcs = { + 'create': shader_objects.glCreateShaderObjectARB, + 'source': shader_objects.base_glShaderSourceARB, + 'compile': shader_objects.glCompileShaderARB, + 'program': shader_objects.glCreateProgramObjectARB, + 'attach': shader_objects.glAttachObjectARB, + 'link': shader_objects.glLinkProgramARB, + 'use': shader_objects.glUseProgramObjectARB, + 'param': shader_objects.glGetObjectParameterivARB, + 'arraytype': GLcharARBArray + } + + def init_gl(self): + import files + #print glGetString(GL_EXTENSIONS) + if True: + self.use_gl2_shaders() + else: + self.use_arb_shaders() + #self.use_gl2_shaders() + + for name, vertex, fragment in self.shadersources: + vf = files.mgr.open('shaders/%s.vert' % (vertex,)) + ff = files.mgr.open('shaders/%s.frag' % (fragment,)) + vs = self.funcs['create'](GL_VERTEX_SHADER) + fs = self.funcs['create'](GL_FRAGMENT_SHADER) + self.funcs['source'](vs, vf.read()) + self.funcs['source'](fs, ff.read()) + rv = self.funcs['compile'](vs) + rv = self.funcs['compile'](fs) + sp = self.funcs['program']() + self.funcs['attach'](sp, vs) + self.funcs['attach'](sp, fs) + rv = self.funcs['link'](sp) + self.shaderlib[name] = sp + self.shaderprograms[name] = (vs, fs) + + def detect(self): + shaderlist = [ + ('GL2', self.use_gl2_shaders), + ('ARB', self.use_arb_shaders), + ('ARBNEW', self.use_arb_new_shaders), + ('RAW', self.use_raw_shaders) + ] + + workable_shaders = [] + + for shadername, shaderinit in shaderlist: + try: + shaderinit() + except: + print "Shader type %s failed to initialize" % (shadername,) + continue + try: + self.select("ffp") + except: + print "Shader type %s failed to access the fixed function pipeline" % (shadername,) + continue + try: + self.select("standard") + except: + print "Shader type %s failed to load the \"standard\" vertex and fragment shaders" % (shadername,) + continue + + workable_shaders.append(shadername) + + return workable_shaders + + + def init_shadertype(self, shadertype): + if shadertype == "GL2": + self.use_gl2_shaders() + elif shadertype == "ARB": + self.use_arb_shaders() + elif shadertype == "ARBNEW": + self.use_arb_new_shaders() + elif shadertype == "RAW": + self.use_raw_shaders() + + + + def select(self, shader): + if self.shadersources: + self.init_gl() + self.shadersources = [] + if not shader in self.shaderlib: + self.funcs['use'](0) + return True + try: + self.funcs['use'](self.shaderlib[shader]) + except GLError: + p = self.shaderlib[shader] + v, f = self.shaderprograms[shader] + print "Shader failed to execute: %s" % (shader,) + print "Vertex shader log:" + lenarr = GLintArray.zeros(1) + glGetShaderiv(v, GL_INFO_LOG_LENGTH, lenarr) + infoarr = GLcharArray.zeros(lenarr[0]) + outsize = GLsizeiArray.zeros(1) + glGetShaderInfoLog(v, lenarr[0], outsize, infoarr) + print ''.join([chr(x) for x in infoarr[:outsize[0]]]) + print "Fragment shader log:" + lenarr = GLintArray.zeros(1) + glGetShaderiv(f, GL_INFO_LOG_LENGTH, lenarr) + infoarr = GLcharArray.zeros(lenarr[0]) + outsize = GLsizeiArray.zeros(1) + glGetShaderInfoLog(f, lenarr[0], outsize, infoarr) + print ''.join([chr(x) for x in infoarr[:outsize[0]]]) + print "Program info log:" + lenarr = GLintArray.zeros(1) + glGetProgramiv(p, GL_INFO_LOG_LENGTH, lenarr) + infoarr = GLcharArray.zeros(lenarr[0]) + outsize = GLsizeiArray.zeros(1) + glGetProgramInfoLog(p, lenarr[0], outsize, infoarr) + print ''.join([chr(x) for x in infoarr[:outsize[0]]]) + glDeleteShader(v) + glDeleteShader(f) + glDeleteProgram(p) + del self.shaderprograms[shader] + del self.shaderlib[shader] + glUseProgram(0) + + return False + + return True + + def load_shaders(self, shaders): + for shader in shaders.shader: + self.shadersources.append((shader['id'], shader['vertex'], shader['fragment'])) + +mgr = shader_manager() diff --git a/shader.pyc b/shader.pyc new file mode 100755 index 0000000..fedb279 Binary files /dev/null and b/shader.pyc differ diff --git a/video.py b/video.py new file mode 100644 index 0000000..d04334a --- /dev/null +++ b/video.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python2.4 + +from OpenGL.GL import * +from OpenGL.GLU import * +from OpenGL.arrays import GLcharArray +import pygame +from pygame.locals import * +import sys + +def enable_vsync(): + if sys.platform != 'darwin': + return + try: + import ctypes + import ctypes.util + ogl = ctypes.cdll.LoadLibrary(ctypes.util.find_library("OpenGL")) + v = ctypes.c_int(1) + ogl.CGLSetParameter(ogl.CGLGetCurrentContext(), ctypes.c_int(222), ctypes.pointer(v)) + except: + print "Unable to set vsync mode, using driver defaults" +def skipping_next_frame(): + return False +def set_res((width, height)): + if height==0: + height=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) + #print pygame.display.gl_get_attribute(GL_DEPTH_SIZE) + glViewport(0, 0, width, height) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + gluPerspective(45, 1.0*width/height, 1.0, 10e6) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + +def init(): + import shader + glShadeModel(GL_SMOOTH) + glClearColor(0.0, 0.0, 0.0, 0.0) + glClearDepth(1.0) + glEnable(GL_DEPTH_TEST) + glEnable(GL_CULL_FACE) + glEnable(GL_TEXTURE_2D) + glDepthFunc(GL_LEQUAL) + #glEnable(GL_BLEND) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1) + """ + """ + LightAmbient = ( (0.2, 0.2, 0.2, 1.0) ) + LightDiffuse = ( (0.5, 0.5, 0.5, 1.0) ) + LightPosition = ( (0.0, 0.2, 2.0, 1.0) ) + glEnable(GL_LIGHTING) + glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient ) + glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiffuse ) + glLightfv( GL_LIGHT1, GL_POSITION, LightPosition ) + glEnable( GL_LIGHT1 ) + """ + """ + 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) + +def next_frame(): + pygame.display.flip() + + + +if __name__ == '__main__': main() + diff --git a/video.pyc b/video.pyc new file mode 100755 index 0000000..0a6d6c3 Binary files /dev/null and b/video.pyc differ