#include "CMDL.hpp" namespace Retro { namespace DNACMDL { void InitGeomBlenderContext(HECL::BlenderConnection::PyOutStream& os, const HECL::ProjectPath& masterShaderPath) { os << "# Using 'Blender Game'\n" "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" "\n" "# Clear Scene\n" "for ob in bpy.data.objects:\n" " if ob.type != 'LAMP':\n" " bpy.context.scene.objects.unlink(ob)\n" " bpy.data.objects.remove(ob)\n" "\n" "def loop_from_facevert(bm, face, vert_idx):\n" " for loop in face.loops:\n" " if loop.vert[bm.verts.layers.int['CMDLOriginalPosIdxs']] == vert_idx:\n" " return loop\n" "\n" "def add_triangle(bm, vert_seq, vert_indices, norm_seq, norm_indices, mat_nr, od_list):\n" " if len(set(vert_indices)) != 3:\n" " return None, None\n" "\n" " ret_mesh = bm\n" " vert_seq.ensure_lookup_table()\n" " verts = [vert_seq[i] for i in vert_indices]\n" "\n" " # Make the face\n" " face = bm.faces.get(verts)\n" "\n" " if face is not None and face.material_index != mat_nr: # Same poly, new material\n" " # Overdraw detected; track copy\n" " od_entry = None\n" " for entry in od_list:\n" " if entry['material'] == mat_nr:\n" " od_entry = entry\n" " if od_entry is None:\n" " bm_cpy = bm.copy()\n" " od_entry = {'material':mat_nr, 'bm':bm_cpy}\n" " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context=3)\n" " od_list.append(od_entry)\n" " od_entry['bm'].verts.ensure_lookup_table()\n" " verts = [od_entry['bm'].verts[i] for i in vert_indices]\n" " face = od_entry['bm'].faces.get(verts)\n" " if face is None:\n" " face = od_entry['bm'].faces.new(verts)\n" " else: # Probably a double-sided surface\n" " face = face.copy()\n" " for i in range(3):\n" " face.verts[i].co = verts[i].co\n" " ret_mesh = od_entry['bm']\n" "\n" " elif face is not None: # Same material, probably double-sided\n" " face = face.copy()\n" " for i in range(3):\n" " face.verts[i].co = verts[i].co\n" "\n" " else: \n" " face = bm.faces.new(verts)\n" "\n" " for i in range(3):\n" " face.verts[i][ret_mesh.verts.layers.int['CMDLOriginalPosIdxs']] = vert_indices[i]\n" " face.loops[i][ret_mesh.loops.layers.int['CMDLOriginalNormIdxs']] = norm_indices[i]\n" " face.material_index = mat_nr\n" " face.smooth = True\n" "\n" " return face, ret_mesh\n" "\n" "def expand_lightmap_triangle(uva, uvb, uvc):\n" " result = ([uva[0],uva[1]], [uvb[0],uvb[1]], [uvc[0],uvc[1]])\n" " if uva == uvb:\n" " result[1][0] += 0.005\n" " if uva == uvc:\n" " result[2][1] -= 0.005\n" " return result\n" "\n"; /* Link master shader library */ os.format("# Master shader library\n" "with bpy.data.libraries.load('%s', link=True, relative=True) as (data_from, data_to):\n" " data_to.node_groups = data_from.node_groups\n" "\n", masterShaderPath.getAbsolutePathUTF8().c_str()); } void FinishBlenderMesh(HECL::BlenderConnection::PyOutStream& os, unsigned matSetCount, int meshIdx) { if (meshIdx < 0) os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name)\n" "obj = bpy.data.objects.new(mesh.name, mesh)\n" "obj.show_transparent = True\n" "bpy.context.scene.objects.link(obj)\n" "mesh.hecl_material_count = %u\n", matSetCount); else os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n" "obj = bpy.data.objects.new(mesh.name, mesh)\n" "obj.show_transparent = True\n" "bpy.context.scene.objects.link(obj)\n" "mesh.hecl_material_count = %u\n", meshIdx, matSetCount); os << "mesh.use_auto_smooth = True\n" "\n" "for material in materials:\n" " mesh.materials.append(material)\n" "\n" "# Merge OD meshes\n" "for od_entry in od_list:\n" " vert_dict = {}\n" "\n" " for vert in od_entry['bm'].verts:\n" " if len(vert.link_faces):\n" " copy_vert = bm.verts.new(vert.co, vert)\n" " vert_dict[vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] = copy_vert\n" " copy_vert[orig_pidx_lay] = vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]\n" "\n" " for face in od_entry['bm'].faces:\n" " merge_verts = [vert_dict[fv[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] for fv in face.verts]\n" " if bm.faces.get(merge_verts) is not None:\n" " continue\n" " merge_face = bm.faces.new(merge_verts)\n" " for i in range(len(face.loops)):\n" " old = face.loops[i]\n" " new = merge_face.loops[i]\n" " for j in range(len(od_entry['bm'].loops.layers.uv)):\n" " new[bm.loops.layers.uv[j]] = old[od_entry['bm'].loops.layers.uv[j]]\n" " new[orig_nidx_lay] = old[od_entry['bm'].loops.layers.int['CMDLOriginalNormIdxs']]\n" " merge_face.smooth = True\n" " merge_face.material_index = face.material_index\n" "\n" " od_entry['bm'].free()\n" "\n" "bm.to_mesh(mesh)\n" "\n" "# Load split normal data\n" "split_normals = []\n" "for face in bm.faces:\n" " for loop in face.loops:\n" " split_normals.append(norm_list[loop[orig_nidx_lay]])\n" "mesh.normals_split_custom_set(split_normals)\n" "\n" "bm.free()\n" "\n" "# Remove redundant materials\n" "present_mats = set()\n" "for poly in mesh.polygons:\n" " present_mats.add(poly.material_index)\n" "for mat_idx in reversed(range(len(mesh.materials))):\n" " if mat_idx not in present_mats:\n" " mesh.materials.pop(index=mat_idx, update_data=True)\n" "\n" "mesh.update()\n" "\n"; } } }