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>
|
#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
|
||||||
|
{
|
||||||
|
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,
|
Athena::io::IStreamReader& reader,
|
||||||
PAKRouter<PAKBridge>& pakRouter,
|
PAKRouter& pakRouter,
|
||||||
const PAK::Entry& entry,
|
const typename PAKRouter::EntryType& entry,
|
||||||
const HECL::ProjectPath& masterShader)
|
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_
|
|
@ -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)
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 */
|
||||||
|
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]);
|
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);}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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/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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
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)
|
||||||
|
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue