Completed
Push — master ( 029ee2...010d86 )
by
unknown
06:05
created

ed2d.MeshBase.addMaterials()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 3
rs 10
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
def calc_face_normal(vertex1, vertex2, vertex3):
47
    ''' Calculate a face normal from 3 vertices. 3D Vector inputs. '''
48
    vertex11 = vertex2 - vertex1
49
    vertex22 = vertex3 - vertex1
50
    normal = vertex11.cross(vertex22)
51
    normal.i_normalize()
52
    return normal
53
54
55
class Indexer(object):
56
    ''' This is needed for CSG.'''
57
    def __init__(self):
58
        self.unique = []
59
        self.indices = []
60
        self.map = {}
61
62
    def add(self, obj):
63
        key = repr(obj)
64
65
        if not (key in self.map):
66
            self.map[key] = len(self.unique)
67
            self.unique.append(obj)
68
69
        return self.map[key]
70
71
72
class MeshBase(object):
73
    def __init__(self):
74
        self.program = None
75
        self.vertLoc = None
76
        self.UVLoc = None
77
        self.colorLoc = None
78
        self.modelID = None
79
        self.matrix = matrix.Matrix(4) # Model matrix
80
81
    def addProgram(self, program):
82
        self.program = program
83
        self.vertLoc = self.program.get_attribute(b'position')
84
        self.UVLoc = self.program.get_attribute(b'vertexUV')
85
        self.colorLoc = self.program.get_attribute(b'color')
86
        self.modelID = self.program.new_uniform(b'model')
87
88
    def addMaterials(self, materList):
89
        # Because there are different materials per mesh, a list needs to be provided
90
        self.materials = materList
91
92
    # This will get removed-------
93
    def addTexture(self, texture):
94
        self.texture = texture
95
    #-----------------------------
96
97
    def render(self):
98
        #NOTE: Need to implement rendering by materials
99
100
        self.program.set_uniform_matrix(self.modelID, self.matrix)
101
102
        if self.texture is not None:
103
            self.texture.bind()
104
        else:
105
            gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
106
107
        self.cbo = buffer_object(self.colors, gl.GLfloat)
108
109
        bind_object(self.vertLoc, self.vbo, 3)
110
        bind_object(self.UVLoc, self.uvbo, 3)
111
        bind_object(self.colorLoc, self.cbo, 3)
112
113
        if self.ibo:
114
            gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo)
115
116
            gl.glDrawElements(gl.GL_TRIANGLES, self.ntris * 3,
117
                              gl.GL_UNSIGNED_INT, 0)
118
119
            gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0)
120
        else:
121
            gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, self.nverts)
122
123
        unbind_object(self.colorLoc)
124
        unbind_object(self.UVLoc)
125
        unbind_object(self.vertLoc)
126
127
    def buffer_objects(self):
128
        self.vbo = buffer_object(self.data, gl.GLfloat)
129
        self.uvbo = buffer_object(self.texCoord, gl.GLfloat)
130
        self.ibo = index_buffer_object(self.triangles, gl.GLuint)
131
132
133
class Mesh(MeshBase):
134
    def __init__(self):
135
        super(Mesh, self).__init__()
136
137
        self.xPos = 0
138
        self.yPos = 0
139
        self.xPosDelta = 0
140
        self.yPosDelta = 0
141
142
        self._scale = 1
143
        self.scaleDelta = 0
144
145
        self.rect = None
146
        self.nverts = 0
147
        self.ntris = 0
148
        self.data = []
149
        self.texCoord = []
150
151
        self.normals = []
152
        self.colors = []
153
        self.triangles = []
154
155
        self.physObj = None
156
157
    def setColorAll(self, r, g, b):
158
        '''
159
        This will populate the colors array with same color for every vertex.
160
        '''
161
162
        if not self.colors:
163
            for i in range(self.nverts):
164
                self.colors.append([r, g, b])
165
        else:
166
            for i in range(self.nverts):
167
                self.colors[i] = [r, g, b]
168
169
    def fromData(self, data, texCoord=None, colors=None):
170
        '''
171
        This will take in any set of vertices, uv coordinates and colors arrays
172
        '''
173
        self.data = data
174
        self.nverts = len(self.data)
175
176
        if texCoord is not None:
177
            self.texCoord = texCoord
178
        else:
179
            self.texCoord = self.data
180
181
        if colors is not None:
182
            self.colors = colors
183
        else:
184
            self.colors = []
185
186
        self.buffer_objects()
187
188
    def fromCSG(self, csg):
189
        '''
190
        This will take in a CSG object and convert it to mesh for
191
        rendering and simulation purposes.
192
        '''
193
        indexer = Indexer()
194
        polygons = csg.toPolygons()
195
196
        for i in range(len(polygons)):
197
            polygon = polygons[i]
198
            indices = []
199
            for j in range(len(polygon.vertices)):
200
                vertex = polygon.vertices[j]
201
                vertex.color = polygon.shared or [1.0, 1.0, 1.0]
202
                index = indexer.add(vertex)
203
                indices.append(index)
204
            for k in range(2, len(indices), 1):
205
                self.triangles.append([indices[0], indices[k - 1], indices[k]])
206
207
        for i in range(len(indexer.unique)):
208
            v = indexer.unique[i]
209
            self.data.append(v.pos.vector)
210
            self.normals.append(v.normal.vector)
211
            self.colors.append(v.color)
212
213
        # print("Indexer Unique Count: ", len(indexer.unique))
214
        # print("Polygon Count: ", len(polygons))
215
        # print("Triangles Count: ", len(self.triangles))
216
        # print("Vertices Count: ", len(self.data))
217
218
        self.nverts = len(self.data)
219
        self.ntris = len(self.triangles)
220
221
        self.buffer_objects()
222
223
    def addPhysicsObject(self, physObj):
224
        '''This will attach a physics object to the mesh.'''
225
        self.physObj = physObj
226
        self.rect = physObj.getCollisionModel().getModel()
227
        self.data = self.rect.getVertices()
228
        self.texCoord = self.rect.getVertices()
229
        self.matrix = self.rect.getModelMatrix()
230
231
    def scale(self, value):
232
        self.scaleDelta = value / self._scale
233
        self._scale = value
234
235
    def translate(self, x, y):
236
        self.xPosDelta += x - self.xPos
237
        self.yPosDelta += y - self.yPos
238
        self.xPos = x
239
        self.yPos = y
240
241
    # TODO - Implement rotation..
242
243
    def update(self):
244
245
        if self.physObj is None:
246
            pass
247
        else:
248
            self.rect = self.physObj.getCollisionModel().getModel()
249
            self.matrix = self.rect.getModelMatrix()
250
251
        if self.scaleDelta:
252
            vecScale = vector.Vector(
253
                3,
254
                data=[self.scaleDelta, self.scaleDelta, 0.0])
255
256
            self.matrix.i_scale(vecScale)
257
            self.scaleDelta = 0
258
259
        if self.xPosDelta or self.yPosDelta:
260
            vecTrans = vector.Vector(
261
                3,
262
                data=[self.xPosDelta, self.yPosDelta, 0.0])
263
264
            self.matrix.i_translate(vecTrans)
265
            self.xPosDelta = 0
266
            self.yPosDelta = 0
267