mirror of https://github.com/AxioDL/metaforce.git
Refactor of CMDL to effectively share across games
This commit is contained in:
parent
ca49972974
commit
310aa10116
|
@ -1,40 +1,275 @@
|
|||
#include <cstddef>
|
||||
#include "CMDL.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
#include "CMDLMaterials.hpp"
|
||||
#ifndef _DNACOMMON_CMDL_HPP_
|
||||
#define _DNACOMMON_CMDL_HPP_
|
||||
|
||||
struct DLPrimVert
|
||||
{
|
||||
atUint16 pos;
|
||||
atUint16 norm;
|
||||
atUint16 uvs[8];
|
||||
};
|
||||
#include "DNACommon.hpp"
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "GX.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
namespace DNAMP1
|
||||
namespace DNACMDL
|
||||
{
|
||||
|
||||
bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
|
||||
Athena::io::IStreamReader& reader,
|
||||
PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry,
|
||||
const HECL::ProjectPath& masterShader)
|
||||
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;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
CMDL::Header head;
|
||||
Header head;
|
||||
head.read(reader);
|
||||
|
||||
if (head.magic != 0xDEADBABE)
|
||||
{
|
||||
Log.report(LogVisor::Error, "invalid CMDL magic");
|
||||
LogDNACommon.report(LogVisor::Error, "invalid CMDL magic");
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -136,8 +371,7 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
|
|||
"od_list = []\n"
|
||||
"\n";
|
||||
|
||||
std::vector<std::vector<unsigned>> matUVCounts;
|
||||
matUVCounts.reserve(head.matSetCount);
|
||||
std::vector<VertexAttributes> vertAttribs;
|
||||
bool visitedDLOffsets = false;
|
||||
unsigned createdUVLayers = 0;
|
||||
unsigned surfIdx = 0;
|
||||
|
@ -149,39 +383,7 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
|
|||
{
|
||||
MaterialSet matSet;
|
||||
matSet.read(reader);
|
||||
|
||||
/* 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";
|
||||
}
|
||||
matSet.readToBlender(os, pakRouter, entry, vertAttribs, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -273,7 +475,7 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
|
|||
atUint64 start = reader.position();
|
||||
SurfaceHeader sHead;
|
||||
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++);
|
||||
if (matUVCount > createdUVLayers)
|
||||
|
@ -284,55 +486,41 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
|
|||
}
|
||||
|
||||
atUint32 realDlSize = head.secSizes[s] - (reader.position() - secStart);
|
||||
std::unique_ptr<atUint8[]> dlBuf = reader.readUBytes(realDlSize);
|
||||
atUint8* origDl = dlBuf.get();
|
||||
atUint8* dl = origDl;
|
||||
DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize);
|
||||
|
||||
while (*dl && (dl-origDl) < realDlSize)
|
||||
while (dl)
|
||||
{
|
||||
|
||||
GX::Primitive ptype = GX::Primitive(*dl & 0xf8);
|
||||
if (ptype == 0)
|
||||
break;
|
||||
|
||||
atUint16 vert_count = HECL::SBig(*(atUint16*)(dl + 1));
|
||||
os.format("# VAT Type: %u\n", *dl&7);
|
||||
|
||||
atUint16* dli = (atUint16*)(dl + 3);
|
||||
GX::Primitive ptype = dl.readPrimitive();
|
||||
atUint16 vertCount = dl.readVertCount();
|
||||
|
||||
/* First vert */
|
||||
DLPrimVert first_prim_vert;
|
||||
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]);
|
||||
DLReader::DLPrimVert firstPrimVert = dl.readVert(true);
|
||||
|
||||
/* 3 Prim Verts to start */
|
||||
int c = 0;
|
||||
DLPrimVert prim_verts[3];
|
||||
for (int pv=0 ; pv<3 ; ++pv)
|
||||
DLReader::DLPrimVert primVerts[3] =
|
||||
{
|
||||
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++);
|
||||
}
|
||||
dl.readVert(),
|
||||
dl.readVert(),
|
||||
dl.readVert()
|
||||
};
|
||||
|
||||
if (ptype == GX::TRIANGLESTRIP)
|
||||
{
|
||||
atUint8 flip = 0;
|
||||
for (int v=0 ; v<vert_count-2 ; ++v)
|
||||
for (int v=0 ; v<vertCount-2 ; ++v)
|
||||
{
|
||||
|
||||
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",
|
||||
prim_verts[c%3].pos,
|
||||
prim_verts[(c+2)%3].pos,
|
||||
prim_verts[(c+1)%3].pos,
|
||||
prim_verts[c%3].norm,
|
||||
prim_verts[(c+2)%3].norm,
|
||||
prim_verts[(c+1)%3].norm,
|
||||
primVerts[c%3].pos,
|
||||
primVerts[(c+2)%3].pos,
|
||||
primVerts[(c+1)%3].pos,
|
||||
primVerts[c%3].norm,
|
||||
primVerts[(c+2)%3].norm,
|
||||
primVerts[(c+1)%3].norm,
|
||||
sHead.matIdx);
|
||||
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"
|
||||
" 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],
|
||||
prim_verts[(c+2)%3].pos, j, prim_verts[(c+2)%3].uvs[j],
|
||||
prim_verts[(c+1)%3].pos, j, prim_verts[(c+1)%3].uvs[j]);
|
||||
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("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,
|
||||
prim_verts[(c+1)%3].pos,
|
||||
prim_verts[(c+2)%3].pos,
|
||||
prim_verts[c%3].norm,
|
||||
prim_verts[(c+1)%3].norm,
|
||||
prim_verts[(c+2)%3].norm,
|
||||
primVerts[c%3].pos,
|
||||
primVerts[(c+1)%3].pos,
|
||||
primVerts[(c+2)%3].pos,
|
||||
primVerts[c%3].norm,
|
||||
primVerts[(c+1)%3].norm,
|
||||
primVerts[(c+2)%3].norm,
|
||||
sHead.matIdx);
|
||||
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"
|
||||
" 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],
|
||||
prim_verts[(c+1)%3].pos, j, prim_verts[(c+1)%3].uvs[j],
|
||||
prim_verts[(c+2)%3].pos, j, prim_verts[(c+2)%3].uvs[j]);
|
||||
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;
|
||||
|
||||
dl = (atUint8*)dli;
|
||||
bool peek = (v >= vertCount - 3);
|
||||
|
||||
/* Advance one prim vert */
|
||||
prim_verts[c%3].pos = HECL::SBig(*dli++);
|
||||
prim_verts[c%3].norm = HECL::SBig(*dli++);
|
||||
for (int uv=0 ; uv<matUVCount ; ++uv)
|
||||
prim_verts[c%3].uvs[uv] = HECL::SBig(*dli++);
|
||||
primVerts[c%3] = dl.readVert(peek);
|
||||
++c;
|
||||
|
||||
}
|
||||
}
|
||||
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",
|
||||
prim_verts[0].pos,
|
||||
prim_verts[1].pos,
|
||||
prim_verts[2].pos,
|
||||
prim_verts[0].norm,
|
||||
prim_verts[1].norm,
|
||||
prim_verts[2].norm,
|
||||
primVerts[0].pos,
|
||||
primVerts[1].pos,
|
||||
primVerts[2].pos,
|
||||
primVerts[0].norm,
|
||||
primVerts[1].norm,
|
||||
primVerts[2].norm,
|
||||
sHead.matIdx);
|
||||
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"
|
||||
" 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],
|
||||
prim_verts[1].pos, j, prim_verts[1].uvs[j],
|
||||
prim_verts[2].pos, j, prim_verts[2].uvs[j]);
|
||||
primVerts[0].pos, j, primVerts[0].uvs[j],
|
||||
primVerts[1].pos, j, primVerts[1].uvs[j],
|
||||
primVerts[2].pos, j, primVerts[2].uvs[j]);
|
||||
}
|
||||
|
||||
dl = (atUint8*)dli;
|
||||
|
||||
/* Break if done */
|
||||
if (v+3 >= vert_count)
|
||||
if (v+3 >= vertCount)
|
||||
break;
|
||||
|
||||
bool peek = (v >= vertCount - 3);
|
||||
|
||||
/* Advance 3 Prim Verts */
|
||||
for (int pv=0 ; pv<3 ; ++pv)
|
||||
{
|
||||
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++);
|
||||
}
|
||||
primVerts[pv] = dl.readVert(peek);
|
||||
}
|
||||
}
|
||||
else if (ptype == GX::TRIANGLEFAN)
|
||||
{
|
||||
++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",
|
||||
first_prim_vert.pos,
|
||||
prim_verts[c%3].pos,
|
||||
prim_verts[(c+1)%3].pos,
|
||||
first_prim_vert.norm,
|
||||
prim_verts[c%3].norm,
|
||||
prim_verts[(c+1)%3].norm,
|
||||
firstPrimVert.pos,
|
||||
primVerts[c%3].pos,
|
||||
primVerts[(c+1)%3].pos,
|
||||
firstPrimVert.norm,
|
||||
primVerts[c%3].norm,
|
||||
primVerts[(c+1)%3].norm,
|
||||
sHead.matIdx);
|
||||
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"
|
||||
" 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],
|
||||
prim_verts[c%3].pos, j, prim_verts[c%3].uvs[j],
|
||||
prim_verts[(c+1)%3].pos, j, prim_verts[(c+1)%3].uvs[j]);
|
||||
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]);
|
||||
}
|
||||
|
||||
dl = (atUint8*)dli;
|
||||
bool peek = (v >= vertCount - 3);
|
||||
|
||||
/* Advance one prim vert */
|
||||
prim_verts[(c+2)%3].pos = HECL::SBig(*dli++);
|
||||
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++);
|
||||
primVerts[(c+2)%3] = dl.readVert(peek);
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
@ -522,3 +699,5 @@ bool CMDL::ReadToBlender(HECL::BlenderConnection& conn,
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _DNACOMMON_CMDL_HPP_
|
|
@ -1,5 +1,8 @@
|
|||
make_dnalist(liblist
|
||||
CMDL)
|
||||
add_library(DNACommon
|
||||
DNACommon.hpp DNACommon.cpp
|
||||
${liblist}
|
||||
GX.hpp
|
||||
STRG.hpp STRG.cpp
|
||||
TXTR.hpp TXTR.cpp)
|
||||
|
|
|
@ -262,17 +262,22 @@ struct ResExtractor
|
|||
template <class BRIDGETYPE>
|
||||
class PAKRouter
|
||||
{
|
||||
public:
|
||||
using PAKType = typename BRIDGETYPE::PAKType;
|
||||
using IDType = typename PAKType::IDType;
|
||||
using EntryType = typename PAKType::Entry;
|
||||
private:
|
||||
const SpecBase& m_dataSpec;
|
||||
const HECL::ProjectPath& m_gameWorking;
|
||||
const HECL::ProjectPath& m_gameCooked;
|
||||
HECL::ProjectPath m_sharedWorking;
|
||||
HECL::ProjectPath m_sharedCooked;
|
||||
const typename BRIDGETYPE::PAKType* m_pak = nullptr;
|
||||
const PAKType* m_pak = nullptr;
|
||||
const NOD::DiscBase::IPartition::Node* m_node = nullptr;
|
||||
HECL::ProjectPath m_pakWorking;
|
||||
HECL::ProjectPath m_pakCooked;
|
||||
std::unordered_map<typename BRIDGETYPE::PAKType::IDType, typename BRIDGETYPE::PAKType::Entry*> m_uniqueEntries;
|
||||
std::unordered_map<typename BRIDGETYPE::PAKType::IDType, typename BRIDGETYPE::PAKType::Entry*> m_sharedEntries;
|
||||
std::unordered_map<typename PAKType::IDType, typename PAKType::Entry*> m_uniqueEntries;
|
||||
std::unordered_map<IDType, EntryType*> m_sharedEntries;
|
||||
public:
|
||||
PAKRouter(const SpecBase& dataSpec, const HECL::ProjectPath& working, const HECL::ProjectPath& cooked)
|
||||
: m_dataSpec(dataSpec),
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#define _DNAMP1_CMDL_HPP_
|
||||
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
#include "../DNACommon/CMDL.hpp"
|
||||
#include "CMDLMaterials.hpp"
|
||||
#include "BlenderConnection.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
|
||||
namespace Retro
|
||||
|
@ -13,48 +13,6 @@ namespace DNAMP1
|
|||
|
||||
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,
|
||||
PAKEntryReadStream& rs,
|
||||
const HECL::ProjectPath& outPath,
|
||||
|
@ -64,7 +22,8 @@ struct CMDL
|
|||
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
|
||||
if (!conn.createBlend(outPath.getAbsolutePath()))
|
||||
return false;
|
||||
ReadToBlender(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, 2>
|
||||
(conn, rs, pakRouter, entry, dataSpec.getMasterShaderPath());
|
||||
return conn.saveBlend();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -560,8 +560,7 @@ template <class MAT>
|
|||
void _ConstructMaterial(Stream& out,
|
||||
const MAT& material,
|
||||
unsigned groupIdx,
|
||||
unsigned matIdx,
|
||||
unsigned& uvCountOut)
|
||||
unsigned matIdx)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
|
@ -615,23 +614,6 @@ void _ConstructMaterial(Stream& out,
|
|||
for (atUint32 idx : material.texureIdxs)
|
||||
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 */
|
||||
if (material.flags.konstValuesEnabled())
|
||||
{
|
||||
|
@ -707,7 +689,11 @@ void _ConstructMaterial(Stream& out,
|
|||
}
|
||||
|
||||
/* 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"))
|
||||
out << "final_node.inputs['Alpha'].default_value = 1.0\n";
|
||||
else
|
||||
|
@ -722,9 +708,8 @@ void _ConstructMaterial(Stream& out,
|
|||
void MaterialSet::ConstructMaterial(Stream& out,
|
||||
const MaterialSet::Material& material,
|
||||
unsigned groupIdx,
|
||||
unsigned matIdx,
|
||||
unsigned& uvCountOut)
|
||||
{_ConstructMaterial(out, material, groupIdx, matIdx, uvCountOut);}
|
||||
unsigned matIdx)
|
||||
{_ConstructMaterial(out, material, groupIdx, matIdx);}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -737,9 +722,8 @@ namespace DNAMP2
|
|||
void MaterialSet::ConstructMaterial(Stream& out,
|
||||
const MaterialSet::Material& material,
|
||||
unsigned groupIdx,
|
||||
unsigned matIdx,
|
||||
unsigned& uvCountOut)
|
||||
{Retro::DNAMP1::_ConstructMaterial(out, material, groupIdx, matIdx, uvCountOut);}
|
||||
unsigned matIdx)
|
||||
{Retro::DNAMP1::_ConstructMaterial(out, material, groupIdx, matIdx);}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <BlenderConnection.hpp>
|
||||
#include "../DNACommon/DNACommon.hpp"
|
||||
#include "../DNACommon/GX.hpp"
|
||||
#include "../DNACommon/CMDL.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -81,7 +83,24 @@ struct MaterialSet : BigDNA
|
|||
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;}
|
||||
} vaFlags;
|
||||
inline const VAFlags& getVAFlags() const {return vaFlags;}
|
||||
Value<atUint32> groupIdx;
|
||||
|
||||
Vector<atUint32, DNA_COUNT(flags.konstValuesEnabled())> konstCount;
|
||||
|
@ -287,8 +306,16 @@ struct MaterialSet : BigDNA
|
|||
static void RegisterMaterialProps(HECL::BlenderConnection::PyOutStream& out);
|
||||
static void ConstructMaterial(HECL::BlenderConnection::PyOutStream& out,
|
||||
const MaterialSet::Material& material,
|
||||
unsigned groupIdx, unsigned matIdx,
|
||||
unsigned& uvCountOut);
|
||||
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_1_2(os, *this, pakRouter, entry, attributesOut, setIdx);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ make_dnalist(liblist
|
|||
MLVL
|
||||
ANCS
|
||||
MAPA
|
||||
CMDL
|
||||
CMDLMaterials)
|
||||
add_library(DNAMP1
|
||||
DNAMP1.hpp DNAMP1.cpp
|
||||
|
@ -11,5 +10,5 @@ add_library(DNAMP1
|
|||
PAK.cpp
|
||||
STRG.hpp STRG.cpp
|
||||
ANCS.cpp
|
||||
CMDL.cpp
|
||||
CMDL.hpp
|
||||
CMDLMaterials.cpp)
|
||||
|
|
|
@ -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_
|
|
@ -4,6 +4,7 @@
|
|||
#include "../DNACommon/DNACommon.hpp"
|
||||
#include "../DNACommon/GX.hpp"
|
||||
#include "../DNAMP1/CMDLMaterials.hpp"
|
||||
#include "DNAMP2.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -23,13 +24,15 @@ struct MaterialSet : BigDNA
|
|||
|
||||
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;}
|
||||
Value<atUint32> unk0; /* MP2 only */
|
||||
Value<atUint32> unk1; /* MP2 only */
|
||||
Value<atUint32> groupIdx;
|
||||
|
||||
Value<atUint32> konstCount;
|
||||
Vector<GX::Color, DNA_COUNT(konstCount)> konstColors;
|
||||
Vector<atUint32, DNA_COUNT(flags.konstValuesEnabled())> konstCount;
|
||||
Vector<GX::Color, DNA_COUNT(flags.konstValuesEnabled() ? konstCount[0] : 0)> konstColors;
|
||||
|
||||
Value<atUint16> _blendDstFac;
|
||||
using BlendFactor = DNAMP1::MaterialSet::Material::BlendFactor;
|
||||
|
@ -56,10 +59,22 @@ struct MaterialSet : BigDNA
|
|||
};
|
||||
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,
|
||||
const MaterialSet::Material& material,
|
||||
unsigned groupIdx, unsigned matIdx,
|
||||
unsigned& uvCountOut);
|
||||
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_1_2(os, *this, pakRouter, entry, attributesOut, setIdx);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -4,4 +4,5 @@ make_dnalist(liblist
|
|||
add_library(DNAMP2
|
||||
DNAMP2.hpp DNAMP2.cpp
|
||||
${liblist}
|
||||
CMDL.hpp
|
||||
STRG.hpp STRG.cpp)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "DNAMP2.hpp"
|
||||
#include "STRG.hpp"
|
||||
#include "MLVL.hpp"
|
||||
#include "CMDL.hpp"
|
||||
#include "../DNACommon/TXTR.hpp"
|
||||
|
||||
namespace Retro
|
||||
|
@ -186,6 +187,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& ent
|
|||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, nullptr, ".png"};
|
||||
case SBIG('CMDL'):
|
||||
return {nullptr, CMDL::Extract, ".blend", 1};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -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_
|
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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*)§ion->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_
|
|
@ -1,8 +1,11 @@
|
|||
make_dnalist(liblist
|
||||
PAK
|
||||
MLVL)
|
||||
MLVL
|
||||
CMDLMaterials)
|
||||
add_library(DNAMP3
|
||||
DNAMP3.hpp DNAMP3.cpp
|
||||
${liblist}
|
||||
PAK.cpp
|
||||
CMDL.hpp
|
||||
CMDLMaterials.cpp
|
||||
STRG.hpp STRG.cpp)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "DNAMP3.hpp"
|
||||
#include "STRG.hpp"
|
||||
#include "MLVL.hpp"
|
||||
#include "CMDL.hpp"
|
||||
#include "../DNACommon/TXTR.hpp"
|
||||
|
||||
namespace Retro
|
||||
|
@ -60,6 +61,8 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const PAK::Entry& entry)
|
|||
return {STRG::Extract, nullptr, ".yaml"};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, nullptr, ".png"};
|
||||
case SBIG('CMDL'):
|
||||
return {nullptr, CMDL::Extract, ".blend", 1};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ struct SpecMP1 : SpecBase
|
|||
return false;
|
||||
}
|
||||
|
||||
bool doMP1 = false;
|
||||
std::vector<const NOD::DiscBase::IPartition::Node*> m_nonPaks;
|
||||
std::vector<DNAMP1::PAKBridge> m_paks;
|
||||
std::map<std::string, DNAMP1::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
|
@ -122,7 +121,6 @@ struct SpecMP1 : SpecBase
|
|||
const std::vector<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& reps)
|
||||
{
|
||||
doMP1 = true;
|
||||
NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
|
||||
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
|
||||
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<HECL::SystemString> mp1args;
|
||||
bool doExtract = false;
|
||||
if (args.size())
|
||||
{
|
||||
/* Needs filter */
|
||||
|
@ -161,7 +160,7 @@ struct SpecMP1 : SpecBase
|
|||
HECL::ToLower(lowerArg);
|
||||
if (!lowerArg.compare(0, 3, _S("mp1")))
|
||||
{
|
||||
doMP1 = true;
|
||||
doExtract = true;
|
||||
size_t slashPos = arg.find(_S('/'));
|
||||
if (slashPos == HECL::SystemString::npos)
|
||||
slashPos = arg.find(_S('\\'));
|
||||
|
@ -171,10 +170,10 @@ struct SpecMP1 : SpecBase
|
|||
}
|
||||
}
|
||||
else
|
||||
doMP1 = true;
|
||||
doExtract = true;
|
||||
|
||||
if (!doMP1)
|
||||
return true;
|
||||
if (!doExtract)
|
||||
return false;
|
||||
|
||||
NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
|
||||
NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot();
|
||||
|
@ -208,9 +207,6 @@ struct SpecMP1 : SpecBase
|
|||
|
||||
bool extractFromDisc(NOD::DiscBase&, bool force, FExtractProgress progress)
|
||||
{
|
||||
if (!doMP1)
|
||||
return true;
|
||||
|
||||
progress(_S("Indexing PAKs"), 2, 0.0);
|
||||
m_pakRouter.build(m_paks, [&progress](float factor)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,6 @@ struct SpecMP2 : SpecBase
|
|||
return false;
|
||||
}
|
||||
|
||||
bool doMP2 = false;
|
||||
std::vector<const NOD::DiscBase::IPartition::Node*> m_nonPaks;
|
||||
std::vector<DNAMP2::PAKBridge> m_paks;
|
||||
std::map<std::string, DNAMP2::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
|
@ -118,7 +117,6 @@ struct SpecMP2 : SpecBase
|
|||
const std::vector<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& reps)
|
||||
{
|
||||
doMP2 = true;
|
||||
NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
|
||||
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
|
||||
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<HECL::SystemString> mp2args;
|
||||
bool doExtract = false;
|
||||
if (args.size())
|
||||
{
|
||||
/* Needs filter */
|
||||
|
@ -157,7 +156,7 @@ struct SpecMP2 : SpecBase
|
|||
HECL::ToLower(lowerArg);
|
||||
if (!lowerArg.compare(0, 3, _S("mp2")))
|
||||
{
|
||||
doMP2 = true;
|
||||
doExtract = true;
|
||||
size_t slashPos = arg.find(_S('/'));
|
||||
if (slashPos == HECL::SystemString::npos)
|
||||
slashPos = arg.find(_S('\\'));
|
||||
|
@ -167,10 +166,10 @@ struct SpecMP2 : SpecBase
|
|||
}
|
||||
}
|
||||
else
|
||||
doMP2 = true;
|
||||
doExtract = true;
|
||||
|
||||
if (!doMP2)
|
||||
return true;
|
||||
if (!doExtract)
|
||||
return false;
|
||||
|
||||
NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
|
||||
NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot();
|
||||
|
@ -204,9 +203,6 @@ struct SpecMP2 : SpecBase
|
|||
|
||||
bool extractFromDisc(NOD::DiscBase&, bool force, FExtractProgress progress)
|
||||
{
|
||||
if (!doMP2)
|
||||
return true;
|
||||
|
||||
progress(_S("Indexing PAKs"), 2, 0.0);
|
||||
m_pakRouter.build(m_paks, [&progress](float factor)
|
||||
{
|
||||
|
|
|
@ -238,6 +238,9 @@ struct SpecMP3 : SpecBase
|
|||
doMPTFE = true;
|
||||
}
|
||||
|
||||
if (!doMP3 && !doMPTFE)
|
||||
return false;
|
||||
|
||||
NOD::DiscGCN::IPartition* partition = disc.getDataPartition();
|
||||
NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot();
|
||||
|
||||
|
|
Loading…
Reference in New Issue