comparison pytouhou/ui/texture.pyx @ 393:9e2cbb2c2c64

Implement THTX, uncompressed textures stored inside ANM files, and use it instead of pyglet’s own wrapper.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Wed, 06 Feb 2013 19:55:54 +0100
parents 45e1a9a37e66
children 3a7b36324611
comparison
equal deleted inserted replaced
392:45e1a9a37e66 393:9e2cbb2c2c64
13 ## 13 ##
14 14
15 from libc.stdlib cimport malloc, free 15 from libc.stdlib cimport malloc, free
16 16
17 import pyglet 17 import pyglet
18 from pyglet.gl import (glTexParameteri, 18 from pyglet.gl import (glTexParameteri, GL_TEXTURE_MIN_FILTER,
19 GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, GL_LINEAR) 19 GL_TEXTURE_MAG_FILTER, GL_LINEAR, GL_BGRA, GL_RGBA,
20 GL_RGB, GL_LUMINANCE, GL_UNSIGNED_BYTE,
21 GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4_REV,
22 glGenTextures, glBindTexture, glTexImage2D,
23 GL_TEXTURE_2D)
24 from ctypes import c_uint, byref
20 import os 25 import os
26
27 from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere?
21 28
22 29
23 cdef class TextureManager: 30 cdef class TextureManager:
24 def __init__(self, loader=None): 31 def __init__(self, loader=None):
25 self.loader = loader 32 self.loader = loader
31 self.textures[key] = self.load_texture(key) 38 self.textures[key] = self.load_texture(key)
32 return self.textures[key] 39 return self.textures[key]
33 40
34 41
35 def preload(self, anm_wrapper): 42 def preload(self, anm_wrapper):
36 try: 43 for anm in anm_wrapper:
37 anms = anm_wrapper.anm_files 44 anm.texture = self.load_png_texture(anm.first_name, anm.secondary_name)
38 except AttributeError:
39 anms = anm_wrapper
40
41 for anm in anms:
42 key = anm.first_name, anm.secondary_name
43 texture = self[key]
44 45
45 46
46 def load_texture(self, key): 47 def load_png_texture(self, first_name, secondary_name):
47 cdef char *image, *alpha, *new_data 48 cdef char *image, *alpha, *new_data
48 cdef unsigned int i, width, height, pixels 49 cdef unsigned int i, width, height, pixels
49 50
50 first_name, secondary_name = key
51
52 image_file = pyglet.image.load(first_name, file=self.loader.get_file(os.path.basename(first_name))) 51 image_file = pyglet.image.load(first_name, file=self.loader.get_file(os.path.basename(first_name)))
52 width, height = image_file.width, image_file.height
53 image_data = image_file.get_data('RGB', width * 3)
53 54
54 if secondary_name: 55 if secondary_name:
55 alpha_file = pyglet.image.load(secondary_name, file=self.loader.get_file(os.path.basename(secondary_name))) 56 alpha_file = pyglet.image.load(secondary_name, file=self.loader.get_file(os.path.basename(secondary_name)))
56 assert (image_file.width, image_file.height) == (alpha_file.width, image_file.height) 57 assert (image_file.width, image_file.height) == (alpha_file.width, image_file.height)
57 58
58 width, height = image_file.width, image_file.height
59 pixels = width * height 59 pixels = width * height
60 60
61 image_data = image_file.get_data('RGB', width * 3)
62 alpha_data = alpha_file.get_data('RGB', width * 3) 61 alpha_data = alpha_file.get_data('RGB', width * 3)
63 image = <char *>image_data 62 image = <char *>image_data
64 alpha = <char *>alpha_data 63 alpha = <char *>alpha_data
65 64
66 # TODO: further optimizations 65 # TODO: further optimizations
68 for i in range(pixels): 67 for i in range(pixels):
69 new_data[i*4] = image[i*3] 68 new_data[i*4] = image[i*3]
70 new_data[i*4+1] = image[i*3+1] 69 new_data[i*4+1] = image[i*3+1]
71 new_data[i*4+2] = image[i*3+2] 70 new_data[i*4+2] = image[i*3+2]
72 new_data[i*4+3] = alpha[i*3] 71 new_data[i*4+3] = alpha[i*3]
73 image_file = pyglet.image.ImageData(width, height, 'RGBA', new_data[:(pixels * 4)]) 72 data = new_data[:(pixels * 4)]
74 free(new_data) 73 free(new_data)
74 return Texture(width, height, -4, data)
75 75
76 texture = image_file.get_texture() 76 return Texture(width, height, -3, image_data)
77 77
78 glTexParameteri(texture.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
79 glTexParameteri(texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
80 78
81 return texture 79 def load_texture(self, key):
80 if not isinstance(key, Texture):
81 first_name, secondary_name = key
82 key = self.load_png_texture(first_name, secondary_name)
82 83
84 if key.fmt == 1:
85 format_ = GL_BGRA
86 type_ = GL_UNSIGNED_BYTE
87 composants = GL_RGBA
88 elif key.fmt == 3:
89 format_ = GL_RGB
90 type_ = GL_UNSIGNED_SHORT_5_6_5
91 composants = GL_RGB
92 elif key.fmt == 5:
93 format_ = GL_BGRA
94 type_ = GL_UNSIGNED_SHORT_4_4_4_4_REV
95 composants = GL_RGBA
96 elif key.fmt == 7:
97 format_ = GL_LUMINANCE
98 type_ = GL_UNSIGNED_BYTE
99 composants = GL_LUMINANCE
100 elif key.fmt == -3: #XXX: non-standard, remove it!
101 format_ = GL_RGB
102 type_ = GL_UNSIGNED_BYTE
103 composants = GL_RGB
104 elif key.fmt == -4: #XXX: non-standard
105 format_ = GL_RGBA
106 type_ = GL_UNSIGNED_BYTE
107 composants = GL_RGBA
108 else:
109 raise Exception('Unknown texture type')
110
111 id_ = c_uint()
112 glGenTextures(1, byref(id_))
113 glBindTexture(GL_TEXTURE_2D, id_.value)
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
116
117 glTexImage2D(GL_TEXTURE_2D, 0,
118 composants,
119 key.width, key.height,
120 0,
121 format_, type_,
122 key.data)
123
124 return id_.value