Mercurial > parpg-source
comparison bGrease/renderer/vector.py @ 65:e856b604b650
Changed "import bGrease" to "import parpg.bGrease".
author | KarstenBock@gmx.net |
---|---|
date | Wed, 21 Sep 2011 16:10:14 +0200 |
parents | ff3e395abf91 |
children |
comparison
equal
deleted
inserted
replaced
64:b73050f98411 | 65:e856b604b650 |
---|---|
13 | 13 |
14 __version__ = '$Id$' | 14 __version__ = '$Id$' |
15 | 15 |
16 __all__ = ('Vector',) | 16 __all__ = ('Vector',) |
17 | 17 |
18 from bGrease.geometry import Vec2d | 18 from parpg.bGrease.geometry import Vec2d |
19 import ctypes | 19 import ctypes |
20 from math import sin, cos, radians | 20 from math import sin, cos, radians |
21 import pyglet | 21 import pyglet |
22 | 22 |
23 | 23 |
24 class Vector(object): | 24 class Vector(object): |
25 """Renders shapes in a classic vector graphics style | 25 """Renders shapes in a classic vector graphics style |
26 | |
27 :param scale: Scaling factor applied to shape vertices when rendered. | |
28 | |
29 :param line_width: The line width provided to ``glLineWidth`` before rendering. | |
30 If not specified or None, ``glLineWidth`` is not called, and the line | |
31 width used is determined by the OpenGL state at the time of rendering. | |
32 | 26 |
33 :param anti_alias: If ``True``, OpenGL blending and line smoothing is enabled. | 27 :param scale: Scaling factor applied to shape vertices when rendered. |
34 This allows for fractional line widths as well. If ``False``, the blending | |
35 and line smoothing modes are unchanged. | |
36 | 28 |
37 :param corner_fill: If true (the default), the shape corners will be filled | 29 :param line_width: The line width provided to ``glLineWidth`` before rendering. |
38 with round points when the ``line_width`` exceeds 2.0. This improves | 30 If not specified or None, ``glLineWidth`` is not called, and the line |
39 the visual quality of the rendering at larger line widths at some | 31 width used is determined by the OpenGL state at the time of rendering. |
40 cost to performance. Has no effect if ``line_width`` is not specified. | |
41 | 32 |
42 :param position_component: Name of :class:`grease.component.Position` | 33 :param anti_alias: If ``True``, OpenGL blending and line smoothing is enabled. |
43 component to use. Shapes rendered are offset by the entity positions. | 34 This allows for fractional line widths as well. If ``False``, the blending |
35 and line smoothing modes are unchanged. | |
44 | 36 |
45 :param renderable_component: Name of :class:`grease.component.Renderable` | 37 :param corner_fill: If true (the default), the shape corners will be filled |
46 component to use. This component specifies the entities to be | 38 with round points when the ``line_width`` exceeds 2.0. This improves |
47 rendered and their base color. | 39 the visual quality of the rendering at larger line widths at some |
40 cost to performance. Has no effect if ``line_width`` is not specified. | |
48 | 41 |
49 :param shape_component: Name of :class:`grease.component.Shape` | 42 :param position_component: Name of :class:`grease.component.Position` |
50 component to use. Source of the shape vertices for each entity. | 43 component to use. Shapes rendered are offset by the entity positions. |
51 | 44 |
52 The entities rendered are taken from the intersection of he position, | 45 :param renderable_component: Name of :class:`grease.component.Renderable` |
53 renderable and shape components each time :meth:`draw` is called. | 46 component to use. This component specifies the entities to be |
54 """ | 47 rendered and their base color. |
55 | 48 |
56 CORNER_FILL_SCALE = 0.6 | 49 :param shape_component: Name of :class:`grease.component.Shape` |
57 CORNER_FILL_THRESHOLD = 2.0 | 50 component to use. Source of the shape vertices for each entity. |
58 | 51 |
59 def __init__(self, scale=1.0, line_width=None, anti_alias=True, corner_fill=True, | 52 The entities rendered are taken from the intersection of he position, |
60 position_component='position', | 53 renderable and shape components each time :meth:`draw` is called. |
61 renderable_component='renderable', | 54 """ |
62 shape_component='shape'): | |
63 self.scale = float(scale) | |
64 self.corner_fill = corner_fill | |
65 self.line_width = line_width | |
66 self.anti_alias = anti_alias | |
67 self._max_line_width = None | |
68 self.position_component = position_component | |
69 self.renderable_component = renderable_component | |
70 self.shape_component = shape_component | |
71 | |
72 def set_world(self, world): | |
73 self.world = world | |
74 | 55 |
75 def _generate_verts(self): | 56 CORNER_FILL_SCALE = 0.6 |
76 """Generate vertex and index arrays for rendering""" | 57 CORNER_FILL_THRESHOLD = 2.0 |
77 vert_count = sum(len(shape.verts) + 1 | |
78 for shape, ignored, ignored in self.world.components.join( | |
79 self.shape_component, self.position_component, self.renderable_component)) | |
80 v_array = (CVertColor * vert_count)() | |
81 if vert_count > 65536: | |
82 i_array = (ctypes.c_uint * 2 * vert_count)() | |
83 i_size = pyglet.gl.GL_UNSIGNED_INT | |
84 else: | |
85 i_array = (ctypes.c_ushort * (2 * vert_count))() | |
86 i_size = pyglet.gl.GL_UNSIGNED_SHORT | |
87 v_index = 0 | |
88 i_index = 0 | |
89 scale = self.scale | |
90 rot_vec = Vec2d(0, 0) | |
91 for shape, position, renderable in self.world.components.join( | |
92 self.shape_component, self.position_component, self.renderable_component): | |
93 shape_start = v_index | |
94 angle = radians(-position.angle) | |
95 rot_vec.x = cos(angle) | |
96 rot_vec.y = sin(angle) | |
97 r = int(renderable.color.r * 255) | |
98 g = int(renderable.color.g * 255) | |
99 b = int(renderable.color.b * 255) | |
100 a = int(renderable.color.a * 255) | |
101 for vert in shape.verts: | |
102 vert = vert.cpvrotate(rot_vec) * scale + position.position | |
103 v_array[v_index].vert.x = vert.x | |
104 v_array[v_index].vert.y = vert.y | |
105 v_array[v_index].color.r = r | |
106 v_array[v_index].color.g = g | |
107 v_array[v_index].color.b = b | |
108 v_array[v_index].color.a = a | |
109 if v_index > shape_start: | |
110 i_array[i_index] = v_index - 1 | |
111 i_index += 1 | |
112 i_array[i_index] = v_index | |
113 i_index += 1 | |
114 v_index += 1 | |
115 if shape.closed and v_index - shape_start > 2: | |
116 i_array[i_index] = v_index - 1 | |
117 i_index += 1 | |
118 i_array[i_index] = shape_start | |
119 i_index += 1 | |
120 return v_array, i_size, i_array, i_index | |
121 | 58 |
122 def draw(self, gl=pyglet.gl): | 59 def __init__(self, scale=1.0, line_width=None, anti_alias=True, corner_fill=True, |
123 vertices, index_size, indices, index_count = self._generate_verts() | 60 position_component='position', |
124 if index_count: | 61 renderable_component='renderable', |
125 if self.anti_alias: | 62 shape_component='shape'): |
126 gl.glEnable(gl.GL_LINE_SMOOTH) | 63 self.scale = float(scale) |
127 gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST) | 64 self.corner_fill = corner_fill |
128 gl.glEnable(gl.GL_BLEND) | 65 self.line_width = line_width |
129 gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) | 66 self.anti_alias = anti_alias |
130 gl.glPushClientAttrib(gl.GL_CLIENT_VERTEX_ARRAY_BIT) | 67 self._max_line_width = None |
131 gl.glEnableClientState(gl.GL_VERTEX_ARRAY) | 68 self.position_component = position_component |
132 gl.glEnableClientState(gl.GL_COLOR_ARRAY) | 69 self.renderable_component = renderable_component |
133 gl.glVertexPointer( | 70 self.shape_component = shape_component |
134 2, gl.GL_FLOAT, ctypes.sizeof(CVertColor), ctypes.pointer(vertices)) | 71 |
135 gl.glColorPointer( | 72 def set_world(self, world): |
136 4, gl.GL_UNSIGNED_BYTE, ctypes.sizeof(CVertColor), | 73 self.world = world |
137 ctypes.pointer(vertices[0].color)) | 74 |
138 if self.line_width is not None: | 75 def _generate_verts(self): |
139 gl.glLineWidth(self.line_width) | 76 """Generate vertex and index arrays for rendering""" |
140 if self._max_line_width is None: | 77 vert_count = sum(len(shape.verts) + 1 |
141 range_out = (ctypes.c_float * 2)() | 78 for shape, ignored, ignored in self.world.components.join( |
142 gl.glGetFloatv(gl.GL_ALIASED_LINE_WIDTH_RANGE, range_out) | 79 self.shape_component, self.position_component, self.renderable_component)) |
143 self._max_line_width = float(range_out[1]) * self.CORNER_FILL_SCALE | 80 v_array = (CVertColor * vert_count)() |
144 if self.corner_fill and self.line_width > self.CORNER_FILL_THRESHOLD: | 81 if vert_count > 65536: |
145 gl.glEnable(gl.GL_POINT_SMOOTH) | 82 i_array = (ctypes.c_uint * 2 * vert_count)() |
146 gl.glPointSize( | 83 i_size = pyglet.gl.GL_UNSIGNED_INT |
147 min(self.line_width * self.CORNER_FILL_SCALE, self._max_line_width)) | 84 else: |
148 gl.glDrawArrays(gl.GL_POINTS, 0, index_count) | 85 i_array = (ctypes.c_ushort * (2 * vert_count))() |
149 gl.glDrawElements(gl.GL_LINES, index_count, index_size, ctypes.pointer(indices)) | 86 i_size = pyglet.gl.GL_UNSIGNED_SHORT |
150 gl.glPopClientAttrib() | 87 v_index = 0 |
88 i_index = 0 | |
89 scale = self.scale | |
90 rot_vec = Vec2d(0, 0) | |
91 for shape, position, renderable in self.world.components.join( | |
92 self.shape_component, self.position_component, self.renderable_component): | |
93 shape_start = v_index | |
94 angle = radians(-position.angle) | |
95 rot_vec.x = cos(angle) | |
96 rot_vec.y = sin(angle) | |
97 r = int(renderable.color.r * 255) | |
98 g = int(renderable.color.g * 255) | |
99 b = int(renderable.color.b * 255) | |
100 a = int(renderable.color.a * 255) | |
101 for vert in shape.verts: | |
102 vert = vert.cpvrotate(rot_vec) * scale + position.position | |
103 v_array[v_index].vert.x = vert.x | |
104 v_array[v_index].vert.y = vert.y | |
105 v_array[v_index].color.r = r | |
106 v_array[v_index].color.g = g | |
107 v_array[v_index].color.b = b | |
108 v_array[v_index].color.a = a | |
109 if v_index > shape_start: | |
110 i_array[i_index] = v_index - 1 | |
111 i_index += 1 | |
112 i_array[i_index] = v_index | |
113 i_index += 1 | |
114 v_index += 1 | |
115 if shape.closed and v_index - shape_start > 2: | |
116 i_array[i_index] = v_index - 1 | |
117 i_index += 1 | |
118 i_array[i_index] = shape_start | |
119 i_index += 1 | |
120 return v_array, i_size, i_array, i_index | |
121 | |
122 def draw(self, gl=pyglet.gl): | |
123 vertices, index_size, indices, index_count = self._generate_verts() | |
124 if index_count: | |
125 if self.anti_alias: | |
126 gl.glEnable(gl.GL_LINE_SMOOTH) | |
127 gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST) | |
128 gl.glEnable(gl.GL_BLEND) | |
129 gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) | |
130 gl.glPushClientAttrib(gl.GL_CLIENT_VERTEX_ARRAY_BIT) | |
131 gl.glEnableClientState(gl.GL_VERTEX_ARRAY) | |
132 gl.glEnableClientState(gl.GL_COLOR_ARRAY) | |
133 gl.glVertexPointer( | |
134 2, gl.GL_FLOAT, ctypes.sizeof(CVertColor), ctypes.pointer(vertices)) | |
135 gl.glColorPointer( | |
136 4, gl.GL_UNSIGNED_BYTE, ctypes.sizeof(CVertColor), | |
137 ctypes.pointer(vertices[0].color)) | |
138 if self.line_width is not None: | |
139 gl.glLineWidth(self.line_width) | |
140 if self._max_line_width is None: | |
141 range_out = (ctypes.c_float * 2)() | |
142 gl.glGetFloatv(gl.GL_ALIASED_LINE_WIDTH_RANGE, range_out) | |
143 self._max_line_width = float(range_out[1]) * self.CORNER_FILL_SCALE | |
144 if self.corner_fill and self.line_width > self.CORNER_FILL_THRESHOLD: | |
145 gl.glEnable(gl.GL_POINT_SMOOTH) | |
146 gl.glPointSize( | |
147 min(self.line_width * self.CORNER_FILL_SCALE, self._max_line_width)) | |
148 gl.glDrawArrays(gl.GL_POINTS, 0, index_count) | |
149 gl.glDrawElements(gl.GL_LINES, index_count, index_size, ctypes.pointer(indices)) | |
150 gl.glPopClientAttrib() | |
151 | 151 |
152 | 152 |
153 class CVert(ctypes.Structure): | 153 class CVert(ctypes.Structure): |
154 _fields_ = [("x", ctypes.c_float), ("y", ctypes.c_float)] | 154 _fields_ = [("x", ctypes.c_float), ("y", ctypes.c_float)] |
155 | 155 |
156 class CColor(ctypes.Structure): | 156 class CColor(ctypes.Structure): |
157 _fields_ = [ | 157 _fields_ = [ |
158 ("r", ctypes.c_ubyte), | 158 ("r", ctypes.c_ubyte), |
159 ("g", ctypes.c_ubyte), | 159 ("g", ctypes.c_ubyte), |
160 ("b", ctypes.c_ubyte), | 160 ("b", ctypes.c_ubyte), |
161 ("a", ctypes.c_ubyte), | 161 ("a", ctypes.c_ubyte), |
162 ] | 162 ] |
163 | 163 |
164 class CVertColor(ctypes.Structure): | 164 class CVertColor(ctypes.Structure): |
165 _fields_ = [("vert", CVert), ("color", CColor)] | 165 _fields_ = [("vert", CVert), ("color", CColor)] |
166 |