Completed
Push — master ( 0c9b68...9c9dd3 )
by Matthew
01:04
created

ed2d.Mesh.fromData()   A

Complexity

Conditions 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 16
rs 9.4286
1
from gem import matrix
2
from gem import vector
3
from ed2d.opengl import gl, pgl
4
5
6
def buffer_object(data, typeM):
7
    if data or 0:
8
        vbo = pgl.glGenBuffers(1)
9
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo)
10
        pgl.glBufferData(gl.GL_ARRAY_BUFFER, data, typeM, gl.GL_STATIC_DRAW)
11
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
12
        return vbo
13
    else:
14
        return None
15
16
17
def index_buffer_object(data, typeM):
18
    if data or 0:
19
        ibo = pgl.glGenBuffers(1)
20
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, ibo)
21
        pgl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, data, typeM,
22
                         gl.GL_STATIC_DRAW)
23
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0)
24
        return ibo
25
    else:
26
        return None
27
28
29
def bind_object(dataLoc, vbo, size):
30
    if (dataLoc is not None) and (vbo is not None):
31
        gl.glEnableVertexAttribArray(dataLoc)
32
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo)
33
        pgl.glVertexAttribPointer(dataLoc, size, gl.GL_FLOAT, gl.GL_FALSE, 0,
34
                                  None)
35
    else:
36
        pass
37
38
39
def unbind_object(dataLoc):
40
    if dataLoc is not None:
41
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
42
        gl.glDisableVertexAttribArray(dataLoc)
43
    else:
44
        pass
45
46
47
class Indexer(object):
48
    ''' This is needed for CSG.'''
49
    def __init__(self):
50
        self.unique = []
51
        self.indices = []
52
        self.map = {}
53
54
    def add(self, obj):
55
        key = repr(obj)
56
57
        if not (key in self.map):
58
            self.map[key] = len(self.unique)
59
            self.unique.append(obj)
60
61
        return self.map[key]
62
63
64
class MeshBase(object):
65
    def __init__(self):
66
        self.program = None
67
        self.vertLoc = None
68
        self.UVLoc = None
69
        self.colorLoc = None
70
        self.modelID = None
71
72
    def addProgram(self, program):
73
        self.program = program
74
        self.vertLoc = self.program.get_attribute(b'position')
75
        self.UVLoc = self.program.get_attribute(b'vertexUV')
76
        self.colorLoc = self.program.get_attribute(b'color')
77
        self.modelID = self.program.new_uniform(b'model')
78
79
    def addTexture(self, texture):
80
        self.texture = texture
81
82
    def render(self):
83
84
        self.program.set_uniform_matrix(self.modelID, self.modelMatrix)
85
86
        if self.texture is not None:
87
            self.texture.bind()
88
        else:
89
            gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
90
91
        self.cbo = buffer_object(self.colors, gl.GLfloat)
92
93
        bind_object(self.vertLoc, self.vbo, 3)
94
        bind_object(self.UVLoc, self.uvbo, 3)
95
        bind_object(self.colorLoc, self.cbo, 3)
96
97
        if self.ibo:
98
            gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)
99
100
            gl.glDrawElements(gl.GL_TRIANGLES, self.ntris * 3,
101
                              gl.GL_UNSIGNED_INT, 0)
102
103
            gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0)
104
        else:
105
            gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, self.nverts)
106
107
        unbind_object(self.colorLoc)
108
        unbind_object(self.UVLoc)
109
        unbind_object(self.vertLoc)
110
111
    def buffer_objects(self):
112
        self.vbo = buffer_object(self.data, gl.GLfloat)
113
        self.uvbo = buffer_object(self.texCoord, gl.GLfloat)
114
        self.ibo = index_buffer_object(self.triangles, gl.GLuint)
115
116
117
class Mesh(MeshBase):
118
    def __init__(self):
119
        super(Mesh, self).__init__()
120
121
        self.xPos = 0
122
        self.yPos = 0
123
        self.xPosDelta = 0
124
        self.yPosDelta = 0
125
126
        self._scale = 1
127
        self.scaleDelta = 0
128
129
        self.modelMatrix = matrix.Matrix(4)
130
131
        self.rect = None
132
        self.nverts = 0
133
        self.ntris = 0
134
        self.data = []
135
        self.texCoord = []
136
137
        self.normals = []
138
        self.colors = []
139
        self.triangles = []
140
141
    def setColorAll(self, r, g, b):
142
        '''
143
        This will populate the colors array with same color for every vertex.
144
        '''
145
146
        if not self.colors:
147
            for i in range(self.nverts):
148
                self.colors.append([r, g, b])
149
        else:
150
            for i in range(self.nverts):
151
                self.colors[i] = [r, g, b]
152
153
    def fromData(self, data, texCoord=None, colors=None):
154
        '''
155
        This will take in any set of vertices, uv coordinates and colors arrays
156
        '''
157
        self.data = data
158
        self.nverts = len(self.data)
159
160
        if texCoord is not None:
161
            self.texCoord = texCoord
162
        else:
163
            self.texCoord = self.data
164
165
        if colors is not None:
166
            self.colors = colors
167
        else:
168
            self.colors = []
169
170
    def fromCSG(self, csg):
171
        '''
172
        This will take in a CSG object and convert it to mesh for
173
        rendering and simulation purposes.
174
        '''
175
        indexer = Indexer()
176
        polygons = csg.toPolygons()
177
178
        for i in range(len(polygons)):
179
            polygon = polygons[i]
180
            indices = []
181
            for j in range(len(polygon.vertices)):
182
                vertex = polygon.vertices[j]
183
                vertex.color = polygon.shared or [1.0, 1.0, 1.0]
184
                index = indexer.add(vertex)
185
                indices.append(index)
186
            for k in range(2, len(indices), 1):
187
                self.triangles.append([indices[0], indices[k - 1], indices[k]])
188
189
        for i in range(len(indexer.unique)):
190
            v = indexer.unique[i]
191
            self.data.append(v.pos.vector)
192
            self.normals.append(v.normal.vector)
193
            self.colors.append(v.color)
194
195
        # print("Indexer Unique Count: ", len(indexer.unique))
196
        # print("Polygon Count: ", len(polygons))
197
        # print("Triangles Count: ", len(self.triangles))
198
        # print("Vertices Count: ", len(self.data))
199
200
        self.nverts = len(self.data)
201
        self.ntris = len(self.triangles)
202
203
    def setBuffers(self):
204
        self.buffer_objects()
205
206
    def addPhysicsObject(self, physObj):
207
        '''This will attach a physics object to the mesh.'''
208
        self.rect = physObj.getCollisionModel().getModel()
209
        self.data = self.rect.getVertices()
210
        self.texCoord = self.rect.getVertices()
211
        self.modelMatrix = self.rect.getModelMatrix()
212
213
    def scale(self, value):
214
        self.scaleDelta = value / self._scale
215
        self._scale = value
216
217
    def translate(self, x, y):
218
        self.xPosDelta += x - self.xPos
219
        self.yPosDelta += y - self.yPos
220
        self.xPos = x
221
        self.yPos = y
222
223
    def update(self, physicsObject=None):
224
225
        if physicsObject is None:
226
            pass
227
        else:
228
            self.rect = physicsObject.getCollisionModel().getModel()
229
            self.modelMatrix = self.rect.getModelMatrix()
230
231
        if self.scaleDelta:
232
            vecScale = vector.Vector(
233
                3,
234
                data=[self.scaleDelta, self.scaleDelta, 0.0])
235
236
            self.modelMatrix.i_scale(vecScale)
237
            self.scaleDelta = 0
238
239
        if self.xPosDelta or self.yPosDelta:
240
            vecTrans = vector.Vector(
241
                3,
242
                data=[self.xPosDelta, self.yPosDelta, 0.0])
243
244
            self.modelMatrix.i_translate(vecTrans)
245
            self.xPosDelta = 0
246
            self.yPosDelta = 0
247