basilisk-engine 0.1.9__py3-none-any.whl → 0.1.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of basilisk-engine might be problematic. Click here for more details.

Files changed (87) hide show
  1. basilisk/__init__.py +14 -14
  2. basilisk/audio/sound.py +27 -27
  3. basilisk/bsk_assets/cube.obj +48 -48
  4. basilisk/collisions/broad/broad_aabb.py +102 -102
  5. basilisk/collisions/broad/broad_bvh.py +137 -137
  6. basilisk/collisions/collider.py +95 -95
  7. basilisk/collisions/collider_handler.py +224 -224
  8. basilisk/collisions/narrow/contact_manifold.py +95 -95
  9. basilisk/collisions/narrow/dataclasses.py +34 -34
  10. basilisk/collisions/narrow/deprecated.py +46 -46
  11. basilisk/collisions/narrow/epa.py +91 -91
  12. basilisk/collisions/narrow/gjk.py +66 -66
  13. basilisk/collisions/narrow/graham_scan.py +24 -24
  14. basilisk/collisions/narrow/helper.py +29 -29
  15. basilisk/collisions/narrow/line_intersections.py +106 -106
  16. basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
  17. basilisk/config.py +2 -2
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +179 -179
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +206 -206
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +72 -72
  25. basilisk/generic/input_validation.py +66 -66
  26. basilisk/generic/math.py +6 -6
  27. basilisk/generic/matrices.py +35 -35
  28. basilisk/generic/meshes.py +72 -72
  29. basilisk/generic/quat.py +142 -142
  30. basilisk/generic/quat_methods.py +7 -7
  31. basilisk/generic/raycast_result.py +23 -23
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input/mouse.py +61 -61
  34. basilisk/input/path.py +14 -14
  35. basilisk/mesh/cube.py +33 -33
  36. basilisk/mesh/mesh.py +230 -230
  37. basilisk/mesh/mesh_from_data.py +130 -130
  38. basilisk/mesh/model.py +271 -271
  39. basilisk/mesh/narrow_aabb.py +89 -89
  40. basilisk/mesh/narrow_bvh.py +91 -91
  41. basilisk/mesh/narrow_primative.py +23 -23
  42. basilisk/nodes/helper.py +28 -28
  43. basilisk/nodes/node.py +682 -682
  44. basilisk/nodes/node_handler.py +95 -95
  45. basilisk/particles/particle_handler.py +63 -63
  46. basilisk/particles/particle_renderer.py +87 -87
  47. basilisk/physics/impulse.py +112 -112
  48. basilisk/physics/physics_body.py +43 -43
  49. basilisk/physics/physics_engine.py +35 -35
  50. basilisk/render/batch.py +86 -86
  51. basilisk/render/camera.py +206 -206
  52. basilisk/render/chunk.py +99 -99
  53. basilisk/render/chunk_handler.py +154 -154
  54. basilisk/render/frame.py +101 -101
  55. basilisk/render/framebuffer.py +130 -130
  56. basilisk/render/image.py +87 -87
  57. basilisk/render/image_handler.py +122 -122
  58. basilisk/render/light.py +96 -96
  59. basilisk/render/light_handler.py +58 -58
  60. basilisk/render/material.py +219 -219
  61. basilisk/render/material_handler.py +135 -135
  62. basilisk/render/post_process.py +132 -132
  63. basilisk/render/shader.py +109 -109
  64. basilisk/render/shader_handler.py +79 -79
  65. basilisk/render/sky.py +120 -120
  66. basilisk/scene.py +264 -264
  67. basilisk/shaders/batch.frag +276 -276
  68. basilisk/shaders/batch.vert +115 -115
  69. basilisk/shaders/crt.frag +31 -31
  70. basilisk/shaders/draw.frag +21 -21
  71. basilisk/shaders/draw.vert +21 -21
  72. basilisk/shaders/filter.frag +22 -22
  73. basilisk/shaders/frame.frag +12 -12
  74. basilisk/shaders/frame.vert +13 -13
  75. basilisk/shaders/geometry.frag +8 -8
  76. basilisk/shaders/geometry.vert +41 -41
  77. basilisk/shaders/normal.frag +59 -59
  78. basilisk/shaders/normal.vert +96 -96
  79. basilisk/shaders/particle.frag +71 -71
  80. basilisk/shaders/particle.vert +84 -84
  81. basilisk/shaders/sky.frag +9 -9
  82. basilisk/shaders/sky.vert +13 -13
  83. {basilisk_engine-0.1.9.dist-info → basilisk_engine-0.1.10.dist-info}/METADATA +45 -38
  84. basilisk_engine-0.1.10.dist-info/RECORD +103 -0
  85. {basilisk_engine-0.1.9.dist-info → basilisk_engine-0.1.10.dist-info}/WHEEL +1 -1
  86. basilisk_engine-0.1.9.dist-info/RECORD +0 -103
  87. {basilisk_engine-0.1.9.dist-info → basilisk_engine-0.1.10.dist-info}/top_level.txt +0 -0
basilisk/mesh/model.py CHANGED
@@ -1,272 +1,272 @@
1
- import numpy as np
2
- import glm
3
-
4
-
5
- class Model:
6
- """
7
- Instance of a loaded model. Contains all objects, groups, and vertex data
8
- model.vertex_data contains all vertex data
9
- Objects stored in the model.objects dictionary, where keys are the object names (marked by 'o') in the .obj
10
- Default object key is '0'
11
- """
12
-
13
- def __init__(self) -> None:
14
- self.objects = {0 : VertexObject()}
15
-
16
- self.vertex_data = []
17
- """All vertex data in the obj. Use this for buffer data"""
18
- self.tangent_data = []
19
- """Tangents and bitangents"""
20
- self.format = None
21
- self.attribs = None
22
-
23
- self.vertex_points = []
24
- """The unique points given by the file"""
25
- self.vertex_uv = []
26
- """The unique texture coordinates given by the file"""
27
- self.vertex_normals = []
28
- """The unique normals given by the file"""
29
-
30
- self.point_indices = []
31
- """Indices of to vertex_points to construct triangles. Grouped in three."""
32
- self.uv_indices = []
33
- """Indices of to vertex_uv to construct triangles. Grouped in three."""
34
- self.normal_indices = []
35
- """Indices of to vertex_normals to construct triangles. Grouped in three."""
36
-
37
-
38
- def __repr__(self) -> str:
39
- return_string = '<Model | objects: {'
40
- for vertex_object in self.objects.keys():
41
- return_string += str(vertex_object) + ', '
42
- return_string = return_string[:-2] + '}>'
43
- return return_string
44
-
45
-
46
- class VertexObject:
47
- """
48
- Object conataining groups of vertices.
49
- Groups stored in the vertex_object.groups dictionary, where keys are the group names (marked by 'g') in the .obj
50
- Default group key is '0'
51
- """
52
-
53
- def __init__(self) -> None:
54
- self.groups = {0 : VertexGroup()}
55
-
56
- def __repr__(self) -> str:
57
- return_string = '<Vertex Object | groups: {'
58
- for vertex_group in self.groups.keys():
59
- return_string += str(vertex_group) + ', '
60
- return_string = return_string[:-2] + '}>'
61
- return return_string
62
-
63
-
64
- class VertexGroup:
65
- """
66
- Groups containing the vertex data
67
- vertex_group.vertex_data will be a numpy array of vertices
68
- """
69
-
70
- def __init__(self) -> None:
71
- self.vertex_data = []
72
- self.tangent_data = []
73
-
74
- def __repr__(self) -> str:
75
- return f'<Vertex Group | {self.vertex_data}>'
76
-
77
-
78
- def load_model(obj_file: str, calculate_tangents=False) -> Model:
79
- """
80
- Loads an obj model. Returns a model class instance
81
- model.vertex_data contains all vertex data combined in a single numpy array
82
- Args:
83
- file:
84
- Path to the .obj file to load
85
- calculate_tangents:
86
- Calculates the tangent and bitangent vectors for normal mapping
87
- """
88
-
89
- model = Model()
90
- current_object = 0
91
- current_group = 0
92
-
93
- vertex_format = None
94
- vertex_attribs = None
95
-
96
- with open(obj_file, 'r') as file:
97
- line = file.readline()
98
- while line:
99
- line = line.strip()
100
-
101
- # Add object
102
- if line.startswith('o '):
103
- if line[2:].strip() not in model.objects:
104
- model.objects[line[2:].strip()] = VertexObject()
105
- current_object = line[2:].strip()
106
-
107
- # Add group
108
- elif line.startswith('g '):
109
- if line[2:].strip() not in model.objects[current_object].groups:
110
- model.objects[current_object].groups[line[2:].strip()] = VertexGroup()
111
- current_group = line[2:].strip()
112
-
113
- # Add vertex point
114
- elif line.startswith('v '):
115
- points = list(map(float, line[2:].strip().split(' ')))
116
- model.vertex_points.append(points)
117
-
118
- # Add vertex UV
119
- elif line.startswith('vt '):
120
- uvs = list(map(float, line[3:].strip().split(' ')))
121
- model.vertex_uv.append(uvs[:2])
122
-
123
- # Add vertex normals
124
- elif line.startswith('vn '):
125
- normals = list(map(float, line[3:].strip().split(' ')))
126
- model.vertex_normals.append(normals)
127
-
128
- # Create faces
129
- elif line.startswith('f '):
130
- corners = line[2:].strip().split(' ')
131
- # The index of the position, uv, and normal in each vertex
132
- vertex_indices = [[0, 0, 0] for i in range(len(corners))]
133
- for corner_index, corner in enumerate(corners):
134
- corner = corner.split('/')
135
-
136
- if not vertex_format:
137
- if len(corner) == 1:
138
- vertex_format = '3f'
139
- vertex_attribs = ['in_position']
140
- elif not corner[1]:
141
- vertex_format = '3f 3f'
142
- vertex_attribs = ['in_position', 'in_normal']
143
- else:
144
- vertex_format = '3f 2f 3f'
145
- vertex_attribs = ['in_position', 'in_uv', 'in_normal']
146
-
147
- vertex = []
148
-
149
- # Add each attribute to the vertex
150
- for attribute, index in enumerate(corner):
151
- if attribute == 0 and index:
152
- vertex += model.vertex_points[int(index) - 1]
153
- vertex_indices[corner_index][0] = int(index) - 1
154
- if attribute == 1 and index:
155
- vertex += model.vertex_uv[int(index) - 1]
156
- vertex_indices[corner_index][1] = int(index) - 1
157
- if attribute == 2 and index:
158
- vertex += model.vertex_normals[int(index) - 1]
159
- vertex_indices[corner_index][2] = int(index) - 1
160
-
161
- # Replace the vertex data
162
- corners[corner_index] = vertex
163
-
164
- # Add each triangle to the objects vertex array
165
- for triangle in range(len(corners) - 2):
166
- if 'in_normal' not in vertex_attribs: # If the model doesnt have normals, calculate face normals
167
- p1 = glm.vec3(corners[0])
168
- p2 = glm.vec3(corners[1 + triangle])
169
- p3 = glm.vec3(corners[2 + triangle])
170
- normal = glm.normalize(glm.cross(p2 - p1, p3 - p1))
171
- normal = list(normal.xyz)
172
- model.vertex_normals.append(normal)
173
- model.objects[current_object].groups[current_group].vertex_data.append(corners[0] + normal)
174
- model.objects[current_object].groups[current_group].vertex_data.append(corners[1 + triangle] + normal)
175
- model.objects[current_object].groups[current_group].vertex_data.append(corners[2 + triangle] + normal)
176
-
177
- # Add the triangle to the indices
178
- model.point_indices.append([vertex_indices[0][0], vertex_indices[1 + triangle][0], vertex_indices[2 + triangle][0]])
179
- model.normal_indices.append([len(model.vertex_normals) - 1] * 3)
180
- else: # Standard reading
181
- model.objects[current_object].groups[current_group].vertex_data.append(corners[0])
182
- model.objects[current_object].groups[current_group].vertex_data.append(corners[1 + triangle])
183
- model.objects[current_object].groups[current_group].vertex_data.append(corners[2 + triangle])
184
-
185
- # Add the triangle to the indices
186
- model.point_indices.append([vertex_indices[0][0], vertex_indices[1 + triangle][0], vertex_indices[2 + triangle][0]])
187
- model.uv_indices.append([vertex_indices[0][1], vertex_indices[1 + triangle][1], vertex_indices[2 + triangle][1]])
188
- model.normal_indices.append([vertex_indices[0][2], vertex_indices[1 + triangle][2], vertex_indices[2 + triangle][2]])
189
-
190
- # Calculate the tangents and bitangents
191
- if calculate_tangents and 'in_uv' in vertex_attribs:
192
- v1 = corners[0]
193
- v2 = corners[1 + triangle]
194
- v3 = corners[2 + triangle]
195
-
196
- x1 = v2[0] - v1[0]
197
- x2 = v3[0] - v1[0]
198
- y1 = v2[1] - v1[1]
199
- y2 = v3[1] - v1[1]
200
- z1 = v2[2] - v1[2]
201
- z2 = v3[2] - v1[2]
202
-
203
- s1 = v2[3] - v1[3]
204
- s2 = v3[3] - v1[3]
205
- t1 = v2[4] - v1[4]
206
- t2 = v3[4] - v1[4]
207
-
208
- if (s1 * t2 - s2 * t1): r = 1.0 / (s1 * t2 - s2 * t1)
209
- else: r = 1
210
-
211
- tangent = glm.normalize(((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r))
212
- bitangent = glm.normalize(((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r))
213
-
214
- T = np.array(tangent)
215
- U = np.array(bitangent)
216
- N1 = np.array(corners[0][5:8])
217
- N2 = np.array(corners[1 + triangle][5:8])
218
- N3 = np.array(corners[2 + triangle][5:8])
219
-
220
- T1 = T - np.dot(N1, T) * N1
221
- T2 = T - np.dot(N2, T) * N2
222
- T3 = T - np.dot(N3, T) * N3
223
- U1 = U - np.dot(N1, U) * N1 - np.dot(T1, U) * T1
224
- U2 = U - np.dot(N2, U) * N2 - np.dot(T2, U) * T2
225
- U3 = U - np.dot(N3, U) * N3 - np.dot(T3, U) * T3
226
-
227
- data = [[*T1, *U1], [*T2, *U2], [*T3, *U3]]
228
-
229
- model.objects[current_object].groups[current_group].tangent_data.extend(data)
230
-
231
- line = file.readline()
232
-
233
- vertex_groups = []
234
- tangent_groups = []
235
-
236
- # Loop through all vertex objects and groups in the model
237
- for object in model.objects.values():
238
- for group in object.groups.values():
239
- # Ignore empty groups
240
- if not len(group.vertex_data): continue
241
- # Convert to a numpy array
242
- group.vertex_data = np.array(group.vertex_data, dtype='f4')
243
- # Add to the vertex_groups list to be stacked
244
- vertex_groups.append(group.vertex_data)
245
- tangent_groups.append(group.tangent_data)
246
-
247
- # Array of all vertices from all the model's groups combined
248
- vertices = np.vstack(vertex_groups, dtype='f4')
249
- tangents = np.vstack(tangent_groups, dtype='f4')
250
-
251
- # Save the model's combined vertices
252
- model.vertex_data = vertices
253
- model.tangent_data = tangents
254
-
255
- # Convert the points and indices to array for convenience with C-like buffers
256
- model.vertex_points = np.array(model.vertex_points, dtype="f4")
257
- model.vertex_uv = np.array(model.vertex_uv, dtype="f4")
258
- model.vertex_normals = np.array(model.vertex_normals, dtype="f4")
259
- model.point_indices = np.array(model.point_indices, dtype="i4")
260
- model.uv_indices = np.array(model.uv_indices, dtype="i4")
261
- model.normal_indices = np.array(model.normal_indices, dtype="i4")
262
-
263
- # Add normals to position only models
264
- if vertex_format == '3f':
265
- vertex_format = '3f 3f'
266
- vertex_attribs = ['in_position', 'in_normal']
267
-
268
- # Save the model vertex format and attribs
269
- model.format = vertex_format
270
- model.attribs = vertex_attribs
271
-
1
+ import numpy as np
2
+ import glm
3
+
4
+
5
+ class Model:
6
+ """
7
+ Instance of a loaded model. Contains all objects, groups, and vertex data
8
+ model.vertex_data contains all vertex data
9
+ Objects stored in the model.objects dictionary, where keys are the object names (marked by 'o') in the .obj
10
+ Default object key is '0'
11
+ """
12
+
13
+ def __init__(self) -> None:
14
+ self.objects = {0 : VertexObject()}
15
+
16
+ self.vertex_data = []
17
+ """All vertex data in the obj. Use this for buffer data"""
18
+ self.tangent_data = []
19
+ """Tangents and bitangents"""
20
+ self.format = None
21
+ self.attribs = None
22
+
23
+ self.vertex_points = []
24
+ """The unique points given by the file"""
25
+ self.vertex_uv = []
26
+ """The unique texture coordinates given by the file"""
27
+ self.vertex_normals = []
28
+ """The unique normals given by the file"""
29
+
30
+ self.point_indices = []
31
+ """Indices of to vertex_points to construct triangles. Grouped in three."""
32
+ self.uv_indices = []
33
+ """Indices of to vertex_uv to construct triangles. Grouped in three."""
34
+ self.normal_indices = []
35
+ """Indices of to vertex_normals to construct triangles. Grouped in three."""
36
+
37
+
38
+ def __repr__(self) -> str:
39
+ return_string = '<Model | objects: {'
40
+ for vertex_object in self.objects.keys():
41
+ return_string += str(vertex_object) + ', '
42
+ return_string = return_string[:-2] + '}>'
43
+ return return_string
44
+
45
+
46
+ class VertexObject:
47
+ """
48
+ Object conataining groups of vertices.
49
+ Groups stored in the vertex_object.groups dictionary, where keys are the group names (marked by 'g') in the .obj
50
+ Default group key is '0'
51
+ """
52
+
53
+ def __init__(self) -> None:
54
+ self.groups = {0 : VertexGroup()}
55
+
56
+ def __repr__(self) -> str:
57
+ return_string = '<Vertex Object | groups: {'
58
+ for vertex_group in self.groups.keys():
59
+ return_string += str(vertex_group) + ', '
60
+ return_string = return_string[:-2] + '}>'
61
+ return return_string
62
+
63
+
64
+ class VertexGroup:
65
+ """
66
+ Groups containing the vertex data
67
+ vertex_group.vertex_data will be a numpy array of vertices
68
+ """
69
+
70
+ def __init__(self) -> None:
71
+ self.vertex_data = []
72
+ self.tangent_data = []
73
+
74
+ def __repr__(self) -> str:
75
+ return f'<Vertex Group | {self.vertex_data}>'
76
+
77
+
78
+ def load_model(obj_file: str, calculate_tangents=False) -> Model:
79
+ """
80
+ Loads an obj model. Returns a model class instance
81
+ model.vertex_data contains all vertex data combined in a single numpy array
82
+ Args:
83
+ file:
84
+ Path to the .obj file to load
85
+ calculate_tangents:
86
+ Calculates the tangent and bitangent vectors for normal mapping
87
+ """
88
+
89
+ model = Model()
90
+ current_object = 0
91
+ current_group = 0
92
+
93
+ vertex_format = None
94
+ vertex_attribs = None
95
+
96
+ with open(obj_file, 'r') as file:
97
+ line = file.readline()
98
+ while line:
99
+ line = line.strip()
100
+
101
+ # Add object
102
+ if line.startswith('o '):
103
+ if line[2:].strip() not in model.objects:
104
+ model.objects[line[2:].strip()] = VertexObject()
105
+ current_object = line[2:].strip()
106
+
107
+ # Add group
108
+ elif line.startswith('g '):
109
+ if line[2:].strip() not in model.objects[current_object].groups:
110
+ model.objects[current_object].groups[line[2:].strip()] = VertexGroup()
111
+ current_group = line[2:].strip()
112
+
113
+ # Add vertex point
114
+ elif line.startswith('v '):
115
+ points = list(map(float, line[2:].strip().split(' ')))
116
+ model.vertex_points.append(points)
117
+
118
+ # Add vertex UV
119
+ elif line.startswith('vt '):
120
+ uvs = list(map(float, line[3:].strip().split(' ')))
121
+ model.vertex_uv.append(uvs[:2])
122
+
123
+ # Add vertex normals
124
+ elif line.startswith('vn '):
125
+ normals = list(map(float, line[3:].strip().split(' ')))
126
+ model.vertex_normals.append(normals)
127
+
128
+ # Create faces
129
+ elif line.startswith('f '):
130
+ corners = line[2:].strip().split(' ')
131
+ # The index of the position, uv, and normal in each vertex
132
+ vertex_indices = [[0, 0, 0] for i in range(len(corners))]
133
+ for corner_index, corner in enumerate(corners):
134
+ corner = corner.split('/')
135
+
136
+ if not vertex_format:
137
+ if len(corner) == 1:
138
+ vertex_format = '3f'
139
+ vertex_attribs = ['in_position']
140
+ elif not corner[1]:
141
+ vertex_format = '3f 3f'
142
+ vertex_attribs = ['in_position', 'in_normal']
143
+ else:
144
+ vertex_format = '3f 2f 3f'
145
+ vertex_attribs = ['in_position', 'in_uv', 'in_normal']
146
+
147
+ vertex = []
148
+
149
+ # Add each attribute to the vertex
150
+ for attribute, index in enumerate(corner):
151
+ if attribute == 0 and index:
152
+ vertex += model.vertex_points[int(index) - 1]
153
+ vertex_indices[corner_index][0] = int(index) - 1
154
+ if attribute == 1 and index:
155
+ vertex += model.vertex_uv[int(index) - 1]
156
+ vertex_indices[corner_index][1] = int(index) - 1
157
+ if attribute == 2 and index:
158
+ vertex += model.vertex_normals[int(index) - 1]
159
+ vertex_indices[corner_index][2] = int(index) - 1
160
+
161
+ # Replace the vertex data
162
+ corners[corner_index] = vertex
163
+
164
+ # Add each triangle to the objects vertex array
165
+ for triangle in range(len(corners) - 2):
166
+ if 'in_normal' not in vertex_attribs: # If the model doesnt have normals, calculate face normals
167
+ p1 = glm.vec3(corners[0])
168
+ p2 = glm.vec3(corners[1 + triangle])
169
+ p3 = glm.vec3(corners[2 + triangle])
170
+ normal = glm.normalize(glm.cross(p2 - p1, p3 - p1))
171
+ normal = list(normal.xyz)
172
+ model.vertex_normals.append(normal)
173
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[0] + normal)
174
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[1 + triangle] + normal)
175
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[2 + triangle] + normal)
176
+
177
+ # Add the triangle to the indices
178
+ model.point_indices.append([vertex_indices[0][0], vertex_indices[1 + triangle][0], vertex_indices[2 + triangle][0]])
179
+ model.normal_indices.append([len(model.vertex_normals) - 1] * 3)
180
+ else: # Standard reading
181
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[0])
182
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[1 + triangle])
183
+ model.objects[current_object].groups[current_group].vertex_data.append(corners[2 + triangle])
184
+
185
+ # Add the triangle to the indices
186
+ model.point_indices.append([vertex_indices[0][0], vertex_indices[1 + triangle][0], vertex_indices[2 + triangle][0]])
187
+ model.uv_indices.append([vertex_indices[0][1], vertex_indices[1 + triangle][1], vertex_indices[2 + triangle][1]])
188
+ model.normal_indices.append([vertex_indices[0][2], vertex_indices[1 + triangle][2], vertex_indices[2 + triangle][2]])
189
+
190
+ # Calculate the tangents and bitangents
191
+ if calculate_tangents and 'in_uv' in vertex_attribs:
192
+ v1 = corners[0]
193
+ v2 = corners[1 + triangle]
194
+ v3 = corners[2 + triangle]
195
+
196
+ x1 = v2[0] - v1[0]
197
+ x2 = v3[0] - v1[0]
198
+ y1 = v2[1] - v1[1]
199
+ y2 = v3[1] - v1[1]
200
+ z1 = v2[2] - v1[2]
201
+ z2 = v3[2] - v1[2]
202
+
203
+ s1 = v2[3] - v1[3]
204
+ s2 = v3[3] - v1[3]
205
+ t1 = v2[4] - v1[4]
206
+ t2 = v3[4] - v1[4]
207
+
208
+ if (s1 * t2 - s2 * t1): r = 1.0 / (s1 * t2 - s2 * t1)
209
+ else: r = 1
210
+
211
+ tangent = glm.normalize(((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r))
212
+ bitangent = glm.normalize(((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r))
213
+
214
+ T = np.array(tangent)
215
+ U = np.array(bitangent)
216
+ N1 = np.array(corners[0][5:8])
217
+ N2 = np.array(corners[1 + triangle][5:8])
218
+ N3 = np.array(corners[2 + triangle][5:8])
219
+
220
+ T1 = T - np.dot(N1, T) * N1
221
+ T2 = T - np.dot(N2, T) * N2
222
+ T3 = T - np.dot(N3, T) * N3
223
+ U1 = U - np.dot(N1, U) * N1 - np.dot(T1, U) * T1
224
+ U2 = U - np.dot(N2, U) * N2 - np.dot(T2, U) * T2
225
+ U3 = U - np.dot(N3, U) * N3 - np.dot(T3, U) * T3
226
+
227
+ data = [[*T1, *U1], [*T2, *U2], [*T3, *U3]]
228
+
229
+ model.objects[current_object].groups[current_group].tangent_data.extend(data)
230
+
231
+ line = file.readline()
232
+
233
+ vertex_groups = []
234
+ tangent_groups = []
235
+
236
+ # Loop through all vertex objects and groups in the model
237
+ for object in model.objects.values():
238
+ for group in object.groups.values():
239
+ # Ignore empty groups
240
+ if not len(group.vertex_data): continue
241
+ # Convert to a numpy array
242
+ group.vertex_data = np.array(group.vertex_data, dtype='f4')
243
+ # Add to the vertex_groups list to be stacked
244
+ vertex_groups.append(group.vertex_data)
245
+ tangent_groups.append(group.tangent_data)
246
+
247
+ # Array of all vertices from all the model's groups combined
248
+ vertices = np.vstack(vertex_groups, dtype='f4')
249
+ tangents = np.vstack(tangent_groups, dtype='f4')
250
+
251
+ # Save the model's combined vertices
252
+ model.vertex_data = vertices
253
+ model.tangent_data = tangents
254
+
255
+ # Convert the points and indices to array for convenience with C-like buffers
256
+ model.vertex_points = np.array(model.vertex_points, dtype="f4")
257
+ model.vertex_uv = np.array(model.vertex_uv, dtype="f4")
258
+ model.vertex_normals = np.array(model.vertex_normals, dtype="f4")
259
+ model.point_indices = np.array(model.point_indices, dtype="i4")
260
+ model.uv_indices = np.array(model.uv_indices, dtype="i4")
261
+ model.normal_indices = np.array(model.normal_indices, dtype="i4")
262
+
263
+ # Add normals to position only models
264
+ if vertex_format == '3f':
265
+ vertex_format = '3f 3f'
266
+ vertex_attribs = ['in_position', 'in_normal']
267
+
268
+ # Save the model vertex format and attribs
269
+ model.format = vertex_format
270
+ model.attribs = vertex_attribs
271
+
272
272
  return model