Skip to content

Commit

Permalink
Fix another path error and prepare to handle vertex colors on instances
Browse files Browse the repository at this point in the history
  • Loading branch information
Steven Garcia committed Oct 22, 2024
1 parent 143968b commit cb0526d
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 91 deletions.
11 changes: 10 additions & 1 deletion io_scene_halo/file_tag/build_scene/build_bsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,15 @@ def build_scene(context, LEVEL, game_version, game_title, file_version, fix_rota
object_mesh.data.use_auto_smooth = True

if len(LEVEL.instanced_geometry_instances) > 0:
instance_collection = cluster_collection_override
if not cluster_collection_override == None:
bsp_name = instance_collection.name.split("_", 1)[0]
intances_name = "%s_instances" % bsp_name
instance_collection = bpy.data.collections.get(intances_name)
if instance_collection == None:
instance_collection = bpy.data.collections.new(intances_name)
cluster_collection_override.children.link(instance_collection)

meshes = []
for instanced_geometry_definition_idx, instanced_geometry_definition in enumerate(LEVEL.instanced_geometry_definition):
cluster_name = "instanced_geometry_definition_%s" % instanced_geometry_definition_idx
Expand All @@ -588,7 +597,7 @@ def build_scene(context, LEVEL, game_version, game_title, file_version, fix_rota
object_mesh.tag_view.instance_lightmap_policy_enum = str(instanced_geometry_instance.lightmapping_policy)

object_mesh.parent = level_root
cluster_collection_override.objects.link(object_mesh)
instance_collection.objects.link(object_mesh)

matrix_scale = Matrix.Scale(instanced_geometry_instance.scale, 4)
matrix_rotation = Matrix()
Expand Down
9 changes: 8 additions & 1 deletion io_scene_halo/file_tag/build_scene/build_lightmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,13 @@ def build_clusters(lightmap_group, SBSP_ASSET, level_root, random_color_gen, col
def build_poops(lightmap_group, SBSP_ASSET, level_root, random_color_gen, collection, shader_collection_dic):
lightmap_instance_count = len(lightmap_group.poop_definitions)
if lightmap_instance_count > 0:
bsp_name = collection.name.split("_", 1)[0]
intances_name = "%s_lightmap_instances" % bsp_name
instance_collection = bpy.data.collections.get(intances_name)
if instance_collection == None:
instance_collection = bpy.data.collections.new(intances_name)
collection.children.link(instance_collection)

meshes = []
material_count = 0
if not SBSP_ASSET == None:
Expand All @@ -202,7 +209,7 @@ def build_poops(lightmap_group, SBSP_ASSET, level_root, random_color_gen, collec
if not mesh == None:
object_mesh = bpy.data.objects.new(ob_name, mesh)
object_mesh.parent = level_root
collection.objects.link(object_mesh)
instance_collection.objects.link(object_mesh)

object_mesh.tag_view.data_type_enum = '16'
object_mesh.tag_view.instance_lightmap_policy_enum = str(instanced_geometry_instance.lightmapping_policy)
Expand Down
3 changes: 3 additions & 0 deletions io_scene_halo/file_tag/build_scene/generate_h2_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,9 @@ def generate_scenario_scene(context, H2_ASSET, game_version, game_title, file_ve
clusters_collection = bpy.data.collections.new(cluster_name)
level_collection.children.link(clusters_collection)

clusters_collection.hide_viewport = True
clusters_collection.hide_render = True

build_scene_level.build_scene(context, SBSP_ASSET, game_version, game_title, file_version, fix_rotations, empty_markers, report, level_collection, clusters_collection)

if not LTMP_ASSET == None:
Expand Down
54 changes: 28 additions & 26 deletions io_scene_halo/global_functions/shader_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,21 +939,22 @@ def find_h2_shader_tag(import_filepath, material_name):

if not collection == None:
shader_directory = shader_collection_dic.get(collection)
import_shader_directory = os.path.join(tag_path, shader_directory.lower())
for root, dirs, filenames in os.walk(import_shader_directory):
for filename in filenames:
file = os.path.join(root, filename).lower()
if not shader_directory == None:
import_shader_directory = os.path.join(tag_path, shader_directory.lower())
for root, dirs, filenames in os.walk(import_shader_directory):
for filename in filenames:
file = os.path.join(root, filename).lower()

file_name = os.path.basename(file)
extension = None
result = file_name.rsplit(".", 1)
if len(result) == 2:
file_name = result[0]
extension = result[1]
file_name = os.path.basename(file)
extension = None
result = file_name.rsplit(".", 1)
if len(result) == 2:
file_name = result[0]
extension = result[1]

if shader_name == file_name and extension == "shader":
shader_path = file
break
if shader_name == file_name and extension == "shader":
shader_path = file
break

if shader_path == None:
import_directory = os.path.dirname(os.path.dirname(import_filepath)).lower()
Expand Down Expand Up @@ -1049,21 +1050,22 @@ def find_h3_shader_tag(import_filepath, material_name):

if not collection == None:
shader_directory = shader_collection_dic.get(collection)
import_shader_directory = os.path.join(tag_path, shader_directory.lower())
for root, dirs, filenames in os.walk(import_shader_directory):
for filename in filenames:
file = os.path.join(root, filename).lower()
if not shader_directory == None:
import_shader_directory = os.path.join(tag_path, shader_directory.lower())
for root, dirs, filenames in os.walk(import_shader_directory):
for filename in filenames:
file = os.path.join(root, filename).lower()

file_name = os.path.basename(file)
extension = None
result = file_name.rsplit(".", 1)
if len(result) == 2:
file_name = result[0]
extension = result[1]
file_name = os.path.basename(file)
extension = None
result = file_name.rsplit(".", 1)
if len(result) == 2:
file_name = result[0]
extension = result[1]

if shader_name == file_name and extension in shader_extensions:
shader_path = file
break
if shader_name == file_name and extension in shader_extensions:
shader_path = file
break

if shader_path == None:
import_directory = os.path.dirname(os.path.dirname(import_filepath)).lower()
Expand Down
143 changes: 80 additions & 63 deletions io_scene_halo/misc/lightmap_baking.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,70 @@
print("PIL not found. Unable to create image node.")
Image = None

def light_halo_2_mesh(context, lightmap_ob, BITMAP_ASSET, BITMAP, TAG, image_multiplier, lightmap_idx, pixel_offset):
lightmap_data = None
bitmap_class = None
if lightmap_ob.tag_view.instance_lightmap_policy_enum == '0':
bitmap_element = BITMAP_ASSET.bitmaps[lightmap_idx]
width = int(bitmap_element.width * image_multiplier)
height = int(bitmap_element.height * image_multiplier)
image = bpy.data.images.get("Lightmap_%s" % lightmap_idx)
if not image:
image = bpy.data.images.new("Lightmap_%s" % lightmap_idx, width, height)
else:
image.scale(width, height)
image.update()

for material_slot in lightmap_ob.material_slots:
material_slot.material.use_nodes = True
material_nodes = material_slot.material.node_tree.nodes
image_node = material_nodes.get("Lightmap Texture")
if image_node == None:
image_node = material_nodes.new("ShaderNodeTexImage")
image_node.name = "Lightmap Texture"
image_node.location = Vector((-260.0, 280.0))

image_node.image = image

for node in material_nodes:
node.select = False

image_node.select = True
material_nodes.active = image_node

lightmap_ob.select_set(True)
context.view_layer.objects.active = lightmap_ob

context.scene.render.engine = 'CYCLES'
bpy.ops.object.bake(type='DIFFUSE', pass_filter={'DIRECT','INDIRECT'}, uv_layer=lightmap_ob.data.uv_layers[1].name)
lightmap_ob.select_set(False)
context.view_layer.objects.active = None

buf = bytearray([int(p * 255) for p in image.pixels])
image = Image.frombytes("RGBA", (width, height), buf, 'raw', "RGBA")

lightmap_flags = H2BitmapFlags.power_of_two_dimensions.value

lightmap_image = image.convert('RGBA')
r,g,b,a = lightmap_image.split()
lightmap_data = Image.merge("RGBA", (b, g, r, a)).tobytes()
lightmap_format = H2BitmapFormatEnum.a8r8g8b8.value

bitmap_class = BITMAP.Bitmap()
bitmap_class.signature = "bitm"
bitmap_class.width = width
bitmap_class.height = height
bitmap_class.depth = 1
bitmap_class.bitmap_format = lightmap_format
bitmap_class.flags = lightmap_flags
bitmap_class.pixels_offset = pixel_offset
bitmap_class.native_mipmap_info_tag_block = TAG.TagBlock()
bitmap_class.native_mipmap_info_header = TAG.TagBlockHeader("tbfd", 0, 0, 12)
bitmap_class.native_mipmap_info = []
bitmap_class.nbmi_header = TAG.TagBlockHeader("nbmi", 0, 1, 24)

return lightmap_data, bitmap_class

def bake_clusters(context, game_title, scenario_path, image_multiplier, report, H2V=False):
bpy.ops.object.select_all(action='DESELECT')
if game_title == "halo1" and Image:
Expand Down Expand Up @@ -213,7 +277,9 @@ def bake_clusters(context, game_title, scenario_path, image_multiplier, report,
for bsp_element in SCNR_ASSET.structure_bsps:
bsp_name = os.path.basename(bsp_element.structure_bsp.name)
lightmap_name = "%s_lightmaps" % bsp_name
lightmap_instances_name = "%s_lightmap_instances" % bsp_name
lightmap_collection = bpy.data.collections.get(lightmap_name)
lightmap_instances_collection = bpy.data.collections.get(lightmap_instances_name)
if not lightmap_collection == None:
BSP_ASSET = parse_tag(bsp_element.structure_bsp, report, game_title, "retail")
LTMP_ASSET = parse_tag(bsp_element.structure_lightmap, report, game_title, "retail")
Expand Down Expand Up @@ -258,75 +324,25 @@ def bake_clusters(context, game_title, scenario_path, image_multiplier, report,

lightmap_idx = 0
lightmap_collection.hide_render = False
lightmap_instances_collection.hide_render = False
for lightmap_ob in lightmap_collection.objects:
cluster_lightmap_data, cluster_bitmap_class = light_halo_2_mesh(context, lightmap_ob, BITMAP_ASSET, BITMAP, TAG, image_multiplier, lightmap_idx, pixel_offset)
if lightmap_ob.tag_view.instance_lightmap_policy_enum == '0':
bitmap_element = BITMAP_ASSET.bitmaps[lightmap_idx]
width = int(bitmap_element.width * image_multiplier)
height = int(bitmap_element.height * image_multiplier)
image = bpy.data.images.get("Lightmap_%s" % lightmap_idx)
if not image:
image = bpy.data.images.new("Lightmap_%s" % lightmap_idx, width, height)
else:
image.scale(width, height)
image.update()

BITMAP.bitmaps.append(cluster_bitmap_class)
lightmap_idx += 1
for material_slot in lightmap_ob.material_slots:
material_slot.material.use_nodes = True
material_nodes = material_slot.material.node_tree.nodes
image_node = material_nodes.get("Lightmap Texture")
if image_node == None:
image_node = material_nodes.new("ShaderNodeTexImage")
image_node.name = "Lightmap Texture"
image_node.location = Vector((-260.0, 280.0))

image_node.image = image

for node in material_nodes:
node.select = False

image_node.select = True
material_nodes.active = image_node

lightmap_ob.select_set(True)
context.view_layer.objects.active = lightmap_ob

context.scene.render.engine = 'CYCLES'
bpy.ops.object.bake(type='DIFFUSE', pass_filter={'DIRECT','INDIRECT'}, uv_layer=lightmap_ob.data.uv_layers[1].name)
lightmap_ob.select_set(False)
context.view_layer.objects.active = None
pixel_data += cluster_lightmap_data
pixel_offset += len(cluster_lightmap_data)

buf = bytearray([int(p * 255) for p in image.pixels])
image = Image.frombytes("RGBA", (width, height), buf, 'raw', "RGBA")

bitmap_format = BITMAP.bitmap_body.format
lightmap_flags = H2BitmapFlags.power_of_two_dimensions.value

lightmap_image = image.convert('RGBA')
r,g,b,a = lightmap_image.split()
lightmap_data = Image.merge("RGBA", (b, g, r, a)).tobytes()
lightmap_format = H2BitmapFormatEnum.a8r8g8b8.value

pixel_data = pixel_data + lightmap_data

bitmap_class = BITMAP.Bitmap()
bitmap_class.signature = "bitm"
bitmap_class.width = width
bitmap_class.height = height
bitmap_class.depth = 1
bitmap_class.bitmap_format = lightmap_format
bitmap_class.flags = lightmap_flags
bitmap_class.pixels_offset = pixel_offset
bitmap_class.native_mipmap_info_tag_block = TAG.TagBlock()
bitmap_class.native_mipmap_info_header = TAG.TagBlockHeader("tbfd", 0, 0, 12)
bitmap_class.native_mipmap_info = []
bitmap_class.nbmi_header = TAG.TagBlockHeader("nbmi", 0, 1, 24)

BITMAP.bitmaps.append(bitmap_class)

pixel_offset += len(lightmap_data)
for lightmap_instance_ob in lightmap_instances_collection.objects:
instance_lightmap_data, instance_bitmap_class = light_halo_2_mesh(context, lightmap_instance_ob, BITMAP_ASSET, BITMAP, TAG, image_multiplier, lightmap_idx, pixel_offset)
if lightmap_instance_ob.tag_view.instance_lightmap_policy_enum == '0':
BITMAP.bitmaps.append(instance_bitmap_class)
lightmap_idx += 1
pixel_data += instance_lightmap_data
pixel_offset += len(instance_lightmap_data)

lightmap_collection.hide_render = True
lightmap_instances_collection.hide_render = True
BITMAP.bitmap_body.processed_pixel_data = TAG.RawData(len(pixel_data))
BITMAP.bitmap_body.processed_pixels = pixel_data

Expand All @@ -344,6 +360,7 @@ def bake_clusters(context, game_title, scenario_path, image_multiplier, report,
build_h2_bitmap(output_stream, BITMAP, report, H2V)
output_stream.close()

context.scene.halo_tag.image_multiplier = 1
return {'FINISHED'}

if __name__ == '__main__':
Expand Down

0 comments on commit cb0526d

Please sign in to comment.