working textures!
completely overhauled models framework... now loads Model, Mesh, Material, and Texture (plus TextureFile) fixed a number of bugs/inflexibilities in gamedata xml parser refactored the various modules to use "init" functions to better control when they get loaded (ie, before or after OpenGL init) which it turns out is *very important*, because if the shaders and textures get loaded before OpenGL does, they don't work. go figure.
This commit is contained in:
parent
edd7630844
commit
deaa55d535
14 changed files with 440 additions and 359 deletions
6
asset.py
6
asset.py
|
@ -10,4 +10,8 @@ class asset_manager(object):
|
|||
return go
|
||||
|
||||
|
||||
mgr = asset_manager()
|
||||
def init():
|
||||
global mgr
|
||||
mgr = asset_manager()
|
||||
|
||||
mgr = None
|
||||
|
|
|
@ -1,23 +1,37 @@
|
|||
<xml_binary_packing name="models">
|
||||
<datatag name="mesh" multiple="yes">
|
||||
<attribute name="id" data="string"/>
|
||||
<datatag name="file" data="string" default=""/>
|
||||
<datatag name="sprite" data="bool" default=""/>
|
||||
<datatag name="centered_sprite" data="bool" default=""/>
|
||||
</datatag>
|
||||
<datatag name="model" multiple="yes">
|
||||
<attribute name="id" data="string"/>
|
||||
<datatag name="render" multiple="yes">
|
||||
<attribute name="layer" data="int"/>
|
||||
<datatag name="model">
|
||||
<datatag name="file" data="string" default=""/>
|
||||
<datatag name="xaxis_index" data="int" default="0"/>
|
||||
<datatag name="yaxis_index" data="int" default="1"/>
|
||||
<datatag name="zaxis_index" data="int" default="2"/>
|
||||
<datatag name="mesh">
|
||||
<datatag name="ref" data="string" default=""/>
|
||||
<datatag name="xaxis" data="int" default="0"/>
|
||||
<datatag name="yaxis" data="int" default="1"/>
|
||||
<datatag name="zaxis" data="int" default="2"/>
|
||||
<datatag name="scale" data="float" default="1.0">
|
||||
<attribute name="x" data="float" default="1.0"/>
|
||||
<attribute name="y" data="float" default="1.0"/>
|
||||
<attribute name="z" data="float" default="1.0"/>
|
||||
</datatag>
|
||||
</datatag>
|
||||
<datatag name="texture" data="string" optional="yes" multiple="yes">
|
||||
<attribute name="layer" data="int" default="0"/>
|
||||
<datatag name="material">
|
||||
<datatag name="ref" data="string"/>
|
||||
<datatag name="color" optional="yes">
|
||||
<attribute name="r" data="float" default="1.0"/>
|
||||
<attribute name="g" data="float" default="1.0"/>
|
||||
<attribute name="b" data="float" default="1.0"/>
|
||||
<attribute name="a" data="float" default="1.0"/>
|
||||
</datatag>
|
||||
</datatag>
|
||||
<datatag name="sprite" data="string" default=""/>
|
||||
<datatag name="sprite_color" data="string" default=""/>
|
||||
<datatag name="billboard" data="bool" default=""/>
|
||||
<datatag name="beam_align" data="bool" default=""/>
|
||||
<datatag name="particle" data="bool" default=""/>
|
||||
<datatag name="scale" data="float" default="1.0"/>
|
||||
</datatag>
|
||||
<datatag name="light" multiple="yes">
|
||||
<datatag name="color" optional="yes">
|
||||
|
|
|
@ -3,9 +3,16 @@
|
|||
<attribute name="id" data="string"/>
|
||||
<datatag name="file" data="string"/>
|
||||
<datatag name="coords" optional="yes">
|
||||
<attribute name="x" data="int" default="-1" optional="yes"/>
|
||||
<attribute name="y" data="int" default="-1" optional="yes"/>
|
||||
<attribute name="x1" data="int" default="-1"/>
|
||||
<attribute name="y1" data="int" default="-1"/>
|
||||
<attribute name="x2" data="int" default="-1"/>
|
||||
<attribute name="y2" data="int" default="-1"/>
|
||||
<attribute name="x" data="int" default="-1"/>
|
||||
<attribute name="y" data="int" default="-1"/>
|
||||
<attribute name="h" data="int" default="-1"/>
|
||||
<attribute name="w" data="int" default="-1"/>
|
||||
</datatag>
|
||||
<datatag name="uniform" data="bool" default=""/>
|
||||
</datatag>
|
||||
<datatag name="material" multiple="yes">
|
||||
<attribute name="id" data="string"/>
|
||||
|
|
|
@ -1,101 +1,14 @@
|
|||
<models>
|
||||
<model id="m_star_yellow">
|
||||
<mesh id="mesh_sprite">
|
||||
<sprite/>
|
||||
</mesh>
|
||||
<mesh id="mesh_centered_sprite">
|
||||
<centered_sprite/>
|
||||
</mesh>
|
||||
<model id="m_test">
|
||||
<render layer="0">
|
||||
<sprite>star_sprite_washout</sprite>
|
||||
<billboard/>
|
||||
<sprite_color>1.0,1.0,0.5,1.0</sprite_color>
|
||||
</render>
|
||||
<render layer="1">
|
||||
<sprite>star_sprite_main</sprite>
|
||||
<billboard/>
|
||||
<sprite_color>1.0,1.0,0.7,1.0</sprite_color>
|
||||
</render>
|
||||
<render layer="2">
|
||||
<sprite>star_sprite_inner</sprite>
|
||||
<billboard/>
|
||||
<sprite_color>1.0,1.0,1.0,1.0</sprite_color>
|
||||
</render>
|
||||
<light>
|
||||
<color r="1.0" g="0.95" b="0.8"/>
|
||||
<sun/>
|
||||
<basepower>1.0</basepower>
|
||||
</light>
|
||||
</model>
|
||||
<model id="m_fi_kestrel">
|
||||
<render layer="0">
|
||||
<model><file>kestrel</file></model>
|
||||
<texture>kestrel</texture>
|
||||
</render>
|
||||
</model>
|
||||
<model id="m_bs_thor">
|
||||
<render layer="0">
|
||||
<model><file>thor</file></model>
|
||||
</render>
|
||||
<light>
|
||||
<color r="1.0" g="0.0" b="0.0"/>
|
||||
<basepower>0.5</basepower>
|
||||
<attenuation quadratic="0.0001"/>
|
||||
</light>
|
||||
</model>
|
||||
<model id="m_misc_navbuoy0">
|
||||
<render layer="0">
|
||||
<model><file>navbuoy</file></model>
|
||||
</render>
|
||||
<light>
|
||||
<color r="0.0" g="1.0" b="0.0"/>
|
||||
<basepower>1.0</basepower>
|
||||
<attenuation quadratic="0.000001"/>
|
||||
|
||||
</light>
|
||||
</model>
|
||||
<model id="m_misc_navbuoy_test">
|
||||
<render layer="0">
|
||||
<model><file>navbuoy</file></model>
|
||||
</render>
|
||||
<light>
|
||||
<color r="0.0" g="0.0" b="1.0"/>
|
||||
<basepower>2.5</basepower>
|
||||
<attenuation quadratic="0.00000001"/>
|
||||
</light>
|
||||
</model>
|
||||
<model id="m_planet_bob">
|
||||
<render layer="0">
|
||||
<model><file>planet1</file></model>
|
||||
<scale>100.0</scale>
|
||||
</render>
|
||||
</model>
|
||||
<model id="p_soft">
|
||||
<render layer="0">
|
||||
<sprite>soft_particle</sprite>
|
||||
<billboard/>
|
||||
<particle/>
|
||||
</render>
|
||||
</model>
|
||||
<model id="p_hard">
|
||||
<render layer="0">
|
||||
<sprite>hard_particle</sprite>
|
||||
<billboard/>
|
||||
<particle/>
|
||||
</render>
|
||||
</model>
|
||||
<model id="p_medium">
|
||||
<render layer="0">
|
||||
<sprite>medium_particle</sprite>
|
||||
<billboard/>
|
||||
<particle/>
|
||||
</render>
|
||||
</model>
|
||||
<model id="m_fr_spacetruck">
|
||||
<render layer="0">
|
||||
<model><file>kestrel</file></model>
|
||||
<texture>kestrel</texture>
|
||||
</render>
|
||||
</model>
|
||||
<model id="m_pl_bob">
|
||||
<render layer="0">
|
||||
<model><file>planet1</file></model>
|
||||
<texture>planet1_earthy</texture>
|
||||
<scale>1000.0</scale>
|
||||
<mesh><ref>mesh_sprite</ref><scale x="200" y="200"/></mesh>
|
||||
<material><ref>mat_test</ref></material>
|
||||
</render>
|
||||
</model>
|
||||
</models>
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
<textures>
|
||||
<texture id="t_black">
|
||||
<file>tex/black.png</file>
|
||||
<coords/>
|
||||
<uniform/>
|
||||
</texture>
|
||||
<texture id="t_white">
|
||||
<file>tex/white.png</file>
|
||||
<uniform/>
|
||||
</texture>
|
||||
<texture id="tnm_flat">
|
||||
<file>tex/nm_flat.png</file>
|
||||
<uniform/>
|
||||
</texture>
|
||||
<material id="m_blank">
|
||||
<material id="mat_blank">
|
||||
<texture ref="t_white" type="diffuse"/>
|
||||
<texture ref="tnm_black" type="normal"/>
|
||||
<texture ref="tnm_flat" type="normal"/>
|
||||
</material>
|
||||
<texture id="t_test">
|
||||
<file>tex/test1.png</file>
|
||||
|
@ -21,7 +25,7 @@
|
|||
<texture id="t_test_plasma2">
|
||||
<file>tex/plasma2.png</file>
|
||||
</texture>
|
||||
<material id="m_test">
|
||||
<texture ref="t_test">
|
||||
<material id="mat_test">
|
||||
<texture ref="t_test"/>
|
||||
</material>
|
||||
</textures>
|
20
enums.py
20
enums.py
|
@ -1,16 +1,32 @@
|
|||
|
||||
class enum(object):
|
||||
pass
|
||||
def __len__(self):
|
||||
return len([x for x in dir(self) if x[0] != '_'])
|
||||
|
||||
def __iter__(self):
|
||||
for name in sequence(self):
|
||||
yield getattr(self, name)
|
||||
|
||||
def index(enumobj, name):
|
||||
return getattr(enumobj, name)
|
||||
|
||||
def reverse(enumobj, value):
|
||||
for name in dir(enumobj):
|
||||
if name[0] == '_':
|
||||
continue
|
||||
if value == eval("enumobj.%s" % (name,)):
|
||||
if value == getattr(enumobj, name):
|
||||
return name
|
||||
|
||||
return None
|
||||
|
||||
def sequence(enumobj):
|
||||
retlist = []
|
||||
for name in dir(enumobj):
|
||||
if name[0] == '_':
|
||||
continue
|
||||
retlist.append((getattr(enumobj, name), name))
|
||||
|
||||
return [x[1] for x in sorted(retlist)]
|
||||
|
||||
# render types (for model.renderable_layer)
|
||||
rt = enum()
|
||||
|
|
9
files.py
9
files.py
|
@ -24,5 +24,12 @@ class filemanager(object):
|
|||
def png(self, *args):
|
||||
filename = self.path(*args)
|
||||
return pygame.image.load(filename)
|
||||
|
||||
def canonize_path(self, path):
|
||||
return path.lower()
|
||||
|
||||
mgr = filemanager()
|
||||
def init():
|
||||
global mgr
|
||||
mgr = filemanager()
|
||||
|
||||
mgr = None
|
||||
|
|
85
gamedata.py
85
gamedata.py
|
@ -24,6 +24,8 @@ class GameDataTagDef(object):
|
|||
class GameDataNode(object):
|
||||
def __init__(self):
|
||||
self.dict = {}
|
||||
self.missing = False
|
||||
|
||||
def __setitem__(self, name, val):
|
||||
self.dict[name] = val
|
||||
def __getitem__(self, name):
|
||||
|
@ -97,20 +99,24 @@ class XMLGameDataReader(object):
|
|||
def create_attribute_def(self, tag):
|
||||
return self.create_datatag_def(tag)
|
||||
|
||||
def construct_node(self, bin, xml):
|
||||
def construct_node(self, bin, xml, allow_missing=False):
|
||||
node = GameDataNode()
|
||||
if isinstance(xml, MissingNode):
|
||||
node.missing = True
|
||||
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:
|
||||
if df.type == 'bool':
|
||||
# if tag exists, since it is a bool, that means it's True
|
||||
value = not node.missing
|
||||
elif (node.missing or value == None) and df.opt:
|
||||
value = df.default
|
||||
elif type(xml) == MissingNode:
|
||||
elif (node.missing or value == None) and not allow_missing:
|
||||
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
|
||||
elif (node.missing or value == None):
|
||||
value = None
|
||||
else:
|
||||
value = self.value_as_type(value, df.type)
|
||||
|
||||
|
@ -121,8 +127,10 @@ class XMLGameDataReader(object):
|
|||
value = xml.get(bin.get('name'))
|
||||
if value == None and df.opt:
|
||||
value = df.default
|
||||
elif not value:
|
||||
elif not value and not allow_missing:
|
||||
raise ValueError, "Missing value for mandatory tag %s" % (bin.get('name'),)
|
||||
elif not value:
|
||||
value = None
|
||||
else:
|
||||
value = self.value_as_type(value, df.type)
|
||||
|
||||
|
@ -133,7 +141,7 @@ class XMLGameDataReader(object):
|
|||
return node
|
||||
|
||||
|
||||
def construct_recurse(self, bin, xml):
|
||||
def construct_recurse(self, bin, xml, allow_missing=False):
|
||||
xmldict = {}
|
||||
tagdict = {}
|
||||
attrdict = {}
|
||||
|
@ -141,7 +149,7 @@ class XMLGameDataReader(object):
|
|||
if bin.tag == 'xml_binary_packing':
|
||||
node = GameDataNode()
|
||||
else:
|
||||
node = self.construct_node(bin, xml)
|
||||
node = self.construct_node(bin, xml, allow_missing)
|
||||
|
||||
for child in bin.getchildren():
|
||||
if child.tag == 'datatag':
|
||||
|
@ -152,38 +160,41 @@ class XMLGameDataReader(object):
|
|||
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)
|
||||
|
||||
|
||||
if not isinstance(xml, MissingNode):
|
||||
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, allow_missing)
|
||||
if subnode._def.multi:
|
||||
node.add_multi(k, subnode)
|
||||
else:
|
||||
node.add_single(k, subnode)
|
||||
|
||||
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, allow_missing)
|
||||
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)
|
||||
subnode = self.construct_recurse(tagdict[k], missing, isinstance(xml, MissingNode))
|
||||
if not subnode._def.multi:
|
||||
node.add_single(k, subnode)
|
||||
else:
|
||||
|
@ -192,7 +203,7 @@ class XMLGameDataReader(object):
|
|||
for k in attrdict.keys():
|
||||
if not k in xmlattrdict:
|
||||
# Missing attribute
|
||||
subnode = self.construct_node(attrdict[k], missing)
|
||||
subnode = self.construct_node(attrdict[k], missing, isinstance(xml, MissingNode))
|
||||
if not subnode._def.multi:
|
||||
node.add_single(k, subnode)
|
||||
else:
|
||||
|
|
344
models.py
344
models.py
|
@ -1,4 +1,9 @@
|
|||
import enums
|
||||
import files
|
||||
import gamedata
|
||||
import pygame
|
||||
from OpenGL.GL import *
|
||||
from py3dutil import vect
|
||||
|
||||
class Vertex(object):
|
||||
__slots__ = [
|
||||
|
@ -7,39 +12,99 @@ class Vertex(object):
|
|||
't', # texture coordinates
|
||||
'c', # color
|
||||
]
|
||||
|
||||
def __init__(self, v, n, t, c):
|
||||
self.v = v
|
||||
self.n = n
|
||||
self.t = t
|
||||
self.c = c
|
||||
|
||||
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)
|
||||
pass
|
||||
|
||||
def create(self, mname):
|
||||
return self.models[mname].instance()
|
||||
|
||||
|
||||
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')
|
||||
|
||||
def load(self):
|
||||
self.load_textypes()
|
||||
self.load_textures()
|
||||
self.load_materials()
|
||||
self.load_models()
|
||||
|
||||
mgr = Model_Manager()
|
||||
def load_textypes(self):
|
||||
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.emissive] = 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)
|
||||
|
||||
for tt in self.textypes.values():
|
||||
tt.initialize()
|
||||
|
||||
|
||||
def load_textures(self):
|
||||
texdata = gamedata.get('textures')
|
||||
self.texture_files = {}
|
||||
self.texture_ids = {}
|
||||
self.textures = {}
|
||||
self.materials = {}
|
||||
for texd in texdata.texture:
|
||||
fp = files.mgr.canonize_path(texd['file'])
|
||||
if not fp in self.texture_files:
|
||||
tf = TextureFile()
|
||||
tf.load(fp)
|
||||
self.texture_files[fp] = tf
|
||||
self.texture_ids[tf.id] = tf
|
||||
else:
|
||||
tf = self.texture_files[fp]
|
||||
to = Texture()
|
||||
to.load(texd, tf)
|
||||
self.textures[to.id] = to
|
||||
|
||||
for matd in texdata.material:
|
||||
mo = Material()
|
||||
mo.load(matd)
|
||||
self.materials[mo.id] = mo
|
||||
|
||||
|
||||
def load_meshes(self):
|
||||
"ignored!!! meshes are contained in models.xml for now"
|
||||
return
|
||||
gamedata.get('meshes')
|
||||
|
||||
def load_materials(self):
|
||||
"ignored!!! materials are contained in textures.xml for now"
|
||||
return
|
||||
gamedata.get('materials')
|
||||
|
||||
|
||||
def load_models(self):
|
||||
mdldata = gamedata.get('models')
|
||||
self.meshes = {}
|
||||
self.models = {}
|
||||
for meshdata in mdldata.mesh:
|
||||
if meshdata['sprite']:
|
||||
mesh = SpriteMesh.singleton()
|
||||
elif meshdata['centered_sprite']:
|
||||
mesh = SpriteMeshCentered.singleton()
|
||||
else:
|
||||
mesh = Mesh.factory(meshdata)
|
||||
mgr.meshes[meshdata['id']] = mesh
|
||||
|
||||
for modeldata in mdldata.model:
|
||||
model = Model()
|
||||
model.load(modeldata)
|
||||
mgr.models[modeldata['id']] = model
|
||||
|
||||
class TextureType(object):
|
||||
def __init__(self, texunit, texdim, wrap_s=GL_CLAMP, wrap_t=GL_CLAMP, mag=GL_LINEAR, min=GL_LINEAR)
|
||||
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
|
||||
|
@ -64,32 +129,126 @@ class TextureType(object):
|
|||
|
||||
|
||||
class Material(object):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
def attach_texture(self, textype, texid):
|
||||
textype = mgr.get_textype(textype)
|
||||
textype.activate()
|
||||
self.id = None
|
||||
self.textures = {}
|
||||
self.texcoords = self.texcoords_notimpl
|
||||
self.texcoords_uniform = self.texcoords_notimpl
|
||||
|
||||
def texcoords_notimpl(self, u, v):
|
||||
raise NotImplementedError("No textures were associated with this material.")
|
||||
|
||||
def bind(self):
|
||||
for tt in enums.tt:
|
||||
if tt in self.textures:
|
||||
tto = mgr.get_textype(tt)
|
||||
tto.initialize()
|
||||
tex = self.textures[tt]
|
||||
tex.bind()
|
||||
|
||||
def load(self, data):
|
||||
self.id = data['id']
|
||||
prevtex = None
|
||||
for tex in data.texture:
|
||||
try:
|
||||
texobj = mgr.textures[tex['ref']]
|
||||
except KeyError:
|
||||
raise KeyError("""Material "%s" references invalid %s texture "%s".""" % (self.id, tex['type'], tex['ref']))
|
||||
|
||||
typeidx = enums.index(enums.tt, tex['type'])
|
||||
self.textures[typeidx] = texobj
|
||||
|
||||
if texobj.uniform:
|
||||
if self.texcoords_uniform == self.texcoords_notimpl:
|
||||
self.texcoords_uniform = texobj.texcoords
|
||||
else:
|
||||
if prevtex:
|
||||
assert texobj.texcoords(0.0, 0.0) == prevtex.texcoords(0.0, 0.0) and texobj.texcoords(1.0, 1.0) == prevtex.texcoords(1.0, 1.0)
|
||||
if self.texcoords == self.texcoords_notimpl:
|
||||
self.texcoords = texobj.texcoords
|
||||
prevtex = texobj
|
||||
|
||||
print self.textures
|
||||
|
||||
self.texid
|
||||
|
||||
class Texture(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def load(self, file):
|
||||
img = files.mgr.png(file)
|
||||
texid, = glGenTextures(1)
|
||||
self.id = None
|
||||
self.texid = None
|
||||
self.uniform = False
|
||||
self.x = None
|
||||
self.y = None
|
||||
self.h = None
|
||||
self.w = None
|
||||
|
||||
|
||||
def texcoords_subset(self, u, v):
|
||||
tf = mgr.texture_ids[self.texid]
|
||||
dest_x = float(self.x) / float(tf.w)
|
||||
dest_w = (float(self.x + self.w) / float(tf.w)) - dest_x
|
||||
dest_y = float(self.y) / float(tf.h)
|
||||
dest_h = (float(self.y + self.h) / float(tf.h)) - dest_y
|
||||
return (dest_x + (u * dest_w), dest_y + (v * dest_h))
|
||||
|
||||
def texcoords_direct(self, u, v):
|
||||
return (u, v)
|
||||
|
||||
def load(self, data, tf):
|
||||
self.id = data['id']
|
||||
self.texid = tf.id
|
||||
self.uniform = data['uniform']
|
||||
c = data.coords
|
||||
if c['x'] != -1 and c['y'] != -1 and c['h'] != -1 and c['w'] != -1:
|
||||
self.x = c['x']
|
||||
self.y = c['y']
|
||||
self.w = c['w']
|
||||
self.h = c['h']
|
||||
assert self.x < tf.w and self.w < tf.w and self.y < tf.h and self.h < tf.h
|
||||
self.texcoords = self.texcoords_subset
|
||||
elif c['x1'] != -1 and c['y1'] != -1 and c['x2'] != -1 and c['y2'] != -1:
|
||||
self.x = c['x1']
|
||||
self.y = c['y1']
|
||||
self.w = c['x2'] - self.x
|
||||
self.h = c['y2'] - self.y
|
||||
assert self.x < tf.w and self.w < tf.w and self.y < tf.h and self.h < tf.h
|
||||
self.texcoords = self.texcoords_subset
|
||||
else:
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.w = tf.w
|
||||
self.h = tf.h
|
||||
self.texcoords = self.texcoords_direct
|
||||
|
||||
def bind(self):
|
||||
glBindTexture(GL_TEXTURE_2D, self.texid)
|
||||
|
||||
class TextureFile(object):
|
||||
def __init__(self):
|
||||
self.id = None
|
||||
self.filename = None
|
||||
self.h = None
|
||||
self.w = None
|
||||
|
||||
def load(self, filename):
|
||||
self.filename = filename
|
||||
img = files.mgr.png(filename)
|
||||
texid = glGenTextures(1)
|
||||
print "Generated texture id %s" % (texid,)
|
||||
|
||||
self.id = texid
|
||||
|
||||
imgdata = pygame.image.tostring(img, "RGBA")
|
||||
imgr = img.get_rect()
|
||||
self.h = imgr.h
|
||||
self.w = imgr.w
|
||||
|
||||
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)
|
||||
dimension = GL_TEXTURE_2D
|
||||
glBindTexture(dimension, texid)
|
||||
glTexImage2D(dimension, 0, GL_RGBA8, imgr.w, imgr.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgdata)
|
||||
glBindTexture(dimension, 0)
|
||||
|
||||
class Model(object):
|
||||
|
||||
class Mesh(object):
|
||||
def __init__(self):
|
||||
self.vertexes = []
|
||||
|
||||
|
@ -101,26 +260,105 @@ class Model(object):
|
|||
def unset_rotation(self):
|
||||
glPopMatrix()
|
||||
|
||||
def bind_textures(self):
|
||||
glBindTexture(GL_TEXTURE_2D
|
||||
def unbind_textures(self):
|
||||
|
||||
def draw(self):
|
||||
self.bind_textures()
|
||||
def draw(self, texcoord):
|
||||
glBegin(GL_TRIANGLES)
|
||||
for v in self.vertexes:
|
||||
self.draw_vertex(v)
|
||||
glEnd(GL_TRIANGLES)
|
||||
self.unbind_textures()
|
||||
self.draw_vertex(v, texcoord)
|
||||
glEnd()
|
||||
|
||||
def draw_vertex(self, v):
|
||||
def draw_vertex(self, v, texcoord):
|
||||
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])
|
||||
glTexCoord2f(*texcoord(v.t[0], v.t[1]))
|
||||
glVertex3f(v.v.x, v.v.y, v.v.z)
|
||||
|
||||
|
||||
|
||||
|
||||
class SpriteMesh(Mesh):
|
||||
_SINGLETON = None
|
||||
|
||||
def __init__(self):
|
||||
Mesh.__init__(self)
|
||||
self.vertexes = [
|
||||
Vertex(vect(0.0, 0.0, 0.0), vect(0.0, 0.0, 1.0), (0.0, 0.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect(0.0, 1.0, 0.0), vect(0.0, 0.0, 1.0), (0.0, 1.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect(1.0, 0.0, 0.0), vect(0.0, 0.0, 1.0), (1.0, 0.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect(1.0, 0.0, 0.0), vect(0.0, 0.0, 1.0), (1.0, 0.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect(0.0, 1.0, 0.0), vect(0.0, 0.0, 1.0), (0.0, 1.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect(1.0, 1.0, 0.0), vect(0.0, 0.0, 1.0), (1.0, 1.0), (1.0, 1.0, 1.0)),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def return_singleton(cls):
|
||||
return cls._SINGLETON
|
||||
|
||||
@classmethod
|
||||
def singleton(cls):
|
||||
cls._SINGLETON = cls()
|
||||
cls.singleton = cls.return_singleton
|
||||
return cls._SINGLETON
|
||||
|
||||
|
||||
class SpriteMeshCentered(SpriteMesh):
|
||||
def __init__(self):
|
||||
SpriteMesh.__init__(self)
|
||||
self.vertexes = [
|
||||
Vertex(vect(-0.5, -0.5, 0.0), vect(0.0, 0.0, 1.0), (0.0, 0.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect( 0.5, -0.5, 0.0), vect(0.0, 0.0, 1.0), (1.0, 0.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect(-0.5, 0.5, 0.0), vect(0.0, 0.0, 1.0), (0.0, 1.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect( 0.5, -0.5, 0.0), vect(0.0, 0.0, 1.0), (1.0, 0.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect(-0.5, 0.5, 0.0), vect(0.0, 0.0, 1.0), (0.0, 1.0), (1.0, 1.0, 1.0)),
|
||||
Vertex(vect( 0.5, 0.5, 0.0), vect(0.0, 0.0, 1.0), (1.0, 1.0), (1.0, 1.0, 1.0)),
|
||||
]
|
||||
|
||||
|
||||
class Model(object):
|
||||
def __init__(self):
|
||||
self.layers = []
|
||||
|
||||
def load(self, data):
|
||||
tmplayers = []
|
||||
for rend in data.render:
|
||||
layernum = rend['layer']
|
||||
rl = RenderLayer(layernum)
|
||||
rl.load(rend)
|
||||
tmplayers.append((layernum, rl))
|
||||
|
||||
for ln, rl in sorted(tmplayers):
|
||||
self.layers.append(rl)
|
||||
|
||||
def instance(self):
|
||||
return self
|
||||
|
||||
def render(self):
|
||||
for layer in self.layers:
|
||||
layer.render()
|
||||
|
||||
class RenderLayer(object):
|
||||
def __init__(self, layernum):
|
||||
self.id = layernum
|
||||
self.mesh = None
|
||||
self.material = None
|
||||
self.color = [1.0, 1.0, 1.0, 1.0]
|
||||
self.scale = [1.0, 1.0, 1.0]
|
||||
|
||||
def load(self, layerdata):
|
||||
meshdata = layerdata.mesh
|
||||
matdata = layerdata.material
|
||||
self.mesh = mgr.meshes[meshdata['ref']]
|
||||
self.material = mgr.materials[matdata['ref']]
|
||||
self.color = [matdata.color['r'], matdata.color['g'], matdata.color['b'], matdata.color['a']]
|
||||
self.scale = [meshdata.scale['x'], meshdata.scale['y'], meshdata.scale['z']]
|
||||
self.scale = [x * meshdata['scale'] for x in self.scale]
|
||||
|
||||
def render(self):
|
||||
self.material.bind()
|
||||
glPushMatrix()
|
||||
glTranslatef(500.0, 300.0, 0.0)
|
||||
glScalef(*self.scale)
|
||||
self.mesh.draw(self.material.texcoords)
|
||||
glPopMatrix()
|
||||
|
||||
|
||||
class Sprite(object):
|
||||
def __init__(self):
|
||||
|
@ -143,4 +381,12 @@ class Sprite(object):
|
|||
self.corners = vl
|
||||
self.vertexes = [tl, bl, tr, bl, tr, br]
|
||||
|
||||
def set_texture(
|
||||
def set_texture(self):
|
||||
pass
|
||||
|
||||
def init():
|
||||
global mgr
|
||||
mgr = Model_Manager()
|
||||
mgr.load()
|
||||
|
||||
mgr = None
|
||||
|
|
72
roc.py
72
roc.py
|
@ -1,11 +1,9 @@
|
|||
import pygame
|
||||
from pygame.locals import *
|
||||
import gamedata
|
||||
import gametimer
|
||||
import files
|
||||
import video
|
||||
import shader
|
||||
import inputs
|
||||
from OpenGL.GL import *
|
||||
import models
|
||||
import roc_main
|
||||
|
||||
|
||||
def init2d():
|
||||
|
@ -16,6 +14,8 @@ def init3d():
|
|||
|
||||
def init(videoinit):
|
||||
pygame.init()
|
||||
files.init()
|
||||
shader.init()
|
||||
|
||||
size = width, height = (1600,1200)
|
||||
size = width, height = (1024,768)
|
||||
|
@ -23,64 +23,8 @@ def init(videoinit):
|
|||
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()
|
||||
models.init()
|
||||
|
||||
test_frame()
|
||||
|
||||
video.next_frame()
|
||||
def main():
|
||||
roc_main.mainloop()
|
||||
|
|
|
@ -211,5 +211,9 @@ class shader_manager(object):
|
|||
def load_shaders(self, shaders):
|
||||
for shader in shaders.shader:
|
||||
self.initshadersources.append((shader['id'], shader['vertex'], shader['fragment']))
|
||||
|
||||
mgr = shader_manager()
|
||||
|
||||
def init():
|
||||
global mgr
|
||||
mgr = shader_manager()
|
||||
|
||||
mgr = None
|
||||
|
|
69
sprite.py
69
sprite.py
|
@ -1,69 +0,0 @@
|
|||
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()
|
21
texture.py
21
texture.py
|
@ -1,21 +0,0 @@
|
|||
|
||||
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()
|
3
video.py
3
video.py
|
@ -70,7 +70,8 @@ def init2d():
|
|||
glDepthFunc(GL_GEQUAL)
|
||||
glEnable(GL_BLEND)
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
|
||||
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (0.3, 0.3, 0.3, 1.0))
|
||||
|
||||
shader.mgr.load()
|
||||
shader.mgr.init_gl()
|
||||
shader.mgr.select("ffp")
|
||||
|
|
Loading…
Add table
Reference in a new issue