basilisk-engine 0.1.38__py3-none-any.whl → 0.1.40__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 (97) hide show
  1. basilisk/__init__.py +26 -26
  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 +226 -226
  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 +53 -53
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +178 -178
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +165 -165
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +70 -70
  25. basilisk/generic/input_validation.py +82 -82
  26. basilisk/generic/math.py +18 -7
  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 +26 -26
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input/__init__.py +0 -0
  34. basilisk/input/mouse.py +62 -0
  35. basilisk/input/path.py +14 -0
  36. basilisk/input_output/IO_handler.py +91 -91
  37. basilisk/input_output/clock.py +49 -49
  38. basilisk/input_output/keys.py +43 -43
  39. basilisk/input_output/mouse.py +90 -90
  40. basilisk/input_output/path.py +14 -14
  41. basilisk/mesh/cube.py +33 -33
  42. basilisk/mesh/mesh.py +233 -233
  43. basilisk/mesh/mesh_from_data.py +150 -150
  44. basilisk/mesh/model.py +271 -271
  45. basilisk/mesh/narrow_aabb.py +89 -89
  46. basilisk/mesh/narrow_bvh.py +91 -91
  47. basilisk/mesh/narrow_primative.py +23 -23
  48. basilisk/nodes/helper.py +28 -28
  49. basilisk/nodes/node.py +709 -704
  50. basilisk/nodes/node_handler.py +97 -97
  51. basilisk/particles/particle_handler.py +64 -64
  52. basilisk/particles/particle_renderer.py +93 -93
  53. basilisk/physics/impulse.py +112 -112
  54. basilisk/physics/physics_body.py +43 -43
  55. basilisk/physics/physics_engine.py +35 -35
  56. basilisk/render/batch.py +103 -103
  57. basilisk/render/bloom.py +107 -107
  58. basilisk/render/camera.py +260 -260
  59. basilisk/render/chunk.py +108 -108
  60. basilisk/render/chunk_handler.py +167 -167
  61. basilisk/render/frame.py +110 -110
  62. basilisk/render/framebuffer.py +202 -202
  63. basilisk/render/image.py +120 -120
  64. basilisk/render/image_handler.py +120 -120
  65. basilisk/render/light.py +96 -96
  66. basilisk/render/light_handler.py +58 -58
  67. basilisk/render/material.py +232 -232
  68. basilisk/render/material_handler.py +133 -133
  69. basilisk/render/post_process.py +146 -146
  70. basilisk/render/shader.py +134 -134
  71. basilisk/render/shader_handler.py +85 -85
  72. basilisk/render/sky.py +120 -120
  73. basilisk/scene.py +290 -290
  74. basilisk/shaders/batch.frag +289 -289
  75. basilisk/shaders/batch.vert +117 -117
  76. basilisk/shaders/bloom_downsample.frag +42 -42
  77. basilisk/shaders/bloom_frame.frag +24 -24
  78. basilisk/shaders/bloom_upsample.frag +33 -33
  79. basilisk/shaders/crt.frag +31 -31
  80. basilisk/shaders/draw.frag +25 -25
  81. basilisk/shaders/draw.vert +25 -25
  82. basilisk/shaders/filter.frag +22 -22
  83. basilisk/shaders/frame.frag +12 -12
  84. basilisk/shaders/frame.vert +13 -13
  85. basilisk/shaders/geometry.frag +10 -10
  86. basilisk/shaders/geometry.vert +41 -41
  87. basilisk/shaders/normal.frag +62 -62
  88. basilisk/shaders/normal.vert +96 -96
  89. basilisk/shaders/particle.frag +76 -76
  90. basilisk/shaders/particle.vert +86 -86
  91. basilisk/shaders/sky.frag +23 -23
  92. basilisk/shaders/sky.vert +13 -13
  93. {basilisk_engine-0.1.38.dist-info → basilisk_engine-0.1.40.dist-info}/METADATA +89 -89
  94. basilisk_engine-0.1.40.dist-info/RECORD +114 -0
  95. {basilisk_engine-0.1.38.dist-info → basilisk_engine-0.1.40.dist-info}/WHEEL +1 -1
  96. basilisk_engine-0.1.38.dist-info/RECORD +0 -111
  97. {basilisk_engine-0.1.38.dist-info → basilisk_engine-0.1.40.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