Skip to content

Commit

Permalink
w3d properties internal rename, multiple material per mesh object sup…
Browse files Browse the repository at this point in the history
…port, alpha transparency support, empty data object error fix (#261)

* __init__.py: blend_mode fixed to blend_method

Renamed from blend_mode to blend_method in accordance with blender internals

* material_import.py: Alpha Clip blend method for working transparency

* material_import.py: Added support for Multiple Materials per Mesh Object

Based on makarenk0's implementation, now with alpha transparency support.

* Update mesh_import.py: Multiple Material per Mesh Object support

+1 Argument to create_vertex_material in \material_import.py

* material_import.py: alpha clip blend mode for multiple material meshes

* Create an empty UV Map on early return

This is to ensure no export errors due to empty object data in certain formats. (One example would be an error thrown on Airfield Imports due to the HOUSECOLOR01 material not having an UV Map attached.)

* material_import.py: Fixed material duplication, node_tree manipulation

* autopep8 action fixes

* helpers.py : create_uvlayer, check if mesh exists

* Update material_pass.py

* Update material_pass.py

* tests/material_pass.py get_texture_stage() : attempt at per face texture id enumeration

* Update material_pass.py

* Update material_import.py

* Update material_import.py

* Update material_import.py

* autopep8 action fixes

---------

Co-authored-by: rizzntine <[email protected]>
  • Loading branch information
rizzntine and rizzntine authored Feb 1, 2024
1 parent 7eccd38 commit 1c3bf35
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 23 deletions.
4 changes: 2 additions & 2 deletions io_mesh_w3d/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ def draw(self, context):
col = layout.column()
col.prop(mat, 'surface_type')
col = layout.column()
col.prop(mat, 'blend_mode')
col.prop(mat, 'blend_method')
col = layout.column()
col.prop(mat, 'ambient')

Expand Down Expand Up @@ -370,7 +370,7 @@ def draw(self, context):
col = layout.column()
col.prop(mat, 'damaged_texture')
col = layout.column()
col.prop(mat, 'secondary_texture_blend_mode')
col.prop(mat, 'secondary_texture_blend_method')
col = layout.column()
col.prop(mat, 'tex_coord_mapper_0')
col = layout.column()
Expand Down
3 changes: 3 additions & 0 deletions io_mesh_w3d/common/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ def create_uvlayer(context, mesh, b_mesh, tris, mat_pass):
context.warning('only one texture stage per material pass supported')

if tx_coords is None:
if mesh is not None:
uv_layer = mesh.uv_layers.new(do_init=False)
return

uv_layer = mesh.uv_layers.new(do_init=False)
Expand All @@ -96,6 +98,7 @@ def create_uvlayer_2(context, mesh, b_mesh, tris, mat_pass):
if mat_pass.tx_coords_2:
tx_coords_2 = mat_pass.tx_coords_2
else:
uv_layer = mesh.uv_layers.new(do_init=False)
return

uv_layer = mesh.uv_layers.new(do_init=False)
Expand Down
81 changes: 63 additions & 18 deletions io_mesh_w3d/common/utils/material_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,71 @@
# vertex material
##########################################################################

def create_vertex_material(context, principleds, structure, mesh, b_mesh, name, triangles):
for vertMat in structure.vert_materials:
(material, principled) = create_material_from_vertex_material(name, vertMat)
mesh.materials.append(material)
principleds.append(principled)

for mat_pass in structure.material_passes:
create_uvlayer(context, mesh, b_mesh, triangles, mat_pass)
create_uvlayer_2(context, mesh, b_mesh, triangles, mat_pass)

if mat_pass.tx_stages:
tx_stage = mat_pass.tx_stages[0]
mat_id = mat_pass.vertex_material_ids[0]
tex_id = tx_stage.tx_ids[0][0]
def create_vertex_material(context, principleds, structure, mesh, b_mesh, name, triangles, mesh_ob):

if len(structure.material_passes) == 1 and len(
structure.textures) > 1: # condition for multiple materials per single mesh object
# Create the same amount of materials as textures used for this mesh
source_mat = structure.vert_materials[0]
for texture in structure.textures:
source_mat.vm_name = texture.id
(material, principled) = create_material_from_vertex_material(name, source_mat)
mesh.materials.append(material)
principleds.append(principled)

create_uvlayer(context, mesh, b_mesh, triangles, structure.material_passes[0])

# Load textures
for tex_id, texture in enumerate(structure.textures):
texture = structure.textures[tex_id]
tex = find_texture(context, texture.file, texture.id)
principleds[mat_id].base_color_texture.image = tex
principleds[mat_id].base_color_texture.image.name = texture.file
node_tree = mesh.materials[tex_id].node_tree
bsdf_node = node_tree.nodes.get('Principled BSDF')
texture_node = node_tree.nodes.new('ShaderNodeTexImage')
texture_node.image = tex
texture_node.location = (-350, 300)
links = node_tree.links
links.new(texture_node.outputs['Color'], bsdf_node.inputs['Base Color'])
links.new(texture_node.outputs['Alpha'], bsdf_node.inputs['Alpha'])

# Assign material to appropriate object faces
bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(mesh_ob.data)
bm.faces.ensure_lookup_table()
for i, face in enumerate(bm.faces):
if(i < len(structure.material_passes[0].tx_stages[0].tx_ids[0])):
bm.faces[i].material_index = structure.material_passes[0].tx_stages[0].tx_ids[0][i]
else:
bm.faces[i].material_index = structure.material_passes[0].tx_stages[0].tx_ids[0][0]
bpy.ops.object.mode_set(mode='OBJECT')
else:
for vertMat in structure.vert_materials:
(material, principled) = create_material_from_vertex_material(name, vertMat)
mesh.materials.append(material)
principleds.append(principled)

for mat_pass in structure.material_passes:
create_uvlayer(context, mesh, b_mesh, triangles, mat_pass)

if mat_pass.tx_stages:
tx_stage = mat_pass.tx_stages[0]
mat_id = mat_pass.vertex_material_ids[0]
tex_id = tx_stage.tx_ids[0][0]
texture = structure.textures[tex_id]
tex = find_texture(context, texture.file, texture.id)
node_tree = mesh.materials[tex_id].node_tree
bsdf_node = node_tree.nodes.get('Principled BSDF')
texture_node = node_tree.nodes.new('ShaderNodeTexImage')
texture_node.image = tex
texture_node.location = (-350, 300)
links = node_tree.links
links.new(texture_node.outputs['Color'], bsdf_node.inputs['Base Color'])
links.new(texture_node.outputs['Alpha'], bsdf_node.inputs['Alpha'])

# Iterate through all materials and set their blend mode to Alpha Clip for transparency
for material in mesh.materials:
if material:
material.blend_method = 'CLIP'


def create_material_from_vertex_material(name, vert_mat):
Expand All @@ -43,7 +90,6 @@ def create_material_from_vertex_material(name, vert_mat):
material = bpy.data.materials.new(name)
material.material_type = 'VERTEX_MATERIAL'
material.use_nodes = True
material.blend_method = 'BLEND'
material.show_transparent_back = False

attributes = {'DEFAULT'}
Expand Down Expand Up @@ -91,7 +137,6 @@ def create_material_from_shader_material(context, name, shader_mat):
material = bpy.data.materials.new(name)
material.material_type = 'SHADER_MATERIAL'
material.use_nodes = True
material.blend_method = 'BLEND'
material.show_transparent_back = False

material.technique = shader_mat.header.technique
Expand Down
4 changes: 2 additions & 2 deletions io_mesh_w3d/common/utils/mesh_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ def create_mesh(context, mesh_struct, coll):

if mesh_struct.vert_materials:
create_vertex_material(
context, principleds, mesh_struct, mesh, b_mesh, actual_mesh_name, triangles)
context, principleds, mesh_struct, mesh, b_mesh, actual_mesh_name, triangles, mesh_ob)

for i, shader in enumerate(mesh_struct.shaders):
set_shader_properties(mesh.materials[min(i, len(mesh.materials) - 1)], shader)

elif mesh_struct.prelit_vertex:
create_vertex_material(context, principleds, mesh_struct.prelit_vertex,
mesh, b_mesh, actual_mesh_name, triangles)
mesh, b_mesh, actual_mesh_name, triangles, mesh_ob)

for i, shader in enumerate(mesh_struct.prelit_vertex.shaders):
set_shader_properties(mesh.materials[i], shader)
Expand Down
2 changes: 1 addition & 1 deletion tests/w3d/helpers/mesh_structs/material_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def get_per_face_txcoords():

def get_texture_stage(index=0):
return TextureStage(
tx_ids=[[index]],
tx_ids=[[index] + [index] * max(0, index - 1)],
per_face_tx_coords=[get_per_face_txcoords()],
tx_coords=[get_uvs()])

Expand Down

0 comments on commit 1c3bf35

Please sign in to comment.