metaforce/DataSpec/DNACommon/CMDL.cpp

163 lines
7.0 KiB
C++

#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"
" #norms = [norm_seq[i] for i in norm_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";
}
}
}