class PointRenderer(Widget): def __init__(self, **kwargs): self.canvas = RenderContext(use_parent_projection=True) self.canvas.shader.source = 'pointshader.glsl' glEnable(0x8642) #GL_VERTEX_PROGRAM_POINT_SIZE glEnable(0x8861) #GL_POINT_SPRITE self.mesh = None super(PointRenderer, self).__init__(**kwargs) self.draw_mesh_points(60) Clock.schedule_interval(self.test_mesh_remove, 1. / 60.) def test_mesh_remove(self, dt): r = random() if r > .5: self.canvas.remove(self.mesh) self.mesh = None self.draw_mesh_points(60) def draw_mesh_points(self, number): star_list = [] w, h = self.size sa = star_list.append for number in range(number): rand_x = random() * w rand_y = random() * h size = 29.0 rotation = random() * 360.0 sa((rand_x, rand_y, size, rotation)) self.draw_mesh(star_list) def draw_mesh(self, star_list): star_tex = Image('star1.png').texture vertex_format = [ (b'vPosition', 2, 'float'), (b'vSize', 1, 'float'), (b'vRotation', 1, 'float'), ] indices = [] ia = indices.append for star_number in range(len(star_list)): ia(star_number) vertices = [] e = vertices.extend for star in star_list: e([star[0], star[1], star[2], star[3]]) if self.mesh == None: with self.canvas: PushMatrix() self.mesh = Mesh(indices=indices, vertices=vertices, fmt=vertex_format, mode='points', texture=star_tex) PopMatrix() else: self.mesh.indices = indices self.mesh.vertices = vertices
class EffectWidget(RelativeLayout): ''' Widget with the ability to apply a series of graphical effects to its children. See module documentation for full information on setting effects and creating your own. ''' background_color = ListProperty((0, 0, 0, 1)) '''This defines the background color to be used for the fbo in the EffectWidget. :attr:`background_color` is a :class:`ListProperty` defaults to (0, 0, 0, 1) ''' texture = ObjectProperty(None) '''The output texture of our final :class:`~kivy.graphics.Fbo` after all effects have been applied. texture is an :class:`~kivy.properties.ObjectProperty` and defaults to None. ''' effects = ListProperty([]) '''List of all the effects to be applied. These should all be instances of :class:`EffectBase`. effects is a :class:`ListProperty` and defaults to []. ''' fbo_list = ListProperty([]) '''(internal) list of all the fbos that are being used to apply the effects. fbo_list is a :class:`ListProperty` and defaults to []. ''' _bound_effects = ListProperty([]) '''(internal) list of effect classes that have been given an fbo to manage. This is necessary so that the fbo can be removed it the effect is no longer in use. _bound_effects is a :class:`ListProperty` and defaults to []. ''' def __init__(self, **kwargs): # Make sure opengl context exists EventLoop.ensure_window() self.canvas = RenderContext(use_parent_projection=True, use_parent_modelview=True) with self.canvas: self.fbo = Fbo(size=self.size) with self.fbo.before: PushMatrix() with self.fbo: ClearColor(0, 0, 0, 0) ClearBuffers() self._background_color = Color(*self.background_color) self.fbo_rectangle = Rectangle(size=self.size) with self.fbo.after: PopMatrix() super(EffectWidget, self).__init__(**kwargs) Clock.schedule_interval(self._update_glsl, 0) self.bind(size=self.refresh_fbo_setup, effects=self.refresh_fbo_setup, background_color=self._refresh_background_color) self.refresh_fbo_setup() self._refresh_background_color() # In case thi was changed in kwargs def _refresh_background_color(self, *args): self._background_color.rgba = self.background_color def _update_glsl(self, *largs): '''(internal) Passes new time and resolution uniform variables to the shader. ''' time = Clock.get_boottime() resolution = [float(size) for size in self.size] self.canvas['time'] = time self.canvas['resolution'] = resolution for fbo in self.fbo_list: fbo['time'] = time fbo['resolution'] = resolution def refresh_fbo_setup(self, *args): '''(internal) Creates and assigns one :class:`~kivy.graphics.Fbo` per effect, and makes sure all sizes etc. are correct and consistent. ''' # Add/remove fbos until there is one per effect while len(self.fbo_list) < len(self.effects): with self.canvas: new_fbo = EffectFbo(size=self.size) with new_fbo: ClearColor(0, 0, 0, 0) ClearBuffers() Color(1, 1, 1, 1) new_fbo.texture_rectangle = Rectangle(size=self.size) new_fbo.texture_rectangle.size = self.size self.fbo_list.append(new_fbo) while len(self.fbo_list) > len(self.effects): old_fbo = self.fbo_list.pop() self.canvas.remove(old_fbo) # Remove fbos from unused effects for effect in self._bound_effects: if effect not in self.effects: effect.fbo = None self._bound_effects = self.effects # Do resizing etc. self.fbo.size = self.size self.fbo_rectangle.size = self.size for i in range(len(self.fbo_list)): self.fbo_list[i].size = self.size self.fbo_list[i].texture_rectangle.size = self.size # If there are no effects, just draw our main fbo if len(self.fbo_list) == 0: self.texture = self.fbo.texture return for i in range(1, len(self.fbo_list)): fbo = self.fbo_list[i] fbo.texture_rectangle.texture = self.fbo_list[i - 1].texture # Build effect shaders for effect, fbo in zip(self.effects, self.fbo_list): effect.fbo = fbo self.fbo_list[0].texture_rectangle.texture = self.fbo.texture self.texture = self.fbo_list[-1].texture def add_widget(self, widget): # Add the widget to our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).add_widget(widget) self.canvas = c def remove_widget(self, widget): # Remove the widget from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).remove_widget(widget) self.canvas = c def clear_widgets(self, children=None): # Clear widgets from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).clear_widgets(children) self.canvas = c
class EffectWidget(RelativeLayout): ''' Widget with the ability to apply a series of graphical effects to its children. See the module documentation for more information on setting effects and creating your own. ''' background_color = ListProperty((0, 0, 0, 1)) '''This defines the background color to be used for the fbo in the EffectWidget. :attr:`background_color` is a :class:`ListProperty` defaults to (0, 0, 0, 1) ''' texture = ObjectProperty(None) '''The output texture of the final :class:`~kivy.graphics.Fbo` after all effects have been applied. texture is an :class:`~kivy.properties.ObjectProperty` and defaults to None. ''' effects = ListProperty([]) '''List of all the effects to be applied. These should all be instances or subclasses of :class:`EffectBase`. effects is a :class:`ListProperty` and defaults to []. ''' fbo_list = ListProperty([]) '''(internal) List of all the fbos that are being used to apply the effects. fbo_list is a :class:`ListProperty` and defaults to []. ''' _bound_effects = ListProperty([]) '''(internal) List of effect classes that have been given an fbo to manage. This is necessary so that the fbo can be removed if the effect is no longer in use. _bound_effects is a :class:`ListProperty` and defaults to []. ''' def __init__(self, **kwargs): # Make sure opengl context exists EventLoop.ensure_window() self.canvas = RenderContext(use_parent_projection=True, use_parent_modelview=True) with self.canvas: self.fbo = Fbo(size=self.size) with self.fbo.before: PushMatrix() with self.fbo: ClearColor(0, 0, 0, 0) ClearBuffers() self._background_color = Color(*self.background_color) self.fbo_rectangle = Rectangle(size=self.size) with self.fbo.after: PopMatrix() super(EffectWidget, self).__init__(**kwargs) Clock.schedule_interval(self._update_glsl, 0) fbind = self.fbind fbo_setup = self.refresh_fbo_setup fbind('size', fbo_setup) fbind('effects', fbo_setup) fbind('background_color', self._refresh_background_color) self.refresh_fbo_setup() self._refresh_background_color() # In case thi was changed in kwargs def _refresh_background_color(self, *args): self._background_color.rgba = self.background_color def _update_glsl(self, *largs): '''(internal) Passes new time and resolution uniform variables to the shader. ''' time = Clock.get_boottime() resolution = [float(size) for size in self.size] self.canvas['time'] = time self.canvas['resolution'] = resolution for fbo in self.fbo_list: fbo['time'] = time fbo['resolution'] = resolution def refresh_fbo_setup(self, *args): '''(internal) Creates and assigns one :class:`~kivy.graphics.Fbo` per effect, and makes sure all sizes etc. are correct and consistent. ''' # Add/remove fbos until there is one per effect while len(self.fbo_list) < len(self.effects): with self.canvas: new_fbo = EffectFbo(size=self.size) with new_fbo: ClearColor(0, 0, 0, 0) ClearBuffers() Color(1, 1, 1, 1) new_fbo.texture_rectangle = Rectangle(size=self.size) new_fbo.texture_rectangle.size = self.size self.fbo_list.append(new_fbo) while len(self.fbo_list) > len(self.effects): old_fbo = self.fbo_list.pop() self.canvas.remove(old_fbo) # Remove fbos from unused effects for effect in self._bound_effects: if effect not in self.effects: effect.fbo = None self._bound_effects = self.effects # Do resizing etc. self.fbo.size = self.size self.fbo_rectangle.size = self.size for i in range(len(self.fbo_list)): self.fbo_list[i].size = self.size self.fbo_list[i].texture_rectangle.size = self.size # If there are no effects, just draw our main fbo if len(self.fbo_list) == 0: self.texture = self.fbo.texture return for i in range(1, len(self.fbo_list)): fbo = self.fbo_list[i] fbo.texture_rectangle.texture = self.fbo_list[i - 1].texture # Build effect shaders for effect, fbo in zip(self.effects, self.fbo_list): effect.fbo = fbo self.fbo_list[0].texture_rectangle.texture = self.fbo.texture self.texture = self.fbo_list[-1].texture def add_widget(self, widget): # Add the widget to our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).add_widget(widget) self.canvas = c def remove_widget(self, widget): # Remove the widget from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).remove_widget(widget) self.canvas = c def clear_widgets(self, children=None): # Clear widgets from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).clear_widgets(children) self.canvas = c
class EffectWidget(FloatLayout): fs = StringProperty(None) # Texture of the final Fbo texture = ObjectProperty(None) # Rectangle clearing Fbo fbo_rectangle = ObjectProperty(None) # List of effect strings effects = ListProperty([]) # One extra Fbo for each effect fbo_list = ListProperty([]) effect_mask = None motion_effect = None def __init__(self, **kwargs): # Make sure opengl context exists EventLoop.ensure_window() self.mask_effect = kwargs.get("mask_effect", None) self.motion_effect = kwargs.get("motion_effect", None) self.canvas = RenderContext(use_parent_projection=True, use_parent_modelview=True) self.size = C_SIZE with self.canvas: #self._viewport = Rectangle(size=(800,600), pos=self.pos) self.fbo = Fbo(size=C_SIZE, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0.3, 0.3, 0.7, 1)) with self.fbo.before: #Rectangle(size=(800, 600)) PushMatrix() self.fbo_translation = Translate(-self.x, -self.y, 0) BindTexture(texture=self.mask_effect.texture, index=4) BindTexture(texture=self.motion_effect.texture, index=5) with self.fbo: Color(0, 0, 0) BindTexture(texture=self.mask_effect.texture, index=4) BindTexture(texture=self.motion_effect.texture, index=5) self.fbo_rectangle = Rectangle(size=C_SIZE) self._instructions = InstructionGroup() with self.fbo.after: PopMatrix() self.cbs = Callback(self.reset_gl_context) super(EffectWidget, self).__init__() self.size = C_SIZE Clock.schedule_interval(self.update_glsl, 0) self._instructions.add(Callback(self.setup_gl_context)) self.refresh_fbo_setup() Clock.schedule_interval(self.update_fbos, 0) def on_pos(self, *args): self.fbo_translation.x = -self.x self.fbo_translation.y = -self.y def on_size(self, instance, value): self.fbo.size = C_SIZE self.fbo_rectangle.size = C_SIZE self.refresh_fbo_setup() #self._viewport.texture = self.fbo.texture #self._viewport.size = value def setup_gl_context(self, *args): glEnable(GL_DEPTH_TEST) self.fbo.clear_buffer() #for fbo in self.fbo_list: # fbo.clear_buffer() def reset_gl_context(self, *args): glDisable(GL_DEPTH_TEST) def update_glsl(self, *largs): time = Clock.get_boottime() resolution = [float(size) for size in C_SIZE] self.canvas['time'] = time self.canvas['resolution'] = resolution self.canvas['texture4'] = 4 self.canvas['texture5'] = 5 for fbo in self.fbo_list: fbo['time'] = time fbo['resolution'] = resolution fbo['texture4'] = 4 fbo['texture5'] = 5 def on_effects(self, *args): self.refresh_fbo_setup() def update_fbos(self, *args): for fbo in self.fbo_list: fbo.ask_update() def refresh_fbo_setup(self, *args): # Add/remove fbos until there is one per effect while len(self.fbo_list) < len(self.effects): with self.canvas: new_fbo = EffectFbo(size=C_SIZE) with new_fbo: Color(1, 1, 1, 1) new_fbo.texture_rectangle = Rectangle(size=C_SIZE) new_fbo.texture_rectangle.size = C_SIZE self.fbo_list.append(new_fbo) while len(self.fbo_list) > len(self.effects): old_fbo = self.fbo_list.pop() self.canvas.remove(old_fbo) # Do resizing etc. self.fbo.size = C_SIZE self.fbo_rectangle.size = C_SIZE for i in range(len(self.fbo_list)): self.fbo_list[i].size = C_SIZE self.fbo_list[i].texture_rectangle.size = C_SIZE # If there are no effects, just draw our main fbo if len(self.fbo_list) == 0: self.texture = self.fbo.texture return for i in range(1, len(self.fbo_list)): fbo = self.fbo_list[i] fbo.texture_rectangle.texture = self.fbo_list[i - 1].texture for effect, fbo in zip(self.effects, self.fbo_list): fbo.set_fs(shader_header + shader_uniforms + effect + shader_footer_effect) self.fbo_list[0].texture_rectangle.texture = self.fbo.texture self.texture = self.fbo_list[-1].texture def on_fs(self, instance, value): # set the fragment shader to our source code shader = self.canvas.shader old_value = shader.fs shader.fs = value if not shader.success: shader.fs = old_value raise Exception('failed') def add_widget(self, widget): # Add the widget to our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).add_widget(widget) #self._instructions.add(widget.canvas) self.canvas = c def remove_widget(self, widget): # Remove the widget from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).remove_widget(widget) self.canvas = c def clear_widgets(self, children=None): # Clear widgets from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).clear_widgets(children) self.canvas = c
class EffectWidget(FloatLayout): fs = StringProperty(None) # Texture of the final Fbo texture = ObjectProperty(None) # Rectangle clearing Fbo fbo_rectangle = ObjectProperty(None) # List of effect strings effects = ListProperty([]) # One extra Fbo for each effect fbo_list = ListProperty([]) effect_mask = None motion_effect = None def __init__(self, **kwargs): # Make sure opengl context exists EventLoop.ensure_window() self.mask_effect = kwargs.get("mask_effect", None) self.motion_effect = kwargs.get("motion_effect", None) self.canvas = RenderContext(use_parent_projection=True, use_parent_modelview=True) self.size = C_SIZE with self.canvas: #self._viewport = Rectangle(size=(800,600), pos=self.pos) self.fbo = Fbo(size=C_SIZE, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0.3, 0.3, 0.7, 1)) with self.fbo.before: #Rectangle(size=(800, 600)) PushMatrix() self.fbo_translation = Translate(-self.x, -self.y, 0) BindTexture(texture=self.mask_effect.texture, index=4) BindTexture(texture=self.motion_effect.texture, index=5) with self.fbo: Color(0, 0, 0) BindTexture(texture=self.mask_effect.texture, index=4) BindTexture(texture=self.motion_effect.texture, index=5) self.fbo_rectangle = Rectangle(size=C_SIZE) self._instructions = InstructionGroup() with self.fbo.after: PopMatrix() self.cbs = Callback(self.reset_gl_context) super(EffectWidget, self).__init__(**kwargs) self.size = C_SIZE Clock.schedule_interval(self.update_glsl, 0) self._instructions.add(Callback(self.setup_gl_context)) self.refresh_fbo_setup() Clock.schedule_interval(self.update_fbos, 0) def on_pos(self, *args): self.fbo_translation.x = -self.x self.fbo_translation.y = -self.y def on_size(self, instance, value): self.fbo.size = C_SIZE self.fbo_rectangle.size = C_SIZE self.refresh_fbo_setup() #self._viewport.texture = self.fbo.texture #self._viewport.size = value def setup_gl_context(self, *args): glEnable(GL_DEPTH_TEST) self.fbo.clear_buffer() #for fbo in self.fbo_list: # fbo.clear_buffer() def reset_gl_context(self, *args): glDisable(GL_DEPTH_TEST) def update_glsl(self, *largs): time = Clock.get_boottime() resolution = [float(size) for size in C_SIZE] self.canvas['time'] = time self.canvas['resolution'] = resolution self.canvas['texture4'] = 4 self.canvas['texture5'] = 5 for fbo in self.fbo_list: fbo['time'] = time fbo['resolution'] = resolution fbo['texture4'] = 4 fbo['texture5'] = 5 def on_effects(self, *args): self.refresh_fbo_setup() def update_fbos(self, *args): for fbo in self.fbo_list: fbo.ask_update() def refresh_fbo_setup(self, *args): # Add/remove fbos until there is one per effect while len(self.fbo_list) < len(self.effects): with self.canvas: new_fbo = EffectFbo(size=C_SIZE) with new_fbo: Color(1, 1, 1, 1) new_fbo.texture_rectangle = Rectangle( size=C_SIZE) new_fbo.texture_rectangle.size = C_SIZE self.fbo_list.append(new_fbo) while len(self.fbo_list) > len(self.effects): old_fbo = self.fbo_list.pop() self.canvas.remove(old_fbo) # Do resizing etc. self.fbo.size = C_SIZE self.fbo_rectangle.size = C_SIZE for i in range(len(self.fbo_list)): self.fbo_list[i].size = C_SIZE self.fbo_list[i].texture_rectangle.size = C_SIZE # If there are no effects, just draw our main fbo if len(self.fbo_list) == 0: self.texture = self.fbo.texture return for i in range(1, len(self.fbo_list)): fbo = self.fbo_list[i] fbo.texture_rectangle.texture = self.fbo_list[i - 1].texture for effect, fbo in zip(self.effects, self.fbo_list): fbo.set_fs(shader_header + shader_uniforms + effect + shader_footer_effect) self.fbo_list[0].texture_rectangle.texture = self.fbo.texture self.texture = self.fbo_list[-1].texture def on_fs(self, instance, value): # set the fragment shader to our source code shader = self.canvas.shader old_value = shader.fs shader.fs = value if not shader.success: shader.fs = old_value raise Exception('failed') def add_widget(self, widget): # Add the widget to our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).add_widget(widget) #self._instructions.add(widget.canvas) self.canvas = c def remove_widget(self, widget): # Remove the widget from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).remove_widget(widget) self.canvas = c def clear_widgets(self, children=None): # Clear widgets from our Fbo instead of the normal canvas c = self.canvas self.canvas = self.fbo super(EffectWidget, self).clear_widgets(children) self.canvas = c
class PointRenderer(Widget): def __init__(self, **kwargs): self.canvas = RenderContext(use_parent_projection=True) self.canvas.shader.source = 'pointshader.glsl' glEnable(0x8642) #GL_VERTEX_PROGRAM_POINT_SIZE glEnable(0x8861) #GL_POINT_SPRITE self.mesh = None super(PointRenderer, self).__init__(**kwargs) self.draw_mesh_points(60) Clock.schedule_interval(self.test_mesh_remove, 1./60.) def test_mesh_remove(self, dt): r = random() if r > .5: self.canvas.remove(self.mesh) self.mesh = None self.draw_mesh_points(60) def draw_mesh_points(self, number): star_list = [] w, h = self.size sa = star_list.append for number in xrange(number): rand_x = random()*w rand_y = random()*h size = 29.0 rotation = random()*360.0 sa((rand_x, rand_y, size, rotation)) self.draw_mesh(star_list) def draw_mesh(self, star_list): star_tex = Image('star1.png').texture vertex_format = [ ('vPosition', 2, 'float'), ('vSize', 1, 'float'), ('vRotation', 1, 'float'), ] indices = [] ia = indices.append for star_number in range(len(star_list)): ia(star_number) vertices = [] e = vertices.extend for star in star_list: e([ star[0], star[1], star[2], star[3] ]) if self.mesh == None: with self.canvas: PushMatrix() self.mesh = Mesh( indices=indices, vertices=vertices, fmt=vertex_format, mode='points', texture=star_tex) PopMatrix() else: self.mesh.indices = indices self.mesh.vertices = vertices
class PointRenderer(Widget): def __init__(self, **kwargs): self.this_op = None self.units_per_meter = 16.0 self.gravity = 9.8 self.fps = 60.0 self.vertex_format = [ (b'vPosition', 3, 'float'), (b'vSize', 1, 'float'), (b'vRotation', 1, 'float'), (b'vVelocity', 3, 'float'), ] self.ROTATION_I = 4 # must match index of vRotation above self.VELOCITY_I = 5 # must match index of vVelocity above self.vertex_depth = 0 for element in self.vertex_format: self.vertex_depth += element[1] self.star_list = [] self.canvas = RenderContext(use_parent_projection=True) self.canvas.shader.source = 'pointshader3d.glsl' glEnable(0x8642) #GL_VERTEX_PROGRAM_POINT_SIZE glEnable(0x8861) #GL_POINT_SPRITE self.mesh = None super(PointRenderer, self).__init__(**kwargs) self.canvas["camera_eyespace_z"] = self.width / 2.0 self.canvas["max_particle_size"] = self.width self.draw_mesh_points(60) #Clock.schedule_interval(self.test_mesh_remove, 1./60.) Clock.schedule_interval(self.test_mesh_move, 1. / self.fps) def test_mesh_move(self, dt): this_star_list = self.star_list offset = 0 #sl_len = len(this_star_list) #vertex_count = int(sl_len/self.vertex_depth) #v_i = 0 v_len = len(self.this_op.vertices) while offset < v_len: if self.this_op.vertices[offset + 1] > 0.0: self.this_op.vertices[offset] += self.this_op.vertices[ offset + self.VELOCITY_I] self.this_op.vertices[offset + 1] += self.this_op.vertices[ offset + self.VELOCITY_I + 1] # +1 for y self.this_op.vertices[offset + 2] += self.this_op.vertices[ offset + self.VELOCITY_I + 2] # +2 for z if self.this_op.vertices[offset + 1] < 0.0: self.this_op.vertices[offset + 1] = 0.0 self.this_op.vertices[offset + self.VELOCITY_I + 1] -= ( self.gravity / self.units_per_meter) / self.fps # +1 for y self.this_op.vertices[ offset + self.ROTATION_I] += self.this_op.vertices[ offset + self.VELOCITY_I + 2] * 2 # +2 for z (spin according to speed and direction of z velocity) else: self.this_op.vertices[offset + self.VELOCITY_I] = 0.0 self.this_op.vertices[offset + self.VELOCITY_I + 1] = 0.0 self.this_op.vertices[offset + self.VELOCITY_I + 2] = 0.0 offset += self.vertex_depth self.draw_mesh(None) def test_mesh_remove(self, dt): r = random() if r > .5: self.canvas.remove(self.mesh) self.mesh = None self.draw_mesh_points(60) def draw_mesh_points(self, number): self.star_list = [] w, h = self.size sa = self.star_list.append for number in range(number): rand_x = random() * w rand_y = random() * h rand_z = random() * w rand_velocity = [ random() * 10. - 5., random() * 5. - 2.5, random() * 20. - 5. ] size = 29.0 rotation = random() * 360.0 this_v = (rand_x, rand_y, rand_z, size, rotation, rand_velocity[0], rand_velocity[1], rand_velocity[2]) if len(this_v) != self.vertex_depth: print( "FATAL ERROR: tuple size does not match vertex depth (offset)" ) exit(1) sa(this_v) self.draw_mesh(self.star_list) def draw_mesh(self, this_star_list): if self.this_op is None: self.this_op = PointRendererOp() star_tex = Image('star1.png').texture self.this_op.indices = [] ia = self.this_op.indices.append for star_number in range(len(this_star_list)): ia(star_number) self.this_op.vertices = [] e = self.this_op.vertices.extend for star in this_star_list: this_star = [ star[0], star[1], star[2], star[3], \ star[4], star[5], star[6], star[7] ] if len(this_star) != self.vertex_depth: print("FATAL ERROR: array size does not match " + \ "vertex depth (offset)") exit(1) e(this_star) if self.mesh == None: with self.canvas: PushMatrix() self.mesh = Mesh(indices=self.this_op.indices, vertices=self.this_op.vertices, fmt=self.vertex_format, mode='points', texture=star_tex) PopMatrix() else: # self.mesh.indices = self.this_op.indices self.mesh.vertices = self.this_op.vertices pass