Initial MP1 MREA support

This commit is contained in:
Jack Andersen 2015-09-06 18:05:44 -10:00
parent 35a6ddab14
commit 2fef79ceaa
9 changed files with 630 additions and 366 deletions

152
DataSpec/DNACommon/CMDL.cpp Normal file
View File

@ -0,0 +1,152 @@
#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"
"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"
" face.normal_flip()\n"
" ret_mesh = od_entry['bm']\n"
"\n"
" elif face is not None: # Same material, probably double-sided\n"
" face = face.copy()\n"
" face.normal_flip()\n"
"\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"
"\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 + '_%3d')\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 << "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"
"\n";
}
}
}

View File

@ -58,6 +58,7 @@ struct VertexAttributes
GX::AttrType pnMtxIdx = GX::NONE;
unsigned texMtxIdxCount = 0;
GX::AttrType texMtxIdx[7] = {GX::NONE};
bool shortUVs;
};
template <class MaterialSet>
@ -109,6 +110,8 @@ void GetVertexAttributes(const MaterialSet& matSet,
++va.texMtxIdxCount;
if ((va.texMtxIdx[6] = vaFlags.tex6MatIdx()))
++va.texMtxIdxCount;
va.shortUVs = mat.getFlags().lightmapUVArray();
}
}
@ -304,141 +307,46 @@ public:
}
};
template <class PAKRouter, class MaterialSet, class RIGPAIR, atUint32 Version>
bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
Athena::io::IStreamReader& reader,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
const RIGPAIR& rp)
void InitGeomBlenderContext(HECL::BlenderConnection::PyOutStream& os,
const HECL::ProjectPath& masterShaderPath);
void FinishBlenderMesh(HECL::BlenderConnection::PyOutStream& os,
unsigned matSetCount, int meshIdx);
template <class PAKRouter, class MaterialSet, class RIGPAIR>
atUint32 ReadGeomSectionsToBlender(HECL::BlenderConnection::PyOutStream& os,
Athena::io::IStreamReader& reader,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
const RIGPAIR& rp,
bool shortNormals,
bool shortUVs,
std::vector<VertexAttributes>& vertAttribs,
int meshIdx,
atUint32 secCount,
atUint32 matSetCount,
const atUint32* secSizes)
{
Header head;
head.read(reader);
if (head.magic != 0xDEADBABE)
{
LogDNACommon.report(LogVisor::Error, "invalid CMDL magic");
return false;
}
if (head.version != Version)
{
LogDNACommon.report(LogVisor::Error, "invalid CMDL version");
return false;
}
/* Open Py Stream */
HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true);
os.format("import bpy\n"
"import bmesh\n"
"\n"
"bpy.context.scene.name = '%s'\n"
"bpy.context.scene.hecl_type = 'MESH'\n"
"bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
"\n"
"# 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"
"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"
" face.normal_flip()\n"
" ret_mesh = od_entry['bm']\n"
"\n"
" elif face is not None: # Same material, probably double-sided\n"
" face = face.copy()\n"
" face.normal_flip()\n"
"\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"
"\n"
"# Begin bmesh\n"
"bm = bmesh.new()\n"
"\n", pakRouter.getBestEntryName(entry).c_str());
os << "# Begin bmesh\n"
"bm = bmesh.new()\n"
"\n";
if (rp.first)
os << "dvert_lay = bm.verts.layers.deform.verify()\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", dataspec.getMasterShaderPath().getAbsolutePathUTF8().c_str());
MaterialSet::RegisterMaterialProps(os);
os << "# Materials\n"
"materials = []\n"
"\n"
"# Overdraw-tracking\n"
os << "# Overdraw-tracking\n"
"od_list = []\n"
"\n";
/* Pre-read pass to determine maximum used vert indices */
bool visitedDLOffsets = false;
std::vector<VertexAttributes> vertAttribs;
atUint32 lastDlSec = secCount;
atUint64 afterHeaderPos = reader.position();
DLReader::DLPrimVert maxIdxs;
for (size_t s=0 ; s<head.secCount ; ++s)
for (size_t s=0 ; s<lastDlSec ; ++s)
{
atUint64 secStart = reader.position();
if (s < head.matSetCount)
if (s < matSetCount)
{
if (!s)
{
@ -449,7 +357,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
}
else
{
switch (s-head.matSetCount)
switch (s-matSetCount)
{
case 0:
{
@ -474,11 +382,12 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
case 4:
{
/* Short UVs */
if (head.flags.shortUVs())
if (shortUVs)
break;
/* DL Offsets (here or next section) */
visitedDLOffsets = true;
lastDlSec = s + reader.readUint32Big() + 1;
break;
}
default:
@ -486,6 +395,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
if (!visitedDLOffsets)
{
visitedDLOffsets = true;
lastDlSec = s + reader.readUint32Big() + 1;
break;
}
@ -494,7 +404,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
sHead.read(reader);
/* Do max index pre-read */
atUint32 realDlSize = head.secSizes[s] - (reader.position() - secStart);
atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
dl.preReadMaxIdxs(maxIdxs);
@ -502,8 +412,8 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
}
}
if (s < head.secCount - 1)
reader.seek(secStart + head.secSizes[s], Athena::Begin);
if (s < secCount - 1)
reader.seek(secStart + secSizes[s], Athena::Begin);
}
reader.seek(afterHeaderPos, Athena::Begin);
@ -512,10 +422,10 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
unsigned createdUVLayers = 0;
unsigned surfIdx = 0;
for (size_t s=0 ; s<head.secCount ; ++s)
for (size_t s=0 ; s<lastDlSec ; ++s)
{
atUint64 secStart = reader.position();
if (s < head.matSetCount)
if (s < matSetCount)
{
MaterialSet matSet;
matSet.read(reader);
@ -525,7 +435,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
}
else
{
switch (s-head.matSetCount)
switch (s-matSetCount)
{
case 0:
{
@ -544,18 +454,20 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
{
/* Normals */
os << "norm_list = []\n";
if (head.flags.shortNormals())
if (shortNormals)
{
size_t normCount = head.secSizes[s] / 6;
size_t normCount = secSizes[s] / 6;
for (size_t i=0 ; i<normCount ; ++i)
{
os.format("norm_list.append((%f,%f,%f))\n",
reader.readInt16Big(), reader.readInt16Big(), reader.readInt16Big());
reader.readInt16Big() / 16834.0f,
reader.readInt16Big() / 16834.0f,
reader.readInt16Big() / 16834.0f);
}
}
else
{
size_t normCount = head.secSizes[s] / 12;
size_t normCount = secSizes[s] / 12;
for (size_t i=0 ; i<normCount ; ++i)
{
atVec3f norm = reader.readVec3fBig();
@ -574,7 +486,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
{
/* Float UVs */
os << "uv_list = []\n";
size_t uvCount = head.secSizes[s] / 8;
size_t uvCount = secSizes[s] / 8;
for (size_t i=0 ; i<uvCount ; ++i)
{
atVec2f uv = reader.readVec2fBig();
@ -587,13 +499,14 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
{
/* Short UVs */
os << "suv_list = []\n";
if (head.flags.shortUVs())
if (shortUVs)
{
size_t uvCount = head.secSizes[s] / 4;
size_t uvCount = secSizes[s] / 4;
for (size_t i=0 ; i<uvCount ; ++i)
{
os.format("suv_list.append((%f,%f))\n",
reader.readInt16Big(), reader.readInt16Big());
reader.readInt16Big() / 32768.0f,
reader.readInt16Big() / 32768.0f);
}
break;
}
@ -613,7 +526,9 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
/* GX Display List (surface) */
SurfaceHeader sHead;
sHead.read(reader);
unsigned matUVCount = vertAttribs[sHead.matIdx].uvCount;
VertexAttributes& curVA = vertAttribs[sHead.matIdx];
unsigned matUVCount = curVA.uvCount;
bool matShortUVs = curVA.shortUVs;
os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++);
if (matUVCount > createdUVLayers)
@ -623,7 +538,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
createdUVLayers = matUVCount;
}
atUint32 realDlSize = head.secSizes[s] - (reader.position() - secStart);
atUint32 realDlSize = secSizes[s] - (reader.position() - secStart);
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
while (dl)
@ -664,12 +579,22 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
{
os << "if last_face is not None:\n";
for (unsigned j=0 ; j<matUVCount ; ++j)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
{
if (j==0 && matShortUVs)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
else
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
}
}
}
else
@ -686,12 +611,22 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
{
os << "if last_face is not None:\n";
for (unsigned j=0 ; j<matUVCount ; ++j)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j],
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j]);
{
if (j==0 && matShortUVs)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j],
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j]);
else
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j],
primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j]);
}
}
}
flip ^= 1;
@ -721,12 +656,22 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
{
os << "if last_face is not None:\n";
for (unsigned j=0 ; j<matUVCount ; ++j)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
primVerts[0].pos, j, primVerts[0].uvs[j],
primVerts[1].pos, j, primVerts[1].uvs[j],
primVerts[2].pos, j, primVerts[2].uvs[j]);
{
if (j==0 && matShortUVs)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
primVerts[0].pos, j, primVerts[0].uvs[j],
primVerts[1].pos, j, primVerts[1].uvs[j],
primVerts[2].pos, j, primVerts[2].uvs[j]);
else
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
primVerts[0].pos, j, primVerts[0].uvs[j],
primVerts[1].pos, j, primVerts[1].uvs[j],
primVerts[2].pos, j, primVerts[2].uvs[j]);
}
}
/* Break if done */
@ -757,12 +702,22 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
{
os << "if last_face is not None:\n";
for (unsigned j=0 ; j<matUVCount ; ++j)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
firstPrimVert.pos, j, firstPrimVert.uvs[j],
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
{
if (j==0 && matShortUVs)
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = suv_list[%u]\n",
firstPrimVert.pos, j, firstPrimVert.uvs[j],
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
else
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n"
" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n",
firstPrimVert.pos, j, firstPrimVert.uvs[j],
primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
}
}
bool peek = (v >= vertCount - 3);
@ -778,63 +733,64 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
}
}
if (s < head.secCount - 1)
reader.seek(secStart + head.secSizes[s], Athena::Begin);
if (s < secCount - 1)
reader.seek(secStart + secSizes[s], Athena::Begin);
}
/* Finish Mesh */
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"
"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"
"\n", head.matSetCount);
FinishBlenderMesh(os, matSetCount, meshIdx);
if (rp.first)
rp.second->sendVertexGroupsToBlender(os);
return lastDlSec;
}
template <class PAKRouter, class MaterialSet, class RIGPAIR, atUint32 Version>
bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
Athena::io::IStreamReader& reader,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const SpecBase& dataspec,
const RIGPAIR& rp)
{
Header head;
head.read(reader);
if (head.magic != 0xDEADBABE)
{
LogDNACommon.report(LogVisor::Error, "invalid CMDL magic");
return false;
}
if (head.version != Version)
{
LogDNACommon.report(LogVisor::Error, "invalid CMDL version");
return false;
}
/* Open Py Stream and read sections */
HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true);
os.format("import bpy\n"
"import bmesh\n"
"\n"
"bpy.context.scene.name = '%s'\n"
"bpy.context.scene.hecl_type = 'MESH'\n"
"bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n",
pakRouter.getBestEntryName(entry).c_str());
InitGeomBlenderContext(os, dataspec.getMasterShaderPath());
MaterialSet::RegisterMaterialProps(os);
os << "# Materials\n"
"materials = []\n"
"\n";
std::vector<VertexAttributes> vertAttribs;
ReadGeomSectionsToBlender<PAKRouter, MaterialSet, RIGPAIR>
(os, reader, pakRouter, entry, dataspec, rp, head.flags.shortNormals(),
head.flags.shortUVs(), vertAttribs, -1,
head.secCount, head.matSetCount, head.secSizes.data());
return true;
}

View File

@ -5,6 +5,7 @@ add_library(DNACommon
${liblist}
PAK.hpp
GX.hpp
CMDL.cpp
STRG.hpp STRG.cpp
TXTR.hpp TXTR.cpp
ANCS.hpp

View File

@ -31,29 +31,30 @@ struct MaterialSet : BigDNA
{
DECL_DNA
Value<atUint32> flags;
inline bool konstValuesEnabled() const {return (flags & 0x8) != 0;}
inline void setKonstValuesEnabled(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;}
inline bool depthSorting() const {return (flags & 0x10) != 0;}
inline void setDepthSorting(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;}
inline bool punchthroughAlpha() const {return (flags & 0x20) != 0;}
inline void setPunchthroughAlpha(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;}
inline bool samusReflection() const {return (flags & 0x40) != 0;}
inline void setSamusReflection(bool enabled) {flags &= ~0x40; flags |= atUint32(enabled) << 6;}
inline bool depthWrite() const {return (flags & 0x80) != 0;}
inline void setDepthWrite(bool enabled) {flags &= ~0x80; flags |= atUint32(enabled) << 7;}
inline bool samusReflectionSurfaceEye() const {return (flags & 0x100) != 0;}
inline void setSamusReflectionSurfaceEye(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;}
inline bool shadowOccluderMesh() const {return (flags & 0x200) != 0;}
inline void setShadowOccluderMesh(bool enabled) {flags &= ~0x200; flags |= atUint32(enabled) << 9;}
inline bool samusReflectionIndirectTexture() const {return (flags & 0x400) != 0;}
inline void setSamusReflectionIndirectTexture(bool enabled) {flags &= ~0x400; flags |= atUint32(enabled) << 10;}
inline bool lightmap() const {return (flags & 0x800) != 0;}
inline void setLightmap(bool enabled) {flags &= ~0x800; flags |= atUint32(enabled) << 11;}
inline bool lightmapUVArray() const {return (flags & 0x2000) != 0;}
inline void setLightmapUVArray(bool enabled) {flags &= ~0x2000; flags |= atUint32(enabled) << 13;}
inline atUint16 textureSlots() const {return (flags >> 16) != 0;}
inline void setTextureSlots(atUint16 texslots) {flags &= ~0xffff0000; flags |= atUint32(texslots) << 16;}
bool konstValuesEnabled() const {return (flags & 0x8) != 0;}
void setKonstValuesEnabled(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;}
bool depthSorting() const {return (flags & 0x10) != 0;}
void setDepthSorting(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;}
bool punchthroughAlpha() const {return (flags & 0x20) != 0;}
void setPunchthroughAlpha(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;}
bool samusReflection() const {return (flags & 0x40) != 0;}
void setSamusReflection(bool enabled) {flags &= ~0x40; flags |= atUint32(enabled) << 6;}
bool depthWrite() const {return (flags & 0x80) != 0;}
void setDepthWrite(bool enabled) {flags &= ~0x80; flags |= atUint32(enabled) << 7;}
bool samusReflectionSurfaceEye() const {return (flags & 0x100) != 0;}
void setSamusReflectionSurfaceEye(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;}
bool shadowOccluderMesh() const {return (flags & 0x200) != 0;}
void setShadowOccluderMesh(bool enabled) {flags &= ~0x200; flags |= atUint32(enabled) << 9;}
bool samusReflectionIndirectTexture() const {return (flags & 0x400) != 0;}
void setSamusReflectionIndirectTexture(bool enabled) {flags &= ~0x400; flags |= atUint32(enabled) << 10;}
bool lightmap() const {return (flags & 0x800) != 0;}
void setLightmap(bool enabled) {flags &= ~0x800; flags |= atUint32(enabled) << 11;}
bool lightmapUVArray() const {return (flags & 0x2000) != 0;}
void setLightmapUVArray(bool enabled) {flags &= ~0x2000; flags |= atUint32(enabled) << 13;}
atUint16 textureSlots() const {return (flags >> 16) != 0;}
void setTextureSlots(atUint16 texslots) {flags &= ~0xffff0000; flags |= atUint32(texslots) << 16;}
} flags;
const Flags& getFlags() const {return flags;}
Value<atUint32> textureCount;
Vector<atUint32, DNA_COUNT(textureCount)> texureIdxs;
@ -61,46 +62,46 @@ struct MaterialSet : BigDNA
{
DECL_DNA
Value<atUint32> vaFlags;
inline GX::AttrType position() const {return GX::AttrType(vaFlags & 0x3);}
inline void setPosition(GX::AttrType val) {vaFlags &= ~0x3; vaFlags |= atUint32(val);}
inline GX::AttrType normal() const {return GX::AttrType(vaFlags >> 2 & 0x3);}
inline void setNormal(GX::AttrType val) {vaFlags &= ~0xC; vaFlags |= atUint32(val) << 2;}
inline GX::AttrType color0() const {return GX::AttrType(vaFlags >> 4 & 0x3);}
inline void setColor0(GX::AttrType val) {vaFlags &= ~0x30; vaFlags |= atUint32(val) << 4;}
inline GX::AttrType color1() const {return GX::AttrType(vaFlags >> 6 & 0x3);}
inline void setColor1(GX::AttrType val) {vaFlags &= ~0xC0; vaFlags |= atUint32(val) << 6;}
inline GX::AttrType tex0() const {return GX::AttrType(vaFlags >> 8 & 0x3);}
inline void setTex0(GX::AttrType val) {vaFlags &= ~0x300; vaFlags |= atUint32(val) << 8;}
inline GX::AttrType tex1() const {return GX::AttrType(vaFlags >> 10 & 0x3);}
inline void setTex1(GX::AttrType val) {vaFlags &= ~0xC00; vaFlags |= atUint32(val) << 10;}
inline GX::AttrType tex2() const {return GX::AttrType(vaFlags >> 12 & 0x3);}
inline void setTex2(GX::AttrType val) {vaFlags &= ~0x3000; vaFlags |= atUint32(val) << 12;}
inline GX::AttrType tex3() const {return GX::AttrType(vaFlags >> 14 & 0x3);}
inline void setTex3(GX::AttrType val) {vaFlags &= ~0xC000; vaFlags |= atUint32(val) << 14;}
inline GX::AttrType tex4() const {return GX::AttrType(vaFlags >> 16 & 0x3);}
inline void setTex4(GX::AttrType val) {vaFlags &= ~0x30000; vaFlags |= atUint32(val) << 16;}
inline GX::AttrType tex5() const {return GX::AttrType(vaFlags >> 18 & 0x3);}
inline void setTex5(GX::AttrType val) {vaFlags &= ~0xC0000; vaFlags |= atUint32(val) << 18;}
inline GX::AttrType tex6() const {return GX::AttrType(vaFlags >> 20 & 0x3);}
inline void setTex6(GX::AttrType val) {vaFlags &= ~0x300000; vaFlags |= atUint32(val) << 20;}
inline GX::AttrType pnMatIdx() const {return GX::AttrType(vaFlags >> 24 & 0x1);}
inline void setPnMatIdx(GX::AttrType val) {vaFlags &= ~0x1000000; vaFlags |= atUint32(val & 0x1) << 24;}
inline GX::AttrType tex0MatIdx() const {return GX::AttrType(vaFlags >> 25 & 0x1);}
inline void setTex0MatIdx(GX::AttrType val) {vaFlags &= ~0x2000000; vaFlags |= atUint32(val & 0x1) << 25;}
inline GX::AttrType tex1MatIdx() const {return GX::AttrType(vaFlags >> 26 & 0x1);}
inline void setTex1MatIdx(GX::AttrType val) {vaFlags &= ~0x4000000; vaFlags |= atUint32(val & 0x1) << 26;}
inline GX::AttrType tex2MatIdx() const {return GX::AttrType(vaFlags >> 27 & 0x1);}
inline void setTex2MatIdx(GX::AttrType val) {vaFlags &= ~0x8000000; vaFlags |= atUint32(val & 0x1) << 27;}
inline GX::AttrType tex3MatIdx() const {return GX::AttrType(vaFlags >> 28 & 0x1);}
inline void setTex3MatIdx(GX::AttrType val) {vaFlags &= ~0x10000000; vaFlags |= atUint32(val & 0x1) << 28;}
inline GX::AttrType tex4MatIdx() const {return GX::AttrType(vaFlags >> 29 & 0x1);}
inline void setTex4MatIdx(GX::AttrType val) {vaFlags &= ~0x20000000; vaFlags |= atUint32(val & 0x1) << 29;}
inline GX::AttrType tex5MatIdx() const {return GX::AttrType(vaFlags >> 30 & 0x1);}
inline void setTex5MatIdx(GX::AttrType val) {vaFlags &= ~0x40000000; vaFlags |= atUint32(val & 0x1) << 30;}
inline GX::AttrType tex6MatIdx() const {return GX::AttrType(vaFlags >> 31 & 0x1);}
inline void setTex6MatIdx(GX::AttrType val) {vaFlags &= ~0x80000000; vaFlags |= atUint32(val & 0x1) << 31;}
GX::AttrType position() const {return GX::AttrType(vaFlags & 0x3);}
void setPosition(GX::AttrType val) {vaFlags &= ~0x3; vaFlags |= atUint32(val);}
GX::AttrType normal() const {return GX::AttrType(vaFlags >> 2 & 0x3);}
void setNormal(GX::AttrType val) {vaFlags &= ~0xC; vaFlags |= atUint32(val) << 2;}
GX::AttrType color0() const {return GX::AttrType(vaFlags >> 4 & 0x3);}
void setColor0(GX::AttrType val) {vaFlags &= ~0x30; vaFlags |= atUint32(val) << 4;}
GX::AttrType color1() const {return GX::AttrType(vaFlags >> 6 & 0x3);}
void setColor1(GX::AttrType val) {vaFlags &= ~0xC0; vaFlags |= atUint32(val) << 6;}
GX::AttrType tex0() const {return GX::AttrType(vaFlags >> 8 & 0x3);}
void setTex0(GX::AttrType val) {vaFlags &= ~0x300; vaFlags |= atUint32(val) << 8;}
GX::AttrType tex1() const {return GX::AttrType(vaFlags >> 10 & 0x3);}
void setTex1(GX::AttrType val) {vaFlags &= ~0xC00; vaFlags |= atUint32(val) << 10;}
GX::AttrType tex2() const {return GX::AttrType(vaFlags >> 12 & 0x3);}
void setTex2(GX::AttrType val) {vaFlags &= ~0x3000; vaFlags |= atUint32(val) << 12;}
GX::AttrType tex3() const {return GX::AttrType(vaFlags >> 14 & 0x3);}
void setTex3(GX::AttrType val) {vaFlags &= ~0xC000; vaFlags |= atUint32(val) << 14;}
GX::AttrType tex4() const {return GX::AttrType(vaFlags >> 16 & 0x3);}
void setTex4(GX::AttrType val) {vaFlags &= ~0x30000; vaFlags |= atUint32(val) << 16;}
GX::AttrType tex5() const {return GX::AttrType(vaFlags >> 18 & 0x3);}
void setTex5(GX::AttrType val) {vaFlags &= ~0xC0000; vaFlags |= atUint32(val) << 18;}
GX::AttrType tex6() const {return GX::AttrType(vaFlags >> 20 & 0x3);}
void setTex6(GX::AttrType val) {vaFlags &= ~0x300000; vaFlags |= atUint32(val) << 20;}
GX::AttrType pnMatIdx() const {return GX::AttrType(vaFlags >> 24 & 0x1);}
void setPnMatIdx(GX::AttrType val) {vaFlags &= ~0x1000000; vaFlags |= atUint32(val & 0x1) << 24;}
GX::AttrType tex0MatIdx() const {return GX::AttrType(vaFlags >> 25 & 0x1);}
void setTex0MatIdx(GX::AttrType val) {vaFlags &= ~0x2000000; vaFlags |= atUint32(val & 0x1) << 25;}
GX::AttrType tex1MatIdx() const {return GX::AttrType(vaFlags >> 26 & 0x1);}
void setTex1MatIdx(GX::AttrType val) {vaFlags &= ~0x4000000; vaFlags |= atUint32(val & 0x1) << 26;}
GX::AttrType tex2MatIdx() const {return GX::AttrType(vaFlags >> 27 & 0x1);}
void setTex2MatIdx(GX::AttrType val) {vaFlags &= ~0x8000000; vaFlags |= atUint32(val & 0x1) << 27;}
GX::AttrType tex3MatIdx() const {return GX::AttrType(vaFlags >> 28 & 0x1);}
void setTex3MatIdx(GX::AttrType val) {vaFlags &= ~0x10000000; vaFlags |= atUint32(val & 0x1) << 28;}
GX::AttrType tex4MatIdx() const {return GX::AttrType(vaFlags >> 29 & 0x1);}
void setTex4MatIdx(GX::AttrType val) {vaFlags &= ~0x20000000; vaFlags |= atUint32(val & 0x1) << 29;}
GX::AttrType tex5MatIdx() const {return GX::AttrType(vaFlags >> 30 & 0x1);}
void setTex5MatIdx(GX::AttrType val) {vaFlags &= ~0x40000000; vaFlags |= atUint32(val & 0x1) << 30;}
GX::AttrType tex6MatIdx() const {return GX::AttrType(vaFlags >> 31 & 0x1);}
void setTex6MatIdx(GX::AttrType val) {vaFlags &= ~0x80000000; vaFlags |= atUint32(val & 0x1) << 31;}
} vaFlags;
inline const VAFlags& getVAFlags() const {return vaFlags;}
const VAFlags& getVAFlags() const {return vaFlags;}
Value<atUint32> groupIdx;
Vector<atUint32, DNA_COUNT(flags.konstValuesEnabled())> konstCount;
@ -127,18 +128,18 @@ struct MaterialSet : BigDNA
{
DECL_DNA
Value<atUint32> flags;
inline bool lighting() const {return (flags & 0x1) != 0;}
inline void setLighting(bool enabled) {flags &= ~0x1; flags |= atUint32(enabled);}
inline bool useAmbient() const {return (flags & 0x2) != 0;}
inline void setUseAmbient(bool enabled) {flags &= ~0x2; flags |= atUint32(enabled) << 1;}
inline bool useMaterial() const {return (flags & 0x4) != 0;}
inline void setUseMaterial(bool enabled) {flags &= ~0x4; flags |= atUint32(enabled) << 2;}
inline atUint8 lightmask() const {return atUint8(flags >> 3 & 0xff);}
inline void setLightmask(atUint8 mask) {flags &= ~0x7f8; flags |= atUint32(mask) << 3;}
inline atUint8 diffuseFn() const {return atUint8(flags >> 11 & 0x3);}
inline void setDiffuseFn(atUint8 fn) {flags &= ~0x1800; flags |= atUint32(fn) << 11;}
inline atUint8 attenuationFn() const {return atUint8(flags >> 13 & 0x3);}
inline void setAttenuationFn(atUint8 fn) {flags &= ~0x6000; flags |= atUint32(fn) << 13;}
bool lighting() const {return (flags & 0x1) != 0;}
void setLighting(bool enabled) {flags &= ~0x1; flags |= atUint32(enabled);}
bool useAmbient() const {return (flags & 0x2) != 0;}
void setUseAmbient(bool enabled) {flags &= ~0x2; flags |= atUint32(enabled) << 1;}
bool useMaterial() const {return (flags & 0x4) != 0;}
void setUseMaterial(bool enabled) {flags &= ~0x4; flags |= atUint32(enabled) << 2;}
atUint8 lightmask() const {return atUint8(flags >> 3 & 0xff);}
void setLightmask(atUint8 mask) {flags &= ~0x7f8; flags |= atUint32(mask) << 3;}
atUint8 diffuseFn() const {return atUint8(flags >> 11 & 0x3);}
void setDiffuseFn(atUint8 fn) {flags &= ~0x1800; flags |= atUint32(fn) << 11;}
atUint8 attenuationFn() const {return atUint8(flags >> 13 & 0x3);}
void setAttenuationFn(atUint8 fn) {flags &= ~0x6000; flags |= atUint32(fn) << 13;}
};
Vector<ColorChannel, DNA_COUNT(colorChannelCount)> colorChannels;
@ -155,48 +156,48 @@ struct MaterialSet : BigDNA
Value<atUint8> kcInput;
Value<atUint8> rascInput;
inline GX::TevColorArg colorInA() const {return GX::TevColorArg(ciFlags & 0xf);}
inline void setColorInA(GX::TevColorArg val) {ciFlags &= ~0x1f; ciFlags |= atUint32(val);}
inline GX::TevColorArg colorInB() const {return GX::TevColorArg(ciFlags >> 5 & 0xf);}
inline void setColorInB(GX::TevColorArg val) {ciFlags &= ~0x3e0; ciFlags |= atUint32(val) << 5;}
inline GX::TevColorArg colorInC() const {return GX::TevColorArg(ciFlags >> 10 & 0xf);}
inline void setColorInC(GX::TevColorArg val) {ciFlags &= ~0x7c00; ciFlags |= atUint32(val) << 10;}
inline GX::TevColorArg colorInD() const {return GX::TevColorArg(ciFlags >> 15 & 0xf);}
inline void setColorInD(GX::TevColorArg val) {ciFlags &= ~0xf8000; ciFlags |= atUint32(val) << 15;}
GX::TevColorArg colorInA() const {return GX::TevColorArg(ciFlags & 0xf);}
void setColorInA(GX::TevColorArg val) {ciFlags &= ~0x1f; ciFlags |= atUint32(val);}
GX::TevColorArg colorInB() const {return GX::TevColorArg(ciFlags >> 5 & 0xf);}
void setColorInB(GX::TevColorArg val) {ciFlags &= ~0x3e0; ciFlags |= atUint32(val) << 5;}
GX::TevColorArg colorInC() const {return GX::TevColorArg(ciFlags >> 10 & 0xf);}
void setColorInC(GX::TevColorArg val) {ciFlags &= ~0x7c00; ciFlags |= atUint32(val) << 10;}
GX::TevColorArg colorInD() const {return GX::TevColorArg(ciFlags >> 15 & 0xf);}
void setColorInD(GX::TevColorArg val) {ciFlags &= ~0xf8000; ciFlags |= atUint32(val) << 15;}
inline GX::TevAlphaArg alphaInA() const {return GX::TevAlphaArg(aiFlags & 0x7);}
inline void setAlphaInA(GX::TevAlphaArg val) {aiFlags &= ~0x1f; aiFlags |= atUint32(val);}
inline GX::TevAlphaArg alphaInB() const {return GX::TevAlphaArg(aiFlags >> 5 & 0x7);}
inline void setAlphaInB(GX::TevAlphaArg val) {aiFlags &= ~0x3e0; aiFlags |= atUint32(val) << 5;}
inline GX::TevAlphaArg alphaInC() const {return GX::TevAlphaArg(aiFlags >> 10 & 0x7);}
inline void setAlphaInC(GX::TevAlphaArg val) {aiFlags &= ~0x7c00; aiFlags |= atUint32(val) << 10;}
inline GX::TevAlphaArg alphaInD() const {return GX::TevAlphaArg(aiFlags >> 15 & 0x7);}
inline void setAlphaInD(GX::TevAlphaArg val) {aiFlags &= ~0xf8000; aiFlags |= atUint32(val) << 15;}
GX::TevAlphaArg alphaInA() const {return GX::TevAlphaArg(aiFlags & 0x7);}
void setAlphaInA(GX::TevAlphaArg val) {aiFlags &= ~0x1f; aiFlags |= atUint32(val);}
GX::TevAlphaArg alphaInB() const {return GX::TevAlphaArg(aiFlags >> 5 & 0x7);}
void setAlphaInB(GX::TevAlphaArg val) {aiFlags &= ~0x3e0; aiFlags |= atUint32(val) << 5;}
GX::TevAlphaArg alphaInC() const {return GX::TevAlphaArg(aiFlags >> 10 & 0x7);}
void setAlphaInC(GX::TevAlphaArg val) {aiFlags &= ~0x7c00; aiFlags |= atUint32(val) << 10;}
GX::TevAlphaArg alphaInD() const {return GX::TevAlphaArg(aiFlags >> 15 & 0x7);}
void setAlphaInD(GX::TevAlphaArg val) {aiFlags &= ~0xf8000; aiFlags |= atUint32(val) << 15;}
inline GX::TevOp colorOp() const {return GX::TevOp(ccFlags & 0xf);}
inline void setColorOp(GX::TevOp val) {ccFlags &= ~0x1; ccFlags |= atUint32(val);}
inline GX::TevBias colorOpBias() const {return GX::TevBias(ccFlags >> 4 & 0x3);}
inline void setColorOpBias(GX::TevBias val) {ccFlags &= ~0x30; ccFlags |= atUint32(val) << 4;}
inline GX::TevScale colorOpScale() const {return GX::TevScale(ccFlags >> 6 & 0x3);}
inline void setColorOpScale(GX::TevScale val) {ccFlags &= ~0xc0; ccFlags |= atUint32(val) << 6;}
inline bool colorOpClamp() const {return ccFlags >> 8 & 0x1;}
inline void setColorOpClamp(bool val) {ccFlags &= ~0x100; ccFlags |= atUint32(val) << 8;}
inline GX::TevRegID colorOpOutReg() const {return GX::TevRegID(ccFlags >> 9 & 0x3);}
inline void setColorOpOutReg(GX::TevRegID val) {ccFlags &= ~0x600; ccFlags |= atUint32(val) << 9;}
GX::TevOp colorOp() const {return GX::TevOp(ccFlags & 0xf);}
void setColorOp(GX::TevOp val) {ccFlags &= ~0x1; ccFlags |= atUint32(val);}
GX::TevBias colorOpBias() const {return GX::TevBias(ccFlags >> 4 & 0x3);}
void setColorOpBias(GX::TevBias val) {ccFlags &= ~0x30; ccFlags |= atUint32(val) << 4;}
GX::TevScale colorOpScale() const {return GX::TevScale(ccFlags >> 6 & 0x3);}
void setColorOpScale(GX::TevScale val) {ccFlags &= ~0xc0; ccFlags |= atUint32(val) << 6;}
bool colorOpClamp() const {return ccFlags >> 8 & 0x1;}
void setColorOpClamp(bool val) {ccFlags &= ~0x100; ccFlags |= atUint32(val) << 8;}
GX::TevRegID colorOpOutReg() const {return GX::TevRegID(ccFlags >> 9 & 0x3);}
void setColorOpOutReg(GX::TevRegID val) {ccFlags &= ~0x600; ccFlags |= atUint32(val) << 9;}
inline GX::TevOp alphaOp() const {return GX::TevOp(acFlags & 0xf);}
inline void setAlphaOp(GX::TevOp val) {acFlags &= ~0x1; acFlags |= atUint32(val);}
inline GX::TevBias alphaOpBias() const {return GX::TevBias(acFlags >> 4 & 0x3);}
inline void setAlphaOpBias(GX::TevBias val) {acFlags &= ~0x30; acFlags |= atUint32(val) << 4;}
inline GX::TevScale alphaOpScale() const {return GX::TevScale(acFlags >> 6 & 0x3);}
inline void setAlphaOpScale(GX::TevScale val) {acFlags &= ~0xc0; acFlags |= atUint32(val) << 6;}
inline bool alphaOpClamp() const {return acFlags >> 8 & 0x1;}
inline void setAlphaOpClamp(bool val) {acFlags &= ~0x100; acFlags |= atUint32(val) << 8;}
inline GX::TevRegID alphaOpOutReg() const {return GX::TevRegID(acFlags >> 9 & 0x3);}
inline void setAlphaOpOutReg(GX::TevRegID val) {acFlags &= ~0x600; acFlags |= atUint32(val) << 9;}
GX::TevOp alphaOp() const {return GX::TevOp(acFlags & 0xf);}
void setAlphaOp(GX::TevOp val) {acFlags &= ~0x1; acFlags |= atUint32(val);}
GX::TevBias alphaOpBias() const {return GX::TevBias(acFlags >> 4 & 0x3);}
void setAlphaOpBias(GX::TevBias val) {acFlags &= ~0x30; acFlags |= atUint32(val) << 4;}
GX::TevScale alphaOpScale() const {return GX::TevScale(acFlags >> 6 & 0x3);}
void setAlphaOpScale(GX::TevScale val) {acFlags &= ~0xc0; acFlags |= atUint32(val) << 6;}
bool alphaOpClamp() const {return acFlags >> 8 & 0x1;}
void setAlphaOpClamp(bool val) {acFlags &= ~0x100; acFlags |= atUint32(val) << 8;}
GX::TevRegID alphaOpOutReg() const {return GX::TevRegID(acFlags >> 9 & 0x3);}
void setAlphaOpOutReg(GX::TevRegID val) {acFlags &= ~0x600; acFlags |= atUint32(val) << 9;}
inline GX::TevKColorSel kColorIn() const {return GX::TevKColorSel(kcInput);}
inline GX::TevKAlphaSel kAlphaIn() const {return GX::TevKAlphaSel(kaInput);}
GX::TevKColorSel kColorIn() const {return GX::TevKColorSel(kcInput);}
GX::TevKAlphaSel kAlphaIn() const {return GX::TevKAlphaSel(kaInput);}
};
Vector<TEVStage, DNA_COUNT(tevStageCount)> tevStages;
struct TEVStageTexInfo : BigDNA
@ -214,16 +215,16 @@ struct MaterialSet : BigDNA
DECL_DNA
Value<atUint32> flags;
inline GX::TexGenType type() const {return GX::TexGenType(flags & 0xf);}
inline void setType(GX::TexGenType val) {flags &= ~0xf; flags |= atUint32(val);}
inline GX::TexGenSrc source() const {return GX::TexGenSrc(flags >> 4 & 0x1f);}
inline void setSource(GX::TexGenSrc val) {flags &= ~0x1f0; flags |= atUint32(val) << 4;}
inline GX::TexMtx mtx() const {return GX::TexMtx(flags >> 9 & 0x1f + 30);}
inline void setMtx(GX::TexMtx val) {flags &= ~0x3e00; flags |= (atUint32(val)-30) << 9;}
inline bool normalize() const {return flags >> 14 & 0x1;}
inline void setNormalize(bool val) {flags &= ~0x4000; flags |= atUint32(val) << 14;}
inline GX::PTTexMtx postMtx() const {return GX::PTTexMtx(flags >> 15 & 0x3f + 64);}
inline void setPostMtx(GX::PTTexMtx val) {flags &= ~0x1f8000; flags |= (atUint32(val)-64) << 15;}
GX::TexGenType type() const {return GX::TexGenType(flags & 0xf);}
void setType(GX::TexGenType val) {flags &= ~0xf; flags |= atUint32(val);}
GX::TexGenSrc source() const {return GX::TexGenSrc(flags >> 4 & 0x1f);}
void setSource(GX::TexGenSrc val) {flags &= ~0x1f0; flags |= atUint32(val) << 4;}
GX::TexMtx mtx() const {return GX::TexMtx(flags >> 9 & 0x1f + 30);}
void setMtx(GX::TexMtx val) {flags &= ~0x3e00; flags |= (atUint32(val)-30) << 9;}
bool normalize() const {return flags >> 14 & 0x1;}
void setNormalize(bool val) {flags &= ~0x4000; flags |= atUint32(val) << 14;}
GX::PTTexMtx postMtx() const {return GX::PTTexMtx(flags >> 15 & 0x3f + 64);}
void setPostMtx(GX::PTTexMtx val) {flags &= ~0x1f8000; flags |= (atUint32(val)-64) << 15;}
};
Vector<TexCoordGen, DNA_COUNT(tcgCount)> tcgs;
@ -302,11 +303,11 @@ struct MaterialSet : BigDNA
const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx);
inline void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
{
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx, dataspec);
}

View File

@ -7,6 +7,7 @@
#include "../DNACommon/TXTR.hpp"
#include "CMDL.hpp"
#include "ANCS.hpp"
#include "MREA.hpp"
namespace Retro
{
@ -217,6 +218,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
return {nullptr, CMDL::Extract, {_S(".blend")}, 1};
case SBIG('ANCS'):
return {nullptr, ANCS::Extract, {_S(".yaml"), _S(".blend")}, 2};
case SBIG('MREA'):
return {nullptr, MREA::Extract, {_S(".yaml"), _S(".blend")}, 3};
case SBIG('MLVL'):
return {MLVL::Extract, nullptr, {_S(".yaml")}};
}

View File

@ -2,17 +2,164 @@
#define __DNAMP1_MREA_HPP__
#include "../DNACommon/DNACommon.hpp"
#include "CMDLMaterials.hpp"
#include "CSKR.hpp"
namespace Retro
{
namespace DNAMP1
{
struct MREA : BigDNA
struct MREA
{
DECL_DNA
Value<atUint32> magic;
struct Header : BigDNA
{
DECL_DNA
Value<atUint32> magic;
Value<atUint32> version;
Value<atVec4f> localToWorldMtx[3];
Value<atUint32> meshCount;
Value<atUint32> secCount;
Value<atUint32> geomSecIdx;
Value<atUint32> sclySecIdx;
Value<atUint32> collisionSecIdx;
Value<atUint32> unkSecIdx;
Value<atUint32> lightSecIdx;
Value<atUint32> visiSecIdx;
Value<atUint32> pathSecIdx;
Value<atUint32> arotSecIdx;
Vector<atUint32, DNA_COUNT(secCount)> secSizes;
};
struct MeshHeader : BigDNA
{
DECL_DNA
struct VisorFlags : BigDNA
{
DECL_DNA
Value<atUint32> flags;
enum ThermalLevel
{
ThermalCool,
ThermalHot,
ThermalWarm
};
static const char* GetThermalLevelStr(ThermalLevel t)
{
switch (t)
{
case ThermalCool: return "COOL";
case ThermalHot: return "HOT";
case ThermalWarm: return "WARM";
default: break;
}
return nullptr;
}
bool disableEnviro() const {return flags >> 1 & 0x1;}
void setDisableEnviro(bool v) {flags &= ~0x2; flags |= v << 1;}
bool disableThermal() const {return flags >> 2 & 0x1;}
void setDisableThermal(bool v) {flags &= ~0x4; flags |= v << 2;}
bool disableXray() const {return flags >> 3 & 0x1;}
void setDisableXray(bool v) {flags &= ~0x8; flags |= v << 3;}
ThermalLevel thermalLevel() const {return ThermalLevel(flags >> 4 & 0x3);}
void setThermalLevel(ThermalLevel v) {flags &= ~0x30; flags |= v << 4;}
const char* thermalLevelStr() const {return GetThermalLevelStr(thermalLevel());}
} visorFlags;
Value<atVec4f> xfMtx[3];
Value<atVec3f> aabb[2];
};
static bool Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs,
const HECL::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
bool,
std::function<void(const HECL::SystemChar*)>)
{
using RigPair = std::pair<CSKR*, CINF*>;
RigPair dummy(nullptr, nullptr);
/* Do extract */
Header head;
head.read(rs);
rs.seekAlign32();
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getWithExtension(_S(".blend")).getAbsolutePath()))
return false;
/* Open Py Stream and read sections */
HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true);
os.format("import bpy\n"
"import bmesh\n"
"\n"
"bpy.context.scene.name = '%s'\n"
"bpy.context.scene.hecl_type = 'AREA'\n",
pakRouter.getBestEntryName(entry).c_str());
DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath());
MaterialSet::RegisterMaterialProps(os);
os << "# Clear Scene\n"
"for ob in bpy.data.objects:\n"
" bpy.context.scene.objects.unlink(ob)\n"
" bpy.data.objects.remove(ob)\n"
"bpy.types.Object.retro_disable_enviro_visor = bpy.props.BoolProperty(name='Retro: Disable in Combat/Scan Visor')\n"
"bpy.types.Object.retro_disable_thermal_visor = bpy.props.BoolProperty(name='Retro: Disable in Thermal Visor')\n"
"bpy.types.Object.retro_disable_xray_visor = bpy.props.BoolProperty(name='Retro: Disable in X-Ray Visor')\n"
"bpy.types.Object.retro_thermal_level = bpy.props.EnumProperty(items=[('COOL', 'Cool', 'Cool Temperature'),"
"('HOT', 'Hot', 'Hot Temperature'),"
"('WARM', 'Warm', 'Warm Temperature')],"
"name='Retro: Thermal Visor Level')\n"
"\n";
/* One shared material set for all meshes */
os << "# Materials\n"
"materials = []\n"
"\n";
MaterialSet matSet;
atUint64 secStart = rs.position();
matSet.read(rs);
matSet.readToBlender(os, pakRouter, entry, 0, dataSpec);
rs.seek(secStart + head.secSizes[0], Athena::Begin);
std::vector<DNACMDL::VertexAttributes> vertAttribs;
DNACMDL::GetVertexAttributes(matSet, vertAttribs);
/* Read meshes */
atUint32 curSec = 1;
for (int m=0 ; m<head.meshCount ; ++m)
{
MeshHeader mHeader;
secStart = rs.position();
mHeader.read(rs);
rs.seek(secStart + head.secSizes[curSec++], Athena::Begin);
curSec += DNACMDL::ReadGeomSectionsToBlender<PAKRouter<PAKBridge>, MaterialSet, RigPair>
(os, rs, pakRouter, entry, dataSpec, dummy, true,
true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]);
os.format("obj.retro_disable_enviro_visor = %s\n"
"obj.retro_disable_thermal_visor = %s\n"
"obj.retro_disable_xray_visor = %s\n"
"obj.retro_thermal_level = '%s'\n",
mHeader.visorFlags.disableEnviro() ? "True" : "False",
mHeader.visorFlags.disableThermal() ? "True" : "False",
mHeader.visorFlags.disableXray() ? "True" : "False",
mHeader.visorFlags.thermalLevelStr());
}
/* Center view */
os << "bpy.context.user_preferences.view.smooth_view = 0\n"
"for window in bpy.context.window_manager.windows:\n"
" screen = window.screen\n"
" for area in screen.areas:\n"
" if area.type == 'VIEW_3D':\n"
" for region in area.regions:\n"
" if region.type == 'WINDOW':\n"
" override = {'scene': bpy.context.scene, 'window': window, 'screen': screen, 'area': area, 'region': region}\n"
" bpy.ops.view3d.view_all(override)\n"
" break\n";
os.close();
return conn.saveBlend();
}
};
}

View File

@ -20,13 +20,15 @@ struct MaterialSet : BigDNA
struct Material : BigDNA
{
DECL_DNA
DNAMP1::MaterialSet::Material::Flags flags;
using Flags = DNAMP1::MaterialSet::Material::Flags;
Flags flags;
const Flags& getFlags() const {return flags;}
Value<atUint32> textureCount;
Vector<atUint32, DNA_COUNT(textureCount)> texureIdxs;
using VAFlags = DNAMP1::MaterialSet::Material::VAFlags;
DNAMP1::MaterialSet::Material::VAFlags vaFlags;
inline const VAFlags& getVAFlags() const {return vaFlags;}
const VAFlags& getVAFlags() const {return vaFlags;}
Value<atUint32> unk0; /* MP2 only */
Value<atUint32> unk1; /* MP2 only */
Value<atUint32> groupIdx;
@ -55,7 +57,7 @@ struct MaterialSet : BigDNA
};
Vector<Material, DNA_COUNT(head.materialCount)> materials;
static inline void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out)
static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out)
{
DNAMP1::MaterialSet::RegisterMaterialProps(out);
}
@ -63,11 +65,11 @@ struct MaterialSet : BigDNA
const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx);
inline void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
{
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx, dataspec);
}

View File

@ -28,14 +28,15 @@ struct MaterialSet : BigDNA
{
DECL_DNA
Value<atUint32> flags;
inline bool alphaBlending() const {return (flags & 0x8) != 0;}
inline void setAlphaBlending(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;}
inline bool punchthroughAlpha() const {return (flags & 0x10) != 0;}
inline void setPunchthroughAlpha(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;}
inline bool additiveBlending() const {return (flags & 0x20) != 0;}
inline void setAdditiveBlending(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;}
inline bool shadowOccluderMesh() const {return (flags & 0x100) != 0;}
inline void setShadowOccluderMesh(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;}
bool alphaBlending() const {return (flags & 0x8) != 0;}
void setAlphaBlending(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;}
bool punchthroughAlpha() const {return (flags & 0x10) != 0;}
void setPunchthroughAlpha(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;}
bool additiveBlending() const {return (flags & 0x20) != 0;}
void setAdditiveBlending(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;}
bool shadowOccluderMesh() const {return (flags & 0x100) != 0;}
void setShadowOccluderMesh(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;}
bool lightmapUVArray() const {return false;} /* For polymorphic compatibility with MP1/2 */
} flags;
Value<atUint32> groupIdx;
Value<atUint32> unk1;
@ -44,7 +45,8 @@ struct MaterialSet : BigDNA
Value<atUint32> unk3;
Value<atUint32> unk4;
} header;
inline const VAFlags& getVAFlags() const {return header.vaFlags;}
const Header::Flags& getFlags() const {return header.flags;}
const VAFlags& getVAFlags() const {return header.vaFlags;}
struct ISection : BigDNA
{
@ -180,7 +182,7 @@ struct MaterialSet : BigDNA
};
Vector<Material, DNA_COUNT(materialCount)> materials;
static inline void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out)
static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out)
{
DNAMP1::MaterialSet::RegisterMaterialProps(out);
}
@ -188,11 +190,11 @@ struct MaterialSet : BigDNA
const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx);
inline void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const PAKRouter<PAKBridge>::EntryType& entry,
unsigned setIdx,
const SpecBase& dataspec)
{
DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, setIdx, dataspec);
}

2
hecl

@ -1 +1 @@
Subproject commit d4db7e3dbe400bd900af32b05cdb726e4fc4f8f9
Subproject commit 1e643175a85cea0d72c0023384e522d3cd4bb472