-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathblender_import.py
217 lines (176 loc) · 7.16 KB
/
blender_import.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
import bpy
import bmesh
from .import_settings import ImportSettings
from .import_options import ImportOptions
from .blender_materials import BlenderMaterials
from .ldraw_file import LDrawFile
from .ldraw_node import LDrawNode
from .filesystem import FileSystem
from .ldraw_color import LDrawColor
from . import blender_camera
from . import helpers
from . import strings
from . import group
from . import ldraw_meta
from . import ldraw_object
from . import matrices
def do_import(filepath, color_code="16", return_mesh=False):
print(filepath) # TODO: multiple filepaths?
ImportSettings.save_settings()
ImportSettings.apply_settings()
BlenderMaterials.reset_caches()
FileSystem.reset_caches()
LDrawColor.reset_caches()
LDrawFile.reset_caches()
LDrawNode.reset_caches()
group.reset_caches()
ldraw_meta.reset_caches()
ldraw_object.reset_caches()
matrices.reset_caches()
__scene_setup()
FileSystem.build_search_paths(parent_filepath=filepath)
LDrawFile.read_color_table()
BlenderMaterials.create_blender_node_groups()
ldraw_file = LDrawFile.get_file(filepath)
if ldraw_file is None:
return
if ldraw_file.is_configuration():
__load_materials(ldraw_file)
return
root_node = LDrawNode()
root_node.is_root = True
root_node.file = ldraw_file
group.groups_setup(filepath)
ldraw_meta.meta_step()
# return root_node.load()
obj = root_node.load(color_code=color_code, return_mesh=return_mesh)
# s = {str(k): v for k, v in sorted(LDrawNode.geometry_datas2.items(), key=lambda ele: ele[1], reverse=True)}
# helpers.write_json("gs2.json", s, indent=4)
if ImportOptions.meta_step:
if ImportOptions.set_end_frame:
bpy.context.scene.frame_end = ldraw_meta.current_frame + ImportOptions.frames_per_step
bpy.context.scene.frame_set(bpy.context.scene.frame_end)
max_clip_end = 0
for camera in ldraw_meta.cameras:
camera = blender_camera.create_camera(camera, empty=ldraw_object.top_empty, collection=group.top_collection)
if bpy.context.scene.camera is None:
if camera.data.clip_end > max_clip_end:
max_clip_end = camera.data.clip_end
bpy.context.scene.camera = camera
for area in bpy.context.screen.areas:
if area.type == "VIEW_3D":
for space in area.spaces:
# space.shading.show_backface_culling = False
if space.type == "VIEW_3D":
if space.clip_end < max_clip_end:
space.clip_end = max_clip_end
return obj
def __scene_setup():
print('==========')
print(bpy.app.version)
print(bpy.app.version < (4, 3))
print('==========')
if bpy.app.version < (4, 3):
bpy.context.scene.eevee.use_ssr = True
bpy.context.scene.eevee.use_ssr_refraction = True
bpy.context.scene.eevee.use_taa_reprojection = True
else:
bpy.context.scene.eevee.use_raytracing = True
# https://blender.stackexchange.com/a/146838
# TODO: use line art modifier with grease pencil object
# parts can't be in more than one group if those group's parent is targeted by the modifier
# groups and ungroup collections can't be under model.ldr collection or else the lines don't render
# studs, and maybe other intersecting geometry, may have broken lines
# checking "overlapping edges as contour" helps, applying edge split, scale, marking freestyle edge does not seem to make a difference
if ImportOptions.use_freestyle_edges:
bpy.context.scene.render.use_freestyle = True
linesets = bpy.context.view_layer.freestyle_settings.linesets
if len(linesets) < 1:
linesets.new("LDraw LineSet")
lineset = linesets[0]
# lineset.linestyle.color = color.edge_color
lineset.select_by_visibility = True
lineset.select_by_edge_types = True
lineset.select_by_face_marks = False
lineset.select_by_collection = False
lineset.select_by_image_border = False
lineset.visibility = 'VISIBLE'
lineset.edge_type_negation = 'INCLUSIVE'
lineset.edge_type_combination = 'OR'
lineset.select_silhouette = False
lineset.select_border = False
lineset.select_contour = False
lineset.select_suggestive_contour = False
lineset.select_ridge_valley = False
lineset.select_crease = False
lineset.select_edge_mark = True
lineset.select_external_contour = False
lineset.select_material_boundary = False
def __load_materials(file):
ImportOptions.meta_group = False
ImportOptions.parent_to_empty = False
ImportOptions.make_gaps = False
# slope texture demonstration
obj = do_import('3044.dat')
if obj is not None:
obj.location.x = 0.0
obj.location.y = 5.0
obj.location.z = 0.5
# texmap demonstration
obj = do_import('27062p01.dat')
if obj is not None:
obj.location.x = 3
obj.location.y = 5
# cloth demonstration
obj = do_import('50231.dat')
if obj is not None:
obj.location.x = 6
obj.location.y = 5
colors = {}
group_name = 'blank'
for line in file.lines:
clean_line = helpers.clean_line(line)
strip_line = line.strip()
if clean_line.startswith("0 // LDraw"):
group_name = clean_line
colors[group_name] = []
continue
if clean_line.startswith("0 !COLOUR "):
colors[group_name].append(LDrawColor.parse_color(clean_line))
continue
j = 0
for collection_name, codes in colors.items():
scene_collection = group.get_scene_collection()
collection = group.get_collection(collection_name, scene_collection)
for i, color_code in enumerate(codes):
bm = bmesh.new()
monkey = True
if monkey:
prefix = 'monkey'
bmesh.ops.create_monkey(bm)
else:
prefix = 'cube'
bmesh.ops.create_cube(bm, size=1.0)
helpers.ensure_bmesh(bm)
for f in bm.faces:
f.smooth = True
mesh = bpy.data.meshes.new(f"{prefix}_{color_code}")
mesh[strings.ldraw_color_code_key] = color_code
material = BlenderMaterials.get_material(color_code, easy_key=True)
# https://blender.stackexchange.com/questions/23905/select-faces-depending-on-material
if material.name not in mesh.materials:
mesh.materials.append(material)
for face in bm.faces:
face.material_index = mesh.materials.find(material.name)
helpers.finish_bmesh(bm, mesh)
helpers.finish_mesh(mesh)
obj = bpy.data.objects.new(mesh.name, mesh)
obj[strings.ldraw_filename_key] = file.name
obj[strings.ldraw_color_code_key] = color_code
obj.modifiers.new("Subdivision", type='SUBSURF')
obj.location.x = i * 3
obj.location.y = -j * 3
color = LDrawColor.get_color(color_code)
obj.color = color.linear_color_a
group.link_obj(collection, obj)
j += 1