mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-06-07 17:13:29 +00:00
Added HMDL outputting from blender intermediate
This commit is contained in:
parent
7c0206bd39
commit
db335e5d98
@ -503,8 +503,8 @@ void BlenderConnection::PyOutStream::linkBackground(const char* target,
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlenderConnection::DataStream::Mesh::Mesh
|
BlenderConnection::DataStream::Mesh::Mesh
|
||||||
(BlenderConnection& conn, OutputMode outMode, int skinSlotCount, SurfProgFunc& surfProg)
|
(BlenderConnection& conn, HMDLTopology topologyIn, int skinSlotCount, SurfProgFunc& surfProg)
|
||||||
: outputMode(outMode), aabbMin(conn), aabbMax(conn)
|
: topology(topologyIn), aabbMin(conn), aabbMax(conn)
|
||||||
{
|
{
|
||||||
uint32_t matSetCount;
|
uint32_t matSetCount;
|
||||||
conn._readBuf(&matSetCount, 4);
|
conn._readBuf(&matSetCount, 4);
|
||||||
@ -587,12 +587,12 @@ BlenderConnection::DataStream::Mesh::Mesh
|
|||||||
{
|
{
|
||||||
for (Surface& surf : surfaces)
|
for (Surface& surf : surfaces)
|
||||||
{
|
{
|
||||||
std::vector<uint32_t>& bank = skinBanks.banks[surf.skinBankIdx];
|
SkinBanks::Bank& bank = skinBanks.banks[surf.skinBankIdx];
|
||||||
for (Surface::Vert& vert : surf.verts)
|
for (Surface::Vert& vert : surf.verts)
|
||||||
{
|
{
|
||||||
for (uint32_t i=0 ; i<bank.size() ; ++i)
|
for (uint32_t i=0 ; i<bank.m_skinIdxs.size() ; ++i)
|
||||||
{
|
{
|
||||||
if (bank[i] == vert.iSkin)
|
if (bank.m_skinIdxs[i] == vert.iSkin)
|
||||||
{
|
{
|
||||||
vert.iBankSkin = i;
|
vert.iBankSkin = i;
|
||||||
break;
|
break;
|
||||||
@ -706,7 +706,7 @@ BlenderConnection::DataStream::Mesh::Surface::Surface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parent.boneNames.size())
|
if (parent.boneNames.size())
|
||||||
skinBankIdx = parent.skinBanks.addSurface(*this, skinSlotCount);
|
skinBankIdx = parent.skinBanks.addSurface(parent, *this, skinSlotCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlenderConnection::DataStream::Mesh::Surface::Vert::Vert
|
BlenderConnection::DataStream::Mesh::Surface::Vert::Vert
|
||||||
@ -730,27 +730,27 @@ static bool VertInBank(const std::vector<uint32_t>& bank, uint32_t sIdx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BlenderConnection::DataStream::Mesh::SkinBanks::addSurface
|
uint32_t BlenderConnection::DataStream::Mesh::SkinBanks::addSurface
|
||||||
(const Surface& surf, int skinSlotCount)
|
(const Mesh& mesh, const Surface& surf, int skinSlotCount)
|
||||||
{
|
{
|
||||||
if (banks.empty())
|
if (banks.empty())
|
||||||
addSkinBank(skinSlotCount);
|
addSkinBank(skinSlotCount);
|
||||||
std::vector<uint32_t> toAdd;
|
std::vector<uint32_t> toAdd;
|
||||||
if (skinSlotCount > 0)
|
if (skinSlotCount > 0)
|
||||||
toAdd.reserve(skinSlotCount);
|
toAdd.reserve(skinSlotCount);
|
||||||
std::vector<std::vector<uint32_t>>::iterator bankIt = banks.begin();
|
std::vector<Bank>::iterator bankIt = banks.begin();
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
bool done = true;
|
bool done = true;
|
||||||
for (; bankIt != banks.end() ; ++bankIt)
|
for (; bankIt != banks.end() ; ++bankIt)
|
||||||
{
|
{
|
||||||
std::vector<uint32_t>& bank = *bankIt;
|
Bank& bank = *bankIt;
|
||||||
done = true;
|
done = true;
|
||||||
for (const Surface::Vert& v : surf.verts)
|
for (const Surface::Vert& v : surf.verts)
|
||||||
{
|
{
|
||||||
if (!VertInBank(bank, v.iSkin) && !VertInBank(toAdd, v.iSkin))
|
if (!VertInBank(bank.m_skinIdxs, v.iSkin) && !VertInBank(toAdd, v.iSkin))
|
||||||
{
|
{
|
||||||
toAdd.push_back(v.iSkin);
|
toAdd.push_back(v.iSkin);
|
||||||
if (skinSlotCount > 0 && bank.size() + toAdd.size() > skinSlotCount)
|
if (skinSlotCount > 0 && bank.m_skinIdxs.size() + toAdd.size() > skinSlotCount)
|
||||||
{
|
{
|
||||||
toAdd.clear();
|
toAdd.clear();
|
||||||
done = false;
|
done = false;
|
||||||
@ -760,8 +760,7 @@ uint32_t BlenderConnection::DataStream::Mesh::SkinBanks::addSurface
|
|||||||
}
|
}
|
||||||
if (toAdd.size())
|
if (toAdd.size())
|
||||||
{
|
{
|
||||||
for (uint32_t a : toAdd)
|
bank.addSkins(mesh, toAdd);
|
||||||
bank.push_back(a);
|
|
||||||
toAdd.clear();
|
toAdd.clear();
|
||||||
}
|
}
|
||||||
if (done)
|
if (done)
|
||||||
|
@ -21,13 +21,16 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "HECL/HECL.hpp"
|
#include "HECL/HECL.hpp"
|
||||||
|
#include "HECL/HMDLMeta.hpp"
|
||||||
#include <Athena/Types.hpp>
|
#include <Athena/Types.hpp>
|
||||||
|
#include <Athena/MemoryWriter.hpp>
|
||||||
|
|
||||||
namespace HECL
|
namespace HECL
|
||||||
{
|
{
|
||||||
|
|
||||||
extern LogVisor::LogModule BlenderLog;
|
extern LogVisor::LogModule BlenderLog;
|
||||||
extern class BlenderConnection* SharedBlenderConnection;
|
extern class BlenderConnection* SharedBlenderConnection;
|
||||||
|
class HMDLBuffers;
|
||||||
|
|
||||||
class BlenderConnection
|
class BlenderConnection
|
||||||
{
|
{
|
||||||
@ -374,11 +377,7 @@ public:
|
|||||||
/** Intermediate mesh representation prepared by blender from a single mesh object */
|
/** Intermediate mesh representation prepared by blender from a single mesh object */
|
||||||
struct Mesh
|
struct Mesh
|
||||||
{
|
{
|
||||||
enum OutputMode
|
enum HMDLTopology topology;
|
||||||
{
|
|
||||||
OutputTriangles,
|
|
||||||
OutputTriStrips,
|
|
||||||
} outputMode;
|
|
||||||
|
|
||||||
/* Cumulative AABB */
|
/* Cumulative AABB */
|
||||||
Vector3f aabbMin;
|
Vector3f aabbMin;
|
||||||
@ -436,6 +435,23 @@ public:
|
|||||||
uint32_t iBankSkin = -1;
|
uint32_t iBankSkin = -1;
|
||||||
|
|
||||||
Vert(BlenderConnection& conn, const Mesh& parent);
|
Vert(BlenderConnection& conn, const Mesh& parent);
|
||||||
|
|
||||||
|
bool operator==(const Vert& other) const
|
||||||
|
{
|
||||||
|
if (iPos != other.iPos)
|
||||||
|
return false;
|
||||||
|
if (iNorm != other.iNorm)
|
||||||
|
return false;
|
||||||
|
for (int i=0 ; i<4 ; ++i)
|
||||||
|
if (iColor[i] != other.iColor[i])
|
||||||
|
return false;
|
||||||
|
for (int i=0 ; i<8 ; ++i)
|
||||||
|
if (iUv[i] != other.iUv[i])
|
||||||
|
return false;
|
||||||
|
if (iSkin != other.iSkin)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
std::vector<Vert> verts;
|
std::vector<Vert> verts;
|
||||||
|
|
||||||
@ -445,33 +461,73 @@ public:
|
|||||||
|
|
||||||
struct SkinBanks
|
struct SkinBanks
|
||||||
{
|
{
|
||||||
std::vector<std::vector<uint32_t>> banks;
|
struct Bank
|
||||||
std::vector<std::vector<uint32_t>>::iterator addSkinBank(int skinSlotCount)
|
{
|
||||||
|
std::vector<uint32_t> m_skinIdxs;
|
||||||
|
std::vector<uint32_t> m_boneIdxs;
|
||||||
|
|
||||||
|
void addSkins(const Mesh& parent, const std::vector<uint32_t>& skinIdxs)
|
||||||
|
{
|
||||||
|
for (uint32_t sidx : skinIdxs)
|
||||||
|
{
|
||||||
|
m_skinIdxs.push_back(sidx);
|
||||||
|
for (const SkinBind& bind : parent.skins[sidx])
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (uint32_t bidx : m_boneIdxs)
|
||||||
|
{
|
||||||
|
if (bidx == bind.boneIdx)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
m_boneIdxs.push_back(bind.boneIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t lookupLocalBoneIdx(uint32_t boneIdx) const
|
||||||
|
{
|
||||||
|
for (size_t i=0 ; i<m_boneIdxs.size() ; ++i)
|
||||||
|
if (m_boneIdxs[i] == boneIdx)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::vector<Bank> banks;
|
||||||
|
std::vector<Bank>::iterator addSkinBank(int skinSlotCount)
|
||||||
{
|
{
|
||||||
banks.emplace_back();
|
banks.emplace_back();
|
||||||
if (skinSlotCount > 0)
|
if (skinSlotCount > 0)
|
||||||
banks.back().reserve(skinSlotCount);
|
banks.back().m_skinIdxs.reserve(skinSlotCount);
|
||||||
return banks.end() - 1;
|
return banks.end() - 1;
|
||||||
}
|
}
|
||||||
uint32_t addSurface(const Surface& surf, int skinSlotCount);
|
uint32_t addSurface(const Mesh& mesh, const Surface& surf, int skinSlotCount);
|
||||||
} skinBanks;
|
} skinBanks;
|
||||||
|
|
||||||
using SurfProgFunc = std::function<void(int)>;
|
using SurfProgFunc = std::function<void(int)>;
|
||||||
Mesh(BlenderConnection& conn, OutputMode outMode, int skinSlotCount, SurfProgFunc& surfProg);
|
Mesh(BlenderConnection& conn, HMDLTopology topology, int skinSlotCount, SurfProgFunc& surfProg);
|
||||||
|
|
||||||
Mesh getContiguousSkinningVersion() const;
|
Mesh getContiguousSkinningVersion() const;
|
||||||
|
|
||||||
|
/** Prepares mesh representation for indexed access on modern APIs.
|
||||||
|
* Mesh must remain resident for accessing reference members
|
||||||
|
*/
|
||||||
|
HMDLBuffers getHMDLBuffers() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const char* MeshOutputModeString(Mesh::OutputMode mode)
|
static const char* MeshOutputModeString(HMDLTopology topology)
|
||||||
{
|
{
|
||||||
static const char* STRS[] = {"TRIANGLES", "TRISTRIPS"};
|
static const char* STRS[] = {"TRIANGLES", "TRISTRIPS"};
|
||||||
return STRS[mode];
|
return STRS[topology];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Compile mesh by context (MESH blends only) */
|
/** Compile mesh by context (MESH blends only) */
|
||||||
Mesh compileMesh(Mesh::OutputMode outMode, int skinSlotCount=10,
|
Mesh compileMesh(HMDLTopology topology, int skinSlotCount=10,
|
||||||
Mesh::SurfProgFunc surfProg=[](int){})
|
Mesh::SurfProgFunc surfProg=[](int){})
|
||||||
{
|
{
|
||||||
if (m_parent->m_loadedType != TypeMesh)
|
if (m_parent->m_loadedType != TypeMesh)
|
||||||
@ -480,7 +536,7 @@ public:
|
|||||||
|
|
||||||
char req[128];
|
char req[128];
|
||||||
snprintf(req, 128, "MESHCOMPILE %s %d",
|
snprintf(req, 128, "MESHCOMPILE %s %d",
|
||||||
MeshOutputModeString(outMode), skinSlotCount);
|
MeshOutputModeString(topology), skinSlotCount);
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeLine(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
@ -488,11 +544,11 @@ public:
|
|||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(LogVisor::FatalError, "unable to cook mesh: %s", readBuf);
|
BlenderLog.report(LogVisor::FatalError, "unable to cook mesh: %s", readBuf);
|
||||||
|
|
||||||
return Mesh(*m_parent, outMode, skinSlotCount, surfProg);
|
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compile mesh by name (AREA blends only) */
|
/** Compile mesh by name (AREA blends only) */
|
||||||
Mesh compileMesh(const std::string& name, Mesh::OutputMode outMode, int skinSlotCount=10,
|
Mesh compileMesh(const std::string& name, HMDLTopology topology, int skinSlotCount=10,
|
||||||
Mesh::SurfProgFunc surfProg=[](int){})
|
Mesh::SurfProgFunc surfProg=[](int){})
|
||||||
{
|
{
|
||||||
if (m_parent->m_loadedType != TypeArea)
|
if (m_parent->m_loadedType != TypeArea)
|
||||||
@ -501,7 +557,7 @@ public:
|
|||||||
|
|
||||||
char req[128];
|
char req[128];
|
||||||
snprintf(req, 128, "MESHCOMPILENAME %s %s %d", name.c_str(),
|
snprintf(req, 128, "MESHCOMPILENAME %s %s %d", name.c_str(),
|
||||||
MeshOutputModeString(outMode), skinSlotCount);
|
MeshOutputModeString(topology), skinSlotCount);
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeLine(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
@ -509,11 +565,11 @@ public:
|
|||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(LogVisor::FatalError, "unable to cook mesh '%s': %s", name.c_str(), readBuf);
|
BlenderLog.report(LogVisor::FatalError, "unable to cook mesh '%s': %s", name.c_str(), readBuf);
|
||||||
|
|
||||||
return Mesh(*m_parent, outMode, skinSlotCount, surfProg);
|
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compile all meshes into one (AREA blends only) */
|
/** Compile all meshes into one (AREA blends only) */
|
||||||
Mesh compileAllMeshes(Mesh::OutputMode outMode, int skinSlotCount=10, float maxOctantLength=5.0,
|
Mesh compileAllMeshes(HMDLTopology topology, int skinSlotCount=10, float maxOctantLength=5.0,
|
||||||
Mesh::SurfProgFunc surfProg=[](int){})
|
Mesh::SurfProgFunc surfProg=[](int){})
|
||||||
{
|
{
|
||||||
if (m_parent->m_loadedType != TypeArea)
|
if (m_parent->m_loadedType != TypeArea)
|
||||||
@ -522,7 +578,7 @@ public:
|
|||||||
|
|
||||||
char req[128];
|
char req[128];
|
||||||
snprintf(req, 128, "MESHCOMPILEALL %s %d %f",
|
snprintf(req, 128, "MESHCOMPILEALL %s %d %f",
|
||||||
MeshOutputModeString(outMode),
|
MeshOutputModeString(topology),
|
||||||
skinSlotCount, maxOctantLength);
|
skinSlotCount, maxOctantLength);
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeLine(req);
|
||||||
|
|
||||||
@ -531,7 +587,7 @@ public:
|
|||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(LogVisor::FatalError, "unable to cook all meshes: %s", readBuf);
|
BlenderLog.report(LogVisor::FatalError, "unable to cook all meshes: %s", readBuf);
|
||||||
|
|
||||||
return Mesh(*m_parent, outMode, skinSlotCount, surfProg);
|
return Mesh(*m_parent, topology, skinSlotCount, surfProg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Intermediate actor representation prepared by blender from a single HECL actor blend */
|
/** Intermediate actor representation prepared by blender from a single HECL actor blend */
|
||||||
@ -651,6 +707,52 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HMDLBuffers
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Surface;
|
||||||
|
private:
|
||||||
|
friend struct BlenderConnection::DataStream::Mesh;
|
||||||
|
HMDLBuffers(const HMDLMeta& meta,
|
||||||
|
size_t vboSz, const std::vector<atUint32>& iboData,
|
||||||
|
std::vector<Surface>&& surfaces,
|
||||||
|
const BlenderConnection::DataStream::Mesh::SkinBanks& skinBanks)
|
||||||
|
: m_metaSz(HECL_HMDL_META_SZ), m_metaData(new uint8_t[HECL_HMDL_META_SZ]),
|
||||||
|
m_vboSz(vboSz), m_vboData(new uint8_t[vboSz]),
|
||||||
|
m_iboSz(iboData.size()*4), m_iboData(new uint8_t[iboData.size()*4]),
|
||||||
|
m_surfaces(std::move(surfaces)), m_skinBanks(skinBanks)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Athena::io::MemoryWriter w(m_metaData.get(), HECL_HMDL_META_SZ);
|
||||||
|
meta.write(w);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Athena::io::MemoryWriter w(m_iboData.get(), m_iboSz);
|
||||||
|
w.enumerateLittle(iboData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
size_t m_metaSz;
|
||||||
|
std::unique_ptr<uint8_t[]> m_metaData;
|
||||||
|
size_t m_vboSz;
|
||||||
|
std::unique_ptr<uint8_t[]> m_vboData;
|
||||||
|
size_t m_iboSz;
|
||||||
|
std::unique_ptr<uint8_t[]> m_iboData;
|
||||||
|
|
||||||
|
struct Surface
|
||||||
|
{
|
||||||
|
Surface(const BlenderConnection::DataStream::Mesh::Surface& origSurf,
|
||||||
|
atUint32 start, atUint32 count)
|
||||||
|
: m_origSurf(origSurf), m_start(start), m_count(count) {}
|
||||||
|
const BlenderConnection::DataStream::Mesh::Surface& m_origSurf;
|
||||||
|
atUint32 m_start;
|
||||||
|
atUint32 m_count;
|
||||||
|
};
|
||||||
|
std::vector<Surface> m_surfaces;
|
||||||
|
|
||||||
|
const BlenderConnection::DataStream::Mesh::SkinBanks& m_skinBanks;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // BLENDERCONNECTION_HPP
|
#endif // BLENDERCONNECTION_HPP
|
||||||
|
@ -25,6 +25,7 @@ bintoc(hecl_startup.c hecl_startup.blend HECL_STARTUP)
|
|||||||
add_library(HECLBlender
|
add_library(HECLBlender
|
||||||
BlenderConnection.cpp
|
BlenderConnection.cpp
|
||||||
BlenderConnection.hpp
|
BlenderConnection.hpp
|
||||||
|
HMDL.cpp
|
||||||
hecl_blendershell.py
|
hecl_blendershell.py
|
||||||
hecl_blendershell.c
|
hecl_blendershell.c
|
||||||
zip_package.py
|
zip_package.py
|
||||||
|
121
hecl/blender/HMDL.cpp
Normal file
121
hecl/blender/HMDL.cpp
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include "BlenderConnection.hpp"
|
||||||
|
|
||||||
|
namespace HECL
|
||||||
|
{
|
||||||
|
|
||||||
|
HMDLBuffers BlenderConnection::DataStream::Mesh::getHMDLBuffers() const
|
||||||
|
{
|
||||||
|
/* If skinned, compute max weight vec count */
|
||||||
|
size_t weightCount = 0;
|
||||||
|
for (const SkinBanks::Bank& bank : skinBanks.banks)
|
||||||
|
weightCount = std::max(weightCount, bank.m_boneIdxs.size());
|
||||||
|
size_t weightVecCount = weightCount / 4;
|
||||||
|
if (weightCount % 4)
|
||||||
|
++weightVecCount;
|
||||||
|
|
||||||
|
/* Prepare HMDL meta */
|
||||||
|
HMDLMeta metaOut;
|
||||||
|
metaOut.topology = topology;
|
||||||
|
metaOut.vertStride = (3 + 3 + colorLayerCount + uvLayerCount * 2 + weightVecCount * 4) * 4;
|
||||||
|
metaOut.colorCount = colorLayerCount;
|
||||||
|
metaOut.uvCount = uvLayerCount;
|
||||||
|
metaOut.weightCount = weightVecCount;
|
||||||
|
|
||||||
|
/* Total all verts from all surfaces (for ibo length) */
|
||||||
|
size_t boundVerts = 0;
|
||||||
|
for (const Surface& surf : surfaces)
|
||||||
|
boundVerts += surf.verts.size();
|
||||||
|
|
||||||
|
/* Maintain unique vert pool for VBO */
|
||||||
|
std::vector<std::pair<const Surface*, const Surface::Vert*>> vertPool;
|
||||||
|
vertPool.reserve(boundVerts);
|
||||||
|
|
||||||
|
/* Target surfaces representation */
|
||||||
|
std::vector<HMDLBuffers::Surface> outSurfaces;
|
||||||
|
outSurfaces.reserve(surfaces.size());
|
||||||
|
|
||||||
|
/* Index buffer */
|
||||||
|
std::vector<atUint32> iboData;
|
||||||
|
iboData.reserve(boundVerts);
|
||||||
|
|
||||||
|
for (const Surface& surf : surfaces)
|
||||||
|
{
|
||||||
|
size_t iboStart = iboData.size();
|
||||||
|
for (const Surface::Vert& v : surf.verts)
|
||||||
|
{
|
||||||
|
size_t ti = 0;
|
||||||
|
bool found = false;
|
||||||
|
for (const std::pair<const Surface*, const Surface::Vert*>& tv : vertPool)
|
||||||
|
{
|
||||||
|
if (v == *tv.second)
|
||||||
|
{
|
||||||
|
iboData.push_back(ti);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++ti;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
iboData.push_back(vertPool.size());
|
||||||
|
vertPool.emplace_back(&surf, &v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outSurfaces.emplace_back(surf, iboStart, iboData.size() - iboStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
metaOut.vertCount = vertPool.size();
|
||||||
|
metaOut.indexCount = iboData.size();
|
||||||
|
|
||||||
|
size_t vboSz = metaOut.vertCount * metaOut.vertStride;
|
||||||
|
HMDLBuffers ret(metaOut, vboSz, iboData, std::move(outSurfaces), skinBanks);
|
||||||
|
Athena::io::MemoryWriter vboW(ret.m_vboData.get(), vboSz);
|
||||||
|
for (const std::pair<const Surface*, const Surface::Vert*>& sv : vertPool)
|
||||||
|
{
|
||||||
|
const Surface& s = *sv.first;
|
||||||
|
const Surface::Vert& v = *sv.second;
|
||||||
|
|
||||||
|
vboW.writeVec3fLittle(pos[v.iPos]);
|
||||||
|
vboW.writeVec3fLittle(norm[v.iNorm]);
|
||||||
|
|
||||||
|
for (int i=0 ; i<colorLayerCount ; ++i)
|
||||||
|
{
|
||||||
|
const Vector3f& c = color[v.iColor[i]];
|
||||||
|
vboW.writeUByte(std::max(0, std::min(255, int(c.val.vec[0] * 255))));
|
||||||
|
vboW.writeUByte(std::max(0, std::min(255, int(c.val.vec[1] * 255))));
|
||||||
|
vboW.writeUByte(std::max(0, std::min(255, int(c.val.vec[2] * 255))));
|
||||||
|
vboW.writeUByte(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0 ; i<uvLayerCount ; ++i)
|
||||||
|
vboW.writeVec2fLittle(uv[v.iUv[i]]);
|
||||||
|
|
||||||
|
if (weightVecCount)
|
||||||
|
{
|
||||||
|
const SkinBanks::Bank& bank = skinBanks.banks[s.skinBankIdx];
|
||||||
|
const std::vector<SkinBind>& binds = skins[v.iSkin];
|
||||||
|
auto it = bank.m_boneIdxs.cbegin();
|
||||||
|
for (int i=0 ; i<weightVecCount ; ++i)
|
||||||
|
{
|
||||||
|
atVec4f vec = {};
|
||||||
|
for (int j=0 ; j<4 ; ++j)
|
||||||
|
{
|
||||||
|
if (it == bank.m_boneIdxs.cend())
|
||||||
|
break;
|
||||||
|
for (const SkinBind& bind : binds)
|
||||||
|
if (bind.boneIdx == *it)
|
||||||
|
{
|
||||||
|
vec.vec[j] = bind.weight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
vboW.writeVec4fLittle(vec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
hecl/include/HECL/HMDLMeta.hpp
Normal file
33
hecl/include/HECL/HMDLMeta.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef HMDLMETA_HPP
|
||||||
|
#define HMDLMETA_HPP
|
||||||
|
|
||||||
|
#include <HECL/HECL.hpp>
|
||||||
|
#include <Athena/DNA.hpp>
|
||||||
|
|
||||||
|
namespace HECL
|
||||||
|
{
|
||||||
|
|
||||||
|
enum HMDLTopology : atUint32
|
||||||
|
{
|
||||||
|
TopologyTriangles,
|
||||||
|
TopologyTriStrips,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HECL_HMDL_META_SZ 32
|
||||||
|
|
||||||
|
struct HMDLMeta : Athena::io::DNA<Athena::BigEndian>
|
||||||
|
{
|
||||||
|
DECL_DNA
|
||||||
|
Value<atUint32> magic = SBIG('TACO');
|
||||||
|
Value<HMDLTopology> topology;
|
||||||
|
Value<atUint32> vertStride;
|
||||||
|
Value<atUint32> vertCount;
|
||||||
|
Value<atUint32> indexCount;
|
||||||
|
Value<atUint32> colorCount;
|
||||||
|
Value<atUint32> uvCount;
|
||||||
|
Value<atUint32> weightCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HMDLMETA_HPP
|
@ -115,10 +115,14 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Integrated reader/constructor/container for HMDL data
|
* @brief Integrated reader/constructor/container for HMDL data
|
||||||
*/
|
*/
|
||||||
class HMDLData
|
struct HMDLData
|
||||||
{
|
{
|
||||||
public:
|
boo::IGraphicsBufferS* m_vbo;
|
||||||
HMDLData(boo::IGraphicsDataFactory* factory, const void* data);
|
boo::IGraphicsBufferS* m_ibo;
|
||||||
|
boo::IVertexFormat* m_vtxFmt;
|
||||||
|
|
||||||
|
HMDLData(boo::IGraphicsDataFactory* factory,
|
||||||
|
const void* metaData, const void* vbo, const void* ibo);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ if(WIN32)
|
|||||||
list(APPEND PLAT_SRCS winsupport.cpp ../include/HECL/winsupport.hpp)
|
list(APPEND PLAT_SRCS winsupport.cpp ../include/HECL/winsupport.hpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
atdna(atdna_HMDLMeta.cpp ../include/HECL/HMDLMeta.hpp)
|
||||||
atdna(atdna_Frontend.cpp ../include/HECL/Frontend.hpp)
|
atdna(atdna_Frontend.cpp ../include/HECL/Frontend.hpp)
|
||||||
atdna(atdna_Runtime.cpp ../include/HECL/Runtime.hpp)
|
atdna(atdna_Runtime.cpp ../include/HECL/Runtime.hpp)
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ add_library(HECLCommon
|
|||||||
ProjectPath.cpp
|
ProjectPath.cpp
|
||||||
WideStringConvert.cpp
|
WideStringConvert.cpp
|
||||||
../include/HECL/HECL.hpp
|
../include/HECL/HECL.hpp
|
||||||
|
../include/HECL/HMDLMeta.hpp
|
||||||
../include/HECL/Backend/Backend.hpp
|
../include/HECL/Backend/Backend.hpp
|
||||||
../include/HECL/Backend/GX.hpp
|
../include/HECL/Backend/GX.hpp
|
||||||
../include/HECL/Backend/ProgrammableCommon.hpp
|
../include/HECL/Backend/ProgrammableCommon.hpp
|
||||||
@ -22,6 +24,7 @@ add_library(HECLCommon
|
|||||||
../include/HECL/Frontend.hpp
|
../include/HECL/Frontend.hpp
|
||||||
../include/HECL/Database.hpp
|
../include/HECL/Database.hpp
|
||||||
../include/HECL/Runtime.hpp
|
../include/HECL/Runtime.hpp
|
||||||
|
atdna_HMDLMeta.cpp
|
||||||
atdna_Frontend.cpp
|
atdna_Frontend.cpp
|
||||||
atdna_Runtime.cpp
|
atdna_Runtime.cpp
|
||||||
${PLAT_SRCS})
|
${PLAT_SRCS})
|
||||||
|
@ -1,12 +1,58 @@
|
|||||||
|
#include "HECL/HMDLMeta.hpp"
|
||||||
#include "HECL/Runtime.hpp"
|
#include "HECL/Runtime.hpp"
|
||||||
|
#include <Athena/MemoryReader.hpp>
|
||||||
|
|
||||||
namespace HECL
|
namespace HECL
|
||||||
{
|
{
|
||||||
namespace Runtime
|
namespace Runtime
|
||||||
{
|
{
|
||||||
|
static LogVisor::LogModule Log("HMDL");
|
||||||
|
|
||||||
HMDLData::HMDLData(boo::IGraphicsDataFactory* factory, const void *data)
|
HMDLData::HMDLData(boo::IGraphicsDataFactory* factory,
|
||||||
|
const void* metaData, const void* vbo, const void* ibo)
|
||||||
{
|
{
|
||||||
|
HMDLMeta meta;
|
||||||
|
{
|
||||||
|
Athena::io::MemoryReader r((atUint8*)metaData, HECL_HMDL_META_SZ);
|
||||||
|
meta.read(r);
|
||||||
|
}
|
||||||
|
if (meta.magic != FOURCC('TACO'))
|
||||||
|
Log.report(LogVisor::FatalError, "invalid HMDL magic");
|
||||||
|
|
||||||
|
m_vbo = factory->newStaticBuffer(boo::BufferUseVertex, vbo, meta.vertStride, meta.vertCount);
|
||||||
|
m_ibo = factory->newStaticBuffer(boo::BufferUseIndex, ibo, 4, meta.indexCount);
|
||||||
|
|
||||||
|
size_t elemCount = 2 + meta.colorCount + meta.uvCount + meta.weightCount;
|
||||||
|
std::unique_ptr<boo::VertexElementDescriptor[]> vdescs(new boo::VertexElementDescriptor[elemCount]);
|
||||||
|
for (size_t i=0 ; i<elemCount ; ++i)
|
||||||
|
{
|
||||||
|
vdescs[i].vertBuffer = m_vbo;
|
||||||
|
vdescs[i].indexBuffer = m_ibo;
|
||||||
|
}
|
||||||
|
|
||||||
|
vdescs[0].semantic = boo::VertexSemanticPosition;
|
||||||
|
vdescs[1].semantic = boo::VertexSemanticNormal;
|
||||||
|
size_t e = 2;
|
||||||
|
|
||||||
|
for (size_t i=0 ; i<meta.colorCount ; ++i, ++e)
|
||||||
|
{
|
||||||
|
vdescs[e].semantic = boo::VertexSemanticColor;
|
||||||
|
vdescs[e].semanticIdx = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0 ; i<meta.uvCount ; ++i, ++e)
|
||||||
|
{
|
||||||
|
vdescs[e].semantic = boo::VertexSemanticUV;
|
||||||
|
vdescs[e].semanticIdx = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0 ; i<meta.weightCount ; ++i, ++e)
|
||||||
|
{
|
||||||
|
vdescs[e].semantic = boo::VertexSemanticWeight;
|
||||||
|
vdescs[e].semanticIdx = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vtxFmt = factory->newVertexFormat(elemCount, vdescs.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user