Refactor of CMDL to effectively share across games

This commit is contained in:
Jack Andersen 2015-08-09 15:53:24 -10:00
parent ca49972974
commit 310aa10116
19 changed files with 705 additions and 238 deletions

View File

@ -1,40 +1,275 @@
#include <cstddef> #ifndef _DNACOMMON_CMDL_HPP_
#include "CMDL.hpp" #define _DNACOMMON_CMDL_HPP_
#include "DNAMP1.hpp"
#include "CMDLMaterials.hpp"
struct DLPrimVert #include "DNACommon.hpp"
{ #include "BlenderConnection.hpp"
atUint16 pos; #include "GX.hpp"
atUint16 norm;
atUint16 uvs[8];
};
namespace Retro namespace Retro
{ {
namespace DNAMP1 namespace DNACMDL
{ {
bool CMDL::ReadToBlender(HECL::BlenderConnection& conn, struct Header : BigDNA
Athena::io::IStreamReader& reader, {
PAKRouter<PAKBridge>& pakRouter, DECL_DNA
const PAK::Entry& entry, Value<atUint32> magic;
const HECL::ProjectPath& masterShader) Value<atUint32> version;
struct Flags : BigDNA
{
DECL_DNA
Value<atUint32> flags;
inline bool shortNormals() const {return (flags & 0x2) != 0;}
inline void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;}
inline bool shortUVs() const {return (flags & 0x4) != 0;}
inline void setShortUVs(bool val) {flags &= ~0x4; flags |= val << 2;}
} flags;
Value<atVec3f> aabbMin;
Value<atVec3f> aabbMax;
Value<atUint32> secCount;
Value<atUint32> matSetCount;
Vector<atUint32, DNA_COUNT(secCount)> secSizes;
Align<32> align;
};
struct SurfaceHeader : BigDNA
{
DECL_DNA
Value<atVec3f> centroid;
Value<atUint32> matIdx;
Value<atInt16> qDiv;
Value<atUint16> dlSize;
Seek<8, Athena::Current> seek;
Value<atUint32> aabbSz;
Value<atVec3f> reflectionNormal;
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
Align<32> align;
};
struct VertexAttributes
{
GX::AttrType pos = GX::NONE;
GX::AttrType norm = GX::NONE;
GX::AttrType color0 = GX::NONE;
GX::AttrType color1 = GX::NONE;
unsigned uvCount = 0;
GX::AttrType uvs[7] = {GX::NONE};
GX::AttrType pnMtxIdx = GX::NONE;
unsigned texMtxIdxCount = 0;
GX::AttrType texMtxIdx[7] = {GX::NONE};
};
template <class MaterialSet>
void GetVertexAttributes(const MaterialSet& matSet,
std::vector<VertexAttributes>& attributesOut)
{
attributesOut.clear();
attributesOut.reserve(matSet.materials.size());
for (const typename MaterialSet::Material& mat : matSet.materials)
{
const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags();
attributesOut.emplace_back();
VertexAttributes& metrics = attributesOut.back();
metrics.pos = vaFlags.position();
metrics.norm = vaFlags.normal();
metrics.color0 = vaFlags.color0();
metrics.color1 = vaFlags.color1();
if ((metrics.uvs[0] = vaFlags.tex0()))
++metrics.uvCount;
if ((metrics.uvs[1] = vaFlags.tex1()))
++metrics.uvCount;
if ((metrics.uvs[2] = vaFlags.tex2()))
++metrics.uvCount;
if ((metrics.uvs[3] = vaFlags.tex3()))
++metrics.uvCount;
if ((metrics.uvs[4] = vaFlags.tex4()))
++metrics.uvCount;
if ((metrics.uvs[5] = vaFlags.tex5()))
++metrics.uvCount;
if ((metrics.uvs[6] = vaFlags.tex6()))
++metrics.uvCount;
metrics.pnMtxIdx = vaFlags.pnMatIdx();
if ((metrics.texMtxIdx[0] = vaFlags.tex0MatIdx()))
++metrics.texMtxIdxCount;
if ((metrics.texMtxIdx[1] = vaFlags.tex1MatIdx()))
++metrics.texMtxIdxCount;
if ((metrics.texMtxIdx[2] = vaFlags.tex2MatIdx()))
++metrics.texMtxIdxCount;
if ((metrics.texMtxIdx[3] = vaFlags.tex3MatIdx()))
++metrics.texMtxIdxCount;
if ((metrics.texMtxIdx[4] = vaFlags.tex4MatIdx()))
++metrics.texMtxIdxCount;
if ((metrics.texMtxIdx[5] = vaFlags.tex5MatIdx()))
++metrics.texMtxIdxCount;
if ((metrics.texMtxIdx[6] = vaFlags.tex6MatIdx()))
++metrics.texMtxIdxCount;
}
}
template <class PAKRouter, class MaterialSet>
void ReadMaterialSetToBlender_1_2(HECL::BlenderConnection::PyOutStream& os,
const MaterialSet& matSet,
const PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
std::vector<VertexAttributes>& attributesOut,
unsigned setIdx)
{
/* Texmaps */
os << "texmap_list = []\n";
for (const UniqueID32& tex : matSet.head.textureIDs)
{
std::string texName = pakRouter.getBestEntryName(tex);
HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
HECL::SystemUTF8View resPathView(resPath);
os.format("if '%s' in bpy.data.textures:\n"
" image = bpy.data.images['%s']\n"
" texture = bpy.data.textures[image.name]\n"
"else:\n"
" image = bpy.data.images.load('''//%s''')\n"
" image.name = '%s'\n"
" texture = bpy.data.textures.new(image.name, 'IMAGE')\n"
" texture.image = image\n"
"texmap_list.append(texture)\n"
"\n", texName.c_str(), texName.c_str(),
resPathView.str().c_str(), texName.c_str());
}
if (!setIdx)
GetVertexAttributes(matSet, attributesOut);
unsigned m=0;
for (const typename MaterialSet::Material& mat : matSet.materials)
{
MaterialSet::ConstructMaterial(os, mat, setIdx, m++);
os << "materials.append(new_material)\n";
}
}
template <class PAKRouter, class MaterialSet>
void ReadMaterialSetToBlender_3(HECL::BlenderConnection::PyOutStream& os,
const MaterialSet& matSet,
const PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
std::vector<DNACMDL::VertexAttributes>& attributesOut,
unsigned setIdx)
{
if (!setIdx)
GetVertexAttributes(matSet, attributesOut);
unsigned m=0;
for (const typename MaterialSet::Material& mat : matSet.materials)
{
MaterialSet::ConstructMaterial(os, mat, setIdx, m++);
os << "materials.append(new_material)\n";
}
}
class DLReader
{
const VertexAttributes& m_va;
std::unique_ptr<atUint8[]> m_dl;
size_t m_dlSize;
atUint8* m_cur;
atUint16 readVal(GX::AttrType type)
{
atUint16 retval = 0;
switch (type)
{
case GX::DIRECT:
case GX::INDEX8:
retval = *m_cur;
++m_cur;
break;
case GX::INDEX16:
retval = HECL::SBig(*(atUint16*)m_cur);
m_cur += 2;
break;
default: break;
}
return retval;
}
public:
DLReader(const VertexAttributes& va, std::unique_ptr<atUint8[]>&& dl, size_t dlSize)
: m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize)
{
m_cur = m_dl.get();
}
operator bool()
{
return *m_cur && ((m_cur - m_dl.get()) < m_dlSize);
}
GX::Primitive readPrimitive()
{
return GX::Primitive(*m_cur++ & 0xf8);
}
atUint16 readVertCount()
{
return readVal(GX::INDEX16);
}
struct DLPrimVert
{
atUint16 pos;
atUint16 norm;
atUint16 color[2];
atUint16 uvs[7];
atUint8 pnMtxIdx;
atUint8 texMtxIdx[7];
};
DLPrimVert readVert(bool peek=false)
{
atUint8* bakCur = m_cur;
DLPrimVert retval;
retval.pnMtxIdx = readVal(m_va.pnMtxIdx);
retval.texMtxIdx[0] = readVal(m_va.texMtxIdx[0]);
retval.texMtxIdx[1] = readVal(m_va.texMtxIdx[1]);
retval.texMtxIdx[2] = readVal(m_va.texMtxIdx[2]);
retval.texMtxIdx[3] = readVal(m_va.texMtxIdx[3]);
retval.texMtxIdx[4] = readVal(m_va.texMtxIdx[4]);
retval.texMtxIdx[5] = readVal(m_va.texMtxIdx[5]);
retval.texMtxIdx[6] = readVal(m_va.texMtxIdx[6]);
retval.pos = readVal(m_va.pos);
retval.norm = readVal(m_va.norm);
retval.color[0] = readVal(m_va.color0);
retval.color[1] = readVal(m_va.color1);
retval.uvs[0] = readVal(m_va.uvs[0]);
retval.uvs[1] = readVal(m_va.uvs[1]);
retval.uvs[2] = readVal(m_va.uvs[2]);
retval.uvs[3] = readVal(m_va.uvs[3]);
retval.uvs[4] = readVal(m_va.uvs[4]);
retval.uvs[5] = readVal(m_va.uvs[5]);
retval.uvs[6] = readVal(m_va.uvs[6]);
if (peek)
m_cur = bakCur;
return retval;
}
};
template <class PAKRouter, class MaterialSet, atUint32 Version>
bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
Athena::io::IStreamReader& reader,
PAKRouter& pakRouter,
const typename PAKRouter::EntryType& entry,
const HECL::ProjectPath& masterShader)
{ {
reader.setEndian(Athena::BigEndian); reader.setEndian(Athena::BigEndian);
CMDL::Header head; Header head;
head.read(reader); head.read(reader);
if (head.magic != 0xDEADBABE) if (head.magic != 0xDEADBABE)
{ {
Log.report(LogVisor::Error, "invalid CMDL magic"); LogDNACommon.report(LogVisor::Error, "invalid CMDL magic");
return false; return false;
} }
if (head.version != 2) if (head.version != Version)
{ {
Log.report(LogVisor::Error, "invalid CMDL version for MP1"); LogDNACommon.report(LogVisor::Error, "invalid CMDL version");
return false; return false;
} }
@ -136,8 +371,7 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
"od_list = []\n" "od_list = []\n"
"\n"; "\n";
std::vector<std::vector<unsigned>> matUVCounts; std::vector<VertexAttributes> vertAttribs;
matUVCounts.reserve(head.matSetCount);
bool visitedDLOffsets = false; bool visitedDLOffsets = false;
unsigned createdUVLayers = 0; unsigned createdUVLayers = 0;
unsigned surfIdx = 0; unsigned surfIdx = 0;
@ -149,39 +383,7 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
{ {
MaterialSet matSet; MaterialSet matSet;
matSet.read(reader); matSet.read(reader);
matSet.readToBlender(os, pakRouter, entry, vertAttribs, s);
/* Texmaps */
os << "texmap_list = []\n";
for (const UniqueID32& tex : matSet.head.textureIDs)
{
std::string texName = pakRouter.getBestEntryName(tex);
HECL::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex);
HECL::SystemUTF8View resPathView(resPath);
os.format("if '%s' in bpy.data.textures:\n"
" image = bpy.data.images['%s']\n"
" texture = bpy.data.textures[image.name]\n"
"else:\n"
" image = bpy.data.images.load('''//%s''')\n"
" image.name = '%s'\n"
" texture = bpy.data.textures.new(image.name, 'IMAGE')\n"
" texture.image = image\n"
"texmap_list.append(texture)\n"
"\n", texName.c_str(), texName.c_str(),
resPathView.str().c_str(), texName.c_str());
}
matUVCounts.emplace_back();
std::vector<unsigned>& uvCounts = matUVCounts.back();
uvCounts.reserve(matSet.head.materialCount);
unsigned m=0;
for (const MaterialSet::Material& mat : matSet.materials)
{
uvCounts.emplace_back();
unsigned& uvCount = uvCounts.back();
MaterialSet::ConstructMaterial(os, mat, s, m++, uvCount);
os << "materials.append(new_material)\n";
}
} }
else else
{ {
@ -273,7 +475,7 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
atUint64 start = reader.position(); atUint64 start = reader.position();
SurfaceHeader sHead; SurfaceHeader sHead;
sHead.read(reader); sHead.read(reader);
unsigned matUVCount = matUVCounts[0][sHead.matIdx]; unsigned matUVCount = vertAttribs[sHead.matIdx].uvCount;
os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++); os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++);
if (matUVCount > createdUVLayers) if (matUVCount > createdUVLayers)
@ -284,55 +486,41 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
} }
atUint32 realDlSize = head.secSizes[s] - (reader.position() - secStart); atUint32 realDlSize = head.secSizes[s] - (reader.position() - secStart);
std::unique_ptr<atUint8[]> dlBuf = reader.readUBytes(realDlSize); DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
atUint8* origDl = dlBuf.get();
atUint8* dl = origDl;
while (*dl && (dl-origDl) < realDlSize) while (dl)
{ {
GX::Primitive ptype = GX::Primitive(*dl & 0xf8); GX::Primitive ptype = dl.readPrimitive();
if (ptype == 0) atUint16 vertCount = dl.readVertCount();
break;
atUint16 vert_count = HECL::SBig(*(atUint16*)(dl + 1));
os.format("# VAT Type: %u\n", *dl&7);
atUint16* dli = (atUint16*)(dl + 3);
/* First vert */ /* First vert */
DLPrimVert first_prim_vert; DLReader::DLPrimVert firstPrimVert = dl.readVert(true);
first_prim_vert.pos = HECL::SBig(dli[0]);
first_prim_vert.norm = HECL::SBig(dli[1]);
for (int uv=0 ; uv<matUVCount ; ++uv)
first_prim_vert.uvs[uv] = HECL::SBig(dli[2+uv]);
/* 3 Prim Verts to start */ /* 3 Prim Verts to start */
int c = 0; int c = 0;
DLPrimVert prim_verts[3]; DLReader::DLPrimVert primVerts[3] =
for (int pv=0 ; pv<3 ; ++pv)
{ {
prim_verts[pv].pos = HECL::SBig(*dli++); dl.readVert(),
prim_verts[pv].norm = HECL::SBig(*dli++); dl.readVert(),
for (int uv=0 ; uv<matUVCount ; ++uv) dl.readVert()
prim_verts[pv].uvs[uv] = HECL::SBig(*dli++); };
}
if (ptype == GX::TRIANGLESTRIP) if (ptype == GX::TRIANGLESTRIP)
{ {
atUint8 flip = 0; atUint8 flip = 0;
for (int v=0 ; v<vert_count-2 ; ++v) for (int v=0 ; v<vertCount-2 ; ++v)
{ {
if (flip) if (flip)
{ {
os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n", os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n",
prim_verts[c%3].pos, primVerts[c%3].pos,
prim_verts[(c+2)%3].pos, primVerts[(c+2)%3].pos,
prim_verts[(c+1)%3].pos, primVerts[(c+1)%3].pos,
prim_verts[c%3].norm, primVerts[c%3].norm,
prim_verts[(c+2)%3].norm, primVerts[(c+2)%3].norm,
prim_verts[(c+1)%3].norm, primVerts[(c+1)%3].norm,
sHead.matIdx); sHead.matIdx);
if (matUVCount) if (matUVCount)
{ {
@ -341,20 +529,20 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n" 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"
" 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",
prim_verts[c%3].pos, j, prim_verts[c%3].uvs[j], primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
prim_verts[(c+2)%3].pos, j, prim_verts[(c+2)%3].uvs[j], primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j],
prim_verts[(c+1)%3].pos, j, prim_verts[(c+1)%3].uvs[j]); primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
} }
} }
else else
{ {
os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n", os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n",
prim_verts[c%3].pos, primVerts[c%3].pos,
prim_verts[(c+1)%3].pos, primVerts[(c+1)%3].pos,
prim_verts[(c+2)%3].pos, primVerts[(c+2)%3].pos,
prim_verts[c%3].norm, primVerts[c%3].norm,
prim_verts[(c+1)%3].norm, primVerts[(c+1)%3].norm,
prim_verts[(c+2)%3].norm, primVerts[(c+2)%3].norm,
sHead.matIdx); sHead.matIdx);
if (matUVCount) if (matUVCount)
{ {
@ -363,36 +551,33 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n" 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"
" 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",
prim_verts[c%3].pos, j, prim_verts[c%3].uvs[j], primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
prim_verts[(c+1)%3].pos, j, prim_verts[(c+1)%3].uvs[j], primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j],
prim_verts[(c+2)%3].pos, j, prim_verts[(c+2)%3].uvs[j]); primVerts[(c+2)%3].pos, j, primVerts[(c+2)%3].uvs[j]);
} }
} }
flip ^= 1; flip ^= 1;
dl = (atUint8*)dli; bool peek = (v >= vertCount - 3);
/* Advance one prim vert */ /* Advance one prim vert */
prim_verts[c%3].pos = HECL::SBig(*dli++); primVerts[c%3] = dl.readVert(peek);
prim_verts[c%3].norm = HECL::SBig(*dli++);
for (int uv=0 ; uv<matUVCount ; ++uv)
prim_verts[c%3].uvs[uv] = HECL::SBig(*dli++);
++c; ++c;
} }
} }
else if (ptype == GX::TRIANGLES) else if (ptype == GX::TRIANGLES)
{ {
for (int v=0 ; v<vert_count ; v+=3) for (int v=0 ; v<vertCount ; v+=3)
{ {
os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n", os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n",
prim_verts[0].pos, primVerts[0].pos,
prim_verts[1].pos, primVerts[1].pos,
prim_verts[2].pos, primVerts[2].pos,
prim_verts[0].norm, primVerts[0].norm,
prim_verts[1].norm, primVerts[1].norm,
prim_verts[2].norm, primVerts[2].norm,
sHead.matIdx); sHead.matIdx);
if (matUVCount) if (matUVCount)
{ {
@ -401,39 +586,34 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n" 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"
" 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",
prim_verts[0].pos, j, prim_verts[0].uvs[j], primVerts[0].pos, j, primVerts[0].uvs[j],
prim_verts[1].pos, j, prim_verts[1].uvs[j], primVerts[1].pos, j, primVerts[1].uvs[j],
prim_verts[2].pos, j, prim_verts[2].uvs[j]); primVerts[2].pos, j, primVerts[2].uvs[j]);
} }
dl = (atUint8*)dli;
/* Break if done */ /* Break if done */
if (v+3 >= vert_count) if (v+3 >= vertCount)
break; break;
bool peek = (v >= vertCount - 3);
/* Advance 3 Prim Verts */ /* Advance 3 Prim Verts */
for (int pv=0 ; pv<3 ; ++pv) for (int pv=0 ; pv<3 ; ++pv)
{ primVerts[pv] = dl.readVert(peek);
prim_verts[pv].pos = HECL::SBig(*dli++);
prim_verts[pv].norm = HECL::SBig(*dli++);
for (int uv=0 ; uv<matUVCount ; ++uv)
prim_verts[pv].uvs[uv] = HECL::SBig(*dli++);
}
} }
} }
else if (ptype == GX::TRIANGLEFAN) else if (ptype == GX::TRIANGLEFAN)
{ {
++c; ++c;
for (int v=0 ; v<vert_count-2 ; ++v) for (int v=0 ; v<vertCount-2 ; ++v)
{ {
os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n", os.format("last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list)\n",
first_prim_vert.pos, firstPrimVert.pos,
prim_verts[c%3].pos, primVerts[c%3].pos,
prim_verts[(c+1)%3].pos, primVerts[(c+1)%3].pos,
first_prim_vert.norm, firstPrimVert.norm,
prim_verts[c%3].norm, primVerts[c%3].norm,
prim_verts[(c+1)%3].norm, primVerts[(c+1)%3].norm,
sHead.matIdx); sHead.matIdx);
if (matUVCount) if (matUVCount)
{ {
@ -442,18 +622,15 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
os.format(" loop_from_facevert(last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = uv_list[%u]\n" 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"
" 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",
first_prim_vert.pos, j, first_prim_vert.uvs[j], firstPrimVert.pos, j, firstPrimVert.uvs[j],
prim_verts[c%3].pos, j, prim_verts[c%3].uvs[j], primVerts[c%3].pos, j, primVerts[c%3].uvs[j],
prim_verts[(c+1)%3].pos, j, prim_verts[(c+1)%3].uvs[j]); primVerts[(c+1)%3].pos, j, primVerts[(c+1)%3].uvs[j]);
} }
dl = (atUint8*)dli; bool peek = (v >= vertCount - 3);
/* Advance one prim vert */ /* Advance one prim vert */
prim_verts[(c+2)%3].pos = HECL::SBig(*dli++); primVerts[(c+2)%3] = dl.readVert(peek);
prim_verts[(c+2)%3].norm = HECL::SBig(*dli++);
for (int uv=0 ; uv<matUVCount ; ++uv)
prim_verts[(c+2)%3].uvs[uv] = HECL::SBig(*dli++);
++c; ++c;
} }
} }
@ -522,3 +699,5 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
} }
} }
#endif // _DNACOMMON_CMDL_HPP_

View File

@ -1,5 +1,8 @@
make_dnalist(liblist
CMDL)
add_library(DNACommon add_library(DNACommon
DNACommon.hpp DNACommon.cpp DNACommon.hpp DNACommon.cpp
${liblist}
GX.hpp GX.hpp
STRG.hpp STRG.cpp STRG.hpp STRG.cpp
TXTR.hpp TXTR.cpp) TXTR.hpp TXTR.cpp)

View File

@ -262,17 +262,22 @@ struct ResExtractor
template <class BRIDGETYPE> template <class BRIDGETYPE>
class PAKRouter class PAKRouter
{ {
public:
using PAKType = typename BRIDGETYPE::PAKType;
using IDType = typename PAKType::IDType;
using EntryType = typename PAKType::Entry;
private:
const SpecBase& m_dataSpec; const SpecBase& m_dataSpec;
const HECL::ProjectPath& m_gameWorking; const HECL::ProjectPath& m_gameWorking;
const HECL::ProjectPath& m_gameCooked; const HECL::ProjectPath& m_gameCooked;
HECL::ProjectPath m_sharedWorking; HECL::ProjectPath m_sharedWorking;
HECL::ProjectPath m_sharedCooked; HECL::ProjectPath m_sharedCooked;
const typename BRIDGETYPE::PAKType* m_pak = nullptr; const PAKType* m_pak = nullptr;
const NOD::DiscBase::IPartition::Node* m_node = nullptr; const NOD::DiscBase::IPartition::Node* m_node = nullptr;
HECL::ProjectPath m_pakWorking; HECL::ProjectPath m_pakWorking;
HECL::ProjectPath m_pakCooked; HECL::ProjectPath m_pakCooked;
std::unordered_map<typename BRIDGETYPE::PAKType::IDType, typename BRIDGETYPE::PAKType::Entry*> m_uniqueEntries; std::unordered_map<typename PAKType::IDType, typename PAKType::Entry*> m_uniqueEntries;
std::unordered_map<typename BRIDGETYPE::PAKType::IDType, typename BRIDGETYPE::PAKType::Entry*> m_sharedEntries; std::unordered_map<IDType, EntryType*> m_sharedEntries;
public: public:
PAKRouter(const SpecBase& dataSpec, const HECL::ProjectPath& working, const HECL::ProjectPath& cooked) PAKRouter(const SpecBase& dataSpec, const HECL::ProjectPath& working, const HECL::ProjectPath& cooked)
: m_dataSpec(dataSpec), : m_dataSpec(dataSpec),

View File

@ -2,8 +2,8 @@
#define _DNAMP1_CMDL_HPP_ #define _DNAMP1_CMDL_HPP_
#include "../DNACommon/DNACommon.hpp" #include "../DNACommon/DNACommon.hpp"
#include "../DNACommon/CMDL.hpp"
#include "CMDLMaterials.hpp" #include "CMDLMaterials.hpp"
#include "BlenderConnection.hpp"
#include "DNAMP1.hpp" #include "DNAMP1.hpp"
namespace Retro namespace Retro
@ -13,48 +13,6 @@ namespace DNAMP1
struct CMDL struct CMDL
{ {
struct Header : BigDNA
{
DECL_DNA
Value<atUint32> magic;
Value<atUint32> version;
struct Flags : BigDNA
{
DECL_DNA
Value<atUint32> flags;
inline bool shortNormals() const {return (flags & 0x2) != 0;}
inline void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;}
inline bool shortUVs() const {return (flags & 0x4) != 0;}
inline void setShortUVs(bool val) {flags &= ~0x4; flags |= val << 2;}
} flags;
Value<atVec3f> aabbMin;
Value<atVec3f> aabbMax;
Value<atUint32> secCount;
Value<atUint32> matSetCount;
Vector<atUint32, DNA_COUNT(secCount)> secSizes;
Align<32> align;
};
struct SurfaceHeader : BigDNA
{
DECL_DNA
Value<atVec3f> centroid;
Value<atUint32> matIdx;
Value<atInt16> qDiv;
Value<atUint16> dlSize;
Seek<8, Athena::Current> seek;
Value<atUint32> aabbSz;
Value<atVec3f> reflectionNormal;
Seek<DNA_COUNT(aabbSz), Athena::Current> seek2;
Align<32> align;
};
static bool ReadToBlender(HECL::BlenderConnection& conn,
Athena::io::IStreamReader& reader,
PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry,
const HECL::ProjectPath& masterShader);
static bool Extract(const SpecBase& dataSpec, static bool Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs, PAKEntryReadStream& rs,
const HECL::ProjectPath& outPath, const HECL::ProjectPath& outPath,
@ -64,7 +22,8 @@ struct CMDL
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath())) if (!conn.createBlend(outPath.getAbsolutePath()))
return false; return false;
ReadToBlender(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath()); DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, 2>
(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
return conn.saveBlend(); return conn.saveBlend();
} }
}; };

View File

@ -560,8 +560,7 @@ template <class MAT>
void _ConstructMaterial(Stream& out, void _ConstructMaterial(Stream& out,
const MAT& material, const MAT& material,
unsigned groupIdx, unsigned groupIdx,
unsigned matIdx, unsigned matIdx)
unsigned& uvCountOut)
{ {
unsigned i; unsigned i;
@ -615,23 +614,6 @@ void _ConstructMaterial(Stream& out,
for (atUint32 idx : material.texureIdxs) for (atUint32 idx : material.texureIdxs)
out.format("tex_maps.append(texmap_list[%u])\n", idx); out.format("tex_maps.append(texmap_list[%u])\n", idx);
/* Vertex Attribute Flags */
uvCountOut = 0;
if (material.vaFlags.tex0())
++uvCountOut;
if (material.vaFlags.tex1())
++uvCountOut;
if (material.vaFlags.tex2())
++uvCountOut;
if (material.vaFlags.tex3())
++uvCountOut;
if (material.vaFlags.tex4())
++uvCountOut;
if (material.vaFlags.tex5())
++uvCountOut;
if (material.vaFlags.tex6())
++uvCountOut;
/* KColor entries */ /* KColor entries */
if (material.flags.konstValuesEnabled()) if (material.flags.konstValuesEnabled())
{ {
@ -707,7 +689,11 @@ void _ConstructMaterial(Stream& out,
} }
/* Connect final prev register */ /* Connect final prev register */
out.format("new_nodetree.links.new(%s, final_node.inputs['Color'])\n", c_regs[GX::TEVPREV]); if (!strcmp(c_regs[GX::TEVPREV], "ONE"))
out << "final_node.inputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n";
else
out.format("new_nodetree.links.new(%s, final_node.inputs['Color'])\n", c_regs[GX::TEVPREV]);
if (!strcmp(a_regs[GX::TEVPREV], "ONE")) if (!strcmp(a_regs[GX::TEVPREV], "ONE"))
out << "final_node.inputs['Alpha'].default_value = 1.0\n"; out << "final_node.inputs['Alpha'].default_value = 1.0\n";
else else
@ -722,9 +708,8 @@ void _ConstructMaterial(Stream& out,
void MaterialSet::ConstructMaterial(Stream& out, void MaterialSet::ConstructMaterial(Stream& out,
const MaterialSet::Material& material, const MaterialSet::Material& material,
unsigned groupIdx, unsigned groupIdx,
unsigned matIdx, unsigned matIdx)
unsigned& uvCountOut) {_ConstructMaterial(out, material, groupIdx, matIdx);}
{_ConstructMaterial(out, material, groupIdx, matIdx, uvCountOut);}
} }
} }
@ -737,9 +722,8 @@ namespace DNAMP2
void MaterialSet::ConstructMaterial(Stream& out, void MaterialSet::ConstructMaterial(Stream& out,
const MaterialSet::Material& material, const MaterialSet::Material& material,
unsigned groupIdx, unsigned groupIdx,
unsigned matIdx, unsigned matIdx)
unsigned& uvCountOut) {Retro::DNAMP1::_ConstructMaterial(out, material, groupIdx, matIdx);}
{Retro::DNAMP1::_ConstructMaterial(out, material, groupIdx, matIdx, uvCountOut);}
} }
} }

View File

@ -4,6 +4,8 @@
#include <BlenderConnection.hpp> #include <BlenderConnection.hpp>
#include "../DNACommon/DNACommon.hpp" #include "../DNACommon/DNACommon.hpp"
#include "../DNACommon/GX.hpp" #include "../DNACommon/GX.hpp"
#include "../DNACommon/CMDL.hpp"
#include "DNAMP1.hpp"
namespace Retro namespace Retro
{ {
@ -81,7 +83,24 @@ struct MaterialSet : BigDNA
inline void setTex5(GX::AttrType val) {vaFlags &= ~0xC0000; vaFlags |= atUint32(val) << 18;} inline void setTex5(GX::AttrType val) {vaFlags &= ~0xC0000; vaFlags |= atUint32(val) << 18;}
inline GX::AttrType tex6() const {return GX::AttrType(vaFlags >> 20 & 0x3);} inline GX::AttrType tex6() const {return GX::AttrType(vaFlags >> 20 & 0x3);}
inline void setTex6(GX::AttrType val) {vaFlags &= ~0x300000; vaFlags |= atUint32(val) << 20;} 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;}
} vaFlags; } vaFlags;
inline const VAFlags& getVAFlags() const {return vaFlags;}
Value<atUint32> groupIdx; Value<atUint32> groupIdx;
Vector<atUint32, DNA_COUNT(flags.konstValuesEnabled())> konstCount; Vector<atUint32, DNA_COUNT(flags.konstValuesEnabled())> konstCount;
@ -287,8 +306,16 @@ struct MaterialSet : BigDNA
static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out); static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out);
static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out, static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out,
const MaterialSet::Material& material, const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx, unsigned groupIdx, unsigned matIdx);
unsigned& uvCountOut);
inline void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const typename PAKRouter<PAKBridge>::EntryType& entry,
std::vector<DNACMDL::VertexAttributes>& attributesOut,
unsigned setIdx)
{
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, attributesOut, setIdx);
}
}; };
} }

View File

@ -3,7 +3,6 @@ make_dnalist(liblist
MLVL MLVL
ANCS ANCS
MAPA MAPA
CMDL
CMDLMaterials) CMDLMaterials)
add_library(DNAMP1 add_library(DNAMP1
DNAMP1.hpp DNAMP1.cpp DNAMP1.hpp DNAMP1.cpp
@ -11,5 +10,5 @@ add_library(DNAMP1
PAK.cpp PAK.cpp
STRG.hpp STRG.cpp STRG.hpp STRG.cpp
ANCS.cpp ANCS.cpp
CMDL.cpp CMDL.hpp
CMDLMaterials.cpp) CMDLMaterials.cpp)

34
DataSpec/DNAMP2/CMDL.hpp Normal file
View File

@ -0,0 +1,34 @@
#ifndef _DNAMP2_CMDL_HPP_
#define _DNAMP2_CMDL_HPP_
#include "../DNACommon/DNACommon.hpp"
#include "../DNACommon/CMDL.hpp"
#include "CMDLMaterials.hpp"
#include "DNAMP2.hpp"
namespace Retro
{
namespace DNAMP2
{
struct CMDL
{
static bool Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs,
const HECL::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry)
{
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, 4>
(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
return conn.saveBlend();
}
};
}
}
#endif // _DNAMP2_CMDL_HPP_

View File

@ -4,6 +4,7 @@
#include "../DNACommon/DNACommon.hpp" #include "../DNACommon/DNACommon.hpp"
#include "../DNACommon/GX.hpp" #include "../DNACommon/GX.hpp"
#include "../DNAMP1/CMDLMaterials.hpp" #include "../DNAMP1/CMDLMaterials.hpp"
#include "DNAMP2.hpp"
namespace Retro namespace Retro
{ {
@ -23,13 +24,15 @@ struct MaterialSet : BigDNA
Value<atUint32> textureCount; Value<atUint32> textureCount;
Vector<atUint32, DNA_COUNT(textureCount)> texureIdxs; Vector<atUint32, DNA_COUNT(textureCount)> texureIdxs;
using VAFlags = DNAMP1::MaterialSet::Material::VAFlags;
DNAMP1::MaterialSet::Material::VAFlags vaFlags; DNAMP1::MaterialSet::Material::VAFlags vaFlags;
inline const VAFlags& getVAFlags() const {return vaFlags;}
Value<atUint32> unk0; /* MP2 only */ Value<atUint32> unk0; /* MP2 only */
Value<atUint32> unk1; /* MP2 only */ Value<atUint32> unk1; /* MP2 only */
Value<atUint32> groupIdx; Value<atUint32> groupIdx;
Value<atUint32> konstCount; Vector<atUint32, DNA_COUNT(flags.konstValuesEnabled())> konstCount;
Vector<GX::Color, DNA_COUNT(konstCount)> konstColors; Vector<GX::Color, DNA_COUNT(flags.konstValuesEnabled() ? konstCount[0] : 0)> konstColors;
Value<atUint16> _blendDstFac; Value<atUint16> _blendDstFac;
using BlendFactor = DNAMP1::MaterialSet::Material::BlendFactor; using BlendFactor = DNAMP1::MaterialSet::Material::BlendFactor;
@ -56,10 +59,22 @@ struct MaterialSet : BigDNA
}; };
Vector<Material, DNA_COUNT(head.materialCount)> materials; Vector<Material, DNA_COUNT(head.materialCount)> materials;
static inline void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out)
{
DNAMP1::MaterialSet::RegisterMaterialProps(out);
}
static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out, static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out,
const MaterialSet::Material& material, const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx, unsigned groupIdx, unsigned matIdx);
unsigned& uvCountOut);
inline void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const typename PAKRouter<PAKBridge>::EntryType& entry,
std::vector<DNACMDL::VertexAttributes>& attributesOut,
unsigned setIdx)
{
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, attributesOut, setIdx);
}
}; };
} }

View File

@ -4,4 +4,5 @@ make_dnalist(liblist
add_library(DNAMP2 add_library(DNAMP2
DNAMP2.hpp DNAMP2.cpp DNAMP2.hpp DNAMP2.cpp
${liblist} ${liblist}
CMDL.hpp
STRG.hpp STRG.cpp) STRG.hpp STRG.cpp)

View File

@ -2,6 +2,7 @@
#include "DNAMP2.hpp" #include "DNAMP2.hpp"
#include "STRG.hpp" #include "STRG.hpp"
#include "MLVL.hpp" #include "MLVL.hpp"
#include "CMDL.hpp"
#include "../DNACommon/TXTR.hpp" #include "../DNACommon/TXTR.hpp"
namespace Retro namespace Retro
@ -186,6 +187,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& ent
return {STRG::Extract, nullptr, ".yaml"}; return {STRG::Extract, nullptr, ".yaml"};
case SBIG('TXTR'): case SBIG('TXTR'):
return {TXTR::Extract, nullptr, ".png"}; return {TXTR::Extract, nullptr, ".png"};
case SBIG('CMDL'):
return {nullptr, CMDL::Extract, ".blend", 1};
} }
return {}; return {};
} }

34
DataSpec/DNAMP3/CMDL.hpp Normal file
View File

@ -0,0 +1,34 @@
#ifndef _DNAMP3_CMDL_HPP_
#define _DNAMP3_CMDL_HPP_
#include "../DNACommon/DNACommon.hpp"
#include "../DNACommon/CMDL.hpp"
#include "CMDLMaterials.hpp"
#include "DNAMP3.hpp"
namespace Retro
{
namespace DNAMP3
{
struct CMDL
{
static bool Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs,
const HECL::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const PAK::Entry& entry)
{
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
if (!conn.createBlend(outPath.getAbsolutePath()))
return false;
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, 5>
(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
return conn.saveBlend();
}
};
}
}
#endif // _DNAMP3_CMDL_HPP_

View File

@ -0,0 +1,19 @@
#include "CMDLMaterials.hpp"
using Stream = HECL::BlenderConnection::PyOutStream;
namespace Retro
{
namespace DNAMP3
{
void MaterialSet::ConstructMaterial(Stream& out,
const MaterialSet::Material& material,
unsigned groupIdx,
unsigned matIdx)
{
}
}
}

View File

@ -0,0 +1,204 @@
#ifndef _DNAMP3_CMDL_MATERIALS_HPP_
#define _DNAMP3_CMDL_MATERIALS_HPP_
#include "../DNACommon/DNACommon.hpp"
#include "../DNACommon/GX.hpp"
#include "../DNAMP1/CMDLMaterials.hpp"
#include "DNAMP3.hpp"
namespace Retro
{
namespace DNAMP3
{
struct MaterialSet : BigDNA
{
DECL_DNA
Value<atUint32> materialCount;
struct Material : BigDNA
{
Delete expl;
using VAFlags = DNAMP1::MaterialSet::Material::VAFlags;
struct Header : BigDNA
{
DECL_DNA
Value<atUint32> size;
struct Flags : 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;}
} flags;
Value<atUint32> groupIdx;
Value<atUint32> unk1;
DNAMP1::MaterialSet::Material::VAFlags vaFlags;
Value<atUint32> unk2;
Value<atUint32> unk3;
Value<atUint32> unk4;
} header;
inline const VAFlags& getVAFlags() const {return header.vaFlags;}
struct ISection : BigDNA
{
Delete expl;
enum Type
{
PASS = SBIG('PASS'),
CLR = SBIG('CLR '),
INT = SBIG('INT ')
} m_type;
ISection(Type type) : m_type(type) {}
};
struct SectionPASS : ISection
{
SectionPASS() : ISection(ISection::PASS) {}
DECL_DNA
Value<atUint32> size;
enum Subtype
{
DIFF = SBIG('DIFF'),
RIML = SBIG('RIML'),
BLOL = SBIG('BLOL'),
BLOD = SBIG('BLOD'),
CLR = SBIG('CLR '),
TRAN = SBIG('TRAN'),
INCA = SBIG('INCA'),
RFLV = SBIG('RFLV'),
RFLD = SBIG('RFLD'),
LRLD = SBIG('LRLD'),
LURD = SBIG('LURD'),
BLOI = SBIG('BLOI'),
XRAY = SBIG('XRAY'),
TOON = SBIG('TOON')
};
FourCC subtype;
struct Flags : BigDNA
{
DECL_DNA
Value<atUint32> flags;
} flags;
UniqueID64 txtrId;
Value<atUint32> uvSrc;
Value<atUint32> uvAnimSize;
struct UVAnimation : BigDNA
{
DECL_DNA
Value<atUint16> unk1;
Value<atUint16> unk2;
DNAMP1::MaterialSet::Material::UVAnimation anim;
};
Vector<UVAnimation, DNA_COUNT(uvAnimSize != 0)> uvAnim;
};
struct SectionCLR : ISection
{
SectionCLR() : ISection(ISection::CLR) {}
DECL_DNA
enum Subtype
{
CLR = SBIG('CLR '),
DIFB = SBIG('DIFB')
};
FourCC subtype;
GX::Color color;
};
struct SectionINT : ISection
{
SectionINT() : ISection(ISection::INT) {}
DECL_DNA
enum Subtype
{
OPAC = SBIG('OPAC'),
BLOD = SBIG('BLOD'),
BLOI = SBIG('BLOI'),
BNIF = SBIG('BNIF'),
XRBR = SBIG('XRBR')
};
FourCC subtype;
Value<atUint32> value;
};
struct SectionFactory : BigDNA
{
Delete expl;
std::unique_ptr<ISection> section;
void read(Athena::io::IStreamReader& reader)
{
FourCC type;
type.read(reader);
switch (type)
{
case ISection::PASS:
section.reset(new struct SectionPASS);
section->read(reader);
break;
case ISection::CLR:
section.reset(new struct SectionCLR);
section->read(reader);
break;
case ISection::INT:
section.reset(new struct SectionINT);
section->read(reader);
break;
default:
section.reset(nullptr);
break;
}
}
void write(Athena::io::IStreamWriter& writer) const
{
if (!section)
return;
writer.writeUBytes((atUint8*)&section->m_type, 4);
section->write(writer);
}
};
std::vector<SectionFactory> sections;
void read(Athena::io::IStreamReader& reader)
{
header.read(reader);
sections.clear();
do {
sections.emplace_back();
sections.back().read(reader);
} while (sections.back().section);
sections.pop_back();
}
void write(Athena::io::IStreamWriter& writer) const
{
header.write(writer);
for (const SectionFactory& section : sections)
section.write(writer);
writer.writeUBytes((atUint8*)"END ", 4);
}
};
Vector<Material, DNA_COUNT(materialCount)> materials;
static inline void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out)
{
DNAMP1::MaterialSet::RegisterMaterialProps(out);
}
static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out,
const MaterialSet::Material& material,
unsigned groupIdx, unsigned matIdx);
inline void readToBlender(HECL::BlenderConnection::PyOutStream& os,
const PAKRouter<PAKBridge>& pakRouter,
const typename PAKRouter<PAKBridge>::EntryType& entry,
std::vector<DNACMDL::VertexAttributes>& attributesOut,
unsigned setIdx)
{
DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, attributesOut, setIdx);
}
};
}
}
#endif // _DNAMP3_CMDL_MATERIALS_HPP_

View File

@ -1,8 +1,11 @@
make_dnalist(liblist make_dnalist(liblist
PAK PAK
MLVL) MLVL
CMDLMaterials)
add_library(DNAMP3 add_library(DNAMP3
DNAMP3.hpp DNAMP3.cpp DNAMP3.hpp DNAMP3.cpp
${liblist} ${liblist}
PAK.cpp PAK.cpp
CMDL.hpp
CMDLMaterials.cpp
STRG.hpp STRG.cpp) STRG.hpp STRG.cpp)

View File

@ -4,6 +4,7 @@
#include "DNAMP3.hpp" #include "DNAMP3.hpp"
#include "STRG.hpp" #include "STRG.hpp"
#include "MLVL.hpp" #include "MLVL.hpp"
#include "CMDL.hpp"
#include "../DNACommon/TXTR.hpp" #include "../DNACommon/TXTR.hpp"
namespace Retro namespace Retro
@ -60,6 +61,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
return {STRG::Extract, nullptr, ".yaml"}; return {STRG::Extract, nullptr, ".yaml"};
case SBIG('TXTR'): case SBIG('TXTR'):
return {TXTR::Extract, nullptr, ".png"}; return {TXTR::Extract, nullptr, ".png"};
case SBIG('CMDL'):
return {nullptr, CMDL::Extract, ".blend", 1};
} }
return {}; return {};
} }

View File

@ -20,7 +20,6 @@ struct SpecMP1 : SpecBase
return false; return false;
} }
bool doMP1 = false;
std::vector<const NOD::DiscBase::IPartition::Node*> m_nonPaks; std::vector<const NOD::DiscBase::IPartition::Node*> m_nonPaks;
std::vector<DNAMP1::PAKBridge> m_paks; std::vector<DNAMP1::PAKBridge> m_paks;
std::map<std::string, DNAMP1::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks; std::map<std::string, DNAMP1::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks;
@ -122,7 +121,6 @@ struct SpecMP1 : SpecBase
const std::vector<HECL::SystemString>& args, const std::vector<HECL::SystemString>& args,
std::vector<ExtractReport>& reps) std::vector<ExtractReport>& reps)
{ {
doMP1 = true;
NOD::DiscGCN::IPartition* partition = disc.getDataPartition(); NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf(); std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19;
@ -152,6 +150,7 @@ struct SpecMP1 : SpecBase
std::vector<ExtractReport>& reps) std::vector<ExtractReport>& reps)
{ {
std::vector<HECL::SystemString> mp1args; std::vector<HECL::SystemString> mp1args;
bool doExtract = false;
if (args.size()) if (args.size())
{ {
/* Needs filter */ /* Needs filter */
@ -161,7 +160,7 @@ struct SpecMP1 : SpecBase
HECL::ToLower(lowerArg); HECL::ToLower(lowerArg);
if (!lowerArg.compare(0, 3, _S("mp1"))) if (!lowerArg.compare(0, 3, _S("mp1")))
{ {
doMP1 = true; doExtract = true;
size_t slashPos = arg.find(_S('/')); size_t slashPos = arg.find(_S('/'));
if (slashPos == HECL::SystemString::npos) if (slashPos == HECL::SystemString::npos)
slashPos = arg.find(_S('\\')); slashPos = arg.find(_S('\\'));
@ -171,10 +170,10 @@ struct SpecMP1 : SpecBase
} }
} }
else else
doMP1 = true; doExtract = true;
if (!doMP1) if (!doExtract)
return true; return false;
NOD::DiscGCN::IPartition* partition = disc.getDataPartition(); NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot(); NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot();
@ -208,9 +207,6 @@ struct SpecMP1 : SpecBase
bool extractFromDisc(NOD::DiscBase&, bool force, FExtractProgress progress) bool extractFromDisc(NOD::DiscBase&, bool force, FExtractProgress progress)
{ {
if (!doMP1)
return true;
progress(_S("Indexing PAKs"), 2, 0.0); progress(_S("Indexing PAKs"), 2, 0.0);
m_pakRouter.build(m_paks, [&progress](float factor) m_pakRouter.build(m_paks, [&progress](float factor)
{ {

View File

@ -18,7 +18,6 @@ struct SpecMP2 : SpecBase
return false; return false;
} }
bool doMP2 = false;
std::vector<const NOD::DiscBase::IPartition::Node*> m_nonPaks; std::vector<const NOD::DiscBase::IPartition::Node*> m_nonPaks;
std::vector<DNAMP2::PAKBridge> m_paks; std::vector<DNAMP2::PAKBridge> m_paks;
std::map<std::string, DNAMP2::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks; std::map<std::string, DNAMP2::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks;
@ -118,7 +117,6 @@ struct SpecMP2 : SpecBase
const std::vector<HECL::SystemString>& args, const std::vector<HECL::SystemString>& args,
std::vector<ExtractReport>& reps) std::vector<ExtractReport>& reps)
{ {
doMP2 = true;
NOD::DiscGCN::IPartition* partition = disc.getDataPartition(); NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf(); std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19;
@ -148,6 +146,7 @@ struct SpecMP2 : SpecBase
std::vector<ExtractReport>& reps) std::vector<ExtractReport>& reps)
{ {
std::vector<HECL::SystemString> mp2args; std::vector<HECL::SystemString> mp2args;
bool doExtract = false;
if (args.size()) if (args.size())
{ {
/* Needs filter */ /* Needs filter */
@ -157,7 +156,7 @@ struct SpecMP2 : SpecBase
HECL::ToLower(lowerArg); HECL::ToLower(lowerArg);
if (!lowerArg.compare(0, 3, _S("mp2"))) if (!lowerArg.compare(0, 3, _S("mp2")))
{ {
doMP2 = true; doExtract = true;
size_t slashPos = arg.find(_S('/')); size_t slashPos = arg.find(_S('/'));
if (slashPos == HECL::SystemString::npos) if (slashPos == HECL::SystemString::npos)
slashPos = arg.find(_S('\\')); slashPos = arg.find(_S('\\'));
@ -167,10 +166,10 @@ struct SpecMP2 : SpecBase
} }
} }
else else
doMP2 = true; doExtract = true;
if (!doMP2) if (!doExtract)
return true; return false;
NOD::DiscGCN::IPartition* partition = disc.getDataPartition(); NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot(); NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot();
@ -204,9 +203,6 @@ struct SpecMP2 : SpecBase
bool extractFromDisc(NOD::DiscBase&, bool force, FExtractProgress progress) bool extractFromDisc(NOD::DiscBase&, bool force, FExtractProgress progress)
{ {
if (!doMP2)
return true;
progress(_S("Indexing PAKs"), 2, 0.0); progress(_S("Indexing PAKs"), 2, 0.0);
m_pakRouter.build(m_paks, [&progress](float factor) m_pakRouter.build(m_paks, [&progress](float factor)
{ {

View File

@ -238,6 +238,9 @@ struct SpecMP3 : SpecBase
doMPTFE = true; doMPTFE = true;
} }
if (!doMP3 && !doMPTFE)
return false;
NOD::DiscGCN::IPartition* partition = disc.getDataPartition(); NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot(); NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot();