2015-09-07 04:05:44 +00:00
|
|
|
#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"
|
|
|
|
"# Property to convey original vert indices in overdraw meshes\n"
|
|
|
|
"class CMDLOriginalIndex(bpy.types.PropertyGroup):\n"
|
|
|
|
" index = bpy.props.IntProperty(name='Original Vertex Index')\n"
|
|
|
|
"bpy.utils.register_class(CMDLOriginalIndex)\n"
|
|
|
|
"bpy.types.Mesh.cmdl_orig_verts = bpy.props.CollectionProperty(type=CMDLOriginalIndex)\n"
|
|
|
|
"\n"
|
|
|
|
"def loop_from_facevert(face, vert_idx):\n"
|
|
|
|
" for loop in face.loops:\n"
|
|
|
|
" if loop.vert.index == vert_idx:\n"
|
|
|
|
" return loop\n"
|
|
|
|
"\n"
|
2015-09-21 01:23:20 +00:00
|
|
|
"def eq_normals(n1, n2):\n"
|
|
|
|
" if n1[0] == n2[0] and n1[1] == n2[1] and n1[2] == n2[2]:\n"
|
|
|
|
" return True\n"
|
|
|
|
" return False\n"
|
|
|
|
"\n"
|
2015-09-07 04:05:44 +00:00
|
|
|
"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"
|
2015-09-21 01:23:20 +00:00
|
|
|
" for i in range(3):\n"
|
|
|
|
" if not eq_normals(verts[i].normal, norms[i]):\n"
|
|
|
|
" verts[i] = bm.verts.new(verts[i].co, verts[i])\n"
|
|
|
|
" vert_seq.ensure_lookup_table()\n"
|
|
|
|
"\n"
|
2015-09-07 04:05:44 +00:00
|
|
|
" # 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"
|
2015-09-12 07:13:40 +00:00
|
|
|
" for i in range(3):\n"
|
|
|
|
" face.verts[i].co = verts[i].co\n"
|
2015-09-07 04:05:44 +00:00
|
|
|
" ret_mesh = od_entry['bm']\n"
|
|
|
|
"\n"
|
|
|
|
" elif face is not None: # Same material, probably double-sided\n"
|
|
|
|
" face = face.copy()\n"
|
2015-09-12 07:13:40 +00:00
|
|
|
" for i in range(3):\n"
|
|
|
|
" face.verts[i].co = verts[i].co\n"
|
2015-09-07 04:05:44 +00:00
|
|
|
"\n"
|
|
|
|
" else: \n"
|
|
|
|
" face = bm.faces.new(verts)\n"
|
|
|
|
"\n"
|
|
|
|
" # Apply normals\n"
|
|
|
|
" for i in range(3):\n"
|
|
|
|
" verts[i].normal = norms[i]\n"
|
|
|
|
"\n"
|
|
|
|
" for i in range(3):\n"
|
|
|
|
" face.verts[i].index = vert_indices[i]\n"
|
|
|
|
" face.material_index = mat_nr\n"
|
|
|
|
" face.smooth = True\n"
|
|
|
|
"\n"
|
|
|
|
" return face, ret_mesh\n"
|
2015-09-17 19:50:43 +00:00
|
|
|
"\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"
|
2015-09-07 04:05:44 +00:00
|
|
|
"\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
|
2015-09-09 01:37:00 +00:00
|
|
|
os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n"
|
2015-09-07 04:05:44 +00:00
|
|
|
"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 << "for material in materials:\n"
|
|
|
|
" mesh.materials.append(material)\n"
|
|
|
|
"\n"
|
|
|
|
"# Preserve original indices\n"
|
|
|
|
"for vert in bm.verts:\n"
|
|
|
|
" ov = mesh.cmdl_orig_verts.add()\n"
|
|
|
|
" ov.index = vert.index\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"
|
|
|
|
" vert_dict[vert.index] = bm.verts.new(vert.co, vert)\n"
|
|
|
|
" ov = mesh.cmdl_orig_verts.add()\n"
|
|
|
|
" ov.index = vert.index\n"
|
|
|
|
"\n"
|
|
|
|
" for face in od_entry['bm'].faces:\n"
|
|
|
|
" merge_verts = [vert_dict[fv.index] 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"
|
|
|
|
" merge_face.smooth = True\n"
|
|
|
|
" merge_face.material_index = face.material_index\n"
|
|
|
|
"\n"
|
|
|
|
" od_entry['bm'].free()\n"
|
|
|
|
"\n"
|
|
|
|
"# Remove loose vertices\n"
|
|
|
|
"#to_remove = []\n"
|
|
|
|
"#for vert in bm.verts:\n"
|
|
|
|
"# if not len(vert.link_faces):\n"
|
|
|
|
"# to_remove.append(vert)\n"
|
|
|
|
"#bmesh.ops.delete(bm, geom=to_remove, context=1)\n"
|
|
|
|
"\n"
|
|
|
|
"bm.to_mesh(mesh)\n"
|
|
|
|
"bm.free()\n"
|
2015-09-11 04:53:32 +00:00
|
|
|
"\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"
|
2015-09-07 04:05:44 +00:00
|
|
|
"\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|